"""Provides the Canary DataUpdateCoordinator.""" from __future__ import annotations import asyncio from collections.abc import ValuesView from datetime import timedelta import logging from canary.api import Api from canary.model import Location, Reading from requests.exceptions import ConnectTimeout, HTTPError from homeassistant.core import HomeAssistant from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import DOMAIN from .model import CanaryData _LOGGER = logging.getLogger(__name__) class CanaryDataUpdateCoordinator(DataUpdateCoordinator[CanaryData]): """Class to manage fetching Canary data.""" def __init__(self, hass: HomeAssistant, *, api: Api) -> None: """Initialize global Canary data updater.""" self.canary = api update_interval = timedelta(seconds=30) super().__init__( hass, _LOGGER, name=DOMAIN, update_interval=update_interval, ) def _update_data(self) -> CanaryData: """Fetch data from Canary via sync functions.""" locations_by_id: dict[str, Location] = {} readings_by_device_id: dict[str, ValuesView[Reading]] = {} for location in self.canary.get_locations(): location_id = location.location_id locations_by_id[location_id] = location for device in location.devices: if device.is_online: readings_by_device_id[ device.device_id ] = self.canary.get_latest_readings(device.device_id) return { "locations": locations_by_id, "readings": readings_by_device_id, } async def _async_update_data(self) -> CanaryData: """Fetch data from Canary.""" try: async with asyncio.timeout(15): return await self.hass.async_add_executor_job(self._update_data) except (ConnectTimeout, HTTPError) as error: raise UpdateFailed(f"Invalid response from API: {error}") from error