(usage)= # Usage Assuming that you've followed the {ref}`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`: ```python 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 | | -------- | -------- | ------------------------------------------------------------------------ | | `source` | yes | Stable unique id for the proxy, typically its MAC address. | | `name` | yes | Human-friendly adapter name shown by `habluetooth`. | | `host` | yes | IP or hostname the UDP proxy server listens on. | | `port` | no | UDP port of the proxy server; defaults to `SLZB_BLE_SERVER_PORT` (5050). | `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: 1. Call `data.scanner.async_setup()` to attach the scanner to the running loop. 2. Register the scanner with the host-side Bluetooth manager (and unregister it on teardown). 3. `await data.client.start()` to begin receiving advertisements, and `data.client.stop()` on teardown. ```python 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() ```