Skip to content

About

Local Bluetooth integration for the hai smart showerhead in Home Assistant

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

Hai Smart Shower Head for Home Assistant

A custom Home Assistant integration for the hai smart showerhead. It listens for the shower head's Bluetooth wake advertisements and reads shower data over a local GATT connection — no cloud, no app account.

How it works

The shower head sleeps between showers and only advertises while water is running. This integration treats those advertisements as wake signals:

  1. Water runs → the shower head advertises → Home Assistant wakes the integration.
  2. The integration connects over BLE (directly or through an ESPHome Bluetooth proxy) and reads a full snapshot roughly every 10 seconds while the shower is active.
  3. When the shower ends, the device goes back to sleep. Live values become unavailable; lifetime and last-shower values stay available from cache, including across Home Assistant restarts.

Requirements

  • Home Assistant 2026.7.2 or newer (the version this release is tested against).
  • A Bluetooth adapter usable by Home Assistant, or an ESPHome Bluetooth proxy with active connections enabled, in range of the shower.
  • A shower head that has been paired at least once with the official hai app so it runs current firmware. Factory firmware exposes a different GATT layout and is not supported; polls against it fail with a "missing required characteristics" error in the logs.

Firmware support is based on the GATT layout observed on app-updated firmware (protocol notes). Optional characteristics (flow rate, battery voltage, lifetime average temperature) are probed per device, and their entities appear only when the firmware actually exposes them.

Installation

HACS (custom repository)

  1. In HACS, open ⋮ → Custom repositories.
  2. Add https://github.com/taylorfinnell/hai-homeassistant with category Integration.
  3. Install Hai Smart Shower Head and restart Home Assistant.

Manual

  1. Copy custom_components/hai/ from this repository into <config>/custom_components/hai/.
  2. Restart Home Assistant.

Upgrading from v1

There is no automatic upgrade path. v2 is a rewrite: entity unique IDs, units, and stored state all changed, and no migration is provided. Remove the old integration and add it again.

  1. In Settings → Devices & services, open the existing hai entry and delete it. This removes its device and all of its entities.
  2. Install v2 using one of the methods above and restart Home Assistant.
  3. Run the shower so the head advertises, then add the integration again (see First discovery below).

Recorded history for the v1 entities is not carried over, and any automations, scripts, or dashboard cards that referenced them need repointing at the new entities. Export anything you want to keep before deleting the integration.

First discovery

Run the shower for a little while. The shower head only advertises with water running, so discovery can take a minute; once seen, Home Assistant shows a discovered hai device under Settings → Devices & services. You can also add it manually via Add integration → hai while the water is running.

Entities

Entity Unit Kind Notes
Current shower temperature °C Live
Current shower average temperature °C Live Aggregate; no statistics
Current shower volume mL Live Resets per shower
Current shower duration s Live
Current shower started timestamp Live Only on firmware that exposes it
Flow rate L/min Live Only on firmware that exposes it
Lifetime volume L Retained Feeds the Water dashboard
Lifetime average temperature °C Retained Only on firmware that exposes it
Shower count — Retained Lifetime number of completed showers
Last shower temperature °C Retained
Last shower initial temperature °C Retained How cold the water was at the start
Last shower duration s Retained
Last shower volume mL Retained
Last shower started timestamp Retained
Battery voltage V Retained Diagnostic, disabled by default
Shower active on/off Activity See below
Level 1–4 colour, temperature colour #RRGGBB Config Writable — see below
First/second/third level threshold L Config Writable — see below

Live entities have values only while a shower is running and the integration has completed a fresh read for that shower. Between showers they are unavailable — that is by design, not a bug.

Retained entities keep their last value while the shower head sleeps and across Home Assistant restarts. No input_number persistence workaround is needed anymore.

Shower active turns on with the first wake advertisement. It turns off as soon as a reading reports that no session is in progress, or failing that when Home Assistant declares the device's advertisements stale — which can take several minutes after the water stops. Treat it as a convenience trigger for automations, never as a safety signal.

Water dashboard. Lifetime volume is a water sensor with long-term statistics, so it can be added under Settings → Dashboards → Water. The counter never resets: on firmware 6.11 it read 70,072 L across 1,039 showers, about 67 L each, matching that device's last-shower volume. A 32-bit millilitre counter holds roughly 4.29 million litres — some 63,000 more showers — and the sensor is declared in a way that tolerates a rollover regardless.

Device settings (experimental)

The shower head stores three consumption thresholds and five LED colours. They are read once per shower rather than on every poll, so they cost nothing during normal operation.

The head lights one of four colours according to how much water the running shower has used, with a fifth for temperature. Each is a text entity holding a #RRGGBB value, so setting one is a matter of typing a hex colour.

They are text entities rather than light entities on purpose. Home Assistant couples brightness to every RGB colour mode, so a light would carry a brightness slider that either does nothing or quietly rescales the stored colour — and five entities in the light domain would be swept up by any "turn off all the lights" automation, which here would write #000000 over your configuration.

The three consumption thresholds are writable number entities in litres. They bound the four colour bands: below the first threshold the head shows level 1, and above the third it shows level 4.

Contrary to the published protocol notes, this block is XOR-encrypted the same way the telemetry is. That was settled against firmware 6.11 using the composite e622150d record, which mirrors the individual characteristics and so decides them: e6221502 reads 00 02 03 04, decrypts to 1, and the record independently reports 1. Zero is a special case — the firmware returns plain zeros for unset values rather than the encrypted form.

Writes need a live Bluetooth connection, so they only work while water is running. Setting a threshold while the shower head is asleep fails immediately rather than queueing — a threshold that silently applied hours later would be worse than a clear error. A threshold that decodes to an impossible volume shows as unavailable, which also blocks writing to it.

Nothing in this integration can erase your shower history or factory-reset the device; those characteristics are deliberately not implemented.

If you want to check what your own firmware reports, download diagnostics from the device page: the settings block lists every configuration characteristic with its raw bytes and both candidate decodings.

Troubleshooting

  • Everything unavailable and the device never appears: the shower head only talks while water is running. Run the shower and watch Settings → Devices & services.
  • "Missing required characteristics" in the log: the shower head is on factory firmware. Pair it once with the official hai app to update.
  • Upgraded from v1 and old entities linger or everything is unavailable: v2 does not migrate v1 config entries. Delete the old integration entry and add it again — see Upgrading from v1.
  • A threshold is unavailable: its bytes decoded to a volume no shower could use, which usually means the encoding assumption is wrong for your firmware. Check the settings block in diagnostics.
  • Download diagnostics from the device page to see the last full snapshot, firmware versions (app and bootloader), and polling state.

Development

pip install -r requirements_test.txt
pytest tests/
ruff check .

Protocol details live in custom_components/hai/protocol.py behind a typed snapshot; its tests run without Home Assistant. The PoC script and GATT notes document the observed characteristic map.

Thanks

Thanks to @adizanni's Hydrao integration for the original inspiration for v1 of this integration.

About

Local Bluetooth integration for the hai smart showerhead in Home Assistant

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages