Architecture

This page explains what bleak-smlight does, where the SMLIGHT BLE proxy is implemented, and how the pieces fit together. If you only want to use the library, see Usage.

What this library is, and what it is not

bleak-smlight is the glue layer that lets a Python application receive Bluetooth Low Energy (BLE) advertisements from a SMLIGHT SLZB-U BLE proxy, an ESP32-S3 running SLZB-OS. It does not implement the proxy itself. The proxy is firmware on the device that exposes a small UDP server; this library is the host-side client that consumes that server’s advertisement stream.

The proxy is scan only. It relays raw BLE advertisements but has no GATT/active-connection support, so this library registers a non-connectable scanner and provides no Bleak client.

The split is:

Layer

Where it lives

Repository

SLZB firmware (UDP BLE proxy server)

On the SLZB-U device (ESP32)

SLZB-OS

Python UDP client for the proxy

Host (your app)

smlight-tech/pysmlight

bleak-compatible scanner on top of pysmlight

Host (your app)

this repo

Remote-scanner bookkeeping primitives

Host (your app)

Bluetooth-Devices/habluetooth

Standard BLE scanner API consumed by user code

Host (your app)

hbldh/bleak

So when you call bleak.BleakScanner.discover(...) in an app that has set up a SMLIGHTConnectionManager, what really happens is:

  1. The SLZB device scans for BLE advertisements over the air.

  2. The proxy server forwards each advertisement to your host over Wi-Fi via UDP.

  3. pysmlight.BleProxyClient parses the UDP packet and invokes its callback with the device MAC, RSSI, address type, and raw advertisement bytes.

  4. bleak-smlight’s SMLIGHTScanner._handle_raw_advertisement forwards those values into habluetooth.

  5. bleak’s discovery code sees those advertisements as if they had been seen by a local adapter.

There is no reverse path: the proxy cannot open GATT connections, so devices are discoverable but not connectable.

Where the proxy is implemented

Short answer: not here. The BLE proxy is part of the SLZB-OS firmware that runs on the SLZB-U hardware. It exposes a UDP server (default port 5050) that streams advertisements to a host. The wire protocol and the host-side client (BleProxyClient) live in pysmlight.

What this repository contains:

  • src/bleak_smlight/connection_manager.pySMLIGHTConnectionManager, the convenience wrapper that builds a scanner, registers it with habluetooth, and starts the BleProxyClient.

  • src/bleak_smlight/connect.pyconnect_scanner(), which builds a SMLIGHTScanner plus a pysmlight.BleProxyClient wired to its advertisement callback, and returns them as a SMLIGHTClientData.

  • src/bleak_smlight/backend/scanner.pySMLIGHTScanner, a remote scanner that feeds advertisements received from the proxy into habluetooth.

Connection lifecycle and retries

BleProxyClient owns its own connect/retry loop. start() returns immediately after kicking off a background task that pings the proxy, waits for an ACK, and retries with exponential backoff if the device is unreachable. Because of this, SMLIGHTConnectionManager.start() does not block on the first successful contact; the scanner is registered up front and begins reporting advertisements as soon as packets arrive.

stop() tears down in order: it stops the proxy client (which sends a disconnect packet and closes the UDP socket), unregisters the scanner from habluetooth, and runs the scanner’s own teardown callback.

Who can use it

The library has no Home Assistant dependency. It is plain Python, built on asyncio, and works in any host environment that can reach the SLZB device over UDP and run bleak and habluetooth. The practical entry point is SMLIGHTConnectionManager plus a list of SMLIGHTDeviceConfig entries, as shown in Usage.

See also