- JavaScript 35.3%
- Python 32.3%
- Elm 22.7%
- HTML 9.7%
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0147wFhdfXHRGkmtz6D4hzZB |
||
|---|---|---|
| docs | ||
| proto | ||
| tools | ||
| web | ||
| .gitignore | ||
| LICENSE | ||
| README.md | ||
helium-air-ble
Local control of Helium air conditioners (sold in India, controlled by the Helium Smart Air app) with no vendor cloud — over Bluetooth Low Energy.
The BLE protocol has been fully reverse-engineered from the app. From it, two things get built:
- a Home Assistant integration, installable through HACS;
- a standalone Web Bluetooth web app.
Status
- Protocol — decoded and the read path verified live. Frame format, command
set, value encodings, status stream and the passkey handshake are mapped from
the app's serializer; status was then confirmed against a real unit through an
ESPHome proxy (power/mode/setpoint/fan/room-temp all decode correctly).
See
docs/protocol.md, with a runnable reference codec intools/helium_frames.jsand golden frames inproto/vectors.json. - How it was extracted —
docs/decompile.md. - Plan & design decisions —
docs/architecture.md(HACS integration over add-on; TypeScript site over Rust/WASM; share the spec + test vectors, not a compiled core). - Integration / web app — not built yet. One field datum gates control: the 4-digit passkey a given unit expects. Reading status needs no PIN.
The protocol in one screen
BLE command channel 0xB002 (write), status 0xB003 (notify), service 0xA00A,
scan by name prefix HELM. An AC command is a 25-byte-header frame with
cmdId = AC_CTRL (1003), the command in level[0], and the value in the payload:
POWER ON ff03eb 0001 0001 00000000 02 0000000000 00000001 00000000 00
TEMP 24 °C ff03eb 0001 0001 00000000 02 0200000000 00000001 00000000 18
MODE COOL ff03eb 0001 0001 00000000 02 0300000000 00000001 00000000 01
Control is gated behind a 4-digit passkey sent right after connecting. Status
comes back as 55aa-delimited Tuya-style datapoints, including live power draw
(0x1C). Full detail in docs/protocol.md.
Hardware this was captured from
| advertised name | HELM__9869 |
| model string | HELM0000015HMKP1ac |
| app | com.helium.mobileapp 1.0.1 (React Native / Hermes) |
| observed via | ESPHome bluetooth_proxy, ESP32 |
If your unit reports a different model string, please open an issue with the
output of tools/dump_gatt.py — and, if you can capture it,
the passkey exchange — so we can tell whether the protocol is shared across models.
Licence
GPL-3.0-only. See LICENSE.