mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-04 14:25:08 +00:00
Optional web login, off by default: a device that sets no password behaves exactly as before. Set under General > Security; then every page and API route needs a session login or an API token (Authorization: Bearer). Loopback, the Wi-Fi setup flow in AP mode, static files, captive-portal probes and a reduced /api/v3/health stay open. Secrets live in the web_auth section of config_secrets.json and no API returns them. scripts/reset_web_password.py turns login off. Stacked on #674. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
131 lines
5.3 KiB
Markdown
131 lines
5.3 KiB
Markdown
# Home Assistant MQTT Bridge
|
||
|
||
Control the matrix from Home Assistant: force any plugin or mode on demand,
|
||
turn the display on and off, and set brightness — as real HA entities, not
|
||
hand-written `mqtt.publish` calls.
|
||
|
||
The bridge owns no display logic. It subscribes to one command topic and
|
||
turns each message into a call against the same `api_v3` routes the web UI
|
||
uses, so behaviour lives in one place. It talks to the API over HTTP only —
|
||
no filesystem access — so it can run on the Pi or anywhere that can reach
|
||
the web interface.
|
||
|
||
## What appears in Home Assistant
|
||
|
||
On connect the bridge publishes [MQTT Discovery](https://www.home-assistant.io/integrations/mqtt/#mqtt-discovery)
|
||
config, so the matrix shows up under **Settings → Devices & Services → MQTT**
|
||
with no YAML:
|
||
|
||
| Entity | Does |
|
||
|---|---|
|
||
| `select.ledmatrix_display_mode` | Every mode across enabled plugins. Choosing one force-displays it. |
|
||
| `button.ledmatrix_stop_display` | Back to normal rotation. |
|
||
| `switch.ledmatrix_power` | Starts/stops the display service. |
|
||
| `number.ledmatrix_brightness` | 0–100. |
|
||
|
||
State is read back from the API every 30 seconds, so the entities also track
|
||
changes made from the web UI or an on-demand window expiring on its own.
|
||
All four share an availability topic that is the bridge's MQTT last will:
|
||
if the bridge dies, HA greys the controls out rather than leaving them
|
||
looking live but inert.
|
||
|
||
## Raw commands
|
||
|
||
For anything the entities do not cover, publish JSON to the command topic
|
||
(`ledmatrix/command` by default):
|
||
|
||
```jsonc
|
||
// Force a mode. plugin_id is optional — the bridge fills it in from
|
||
// /api/v3/display/modes.
|
||
{"action": "display", "mode": "nfl_live"}
|
||
|
||
// duration is seconds; pinned holds this one mode instead of rotating
|
||
// through every mode the plugin owns. Pin Starlark apps, where each mode
|
||
// is an unrelated widget; leave a sports plugin unpinned so live/recent/
|
||
// upcoming still cycle.
|
||
{"action": "display", "plugin_id": "starlark-apps", "mode": "aquarium",
|
||
"duration": 300, "pinned": true}
|
||
|
||
{"action": "stop_display"}
|
||
{"action": "power", "state": "on"}
|
||
{"action": "brightness", "value": 75}
|
||
|
||
// Re-read the mode list and re-publish discovery, after installing a plugin
|
||
{"action": "refresh"}
|
||
```
|
||
|
||
Every command publishes its outcome to `<command_topic>/status`, and current
|
||
state to `<command_topic>/state`.
|
||
|
||
## Requirements
|
||
|
||
- A LEDMatrix install with its web interface reachable (default `http://localhost:5000`)
|
||
- An MQTT broker that Home Assistant is also connected to
|
||
- Python 3 with `paho-mqtt` 2.x and `requests`
|
||
|
||
## Install
|
||
|
||
```bash
|
||
sudo ./scripts/install/install_mqtt_bridge.sh
|
||
```
|
||
|
||
That copies `bridge_config.example.json` to `bridge_config.json` on first
|
||
run, installs the dependencies, and enables `ledmatrix-mqtt-bridge.service`.
|
||
Edit the config with your broker details and re-run it.
|
||
|
||
```json
|
||
{
|
||
"mqtt_host": "192.168.1.10",
|
||
"mqtt_port": 8883,
|
||
"mqtt_username": "ledmatrix",
|
||
"mqtt_password": null,
|
||
"mqtt_topic": "ledmatrix/command",
|
||
"mqtt_tls": true,
|
||
"ledmatrix_api_base": "http://localhost:5000"
|
||
}
|
||
```
|
||
|
||
**TLS is on by default.** Without it the broker password and every display
|
||
command cross the network in cleartext. If your broker only listens on plain
|
||
1883 — which the Mosquitto add-on does out of the box — set `"mqtt_tls": false`
|
||
and `"mqtt_port": 1883`. The bridge logs a warning at startup when a password
|
||
is configured without TLS.
|
||
|
||
`bridge_config.json` is gitignored. Any key can also be supplied through the
|
||
environment as `LEDMATRIX_MQTT_<KEY>` (`LEDMATRIX_MQTT_MQTT_PASSWORD`, say),
|
||
which keeps a broker password out of a file on disk — put it in a systemd
|
||
drop-in with `Environment=` or `EnvironmentFile=` instead.
|
||
|
||
**Web login.** If the web interface's optional login is on (General >
|
||
Security), a bridge running on the Pi itself still needs nothing: requests from
|
||
the Pi are never asked to log in. A bridge on another machine needs an API
|
||
token: create one under General > Security and set `"ledmatrix_api_token"`
|
||
(or `LEDMATRIX_MQTT_LEDMATRIX_API_TOKEN`, or the token field in the Tools tab's
|
||
bridge settings). It is sent as `Authorization: Bearer <token>`.
|
||
|
||
Set `mqtt_tls: true` for a broker with TLS. `mqtt_tls_insecure` skips
|
||
certificate verification and exists only for a self-signed broker on a
|
||
trusted LAN; it logs a warning when used.
|
||
|
||
To run it in the foreground while setting things up:
|
||
|
||
```bash
|
||
python3 integrations/mqtt_bridge/ledmatrix_mqtt_bridge.py --config integrations/mqtt_bridge/bridge_config.json
|
||
```
|
||
|
||
## Notes
|
||
|
||
- Only one thing can be on-demand at a time — the same constraint the web UI has.
|
||
- Forcing a mode restarts the display service, so the panel blanks for a moment.
|
||
- The mode list comes from `/api/v3/display/modes`, which triggers plugin
|
||
discovery itself. Discovery is lazy and normally happens because somebody
|
||
opened the dashboard; without that endpoint a bridge that never does would
|
||
see an empty list.
|
||
- Brightness writes `display.hardware.brightness` by posting
|
||
`{"brightness": N}` to `/api/v3/config/main`. A JSON save changes only the
|
||
keys it sends, so the other display settings are left as they were. The
|
||
display service's config hot reload notices the change within a few seconds
|
||
and applies it without a restart (unless `LEDMATRIX_HOT_RELOAD=false`; while
|
||
a dim schedule is dimming the panel, the dim level wins until the dim period
|
||
ends).
|