"""Diagnostic BLE scan: list nearby devices and flag likely Shining Masks. No connection is made -- this only listens for advertisements, so it is safe to run any time:: python examples/scan.py """ import asyncio from bleak import BleakScanner import constants as C async def main(timeout: float = 12.0): print(f"Scanning {timeout:.0f}s for BLE devices " f"(looking for name '{C.DEVICE_NAME_PREFIX}*' or service {C.SERVICE_UUID})...\n") found = await BleakScanner.discover(timeout=timeout, return_adv=True) rows = [] masks = [] for address, (dev, adv) in found.items(): name = adv.local_name or dev.name or "(no name)" svcs = [s.lower() for s in (adv.service_uuids or [])] is_mask = ( str(name).upper().startswith(C.DEVICE_NAME_PREFIX) or C.SERVICE_UUID.lower() in svcs or any("fff0" in s for s in svcs) ) rows.append((adv.rssi if adv.rssi is not None else -999, dev.address, name, svcs, is_mask)) if is_mask: masks.append((dev.address, name)) for rssi, address, name, svcs, is_mask in sorted(rows, reverse=True): flag = " <== LIKELY MASK" if is_mask else "" print(f" {address} rssi={rssi:>4} name={name!r} services={svcs}{flag}") print() if masks: print("Likely mask(s) found:") for address, name in masks: print(f" address={address} name={name!r}") print("\nConnect with, e.g.:") print(f" python cli.py --address {masks[0][0]} light 80") else: print("No mask detected. Checklist:") print(" * Power the mask on (and take it out of the phone app / disconnect the app).") print(" * REMOVE it from the OS Bluetooth settings if you tried to 'pair' it there.") print(" * Make sure Bluetooth is on and no other process holds the adapter.") if __name__ == "__main__": asyncio.run(main())