Files
ha-kiosk-mqtt-control/README.md
T

144 lines
6.8 KiB
Markdown

# HA Kiosk MQTT Control
Reusable Linux/X11 touchscreen kiosk controls for Home Assistant over MQTT. The
project combines local display and brightness management, a restartable browser,
retained MQTT state and availability, and a Home Assistant package for controls.
The reference installation is a Dell portrait touchscreen kiosk. Device values
are configurable so the same controls can be deployed to other kiosks.
## Features
- Display modes: Screen Lock, Screen Off, Screensaver, and Screen On.
- Touch and optional camera-motion wake, shared presence timer and brightness ramp.
- Current/presence brightness, volume, mute, and physical display state.
- Periodic retained-state publication to recover Home Assistant entities after a
broker retained-store reset.
- MQTT heartbeat watchdog that restarts the screen-control service when its
command subscriber has stopped receiving messages.
- Separate Chrome systemd service with automatic restart.
- Retained availability with Last Will.
- Optional performance telemetry and MQTT Discovery sensors.
## Requirements
- Linux desktop session running X11 (the included touch and DPMS controls use X11).
- Google Chrome/Chromium and a kiosk dashboard URL.
- `mosquitto-clients`, `xinput`, `brightnessctl`, `xset`, `xscreensaver`,
`wpctl`, `stdbuf`, `awk`, `grep`, and Bash.
- A Home Assistant MQTT integration and an MQTT broker reachable from the kiosk.
- Optional camera motion service publishing the configured motion state topic.
- Optional telemetry: Python 3 with `psutil` and `paho-mqtt`.
Wayland support is not currently implemented.
## Configure a kiosk
1. Create the per-user directories, then copy the scripts and units into place:
```sh
install -d -m 700 ~/.config/ha-kiosk
install -d ~/.local/lib/ha-kiosk-mqtt-control ~/.config/systemd/user
cp runtime/*.sh ~/.local/lib/ha-kiosk-mqtt-control/
chmod 755 ~/.local/lib/ha-kiosk-mqtt-control/*.sh
cp runtime/*.service ~/.config/systemd/user/
```
2. If no config exists yet, copy `runtime/config.example` to
`~/.config/ha-kiosk/config`; protect it with `chmod 600`. Edit the kiosk
identifier, MQTT roots, dashboard URL, display/touchscreen values, and optional
motion integration. The `KIOSK_ID` topic segment must match the segment used
in the rendered HA package. `KIOSK_ENTITY_PREFIX` must match the package's
`--entity-prefix` (and is used by optional telemetry). Preserve an existing
config when upgrading rather than replacing it with the example.
3. Configure the system Mosquitto clients so `mosquitto_pub` and
`mosquitto_sub` can reach the same broker as Home Assistant. The control and
availability shell scripts currently call those standard clients without
passing authentication flags; use a broker/network policy that allows the
kiosk's client connection, or integrate a credential-safe client wrapper
appropriate to your broker. Do not put passwords in this repository or in
command-line arguments. The optional Python telemetry publisher accepts
broker credentials from its protected systemd environment file.
4. If no systemd environment file exists yet, copy
`runtime/systemd.env.example` to `~/.config/ha-kiosk/systemd.env` and set
`KIOSK_ID` and `STATUS_ROOT` to match `config`. This environment file is used
by systemd for the availability service's orderly-stop publication.
5. Install `ha-kiosk-browser.service`, `ha-kiosk-screen-control.service`, and
`ha-kiosk-availability.service` from `runtime/` into
`~/.config/systemd/user/`. Before enabling the browser unit, disable any
existing desktop/autostart entry that launches the same browser, so there is
only one browser service owner.
6. Run `systemctl --user daemon-reload`, then enable and start
`ha-kiosk-browser.service`, `ha-kiosk-screen-control.service`, and
`ha-kiosk-availability.service`.
7. Enable lingering for the kiosk user if user services must run before login:
`sudo loginctl enable-linger "$USER"`.
The screen-control script reads `~/.config/ha-kiosk/config`. The browser launcher
reads the same file for `KIOSK_URL`, display and Chrome profile values, and touch
mapping values. Systemd environment files use systemd syntax, not shell sourcing.
## Home Assistant package
Render the MQTT entities from the parameterized package template:
```sh
python3 home-assistant/render-package.py \
--name "My Kiosk" \
--entity-prefix my_kiosk \
--command-root kiosk/commands/my_kiosk \
--status-root kiosk/status/my_kiosk \
--manufacturer Generic \
--model "Linux Touchscreen Kiosk" \
--output /path/to/homeassistant/packages/my_kiosk.yaml
```
The `--command-root` and `--status-root` values are full per-device MQTT topic
roots (including the device segment). They should equal `COMMAND_ROOT/KIOSK_ID`
and `STATUS_ROOT/KIOSK_ID` from the kiosk config. The example uses the neutral
`kiosk/commands` and `kiosk/status` namespaces. The generated package provides the
MQTT controls, availability, and diagnostic entities. Add it to a Home Assistant
package directory and validate the HA configuration before reloading the MQTT
integration or restarting Home Assistant. Existing dashboards and automations may refer to the entity IDs, so
review those references when changing the entity prefix.
The package expects the kiosk to publish the topics rooted at the supplied
command/status roots. It uses MQTT retained availability and has no secrets.
## Optional telemetry
Copy `telemetry/telemetry.env.example` to
`~/.config/ha-kiosk/telemetry.env`, set the broker values, and protect it with
`chmod 600`. Copy `telemetry/kiosk-telemetry.service` into
`~/.config/systemd/user/`, then reload systemd and enable
`kiosk-telemetry.service`. Keep the real environment file out of Git;
`.gitignore` excludes it. Telemetry uses Home Assistant MQTT Discovery.
## Recovery behavior
- All control and diagnostic states are republished retained every 30 seconds.
- A non-retained control heartbeat is sent on the same cadence. If the command
subscriber does not return the heartbeat within 90 seconds, systemd restarts
screen control.
- Chrome runs in a separate `Restart=always` service, so restarting screen
control does not take down the browser.
- The availability watcher publishes retained `ON`, while Mosquitto's Last Will
publishes retained `OFF` when the connection is lost.
## Updating
Back up the per-device configuration and current scripts, install the new
version, run `bash -n` on shell scripts, reload user systemd, and restart the
services individually. Check `systemctl --user status` and the retained MQTT
state topics after the update.
## License
This project is licensed under the GNU General Public License, version 3 or any
later version. See `LICENSE`.
## Credentials and repository
Never commit MQTT credentials, SSH private keys, Home Assistant tokens, or a
real per-kiosk config. The Gitea repository is public, so keep secrets and actual
per-kiosk settings out of commits.