Home Assistant Windows Kiosk – An open-source Windows webpage kiosk designed for integration with Home Assistant. Prevents access to the typical Windows UI without pin access and publishes MQTT commands and sensors to Home Assistant. Configurable gestures for reload, clear cache, send MQTT message, and more.
- Download the .exe file from the latest release and once downloaded double click/open to install. It will automatically install .NET 8 if needed.
- On first run, Settings will open. Enter your kiosk webpage URL, MQTT host, port, username, password, and other details as needed.
- Click Save & Back to Kiosk – the fullscreen kiosk will load your HA dashboard or chosen URL.
- Click the gear button to open Settings (If you've disabled show settings button use a configured gesture with action set to
settings, or MQTTopensettings). Use Exit to Windows in Settings to quit the app.
I recommend checking out my setup if you want to sleep/wake your kiosk, use autologin, or have a Surface Pro 3.
- Windows 10/11
- .NET 8 Runtime (Desktop) (the installer will install this automatically if not already present)
- WebView2 Runtime (usually pre-installed on Windows 11)
- WebView zoom is blocked (pinch zoom and Ctrl+wheel zoom).
- WebView back/forward swipe navigation is blocked.
- Kiosk window keeps itself topmost and fullscreen, hides the Windows taskbar while running, and restores the taskbar when the app exits.
- Windows key, context-menu key, Alt+F4, Alt+Tab, F11, F12, Ctrl+Esc, and Ctrl+Shift+Esc are intercepted while the kiosk is running. A limitation of running inside Windows Explorer is that the start menu WILL still come up on windows key and swipe up from bottom.
With MQTT configured, the app publishes MQTT payloads that show up in Integrations > MQTT in Home Assistant. In the app Settings, under MQTT, turn Sensors and Commands on or off for which buttons and sensors are discovered.
Entity IDs in HA include your device name (sanitized). Names below match the name field in discovery.
| Name in HA | Type | Description |
|---|---|---|
| Shutdown | Button | Shut down Windows |
| Restart | Button | Restart Windows |
| System sleep | Button | Suspend the PC (S3 sleep) |
| Monitor sleep | Button | Turn the display off |
| Monitor wake | Button | Turn the display on |
| Refresh kiosk | Button | Reload the page in the kiosk |
| Clear kiosk cache | Button | Clear kiosk cache (passwords & settings kept), then reload kiosk |
| Open settings | Button | Open this app’s Settings screen (no PIN) |
| Close settings | Button | Close Settings and return to the kiosk |
| Run Windows updates | Button | Starts a Windows Update scan/download/install run; app schedules restart if Windows Update reports reboot required |
| PowerShell command | Button | Executes configured PowerShell command text from settings |
| Battery level | Sensor | Remaining battery % (unavailable on desktops without a battery) |
| Last Active | Sensor | Seconds since last input (updates every 1 second, ignoring the update interval) |
| Updates pending | Number | Count of available Windows updates |
| Monitor brightness | Number | Brightness % (0–100) |
When enabled, HA WinKiosk acts as a Wyoming satellite. It captures microphone audio, sends it to your wake word software, and uses Home Assistant Assist for processing via the voice assistant flow. Speech-to-text and text-to-speech can be handled by Whisper and Piper or your choice of software, then the response audio is played back on the kiosk. The kiosk will need to have a static ip set so it can be added in home assistant.
I will not be providing a full tutorial on how to set this up (Maybe in the future)
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#16B9F0', 'primaryTextColor':'#ffffff', 'primaryBorderColor':'#16B9F0', 'lineColor':'#16B9F0', 'secondaryColor':'#B9E9FF', 'tertiaryColor':'#E8F7FD'}}}%%
flowchart TD
A[HA WinKiosk Mic] --> B[OpenWakeWord]
B --> C[Whisper STT]
C --> D[Home Assistant Assist]
D --> E[Piper TTS]
E --> F[Response Audio]
F --> G[HA WinKiosk Speaker]
Details
-
OpenWakeWord (wake word detection) docker container: https://github.com/rhasspy/wyoming-openwakeword
-
Whisper (speech-to-text) docker container: https://github.com/rhasspy/wyoming-whisper
-
Piper (text-to-speech) docker container: https://github.com/rhasspy/wyoming-piper
-
Wyoming integration docker container: https://my.home-assistant.io/redirect/integration/?domain=wyoming
Details
-
OpenWakeWord app (wake word detection): https://my.home-assistant.io/redirect/supervisor_addon/?addon=core_openwakeword
-
Whisper app (speech-to-text): https://my.home-assistant.io/redirect/supervisor_addon/?addon=core_whisper
-
Piper app (text-to-speech): https://my.home-assistant.io/redirect/supervisor_addon/?addon=core_piper
-
Wyoming integration: https://my.home-assistant.io/redirect/integration/?domain=wyoming
Settings are stored at %APPDATA%\HA-WinKiosk\settings.yaml. Settings can be edited either in YAML or in the UI. Older layouts are migrated to the new shape the next time settings are saved.
Below is a key of what all the options are, and below that is an example settings.yaml.
| UI Name | Values | Notes | Published to HA via MQTT? |
|---|---|---|---|
| Kiosk URL | URL | Kiosk page URL | No |
| Ignore HTTPS cert warnings | true/false |
Auto-allow invalid/self-signed TLS certs for the kiosk URL | No |
| Do Not Disturb | true/false |
Suppress toast notifications while the kiosk is running | No |
| Beta updates | true/false |
When true, automatic updates may install GitHub prereleases; when false, only stable releases |
No |
| Show settings button | true/false |
Show/hide gear button | No |
| Theme | auto | light | dark |
UI theme mode | No |
| Brightness (%) | config.brightnessPercent |
0..100 |
Startup screen brightness |
| Start when Windows starts | config.autoStartEnabled |
true/false |
Launch app at sign-in |
| Playback device | config.playbackDeviceId |
string (MMDevice ID) | Default / empty = do not change the Windows default playback device; otherwise sets default output to the chosen device on startup |
| Input device | config.inputDeviceId |
string (MMDevice ID) | Default / empty = Windows default capture device; otherwise the chosen microphone by device ID |
| Volume (%) | config.volumePercent |
0..100 |
Master volume for the playback device the kiosk uses |
| Settings PIN | string | PIN required when PIN protection is enabled. Doesn't have to be numbers. | No |
| PIN hint | string | Hint shown on PIN prompt | No |
| Verification question | string | Forgot-PIN verification question | No |
| PIN reset answer | string | Forgot-PIN verification answer | No |
| PIN protection | true/false |
false disables PIN gate |
No |
| UI Name | Values | Notes | Published to HA via MQTT? |
|---|---|---|---|
| Double tap action | Disabled | Reload | Clear cache and reload | Settings | MQTT message |
Action for double tap | Indirect (when MQTT message) |
| Double tap location | Top left | Top right | Bottom right | Bottom left | Anywhere |
Double-tap screen region | No |
| Double tap MQTT topic | string | Topic suffix when action is MQTT message | Yes |
| Triple tap action | Disabled | Reload | Clear cache and reload | Settings | MQTT message |
Action for triple tap | Indirect (when MQTT message) |
| Triple tap location | Top left | Top right | Bottom right | Bottom left | Anywhere |
Triple-tap screen region | No |
| Triple tap MQTT topic | string | Topic suffix when action is MQTT message | Yes |
| Quadruple tap action | Disabled | Reload | Clear cache and reload | Settings | MQTT message |
Action for quadruple tap | Indirect (when MQTT message) |
| Quadruple tap location | Top left | Top right | Bottom right | Bottom left | Anywhere |
Quadruple-tap screen region | No |
| Quadruple tap MQTT topic | string | Topic suffix when action is MQTT message | Yes |
| Quintuple tap action | Disabled | Reload | Clear cache and reload | Settings | MQTT message |
Action for quintuple tap | Indirect (when MQTT message) |
| Quintuple tap location | Top left | Top right | Bottom right | Bottom left | Anywhere |
Quintuple-tap screen region | No |
| Quintuple tap MQTT topic | string | Topic suffix when action is MQTT message | Yes |
| Swipe action | Disabled | Reload | Clear cache and reload | Settings | MQTT message |
Action for swipe | Indirect (when MQTT message) |
| Swipe direction | Down | Left | Right |
Swipe direction filter | No |
| Swipe MQTT topic | string | Topic suffix when action is MQTT message | Yes |
| Swipe and hold action | Disabled | Reload | Clear cache and reload | Settings | MQTT message |
Action for swipe-and-hold | Indirect (when MQTT message) |
| Swipe and hold direction | Down | Left | Right |
Swipe-and-hold direction filter | No |
| Swipe and hold threshold (milliseconds) | integer (ms) | Hold threshold for swipe-and-hold | No |
| Swipe and hold MQTT topic | string | Topic suffix when action is MQTT message | Yes |
| Two-finger swipe action | Disabled | Reload | Clear cache and reload | Settings | MQTT message |
Touch devices only | Indirect (when MQTT message) |
| Two-finger swipe direction | Down | Left | Right |
Touch devices only | No |
| Two-finger swipe MQTT topic | string | Touch devices only | Yes |
| Two-finger swipe and hold action | Disabled | Reload | Clear cache and reload | Settings | MQTT message |
Touch devices only | Indirect (when MQTT message) |
| Two-finger swipe and hold direction | Down | Left | Right |
Touch devices only | No |
| Two-finger swipe and hold threshold (milliseconds) | integer (ms) | Hold threshold for two-finger swipe-and-hold | No |
| Two-finger swipe and hold MQTT topic | string | Touch devices only | Yes |
| Pinch action | Disabled | Reload | Clear cache and reload | Settings | MQTT message |
Action for pinch-in gesture | Indirect (when MQTT message) |
| Pinch MQTT topic | string | Topic suffix when action is MQTT message | Yes |
| Zoom action | Disabled | Reload | Clear cache and reload | Settings | MQTT message |
Action for zoom gesture | Indirect (when MQTT message) |
| Zoom direction | Any | In | Out |
Zoom gesture direction filter | No |
| Zoom MQTT topic | string | Topic suffix when action is MQTT message | Yes |
| Min swipe distance (pixels) | integer (≥ 20 enforced on load) | Minimum swipe length in pixels before a swipe counts (default 80). Not exposed in the Settings UI. | No |
| UI Name | Values | Notes | Published to HA via MQTT? |
|---|---|---|---|
| MQTT IP | hostname/IP | Broker host | No |
| MQTT port | integer | Broker port | No |
| MQTT username | string | Broker username | No |
| MQTT password | string | Broker password | No |
| Device name | string | Base ID in MQTT entities/topics | No |
| Discovery prefix | string | MQTT discovery prefix for Home Assistant (default homeassistant) |
No |
| Sensor: Battery level | On/Off |
Publishes battery percentage | Yes |
| Sensor: Last Active | On/Off |
Publishes seconds since last input (1s cadence) | Yes |
| Sensor: Updates pending | On/Off |
Publishes Windows update count | Yes |
| Command: Shutdown | On/Off |
Exposes Shutdown MQTT button | Yes |
| Command: Restart | On/Off |
Exposes Restart MQTT button | Yes |
| Command: System sleep | On/Off |
Exposes Sleep MQTT button | Yes |
| Command: Monitor sleep | On/Off |
Exposes Monitor sleep MQTT button | Yes |
| Command: Monitor wake | On/Off |
Exposes Monitor wake MQTT button | Yes |
| Command: Refresh kiosk | On/Off |
Exposes Refresh MQTT button | Yes |
| Command: Clear kiosk cache | On/Off |
Exposes Clear cache MQTT button | Yes |
| Command: Open settings | On/Off |
Exposes Open settings MQTT button | Yes |
| Command: Close settings | On/Off |
Exposes Close settings MQTT button | Yes |
| Command: Run Windows updates | On/Off |
Exposes Windows updates MQTT button | Yes |
| Command: PowerShell command | On/Off |
Exposes custom PowerShell MQTT button | Yes |
| PowerShell command text | string | Command text for powershellcommand MQTT command | Yes |
| (YAML only) | mqtt.sensors.updateIntervalSeconds |
integer ≥ 5 | How often battery and updates_pending refresh. last_active still updates every 1 second when enabled. |
| UI name | YAML key | Values | Notes |
|---|---|---|---|
| Voice Assist | voiceAssist.enabled |
true/false |
Master switch for Wyoming satellite mode |
| Wyoming Host PC | voiceAssist.wyomingHostPc |
hostname/IP | Host running the Wyoming wake service (e.g. Docker rhasspy/wyoming-openwakeword). If empty, the app may derive a host from the kiosk URL. |
| Wyoming Host PC port | voiceAssist.wyomingHostPcPort |
integer | Wyoming port on that host (commonly 10400 for openWakeWord / wyoming-openwakeword) |
| Wake word delay | voiceAssist.wakeWordDelay |
seconds (≥ 0) | Minimum time before the same wake word fires again |
| Wake word model names | voiceAssist.wakeWordNames |
list of strings (UI: comma-separated) | Sent to openWakeWord in the Wyoming detect event. |
config:
url: "http://homeassistant.local:8123"
ignoreCertificateErrors: false
doNotDisturb: true
pin: ""
pinHint: ""
pinResetQuestion: ""
pinResetAnswer: ""
pinProtectionDisabled: false
showSettingsButton: true
uiTheme: auto
betaUpdates: false
playbackDeviceId: ""
inputDeviceId: ""
volumePercent: 100
brightnessPercent: 100
autoStartEnabled: true
gestures:
doubleTapAction: disabled
doubleTapLocation: top-left
doubleTapMqttTopic: "double_tap"
tripleTapAction: disabled
tripleTapLocation: top-left
tripleTapMqttTopic: "triple_tap"
quadrupleTapAction: settings
quadrupleTapLocation: top-left
quadrupleTapMqttTopic: "quadruple_tap"
quintupleTapAction: disabled
quintupleTapLocation: top-left
quintupleTapMqttTopic: "quintuple_tap"
swipeAction: reload
swipeDirection: down
swipeMqttTopic: "swipe"
twoFingerSwipeAction: disabled
twoFingerSwipeDirection: down
twoFingerSwipeMqttTopic: "two_finger_swipe"
swipeHoldAction: clearcache_reload
swipeHoldDirection: down
swipeHoldMs: 1000
swipeHoldMqttTopic: "swipe_hold"
twoFingerSwipeHoldAction: disabled
twoFingerSwipeHoldDirection: down
twoFingerSwipeHoldMs: 1000
twoFingerSwipeHoldMqttTopic: "two_finger_swipe_hold"
pinchAction: disabled
pinchMqttTopic: "pinch"
zoomAction: disabled
zoomDirection: any
zoomMqttTopic: "zoom"
minSwipePixels: 80
mqtt:
host: "192.168.1.?"
port: 1883
username: ""
password: ""
deviceName: "kiosk"
discoveryPrefix: "homeassistant"
sensors:
enabled:
- battery
- last_active
- updates_pending
updateIntervalSeconds: 30
commands:
enabled:
- shutdown
- restart
- sleep
- monitorsleep
- monitorwake
- refresh
- clearcache
- opensettings
- closesettings
- windowsupdate
powerShellCommand: ""
voiceAssist:
enabled: false
wyomingHostPc: ""
wyomingHostPcPort: 10400
wakeWordDelay: 5
wakeWordNames: []The app checks daily at 3:00 AM local device time for any updates. If a newer version is found, it downloads the installer, silently replaces the old app, and relaunches the new version.
If beta updates are enabled, it will download the latest update, even if it is a pre-release. If disabled, it will download the latest stable release.
The app will always open upon boot, first using Task Scheduler then falling back to being a Startup app if that fails.
HASS.Agent 2.0 (hass-agent, forked from LAB02-Research) was heavily leaned on for implementation of sensors and commands, and in the case of monitor wake/sleep, directly mirrored. Go check out this amazing program if you're just looking for sensors and commands without a kiosk!
