Home Assistant Unofficial Reference 2024.12.1
coordinator.py
Go to the documentation of this file.
1 """Weather data coordinator for the AEMET OpenData service."""
2 
3 from __future__ import annotations
4 
5 from asyncio import timeout
6 from dataclasses import dataclass
7 from datetime import timedelta
8 import logging
9 from typing import Any, Final, cast
10 
11 from aemet_opendata.const import (
12  AOD_CONDITION,
13  AOD_FORECAST,
14  AOD_FORECAST_DAILY,
15  AOD_FORECAST_HOURLY,
16  AOD_TOWN,
17 )
18 from aemet_opendata.exceptions import AemetError
19 from aemet_opendata.helpers import dict_nested_value
20 from aemet_opendata.interface import AEMET
21 
22 from homeassistant.components.weather import Forecast
23 from homeassistant.config_entries import ConfigEntry
24 from homeassistant.core import HomeAssistant
25 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
26 
27 from .const import CONDITIONS_MAP, DOMAIN, FORECAST_MAP
28 
29 _LOGGER = logging.getLogger(__name__)
30 
31 API_TIMEOUT: Final[int] = 120
32 WEATHER_UPDATE_INTERVAL = timedelta(minutes=10)
33 
34 type AemetConfigEntry = ConfigEntry[AemetData]
35 
36 
37 @dataclass
38 class AemetData:
39  """Aemet runtime data."""
40 
41  name: str
42  coordinator: WeatherUpdateCoordinator
43 
44 
46  """Weather data update coordinator."""
47 
48  def __init__(
49  self,
50  hass: HomeAssistant,
51  entry: AemetConfigEntry,
52  aemet: AEMET,
53  ) -> None:
54  """Initialize coordinator."""
55  self.aemetaemet = aemet
56 
57  super().__init__(
58  hass,
59  _LOGGER,
60  config_entry=entry,
61  name=DOMAIN,
62  update_interval=WEATHER_UPDATE_INTERVAL,
63  )
64 
65  async def _async_update_data(self) -> dict[str, Any]:
66  """Update coordinator data."""
67  async with timeout(API_TIMEOUT):
68  try:
69  await self.aemetaemet.update()
70  except AemetError as error:
71  raise UpdateFailed(error) from error
72 
73  data = self.aemetaemet.data()
74 
75  return {
76  "forecast": {
77  AOD_FORECAST_DAILY: self.aemet_forecastaemet_forecast(data, AOD_FORECAST_DAILY),
78  AOD_FORECAST_HOURLY: self.aemet_forecastaemet_forecast(data, AOD_FORECAST_HOURLY),
79  },
80  "lib": data,
81  }
82 
84  self,
85  data: dict[str, Any],
86  forecast_mode: str,
87  ) -> list[Forecast]:
88  """Return the forecast array."""
89  forecasts = dict_nested_value(data, [AOD_TOWN, forecast_mode, AOD_FORECAST])
90  forecast_map = FORECAST_MAP[forecast_mode]
91  forecast_list: list[dict[str, Any]] = []
92  for forecast in forecasts:
93  cur_forecast: dict[str, Any] = {}
94  for api_key, ha_key in forecast_map.items():
95  value = forecast[api_key]
96  if api_key == AOD_CONDITION:
97  value = CONDITIONS_MAP.get(value)
98  cur_forecast[ha_key] = value
99  forecast_list += [cur_forecast]
100  return cast(list[Forecast], forecast_list)
None __init__(self, HomeAssistant hass, AemetConfigEntry entry, AEMET aemet)
Definition: coordinator.py:53
list[Forecast] aemet_forecast(self, dict[str, Any] data, str forecast_mode)
Definition: coordinator.py:87
IssData update(pyiss.ISS iss)
Definition: __init__.py:33