Usage¶
Assuming that you’ve followed the installation steps, you’re now ready to use this package.
The SLZB proxy is scan only, so devices are discoverable through bleak but not
connectable.
Example usage with bleak:
from __future__ import annotations
import asyncio
import logging
import habluetooth
from bleak_smlight import SMLIGHTConnectionManager, SMLIGHTDeviceConfig
# An unlimited number of SLZB BLE proxies can be added here. ``source`` is a
# stable unique id for the proxy (typically its MAC address), ``host`` is the
# IP/hostname the UDP proxy server listens on, ``port`` is optional and
# defaults to 5050.
SMLIGHT_DEVICES: list[SMLIGHTDeviceConfig] = [
{"source": "AA:BB:CC:DD:EE:FF", "name": "slzb-1", "host": "10.0.0.5"},
{"source": "AA:BB:CC:DD:EE:00", "name": "slzb-2", "host": "10.0.0.6"},
]
async def example_app() -> None:
"""Example application here."""
import bleak
await asyncio.sleep(5) # Give time for advertisements to be received
# Use bleak normally here
devices = await bleak.BleakScanner.discover(return_adv=True)
for d, a in devices.values():
print()
print(d)
print("-" * len(str(d)))
print(a)
# Wait forever
await asyncio.Event().wait()
async def run() -> None:
"""Run the main application."""
managers = [SMLIGHTConnectionManager(device) for device in SMLIGHT_DEVICES]
await habluetooth.BluetoothManager().async_setup()
try:
# start() does not block on the device (the proxy client retries in
# the background), so gather them concurrently and let any real
# registration error surface instead of being swallowed.
await asyncio.gather(*(manager.start() for manager in managers))
await example_app()
finally:
await asyncio.gather(*(manager.stop() for manager in managers))
logging.basicConfig(level=logging.DEBUG)
asyncio.run(run())
Device configuration¶
Each proxy is described by a SMLIGHTDeviceConfig:
Key |
Required |
Description |
|---|---|---|
|
yes |
Stable unique id for the proxy, typically its MAC address. |
|
yes |
Human-friendly adapter name shown by |
|
yes |
IP or hostname the UDP proxy server listens on. |
|
no |
UDP port of the proxy server; defaults to |
SMLIGHTConnectionManager.start() returns once the scanner is registered and the
proxy client has been started; it does not block waiting for the device to
respond, because the underlying pysmlight.BleProxyClient retries in the
background. Call start() once per manager instance; a second call raises
RuntimeError. stop() is always safe to call, including before start().
Advanced: wiring connect_scanner directly¶
SMLIGHTConnectionManager is the recommended entry point: it builds the scanner,
registers it with habluetooth, starts the proxy client, and tears everything
down on stop(). Reach for connect_scanner only when you want to own the
scanner registration and proxy-client lifecycle yourself.
connect_scanner(source, name, host, port=SLZB_BLE_SERVER_PORT) builds a
SMLIGHTScanner plus a pysmlight.BleProxyClient wired to its advertisement
callback, and returns a SMLIGHTClientData. It leaves three jobs to the caller:
Call
data.scanner.async_setup()to attach the scanner to the running loop.Register the scanner with the host-side Bluetooth manager (and unregister it on teardown).
await data.client.start()to begin receiving advertisements, anddata.client.stop()on teardown.
import habluetooth
import bleak_smlight
data = bleak_smlight.connect_scanner(
"AA:BB:CC:DD:EE:FF", "slzb-1", "10.0.0.5"
)
unsetup = data.scanner.async_setup()
unregister = habluetooth.get_manager().async_register_scanner(data.scanner)
await data.client.start()
# Later, on teardown:
data.client.stop()
unregister()
unsetup()