55 lines
1.9 KiB
Python

"""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())