Home Assistant Unofficial Reference 2024.12.1
coordinator.py
Go to the documentation of this file.
1 """Rabbit Air Update Coordinator."""
2 
3 from collections.abc import Coroutine
4 from datetime import timedelta
5 import logging
6 from typing import Any, cast
7 
8 from rabbitair import Client, State
9 
10 from homeassistant.core import HomeAssistant
11 from homeassistant.helpers.debounce import Debouncer
12 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
13 
14 _LOGGER = logging.getLogger(__name__)
15 
16 
17 class RabbitAirDebouncer(Debouncer[Coroutine[Any, Any, None]]):
18  """Class to rate limit calls to a specific command."""
19 
20  def __init__(
21  self,
22  hass: HomeAssistant,
23  ) -> None:
24  """Initialize debounce."""
25  # We don't want an immediate refresh since the device needs some time
26  # to apply the changes and reflect the updated state. Two seconds
27  # should be sufficient, since the internal cycle of the device runs at
28  # one-second intervals.
29  super().__init__(hass, _LOGGER, cooldown=2.0, immediate=False)
30 
31  async def async_call(self) -> None:
32  """Call the function."""
33  # Restart the timer.
34  self.async_cancelasync_cancel()
35  await super().async_call()
36 
37  def has_pending_call(self) -> bool:
38  """Indicate that the debouncer has a call waiting for cooldown."""
39  return self._execute_at_end_of_timer_execute_at_end_of_timer
40 
41 
43  """Class to manage fetching data from single endpoint."""
44 
45  def __init__(self, hass: HomeAssistant, device: Client) -> None:
46  """Initialize global data updater."""
47  self.devicedevice = device
48  super().__init__(
49  hass,
50  _LOGGER,
51  name="rabbitair",
52  update_interval=timedelta(seconds=10),
53  request_refresh_debouncer=RabbitAirDebouncer(hass),
54  )
55 
56  async def _async_update_data(self) -> State:
57  return await self.devicedevice.get_state()
58 
59  async def _async_refresh(
60  self,
61  log_failures: bool = True,
62  raise_on_auth_failed: bool = False,
63  scheduled: bool = False,
64  raise_on_entry_error: bool = False,
65  ) -> None:
66  """Refresh data."""
67 
68  # Skip a scheduled refresh if there is a pending requested refresh.
69  debouncer = cast(RabbitAirDebouncer, self._debounced_refresh_debounced_refresh)
70  if scheduled and debouncer.has_pending_call():
71  return
72 
73  await super()._async_refresh(
74  log_failures, raise_on_auth_failed, scheduled, raise_on_entry_error
75  )
None _async_refresh(self, bool log_failures=True, bool raise_on_auth_failed=False, bool scheduled=False, bool raise_on_entry_error=False)
Definition: coordinator.py:65
str|float get_state(dict[str, float] data, str key)
Definition: sensor.py:26