Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Ferry information for departures, provided by Trafikverket."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from datetime import datetime, timedelta
8 from typing import Any, cast
9 
11  SensorDeviceClass,
12  SensorEntity,
13  SensorEntityDescription,
14 )
15 from homeassistant.const import CONF_NAME
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 from homeassistant.util.dt import as_utc
22 
23 from . import TVFerryConfigEntry
24 from .const import ATTRIBUTION, DOMAIN
25 from .coordinator import TVDataUpdateCoordinator
26 
27 ATTR_FROM = "from_harbour"
28 ATTR_TO = "to_harbour"
29 ATTR_MODIFIED_TIME = "modified_time"
30 ATTR_OTHER_INFO = "other_info"
31 
32 SCAN_INTERVAL = timedelta(minutes=5)
33 
34 
35 @dataclass(frozen=True, kw_only=True)
37  """Describes Trafikverket sensor entity."""
38 
39  value_fn: Callable[[dict[str, Any]], StateType | datetime]
40  info_fn: Callable[[dict[str, Any]], StateType | list] | None
41 
42 
43 SENSOR_TYPES: tuple[TrafikverketSensorEntityDescription, ...] = (
45  key="departure_time",
46  translation_key="departure_time",
47  device_class=SensorDeviceClass.TIMESTAMP,
48  value_fn=lambda data: as_utc(data["departure_time"]),
49  info_fn=lambda data: cast(list[str], data["departure_information"]),
50  ),
52  key="departure_from",
53  translation_key="departure_from",
54  value_fn=lambda data: cast(str, data["departure_from"]),
55  info_fn=lambda data: cast(list[str], data["departure_information"]),
56  ),
58  key="departure_to",
59  translation_key="departure_to",
60  value_fn=lambda data: cast(str, data["departure_to"]),
61  info_fn=lambda data: cast(list[str], data["departure_information"]),
62  ),
64  key="departure_modified",
65  translation_key="departure_modified",
66  device_class=SensorDeviceClass.TIMESTAMP,
67  value_fn=lambda data: as_utc(data["departure_modified"]),
68  info_fn=lambda data: cast(list[str], data["departure_information"]),
69  entity_registry_enabled_default=False,
70  ),
72  key="departure_time_next",
73  translation_key="departure_time_next",
74  device_class=SensorDeviceClass.TIMESTAMP,
75  value_fn=lambda data: as_utc(data["departure_time_next"]),
76  info_fn=None,
77  entity_registry_enabled_default=False,
78  ),
80  key="departure_time_next_next",
81  translation_key="departure_time_next_next",
82  device_class=SensorDeviceClass.TIMESTAMP,
83  value_fn=lambda data: as_utc(data["departure_time_next_next"]),
84  info_fn=None,
85  entity_registry_enabled_default=False,
86  ),
87 )
88 
89 
91  hass: HomeAssistant,
92  entry: TVFerryConfigEntry,
93  async_add_entities: AddEntitiesCallback,
94 ) -> None:
95  """Set up the Trafikverket sensor entry."""
96 
97  coordinator = entry.runtime_data
98 
100  [
101  FerrySensor(coordinator, entry.data[CONF_NAME], entry.entry_id, description)
102  for description in SENSOR_TYPES
103  ]
104  )
105 
106 
107 class FerrySensor(CoordinatorEntity[TVDataUpdateCoordinator], SensorEntity):
108  """Contains data about a ferry departure."""
109 
110  entity_description: TrafikverketSensorEntityDescription
111  _attr_attribution = ATTRIBUTION
112  _attr_has_entity_name = True
113 
114  def __init__(
115  self,
116  coordinator: TVDataUpdateCoordinator,
117  name: str,
118  entry_id: str,
119  entity_description: TrafikverketSensorEntityDescription,
120  ) -> None:
121  """Initialize the sensor."""
122  super().__init__(coordinator)
123  self._attr_unique_id_attr_unique_id = f"{entry_id}-{entity_description.key}"
124  self.entity_descriptionentity_description = entity_description
125  self._attr_device_info_attr_device_info = DeviceInfo(
126  entry_type=DeviceEntryType.SERVICE,
127  identifiers={(DOMAIN, entry_id)},
128  manufacturer="Trafikverket",
129  model="v2.0",
130  name=name,
131  configuration_url="https://api.trafikinfo.trafikverket.se/",
132  )
133  self._update_attr_update_attr()
134 
135  def _update_attr(self) -> None:
136  """Update _attr."""
137  self._attr_native_value_attr_native_value = self.entity_descriptionentity_description.value_fn(
138  self.coordinator.data
139  )
140 
141  if self.entity_descriptionentity_description.info_fn:
142  self._attr_extra_state_attributes_attr_extra_state_attributes = {
143  "other_information": self.entity_descriptionentity_description.info_fn(
144  self.coordinator.data
145  ),
146  }
147 
148  @callback
149  def _handle_coordinator_update(self) -> None:
150  self._update_attr_update_attr()
151  return super()._handle_coordinator_update()
None __init__(self, TVDataUpdateCoordinator coordinator, str name, str entry_id, TrafikverketSensorEntityDescription entity_description)
Definition: sensor.py:120
None async_setup_entry(HomeAssistant hass, TVFerryConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:94
dt.datetime as_utc(dt.datetime dattim)
Definition: dt.py:132