Documentation
Lighting Controllers
Source:
controllers/lighting/README.md
The controllers.lighting package provides application-agnostic interfaces,
state models, test doubles, and hardware adapters for lighting devices.
Package layout
controllers/lighting/
├── __init__.py
├── lighting_controller_if.py
├── lighting_types.py
├── lighting_controller_stub.py
├── dummy_lighting_controller.py
├── adapters/
│ └── leddmx_bluetooth_controller.py
├── parsers/
│ └── leddmx_config_parser.py
└── component_test/
└── test_dummy_lighting_controller.py
protocols/leddmx/
└── leddmx_protocol.py
config/lighting/
└── leddmx.toml
Controller choices
LightingControllerStub
A silent deterministic implementation of LightingControllerIf.
Use it when a consumer requires a lighting controller but the test does not care about lighting behavior. Commands immediately return successful completed futures and do not mutate state.
DummyLightingController
A stateful in-memory emulator.
Use it for UI development, component tests, and demonstrations where callers
need to inspect LightingState after commands are issued.
LedDmxBluetoothController
The hardware adapter for LEDDMX-compatible Bluetooth Low Energy controllers.
It owns a background asyncio event loop and exposes thread-friendly
concurrent.futures.Future objects to synchronous callers such as Tkinter.
Python dependency
Install Bleak:
python3 -m pip install bleak
Bleak is the Bluetooth Low Energy GATT client used by the LEDDMX adapter.
Linux system dependencies
Bleak’s Linux backend communicates with BlueZ over D-Bus. Install BlueZ and ensure the Bluetooth service is running.
Debian, Ubuntu, and Raspberry Pi OS:
sudo apt update
sudo apt install bluez
sudo systemctl enable --now bluetooth
Confirm the adapter is visible:
bluetoothctl list
The current Bleak documentation requires a Linux distribution with BlueZ 5.55 or newer.
LEDDMX configuration
The BLE service UUID, write characteristic UUID, discovery exclusions, and timing options are stored in:
PROJECT_ROOT/config/lighting/leddmx.toml
Example:
[bluetooth]
service_uuid = "0000ffe0-0000-1000-8000-00805f9b34fb"
characteristic_uuid = "0000ffe1-0000-1000-8000-00805f9b34fb"
excluded_service_uuids = [
"00001101-0000-1000-8000-00805f9b34fb",
]
write_with_response = false
command_delay_seconds = 0.05
reconnect_delay_seconds = 0.25
scan_timeout_seconds = 15.0
candidate_connect_timeout_seconds = 8.0
[discovery]
excluded_name_fragments = ["konnwei"]
Load it explicitly:
from controllers.lighting.parsers.leddmx_config_parser import load_leddmx_config
from controllers.lighting.adapters import LedDmxBluetoothController
config = load_leddmx_config()
controller = LedDmxBluetoothController(
address=None,
config=config,
)
When address is omitted, the adapter scans nearby BLE devices and checks for
the configured write characteristic.
Basic usage
from controllers.lighting import RgbColor
from controllers.lighting.adapters import LedDmxBluetoothController
controller = LedDmxBluetoothController()
try:
controller.connect().result(timeout=20)
controller.set_power(True).result(timeout=5)
controller.set_color(
RgbColor(255, 120, 0)
).result(timeout=5)
controller.set_brightness(75).result(timeout=5)
finally:
controller.close()
Testing
python3 -m unittest controllers.lighting.component_test.test_dummy_lighting_controller
The protocol and configuration parser should also have independent tests as the package grows.