1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-24 12:59:34 +00:00

Add support for scanners that do not provide connectable devices (#77132)

This commit is contained in:
J. Nick Koston
2022-08-22 08:02:26 -10:00
committed by GitHub
parent 61ff1b786b
commit 3938015c93
44 changed files with 1088 additions and 385 deletions

View File

@@ -1,7 +1,8 @@
"""Tests for the Bluetooth integration."""
import asyncio
from datetime import timedelta
from unittest.mock import MagicMock, patch
import time
from unittest.mock import MagicMock, Mock, patch
from bleak import BleakError
from bleak.backends.scanner import AdvertisementData, BLEDevice
@@ -20,6 +21,7 @@ from homeassistant.components.bluetooth import (
)
from homeassistant.components.bluetooth.const import (
DEFAULT_ADDRESS,
DOMAIN,
SOURCE_LOCAL,
UNAVAILABLE_TRACK_SECONDS,
)
@@ -33,6 +35,7 @@ from . import (
_get_manager,
async_setup_with_default_adapter,
inject_advertisement,
inject_advertisement_with_time_and_source_connectable,
patch_discovered_devices,
)
@@ -228,7 +231,7 @@ async def test_discovery_match_by_service_uuid(
wrong_device = BLEDevice("44:44:33:11:23:45", "wrong_name")
wrong_adv = AdvertisementData(local_name="wrong_name", service_uuids=[])
inject_advertisement(wrong_device, wrong_adv)
inject_advertisement(hass, wrong_device, wrong_adv)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
@@ -238,13 +241,160 @@ async def test_discovery_match_by_service_uuid(
local_name="wohand", service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"]
)
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 1
assert mock_config_flow.mock_calls[0][1][0] == "switchbot"
def _domains_from_mock_config_flow(mock_config_flow: Mock) -> list[str]:
"""Get all the domains that were passed to async_init except bluetooth."""
return [call[1][0] for call in mock_config_flow.mock_calls if call[1][0] != DOMAIN]
async def test_discovery_match_by_service_uuid_connectable(
hass, mock_bleak_scanner_start, macos_adapter
):
"""Test bluetooth discovery match by service_uuid and the ble device is connectable."""
mock_bt = [
{
"domain": "switchbot",
"connectable": True,
"service_uuid": "cba20d00-224d-11e6-9fb8-0002a5d5c51b",
}
]
with patch(
"homeassistant.components.bluetooth.async_get_bluetooth", return_value=mock_bt
), patch.object(hass.config_entries.flow, "async_init") as mock_config_flow:
await async_setup_with_default_adapter(hass)
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
assert len(mock_bleak_scanner_start.mock_calls) == 1
wrong_device = BLEDevice("44:44:33:11:23:45", "wrong_name")
wrong_adv = AdvertisementData(local_name="wrong_name", service_uuids=[])
inject_advertisement_with_time_and_source_connectable(
hass, wrong_device, wrong_adv, time.monotonic(), "any", True
)
await hass.async_block_till_done()
assert len(_domains_from_mock_config_flow(mock_config_flow)) == 0
switchbot_device = BLEDevice("44:44:33:11:23:45", "wohand")
switchbot_adv = AdvertisementData(
local_name="wohand", service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"]
)
inject_advertisement_with_time_and_source_connectable(
hass, switchbot_device, switchbot_adv, time.monotonic(), "any", True
)
await hass.async_block_till_done()
called_domains = _domains_from_mock_config_flow(mock_config_flow)
assert len(called_domains) == 1
assert called_domains == ["switchbot"]
async def test_discovery_match_by_service_uuid_not_connectable(
hass, mock_bleak_scanner_start, macos_adapter
):
"""Test bluetooth discovery match by service_uuid and the ble device is not connectable."""
mock_bt = [
{
"domain": "switchbot",
"connectable": True,
"service_uuid": "cba20d00-224d-11e6-9fb8-0002a5d5c51b",
}
]
with patch(
"homeassistant.components.bluetooth.async_get_bluetooth", return_value=mock_bt
), patch.object(hass.config_entries.flow, "async_init") as mock_config_flow:
await async_setup_with_default_adapter(hass)
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
assert len(mock_bleak_scanner_start.mock_calls) == 1
wrong_device = BLEDevice("44:44:33:11:23:45", "wrong_name")
wrong_adv = AdvertisementData(local_name="wrong_name", service_uuids=[])
inject_advertisement_with_time_and_source_connectable(
hass, wrong_device, wrong_adv, time.monotonic(), "any", False
)
await hass.async_block_till_done()
assert len(_domains_from_mock_config_flow(mock_config_flow)) == 0
switchbot_device = BLEDevice("44:44:33:11:23:45", "wohand")
switchbot_adv = AdvertisementData(
local_name="wohand", service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"]
)
inject_advertisement_with_time_and_source_connectable(
hass, switchbot_device, switchbot_adv, time.monotonic(), "any", False
)
await hass.async_block_till_done()
assert len(_domains_from_mock_config_flow(mock_config_flow)) == 0
async def test_discovery_match_by_name_connectable_false(
hass, mock_bleak_scanner_start, macos_adapter
):
"""Test bluetooth discovery match by name and the integration will take non-connectable devices."""
mock_bt = [
{
"domain": "qingping",
"connectable": False,
"local_name": "Qingping*",
}
]
with patch(
"homeassistant.components.bluetooth.async_get_bluetooth", return_value=mock_bt
), patch.object(hass.config_entries.flow, "async_init") as mock_config_flow:
await async_setup_with_default_adapter(hass)
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
assert len(mock_bleak_scanner_start.mock_calls) == 1
wrong_device = BLEDevice("44:44:33:11:23:45", "wrong_name")
wrong_adv = AdvertisementData(local_name="wrong_name", service_uuids=[])
inject_advertisement_with_time_and_source_connectable(
hass, wrong_device, wrong_adv, time.monotonic(), "any", False
)
await hass.async_block_till_done()
assert len(_domains_from_mock_config_flow(mock_config_flow)) == 0
qingping_device = BLEDevice("44:44:33:11:23:45", "Qingping Motion & Light")
qingping_adv = AdvertisementData(
local_name="Qingping Motion & Light",
service_data={
"0000fdcd-0000-1000-8000-00805f9b34fb": b"H\x12\xcd\xd5`4-X\x08\x04\x01\xe8\x00\x00\x0f\x01{"
},
)
inject_advertisement_with_time_and_source_connectable(
hass, qingping_device, qingping_adv, time.monotonic(), "any", False
)
await hass.async_block_till_done()
assert _domains_from_mock_config_flow(mock_config_flow) == ["qingping"]
mock_config_flow.reset_mock()
# Make sure it will also take a connectable device
inject_advertisement_with_time_and_source_connectable(
hass, qingping_device, qingping_adv, time.monotonic(), "any", True
)
await hass.async_block_till_done()
assert _domains_from_mock_config_flow(mock_config_flow) == ["qingping"]
async def test_discovery_match_by_local_name(
hass, mock_bleak_scanner_start, macos_adapter
):
@@ -264,7 +414,7 @@ async def test_discovery_match_by_local_name(
wrong_device = BLEDevice("44:44:33:11:23:45", "wrong_name")
wrong_adv = AdvertisementData(local_name="wrong_name", service_uuids=[])
inject_advertisement(wrong_device, wrong_adv)
inject_advertisement(hass, wrong_device, wrong_adv)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
@@ -272,7 +422,7 @@ async def test_discovery_match_by_local_name(
switchbot_device = BLEDevice("44:44:33:11:23:45", "wohand")
switchbot_adv = AdvertisementData(local_name="wohand", service_uuids=[])
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 1
@@ -315,21 +465,21 @@ async def test_discovery_match_by_manufacturer_id_and_manufacturer_data_start(
# 1st discovery with no manufacturer data
# should not trigger config flow
inject_advertisement(hkc_device, hkc_adv_no_mfr_data)
inject_advertisement(hass, hkc_device, hkc_adv_no_mfr_data)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
mock_config_flow.reset_mock()
# 2nd discovery with manufacturer data
# should trigger a config flow
inject_advertisement(hkc_device, hkc_adv)
inject_advertisement(hass, hkc_device, hkc_adv)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 1
assert mock_config_flow.mock_calls[0][1][0] == "homekit_controller"
mock_config_flow.reset_mock()
# 3rd discovery should not generate another flow
inject_advertisement(hkc_device, hkc_adv)
inject_advertisement(hass, hkc_device, hkc_adv)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
@@ -340,7 +490,7 @@ async def test_discovery_match_by_manufacturer_id_and_manufacturer_data_start(
local_name="lock", service_uuids=[], manufacturer_data={76: b"\x02"}
)
inject_advertisement(not_hkc_device, not_hkc_adv)
inject_advertisement(hass, not_hkc_device, not_hkc_adv)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
@@ -349,7 +499,7 @@ async def test_discovery_match_by_manufacturer_id_and_manufacturer_data_start(
local_name="lock", service_uuids=[], manufacturer_data={21: b"\x02"}
)
inject_advertisement(not_apple_device, not_apple_adv)
inject_advertisement(hass, not_apple_device, not_apple_adv)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
@@ -422,21 +572,21 @@ async def test_discovery_match_by_service_data_uuid_then_others(
)
# 1st discovery should not generate a flow because the
# service_data_uuid is not in the advertisement
inject_advertisement(device, adv_without_service_data_uuid)
inject_advertisement(hass, device, adv_without_service_data_uuid)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
mock_config_flow.reset_mock()
# 2nd discovery should not generate a flow because the
# service_data_uuid is not in the advertisement
inject_advertisement(device, adv_without_service_data_uuid)
inject_advertisement(hass, device, adv_without_service_data_uuid)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
mock_config_flow.reset_mock()
# 3rd discovery should generate a flow because the
# manufacturer_data is in the advertisement
inject_advertisement(device, adv_with_mfr_data)
inject_advertisement(hass, device, adv_with_mfr_data)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 1
assert mock_config_flow.mock_calls[0][1][0] == "other_domain"
@@ -445,7 +595,7 @@ async def test_discovery_match_by_service_data_uuid_then_others(
# 4th discovery should generate a flow because the
# service_data_uuid is in the advertisement and
# we never saw a service_data_uuid before
inject_advertisement(device, adv_with_service_data_uuid)
inject_advertisement(hass, device, adv_with_service_data_uuid)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 1
assert mock_config_flow.mock_calls[0][1][0] == "my_domain"
@@ -453,14 +603,14 @@ async def test_discovery_match_by_service_data_uuid_then_others(
# 5th discovery should not generate a flow because the
# we already saw an advertisement with the service_data_uuid
inject_advertisement(device, adv_with_service_data_uuid)
inject_advertisement(hass, device, adv_with_service_data_uuid)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
# 6th discovery should not generate a flow because the
# manufacturer_data is in the advertisement
# and we saw manufacturer_data before
inject_advertisement(device, adv_with_service_data_uuid_and_mfr_data)
inject_advertisement(hass, device, adv_with_service_data_uuid_and_mfr_data)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
mock_config_flow.reset_mock()
@@ -469,7 +619,7 @@ async def test_discovery_match_by_service_data_uuid_then_others(
# service_uuids is in the advertisement
# and we never saw service_uuids before
inject_advertisement(
device, adv_with_service_data_uuid_and_mfr_data_and_service_uuid
hass, device, adv_with_service_data_uuid_and_mfr_data_and_service_uuid
)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 2
@@ -482,7 +632,7 @@ async def test_discovery_match_by_service_data_uuid_then_others(
# 8th discovery should not generate a flow
# since all fields have been seen at this point
inject_advertisement(
device, adv_with_service_data_uuid_and_mfr_data_and_service_uuid
hass, device, adv_with_service_data_uuid_and_mfr_data_and_service_uuid
)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
@@ -490,19 +640,19 @@ async def test_discovery_match_by_service_data_uuid_then_others(
# 9th discovery should not generate a flow
# since all fields have been seen at this point
inject_advertisement(device, adv_with_service_uuid)
inject_advertisement(hass, device, adv_with_service_uuid)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
# 10th discovery should not generate a flow
# since all fields have been seen at this point
inject_advertisement(device, adv_with_service_data_uuid)
inject_advertisement(hass, device, adv_with_service_data_uuid)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
# 11th discovery should not generate a flow
# since all fields have been seen at this point
inject_advertisement(device, adv_without_service_data_uuid)
inject_advertisement(hass, device, adv_without_service_data_uuid)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
@@ -546,7 +696,7 @@ async def test_discovery_match_first_by_service_uuid_and_then_manufacturer_id(
# 1st discovery with matches service_uuid
# should trigger config flow
inject_advertisement(device, adv_service_uuids)
inject_advertisement(hass, device, adv_service_uuids)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 1
assert mock_config_flow.mock_calls[0][1][0] == "my_domain"
@@ -554,19 +704,19 @@ async def test_discovery_match_first_by_service_uuid_and_then_manufacturer_id(
# 2nd discovery with manufacturer data
# should trigger a config flow
inject_advertisement(device, adv_manufacturer_data)
inject_advertisement(hass, device, adv_manufacturer_data)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 1
assert mock_config_flow.mock_calls[0][1][0] == "my_domain"
mock_config_flow.reset_mock()
# 3rd discovery should not generate another flow
inject_advertisement(device, adv_service_uuids)
inject_advertisement(hass, device, adv_service_uuids)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
# 4th discovery should not generate another flow
inject_advertisement(device, adv_manufacturer_data)
inject_advertisement(hass, device, adv_manufacturer_data)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 0
@@ -590,10 +740,10 @@ async def test_rediscovery(hass, mock_bleak_scanner_start, enable_bluetooth):
local_name="wohand", service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"]
)
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 1
@@ -601,7 +751,7 @@ async def test_rediscovery(hass, mock_bleak_scanner_start, enable_bluetooth):
async_rediscover_address(hass, "44:44:33:11:23:45")
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
assert len(mock_config_flow.mock_calls) == 2
@@ -633,10 +783,10 @@ async def test_async_discovered_device_api(
wrong_device = BLEDevice("44:44:33:11:23:42", "wrong_name")
wrong_adv = AdvertisementData(local_name="wrong_name", service_uuids=[])
inject_advertisement(wrong_device, wrong_adv)
inject_advertisement(hass, wrong_device, wrong_adv)
switchbot_device = BLEDevice("44:44:33:11:23:45", "wohand")
switchbot_adv = AdvertisementData(local_name="wohand", service_uuids=[])
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
wrong_device_went_unavailable = False
switchbot_device_went_unavailable = False
@@ -670,8 +820,8 @@ async def test_async_discovered_device_api(
assert wrong_device_went_unavailable is True
# See the devices again
inject_advertisement(wrong_device, wrong_adv)
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, wrong_device, wrong_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
# Cancel the callbacks
wrong_device_unavailable_cancel()
switchbot_device_unavailable_cancel()
@@ -688,10 +838,11 @@ async def test_async_discovered_device_api(
assert len(service_infos) == 1
# wrong_name should not appear because bleak no longer sees it
assert service_infos[0].name == "wohand"
assert service_infos[0].source == SOURCE_LOCAL
assert isinstance(service_infos[0].device, BLEDevice)
assert isinstance(service_infos[0].advertisement, AdvertisementData)
infos = list(service_infos)
assert infos[0].name == "wohand"
assert infos[0].source == SOURCE_LOCAL
assert isinstance(infos[0].device, BLEDevice)
assert isinstance(infos[0].advertisement, AdvertisementData)
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
@@ -736,25 +887,25 @@ async def test_register_callbacks(hass, mock_bleak_scanner_start, enable_bluetoo
service_data={"00000d00-0000-1000-8000-00805f9b34fb": b"H\x10c"},
)
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
empty_device = BLEDevice("11:22:33:44:55:66", "empty")
empty_adv = AdvertisementData(local_name="empty")
inject_advertisement(empty_device, empty_adv)
inject_advertisement(hass, empty_device, empty_adv)
await hass.async_block_till_done()
empty_device = BLEDevice("11:22:33:44:55:66", "empty")
empty_adv = AdvertisementData(local_name="empty")
# 3rd callback raises ValueError but is still tracked
inject_advertisement(empty_device, empty_adv)
inject_advertisement(hass, empty_device, empty_adv)
await hass.async_block_till_done()
cancel()
# 4th callback should not be tracked since we canceled
inject_advertisement(empty_device, empty_adv)
inject_advertisement(hass, empty_device, empty_adv)
await hass.async_block_till_done()
assert len(callbacks) == 3
@@ -819,25 +970,25 @@ async def test_register_callback_by_address(
service_data={"00000d00-0000-1000-8000-00805f9b34fb": b"H\x10c"},
)
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
empty_device = BLEDevice("11:22:33:44:55:66", "empty")
empty_adv = AdvertisementData(local_name="empty")
inject_advertisement(empty_device, empty_adv)
inject_advertisement(hass, empty_device, empty_adv)
await hass.async_block_till_done()
empty_device = BLEDevice("11:22:33:44:55:66", "empty")
empty_adv = AdvertisementData(local_name="empty")
# 3rd callback raises ValueError but is still tracked
inject_advertisement(empty_device, empty_adv)
inject_advertisement(hass, empty_device, empty_adv)
await hass.async_block_till_done()
cancel()
# 4th callback should not be tracked since we canceled
inject_advertisement(empty_device, empty_adv)
inject_advertisement(hass, empty_device, empty_adv)
await hass.async_block_till_done()
# Now register again with a callback that fails to
@@ -907,7 +1058,7 @@ async def test_register_callback_survives_reload(
service_data={"00000d00-0000-1000-8000-00805f9b34fb": b"H\x10c"},
)
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
assert len(callbacks) == 1
service_info: BluetoothServiceInfo = callbacks[0][0]
assert service_info.name == "wohand"
@@ -918,7 +1069,7 @@ async def test_register_callback_survives_reload(
await hass.config_entries.async_reload(entry.entry_id)
await hass.async_block_till_done()
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
assert len(callbacks) == 2
service_info: BluetoothServiceInfo = callbacks[1][0]
assert service_info.name == "wohand"
@@ -955,9 +1106,9 @@ async def test_process_advertisements_bail_on_good_advertisement(
service_data={"00000d00-0000-1000-8000-00805f9b34fa": b"H\x10c"},
)
inject_advertisement(device, adv)
inject_advertisement(device, adv)
inject_advertisement(device, adv)
inject_advertisement(hass, device, adv)
inject_advertisement(hass, device, adv)
inject_advertisement(hass, device, adv)
await asyncio.sleep(0)
@@ -997,14 +1148,14 @@ async def test_process_advertisements_ignore_bad_advertisement(
# The goal of this loop is to make sure that async_process_advertisements sees at least one
# callback that returns False
while not done.is_set():
inject_advertisement(device, adv)
inject_advertisement(hass, device, adv)
await asyncio.sleep(0)
# Set the return value and mutate the advertisement
# Check that scan ends and correct advertisement data is returned
return_value.set()
adv.service_data["00000d00-0000-1000-8000-00805f9b34fa"] = b"H\x10c"
inject_advertisement(device, adv)
inject_advertisement(hass, device, adv)
await asyncio.sleep(0)
result = await handle
@@ -1062,7 +1213,7 @@ async def test_wrapped_instance_with_filter(
)
scanner.register_detection_callback(_device_detected)
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
discovered = await scanner.discover(timeout=0)
@@ -1082,12 +1233,12 @@ async def test_wrapped_instance_with_filter(
assert len(discovered) == 0
assert discovered == []
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
assert len(detected) == 4
# The filter we created in the wrapped scanner with should be respected
# and we should not get another callback
inject_advertisement(empty_device, empty_adv)
inject_advertisement(hass, empty_device, empty_adv)
assert len(detected) == 4
@@ -1129,14 +1280,14 @@ async def test_wrapped_instance_with_service_uuids(
scanner.register_detection_callback(_device_detected)
for _ in range(2):
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
assert len(detected) == 2
# The UUIDs list we created in the wrapped scanner with should be respected
# and we should not get another callback
inject_advertisement(empty_device, empty_adv)
inject_advertisement(hass, empty_device, empty_adv)
assert len(detected) == 2
@@ -1177,9 +1328,9 @@ async def test_wrapped_instance_with_broken_callbacks(
)
scanner.register_detection_callback(_device_detected)
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
assert len(detected) == 1
@@ -1222,14 +1373,14 @@ async def test_wrapped_instance_changes_uuids(
scanner.register_detection_callback(_device_detected)
for _ in range(2):
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
assert len(detected) == 2
# The UUIDs list we created in the wrapped scanner with should be respected
# and we should not get another callback
inject_advertisement(empty_device, empty_adv)
inject_advertisement(hass, empty_device, empty_adv)
assert len(detected) == 2
@@ -1271,14 +1422,14 @@ async def test_wrapped_instance_changes_filters(
scanner.register_detection_callback(_device_detected)
for _ in range(2):
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
assert len(detected) == 2
# The UUIDs list we created in the wrapped scanner with should be respected
# and we should not get another callback
inject_advertisement(empty_device, empty_adv)
inject_advertisement(hass, empty_device, empty_adv)
assert len(detected) == 2
@@ -1333,7 +1484,7 @@ async def test_async_ble_device_from_address(
switchbot_device = BLEDevice("44:44:33:11:23:45", "wohand")
switchbot_adv = AdvertisementData(local_name="wohand", service_uuids=[])
inject_advertisement(switchbot_device, switchbot_adv)
inject_advertisement(hass, switchbot_device, switchbot_adv)
await hass.async_block_till_done()
assert (