Skip to content

Commit 9f56840

Browse files
authored
feat: improve performance of filtering apple data (#188)
1 parent 69f1587 commit 9f56840

File tree

3 files changed

+66
-13
lines changed

3 files changed

+66
-13
lines changed

src/habluetooth/manager.pxd

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ cdef object BLEDevice
1414
cdef bint TYPE_CHECKING
1515
cdef set APPLE_START_BYTES_WANTED
1616

17+
cdef unsigned char APPLE_IBEACON_START_BYTE
18+
cdef unsigned char APPLE_HOMEKIT_START_BYTE
19+
cdef unsigned char APPLE_HOMEKIT_NOTIFY_START_BYTE
20+
cdef unsigned char APPLE_DEVICE_ID_START_BYTE
21+
cdef unsigned char APPLE_FINDMY_START_BYTE
22+
1723
cdef object APPLE_MFR_ID
1824

1925
@cython.locals(uuids=set)
@@ -73,7 +79,7 @@ cdef class BluetoothManager:
7379
connectable=bint,
7480
scanner=BaseHaScanner,
7581
connectable_scanner=BaseHaScanner,
76-
apple_data=bytes,
82+
apple_cstr="const unsigned char *",
7783
bleak_callback=BleakCallback
7884
)
7985
cpdef void scanner_adv_received(self, BluetoothServiceInfoBleak service_info)

src/habluetooth/manager.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,7 @@
6262
APPLE_DEVICE_ID_START_BYTE: Final = 0x10 # bluetooth_le_tracker
6363
APPLE_HOMEKIT_NOTIFY_START_BYTE: Final = 0x11 # homekit_controller
6464
APPLE_FINDMY_START_BYTE: Final = 0x12 # FindMy network advertisements
65-
APPLE_START_BYTES_WANTED: Final = {
66-
APPLE_IBEACON_START_BYTE,
67-
APPLE_HOMEKIT_START_BYTE,
68-
APPLE_HOMEKIT_NOTIFY_START_BYTE,
69-
APPLE_DEVICE_ID_START_BYTE,
70-
APPLE_FINDMY_START_BYTE,
71-
}
65+
7266

7367
_str = str
7468

@@ -509,13 +503,19 @@ def scanner_adv_received(self, service_info: BluetoothServiceInfoBleak) -> None:
509503
# Pre-filter noisy apple devices as they can account for 20-35% of the
510504
# traffic on a typical network.
511505
if (
512-
len(service_info.manufacturer_data) == 1
513-
and not service_info.service_data
506+
not service_info.service_data
507+
and len(service_info.manufacturer_data) == 1
514508
and (apple_data := service_info.manufacturer_data.get(APPLE_MFR_ID))
515-
is not None
516-
and apple_data[0] not in APPLE_START_BYTES_WANTED
517509
):
518-
return
510+
apple_cstr = apple_data
511+
if apple_cstr[0] not in {
512+
APPLE_IBEACON_START_BYTE,
513+
APPLE_HOMEKIT_START_BYTE,
514+
APPLE_HOMEKIT_NOTIFY_START_BYTE,
515+
APPLE_DEVICE_ID_START_BYTE,
516+
APPLE_FINDMY_START_BYTE,
517+
}:
518+
return
519519

520520
if service_info.connectable:
521521
old_connectable_service_info = self._connectable_history.get(

tests/test_base_scanner.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,3 +593,50 @@ async def test_merge_manufacturer_data_history_new() -> None:
593593

594594
cancel()
595595
unsetup()
596+
597+
598+
@pytest.mark.usefixtures("enable_bluetooth")
599+
@pytest.mark.asyncio
600+
async def test_filter_apple_data() -> None:
601+
"""Test filtering apple data accepts bytes that start with 01."""
602+
manager = get_manager()
603+
604+
device = generate_ble_device(
605+
"44:44:33:11:23:45",
606+
"",
607+
{},
608+
rssi=-60,
609+
)
610+
device_adv = generate_advertisement_data(
611+
local_name="",
612+
rssi=-60,
613+
manufacturer_data={
614+
76: b"\x01\r.\xa9\xb6",
615+
},
616+
service_uuids=["ef090000-11d6-42ba-93b8-9dd7ec090ab0"],
617+
service_data={},
618+
)
619+
620+
connector = HaBluetoothConnector(
621+
MockBleakClient, "mock_bleak_client", lambda: False
622+
)
623+
scanner = FakeScanner("esp32", "esp32", connector, True)
624+
details = scanner.details
625+
assert details == HaScannerDetails(
626+
source=scanner.source,
627+
connectable=scanner.connectable,
628+
name=scanner.name,
629+
adapter=scanner.adapter,
630+
)
631+
unsetup = scanner.async_setup()
632+
cancel = manager.async_register_scanner(scanner)
633+
634+
scanner.inject_advertisement(device, device_adv)
635+
636+
data = scanner.discovered_devices_and_advertisement_data
637+
discovered_device, discovered_adv_data = data[device.address]
638+
assert discovered_device.address == device.address
639+
assert discovered_device.name == device.name
640+
assert discovered_adv_data.manufacturer_data == device_adv.manufacturer_data
641+
unsetup()
642+
cancel()

0 commit comments

Comments
 (0)