Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Train information for departures and delays, provided by Trafikverket."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable, Mapping
6 from dataclasses import dataclass
7 from datetime import datetime
8 from typing import Any
9 
11  SensorDeviceClass,
12  SensorEntity,
13  SensorEntityDescription,
14 )
15 from homeassistant.const import CONF_NAME, UnitOfTime
16 from homeassistant.core import HomeAssistant, callback
17 from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
18 from homeassistant.helpers.entity_platform import AddEntitiesCallback
19 from homeassistant.helpers.typing import StateType
20 from homeassistant.helpers.update_coordinator import CoordinatorEntity
21 
22 from . import TVTrainConfigEntry
23 from .const import ATTRIBUTION, DOMAIN
24 from .coordinator import TrainData, TVDataUpdateCoordinator
25 
26 ATTR_PRODUCT_FILTER = "product_filter"
27 
28 
29 @dataclass(frozen=True, kw_only=True)
31  """Describes Trafikverket sensor entity."""
32 
33  value_fn: Callable[[TrainData], StateType | datetime]
34 
35 
36 SENSOR_TYPES: tuple[TrafikverketSensorEntityDescription, ...] = (
38  key="departure_time",
39  translation_key="departure_time",
40  device_class=SensorDeviceClass.TIMESTAMP,
41  value_fn=lambda data: data.departure_time,
42  ),
44  key="departure_state",
45  translation_key="departure_state",
46  value_fn=lambda data: data.departure_state,
47  device_class=SensorDeviceClass.ENUM,
48  options=["on_time", "delayed", "canceled"],
49  ),
51  key="cancelled",
52  translation_key="cancelled",
53  value_fn=lambda data: data.cancelled,
54  ),
56  key="delayed_time",
57  translation_key="delayed_time",
58  device_class=SensorDeviceClass.DURATION,
59  native_unit_of_measurement=UnitOfTime.SECONDS,
60  value_fn=lambda data: data.delayed_time,
61  ),
63  key="planned_time",
64  translation_key="planned_time",
65  device_class=SensorDeviceClass.TIMESTAMP,
66  value_fn=lambda data: data.planned_time,
67  entity_registry_enabled_default=False,
68  ),
70  key="estimated_time",
71  translation_key="estimated_time",
72  device_class=SensorDeviceClass.TIMESTAMP,
73  value_fn=lambda data: data.estimated_time,
74  entity_registry_enabled_default=False,
75  ),
77  key="actual_time",
78  translation_key="actual_time",
79  device_class=SensorDeviceClass.TIMESTAMP,
80  value_fn=lambda data: data.actual_time,
81  entity_registry_enabled_default=False,
82  ),
84  key="other_info",
85  translation_key="other_info",
86  value_fn=lambda data: data.other_info,
87  ),
89  key="deviation",
90  translation_key="deviation",
91  value_fn=lambda data: data.deviation,
92  ),
94  key="departure_time_next",
95  translation_key="departure_time_next",
96  device_class=SensorDeviceClass.TIMESTAMP,
97  value_fn=lambda data: data.departure_time_next,
98  ),
100  key="departure_time_next_next",
101  translation_key="departure_time_next_next",
102  device_class=SensorDeviceClass.TIMESTAMP,
103  value_fn=lambda data: data.departure_time_next_next,
104  ),
105 )
106 
107 
109  hass: HomeAssistant,
110  entry: TVTrainConfigEntry,
111  async_add_entities: AddEntitiesCallback,
112 ) -> None:
113  """Set up the Trafikverket sensor entry."""
114 
115  coordinator = entry.runtime_data
116 
118  [
119  TrainSensor(coordinator, entry.data[CONF_NAME], entry.entry_id, description)
120  for description in SENSOR_TYPES
121  ]
122  )
123 
124 
125 class TrainSensor(CoordinatorEntity[TVDataUpdateCoordinator], SensorEntity):
126  """Contains data about a train depature."""
127 
128  entity_description: TrafikverketSensorEntityDescription
129  _attr_attribution = ATTRIBUTION
130  _attr_has_entity_name = True
131 
132  def __init__(
133  self,
134  coordinator: TVDataUpdateCoordinator,
135  name: str,
136  entry_id: str,
137  entity_description: TrafikverketSensorEntityDescription,
138  ) -> None:
139  """Initialize the sensor."""
140  super().__init__(coordinator)
141  self._attr_unique_id_attr_unique_id = f"{entry_id}-{entity_description.key}"
142  self.entity_descriptionentity_description = entity_description
143  self._attr_device_info_attr_device_info = DeviceInfo(
144  entry_type=DeviceEntryType.SERVICE,
145  identifiers={(DOMAIN, entry_id)},
146  name=name,
147  configuration_url="https://api.trafikinfo.trafikverket.se/",
148  )
149  self._update_attr_update_attr()
150 
151  @callback
152  def _update_attr(self) -> None:
153  """Update _attr."""
154  self._attr_native_value_attr_native_value = self.entity_descriptionentity_description.value_fn(
155  self.coordinator.data
156  )
157 
158  @callback
159  def _handle_coordinator_update(self) -> None:
160  self._update_attr_update_attr()
161  return super()._handle_coordinator_update()
162 
163  @property
164  def extra_state_attributes(self) -> Mapping[str, Any] | None:
165  """Return additional attributes for Trafikverket Train sensor."""
166  if self.coordinator.data.product_filter:
167  return {ATTR_PRODUCT_FILTER: self.coordinator.data.product_filter}
168  return None
None __init__(self, TVDataUpdateCoordinator coordinator, str name, str entry_id, TrafikverketSensorEntityDescription entity_description)
Definition: sensor.py:138
None async_setup_entry(HomeAssistant hass, TVTrainConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:112