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
psutilandpaho-mqtt.
Wayland support is not currently implemented.
Configure a kiosk
-
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/ -
If no config exists yet, copy
runtime/config.exampleto~/.config/ha-kiosk/config; protect it withchmod 600. Edit the kiosk identifier, MQTT roots, dashboard URL, display/touchscreen values, and optional motion integration. TheKIOSK_IDtopic segment must match the segment used in the rendered HA package.KIOSK_ENTITY_PREFIXmust 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. -
Configure the system Mosquitto clients so
mosquitto_pubandmosquitto_subcan 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. -
If no systemd environment file exists yet, copy
runtime/systemd.env.exampleto~/.config/ha-kiosk/systemd.envand setKIOSK_IDandSTATUS_ROOTto matchconfig. This environment file is used by systemd for the availability service's orderly-stop publication. -
Install
ha-kiosk-browser.service,ha-kiosk-screen-control.service, andha-kiosk-availability.servicefromruntime/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. -
Run
systemctl --user daemon-reload, then enable and startha-kiosk-browser.service,ha-kiosk-screen-control.service, andha-kiosk-availability.service. -
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=alwaysservice, so restarting screen control does not take down the browser. - The availability watcher publishes retained
ON, while Mosquitto's Last Will publishes retainedOFFwhen 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.