Home Assistant Unofficial Reference 2024.12.1
coordinator.py
Go to the documentation of this file.
1 """Tradfri DataUpdateCoordinator."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from datetime import timedelta
7 from typing import Any
8 
9 from pytradfri.command import Command
10 from pytradfri.device import Device
11 from pytradfri.error import RequestError
12 
13 from homeassistant.core import HomeAssistant, callback
14 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
15 
16 from .const import LOGGER
17 
18 SCAN_INTERVAL = 60 # Interval for updating the coordinator
19 
20 
22  """Coordinator to manage data for a specific Tradfri device."""
23 
24  def __init__(
25  self,
26  hass: HomeAssistant,
27  *,
28  api: Callable[[Command | list[Command]], Any],
29  device: Device,
30  ) -> None:
31  """Initialize device coordinator."""
32  self.apiapi = api
33  self.devicedevice = device
34  self._exception_exception: Exception | None = None
35 
36  super().__init__(
37  hass,
38  LOGGER,
39  name=f"Update coordinator for {device}",
40  update_interval=timedelta(seconds=SCAN_INTERVAL),
41  )
42 
43  async def set_hub_available(self, available: bool) -> None:
44  """Set status of hub."""
45  if available != self.last_update_successlast_update_successlast_update_success:
46  if not available:
47  self.last_update_successlast_update_successlast_update_success = False
48  await self.async_request_refreshasync_request_refresh()
49 
50  @callback
51  def _observe_update(self, device: Device) -> None:
52  """Update the coordinator for a device when a change is detected."""
53  self.async_set_updated_dataasync_set_updated_data(data=device)
54 
55  @callback
56  def _exception_callback(self, exc: Exception) -> None:
57  """Schedule handling exception.."""
58  self.hasshass.async_create_task(self._handle_exception_handle_exception(exc))
59 
60  async def _handle_exception(self, exc: Exception) -> None:
61  """Handle observe exceptions in a coroutine."""
62  # Store exception so that it gets raised in _async_update_data
63  self._exception_exception = exc
64 
65  LOGGER.debug(
66  "Observation failed for %s, trying again", self.devicedevice, exc_info=exc
67  )
68  # Change interval so we get a swift refresh
70  await self.async_request_refreshasync_request_refresh()
71 
72  async def _async_update_data(self) -> Device:
73  """Fetch data from the gateway for a specific device."""
74  try:
75  if self._exception_exception:
76  exc = self._exception_exception
77  self._exception_exception = None # Clear stored exception
78  raise exc
79  except RequestError as err:
80  raise UpdateFailed(f"Error communicating with API: {err}.") from err
81 
82  if not self.datadata or not self.last_update_successlast_update_successlast_update_success: # Start subscription
83  try:
84  cmd = self.devicedevice.observe(
85  callback=self._observe_update_observe_update,
86  err_callback=self._exception_callback_exception_callback,
87  duration=0,
88  )
89  await self.apiapi(cmd)
90  except RequestError as err:
91  raise UpdateFailed(f"Error communicating with API: {err}.") from err
92 
93  # Reset update interval
94  self.update_intervalupdate_intervalupdate_intervalupdate_intervalupdate_interval = timedelta(seconds=SCAN_INTERVAL)
95 
96  return self.devicedevice
None __init__(self, HomeAssistant hass, *Callable[[Command|list[Command]], Any] api, Device device)
Definition: coordinator.py:30