Skip to content

Commit 55f6522

Browse files
authored
feat: speed up processing incoming service infos (#16)
1 parent 2566c02 commit 55f6522

File tree

4 files changed

+38
-31
lines changed

4 files changed

+38
-31
lines changed

src/habluetooth/advertisement_tracker.pxd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ cdef class AdvertisementTracker:
88
cdef public dict _timings
99

1010
@cython.locals(timings=list)
11-
cpdef async_collect(self, object service_info)
11+
cpdef void async_collect(self, object service_info)
12+
13+
cpdef void async_remove_address(self, object address)

src/habluetooth/advertisement_tracker.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
TRACKER_BUFFERING_WOBBLE_SECONDS = 5
1414

1515

16+
_str = str
17+
18+
1619
class AdvertisementTracker:
1720
"""Tracker to determine the interval that a device is advertising."""
1821

@@ -59,7 +62,7 @@ def async_collect(self, service_info: BluetoothServiceInfoBleak) -> None:
5962
self.intervals[address] = max_time_between_advertisements
6063
del self._timings[address]
6164

62-
def async_remove_address(self, address: str) -> None:
65+
def async_remove_address(self, address: _str) -> None:
6366
"""Remove the tracker."""
6467
self.intervals.pop(address, None)
6568
self.sources.pop(address, None)

src/habluetooth/manager.pxd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ cdef class BluetoothManager:
4343
cdef public bint shutdown
4444
cdef public object _loop
4545

46-
cdef bint _prefer_previous_adv_from_different_source(self, object old, object new)
46+
cdef bint _prefer_previous_adv_from_different_source(self, object address, object old, object new)
4747

4848
@cython.locals(source=str, connectable=bint, scanner=BaseHaScanner, connectable_scanner=BaseHaScanner)
4949
cpdef void scanner_adv_received(self, object service_info)

src/habluetooth/manager.py

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
APPLE_DEVICE_ID_START_BYTE,
4949
}
5050

51+
_str = str
5152

5253
_LOGGER = logging.getLogger(__name__)
5354

@@ -331,15 +332,16 @@ def _address_disappeared(self, address: str) -> None:
331332

332333
def _prefer_previous_adv_from_different_source(
333334
self,
335+
address: _str,
334336
old: BluetoothServiceInfoBleak,
335337
new: BluetoothServiceInfoBleak,
336338
) -> bool:
337339
"""Prefer previous advertisement from a different source if it is better."""
338340
if new.time - old.time > (
339341
stale_seconds := self._intervals.get(
340-
new.address,
342+
address,
341343
self._fallback_intervals.get(
342-
new.address, FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS
344+
address, FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS
343345
),
344346
)
345347
):
@@ -370,7 +372,7 @@ def _prefer_previous_adv_from_different_source(
370372
" old rssi:%s)"
371373
),
372374
new.name,
373-
new.address,
375+
address,
374376
self._async_describe_source(old),
375377
self._async_describe_source(new),
376378
new.rssi,
@@ -391,17 +393,16 @@ def scanner_adv_received(self, service_info: BluetoothServiceInfoBleak) -> None:
391393
if (
392394
(manufacturer_data := service_info.manufacturer_data)
393395
and APPLE_MFR_ID in manufacturer_data
394-
and manufacturer_data[APPLE_MFR_ID][0] not in APPLE_START_BYTES_WANTED
395396
and len(manufacturer_data) == 1
396397
and not service_info.service_data
398+
and manufacturer_data[APPLE_MFR_ID][0] not in APPLE_START_BYTES_WANTED
397399
):
398400
return
399401

