core/homeassistant/components/canary/coordinator.py

66 lines
2.1 KiB
Python

"""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