mirror of
https://github.com/home-assistant/core.git
synced 2025-07-09 22:37:11 +00:00
Refactor bluetooth scanners for better seperation of concerns (#104909)
This commit is contained in:
parent
7a9c3819e0
commit
dd9c22672a
@ -59,7 +59,11 @@ from .api import (
|
||||
async_set_fallback_availability_interval,
|
||||
async_track_unavailable,
|
||||
)
|
||||
from .base_scanner import BaseHaRemoteScanner, BaseHaScanner, BluetoothScannerDevice
|
||||
from .base_scanner import (
|
||||
BaseHaScanner,
|
||||
BluetoothScannerDevice,
|
||||
HomeAssistantRemoteScanner,
|
||||
)
|
||||
from .const import (
|
||||
BLUETOOTH_DISCOVERY_COOLDOWN_SECONDS,
|
||||
CONF_ADAPTER,
|
||||
@ -103,7 +107,7 @@ __all__ = [
|
||||
"async_scanner_count",
|
||||
"async_scanner_devices_by_address",
|
||||
"BaseHaScanner",
|
||||
"BaseHaRemoteScanner",
|
||||
"HomeAssistantRemoteScanner",
|
||||
"BluetoothCallbackMatcher",
|
||||
"BluetoothChange",
|
||||
"BluetoothServiceInfo",
|
||||
|
@ -1,14 +1,13 @@
|
||||
"""Base classes for HA Bluetooth scanners for bluetooth."""
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from abc import abstractmethod
|
||||
import asyncio
|
||||
from collections.abc import Callable, Generator
|
||||
from contextlib import contextmanager
|
||||
from dataclasses import dataclass
|
||||
import datetime
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Any, Final
|
||||
from typing import Any, Final, final
|
||||
|
||||
from bleak.backends.device import BLEDevice
|
||||
from bleak.backends.scanner import AdvertisementData
|
||||
@ -24,8 +23,6 @@ from homeassistant.core import (
|
||||
HomeAssistant,
|
||||
callback as hass_callback,
|
||||
)
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from . import models
|
||||
from .const import (
|
||||
@ -35,6 +32,7 @@ from .const import (
|
||||
)
|
||||
from .models import HaBluetoothConnector
|
||||
|
||||
SCANNER_WATCHDOG_INTERVAL_SECONDS: Final = SCANNER_WATCHDOG_INTERVAL.total_seconds()
|
||||
MONOTONIC_TIME: Final = monotonic_time_coarse
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -48,11 +46,10 @@ class BluetoothScannerDevice:
|
||||
advertisement: AdvertisementData
|
||||
|
||||
|
||||
class BaseHaScanner(ABC):
|
||||
"""Base class for Ha Scanners."""
|
||||
class BaseHaScanner:
|
||||
"""Base class for high availability BLE scanners."""
|
||||
|
||||
__slots__ = (
|
||||
"hass",
|
||||
"adapter",
|
||||
"connectable",
|
||||
"source",
|
||||
@ -63,17 +60,16 @@ class BaseHaScanner(ABC):
|
||||
"_last_detection",
|
||||
"_start_time",
|
||||
"_cancel_watchdog",
|
||||
"_loop",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
source: str,
|
||||
adapter: str,
|
||||
connector: HaBluetoothConnector | None = None,
|
||||
) -> None:
|
||||
"""Initialize the scanner."""
|
||||
self.hass = hass
|
||||
self.connectable = False
|
||||
self.source = source
|
||||
self.connector = connector
|
||||
@ -83,13 +79,20 @@ class BaseHaScanner(ABC):
|
||||
self.scanning = True
|
||||
self._last_detection = 0.0
|
||||
self._start_time = 0.0
|
||||
self._cancel_watchdog: CALLBACK_TYPE | None = None
|
||||
self._cancel_watchdog: asyncio.TimerHandle | None = None
|
||||
self._loop: asyncio.AbstractEventLoop | None = None
|
||||
|
||||
@hass_callback
|
||||
def async_setup(self) -> CALLBACK_TYPE:
|
||||
"""Set up the scanner."""
|
||||
self._loop = asyncio.get_running_loop()
|
||||
return self._unsetup
|
||||
|
||||
@hass_callback
|
||||
def _async_stop_scanner_watchdog(self) -> None:
|
||||
"""Stop the scanner watchdog."""
|
||||
if self._cancel_watchdog:
|
||||
self._cancel_watchdog()
|
||||
self._cancel_watchdog.cancel()
|
||||
self._cancel_watchdog = None
|
||||
|
||||
@hass_callback
|
||||
@ -97,12 +100,22 @@ class BaseHaScanner(ABC):
|
||||
"""If something has restarted or updated, we need to restart the scanner."""
|
||||
self._start_time = self._last_detection = MONOTONIC_TIME()
|
||||
if not self._cancel_watchdog:
|
||||
self._cancel_watchdog = async_track_time_interval(
|
||||
self.hass,
|
||||
self._async_scanner_watchdog,
|
||||
SCANNER_WATCHDOG_INTERVAL,
|
||||
name=f"{self.name} Bluetooth scanner watchdog",
|
||||
)
|
||||
self._schedule_watchdog()
|
||||
|
||||
def _schedule_watchdog(self) -> None:
|
||||
"""Schedule the watchdog."""
|
||||
loop = self._loop
|
||||
assert loop is not None
|
||||
self._cancel_watchdog = loop.call_at(
|
||||
loop.time() + SCANNER_WATCHDOG_INTERVAL_SECONDS,
|
||||
self._async_call_scanner_watchdog,
|
||||
)
|
||||
|
||||
@final
|
||||
def _async_call_scanner_watchdog(self) -> None:
|
||||
"""Call the scanner watchdog and schedule the next one."""
|
||||
self._async_scanner_watchdog()
|
||||
self._schedule_watchdog()
|
||||
|
||||
@hass_callback
|
||||
def _async_watchdog_triggered(self) -> bool:
|
||||
@ -116,7 +129,7 @@ class BaseHaScanner(ABC):
|
||||
return time_since_last_detection > SCANNER_WATCHDOG_TIMEOUT
|
||||
|
||||
@hass_callback
|
||||
def _async_scanner_watchdog(self, now: datetime.datetime) -> None:
|
||||
def _async_scanner_watchdog(self) -> None:
|
||||
"""Check if the scanner is running.
|
||||
|
||||
Override this method if you need to do something else when the watchdog
|
||||
@ -135,6 +148,10 @@ class BaseHaScanner(ABC):
|
||||
return
|
||||
self.scanning = not self._connecting
|
||||
|
||||
@hass_callback
|
||||
def _unsetup(self) -> None:
|
||||
"""Unset up the scanner."""
|
||||
|
||||
@contextmanager
|
||||
def connecting(self) -> Generator[None, None, None]:
|
||||
"""Context manager to track connecting state."""
|
||||
@ -183,7 +200,7 @@ class BaseHaScanner(ABC):
|
||||
|
||||
|
||||
class BaseHaRemoteScanner(BaseHaScanner):
|
||||
"""Base class for a Home Assistant remote BLE scanner."""
|
||||
"""Base class for a high availability remote BLE scanner."""
|
||||
|
||||
__slots__ = (
|
||||
"_new_info_callback",
|
||||
@ -191,12 +208,11 @@ class BaseHaRemoteScanner(BaseHaScanner):
|
||||
"_discovered_device_timestamps",
|
||||
"_details",
|
||||
"_expire_seconds",
|
||||
"_storage",
|
||||
"_cancel_track",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
scanner_id: str,
|
||||
name: str,
|
||||
new_info_callback: Callable[[BluetoothServiceInfoBleak], None],
|
||||
@ -204,7 +220,7 @@ class BaseHaRemoteScanner(BaseHaScanner):
|
||||
connectable: bool,
|
||||
) -> None:
|
||||
"""Initialize the scanner."""
|
||||
super().__init__(hass, scanner_id, name, connector)
|
||||
super().__init__(scanner_id, name, connector)
|
||||
self._new_info_callback = new_info_callback
|
||||
self._discovered_device_advertisement_datas: dict[
|
||||
str, tuple[BLEDevice, AdvertisementData]
|
||||
@ -215,55 +231,37 @@ class BaseHaRemoteScanner(BaseHaScanner):
|
||||
# Scanners only care about connectable devices. The manager
|
||||
# will handle taking care of availability for non-connectable devices
|
||||
self._expire_seconds = CONNECTABLE_FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS
|
||||
assert models.MANAGER is not None
|
||||
self._storage = models.MANAGER.storage
|
||||
self._cancel_track: asyncio.TimerHandle | None = None
|
||||
|
||||
def _cancel_expire_devices(self) -> None:
|
||||
"""Cancel the expiration of old devices."""
|
||||
if self._cancel_track:
|
||||
self._cancel_track.cancel()
|
||||
self._cancel_track = None
|
||||
|
||||
@hass_callback
|
||||
def _unsetup(self) -> None:
|
||||
"""Unset up the scanner."""
|
||||
self._async_stop_scanner_watchdog()
|
||||
self._cancel_expire_devices()
|
||||
|
||||
@hass_callback
|
||||
def async_setup(self) -> CALLBACK_TYPE:
|
||||
"""Set up the scanner."""
|
||||
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(dt_util.utcnow())
|
||||
|
||||
cancel_track = async_track_time_interval(
|
||||
self.hass,
|
||||
self._async_expire_devices,
|
||||
timedelta(seconds=30),
|
||||
name=f"{self.name} Bluetooth scanner device expire",
|
||||
)
|
||||
cancel_stop = self.hass.bus.async_listen(
|
||||
EVENT_HOMEASSISTANT_STOP, self._async_save_history
|
||||
)
|
||||
super().async_setup()
|
||||
self._schedule_expire_devices()
|
||||
self._async_setup_scanner_watchdog()
|
||||
return self._unsetup
|
||||
|
||||
@hass_callback
|
||||
def _cancel() -> None:
|
||||
self._async_save_history()
|
||||
self._async_stop_scanner_watchdog()
|
||||
cancel_track()
|
||||
cancel_stop()
|
||||
|
||||
return _cancel
|
||||
def _schedule_expire_devices(self) -> None:
|
||||
"""Schedule the expiration of old devices."""
|
||||
loop = self._loop
|
||||
assert loop is not None
|
||||
self._cancel_expire_devices()
|
||||
self._cancel_track = loop.call_at(loop.time() + 30, self._async_expire_devices)
|
||||
|
||||
@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,
|
||||
),
|
||||
)
|
||||
|
||||
@hass_callback
|
||||
def _async_expire_devices(self, _datetime: datetime.datetime) -> None:
|
||||
def _async_expire_devices(self) -> None:
|
||||
"""Expire old devices."""
|
||||
now = MONOTONIC_TIME()
|
||||
expired = [
|
||||
@ -274,6 +272,7 @@ class BaseHaRemoteScanner(BaseHaScanner):
|
||||
for address in expired:
|
||||
del self._discovered_device_advertisement_datas[address]
|
||||
del self._discovered_device_timestamps[address]
|
||||
self._schedule_expire_devices()
|
||||
|
||||
@property
|
||||
def discovered_devices(self) -> list[BLEDevice]:
|
||||
@ -395,9 +394,6 @@ class BaseHaRemoteScanner(BaseHaScanner):
|
||||
"""Return diagnostic information about the scanner."""
|
||||
now = MONOTONIC_TIME()
|
||||
return await super().async_diagnostics() | {
|
||||
"storage": self._storage.async_get_advertisement_history_as_dict(
|
||||
self.source
|
||||
),
|
||||
"connectable": self.connectable,
|
||||
"discovered_device_timestamps": self._discovered_device_timestamps,
|
||||
"time_since_last_device_detection": {
|
||||
@ -405,3 +401,79 @@ class BaseHaRemoteScanner(BaseHaScanner):
|
||||
for address, timestamp in self._discovered_device_timestamps.items()
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@ -3,7 +3,6 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Callable
|
||||
from datetime import datetime
|
||||
import logging
|
||||
import platform
|
||||
from typing import Any
|
||||
@ -19,7 +18,7 @@ from bleak_retry_connector import restore_discoveries
|
||||
from bluetooth_adapters import DEFAULT_ADDRESS
|
||||
from dbus_fast import InvalidMessageError
|
||||
|
||||
from homeassistant.core import HomeAssistant, callback as hass_callback
|
||||
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback as hass_callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.util.package import is_docker_env
|
||||
|
||||
@ -133,12 +132,13 @@ class HaScanner(BaseHaScanner):
|
||||
"""Init bluetooth discovery."""
|
||||
self.mac_address = address
|
||||
source = address if address != DEFAULT_ADDRESS else adapter or SOURCE_LOCAL
|
||||
super().__init__(hass, source, adapter)
|
||||
super().__init__(source, adapter)
|
||||
self.connectable = True
|
||||
self.mode = mode
|
||||
self._start_stop_lock = asyncio.Lock()
|
||||
self._new_info_callback = new_info_callback
|
||||
self.scanning = False
|
||||
self.hass = hass
|
||||
|
||||
@property
|
||||
def discovered_devices(self) -> list[BLEDevice]:
|
||||
@ -153,11 +153,13 @@ class HaScanner(BaseHaScanner):
|
||||
return self.scanner.discovered_devices_and_advertisement_data
|
||||
|
||||
@hass_callback
|
||||
def async_setup(self) -> None:
|
||||
def async_setup(self) -> CALLBACK_TYPE:
|
||||
"""Set up the scanner."""
|
||||
super().async_setup()
|
||||
self.scanner = create_bleak_scanner(
|
||||
self._async_detection_callback, self.mode, self.adapter
|
||||
)
|
||||
return self._unsetup
|
||||
|
||||
async def async_diagnostics(self) -> dict[str, Any]:
|
||||
"""Return diagnostic information about the scanner."""
|
||||
@ -314,7 +316,7 @@ class HaScanner(BaseHaScanner):
|
||||
await restore_discoveries(self.scanner, self.adapter)
|
||||
|
||||
@hass_callback
|
||||
def _async_scanner_watchdog(self, now: datetime) -> None:
|
||||
def _async_scanner_watchdog(self) -> None:
|
||||
"""Check if the scanner is running."""
|
||||
if not self._async_watchdog_triggered():
|
||||
return
|
||||
|
@ -7,11 +7,14 @@ from bluetooth_data_tools import (
|
||||
parse_advertisement_data_tuple,
|
||||
)
|
||||
|
||||
from homeassistant.components.bluetooth import MONOTONIC_TIME, BaseHaRemoteScanner
|
||||
from homeassistant.components.bluetooth import (
|
||||
MONOTONIC_TIME,
|
||||
HomeAssistantRemoteScanner,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
|
||||
|
||||
class ESPHomeScanner(BaseHaRemoteScanner):
|
||||
class ESPHomeScanner(HomeAssistantRemoteScanner):
|
||||
"""Scanner for esphome."""
|
||||
|
||||
__slots__ = ()
|
||||
|
@ -10,7 +10,7 @@ from home_assistant_bluetooth import BluetoothServiceInfoBleak
|
||||
from homeassistant.components.bluetooth import (
|
||||
FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS,
|
||||
MONOTONIC_TIME,
|
||||
BaseHaRemoteScanner,
|
||||
HomeAssistantRemoteScanner,
|
||||
async_get_advertisement_callback,
|
||||
async_register_scanner,
|
||||
)
|
||||
@ -22,7 +22,7 @@ from .coordinator import RuuviGatewayUpdateCoordinator
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RuuviGatewayScanner(BaseHaRemoteScanner):
|
||||
class RuuviGatewayScanner(HomeAssistantRemoteScanner):
|
||||
"""Scanner for Ruuvi Gateway."""
|
||||
|
||||
def __init__(
|
||||
|
@ -6,13 +6,16 @@ from typing import Any
|
||||
from aioshelly.ble import parse_ble_scan_result_event
|
||||
from aioshelly.ble.const import BLE_SCAN_RESULT_EVENT, BLE_SCAN_RESULT_VERSION
|
||||
|
||||
from homeassistant.components.bluetooth import MONOTONIC_TIME, BaseHaRemoteScanner
|
||||
from homeassistant.components.bluetooth import (
|
||||
MONOTONIC_TIME,
|
||||
HomeAssistantRemoteScanner,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
|
||||
from ..const import LOGGER
|
||||
|
||||
|
||||
class ShellyBLEScanner(BaseHaRemoteScanner):
|
||||
class ShellyBLEScanner(HomeAssistantRemoteScanner):
|
||||
"""Scanner for shelly."""
|
||||
|
||||
@callback
|
||||
|
@ -7,9 +7,9 @@ import pytest
|
||||
from homeassistant.components import bluetooth
|
||||
from homeassistant.components.bluetooth import (
|
||||
MONOTONIC_TIME,
|
||||
BaseHaRemoteScanner,
|
||||
BaseHaScanner,
|
||||
HaBluetoothConnector,
|
||||
HomeAssistantRemoteScanner,
|
||||
async_scanner_by_source,
|
||||
async_scanner_devices_by_address,
|
||||
)
|
||||
@ -27,7 +27,7 @@ from . import (
|
||||
async def test_scanner_by_source(hass: HomeAssistant, enable_bluetooth: None) -> None:
|
||||
"""Test we can get a scanner by source."""
|
||||
|
||||
hci2_scanner = FakeScanner(hass, "hci2", "hci2")
|
||||
hci2_scanner = FakeScanner("hci2", "hci2")
|
||||
cancel_hci2 = bluetooth.async_register_scanner(hass, hci2_scanner, True)
|
||||
|
||||
assert async_scanner_by_source(hass, "hci2") is hci2_scanner
|
||||
@ -46,7 +46,7 @@ async def test_async_scanner_devices_by_address_connectable(
|
||||
"""Test getting scanner devices by address with connectable devices."""
|
||||
manager = _get_manager()
|
||||
|
||||
class FakeInjectableScanner(BaseHaRemoteScanner):
|
||||
class FakeInjectableScanner(HomeAssistantRemoteScanner):
|
||||
def inject_advertisement(
|
||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||
) -> None:
|
||||
@ -135,7 +135,7 @@ async def test_async_scanner_devices_by_address_non_connectable(
|
||||
connector = (
|
||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||
)
|
||||
scanner = FakeStaticScanner(hass, "esp32", "esp32", connector)
|
||||
scanner = FakeStaticScanner("esp32", "esp32", connector)
|
||||
cancel = manager.async_register_scanner(scanner, False)
|
||||
|
||||
assert scanner.discovered_devices_and_advertisement_data == {
|
||||
|
@ -13,8 +13,8 @@ import pytest
|
||||
from homeassistant.components import bluetooth
|
||||
from homeassistant.components.bluetooth import (
|
||||
MONOTONIC_TIME,
|
||||
BaseHaRemoteScanner,
|
||||
HaBluetoothConnector,
|
||||
HomeAssistantRemoteScanner,
|
||||
storage,
|
||||
)
|
||||
from homeassistant.components.bluetooth.advertisement_tracker import (
|
||||
@ -89,7 +89,7 @@ async def test_remote_scanner(
|
||||
rssi=-100,
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
def inject_advertisement(
|
||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||
) -> None:
|
||||
@ -173,7 +173,7 @@ async def test_remote_scanner_expires_connectable(
|
||||
rssi=-100,
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
def inject_advertisement(
|
||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||
) -> None:
|
||||
@ -248,7 +248,7 @@ async def test_remote_scanner_expires_non_connectable(
|
||||
rssi=-100,
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
def inject_advertisement(
|
||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||
) -> None:
|
||||
@ -346,7 +346,7 @@ async def test_base_scanner_connecting_behavior(
|
||||
rssi=-100,
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
def inject_advertisement(
|
||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||
) -> None:
|
||||
@ -418,7 +418,7 @@ async def test_restore_history_remote_adapter(
|
||||
connector = (
|
||||
HaBluetoothConnector(MockBleakClient, "mock_bleak_client", lambda: False),
|
||||
)
|
||||
scanner = BaseHaRemoteScanner(
|
||||
scanner = HomeAssistantRemoteScanner(
|
||||
hass,
|
||||
"atom-bluetooth-proxy-ceaac4",
|
||||
"atom-bluetooth-proxy-ceaac4",
|
||||
@ -434,7 +434,7 @@ async def test_restore_history_remote_adapter(
|
||||
cancel()
|
||||
unsetup()
|
||||
|
||||
scanner = BaseHaRemoteScanner(
|
||||
scanner = HomeAssistantRemoteScanner(
|
||||
hass,
|
||||
"atom-bluetooth-proxy-ceaac4",
|
||||
"atom-bluetooth-proxy-ceaac4",
|
||||
@ -470,7 +470,7 @@ async def test_device_with_ten_minute_advertising_interval(
|
||||
rssi=-100,
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
def inject_advertisement(
|
||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||
) -> None:
|
||||
@ -592,7 +592,7 @@ async def test_scanner_stops_responding(
|
||||
"""Test we mark a scanner are not scanning when it stops responding."""
|
||||
manager = _get_manager()
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
"""A fake remote scanner."""
|
||||
|
||||
def inject_advertisement(
|
||||
|
@ -7,8 +7,8 @@ from bluetooth_adapters import DEFAULT_ADDRESS
|
||||
from homeassistant.components import bluetooth
|
||||
from homeassistant.components.bluetooth import (
|
||||
MONOTONIC_TIME,
|
||||
BaseHaRemoteScanner,
|
||||
HaBluetoothConnector,
|
||||
HomeAssistantRemoteScanner,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
@ -442,7 +442,7 @@ async def test_diagnostics_remote_adapter(
|
||||
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
def inject_advertisement(
|
||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||
) -> None:
|
||||
|
@ -12,12 +12,12 @@ import pytest
|
||||
from homeassistant.components import bluetooth
|
||||
from homeassistant.components.bluetooth import (
|
||||
MONOTONIC_TIME,
|
||||
BaseHaRemoteScanner,
|
||||
BluetoothChange,
|
||||
BluetoothScanningMode,
|
||||
BluetoothServiceInfo,
|
||||
BluetoothServiceInfoBleak,
|
||||
HaBluetoothConnector,
|
||||
HomeAssistantRemoteScanner,
|
||||
async_ble_device_from_address,
|
||||
async_get_advertisement_callback,
|
||||
async_get_fallback_availability_interval,
|
||||
@ -56,7 +56,7 @@ from tests.common import async_fire_time_changed, load_fixture
|
||||
@pytest.fixture
|
||||
def register_hci0_scanner(hass: HomeAssistant) -> Generator[None, None, None]:
|
||||
"""Register an hci0 scanner."""
|
||||
hci0_scanner = FakeScanner(hass, "hci0", "hci0")
|
||||
hci0_scanner = FakeScanner("hci0", "hci0")
|
||||
cancel = bluetooth.async_register_scanner(hass, hci0_scanner, True)
|
||||
yield
|
||||
cancel()
|
||||
@ -65,7 +65,7 @@ def register_hci0_scanner(hass: HomeAssistant) -> Generator[None, None, None]:
|
||||
@pytest.fixture
|
||||
def register_hci1_scanner(hass: HomeAssistant) -> Generator[None, None, None]:
|
||||
"""Register an hci1 scanner."""
|
||||
hci1_scanner = FakeScanner(hass, "hci1", "hci1")
|
||||
hci1_scanner = FakeScanner("hci1", "hci1")
|
||||
cancel = bluetooth.async_register_scanner(hass, hci1_scanner, True)
|
||||
yield
|
||||
cancel()
|
||||
@ -562,7 +562,7 @@ async def test_switching_adapters_when_one_goes_away(
|
||||
) -> None:
|
||||
"""Test switching adapters when one goes away."""
|
||||
cancel_hci2 = bluetooth.async_register_scanner(
|
||||
hass, FakeScanner(hass, "hci2", "hci2"), True
|
||||
hass, FakeScanner("hci2", "hci2"), True
|
||||
)
|
||||
|
||||
address = "44:44:33:11:23:45"
|
||||
@ -612,7 +612,7 @@ async def test_switching_adapters_when_one_stop_scanning(
|
||||
hass: HomeAssistant, enable_bluetooth: None, register_hci0_scanner: None
|
||||
) -> None:
|
||||
"""Test switching adapters when stops scanning."""
|
||||
hci2_scanner = FakeScanner(hass, "hci2", "hci2")
|
||||
hci2_scanner = FakeScanner("hci2", "hci2")
|
||||
cancel_hci2 = bluetooth.async_register_scanner(hass, hci2_scanner, True)
|
||||
|
||||
address = "44:44:33:11:23:45"
|
||||
@ -704,7 +704,7 @@ async def test_goes_unavailable_connectable_only_and_recovers(
|
||||
BluetoothScanningMode.ACTIVE,
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
def inject_advertisement(
|
||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||
) -> None:
|
||||
@ -877,7 +877,7 @@ async def test_goes_unavailable_dismisses_discovery_and_makes_discoverable(
|
||||
BluetoothScanningMode.ACTIVE,
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
def inject_advertisement(
|
||||
self, device: BLEDevice, advertisement_data: AdvertisementData
|
||||
) -> None:
|
||||
|
@ -10,9 +10,9 @@ from bleak.backends.scanner import AdvertisementData
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.bluetooth import (
|
||||
BaseHaRemoteScanner,
|
||||
BaseHaScanner,
|
||||
HaBluetoothConnector,
|
||||
HomeAssistantRemoteScanner,
|
||||
)
|
||||
from homeassistant.components.bluetooth.wrappers import (
|
||||
HaBleakClientWrapper,
|
||||
@ -158,7 +158,7 @@ async def test_wrapped_bleak_client_set_disconnected_callback_after_connected(
|
||||
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}, rssi=-100
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
@property
|
||||
def discovered_devices(self) -> list[BLEDevice]:
|
||||
"""Return a list of discovered devices."""
|
||||
@ -271,7 +271,7 @@ async def test_ble_device_with_proxy_client_out_of_connections(
|
||||
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
@property
|
||||
def discovered_devices(self) -> list[BLEDevice]:
|
||||
"""Return a list of discovered devices."""
|
||||
@ -336,7 +336,7 @@ async def test_ble_device_with_proxy_clear_cache(
|
||||
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
@property
|
||||
def discovered_devices(self) -> list[BLEDevice]:
|
||||
"""Return a list of discovered devices."""
|
||||
@ -439,7 +439,7 @@ async def test_ble_device_with_proxy_client_out_of_connections_uses_best_availab
|
||||
"esp32_no_connection_slot",
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
@property
|
||||
def discovered_devices(self) -> list[BLEDevice]:
|
||||
"""Return a list of discovered devices."""
|
||||
@ -553,7 +553,7 @@ async def test_ble_device_with_proxy_client_out_of_connections_uses_best_availab
|
||||
"esp32_no_connection_slot",
|
||||
)
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
@property
|
||||
def discovered_devices(self) -> list[BLEDevice]:
|
||||
"""Return a list of discovered devices."""
|
||||
|
@ -12,9 +12,9 @@ import pytest
|
||||
|
||||
from homeassistant.components.bluetooth import (
|
||||
MONOTONIC_TIME,
|
||||
BaseHaRemoteScanner,
|
||||
BluetoothServiceInfoBleak,
|
||||
HaBluetoothConnector,
|
||||
HomeAssistantRemoteScanner,
|
||||
async_get_advertisement_callback,
|
||||
)
|
||||
from homeassistant.components.bluetooth.usage import (
|
||||
@ -26,7 +26,7 @@ from homeassistant.core import HomeAssistant
|
||||
from . import _get_manager, generate_advertisement_data, generate_ble_device
|
||||
|
||||
|
||||
class FakeScanner(BaseHaRemoteScanner):
|
||||
class FakeScanner(HomeAssistantRemoteScanner):
|
||||
"""Fake scanner."""
|
||||
|
||||
def __init__(
|
||||
|
Loading…
x
Reference in New Issue
Block a user