400-
address = service_info.device.address
401-
all_history = self._all_history
402-
connectable = service_info.connectable
403-
connectable_history = self._connectable_history
404-
old_connectable_service_info = connectable and connectable_history.get(address)
402+
address = service_info.address
403+
old_connectable_service_info = None
404+
if connectable := service_info.connectable:
405+
old_connectable_service_info = self._connectable_history.get(address)
405406
source = service_info.source
406407
# This logic is complex due to the many combinations of scanners
407408
# that are supported.
@@ -420,19 +421,19 @@ def scanner_adv_received(self, service_info: BluetoothServiceInfoBleak) -> None:
420421
# connectable scanner
421422
#
422423
if (
423-
(old_service_info := all_history.get(address))
424-
and source != old_service_info.source
425-
and (scanner := self._sources.get(old_service_info.source))
424+
(old_service_info := self._all_history.get(address))
425+
and source != (old_source := old_service_info.source)
426+
and (scanner := self._sources.get(old_source))
426427
and scanner.scanning
427428
and self._prefer_previous_adv_from_different_source(
428-
old_service_info, service_info
429+
address, old_service_info, service_info
429430
)
430431
):
431432
# If we are rejecting the new advertisement and the device is connectable
432433
# but not in the connectable history or the connectable source is the same
433434
# as the new source, we need to add it to the connectable history
434435
if connectable:
435-
if old_connectable_service_info and (
436+
if old_connectable_service_info is not None and (
436437
# If its the same as the preferred source, we are done
437438
# as we know we prefer the old advertisement
438439
# from the check above
@@ -441,28 +442,29 @@ def scanner_adv_received(self, service_info: BluetoothServiceInfoBleak) -> None:
441442
# source, we need to check it as well to see if we prefer
442443
# the old connectable advertisement
443444
or (
444-
source != old_connectable_service_info.source
445+
(old_connectable_source := old_connectable_service_info.source)
446+
!= source
445447
and (
446448
connectable_scanner := self._sources.get(
447-
old_connectable_service_info.source
449+
old_connectable_source
448450
)
449451
)
450452
and connectable_scanner.scanning
451453
and self._prefer_previous_adv_from_different_source(
452-
old_connectable_service_info, service_info
454+
address, old_connectable_service_info, service_info
453455
)
454456
)
455457
):
456458
return
457459

458-
connectable_history[address] = service_info
460+
self._connectable_history[address] = service_info
459461

460462
return
461463

462464
if connectable:
463-
connectable_history[address] = service_info
465+
self._connectable_history[address] = service_info
464466

465-
all_history[address] = service_info
467+
self._all_history[address] = service_info
466468

467469
# Track advertisement intervals to determine when we need to
468470
# switch adapters or mark a device as unavailable
@@ -479,38 +481,38 @@ def scanner_adv_received(self, service_info: BluetoothServiceInfoBleak) -> None:
479481
# after unavailable callbacks.
480482
if (
481483
# Ensure its not a connectable device missing from connectable history
482-
not (connectable and not old_connectable_service_info)
484+
not (connectable and old_connectable_service_info is None)
483485
# Than check if advertisement data is the same
484-
and old_service_info
486+
and old_service_info is not None
485487
and not (
486-
service_info.manufacturer_data != old_service_info.manufacturer_data
488+
manufacturer_data != old_service_info.manufacturer_data
487489
or service_info.service_data != old_service_info.service_data
488490
or service_info.service_uuids != old_service_info.service_uuids
489491
or service_info.name != old_service_info.name
490492
)
491493
):
492494
return
493495

494-
if not connectable and old_connectable_service_info:
496+
if not connectable and old_connectable_service_info is not None:
495497
# Since we have a connectable path and our BleakClient will
496498
# route any connection attempts to the connectable path, we
497499
# mark the service_info as connectable so that the callbacks
498500
# will be called and the device can be discovered.
499501
service_info = BluetoothServiceInfoBleak(
500502
service_info.name,
501-
service_info.address,
503+
address,
502504
service_info.rssi,
503-
service_info.manufacturer_data,
505+
manufacturer_data,
504506
service_info.service_data,
505507
service_info.service_uuids,
506-
service_info.source,
508+
source,
507509
service_info.device,
508510
service_info.advertisement,
509511
True,
510512
service_info.time,
511513
)
512514

513-
if (connectable or old_connectable_service_info) and (
515+
if (connectable or old_connectable_service_info is not None) and (
514516
bleak_callbacks := self._bleak_callbacks
515517
):
516518
# Bleak callbacks must get a connectable device

0 commit comments

Comments
 (0)