No description
  • Python 80.1%
  • HTML 17.7%
  • Shell 1.3%
  • Dockerfile 0.9%
Find a file
Lumi 1c90396731 fix: remove stale LIVE handler log spam + reset reconnect backoff + add deploy.sh
- Remove unconditional print in LIVE packet handler (logged every ~2s)
- Reset _reconnect_attempts to 0 on successful ONLINE connection
  so backoff always starts from 1s after recovery
- Add deploy.sh: git pull + docker-compose down + build + up -d
- Improve HEALTHCHECK exit logic and bump start-period to 15s
2026-06-24 16:28:52 +00:00
.vscode removed flask launch 2024-10-12 16:52:12 +02:00
API fix: MQTT analysis — 6 issues found and resolved 2026-06-24 12:47:22 +00:00
docs fix: ERROR query dead code + dynamic capability detection + non-blocking producer 2026-06-24 14:22:34 +00:00
misc Added all protos 2025-11-21 15:31:02 +01:00
proto modified: .gitignore 2025-12-04 21:13:16 +00:00
tools fix: MQTT analysis — 6 issues found and resolved 2026-06-24 12:47:22 +00:00
.dockerignore fix: phase-1 critical bug fixes 2026-06-23 16:26:13 +00:00
.gitignore fix: complete remaining phase-1 fixes 2026-06-23 18:36:40 +00:00
bytebuffer.py temp control works 2024-11-04 19:39:42 +01:00
CHANGELOG.md docs: comprehensive MQTT analysis report, CHANGELOG v1.2.0, 0x10 investigation 2026-06-24 13:31:06 +00:00
crc_diagnostic.py feat: add temporary CRC-32 diagnostic to test algorithm on live packets 2026-06-23 20:33:24 +00:00
deploy.sh fix: remove stale LIVE handler log spam + reset reconnect backoff + add deploy.sh 2026-06-24 16:28:52 +00:00
Dockerfile fix: remove stale LIVE handler log spam + reset reconnect backoff + add deploy.sh 2026-06-24 16:28:52 +00:00
HA_auto_mqtt.py fix: MQTT analysis — 6 issues found and resolved 2026-06-24 12:47:22 +00:00
levven_packet.py feat: PCAP-validated protocol improvements 2026-06-24 03:50:56 +00:00
License.md Fixed 2024-10-09 14:15:25 +02:00
README.md docs: comprehensive CHANGELOG.md and updated README.md 2026-06-24 04:27:28 +00:00
requirements.txt modified: .gitignore 2025-12-04 21:13:16 +00:00
SETUP.txt Add Pump 1 to HA, Change Heater1 to a BinarySensor. Add debug info for SpaInformation, SpaConfiguration. Also add deg F. 2025-03-20 16:36:52 -04:00
SpaBoii.code-workspace First 2024-10-08 19:54:42 +02:00
SpaBoii.py fix: remove stale LIVE handler log spam + reset reconnect backoff + add deploy.sh 2026-06-24 16:28:52 +00:00
TODO.md Fixup: TODO.md 2025-03-20 16:38:28 -04:00

SPABoii — No Cloud Access for ARCTIC SPA (Levven) Systems

Disclaimer: USE AT OWN RISK. I TAKE NO RESPONSIBILITY FOR ANY ERRORS THIS MIGHT CAUSE.

License


Background

Thread with progress and history links: https://community.home-assistant.io/t/arctic-spa-no-cloud-api-spa-boii/782040


Overview

SPABoii communicates directly with Arctic SPA / Levven hot tub controllers over TCP (port 65534), bypassing the manufacturer's cloud entirely. It exposes spa controls and sensors as Home Assistant entities via MQTT auto-discovery.

What works:

  • Temperature setpoint control (°F)
  • Current temperature monitoring
  • Pump 1 (OFF / LOW / HIGH)
  • Pump 2, Pump 3 (OFF / ON → HIGH only)
  • Heater 1, Heater 2 status
  • Blower 1, Blower 2
  • Lights
  • Boost / Onzen (ON/OFF)
  • Cl Range (Low / Mid / High) — sets ORP limits
  • pH, ORP sensor readings
  • Error status monitoring (no_flow, heater_over_temp, etc.)
  • Device info (firmware, GUID) via MQTT
  • Device capabilities via MQTT

Requirements

  • Python 3.10+
  • Docker / Docker Compose
  • Home Assistant with MQTT broker (Mosquitto add-on)
  • SPA reachable on local network (TCP port 65534)

