mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Migrate bluetooth to use the singleton helper (#116629)
This commit is contained in:
parent
007b15dc8b
commit
c07f02534b
@ -51,8 +51,9 @@ from homeassistant.helpers.event import async_call_later
|
|||||||
from homeassistant.helpers.issue_registry import async_delete_issue
|
from homeassistant.helpers.issue_registry import async_delete_issue
|
||||||
from homeassistant.loader import async_get_bluetooth
|
from homeassistant.loader import async_get_bluetooth
|
||||||
|
|
||||||
from . import models, passive_update_processor
|
from . import passive_update_processor
|
||||||
from .api import (
|
from .api import (
|
||||||
|
_get_manager,
|
||||||
async_address_present,
|
async_address_present,
|
||||||
async_ble_device_from_address,
|
async_ble_device_from_address,
|
||||||
async_discovered_service_info,
|
async_discovered_service_info,
|
||||||
@ -76,7 +77,6 @@ from .const import (
|
|||||||
CONF_ADAPTER,
|
CONF_ADAPTER,
|
||||||
CONF_DETAILS,
|
CONF_DETAILS,
|
||||||
CONF_PASSIVE,
|
CONF_PASSIVE,
|
||||||
DATA_MANAGER,
|
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS,
|
FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS,
|
||||||
LINUX_FIRMWARE_LOAD_FALLBACK_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
|
hass, integration_matcher, bluetooth_adapters, bluetooth_storage, slot_manager
|
||||||
)
|
)
|
||||||
set_manager(manager)
|
set_manager(manager)
|
||||||
|
|
||||||
await storage_setup_task
|
await storage_setup_task
|
||||||
await manager.async_setup()
|
await manager.async_setup()
|
||||||
hass.data[DATA_MANAGER] = models.MANAGER = manager
|
|
||||||
|
|
||||||
hass.async_create_background_task(
|
hass.async_create_background_task(
|
||||||
_async_start_adapter_discovery(hass, manager, bluetooth_adapters),
|
_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:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Set up a config entry for a bluetooth scanner."""
|
"""Set up a config entry for a bluetooth scanner."""
|
||||||
manager: HomeAssistantBluetoothManager = hass.data[DATA_MANAGER]
|
manager = _get_manager(hass)
|
||||||
address = entry.unique_id
|
address = entry.unique_id
|
||||||
assert address is not None
|
assert address is not None
|
||||||
adapter = await manager.async_get_adapter_from_address_or_recover(address)
|
adapter = await manager.async_get_adapter_from_address_or_recover(address)
|
||||||
|
@ -15,10 +15,12 @@ from habluetooth import (
|
|||||||
BluetoothScannerDevice,
|
BluetoothScannerDevice,
|
||||||
BluetoothScanningMode,
|
BluetoothScanningMode,
|
||||||
HaBleakScannerWrapper,
|
HaBleakScannerWrapper,
|
||||||
|
get_manager,
|
||||||
)
|
)
|
||||||
from home_assistant_bluetooth import BluetoothServiceInfoBleak
|
from home_assistant_bluetooth import BluetoothServiceInfoBleak
|
||||||
|
|
||||||
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback as hass_callback
|
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback as hass_callback
|
||||||
|
from homeassistant.helpers.singleton import singleton
|
||||||
|
|
||||||
from .const import DATA_MANAGER
|
from .const import DATA_MANAGER
|
||||||
from .manager import HomeAssistantBluetoothManager
|
from .manager import HomeAssistantBluetoothManager
|
||||||
@ -29,9 +31,10 @@ if TYPE_CHECKING:
|
|||||||
from bleak.backends.device import BLEDevice
|
from bleak.backends.device import BLEDevice
|
||||||
|
|
||||||
|
|
||||||
|
@singleton(DATA_MANAGER)
|
||||||
def _get_manager(hass: HomeAssistant) -> HomeAssistantBluetoothManager:
|
def _get_manager(hass: HomeAssistant) -> HomeAssistantBluetoothManager:
|
||||||
"""Get the bluetooth manager."""
|
"""Get the bluetooth manager."""
|
||||||
return cast(HomeAssistantBluetoothManager, hass.data[DATA_MANAGER])
|
return cast(HomeAssistantBluetoothManager, get_manager())
|
||||||
|
|
||||||
|
|
||||||
@hass_callback
|
@hass_callback
|
||||||
@ -68,8 +71,6 @@ def async_discovered_service_info(
|
|||||||
hass: HomeAssistant, connectable: bool = True
|
hass: HomeAssistant, connectable: bool = True
|
||||||
) -> Iterable[BluetoothServiceInfoBleak]:
|
) -> Iterable[BluetoothServiceInfoBleak]:
|
||||||
"""Return the discovered devices list."""
|
"""Return the discovered devices list."""
|
||||||
if DATA_MANAGER not in hass.data:
|
|
||||||
return []
|
|
||||||
return _get_manager(hass).async_discovered_service_info(connectable)
|
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
|
hass: HomeAssistant, address: str, connectable: bool = True
|
||||||
) -> BluetoothServiceInfoBleak | None:
|
) -> BluetoothServiceInfoBleak | None:
|
||||||
"""Return the last service info for an address."""
|
"""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)
|
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
|
hass: HomeAssistant, address: str, connectable: bool = True
|
||||||
) -> BLEDevice | None:
|
) -> BLEDevice | None:
|
||||||
"""Return BLEDevice for an address if its present."""
|
"""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)
|
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
|
hass: HomeAssistant, address: str, connectable: bool = True
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Check if an address is present in the bluetooth device list."""
|
"""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)
|
return _get_manager(hass).async_address_present(address, connectable)
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ from bluetooth_adapters import (
|
|||||||
adapter_model,
|
adapter_model,
|
||||||
get_adapters,
|
get_adapters,
|
||||||
)
|
)
|
||||||
|
from habluetooth import get_manager
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components import onboarding
|
from homeassistant.components import onboarding
|
||||||
@ -25,7 +26,6 @@ from homeassistant.helpers.schema_config_entry_flow import (
|
|||||||
)
|
)
|
||||||
from homeassistant.helpers.typing import DiscoveryInfoType
|
from homeassistant.helpers.typing import DiscoveryInfoType
|
||||||
|
|
||||||
from . import models
|
|
||||||
from .const import CONF_ADAPTER, CONF_DETAILS, CONF_PASSIVE, DOMAIN
|
from .const import CONF_ADAPTER, CONF_DETAILS, CONF_PASSIVE, DOMAIN
|
||||||
from .util import adapter_title
|
from .util import adapter_title
|
||||||
|
|
||||||
@ -185,4 +185,4 @@ class BluetoothConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
@callback
|
@callback
|
||||||
def async_supports_options_flow(cls, config_entry: ConfigEntry) -> bool:
|
def async_supports_options_flow(cls, config_entry: ConfigEntry) -> bool:
|
||||||
"""Return options flow support for this handler."""
|
"""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)
|
||||||
|
@ -4,17 +4,9 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from home_assistant_bluetooth import BluetoothServiceInfoBleak
|
from home_assistant_bluetooth import BluetoothServiceInfoBleak
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from .manager import HomeAssistantBluetoothManager
|
|
||||||
|
|
||||||
|
|
||||||
MANAGER: HomeAssistantBluetoothManager | None = None
|
|
||||||
|
|
||||||
|
|
||||||
BluetoothChange = Enum("BluetoothChange", "ADVERTISEMENT")
|
BluetoothChange = Enum("BluetoothChange", "ADVERTISEMENT")
|
||||||
BluetoothCallback = Callable[[BluetoothServiceInfoBleak, BluetoothChange], None]
|
BluetoothCallback = Callable[[BluetoothServiceInfoBleak, BluetoothChange], None]
|
||||||
ProcessAdvertisementCallback = Callable[[BluetoothServiceInfoBleak], bool]
|
ProcessAdvertisementCallback = Callable[[BluetoothServiceInfoBleak], bool]
|
||||||
|
@ -8,7 +8,7 @@ from unittest.mock import ANY, AsyncMock, MagicMock, Mock, patch
|
|||||||
from bleak import BleakError
|
from bleak import BleakError
|
||||||
from bleak.backends.scanner import AdvertisementData, BLEDevice
|
from bleak.backends.scanner import AdvertisementData, BLEDevice
|
||||||
from bluetooth_adapters import DEFAULT_ADDRESS
|
from bluetooth_adapters import DEFAULT_ADDRESS
|
||||||
from habluetooth import scanner
|
from habluetooth import scanner, set_manager
|
||||||
from habluetooth.wrappers import HaBleakScannerWrapper
|
from habluetooth.wrappers import HaBleakScannerWrapper
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -1154,6 +1154,7 @@ async def test_async_discovered_device_api(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test the async_discovered_device API."""
|
"""Test the async_discovered_device API."""
|
||||||
mock_bt = []
|
mock_bt = []
|
||||||
|
set_manager(None)
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"homeassistant.components.bluetooth.async_get_bluetooth",
|
"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)
|
with pytest.raises(RuntimeError, match="BluetoothManager has not been set"):
|
||||||
assert not bluetooth.async_address_present(hass, "44:44:22:22:11:22")
|
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)
|
await async_setup_with_default_adapter(hass)
|
||||||
|
|
||||||
with patch.object(hass.config_entries.flow, "async_init"):
|
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
|
hass: HomeAssistant, mock_bleak_scanner_start: MagicMock, macos_adapter: None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test the async_ble_device_from_address api."""
|
"""Test the async_ble_device_from_address api."""
|
||||||
|
set_manager(None)
|
||||||
mock_bt = []
|
mock_bt = []
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
@ -2760,11 +2764,15 @@ async def test_async_ble_device_from_address(
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
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")
|
assert not bluetooth.async_discovered_service_info(hass)
|
||||||
assert (
|
with pytest.raises(RuntimeError, match="BluetoothManager has not been set"):
|
||||||
bluetooth.async_ble_device_from_address(hass, "44:44:33:11:23:45") is None
|
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)
|
await async_setup_with_default_adapter(hass)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user