1 """Support for the AEMET OpenData service."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
7 from datetime
import datetime
8 from typing
import Final
10 from aemet_opendata.const
import (
20 AOD_PRECIPITATION_PROBABILITY,
27 AOD_STORM_PROBABILITY,
38 from aemet_opendata.helpers
import dict_nested_value
43 SensorEntityDescription,
60 ATTR_API_FORECAST_CONDITION,
61 ATTR_API_FORECAST_PRECIPITATION,
62 ATTR_API_FORECAST_PRECIPITATION_PROBABILITY,
63 ATTR_API_FORECAST_TEMP,
64 ATTR_API_FORECAST_TEMP_LOW,
65 ATTR_API_FORECAST_TIME,
66 ATTR_API_FORECAST_WIND_BEARING,
67 ATTR_API_FORECAST_WIND_MAX_SPEED,
68 ATTR_API_FORECAST_WIND_SPEED,
76 ATTR_API_STATION_NAME,
77 ATTR_API_STATION_TIMESTAMP,
80 ATTR_API_TEMPERATURE_FEELING,
83 ATTR_API_TOWN_TIMESTAMP,
84 ATTR_API_WIND_BEARING,
85 ATTR_API_WIND_MAX_SPEED,
89 from .coordinator
import AemetConfigEntry, WeatherUpdateCoordinator
90 from .entity
import AemetEntity
93 @dataclass(frozen=True, kw_only=True)
95 """A class that describes AEMET OpenData sensor entities."""
97 keys: list[str] |
None =
None
98 value_fn: Callable[[str], datetime | float | int | str |
None] =
lambda value: value
101 FORECAST_SENSORS: Final[tuple[AemetSensorEntityDescription, ...]] = (
103 key=f
"forecast-daily-{ATTR_API_FORECAST_CONDITION}",
104 keys=[AOD_TOWN, AOD_FORECAST_DAILY, AOD_FORECAST_CURRENT, AOD_CONDITION],
105 name=
"Daily forecast condition",
106 value_fn=CONDITIONS_MAP.get,
109 entity_registry_enabled_default=
False,
110 key=f
"forecast-hourly-{ATTR_API_FORECAST_CONDITION}",
111 keys=[AOD_TOWN, AOD_FORECAST_HOURLY, AOD_FORECAST_CURRENT, AOD_CONDITION],
112 name=
"Hourly forecast condition",
113 value_fn=CONDITIONS_MAP.get,
116 entity_registry_enabled_default=
False,
117 key=f
"forecast-hourly-{ATTR_API_FORECAST_PRECIPITATION}",
118 keys=[AOD_TOWN, AOD_FORECAST_HOURLY, AOD_FORECAST_CURRENT, AOD_PRECIPITATION],
119 name=
"Hourly forecast precipitation",
120 native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
121 device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
124 key=f
"forecast-daily-{ATTR_API_FORECAST_PRECIPITATION_PROBABILITY}",
128 AOD_FORECAST_CURRENT,
129 AOD_PRECIPITATION_PROBABILITY,
131 name=
"Daily forecast precipitation probability",
132 native_unit_of_measurement=PERCENTAGE,
135 entity_registry_enabled_default=
False,
136 key=f
"forecast-hourly-{ATTR_API_FORECAST_PRECIPITATION_PROBABILITY}",
140 AOD_FORECAST_CURRENT,
141 AOD_PRECIPITATION_PROBABILITY,
143 name=
"Hourly forecast precipitation probability",
144 native_unit_of_measurement=PERCENTAGE,
147 key=f
"forecast-daily-{ATTR_API_FORECAST_TEMP}",
148 keys=[AOD_TOWN, AOD_FORECAST_DAILY, AOD_FORECAST_CURRENT, AOD_TEMP_MAX],
149 name=
"Daily forecast temperature",
150 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
151 device_class=SensorDeviceClass.TEMPERATURE,
154 key=f
"forecast-daily-{ATTR_API_FORECAST_TEMP_LOW}",
155 keys=[AOD_TOWN, AOD_FORECAST_DAILY, AOD_FORECAST_CURRENT, AOD_TEMP_MIN],
156 name=
"Daily forecast temperature low",
157 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
158 device_class=SensorDeviceClass.TEMPERATURE,
161 entity_registry_enabled_default=
False,
162 key=f
"forecast-hourly-{ATTR_API_FORECAST_TEMP}",
163 keys=[AOD_TOWN, AOD_FORECAST_HOURLY, AOD_FORECAST_CURRENT, AOD_TEMP],
164 name=
"Hourly forecast temperature",
165 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
166 device_class=SensorDeviceClass.TEMPERATURE,
169 key=f
"forecast-daily-{ATTR_API_FORECAST_TIME}",
170 keys=[AOD_TOWN, AOD_FORECAST_DAILY, AOD_FORECAST_CURRENT, AOD_TIMESTAMP_UTC],
171 name=
"Daily forecast time",
172 device_class=SensorDeviceClass.TIMESTAMP,
173 value_fn=dt_util.parse_datetime,
176 entity_registry_enabled_default=
False,
177 key=f
"forecast-hourly-{ATTR_API_FORECAST_TIME}",
178 keys=[AOD_TOWN, AOD_FORECAST_HOURLY, AOD_FORECAST_CURRENT, AOD_TIMESTAMP_UTC],
179 name=
"Hourly forecast time",
180 device_class=SensorDeviceClass.TIMESTAMP,
181 value_fn=dt_util.parse_datetime,
184 key=f
"forecast-daily-{ATTR_API_FORECAST_WIND_BEARING}",
185 keys=[AOD_TOWN, AOD_FORECAST_DAILY, AOD_FORECAST_CURRENT, AOD_WIND_DIRECTION],
186 name=
"Daily forecast wind bearing",
187 native_unit_of_measurement=DEGREE,
190 entity_registry_enabled_default=
False,
191 key=f
"forecast-hourly-{ATTR_API_FORECAST_WIND_BEARING}",
192 keys=[AOD_TOWN, AOD_FORECAST_HOURLY, AOD_FORECAST_CURRENT, AOD_WIND_DIRECTION],
193 name=
"Hourly forecast wind bearing",
194 native_unit_of_measurement=DEGREE,
197 entity_registry_enabled_default=
False,
198 key=f
"forecast-hourly-{ATTR_API_FORECAST_WIND_MAX_SPEED}",
199 keys=[AOD_TOWN, AOD_FORECAST_HOURLY, AOD_FORECAST_CURRENT, AOD_WIND_SPEED_MAX],
200 name=
"Hourly forecast wind max speed",
201 native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
202 device_class=SensorDeviceClass.WIND_SPEED,
205 key=f
"forecast-daily-{ATTR_API_FORECAST_WIND_SPEED}",
206 keys=[AOD_TOWN, AOD_FORECAST_DAILY, AOD_FORECAST_CURRENT, AOD_WIND_SPEED],
207 name=
"Daily forecast wind speed",
208 native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
209 device_class=SensorDeviceClass.WIND_SPEED,
212 entity_registry_enabled_default=
False,
213 key=f
"forecast-hourly-{ATTR_API_FORECAST_WIND_SPEED}",
214 keys=[AOD_TOWN, AOD_FORECAST_HOURLY, AOD_FORECAST_CURRENT, AOD_WIND_SPEED],
215 name=
"Hourly forecast wind speed",
216 native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
217 device_class=SensorDeviceClass.WIND_SPEED,
222 WEATHER_SENSORS: Final[tuple[AemetSensorEntityDescription, ...]] = (
224 key=ATTR_API_CONDITION,
225 keys=[AOD_WEATHER, AOD_CONDITION],
227 value_fn=CONDITIONS_MAP.get,
230 key=ATTR_API_HUMIDITY,
231 keys=[AOD_WEATHER, AOD_HUMIDITY],
233 native_unit_of_measurement=PERCENTAGE,
234 device_class=SensorDeviceClass.HUMIDITY,
235 state_class=SensorStateClass.MEASUREMENT,
238 key=ATTR_API_PRESSURE,
239 keys=[AOD_WEATHER, AOD_PRESSURE],
241 native_unit_of_measurement=UnitOfPressure.HPA,
242 device_class=SensorDeviceClass.PRESSURE,
243 state_class=SensorStateClass.MEASUREMENT,
247 keys=[AOD_WEATHER, AOD_RAIN],
249 native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
250 device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
251 state_class=SensorStateClass.MEASUREMENT,
254 key=ATTR_API_RAIN_PROB,
255 keys=[AOD_WEATHER, AOD_RAIN_PROBABILITY],
256 name=
"Rain probability",
257 native_unit_of_measurement=PERCENTAGE,
258 state_class=SensorStateClass.MEASUREMENT,
262 keys=[AOD_WEATHER, AOD_SNOW],
264 native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
265 device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
266 state_class=SensorStateClass.MEASUREMENT,
269 key=ATTR_API_SNOW_PROB,
270 keys=[AOD_WEATHER, AOD_SNOW_PROBABILITY],
271 name=
"Snow probability",
272 native_unit_of_measurement=PERCENTAGE,
273 state_class=SensorStateClass.MEASUREMENT,
276 key=ATTR_API_STATION_ID,
277 keys=[AOD_STATION, AOD_ID],
281 key=ATTR_API_STATION_NAME,
282 keys=[AOD_STATION, AOD_NAME],
286 key=ATTR_API_STATION_TIMESTAMP,
287 keys=[AOD_STATION, AOD_TIMESTAMP_UTC],
288 name=
"Station timestamp",
289 device_class=SensorDeviceClass.TIMESTAMP,
290 value_fn=dt_util.parse_datetime,
293 key=ATTR_API_STORM_PROB,
294 keys=[AOD_WEATHER, AOD_STORM_PROBABILITY],
295 name=
"Storm probability",
296 native_unit_of_measurement=PERCENTAGE,
297 state_class=SensorStateClass.MEASUREMENT,
300 key=ATTR_API_TEMPERATURE,
301 keys=[AOD_WEATHER, AOD_TEMP],
303 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
304 device_class=SensorDeviceClass.TEMPERATURE,
305 state_class=SensorStateClass.MEASUREMENT,
308 key=ATTR_API_TEMPERATURE_FEELING,
309 keys=[AOD_WEATHER, AOD_FEEL_TEMP],
310 name=
"Temperature feeling",
311 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
312 device_class=SensorDeviceClass.TEMPERATURE,
313 state_class=SensorStateClass.MEASUREMENT,
316 key=ATTR_API_TOWN_ID,
317 keys=[AOD_TOWN, AOD_ID],
321 key=ATTR_API_TOWN_NAME,
322 keys=[AOD_TOWN, AOD_NAME],
326 key=ATTR_API_TOWN_TIMESTAMP,
327 keys=[AOD_TOWN, AOD_FORECAST_HOURLY, AOD_TIMESTAMP_UTC],
328 name=
"Town timestamp",
329 device_class=SensorDeviceClass.TIMESTAMP,
330 value_fn=dt_util.parse_datetime,
333 key=ATTR_API_WIND_BEARING,
334 keys=[AOD_WEATHER, AOD_WIND_DIRECTION],
336 native_unit_of_measurement=DEGREE,
337 state_class=SensorStateClass.MEASUREMENT,
340 key=ATTR_API_WIND_MAX_SPEED,
341 keys=[AOD_WEATHER, AOD_WIND_SPEED_MAX],
342 name=
"Wind max speed",
343 native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
344 device_class=SensorDeviceClass.WIND_SPEED,
345 state_class=SensorStateClass.MEASUREMENT,
348 key=ATTR_API_WIND_SPEED,
349 keys=[AOD_WEATHER, AOD_WIND_SPEED],
351 native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
352 device_class=SensorDeviceClass.WIND_SPEED,
353 state_class=SensorStateClass.MEASUREMENT,
360 config_entry: AemetConfigEntry,
361 async_add_entities: AddEntitiesCallback,
363 """Set up AEMET OpenData sensor entities based on a config entry."""
364 domain_data = config_entry.runtime_data
365 name = domain_data.name
366 coordinator = domain_data.coordinator
368 unique_id = config_entry.unique_id
369 assert unique_id
is not None
378 for description
in FORECAST_SENSORS + WEATHER_SENSORS
379 if dict_nested_value(coordinator.data[
"lib"], description.keys)
is not None
384 """Implementation of an AEMET OpenData sensor."""
386 entity_description: AemetSensorEntityDescription
391 coordinator: WeatherUpdateCoordinator,
392 description: AemetSensorEntityDescription,
395 """Initialize the sensor."""
396 super().
__init__(coordinator, name, unique_id)
402 """Return the state of the device."""
Any get_aemet_value(self, list[str] keys)
None __init__(self, str name, WeatherUpdateCoordinator coordinator, AemetSensorEntityDescription description, str unique_id)
None async_setup_entry(HomeAssistant hass, AemetConfigEntry config_entry, AddEntitiesCallback async_add_entities)