# 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.