Setup

1. Clone the repository

git clone <repo-url> SpaBoii
cd SpaBoii

2. Create settings.yaml

host: YOUR_MQTT_BROKER_HOST
username: MQTT_USERNAME
password: MQTT_PASSWORD
spa_ip: YOUR_SPA_IP_ADDRESS

3. Build and run

docker-compose up -d --build

4. Verify

docker logs -f spaboii-ha-mqtt

You should see:

  • Spa IP: 192.168.x.x
  • Packet: 0x06 - Authenticate (size=100) — device info received
  • Packet: 0x03 - Configuration (size=42) — capabilities received
  • Packet: 0x00 - Live (size=56) — real-time sensor data

Home Assistant Entities

After startup, the following entities appear in HA via MQTT auto-discovery:

Entity Type Description
SPABoii.SetPoint Number Target temperature (°F)
SPABoii.CurrentTemp Sensor Current water temperature
SPABoii.Pump1 Select OFF / LOW / HIGH
SPABoii.Pump2 Switch OFF / ON (maps to HIGH)
SPABoii.Pump3 Switch OFF / ON (maps to HIGH)
SPABoii.Heater1 Binary Sensor Heating / Off
SPABoii.Heater2 Binary Sensor Heating / Off
SPABoii.Blower1 Switch OFF / ON
SPABoii.Blower2 Switch OFF / ON
SPABoii.Lights Switch OFF / ON
SPABoii.Boost Button Onzen / Boost activation
SPABoii.ClRange Select Low / Mid / High (ORP range)
SPABoii.pH Sensor pH level
SPABoii.ORP Sensor ORP level (mV)
SPABoii.ErrorStatus Sensor Error flags (comma-separated)
SPABoii.ConnectionStatus Binary Sensor Connected / Disconnected
SPABoii.FilterStatus Sensor Filter pump status
SPABoii.OzoneStatus Sensor Ozone generator status
SPABoii.CloseService Button Restart monitoring service

Architecture

┌─────────────────┐         ┌──────────────────┐         ┌──────────┐
│   Home Assistant │◄──────►│   MQTT Broker     │◄──────►│ Container│
│   (Auto-Discover)│  1883  │  (Mosquitto)      │  1883  │ SPABoii  │
└─────────────────┘         └──────────────────┘         └────┬─────┘
                                                              │ 65534
                                                              ▼
                                                         ┌──────────┐
                                                         │    SPA    │
                                                         │  (Levven) │
                                                         └──────────┘
  • SPABoii.py — Main process: socket I/O, packet parsing, MQTT callbacks
  • HA_auto_mqtt.py — MQTT entity definitions, Home Assistant auto-discovery
  • levven_packet.py — Packet serialization/deserialization (header + CRC)
  • proto/ — Protocol buffer definitions (.proto + compiled _pb2.py)
  • tools/spa_debug_tool/ — Interactive web debugger (Flask)

Protocol Details

The SPA uses a proprietary TCP protocol on port 65534:

  • Magic bytes: 0xABAD1D3A (4 bytes)
  • CRC-32: Sent as 0x00000000 for outgoing commands (PCAP validated)
  • Payload: Protobuf-encoded (see proto/ for definitions)
  • Heartbeat: PING packets every ~5 seconds

For full protocol documentation, see:

  • docs/PROTOCOL_ANALYSIS.md — PCAP reverse engineering
  • docs/COMPARISON.md — Original vs improved code, CRC research

Deployment

Push to host

git push origin main

Pull and rebuild on host

ssh tech@<host-ip>
cd /home/tech/SpaBoii
git pull origin main
docker-compose down
docker-compose up -d --build

Known Limitations

  • CRC validation disabled: SPA uses a non-standard CRC variant for data packets. PING packets use standard CRC-32. See docs/COMPARISON.md.
  • Onzen presets hardcoded: Cl Range uses fixed ORP values from PCAP.
  • Connection status: Binary sensor (ON/OFF). No quality metrics.
  • Raw socket capture: Requires host-level tcpdump (container is non-root).

Changelog

See CHANGELOG.md for detailed change history.


Contact / Issues

Home Assistant Community Thread: https://community.home-assistant.io/t/arctic-spa-no-cloud-api-spa-boii/782040

REMEMBER: This is boilerplate code, meant to provide a basic codebase for communication with Arctic SPA's. SO USE AT OWN RISK, I TAKE NO RESPONSIBILITY FOR ANY ERRORS THIS MIGHT CAUSE.