- New entities: number (salt output level 0-10), switch (lights, jets); the read-only salt sensor is replaced by the settable number. - Look identical to the official app on the wire: send the app's Dalvik UA on REST, okhttp/4.12.0 on the mTLS creds fetch, and "mqtt-<uuid>" client ids. - Consolidate every constant value into constants.py (well commented); protocol.py keeps only the command builders; const.py removed. - Optional local read path: a `local_status_url` config option polls the dongle's local /status endpoint for telemetry instead of the cloud MQTT subscription (control stays cloud MQTT). State getters handle both schemas. No private/internal values in the repo (the spa IP is runtime config only). Fixes bug-41mqxddz7zeh Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F6B8b3iYNv6QUftK2FDfYb
3.6 KiB
Hot Spring Connected Spa — Home Assistant integration
Monitor and control a Watkins / Hot Spring "Connected Spa" hot tub from Home Assistant, without the vendor mobile app.
- Climate — target setpoint + current water temperature (heater).
- Number — FreshWater salt output level (0–10), settable.
- Switches — spa lights (all zones) and jets.
- Sensors — water temperature, salt cartridge state.
- Live telemetry over the vendor's HiveMQ Cloud MQTT broker, or — optionally —
polled from the spa's local
/statusendpoint (see below).
Requests are sent with the same User-Agents and MQTT client-id format the official app uses, so the traffic is indistinguishable from it.
This is an unofficial integration reverse-engineered from the official app. It talks to Watkins' cloud; there is no local control path. If Watkins changes their API it may break.
Security / credentials
This repository contains no secrets:
- Your account e-mail + password are entered in the config-flow UI when you add the integration and stored in Home Assistant's encrypted config entry — never in this repo.
- The vendor mutual-TLS client certificate required to fetch broker credentials is Watkins material (extractable from the app APK). It is not redistributed here. You provide it as three PEM files on the host (below).
Prerequisites: the client certificate
The integration needs three files in a directory on the Home Assistant host
(default /config/hotspring/certs/):
| File | Origin |
|---|---|
client1_cert.pem |
client cert from the app APK (res/raw/client1.p12) |
client1_key.pem |
its private key |
ca_cert.pem |
firmware CA (res/raw/ca_cert.der) |
To produce them from the APK's client1.p12 and ca_cert.der (the P12 is
protected by a short static password embedded in the app — recover it from the
decompiled APK and pass it to openssl below):
P12PASS=... # static password embedded in the app APK
openssl pkcs12 -legacy -in client1.p12 -passin pass:"$P12PASS" -clcerts -nokeys -out client1_cert.pem
openssl pkcs12 -legacy -in client1.p12 -passin pass:"$P12PASS" -nocerts -nodes -out client1_key.pem
openssl x509 -inform der -in ca_cert.der -out ca_cert.pem
Install
- Copy
custom_components/hotspring/into your Home Assistantconfig/custom_components/. - Place the three PEM files in
/config/hotspring/certs/. - Restart Home Assistant.
- Settings → Devices & Services → Add Integration → “Hot Spring Connected Spa”, and sign in with your account.
How it works
POST iotsupportportalapi.watkinsmfg.com/api/v1/login/→ JWT.GET /user_spa_details/→ the spa'srootTopic(MQTT prefix).- mTLS
GET iotfirmwareota.watkinsmfg.com:8577/(client cert) → rotating HiveMQ broker host/user/pass. - Subscribe
<rootTopic>/#for telemetry; publish<rootTopic>/<subsystem>/controlwith{"<subsystem>":{"control":{…}}}for commands (temperature is an integer string in the spa's unit).
The reusable protocol client lives under custom_components/hotspring/api/
(cloud.py, spa.py, protocol.py); all constant values are in constants.py.
Optional: local read path
If Home Assistant is on the spa's LAN, set Local /status URL in the config
flow (e.g. http://<spa-ip>/status). Telemetry is then polled from the dongle's
local HTTP endpoint instead of subscribed over the cloud broker, keeping
monitoring on-LAN and off the vendor cloud. Control still uses the cloud MQTT
connection. Leave it blank to use cloud MQTT for reads.
License
MIT — see LICENSE.