Home Assistant Unofficial Reference 2024.12.1
coordinator.py
Go to the documentation of this file.
1 """DataUpdateCoordinators for awair integration."""
2 
3 from __future__ import annotations
4 
5 from asyncio import gather, timeout
6 from dataclasses import dataclass
7 from datetime import timedelta
8 
9 from aiohttp import ClientSession
10 from python_awair import Awair, AwairLocal
11 from python_awair.air_data import AirData
12 from python_awair.devices import AwairBaseDevice, AwairLocalDevice
13 from python_awair.exceptions import AuthError, AwairError
14 
15 from homeassistant.config_entries import ConfigEntry
16 from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST
17 from homeassistant.core import HomeAssistant
18 from homeassistant.exceptions import ConfigEntryAuthFailed
19 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
20 
21 from .const import (
22  API_TIMEOUT,
23  DOMAIN,
24  LOGGER,
25  UPDATE_INTERVAL_CLOUD,
26  UPDATE_INTERVAL_LOCAL,
27 )
28 
29 type AwairConfigEntry = ConfigEntry[AwairDataUpdateCoordinator]
30 
31 
32 @dataclass
34  """Wrapper class to hold an awair device and set of air data."""
35 
36  device: AwairBaseDevice
37  air_data: AirData
38 
39 
40 class AwairDataUpdateCoordinator(DataUpdateCoordinator[dict[str, AwairResult]]):
41  """Define a wrapper class to update Awair data."""
42 
43  def __init__(
44  self,
45  hass: HomeAssistant,
46  config_entry: ConfigEntry,
47  update_interval: timedelta | None,
48  ) -> None:
49  """Set up the AwairDataUpdateCoordinator class."""
50  self._config_entry_config_entry = config_entry
51  self.titletitle = config_entry.title
52 
53  super().__init__(hass, LOGGER, name=DOMAIN, update_interval=update_interval)
54 
55  async def _fetch_air_data(self, device: AwairBaseDevice) -> AwairResult:
56  """Fetch latest air quality data."""
57  LOGGER.debug("Fetching data for %s", device.uuid)
58  air_data = await device.air_data_latest()
59  LOGGER.debug(air_data)
60  return AwairResult(device=device, air_data=air_data)
61 
62 
64  """Define a wrapper class to update Awair data from Cloud API."""
65 
66  def __init__(
67  self, hass: HomeAssistant, config_entry: ConfigEntry, session: ClientSession
68  ) -> None:
69  """Set up the AwairCloudDataUpdateCoordinator class."""
70  access_token = config_entry.data[CONF_ACCESS_TOKEN]
71  self._awair_awair = Awair(access_token=access_token, session=session)
72 
73  super().__init__(hass, config_entry, UPDATE_INTERVAL_CLOUD)
74 
75  async def _async_update_data(self) -> dict[str, AwairResult]:
76  """Update data via Awair client library."""
77  async with timeout(API_TIMEOUT):
78  try:
79  LOGGER.debug("Fetching users and devices")
80  user = await self._awair_awair.user()
81  devices = await user.devices()
82  results = await gather(
83  *(self._fetch_air_data_fetch_air_data(device) for device in devices)
84  )
85  return {result.device.uuid: result for result in results}
86  except AuthError as err:
87  raise ConfigEntryAuthFailed from err
88  except Exception as err:
89  raise UpdateFailed(err) from err
90 
91 
93  """Define a wrapper class to update Awair data from the local API."""
94 
95  _device: AwairLocalDevice | None = None
96 
97  def __init__(
98  self, hass: HomeAssistant, config_entry: ConfigEntry, session: ClientSession
99  ) -> None:
100  """Set up the AwairLocalDataUpdateCoordinator class."""
101  self._awair_awair = AwairLocal(
102  session=session, device_addrs=[config_entry.data[CONF_HOST]]
103  )
104 
105  super().__init__(hass, config_entry, UPDATE_INTERVAL_LOCAL)
106 
107  async def _async_update_data(self) -> dict[str, AwairResult]:
108  """Update data via Awair client library."""
109  async with timeout(API_TIMEOUT):
110  try:
111  if self._device_device is None:
112  LOGGER.debug("Fetching devices")
113  devices = await self._awair_awair.devices()
114  self._device_device = devices[0]
115  result = await self._fetch_air_data_fetch_air_data(self._device_device)
116  except AwairError as err:
117  LOGGER.error("Unexpected API error: %s", err)
118  raise UpdateFailed(err) from err
119  return {result.device.uuid: result}
None __init__(self, HomeAssistant hass, ConfigEntry config_entry, ClientSession session)
Definition: coordinator.py:68
None __init__(self, HomeAssistant hass, ConfigEntry config_entry, timedelta|None update_interval)
Definition: coordinator.py:48
AwairResult _fetch_air_data(self, AwairBaseDevice device)
Definition: coordinator.py:55
None __init__(self, HomeAssistant hass, ConfigEntry config_entry, ClientSession session)
Definition: coordinator.py:99
dict[str, dict[str, Any]] devices(HomeAssistant hass)
Definition: __init__.py:237