"""Weather data coordinator for the AEMET OpenData service.""" from __future__ import annotations from asyncio import timeout from datetime import timedelta import logging from typing import Any, Final, cast from aemet_opendata.const import ( AOD_CONDITION, AOD_FORECAST, AOD_FORECAST_DAILY, AOD_FORECAST_HOURLY, AOD_TOWN, ) from aemet_opendata.exceptions import AemetError from aemet_opendata.helpers import dict_nested_value from aemet_opendata.interface import AEMET from homeassistant.components.weather import Forecast from homeassistant.core import HomeAssistant from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import CONDITIONS_MAP, DOMAIN, FORECAST_MAP _LOGGER = logging.getLogger(__name__) API_TIMEOUT: Final[int] = 120 WEATHER_UPDATE_INTERVAL = timedelta(minutes=10) class WeatherUpdateCoordinator(DataUpdateCoordinator): """Weather data update coordinator.""" def __init__( self, hass: HomeAssistant, aemet: AEMET, ) -> None: """Initialize coordinator.""" self.aemet = aemet super().__init__( hass, _LOGGER, name=DOMAIN, update_interval=WEATHER_UPDATE_INTERVAL, ) async def _async_update_data(self) -> dict[str, Any]: """Update coordinator data.""" async with timeout(API_TIMEOUT): try: await self.aemet.update() except AemetError as error: raise UpdateFailed(error) from error data = self.aemet.data() return { "forecast": { AOD_FORECAST_DAILY: self.aemet_forecast(data, AOD_FORECAST_DAILY), AOD_FORECAST_HOURLY: self.aemet_forecast(data, AOD_FORECAST_HOURLY), }, "lib": data, } def aemet_forecast( self, data: dict[str, Any], forecast_mode: str, ) -> list[Forecast]: """Return the forecast array.""" forecasts = dict_nested_value(data, [AOD_TOWN, forecast_mode, AOD_FORECAST]) forecast_map = FORECAST_MAP[forecast_mode] forecast_list: list[dict[str, Any]] = [] for forecast in forecasts: cur_forecast: dict[str, Any] = {} for api_key, ha_key in forecast_map.items(): value = forecast[api_key] if api_key == AOD_CONDITION: value = CONDITIONS_MAP.get(value) cur_forecast[ha_key] = value forecast_list += [cur_forecast] return cast(list[Forecast], forecast_list)