Migrate bluetooth to use the singleton helper (#116629)

This commit is contained in:
J. Nick Koston 2024-05-02 19:35:16 -05:00 committed by GitHub
parent 007b15dc8b
commit c07f02534b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 25 additions and 32 deletions

View File

@ -51,8 +51,9 @@ from homeassistant.helpers.event import async_call_later
from homeassistant.helpers.issue_registry import async_delete_issue
from homeassistant.loader import async_get_bluetooth
from . import models, passive_update_processor
from . import passive_update_processor
from .api import (
_get_manager,
async_address_present,
async_ble_device_from_address,
async_discovered_service_info,
@ -76,7 +77,6 @@ from .const import (
CONF_ADAPTER,
CONF_DETAILS,
CONF_PASSIVE,
DATA_MANAGER,
DOMAIN,
FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS,
LINUX_FIRMWARE_LOAD_FALLBACK_SECONDS,
@ -230,10 +230,8 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
hass, integration_matcher, bluetooth_adapters, bluetooth_storage, slot_manager
)
set_manager(manager)
await storage_setup_task
await manager.async_setup()
hass.data[DATA_MANAGER] = models.MANAGER = manager
hass.async_create_background_task(
_async_start_adapter_discovery(hass, manager, bluetooth_adapters),
@ -314,7 +312,7 @@ async def async_update_device(
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up a config entry for a bluetooth scanner."""
manager: HomeAssistantBluetoothManager = hass.data[DATA_MANAGER]
manager = _get_manager(hass)
address = entry.unique_id
assert address is not None
adapter = await manager.async_get_adapter_from_address_or_recover(address)

View File

@ -15,10 +15,12 @@ from habluetooth import (
BluetoothScannerDevice,
BluetoothScanningMode,
HaBleakScannerWrapper,
get_manager,
)
from home_assistant_bluetooth import BluetoothServiceInfoBleak
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback as hass_callback
from homeassistant.helpers.singleton import singleton
from .const import DATA_MANAGER
from .manager import HomeAssistantBluetoothManager
@ -29,9 +31,10 @@ if TYPE_CHECKING:
from bleak.backends.device import BLEDevice
@singleton(DATA_MANAGER)
def _get_manager(hass: HomeAssistant) -> HomeAssistantBluetoothManager:
"""Get the bluetooth manager."""
return cast(HomeAssistantBluetoothManager, hass.data[DATA_MANAGER])
return cast(HomeAssistantBluetoothManager, get_manager())
@hass_callback
@ -68,8 +71,6 @@ def async_discovered_service_info(
hass: HomeAssistant, connectable: bool = True
) -> Iterable[BluetoothServiceInfoBleak]:
"""Return the discovered devices list."""
if DATA_MANAGER not in hass.data:
return []
return _get_manager(hass).async_discovered_service_info(connectable)
@ -78,8 +79,6 @@ def async_last_service_info(
hass: HomeAssistant, address: str, connectable: bool = True
) -> BluetoothServiceInfoBleak | None:
"""Return the last service info for an address."""
if DATA_MANAGER not in hass.data:
return None
return _get_manager(hass).async_last_service_info(address, connectable)
@ -88,8 +87,6 @@ def async_ble_device_from_address(
hass: HomeAssistant, address: str, connectable: bool = True
) -> BLEDevice | None:
"""Return BLEDevice for an address if its present."""
if DATA_MANAGER not in hass.data:
return None
return _get_manager(hass).async_ble_device_from_address(address, connectable)
@ -106,8 +103,6 @@ def async_address_present(
hass: HomeAssistant, address: str, connectable: bool = True
) -> bool:
"""Check if an address is present in the bluetooth device list."""
if DATA_MANAGER not in hass.data:
return False
return _get_manager(hass).async_address_present(address, connectable)

View File

@ -14,6 +14,7 @@ from bluetooth_adapters import (
adapter_model,
get_adapters,
)
from habluetooth import get_manager
import voluptuous as vol
from homeassistant.components import onboarding
@ -25,7 +26,6 @@ from homeassistant.helpers.schema_config_entry_flow import (
)
from homeassistant.helpers.typing import DiscoveryInfoType
from . import models
from .const import CONF_ADAPTER, CONF_DETAILS, CONF_PASSIVE, DOMAIN
from .util import adapter_title
@ -185,4 +185,4 @@ class BluetoothConfigFlow(ConfigFlow, domain=DOMAIN):
@callback
def async_supports_options_flow(cls, config_entry: ConfigEntry) -> bool:
"""Return options flow support for this handler."""
return bool(models.MANAGER and models.MANAGER.supports_passive_scan)
return bool((manager := get_manager()) and manager.supports_passive_scan)

View File

@ -4,17 +4,9 @@ from __future__ import annotations
from collections.abc import Callable
from enum import Enum
from typing import TYPE_CHECKING
from home_assistant_bluetooth import BluetoothServiceInfoBleak
if TYPE_CHECKING:
from .manager import HomeAssistantBluetoothManager
MANAGER: HomeAssistantBluetoothManager | None = None
BluetoothChange = Enum("BluetoothChange", "ADVERTISEMENT")
BluetoothCallback = Callable[[BluetoothServiceInfoBleak, BluetoothChange], None]
ProcessAdvertisementCallback = Callable[[BluetoothServiceInfoBleak], bool]

View File

@ -8,7 +8,7 @@ from unittest.mock import ANY, AsyncMock, MagicMock, Mock, patch
from bleak import BleakError
from bleak.backends.scanner import AdvertisementData, BLEDevice
from bluetooth_adapters import DEFAULT_ADDRESS
from habluetooth import scanner
from habluetooth import scanner, set_manager
from habluetooth.wrappers import HaBleakScannerWrapper
import pytest
@ -1154,6 +1154,7 @@ async def test_async_discovered_device_api(
) -> None:
"""Test the async_discovered_device API."""
mock_bt = []
set_manager(None)
with (
patch(
"homeassistant.components.bluetooth.async_get_bluetooth",
@ -1169,8 +1170,10 @@ async def test_async_discovered_device_api(
},
),
):
assert not bluetooth.async_discovered_service_info(hass)
assert not bluetooth.async_address_present(hass, "44:44:22:22:11:22")
with pytest.raises(RuntimeError, match="BluetoothManager has not been set"):
assert not bluetooth.async_discovered_service_info(hass)
with pytest.raises(RuntimeError, match="BluetoothManager has not been set"):
assert not bluetooth.async_address_present(hass, "44:44:22:22:11:22")
await async_setup_with_default_adapter(hass)
with patch.object(hass.config_entries.flow, "async_init"):
@ -2744,6 +2747,7 @@ async def test_async_ble_device_from_address(
hass: HomeAssistant, mock_bleak_scanner_start: MagicMock, macos_adapter: None
) -> None:
"""Test the async_ble_device_from_address api."""
set_manager(None)
mock_bt = []
with (
patch(
@ -2760,11 +2764,15 @@ async def test_async_ble_device_from_address(
},
),
):
assert not bluetooth.async_discovered_service_info(hass)
assert not bluetooth.async_address_present(hass, "44:44:22:22:11:22")
assert (
bluetooth.async_ble_device_from_address(hass, "44:44:33:11:23:45") is None
)
with pytest.raises(RuntimeError, match="BluetoothManager has not been set"):
assert not bluetooth.async_discovered_service_info(hass)
with pytest.raises(RuntimeError, match="BluetoothManager has not been set"):
assert not bluetooth.async_address_present(hass, "44:44:22:22:11:22")
with pytest.raises(RuntimeError, match="BluetoothManager has not been set"):
assert (
bluetooth.async_ble_device_from_address(hass, "44:44:33:11:23:45")
is None
)
await async_setup_with_default_adapter(hass)