Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: port bluetooth manager from HA #13

Merged
merged 5 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/habluetooth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,27 @@
TRACKER_BUFFERING_WOBBLE_SECONDS,
AdvertisementTracker,
)
from .base_scanner import BaseHaRemoteScanner, BaseHaScanner
from .base_scanner import BaseHaRemoteScanner, BaseHaScanner, BluetoothScannerDevice
from .const import (
CONNECTABLE_FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS,
FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS,
SCANNER_WATCHDOG_INTERVAL,
SCANNER_WATCHDOG_TIMEOUT,
UNAVAILABLE_TRACK_SECONDS,
)
from .models import HaBluetoothConnector
from .manager import BluetoothManager
from .models import HaBluetoothConnector, get_manager, set_manager
from .scanner import BluetoothScanningMode, HaScanner, ScannerStartError
from .wrappers import HaBleakClientWrapper, HaBleakScannerWrapper

__all__ = [
"HaBleakScannerWrapper",
"HaBleakClientWrapper",
"BluetoothManager",
"get_manager",
"set_manager",
"BluetoothScannerDevice",
"UNAVAILABLE_TRACK_SECONDS",
"TRACKER_BUFFERING_WOBBLE_SECONDS",
"AdvertisementTracker",
"BluetoothScanningMode",
Expand Down
21 changes: 15 additions & 6 deletions src/habluetooth/base_scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import logging
from collections.abc import Callable, Generator
from contextlib import contextmanager
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Final, final

from bleak.backends.device import BLEDevice
Expand All @@ -23,7 +24,6 @@
from .models import HaBluetoothConnector

SCANNER_WATCHDOG_INTERVAL_SECONDS: Final = SCANNER_WATCHDOG_INTERVAL.total_seconds()
MONOTONIC_TIME: Final = monotonic_time_coarse
_LOGGER = logging.getLogger(__name__)


Expand All @@ -32,6 +32,15 @@
_str = str


@dataclass(slots=True)
class BluetoothScannerDevice:
"""Data for a bluetooth device from a given scanner."""

scanner: BaseHaScanner
ble_device: BLEDevice
advertisement: AdvertisementData


class BaseHaScanner:
"""Base class for high availability BLE scanners."""

Expand Down Expand Up @@ -81,7 +90,7 @@ def _async_stop_scanner_watchdog(self) -> None:

def _async_setup_scanner_watchdog(self) -> None:
"""If something has restarted or updated, we need to restart the scanner."""
self._start_time = self._last_detection = MONOTONIC_TIME()
self._start_time = self._last_detection = monotonic_time_coarse()
if not self._cancel_watchdog:
self._schedule_watchdog()

Expand All @@ -103,7 +112,7 @@ def _async_call_scanner_watchdog(self) -> None:

def _async_watchdog_triggered(self) -> bool:
"""Check if the watchdog has been triggered."""
time_since_last_detection = MONOTONIC_TIME() - self._last_detection
time_since_last_detection = monotonic_time_coarse() - self._last_detection
_LOGGER.debug(
"%s: Scanner watchdog time_since_last_detection: %s",
self.name,
Expand Down Expand Up @@ -165,7 +174,7 @@ async def async_diagnostics(self) -> dict[str, Any]:
"scanning": self.scanning,
"type": self.__class__.__name__,
"last_detection": self._last_detection,
"monotonic_time": MONOTONIC_TIME(),
"monotonic_time": monotonic_time_coarse(),
"discovered_devices_and_advertisement_data": [
{
"name": device.name,
Expand Down Expand Up @@ -241,7 +250,7 @@ def _schedule_expire_devices(self) -> None:

def _async_expire_devices(self) -> None:
"""Expire old devices."""
now = MONOTONIC_TIME()
now = monotonic_time_coarse()
expired = [
address
for address, timestamp in self._discovered_device_timestamps.items()
Expand Down Expand Up @@ -369,7 +378,7 @@ def _async_on_advertisement(

async def async_diagnostics(self) -> dict[str, Any]:
"""Return diagnostic information about the scanner."""
now = MONOTONIC_TIME()
now = monotonic_time_coarse()
return await super().async_diagnostics() | {
"connectable": self.connectable,
"discovered_device_timestamps": self._discovered_device_timestamps,
Expand Down
3 changes: 3 additions & 0 deletions src/habluetooth/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,6 @@
# How often to check if the scanner has reached
# the SCANNER_WATCHDOG_TIMEOUT without seeing anything
SCANNER_WATCHDOG_INTERVAL: Final = timedelta(seconds=30)


UNAVAILABLE_TRACK_SECONDS: Final = 60 * 5
Loading