Fire bluetooth listener for all matching devices (#80440)

* Fire listener for all matching devices

* Add test case for seen device

* Avoid looping all data if we have address match

* Initialize to empty list
This commit is contained in:
Joakim Plate 2022-10-16 21:49:12 +02:00 committed by GitHub
parent e71bd2c20b
commit 9eb4faf037
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 10 deletions

View File

@ -483,15 +483,19 @@ class BluetoothManager:
# immediately with the last packet so the subscriber can see the
# device.
all_history = self._get_history_by_type(connectable)
if (
(address := callback_matcher.get(ADDRESS))
and (service_info := all_history.get(address))
and ble_device_matches(callback_matcher, service_info)
):
try:
callback(service_info, BluetoothChange.ADVERTISEMENT)
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Error in bluetooth callback")
service_infos: Iterable[BluetoothServiceInfoBleak] = []
if address := callback_matcher.get(ADDRESS):
if service_info := all_history.get(address):
service_infos = [service_info]
else:
service_infos = all_history.values()
for service_info in service_infos:
if ble_device_matches(callback_matcher, service_info):
try:
callback(service_info, BluetoothChange.ADVERTISEMENT)
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Error in bluetooth callback")
return _async_remove_callback

View File

@ -1089,6 +1089,16 @@ async def test_register_callbacks(hass, mock_bleak_scanner_start, enable_bluetoo
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
seen_switchbot_device = BLEDevice("44:44:33:11:23:46", "wohand")
seen_switchbot_adv = generate_advertisement_data(
local_name="wohand",
service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"],
manufacturer_data={89: b"\xd8.\xad\xcd\r\x85"},
service_data={"00000d00-0000-1000-8000-00805f9b34fb": b"H\x10c"},
)
inject_advertisement(hass, seen_switchbot_device, seen_switchbot_adv)
cancel = bluetooth.async_register_callback(
hass,
_fake_subscriber,
@ -1125,7 +1135,7 @@ async def test_register_callbacks(hass, mock_bleak_scanner_start, enable_bluetoo
inject_advertisement(hass, empty_device, empty_adv)
await hass.async_block_till_done()
assert len(callbacks) == 1
assert len(callbacks) == 2
service_info: BluetoothServiceInfo = callbacks[0][0]
assert service_info.name == "wohand"