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

Discovery filter #565

Merged
merged 9 commits into from
Jun 7, 2021
28 changes: 26 additions & 2 deletions bleak/backends/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ def __repr__(self) -> str:
Optional[Awaitable[None]],
]

AdvertisementDataFilter = Callable[
[BLEDevice, Optional[AdvertisementData]],
dlech marked this conversation as resolved.
Show resolved Hide resolved
bool,
]


class BaseBleakScanner(abc.ABC):
"""Interface for Bleak Bluetooth LE Scanners"""
Expand Down Expand Up @@ -195,10 +200,29 @@ async def find_device_by_address(

"""
device_identifier = device_identifier.lower()
return await cls.find_device_by_filter(lambda d, ad : d.address.lower() == device_identifier)

@classmethod
async def find_device_by_filter(
cls, filterfunc: AdvertisementDataFilter, timeout: float = 10.0, **kwargs
) -> Optional[BLEDevice]:
"""A convenience method for obtaining a ``BLEDevice`` object specified by a filter function.

Args:
filterfunc (AdvertisementDataFilter): A function that is called for every BLEDevice found. It should return True only for the wanted device.
timeout (float): Optional timeout to wait for detection of specified peripheral before giving up. Defaults to 10.0 seconds.

Keyword Args:
adapter (str): Bluetooth adapter to use for discovery.

Returns:
The ``BLEDevice`` sought or ``None`` if not detected.

"""
stop_scanning_event = asyncio.Event()

def stop_if_detected(d: BLEDevice, ad: AdvertisementData):
if d.address.lower() == device_identifier:
if filterfunc(d, ad):
stop_scanning_event.set()

async with cls(
Expand All @@ -211,5 +235,5 @@ def stop_if_detected(d: BLEDevice, ad: AdvertisementData):
return next(
d
for d in scanner.discovered_devices
if d.address.lower() == device_identifier
if filterfunc(d, None)
)
3 changes: 3 additions & 0 deletions examples/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import asyncio
import platform
import sys

from bleak import BleakScanner

Expand All @@ -19,6 +20,8 @@
if platform.system() != "Darwin"
else "B9EA5233-37EF-4DD6-87A8-2A875E821C46" # <--- Change to your device's address here if you are using macOS
)
if len(sys.argv) == 2:
address = sys.argv[1]
jackjansen marked this conversation as resolved.
Show resolved Hide resolved


async def run():
Expand Down
30 changes: 30 additions & 0 deletions examples/scanner_byname.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
Bleak Scanner
-------------



Updated on 2020-08-12 by hbldh <henrik.blidh@nedomkull.com>

"""

import asyncio
import platform
import sys

from bleak import BleakScanner


if len(sys.argv) != 2:
print(f'Usage: {sys.argv[0]} name')
sys.exit(1)
wanted_name = sys.argv[1].lower()


async def run():
device = await BleakScanner.find_device_by_filter(lambda d, ad : d.name and d.name.lower() == wanted_name)
print(device)


loop = asyncio.get_event_loop()
loop.run_until_complete(run())
dlech marked this conversation as resolved.
Show resolved Hide resolved