Home Assistant Unofficial Reference 2024.12.1
passive_update_coordinator.py
Go to the documentation of this file.
1 """Passive update coordinator for the Bluetooth integration."""
2 
3 from __future__ import annotations
4 
5 from typing import TYPE_CHECKING, Any
6 
7 from typing_extensions import TypeVar
8 
9 from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
11  BaseCoordinatorEntity,
12  BaseDataUpdateCoordinatorProtocol,
13 )
14 
15 from .update_coordinator import BasePassiveBluetoothCoordinator
16 
17 if TYPE_CHECKING:
18  from collections.abc import Callable, Generator
19  import logging
20 
21  from . import BluetoothChange, BluetoothScanningMode, BluetoothServiceInfoBleak
22 
23 _PassiveBluetoothDataUpdateCoordinatorT = TypeVar(
24  "_PassiveBluetoothDataUpdateCoordinatorT",
25  bound="PassiveBluetoothDataUpdateCoordinator",
26  default="PassiveBluetoothDataUpdateCoordinator",
27 )
28 
29 
31  BasePassiveBluetoothCoordinator, BaseDataUpdateCoordinatorProtocol
32 ):
33  """Class to manage passive bluetooth advertisements.
34 
35  This coordinator is responsible for dispatching the bluetooth data
36  and tracking devices.
37  """
38 
39  def __init__(
40  self,
41  hass: HomeAssistant,
42  logger: logging.Logger,
43  address: str,
44  mode: BluetoothScanningMode,
45  connectable: bool = False,
46  ) -> None:
47  """Initialize PassiveBluetoothDataUpdateCoordinator."""
48  super().__init__(hass, logger, address, mode, connectable)
49  self._listeners: dict[CALLBACK_TYPE, tuple[CALLBACK_TYPE, object | None]] = {}
50 
51  @property
52  def available(self) -> bool:
53  """Return if device is available."""
54  return self._available_available_available
55 
56  @callback
57  def async_update_listeners(self) -> None:
58  """Update all registered listeners."""
59  for update_callback, _ in list(self._listeners.values()):
60  update_callback()
61 
62  @callback
64  self, service_info: BluetoothServiceInfoBleak
65  ) -> None:
66  """Handle the device going unavailable."""
67  super()._async_handle_unavailable(service_info)
68  self.async_update_listenersasync_update_listeners()
69 
70  @callback
72  self, update_callback: CALLBACK_TYPE, context: Any = None
73  ) -> Callable[[], None]:
74  """Listen for data updates."""
75 
76  @callback
77  def remove_listener() -> None:
78  """Remove update listener."""
79  self._listeners.pop(remove_listener)
80 
81  self._listeners[remove_listener] = (update_callback, context)
82  return remove_listener
83 
84  def async_contexts(self) -> Generator[Any]:
85  """Return all registered contexts."""
86  yield from (
87  context for _, context in self._listeners.values() if context is not None
88  )
89 
90  @callback
92  self,
93  service_info: BluetoothServiceInfoBleak,
94  change: BluetoothChange,
95  ) -> None:
96  """Handle a Bluetooth event."""
97  self._available_available_available = True
98  self.async_update_listenersasync_update_listeners()
99 
100 
101 class PassiveBluetoothCoordinatorEntity( # pylint: disable=hass-enforce-class-module
102  BaseCoordinatorEntity[_PassiveBluetoothDataUpdateCoordinatorT]
103 ):
104  """A class for entities using DataUpdateCoordinator."""
105 
106  async def async_update(self) -> None:
107  """All updates are passive."""
108 
109  @property
110  def available(self) -> bool:
111  """Return if entity is available."""
112  return self.coordinator.available
Callable[[], None] async_add_listener(self, CALLBACK_TYPE update_callback, Any context=None)
None __init__(self, HomeAssistant hass, logging.Logger logger, str address, BluetoothScanningMode mode, bool connectable=False)
None _async_handle_bluetooth_event(self, BluetoothServiceInfoBleak service_info, BluetoothChange change)