Home Assistant Unofficial Reference 2024.12.1
coordinator.py
Go to the documentation of this file.
1 """Provides the switchbot DataUpdateCoordinator."""
2 
3 from __future__ import annotations
4 
5 import asyncio
6 import contextlib
7 import logging
8 from typing import TYPE_CHECKING
9 
10 import switchbot
11 from switchbot import SwitchbotModel
12 
13 from homeassistant.components import bluetooth
15  ActiveBluetoothDataUpdateCoordinator,
16 )
17 from homeassistant.config_entries import ConfigEntry
18 from homeassistant.core import CoreState, HomeAssistant, callback
19 
20 if TYPE_CHECKING:
21  from bleak.backends.device import BLEDevice
22 
23 
24 _LOGGER = logging.getLogger(__name__)
25 
26 DEVICE_STARTUP_TIMEOUT = 30
27 
28 type SwitchbotConfigEntry = ConfigEntry[SwitchbotDataUpdateCoordinator]
29 
30 
32  """Class to manage fetching switchbot data."""
33 
34  def __init__(
35  self,
36  hass: HomeAssistant,
37  logger: logging.Logger,
38  ble_device: BLEDevice,
39  device: switchbot.SwitchbotDevice,
40  base_unique_id: str,
41  device_name: str,
42  connectable: bool,
43  model: SwitchbotModel,
44  ) -> None:
45  """Initialize global switchbot data updater."""
46  super().__init__(
47  hass=hass,
48  logger=logger,
49  address=ble_device.address,
50  needs_poll_method=self._needs_poll_needs_poll,
51  poll_method=self._async_update_async_update,
52  mode=bluetooth.BluetoothScanningMode.ACTIVE,
53  connectable=connectable,
54  )
55  self.ble_deviceble_device = ble_device
56  self.devicedevice = device
57  self.device_namedevice_name = device_name
58  self.base_unique_idbase_unique_id = base_unique_id
59  self.modelmodel = model
60  self._ready_event_ready_event = asyncio.Event()
61  self._was_unavailable_was_unavailable = True
62 
63  @callback
65  self,
66  service_info: bluetooth.BluetoothServiceInfoBleak,
67  seconds_since_last_poll: float | None,
68  ) -> bool:
69  # Only poll if hass is running, we need to poll,
70  # and we actually have a way to connect to the device
71  return (
72  self.hasshass.state is CoreState.running
73  and self.devicedevice.poll_needed(seconds_since_last_poll)
74  and bool(
75  bluetooth.async_ble_device_from_address(
76  self.hasshass, service_info.device.address, connectable=True
77  )
78  )
79  )
80 
81  async def _async_update(
82  self, service_info: bluetooth.BluetoothServiceInfoBleak
83  ) -> None:
84  """Poll the device."""
85  await self.devicedevice.update()
86 
87  @callback
89  self, service_info: bluetooth.BluetoothServiceInfoBleak
90  ) -> None:
91  """Handle the device going unavailable."""
92  super()._async_handle_unavailable(service_info)
93  self._was_unavailable_was_unavailable = True
94 
95  @callback
97  self,
98  service_info: bluetooth.BluetoothServiceInfoBleak,
99  change: bluetooth.BluetoothChange,
100  ) -> None:
101  """Handle a Bluetooth event."""
102  self.ble_deviceble_device = service_info.device
103  if not (
104  adv := switchbot.parse_advertisement_data(
105  service_info.device, service_info.advertisement, self.modelmodel
106  )
107  ):
108  return
109  if "modelName" in adv.data:
110  self._ready_event_ready_event.set()
111  _LOGGER.debug(
112  "%s: Switchbot data: %s", self.ble_deviceble_device.address, self.devicedevice.data
113  )
114  if not self.devicedevice.advertisement_changed(adv) and not self._was_unavailable_was_unavailable:
115  return
116  self._was_unavailable_was_unavailable = False
117  self.devicedevice.update_from_advertisement(adv)
118  super()._async_handle_bluetooth_event(service_info, change)
119 
120  async def async_wait_ready(self) -> bool:
121  """Wait for the device to be ready."""
122  with contextlib.suppress(TimeoutError):
123  async with asyncio.timeout(DEVICE_STARTUP_TIMEOUT):
124  await self._ready_event_ready_event.wait()
125  return True
126  return False
bool _needs_poll(self, bluetooth.BluetoothServiceInfoBleak service_info, float|None seconds_since_last_poll)
Definition: coordinator.py:68
None _async_handle_bluetooth_event(self, bluetooth.BluetoothServiceInfoBleak service_info, bluetooth.BluetoothChange change)
Definition: coordinator.py:100
None __init__(self, HomeAssistant hass, logging.Logger logger, BLEDevice ble_device, switchbot.SwitchbotDevice device, str base_unique_id, str device_name, bool connectable, SwitchbotModel model)
Definition: coordinator.py:44
None _async_update(self, bluetooth.BluetoothServiceInfoBleak service_info)
Definition: coordinator.py:83
None _async_handle_unavailable(self, bluetooth.BluetoothServiceInfoBleak service_info)
Definition: coordinator.py:90
IssData update(pyiss.ISS iss)
Definition: __init__.py:33