Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backends/scanner: always filter by service_uuids #1559

Merged
merged 1 commit into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Fixed
* Fixed using wrong value for ``tx_power`` in Android backend. Fixes #1532.
* Fixed 4-character UUIDs not working on ``BleakClient.*_gatt_char`` methods. Fixes #1498.
* Fixed race condition with getting max PDU size on Windows. Fixes #1497.
* Fixed filtering advertisement data by service UUID when multiple apps are scanning. Fixes #1534.

`0.21.1`_ (2023-09-08)
======================
Expand Down
18 changes: 18 additions & 0 deletions bleak/backends/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,24 @@ def call_detection_callbacks(
Backend implementations should call this method when an advertisement
event is received from the OS.
"""

# Backends will make best effort to filter out advertisements that
# don't match the service UUIDs, but if other apps are scanning at the
# same time or something like that, we may still receive advertisements
# that don't match. So we need to do more filtering here to get the
# expected behavior.

if self._service_uuids:
if not advertisement_data.service_uuids:
return

for uuid in advertisement_data.service_uuids:
if uuid in self._service_uuids:
break
else:
# if there were no matching service uuids, the don't call the callback
return

for callback in self._ad_callbacks.values():
callback(device, advertisement_data)

Expand Down
19 changes: 5 additions & 14 deletions bleak/backends/winrt/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ def __init__(
else:
self._scanning_mode = BluetoothLEScanningMode.ACTIVE

# Unfortunately, due to the way Windows handles filtering, we can't
# make use of the service_uuids filter here. If we did we would only
# get the advertisement data or the scan data, but not both, so would
# miss out on other essential data. Advanced users can pass their own
# filters though if they want to.
self._signal_strength_filter = kwargs.get("SignalStrengthFilter", None)
self._advertisement_filter = kwargs.get("AdvertisementFilter", None)

Expand Down Expand Up @@ -198,20 +203,6 @@ def _received_handler(
bdaddr, local_name, raw_data, advertisement_data
)

# On Windows, we have to fake service UUID filtering. If we were to pass
# a BluetoothLEAdvertisementFilter to the BluetoothLEAdvertisementWatcher
# with the service UUIDs appropriately set, we would no longer receive
# scan response data (which commonly contains the local device name).
# So we have to do it like this instead.

if self._service_uuids:
for uuid in uuids:
if uuid in self._service_uuids:
break
else:
# if there were no matching service uuids, the don't call the callback
return

self.call_detection_callbacks(device, advertisement_data)

def _stopped_handler(self, sender, e):
Expand Down
Loading