# Home Assistant integration

> Connect Kiosky to Home Assistant over MQTT, every entity it creates, example automations in YAML, and the Assist voice satellite.

Kiosky works with Home Assistant in three ways, which you can mix:

1. **Dashboard sign-in and theme**: the tablet shows your HA dashboard, logged in with a long-lived token. See [Dashboards & browser](dashboards.md#home-assistant).
2. **MQTT with discovery**: the tablet appears in HA as a device with sensors, switches, buttons and more, and accepts commands. This page covers it.
3. **Voice**: the tablet is an Assist satellite with an on-device wake word. See [Voice and Assist](#voice-and-assist) below.

MQTT is not required. The same commands are also available over the local [REST API](rest-api.md), which you can call from HA with `rest_command`.

## Set up MQTT

You need an MQTT broker that Home Assistant also uses, for example the Mosquitto add-on with the MQTT integration. Create a broker user for the tablet.

1. On the tablet open **Settings, Connections, MQTT**.
2. Turn on **Enable MQTT**.
3. Fill in **Broker host**, **Port** (default 1883; use 8883 with TLS) and, if your broker requires it, **Username** and **Password**.
4. Turn on **TLS** if your broker uses it.
5. Leave **Base topic** as `kiosk` unless you need another prefix.
6. Leave **Home Assistant discovery** on (the default).
7. Tap **Save MQTT**. The status chip goes from **Connecting** to **Connected**, or shows the error.

A saved password shows "A password is saved. Leave blank to keep it." and **Remove password** clears it. The card also shows the topic prefix it will use, for example `kiosk/hallway_tablet/...`.

The tablet appears in Home Assistant under **Settings, Devices & services, MQTT** with the name you set in **Settings, Device, Device name**. The device id used in topics is a lower-case slug of that name with underscores, for example `Hallway Tablet` becomes `hallway_tablet`. Renaming the device changes every topic; Kiosky clears the retained messages left under the old id.

> **Security.** An anonymous broker lets anyone on your network read state and send commands. Use a broker account and TLS. Kiosky shows warnings under **Lock & security, Security** when the broker is anonymous or has no TLS. See [Security](security.md).

IP address and Wi-Fi signal are published (and their sensors created) only when the connection uses a **Username**, or when you turn on **Share IP and Wi-Fi over MQTT** under **Lock & security, Security**.

## Entities

Kiosky publishes retained discovery configs on `homeassistant/<component>/<device_id>/<object_id>/config`, so HA creates the entities by itself. Every entity belongs to one device, whose **Visit** link opens the tablet's admin page, and goes unavailable when the tablet goes offline.

Some entities appear only when they apply: hardware that exists, features you switched on, or remote control you allowed.

| Entity | Component / object id | Appears when | Notes |
|---|---|---|---|
| Screen | `light` / `screen` | always | On/off and brightness 0 to 255. |
| Screensaver | `switch` / `screensaver` | always | On while the screensaver shows. |
| Kiosk lock | `switch` / `kiosk_lock` | remote unlock allowed | On is locked. Off pauses the lock for 60 minutes. |
| Volume | `number` / `volume` | always | 0 to 100 %. |
| Reload | `button` / `reload` | always | Reloads the page. |
| Restart app | `button` / `restart_app` | remote unlock allowed |  |
| Relaunch app | `button` / `relaunch_app` | remote unlock allowed and single-app mode | Reopens the configured app. |
| Speak | `notify` / `tts` | always | Speaks the message on the tablet. |
| Load URL | `text` / `load_url` | always | Shows the current URL; setting it navigates. |
| Event | `event` / `event` | always | See [event types](#events). |
| Dashboard | `select` / `dashboard` | at least one dashboard | Options are your dashboard names. |
| Battery | `sensor` / `battery` | device has a battery | Percent. |
| Charging | `binary_sensor` / `charging` | device has a battery |  |
| Charging wanted | `binary_sensor` / `charging_wanted` | device has a battery | Battery care: on means charge now. |
| Battery temperature | `sensor` / `battery_temperature` | reported by device | Degrees C. |
| Light level | `sensor` / `light_level` | light sensor | Lux. |
| Proximity | `binary_sensor` / `proximity` | proximity sensor | Occupancy class. |
| Motion | `binary_sensor` / `motion` | camera ready | Camera-based. |
| Camera snapshot | `image` / `snapshot` | camera ready | The latest JPEG. |
| Take snapshot | `button` / `take_snapshot` | camera ready |  |
| Presence | `binary_sensor` / `presence` | face presence on | Someone is in view, never who. |
| Tamper | `binary_sensor` / `tamper` | tamper detection on | Tablet moved. |
| Current URL | `sensor` / `current_url` | always | Truncated to 255 characters. |
| Wi-Fi signal | `sensor` / `wifi_signal` | network info shared | Diagnostic, dBm. |
| IP address | `sensor` / `ip_address` | network info shared | Diagnostic. |
| Uptime | `sensor` / `uptime` | always | Diagnostic, seconds. |
| Memory free | `sensor` / `memory_free` | always | Diagnostic, MB. |
| Storage free | `sensor` / `storage_free` | always | Diagnostic, MB. |
| App version | `sensor` / `app_version` | always | Diagnostic. |
| WebView version | `sensor` / `webview_version` | always | Diagnostic. |
| Memory trim events | `sensor` / `memory_trim_count` | always | Diagnostic. |
| Last interaction | `sensor` / `last_interaction` | always | Diagnostic, timestamp. |
| Microphone | `switch` / `microphone` | voice on | Privacy switch for the mic. |
| Voice state | `sensor` / `voice_state` | voice on | `off`, `idle`, `listening`, `processing`, `responding`. |
| Last voice command | `sensor` / `voice_last_command` | voice on and sharing on | The transcript. Turn off under **Voice** for privacy. |
| Wake word | `event` / `wake_word` | voice on | Fires `wake_word_heard`. |

Entity unique ids look like `kiosky_<device_id>_<object_id>`.

### Events

The **Event** entity mirrors `kiosk/<device_id>/event`. Its event types are:

| Type | When |
|---|---|
| `command_rejected` | A command was refused. Attributes `command` and `reason`. |
| `exit_gesture` | Someone tapped the exit corner. |
| `wrong_pin` | A wrong admin PIN. Attributes `attempts_left` or `locked_out`. |
| `page_error` | The page failed to load. |
| `popup_shown` | A popup appeared. Attribute `host` (URL popups) or `cameras` (count). |
| `popup_dismissed` | A popup closed. Adds `reason`. |
| `audio_error` | Audio could not play. |
| `device_moved` | Tamper detection fired. |
| `kiosk_paused` | The lock was paused. Attribute `until` (an ISO time or `indefinite`). |
| `kiosk_resumed` | The lock returned. Attribute `reason`: `timeout`, `user`, `remote` or `idle`. |

## Example automations

These examples publish to the tablet's command topics. Replace `hallway_tablet` with your device id, which is shown at the top of **Settings, Connections, MQTT** (the "Topics:" line). The YAML uses the Home Assistant 2024.10 format (`triggers:`, `actions:`, `trigger:`, `action:`).

### Show the door camera when someone is at the door

```yaml
automation:
  - alias: Hallway tablet shows front door camera
    triggers:
      - trigger: state
        entity_id: binary_sensor.front_door_person
        to: "on"
    actions:
      - action: mqtt.publish
        data:
          topic: kiosk/hallway_tablet/cmd/popup
          payload: >-
            {"camera": "camera.front_door", "timeout": 30, "title": "Front door"}
```

`camera` takes one entity id or an array of up to four (`["camera.front_door", "camera.driveway"]`). `timeout` is in seconds (default 60, up to 3600) and `title` is optional. The popup needs the Home Assistant address and token saved under **Dashboard, Home Assistant sign-in**. It wakes the screen, and you can close it with `dismiss_popup`:

```yaml
      - delay: "00:00:30"
      - action: mqtt.publish
        data:
          topic: kiosk/hallway_tablet/cmd/dismiss_popup
          payload: ""
```

To show a web page instead of a camera, send a URL: `{"url": "https://example.com/alert", "timeout": 20}`. The host must be an allowed host.

### Wake the screen when someone arrives

```yaml
automation:
  - alias: Hallway tablet wakes on presence
    triggers:
      - trigger: state
        entity_id: binary_sensor.hallway_motion
        to: "on"
    actions:
      - action: mqtt.publish
        data:
          topic: kiosk/hallway_tablet/cmd/screen
          payload: "on"
```

If you enable face presence on the tablet itself, use its **Presence** entity as the trigger instead. Or tick **Wake screen on face** or **Wake screen on motion** in the app, see [Camera & sensors](camera-sensors.md).

### Make the tablet speak

```yaml
automation:
  - alias: Announce laundry done
    triggers:
      - trigger: state
        entity_id: sensor.washer_state
        to: "finished"
    actions:
      - action: mqtt.publish
        data:
          topic: kiosk/hallway_tablet/cmd/tts
          payload: '{"text": "The washing machine has finished.", "volume": 60}'
```

`volume` is optional (0 to 100). The **Speak** notify entity does the same through `notify.send_message`. Speech comes from the tablet's own Android text-to-speech engine.

### Switch dashboard at a set time

```yaml
automation:
  - alias: Evening dashboard
    triggers:
      - trigger: time
        at: "18:00:00"
    actions:
      - action: select.select_option
        target:
          entity_id: select.hallway_tablet_dashboard
        data:
          option: Evening
```

You can also publish `{"name": "Evening"}` or just `Evening` to `kiosk/hallway_tablet/cmd/dashboard`. For fixed daily windows, the built-in [planner](dashboards.md#planner) needs no automation.

### React to someone moving the tablet

```yaml
automation:
  - alias: Tablet tamper alert
    triggers:
      - trigger: state
        entity_id: binary_sensor.hallway_tablet_tamper
        to: "on"
    actions:
      - action: notify.mobile_app_phone
        data:
          message: The hallway tablet was moved.
```

Entity ids such as `select.hallway_tablet_dashboard` are chosen by Home Assistant from the device and entity names. Check the real id in **Settings, Devices & services, Entities**.

## Voice and Assist

Kiosky can be a voice satellite for Home Assistant Assist. A wake word runs on the tablet, and audio is only sent to Home Assistant after the wake word is heard.

**Requirements**

- A Home Assistant with an Assist pipeline that has speech-to-text and text-to-speech (Home Assistant Cloud, or local Whisper and Piper).
- The Home Assistant address and a long-lived token.
- The microphone permission.

**Settings, Voice, Voice assistant**

1. Turn on **Enable voice**.
2. Enter the **Home Assistant URL** and **Long-lived access token** (Profile, Security in HA). The token is stored encrypted. **Remove token** deletes it.
3. Optionally enter an **Assist pipeline id**. Blank uses your preferred pipeline.
4. Tap **Allow microphone** and grant the permission.
5. Choose a **Wake word**: Okay Nabu (the default), Hey Jarvis or Hey Mycroft.
6. Adjust **Wake threshold**. Lower wakes more easily and falsely more often. Higher needs a clearer wake word. Each model has its own default.
7. Tap **Save voice**. A status chip tells you whether Kiosky is listening and why not, for example "Paused while the screen is off".

| Toggle | Default | Effect |
|---|---|---|
| Microphone | On | A privacy switch, also in Home Assistant as the **Microphone** switch. |
| Listen only while the screen is on | On | |
| Listen only while charging | Off | |
| Chime on wake word | On | |
| Show what was heard | On | Shows the transcript on screen. |
| Share last command with Home Assistant | On | Publishes the transcript as a sensor. |

Short commands are handled on the tablet without a round trip to Home Assistant. They are matched against the whole sentence, in English: "screen off", "go home", "volume up", "volume down", "set volume to 40", "stop", "reload", and "show <dashboard name>". Anything else goes to your Assist pipeline, and the spoken answer plays on the tablet.

> **Note.** Wake word accuracy depends on microphone distance and room noise. There is no pipeline picker yet, so enter the pipeline id by hand. Voice needs a Home Assistant address that uses a certificate trusted by Android; self-signed HTTPS is not supported for the voice connection. Voice is among the candidate [Kiosky Pro](pro.md) features.
