Include the source in the bluetooth service info (#75112)

This commit is contained in:
J. Nick Koston 2022-07-16 11:02:08 -05:00 committed by GitHub
parent 859189421b
commit ecc219fbc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 6 deletions

View File

@ -39,6 +39,8 @@ _LOGGER = logging.getLogger(__name__)
MAX_REMEMBER_ADDRESSES: Final = 2048 MAX_REMEMBER_ADDRESSES: Final = 2048
SOURCE_LOCAL: Final = "local"
class BluetoothCallbackMatcherOptional(TypedDict, total=False): class BluetoothCallbackMatcherOptional(TypedDict, total=False):
"""Matcher for the bluetooth integration for callback optional fields.""" """Matcher for the bluetooth integration for callback optional fields."""
@ -266,7 +268,7 @@ class BluetoothManager:
): ):
if service_info is None: if service_info is None:
service_info = BluetoothServiceInfo.from_advertisement( service_info = BluetoothServiceInfo.from_advertisement(
device, advertisement_data device, advertisement_data, SOURCE_LOCAL
) )
try: try:
callback(service_info, BluetoothChange.ADVERTISEMENT) callback(service_info, BluetoothChange.ADVERTISEMENT)
@ -277,7 +279,7 @@ class BluetoothManager:
return return
if service_info is None: if service_info is None:
service_info = BluetoothServiceInfo.from_advertisement( service_info = BluetoothServiceInfo.from_advertisement(
device, advertisement_data device, advertisement_data, SOURCE_LOCAL
) )
for domain in matched_domains: for domain in matched_domains:
discovery_flow.async_create_flow( discovery_flow.async_create_flow(
@ -312,7 +314,9 @@ class BluetoothManager:
): ):
try: try:
callback( callback(
BluetoothServiceInfo.from_advertisement(*device_adv_data), BluetoothServiceInfo.from_advertisement(
*device_adv_data, SOURCE_LOCAL
),
BluetoothChange.ADVERTISEMENT, BluetoothChange.ADVERTISEMENT,
) )
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
@ -338,7 +342,9 @@ class BluetoothManager:
discovered = models.HA_BLEAK_SCANNER.discovered_devices discovered = models.HA_BLEAK_SCANNER.discovered_devices
history = models.HA_BLEAK_SCANNER.history history = models.HA_BLEAK_SCANNER.history
return [ return [
BluetoothServiceInfo.from_advertisement(*history[device.address]) BluetoothServiceInfo.from_advertisement(
*history[device.address], SOURCE_LOCAL
)
for device in discovered for device in discovered
if device.address in history if device.address in history
] ]

View File

@ -22,10 +22,11 @@ class BluetoothServiceInfo(BaseServiceInfo):
manufacturer_data: dict[int, bytes] manufacturer_data: dict[int, bytes]
service_data: dict[str, bytes] service_data: dict[str, bytes]
service_uuids: list[str] service_uuids: list[str]
source: str
@classmethod @classmethod
def from_advertisement( def from_advertisement(
cls, device: BLEDevice, advertisement_data: AdvertisementData cls, device: BLEDevice, advertisement_data: AdvertisementData, source: str
) -> BluetoothServiceInfo: ) -> BluetoothServiceInfo:
"""Create a BluetoothServiceInfo from an advertisement.""" """Create a BluetoothServiceInfo from an advertisement."""
return cls( return cls(
@ -35,6 +36,7 @@ class BluetoothServiceInfo(BaseServiceInfo):
manufacturer_data=advertisement_data.manufacturer_data, manufacturer_data=advertisement_data.manufacturer_data,
service_data=advertisement_data.service_data, service_data=advertisement_data.service_data,
service_uuids=advertisement_data.service_uuids, service_uuids=advertisement_data.service_uuids,
source=source,
) )
@cached_property @cached_property

View File

@ -6,6 +6,7 @@ from bleak.backends.scanner import AdvertisementData, BLEDevice
from homeassistant.components import bluetooth from homeassistant.components import bluetooth
from homeassistant.components.bluetooth import ( from homeassistant.components.bluetooth import (
SOURCE_LOCAL,
BluetoothChange, BluetoothChange,
BluetoothServiceInfo, BluetoothServiceInfo,
models, models,
@ -244,6 +245,7 @@ async def test_async_discovered_device_api(hass, mock_bleak_scanner_start):
assert len(service_infos) == 1 assert len(service_infos) == 1
# wrong_name should not appear because bleak no longer sees it # wrong_name should not appear because bleak no longer sees it
assert service_infos[0].name == "wohand" assert service_infos[0].name == "wohand"
assert service_infos[0].source == SOURCE_LOCAL
assert bluetooth.async_address_present(hass, "44:44:33:11:23:42") is False assert bluetooth.async_address_present(hass, "44:44:33:11:23:42") is False
assert bluetooth.async_address_present(hass, "44:44:33:11:23:45") is True assert bluetooth.async_address_present(hass, "44:44:33:11:23:45") is True
@ -255,7 +257,8 @@ async def test_register_callbacks(hass, mock_bleak_scanner_start):
callbacks = [] callbacks = []
def _fake_subscriber( def _fake_subscriber(
service_info: BluetoothServiceInfo, change: BluetoothChange service_info: BluetoothServiceInfo,
change: BluetoothChange,
) -> None: ) -> None:
"""Fake subscriber for the BleakScanner.""" """Fake subscriber for the BleakScanner."""
callbacks.append((service_info, change)) callbacks.append((service_info, change))
@ -312,16 +315,19 @@ async def test_register_callbacks(hass, mock_bleak_scanner_start):
service_info: BluetoothServiceInfo = callbacks[0][0] service_info: BluetoothServiceInfo = callbacks[0][0]
assert service_info.name == "wohand" assert service_info.name == "wohand"
assert service_info.source == SOURCE_LOCAL
assert service_info.manufacturer == "Nordic Semiconductor ASA" assert service_info.manufacturer == "Nordic Semiconductor ASA"
assert service_info.manufacturer_id == 89 assert service_info.manufacturer_id == 89
service_info: BluetoothServiceInfo = callbacks[1][0] service_info: BluetoothServiceInfo = callbacks[1][0]
assert service_info.name == "empty" assert service_info.name == "empty"
assert service_info.source == SOURCE_LOCAL
assert service_info.manufacturer is None assert service_info.manufacturer is None
assert service_info.manufacturer_id is None assert service_info.manufacturer_id is None
service_info: BluetoothServiceInfo = callbacks[2][0] service_info: BluetoothServiceInfo = callbacks[2][0]
assert service_info.name == "empty" assert service_info.name == "empty"
assert service_info.source == SOURCE_LOCAL
assert service_info.manufacturer is None assert service_info.manufacturer is None
assert service_info.manufacturer_id is None assert service_info.manufacturer_id is None