mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Refactor all Bluetooth scanners to inherit from BaseHaRemoteScanner (#105523)
This commit is contained in:
parent
5bd0833f49
commit
f002a6a732
@ -23,6 +23,7 @@ from bluetooth_adapters import (
|
|||||||
)
|
)
|
||||||
from bluetooth_data_tools import monotonic_time_coarse as MONOTONIC_TIME
|
from bluetooth_data_tools import monotonic_time_coarse as MONOTONIC_TIME
|
||||||
from habluetooth import (
|
from habluetooth import (
|
||||||
|
BaseHaRemoteScanner,
|
||||||
BaseHaScanner,
|
BaseHaScanner,
|
||||||
BluetoothScannerDevice,
|
BluetoothScannerDevice,
|
||||||
BluetoothScanningMode,
|
BluetoothScanningMode,
|
||||||
@ -69,7 +70,6 @@ from .api import (
|
|||||||
async_set_fallback_availability_interval,
|
async_set_fallback_availability_interval,
|
||||||
async_track_unavailable,
|
async_track_unavailable,
|
||||||
)
|
)
|
||||||
from .base_scanner import HomeAssistantRemoteScanner
|
|
||||||
from .const import (
|
from .const import (
|
||||||
BLUETOOTH_DISCOVERY_COOLDOWN_SECONDS,
|
BLUETOOTH_DISCOVERY_COOLDOWN_SECONDS,
|
||||||
CONF_ADAPTER,
|
CONF_ADAPTER,
|
||||||
@ -116,6 +116,7 @@ __all__ = [
|
|||||||
"BluetoothCallback",
|
"BluetoothCallback",
|
||||||
"BluetoothScannerDevice",
|
"BluetoothScannerDevice",
|
||||||
"HaBluetoothConnector",
|
"HaBluetoothConnector",
|
||||||
|
"BaseHaRemoteScanner",
|
||||||
"SOURCE_LOCAL",
|
"SOURCE_LOCAL",
|
||||||
"FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS",
|
"FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS",
|
||||||
"MONOTONIC_TIME",
|
"MONOTONIC_TIME",
|
||||||
|
@ -1,95 +0,0 @@
|
|||||||
"""Base classes for HA Bluetooth scanners for bluetooth."""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from collections.abc import Callable
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from bluetooth_adapters import DiscoveredDeviceAdvertisementData
|
|
||||||
from habluetooth import BaseHaRemoteScanner, HaBluetoothConnector
|
|
||||||
from home_assistant_bluetooth import BluetoothServiceInfoBleak
|
|
||||||
|
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
|
||||||
from homeassistant.core import (
|
|
||||||
CALLBACK_TYPE,
|
|
||||||
Event,
|
|
||||||
HomeAssistant,
|
|
||||||
callback as hass_callback,
|
|
||||||
)
|
|
||||||
|
|
||||||
from . import models
|
|
||||||
|
|
||||||
|
|
||||||
class HomeAssistantRemoteScanner(BaseHaRemoteScanner):
|
|
||||||
"""Home Assistant remote BLE scanner.
|
|
||||||
|
|
||||||
This is the only object that should know about
|
|
||||||
the hass object.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__slots__ = (
|
|
||||||
"hass",
|
|
||||||
"_storage",
|
|
||||||
"_cancel_stop",
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
hass: HomeAssistant,
|
|
||||||
scanner_id: str,
|
|
||||||
name: str,
|
|
||||||
new_info_callback: Callable[[BluetoothServiceInfoBleak], None],
|
|
||||||
connector: HaBluetoothConnector | None,
|
|
||||||
connectable: bool,
|
|
||||||
) -> None:
|
|
||||||
"""Initialize the scanner."""
|
|
||||||
self.hass = hass
|
|
||||||
assert models.MANAGER is not None
|
|
||||||
self._storage = models.MANAGER.storage
|
|
||||||
self._cancel_stop: CALLBACK_TYPE | None = None
|
|
||||||
super().__init__(scanner_id, name, new_info_callback, connector, connectable)
|
|
||||||
|
|
||||||
@hass_callback
|
|
||||||
def async_setup(self) -> CALLBACK_TYPE:
|
|
||||||
"""Set up the scanner."""
|
|
||||||
super().async_setup()
|
|
||||||
if history := self._storage.async_get_advertisement_history(self.source):
|
|
||||||
self._discovered_device_advertisement_datas = (
|
|
||||||
history.discovered_device_advertisement_datas
|
|
||||||
)
|
|
||||||
self._discovered_device_timestamps = history.discovered_device_timestamps
|
|
||||||
# Expire anything that is too old
|
|
||||||
self._async_expire_devices()
|
|
||||||
|
|
||||||
self._cancel_stop = self.hass.bus.async_listen(
|
|
||||||
EVENT_HOMEASSISTANT_STOP, self._async_save_history
|
|
||||||
)
|
|
||||||
return self._unsetup
|
|
||||||
|
|
||||||
@hass_callback
|
|
||||||
def _unsetup(self) -> None:
|
|
||||||
super()._unsetup()
|
|
||||||
self._async_save_history()
|
|
||||||
if self._cancel_stop:
|
|
||||||
self._cancel_stop()
|
|
||||||
self._cancel_stop = None
|
|
||||||
|
|
||||||
@hass_callback
|
|
||||||
def _async_save_history(self, event: Event | None = None) -> None:
|
|
||||||
"""Save the history."""
|
|
||||||
self._storage.async_set_advertisement_history(
|
|
||||||
self.source,
|
|
||||||
DiscoveredDeviceAdvertisementData(
|
|
||||||
self.connectable,
|
|
||||||
self._expire_seconds,
|
|
||||||
self._discovered_device_advertisement_datas,
|
|
||||||
self._discovered_device_timestamps,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
async def async_diagnostics(self) -> dict[str, Any]:
|
|
||||||
"""Return diagnostic information about the scanner."""
|
|
||||||
diag = await super().async_diagnostics()
|
|
||||||
diag["storage"] = self._storage.async_get_advertisement_history_as_dict(
|
|
||||||
self.source
|
|
||||||
)
|
|
||||||
return diag
|
|
@ -2,12 +2,13 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Callable, Iterable
|
from collections.abc import Callable, Iterable
|
||||||
|
from functools import partial
|
||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from bleak_retry_connector import BleakSlotManager
|
from bleak_retry_connector import BleakSlotManager
|
||||||
from bluetooth_adapters import BluetoothAdapters
|
from bluetooth_adapters import BluetoothAdapters
|
||||||
from habluetooth import BluetoothManager
|
from habluetooth import BaseHaRemoteScanner, BaseHaScanner, BluetoothManager
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.const import EVENT_LOGGING_CHANGED
|
from homeassistant.const import EVENT_LOGGING_CHANGED
|
||||||
@ -189,7 +190,45 @@ class HomeAssistantBluetoothManager(BluetoothManager):
|
|||||||
def async_stop(self) -> None:
|
def async_stop(self) -> None:
|
||||||
"""Stop the Bluetooth integration at shutdown."""
|
"""Stop the Bluetooth integration at shutdown."""
|
||||||
_LOGGER.debug("Stopping bluetooth manager")
|
_LOGGER.debug("Stopping bluetooth manager")
|
||||||
|
self._async_save_scanner_histories()
|
||||||
super().async_stop()
|
super().async_stop()
|
||||||
if self._cancel_logging_listener:
|
if self._cancel_logging_listener:
|
||||||
self._cancel_logging_listener()
|
self._cancel_logging_listener()
|
||||||
self._cancel_logging_listener = None
|
self._cancel_logging_listener = None
|
||||||
|
|
||||||
|
def _async_save_scanner_histories(self) -> None:
|
||||||
|
"""Save the scanner histories."""
|
||||||
|
for scanner in itertools.chain(
|
||||||
|
self._connectable_scanners, self._non_connectable_scanners
|
||||||
|
):
|
||||||
|
self._async_save_scanner_history(scanner)
|
||||||
|
|
||||||
|
def _async_save_scanner_history(self, scanner: BaseHaScanner) -> None:
|
||||||
|
"""Save the scanner history."""
|
||||||
|
if isinstance(scanner, BaseHaRemoteScanner):
|
||||||
|
self.storage.async_set_advertisement_history(
|
||||||
|
scanner.source, scanner.serialize_discovered_devices()
|
||||||
|
)
|
||||||
|
|
||||||
|
def _async_unregister_scanner(
|
||||||
|
self, scanner: BaseHaScanner, unregister: CALLBACK_TYPE
|
||||||
|
) -> None:
|
||||||
|
"""Unregister a scanner."""
|
||||||
|
unregister()
|
||||||
|
self._async_save_scanner_history(scanner)
|
||||||
|
|
||||||
|
def async_register_scanner(
|
||||||
|
self,
|
||||||
|
scanner: BaseHaScanner,
|
||||||
|
connectable: bool,
|
||||||
|
connection_slots: int | None = None,
|
||||||
|
) -> CALLBACK_TYPE:
|
||||||
|
"""Register a scanner."""
|
||||||
|
if isinstance(scanner, BaseHaRemoteScanner):
|
||||||
|
if history := self.storage.async_get_advertisement_history(scanner.source):
|
||||||
|
scanner.restore_discovered_devices(history)
|
||||||
|
|
||||||
|
unregister = super().async_register_scanner(
|
||||||
|
scanner, connectable, connection_slots
|
||||||
|
)
|
||||||
|
return partial(self._async_unregister_scanner, scanner, unregister)
|
||||||
|
@ -99,7 +99,7 @@ async def async_connect_scanner(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
scanner = ESPHomeScanner(
|
scanner = ESPHomeScanner(
|
||||||
hass, source, entry.title, new_info_callback, connector, connectable
|
source, entry.title, new_info_callback, connector, connectable
|
||||||
)
|
)
|
||||||
client_data.scanner = scanner
|
client_data.scanner = scanner
|
||||||
coros: list[Coroutine[Any, Any, CALLBACK_TYPE]] = []
|
coros: list[Coroutine[Any, Any, CALLBACK_TYPE]] = []
|
||||||
|
@ -7,14 +7,11 @@ from bluetooth_data_tools import (
|
|||||||
parse_advertisement_data_tuple,
|
parse_advertisement_data_tuple,
|
||||||
)
|
)
|
||||||
|
|
||||||
from homeassistant.components.bluetooth import (
|
from homeassistant.components.bluetooth import MONOTONIC_TIME, BaseHaRemoteScanner
|
||||||
MONOTONIC_TIME,
|
|
||||||
HomeAssistantRemoteScanner,
|
|
||||||
)
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
|
||||||
|
|
||||||
class ESPHomeScanner(HomeAssistantRemoteScanner):
|
class ESPHomeScanner(BaseHaRemoteScanner):
|
||||||
"""Scanner for esphome."""
|
"""Scanner for esphome."""
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
@ -10,7 +10,7 @@ from home_assistant_bluetooth import BluetoothServiceInfoBleak
|
|||||||
from homeassistant.components.bluetooth import (
|
from homeassistant.components.bluetooth import (
|
||||||
FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS,
|
FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS,
|
||||||
MONOTONIC_TIME,
|
MONOTONIC_TIME,
|
||||||
HomeAssistantRemoteScanner,
|
BaseHaRemoteScanner,
|
||||||
async_get_advertisement_callback,
|
async_get_advertisement_callback,
|
||||||
async_register_scanner,
|
async_register_scanner,
|
||||||
)
|
)
|
||||||
@ -22,12 +22,11 @@ from .coordinator import RuuviGatewayUpdateCoordinator
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class RuuviGatewayScanner(HomeAssistantRemoteScanner):
|
class RuuviGatewayScanner(BaseHaRemoteScanner):
|
||||||
"""Scanner for Ruuvi Gateway."""
|
"""Scanner for Ruuvi Gateway."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
hass: HomeAssistant,
|
|
||||||
scanner_id: str,
|
scanner_id: str,
|
||||||
name: str,
|
name: str,
|
||||||
new_info_callback: Callable[[BluetoothServiceInfoBleak], None],
|
new_info_callback: Callable[[BluetoothServiceInfoBleak], None],
|
||||||
@ -36,7 +35,6 @@ class RuuviGatewayScanner(HomeAssistantRemoteScanner):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the scanner, using the given update coordinator as data source."""
|
"""Initialize the scanner, using the given update coordinator as data source."""
|
||||||
super().__init__(
|
super().__init__(
|
||||||
hass,
|
|
||||||
scanner_id,
|
scanner_id,
|
||||||
name,
|
name,
|
||||||
new_info_callback,
|
new_info_callback,
|
||||||
@ -87,7 +85,6 @@ def async_connect_scanner(
|
|||||||
source,
|
source,
|
||||||
)
|
)
|
||||||
scanner = RuuviGatewayScanner(
|
scanner = RuuviGatewayScanner(
|
||||||
hass=hass,
|
|
||||||
scanner_id=source,
|
scanner_id=source,
|
||||||
name=entry.title,
|
name=entry.title,
|
||||||
new_info_callback=async_get_advertisement_callback(hass),
|
new_info_callback=async_get_advertisement_callback(hass),
|
||||||
|
@ -43,9 +43,7 @@ async def async_connect_scanner(
|
|||||||
source=source,
|
source=source,
|
||||||
can_connect=lambda: False,
|
can_connect=lambda: False,
|
||||||
)
|
)
|
||||||
scanner = ShellyBLEScanner(
|
scanner = ShellyBLEScanner(source, entry.title, new_info_callback, connector, False)
|
||||||
hass, source, entry.title, new_info_callback, connector, False
|
|
||||||
)
|
|
||||||
unload_callbacks = [
|
unload_callbacks = [
|
||||||
async_register_scanner(hass, scanner, False),
|
async_register_scanner(hass, scanner, False),
|
||||||
scanner.async_setup(),
|
scanner.async_setup(),
|
||||||
|
@ -6,16 +6,13 @@ from typing import Any
|
|||||||
from aioshelly.ble import parse_ble_scan_result_event
|
from aioshelly.ble import parse_ble_scan_result_event
|
||||||
from aioshelly.ble.const import BLE_SCAN_RESULT_EVENT, BLE_SCAN_RESULT_VERSION
|
from aioshelly.ble.const import BLE_SCAN_RESULT_EVENT, BLE_SCAN_RESULT_VERSION
|
||||||
|
|
||||||
from homeassistant.components.bluetooth import (
|
from homeassistant.components.bluetooth import MONOTONIC_TIME, BaseHaRemoteScanner
|
||||||
MONOTONIC_TIME,
|
|
||||||
HomeAssistantRemoteScanner,
|
|
||||||
)
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
|
||||||
from ..const import LOGGER
|
from ..const import LOGGER
|
||||||
|
|
||||||
|
|
||||||
class ShellyBLEScanner(HomeAssistantRemoteScanner):
|
class ShellyBLEScanner(BaseHaRemoteScanner):
|
||||||
"""Scanner for shelly."""
|
"""Scanner for shelly."""
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -7,9 +7,9 @@ import pytest
|
|||||||
from homeassistant.components import bluetooth
|
from homeassistant.components import bluetooth
|
||||||
from homeassistant.components.bluetooth import (
|
from homeassistant.components.bluetooth import (
|
||||||
MONOTONIC_TIME,
|
MONOTONIC_TIME,
|
||||||
|
BaseHaRemoteScanner,
|
||||||
BaseHaScanner,
|
BaseHaScanner,
|
||||||
HaBluetoothConnector,
|
HaBluetoothConnector,
|
||||||
HomeAssistantRemoteScanner,
|
|
||||||
async_scanner_by_source,
|
async_scanner_by_source,
|
||||||
async_scanner_devices_by_address,
|
async_scanner_devices_by_address,
|
||||||
)
|
)
|
||||||
@ -46,7 +46,7 @@ async def test_async_scanner_devices_by_address_connectable(
|
|||||||
"""Test getting scanner devices by address with connectable devices."""
|
"""Test getting scanner devices by address with connectable devices."""
|
||||||
manager = _get_manager()
|
manager = _get_manager()
|
||||||
|
|
||||||
class FakeInjectableScanner(HomeAssistantRemoteScanner):
|
class FakeInjectableScanner(BaseHaRemoteScanner):
|
||||||
def inject_advertisement(
|
def inject_advertisement(
|
||||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -68,7 +68,7 @@ async def test_async_scanner_devices_by_address_connectable(
|
|||||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||||
)
|
)
|
||||||
scanner = FakeInjectableScanner(
|
scanner = FakeInjectableScanner(
|
||||||
hass, "esp32", "esp32", new_info_callback, connector, False
|
"esp32", "esp32", new_info_callback, connector, False
|
||||||
)
|
)
|
||||||
unsetup = scanner.async_setup()
|
unsetup = scanner.async_setup()
|
||||||
cancel = manager.async_register_scanner(scanner, True)
|
cancel = manager.async_register_scanner(scanner, True)
|
||||||
|
@ -14,8 +14,8 @@ import pytest
|
|||||||
from homeassistant.components import bluetooth
|
from homeassistant.components import bluetooth
|
||||||
from homeassistant.components.bluetooth import (
|
from homeassistant.components.bluetooth import (
|
||||||
MONOTONIC_TIME,
|
MONOTONIC_TIME,
|
||||||
|
BaseHaRemoteScanner,
|
||||||
HaBluetoothConnector,
|
HaBluetoothConnector,
|
||||||
HomeAssistantRemoteScanner,
|
|
||||||
storage,
|
storage,
|
||||||
)
|
)
|
||||||
from homeassistant.components.bluetooth.const import (
|
from homeassistant.components.bluetooth.const import (
|
||||||
@ -41,7 +41,7 @@ from . import (
|
|||||||
from tests.common import async_fire_time_changed, load_fixture
|
from tests.common import async_fire_time_changed, load_fixture
|
||||||
|
|
||||||
|
|
||||||
class FakeScanner(HomeAssistantRemoteScanner):
|
class FakeScanner(BaseHaRemoteScanner):
|
||||||
"""Fake scanner."""
|
"""Fake scanner."""
|
||||||
|
|
||||||
def inject_advertisement(
|
def inject_advertisement(
|
||||||
@ -115,7 +115,7 @@ async def test_remote_scanner(
|
|||||||
connector = (
|
connector = (
|
||||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||||
)
|
)
|
||||||
scanner = FakeScanner(hass, "esp32", "esp32", new_info_callback, connector, True)
|
scanner = FakeScanner("esp32", "esp32", new_info_callback, connector, True)
|
||||||
unsetup = scanner.async_setup()
|
unsetup = scanner.async_setup()
|
||||||
cancel = manager.async_register_scanner(scanner, True)
|
cancel = manager.async_register_scanner(scanner, True)
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ async def test_remote_scanner_expires_connectable(
|
|||||||
connector = (
|
connector = (
|
||||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||||
)
|
)
|
||||||
scanner = FakeScanner(hass, "esp32", "esp32", new_info_callback, connector, True)
|
scanner = FakeScanner("esp32", "esp32", new_info_callback, connector, True)
|
||||||
unsetup = scanner.async_setup()
|
unsetup = scanner.async_setup()
|
||||||
cancel = manager.async_register_scanner(scanner, True)
|
cancel = manager.async_register_scanner(scanner, True)
|
||||||
|
|
||||||
@ -237,7 +237,7 @@ async def test_remote_scanner_expires_non_connectable(
|
|||||||
connector = (
|
connector = (
|
||||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||||
)
|
)
|
||||||
scanner = FakeScanner(hass, "esp32", "esp32", new_info_callback, connector, False)
|
scanner = FakeScanner("esp32", "esp32", new_info_callback, connector, False)
|
||||||
unsetup = scanner.async_setup()
|
unsetup = scanner.async_setup()
|
||||||
cancel = manager.async_register_scanner(scanner, True)
|
cancel = manager.async_register_scanner(scanner, True)
|
||||||
|
|
||||||
@ -312,7 +312,7 @@ async def test_base_scanner_connecting_behavior(
|
|||||||
connector = (
|
connector = (
|
||||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||||
)
|
)
|
||||||
scanner = FakeScanner(hass, "esp32", "esp32", new_info_callback, connector, False)
|
scanner = FakeScanner("esp32", "esp32", new_info_callback, connector, False)
|
||||||
unsetup = scanner.async_setup()
|
unsetup = scanner.async_setup()
|
||||||
cancel = manager.async_register_scanner(scanner, True)
|
cancel = manager.async_register_scanner(scanner, True)
|
||||||
|
|
||||||
@ -363,8 +363,7 @@ async def test_restore_history_remote_adapter(
|
|||||||
connector = (
|
connector = (
|
||||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||||
)
|
)
|
||||||
scanner = HomeAssistantRemoteScanner(
|
scanner = BaseHaRemoteScanner(
|
||||||
hass,
|
|
||||||
"atom-bluetooth-proxy-ceaac4",
|
"atom-bluetooth-proxy-ceaac4",
|
||||||
"atom-bluetooth-proxy-ceaac4",
|
"atom-bluetooth-proxy-ceaac4",
|
||||||
lambda adv: None,
|
lambda adv: None,
|
||||||
@ -379,8 +378,7 @@ async def test_restore_history_remote_adapter(
|
|||||||
cancel()
|
cancel()
|
||||||
unsetup()
|
unsetup()
|
||||||
|
|
||||||
scanner = HomeAssistantRemoteScanner(
|
scanner = BaseHaRemoteScanner(
|
||||||
hass,
|
|
||||||
"atom-bluetooth-proxy-ceaac4",
|
"atom-bluetooth-proxy-ceaac4",
|
||||||
"atom-bluetooth-proxy-ceaac4",
|
"atom-bluetooth-proxy-ceaac4",
|
||||||
lambda adv: None,
|
lambda adv: None,
|
||||||
@ -419,7 +417,7 @@ async def test_device_with_ten_minute_advertising_interval(
|
|||||||
connector = (
|
connector = (
|
||||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||||
)
|
)
|
||||||
scanner = FakeScanner(hass, "esp32", "esp32", new_info_callback, connector, False)
|
scanner = FakeScanner("esp32", "esp32", new_info_callback, connector, False)
|
||||||
unsetup = scanner.async_setup()
|
unsetup = scanner.async_setup()
|
||||||
cancel = manager.async_register_scanner(scanner, True)
|
cancel = manager.async_register_scanner(scanner, True)
|
||||||
|
|
||||||
@ -511,7 +509,7 @@ async def test_scanner_stops_responding(
|
|||||||
connector = (
|
connector = (
|
||||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||||
)
|
)
|
||||||
scanner = FakeScanner(hass, "esp32", "esp32", new_info_callback, connector, False)
|
scanner = FakeScanner("esp32", "esp32", new_info_callback, connector, False)
|
||||||
unsetup = scanner.async_setup()
|
unsetup = scanner.async_setup()
|
||||||
cancel = manager.async_register_scanner(scanner, True)
|
cancel = manager.async_register_scanner(scanner, True)
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ from habluetooth import HaScanner
|
|||||||
from homeassistant.components import bluetooth
|
from homeassistant.components import bluetooth
|
||||||
from homeassistant.components.bluetooth import (
|
from homeassistant.components.bluetooth import (
|
||||||
MONOTONIC_TIME,
|
MONOTONIC_TIME,
|
||||||
|
BaseHaRemoteScanner,
|
||||||
HaBluetoothConnector,
|
HaBluetoothConnector,
|
||||||
HomeAssistantRemoteScanner,
|
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
@ -423,7 +423,7 @@ async def test_diagnostics_remote_adapter(
|
|||||||
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}
|
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}
|
||||||
)
|
)
|
||||||
|
|
||||||
class FakeScanner(HomeAssistantRemoteScanner):
|
class FakeScanner(BaseHaRemoteScanner):
|
||||||
def inject_advertisement(
|
def inject_advertisement(
|
||||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -458,9 +458,7 @@ async def test_diagnostics_remote_adapter(
|
|||||||
connector = (
|
connector = (
|
||||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||||
)
|
)
|
||||||
scanner = FakeScanner(
|
scanner = FakeScanner("esp32", "esp32", new_info_callback, connector, False)
|
||||||
hass, "esp32", "esp32", new_info_callback, connector, False
|
|
||||||
)
|
|
||||||
unsetup = scanner.async_setup()
|
unsetup = scanner.async_setup()
|
||||||
cancel = manager.async_register_scanner(scanner, True)
|
cancel = manager.async_register_scanner(scanner, True)
|
||||||
|
|
||||||
@ -631,7 +629,6 @@ async def test_diagnostics_remote_adapter(
|
|||||||
"scanning": True,
|
"scanning": True,
|
||||||
"source": "esp32",
|
"source": "esp32",
|
||||||
"start_time": ANY,
|
"start_time": ANY,
|
||||||
"storage": None,
|
|
||||||
"time_since_last_device_detection": {"44:44:33:11:23:45": ANY},
|
"time_since_last_device_detection": {"44:44:33:11:23:45": ANY},
|
||||||
"type": "FakeScanner",
|
"type": "FakeScanner",
|
||||||
},
|
},
|
||||||
|
@ -13,12 +13,12 @@ import pytest
|
|||||||
from homeassistant.components import bluetooth
|
from homeassistant.components import bluetooth
|
||||||
from homeassistant.components.bluetooth import (
|
from homeassistant.components.bluetooth import (
|
||||||
MONOTONIC_TIME,
|
MONOTONIC_TIME,
|
||||||
|
BaseHaRemoteScanner,
|
||||||
BluetoothChange,
|
BluetoothChange,
|
||||||
BluetoothScanningMode,
|
BluetoothScanningMode,
|
||||||
BluetoothServiceInfo,
|
BluetoothServiceInfo,
|
||||||
BluetoothServiceInfoBleak,
|
BluetoothServiceInfoBleak,
|
||||||
HaBluetoothConnector,
|
HaBluetoothConnector,
|
||||||
HomeAssistantRemoteScanner,
|
|
||||||
async_ble_device_from_address,
|
async_ble_device_from_address,
|
||||||
async_get_advertisement_callback,
|
async_get_advertisement_callback,
|
||||||
async_get_fallback_availability_interval,
|
async_get_fallback_availability_interval,
|
||||||
@ -703,7 +703,7 @@ async def test_goes_unavailable_connectable_only_and_recovers(
|
|||||||
BluetoothScanningMode.ACTIVE,
|
BluetoothScanningMode.ACTIVE,
|
||||||
)
|
)
|
||||||
|
|
||||||
class FakeScanner(HomeAssistantRemoteScanner):
|
class FakeScanner(BaseHaRemoteScanner):
|
||||||
def inject_advertisement(
|
def inject_advertisement(
|
||||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -725,7 +725,6 @@ async def test_goes_unavailable_connectable_only_and_recovers(
|
|||||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||||
)
|
)
|
||||||
connectable_scanner = FakeScanner(
|
connectable_scanner = FakeScanner(
|
||||||
hass,
|
|
||||||
"connectable",
|
"connectable",
|
||||||
"connectable",
|
"connectable",
|
||||||
new_info_callback,
|
new_info_callback,
|
||||||
@ -749,7 +748,6 @@ async def test_goes_unavailable_connectable_only_and_recovers(
|
|||||||
)
|
)
|
||||||
|
|
||||||
not_connectable_scanner = FakeScanner(
|
not_connectable_scanner = FakeScanner(
|
||||||
hass,
|
|
||||||
"not_connectable",
|
"not_connectable",
|
||||||
"not_connectable",
|
"not_connectable",
|
||||||
new_info_callback,
|
new_info_callback,
|
||||||
@ -800,7 +798,6 @@ async def test_goes_unavailable_connectable_only_and_recovers(
|
|||||||
cancel_unavailable()
|
cancel_unavailable()
|
||||||
|
|
||||||
connectable_scanner_2 = FakeScanner(
|
connectable_scanner_2 = FakeScanner(
|
||||||
hass,
|
|
||||||
"connectable",
|
"connectable",
|
||||||
"connectable",
|
"connectable",
|
||||||
new_info_callback,
|
new_info_callback,
|
||||||
@ -876,7 +873,7 @@ async def test_goes_unavailable_dismisses_discovery_and_makes_discoverable(
|
|||||||
BluetoothScanningMode.ACTIVE,
|
BluetoothScanningMode.ACTIVE,
|
||||||
)
|
)
|
||||||
|
|
||||||
class FakeScanner(HomeAssistantRemoteScanner):
|
class FakeScanner(BaseHaRemoteScanner):
|
||||||
def inject_advertisement(
|
def inject_advertisement(
|
||||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -904,7 +901,6 @@ async def test_goes_unavailable_dismisses_discovery_and_makes_discoverable(
|
|||||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||||
)
|
)
|
||||||
non_connectable_scanner = FakeScanner(
|
non_connectable_scanner = FakeScanner(
|
||||||
hass,
|
|
||||||
"connectable",
|
"connectable",
|
||||||
"connectable",
|
"connectable",
|
||||||
new_info_callback,
|
new_info_callback,
|
||||||
|
@ -11,9 +11,9 @@ from habluetooth.wrappers import HaBleakClientWrapper, HaBleakScannerWrapper
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.bluetooth import (
|
from homeassistant.components.bluetooth import (
|
||||||
|
BaseHaRemoteScanner,
|
||||||
BaseHaScanner,
|
BaseHaScanner,
|
||||||
HaBluetoothConnector,
|
HaBluetoothConnector,
|
||||||
HomeAssistantRemoteScanner,
|
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ async def test_wrapped_bleak_client_set_disconnected_callback_after_connected(
|
|||||||
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}, rssi=-100
|
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}, rssi=-100
|
||||||
)
|
)
|
||||||
|
|
||||||
class FakeScanner(HomeAssistantRemoteScanner):
|
class FakeScanner(BaseHaRemoteScanner):
|
||||||
@property
|
@property
|
||||||
def discovered_devices(self) -> list[BLEDevice]:
|
def discovered_devices(self) -> list[BLEDevice]:
|
||||||
"""Return a list of discovered devices."""
|
"""Return a list of discovered devices."""
|
||||||
@ -182,7 +182,6 @@ async def test_wrapped_bleak_client_set_disconnected_callback_after_connected(
|
|||||||
MockBleakClient, "esp32_has_connection_slot", lambda: True
|
MockBleakClient, "esp32_has_connection_slot", lambda: True
|
||||||
)
|
)
|
||||||
scanner = FakeScanner(
|
scanner = FakeScanner(
|
||||||
hass,
|
|
||||||
"esp32_has_connection_slot",
|
"esp32_has_connection_slot",
|
||||||
"esp32_has_connection_slot",
|
"esp32_has_connection_slot",
|
||||||
lambda info: None,
|
lambda info: None,
|
||||||
@ -267,7 +266,7 @@ async def test_ble_device_with_proxy_client_out_of_connections(
|
|||||||
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}
|
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}
|
||||||
)
|
)
|
||||||
|
|
||||||
class FakeScanner(HomeAssistantRemoteScanner):
|
class FakeScanner(BaseHaRemoteScanner):
|
||||||
@property
|
@property
|
||||||
def discovered_devices(self) -> list[BLEDevice]:
|
def discovered_devices(self) -> list[BLEDevice]:
|
||||||
"""Return a list of discovered devices."""
|
"""Return a list of discovered devices."""
|
||||||
@ -292,7 +291,7 @@ async def test_ble_device_with_proxy_client_out_of_connections(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
connector = HaBluetoothConnector(MockBleakClient, "esp32", lambda: False)
|
connector = HaBluetoothConnector(MockBleakClient, "esp32", lambda: False)
|
||||||
scanner = FakeScanner(hass, "esp32", "esp32", lambda info: None, connector, True)
|
scanner = FakeScanner("esp32", "esp32", lambda info: None, connector, True)
|
||||||
cancel = manager.async_register_scanner(scanner, True)
|
cancel = manager.async_register_scanner(scanner, True)
|
||||||
inject_advertisement_with_source(
|
inject_advertisement_with_source(
|
||||||
hass, switchbot_proxy_device_no_connection_slot, switchbot_adv, "esp32"
|
hass, switchbot_proxy_device_no_connection_slot, switchbot_adv, "esp32"
|
||||||
@ -332,7 +331,7 @@ async def test_ble_device_with_proxy_clear_cache(
|
|||||||
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}
|
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}
|
||||||
)
|
)
|
||||||
|
|
||||||
class FakeScanner(HomeAssistantRemoteScanner):
|
class FakeScanner(BaseHaRemoteScanner):
|
||||||
@property
|
@property
|
||||||
def discovered_devices(self) -> list[BLEDevice]:
|
def discovered_devices(self) -> list[BLEDevice]:
|
||||||
"""Return a list of discovered devices."""
|
"""Return a list of discovered devices."""
|
||||||
@ -357,7 +356,7 @@ async def test_ble_device_with_proxy_clear_cache(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
connector = HaBluetoothConnector(MockBleakClient, "esp32", lambda: True)
|
connector = HaBluetoothConnector(MockBleakClient, "esp32", lambda: True)
|
||||||
scanner = FakeScanner(hass, "esp32", "esp32", lambda info: None, connector, True)
|
scanner = FakeScanner("esp32", "esp32", lambda info: None, connector, True)
|
||||||
cancel = manager.async_register_scanner(scanner, True)
|
cancel = manager.async_register_scanner(scanner, True)
|
||||||
inject_advertisement_with_source(
|
inject_advertisement_with_source(
|
||||||
hass, switchbot_proxy_device_with_connection_slot, switchbot_adv, "esp32"
|
hass, switchbot_proxy_device_with_connection_slot, switchbot_adv, "esp32"
|
||||||
@ -435,7 +434,7 @@ async def test_ble_device_with_proxy_client_out_of_connections_uses_best_availab
|
|||||||
"esp32_no_connection_slot",
|
"esp32_no_connection_slot",
|
||||||
)
|
)
|
||||||
|
|
||||||
class FakeScanner(HomeAssistantRemoteScanner):
|
class FakeScanner(BaseHaRemoteScanner):
|
||||||
@property
|
@property
|
||||||
def discovered_devices(self) -> list[BLEDevice]:
|
def discovered_devices(self) -> list[BLEDevice]:
|
||||||
"""Return a list of discovered devices."""
|
"""Return a list of discovered devices."""
|
||||||
@ -463,7 +462,6 @@ async def test_ble_device_with_proxy_client_out_of_connections_uses_best_availab
|
|||||||
MockBleakClient, "esp32_has_connection_slot", lambda: True
|
MockBleakClient, "esp32_has_connection_slot", lambda: True
|
||||||
)
|
)
|
||||||
scanner = FakeScanner(
|
scanner = FakeScanner(
|
||||||
hass,
|
|
||||||
"esp32_has_connection_slot",
|
"esp32_has_connection_slot",
|
||||||
"esp32_has_connection_slot",
|
"esp32_has_connection_slot",
|
||||||
lambda info: None,
|
lambda info: None,
|
||||||
@ -549,7 +547,7 @@ async def test_ble_device_with_proxy_client_out_of_connections_uses_best_availab
|
|||||||
"esp32_no_connection_slot",
|
"esp32_no_connection_slot",
|
||||||
)
|
)
|
||||||
|
|
||||||
class FakeScanner(HomeAssistantRemoteScanner):
|
class FakeScanner(BaseHaRemoteScanner):
|
||||||
@property
|
@property
|
||||||
def discovered_devices(self) -> list[BLEDevice]:
|
def discovered_devices(self) -> list[BLEDevice]:
|
||||||
"""Return a list of discovered devices."""
|
"""Return a list of discovered devices."""
|
||||||
@ -577,7 +575,6 @@ async def test_ble_device_with_proxy_client_out_of_connections_uses_best_availab
|
|||||||
MockBleakClient, "esp32_has_connection_slot", lambda: True
|
MockBleakClient, "esp32_has_connection_slot", lambda: True
|
||||||
)
|
)
|
||||||
scanner = FakeScanner(
|
scanner = FakeScanner(
|
||||||
hass,
|
|
||||||
"esp32_has_connection_slot",
|
"esp32_has_connection_slot",
|
||||||
"esp32_has_connection_slot",
|
"esp32_has_connection_slot",
|
||||||
lambda info: None,
|
lambda info: None,
|
||||||
|
@ -17,10 +17,10 @@ import pytest
|
|||||||
|
|
||||||
from homeassistant.components.bluetooth import (
|
from homeassistant.components.bluetooth import (
|
||||||
MONOTONIC_TIME,
|
MONOTONIC_TIME,
|
||||||
|
BaseHaRemoteScanner,
|
||||||
BluetoothServiceInfoBleak,
|
BluetoothServiceInfoBleak,
|
||||||
HaBluetoothConnector,
|
HaBluetoothConnector,
|
||||||
HomeAssistantBluetoothManager,
|
HomeAssistantBluetoothManager,
|
||||||
HomeAssistantRemoteScanner,
|
|
||||||
async_get_advertisement_callback,
|
async_get_advertisement_callback,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -36,12 +36,11 @@ def mock_shutdown(manager: HomeAssistantBluetoothManager) -> None:
|
|||||||
manager.shutdown = False
|
manager.shutdown = False
|
||||||
|
|
||||||
|
|
||||||
class FakeScanner(HomeAssistantRemoteScanner):
|
class FakeScanner(BaseHaRemoteScanner):
|
||||||
"""Fake scanner."""
|
"""Fake scanner."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
hass: HomeAssistant,
|
|
||||||
scanner_id: str,
|
scanner_id: str,
|
||||||
name: str,
|
name: str,
|
||||||
new_info_callback: Callable[[BluetoothServiceInfoBleak], None],
|
new_info_callback: Callable[[BluetoothServiceInfoBleak], None],
|
||||||
@ -49,9 +48,7 @@ class FakeScanner(HomeAssistantRemoteScanner):
|
|||||||
connectable: bool,
|
connectable: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the scanner."""
|
"""Initialize the scanner."""
|
||||||
super().__init__(
|
super().__init__(scanner_id, name, new_info_callback, connector, connectable)
|
||||||
hass, scanner_id, name, new_info_callback, connector, connectable
|
|
||||||
)
|
|
||||||
self._details: dict[str, str | HaBluetoothConnector] = {}
|
self._details: dict[str, str | HaBluetoothConnector] = {}
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
@ -187,10 +184,10 @@ def _generate_scanners_with_fake_devices(hass):
|
|||||||
|
|
||||||
new_info_callback = async_get_advertisement_callback(hass)
|
new_info_callback = async_get_advertisement_callback(hass)
|
||||||
scanner_hci0 = FakeScanner(
|
scanner_hci0 = FakeScanner(
|
||||||
hass, "00:00:00:00:00:01", "hci0", new_info_callback, None, True
|
"00:00:00:00:00:01", "hci0", new_info_callback, None, True
|
||||||
)
|
)
|
||||||
scanner_hci1 = FakeScanner(
|
scanner_hci1 = FakeScanner(
|
||||||
hass, "00:00:00:00:00:02", "hci1", new_info_callback, None, True
|
"00:00:00:00:00:02", "hci1", new_info_callback, None, True
|
||||||
)
|
)
|
||||||
|
|
||||||
for device, adv_data in hci0_device_advs.values():
|
for device, adv_data in hci0_device_advs.values():
|
||||||
|
@ -44,7 +44,7 @@ async def client_data_fixture(
|
|||||||
api_version=APIVersion(1, 9),
|
api_version=APIVersion(1, 9),
|
||||||
title=ESP_NAME,
|
title=ESP_NAME,
|
||||||
scanner=ESPHomeScanner(
|
scanner=ESPHomeScanner(
|
||||||
hass, ESP_MAC_ADDRESS, ESP_NAME, lambda info: None, connector, True
|
ESP_MAC_ADDRESS, ESP_NAME, lambda info: None, connector, True
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -130,7 +130,6 @@ async def test_rpc_config_entry_diagnostics(
|
|||||||
"scanning": True,
|
"scanning": True,
|
||||||
"start_time": ANY,
|
"start_time": ANY,
|
||||||
"source": "12:34:56:78:9A:BC",
|
"source": "12:34:56:78:9A:BC",
|
||||||
"storage": None,
|
|
||||||
"time_since_last_device_detection": {"AA:BB:CC:DD:EE:FF": ANY},
|
"time_since_last_device_detection": {"AA:BB:CC:DD:EE:FF": ANY},
|
||||||
"type": "ShellyBLEScanner",
|
"type": "ShellyBLEScanner",
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user