Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Weather information for air and road temperature (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
8 
9 from pytrafikverket.models import WeatherStationInfoModel
10 
12  SensorDeviceClass,
13  SensorEntity,
14  SensorEntityDescription,
15  SensorStateClass,
16 )
17 from homeassistant.const import (
18  DEGREE,
19  PERCENTAGE,
20  UnitOfLength,
21  UnitOfSpeed,
22  UnitOfTemperature,
23  UnitOfVolumetricFlux,
24 )
25 from homeassistant.core import HomeAssistant
26 from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
27 from homeassistant.helpers.entity_platform import AddEntitiesCallback
28 from homeassistant.helpers.typing import StateType
29 from homeassistant.helpers.update_coordinator import CoordinatorEntity
30 from homeassistant.util import dt as dt_util
31 
32 from . import TVWeatherConfigEntry
33 from .const import ATTRIBUTION, CONF_STATION, DOMAIN
34 from .coordinator import TVDataUpdateCoordinator
35 
36 PRECIPITATION_TYPE = [
37  "no",
38  "rain",
39  "freezing_rain",
40  "snow",
41  "sleet",
42  "yes",
43 ]
44 
45 
46 @dataclass(frozen=True, kw_only=True)
48  """Describes Trafikverket sensor entity."""
49 
50  value_fn: Callable[[WeatherStationInfoModel], StateType | datetime]
51 
52 
53 def add_utc_timezone(date_time: datetime | None) -> datetime | None:
54  """Add UTC timezone if datetime."""
55  if date_time:
56  return date_time.replace(tzinfo=dt_util.UTC)
57  return None
58 
59 
60 SENSOR_TYPES: tuple[TrafikverketSensorEntityDescription, ...] = (
62  key="air_temp",
63  translation_key="air_temperature",
64  value_fn=lambda data: data.air_temp,
65  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
66  device_class=SensorDeviceClass.TEMPERATURE,
67  state_class=SensorStateClass.MEASUREMENT,
68  ),
70  key="road_temp",
71  translation_key="road_temperature",
72  value_fn=lambda data: data.road_temp,
73  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
74  device_class=SensorDeviceClass.TEMPERATURE,
75  state_class=SensorStateClass.MEASUREMENT,
76  ),
78  key="precipitation",
79  translation_key="precipitation",
80  value_fn=lambda data: data.precipitationtype,
81  entity_registry_enabled_default=False,
82  options=PRECIPITATION_TYPE,
83  device_class=SensorDeviceClass.ENUM,
84  ),
86  key="wind_direction",
87  translation_key="wind_direction",
88  value_fn=lambda data: data.winddirection,
89  native_unit_of_measurement=DEGREE,
90  state_class=SensorStateClass.MEASUREMENT,
91  ),
93  key="wind_speed",
94  value_fn=lambda data: data.windforce,
95  native_unit_of_measurement=UnitOfSpeed.METERS_PER_SECOND,
96  device_class=SensorDeviceClass.WIND_SPEED,
97  state_class=SensorStateClass.MEASUREMENT,
98  ),
100  key="wind_speed_max",
101  translation_key="wind_speed_max",
102  value_fn=lambda data: data.windforcemax,
103  native_unit_of_measurement=UnitOfSpeed.METERS_PER_SECOND,
104  device_class=SensorDeviceClass.WIND_SPEED,
105  entity_registry_enabled_default=False,
106  state_class=SensorStateClass.MEASUREMENT,
107  ),
109  key="humidity",
110  value_fn=lambda data: data.humidity,
111  native_unit_of_measurement=PERCENTAGE,
112  device_class=SensorDeviceClass.HUMIDITY,
113  entity_registry_enabled_default=False,
114  state_class=SensorStateClass.MEASUREMENT,
115  ),
117  key="precipitation_amount",
118  value_fn=lambda data: data.precipitation_amount,
119  native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
120  device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
121  state_class=SensorStateClass.MEASUREMENT,
122  ),
124  key="measure_time",
125  translation_key="measure_time",
126  value_fn=lambda data: data.measure_time,
127  entity_registry_enabled_default=False,
128  device_class=SensorDeviceClass.TIMESTAMP,
129  ),
131  key="dew_point",
132  translation_key="dew_point",
133  value_fn=lambda data: data.dew_point,
134  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
135  device_class=SensorDeviceClass.TEMPERATURE,
136  state_class=SensorStateClass.MEASUREMENT,
137  ),
139  key="visible_distance",
140  translation_key="visible_distance",
141  value_fn=lambda data: data.visible_distance,
142  native_unit_of_measurement=UnitOfLength.METERS,
143  device_class=SensorDeviceClass.DISTANCE,
144  state_class=SensorStateClass.MEASUREMENT,
145  entity_registry_enabled_default=False,
146  ),
148  key="road_ice_depth",
149  translation_key="road_ice_depth",
150  value_fn=lambda data: data.road_ice_depth,
151  native_unit_of_measurement=UnitOfLength.MILLIMETERS,
152  device_class=SensorDeviceClass.DISTANCE,
153  state_class=SensorStateClass.MEASUREMENT,
154  entity_registry_enabled_default=False,
155  ),
157  key="road_snow_depth",
158  translation_key="road_snow_depth",
159  value_fn=lambda data: data.road_snow_depth,
160  native_unit_of_measurement=UnitOfLength.MILLIMETERS,
161  device_class=SensorDeviceClass.DISTANCE,
162  state_class=SensorStateClass.MEASUREMENT,
163  entity_registry_enabled_default=False,
164  ),
166  key="road_water_depth",
167  translation_key="road_water_depth",
168  value_fn=lambda data: data.road_water_depth,
169  native_unit_of_measurement=UnitOfLength.MILLIMETERS,
170  device_class=SensorDeviceClass.DISTANCE,
171  state_class=SensorStateClass.MEASUREMENT,
172  entity_registry_enabled_default=False,
173  ),
175  key="road_water_equivalent_depth",
176  translation_key="road_water_equivalent_depth",
177  value_fn=lambda data: data.road_water_equivalent_depth,
178  native_unit_of_measurement=UnitOfLength.MILLIMETERS,
179  device_class=SensorDeviceClass.DISTANCE,
180  state_class=SensorStateClass.MEASUREMENT,
181  entity_registry_enabled_default=False,
182  ),
184  key="wind_height",
185  translation_key="wind_height",
186  value_fn=lambda data: data.wind_height,
187  native_unit_of_measurement=UnitOfLength.METERS,
188  device_class=SensorDeviceClass.DISTANCE,
189  state_class=SensorStateClass.MEASUREMENT,
190  entity_registry_enabled_default=False,
191  ),
193  key="modified_time",
194  translation_key="modified_time",
195  value_fn=lambda data: add_utc_timezone(data.modified_time),
196  entity_registry_enabled_default=False,
197  device_class=SensorDeviceClass.TIMESTAMP,
198  ),
199 )
200 
201 
203  hass: HomeAssistant,
204  entry: TVWeatherConfigEntry,
205  async_add_entities: AddEntitiesCallback,
206 ) -> None:
207  """Set up the Trafikverket sensor entry."""
208 
209  coordinator = entry.runtime_data
210 
213  coordinator, entry.entry_id, entry.data[CONF_STATION], description
214  )
215  for description in SENSOR_TYPES
216  )
217 
218 
220  CoordinatorEntity[TVDataUpdateCoordinator], SensorEntity
221 ):
222  """Representation of a Trafikverket sensor."""
223 
224  entity_description: TrafikverketSensorEntityDescription
225  _attr_attribution = ATTRIBUTION
226  _attr_has_entity_name = True
227 
228  def __init__(
229  self,
230  coordinator: TVDataUpdateCoordinator,
231  entry_id: str,
232  sensor_station: str,
233  description: TrafikverketSensorEntityDescription,
234  ) -> None:
235  """Initialize the sensor."""
236  super().__init__(coordinator)
237  self.entity_descriptionentity_description = description
238  self._attr_unique_id_attr_unique_id = f"{entry_id}_{description.key}"
239  self._attr_device_info_attr_device_info = DeviceInfo(
240  entry_type=DeviceEntryType.SERVICE,
241  identifiers={(DOMAIN, entry_id)},
242  manufacturer="Trafikverket",
243  model="v2.0",
244  name=sensor_station,
245  configuration_url="https://api.trafikinfo.trafikverket.se/",
246  )
247 
248  @property
249  def native_value(self) -> StateType | datetime:
250  """Return state of sensor."""
251  return self.entity_descriptionentity_description.value_fn(self.coordinator.data)
None __init__(self, TVDataUpdateCoordinator coordinator, str entry_id, str sensor_station, TrafikverketSensorEntityDescription description)
Definition: sensor.py:234
datetime|None add_utc_timezone(datetime|None date_time)
Definition: sensor.py:53
None async_setup_entry(HomeAssistant hass, TVWeatherConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:206