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

6.8 KiB

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:

    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:

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.