Local Balboa hot tub gateway for Home Assistant (ESP32 + MQTT discovery)

GitHub: GitHub - shomanjk/esp32_balboa_spa: ESP32 Based Balboa Spa wifi controller module for M5stack Atom with Atomic RS485 Base · GitHub

I wanted local status and control for a Balboa spa without routing my automations through a vendor cloud. This project adds a small ESP32 Wi‑Fi gateway that connects to the spa’s main Balboa control board on the existing RS485 bus—you do not need Balboa’s Wi‑Fi module for this gateway (local web UI, MQTT, and Home Assistant). The ESP is another peer on that bus, not a replacement for the main board.

On my tub, the spa control panel (topside) still works, and the official Balboa Spa Control app still works too alongside the gateway (I still have Balboa’s factory connectivity path; the ESP does not disable it). Your panel should behave the same way; app coexistence depends on how your tub was already set up—see caveat below.

Not affiliated with Balboa Water Group. “Balboa” and app names are used only to describe compatibility, not endorsement.

Firmware is open source (Apache 2.0), currently v2.10.0, maintained here: GitHub - shomanjk/esp32_balboa_spa: ESP32 Based Balboa Spa wifi controller module for M5stack Atom with Atomic RS485 Base · GitHub

What it does today

  • Home Assistant via MQTT auto-discovery — entities appear under device Balboa Spa (temperatures, climate/setpoint, pumps as switch or select depending on capability, lights, blower, mister, heating/spa state enums, etc.)

  • MQTT commands on Spa/<gateway>/cmd/… with JSON outcomes on Spa/<gateway>/cmd/result (set temp, heat mode, temp range preset, temp units, panel clock, pump/light toggles)

  • Built-in web UI — phone-friendly /status for live data and v1 controls; /config for equipment and controller identity; /state for Wi‑Fi and RS485 health

  • OTA for documented M5 tub-side builds (M5AtomLite-tub-ota)

  • Optional legacy TCP bridge on port 4257 for Homebridge users (BRIDGE build flag)

Protocol semantics follow the community reference: ccutrer/balboa_worldwide_app protocol.md

Home Assistant setup (summary)

  1. Flash the ESP32 and configure Wi‑Fi + MQTT in config.h (copy from config-example.h).

  2. Use the same MQTT broker as Home Assistant’s MQTT integration.

  3. On connect, the gateway publishes retained discovery under homeassistant/… — look for device Balboa Spa.

  4. Default discovery temperature unit is °F; for Celsius tubs set MQTT_HA_TEMP_UNIT in config.h.

  5. device.configuration_url points at http://<gatewayName>.local/status (mDNS); use a DHCP reservation if .local does not resolve on your LAN.

Disable discovery with #define MQTT_HA_DISCOVERY 0 if you only want manual MQTT entities.

MQTT command topics (v1)

| Topic | Payload examples |

|-------|------------------|

| Spa/<gateway>/cmd/setTemp | 102, 39.5 |

| Spa/<gateway>/cmd/mode | heat, off |

| Spa/<gateway>/cmd/preset | Low Range, High Range |

| Spa/<gateway>/cmd/tempUnits | F, C |

| Spa/<gateway>/cmd/setTime | HH:MM |

| Spa/<gateway>/cmd/syncTime | any non-empty |

| Spa/<gateway>/cmd/button/<code> | toggle, on, off; pumps: Off, Low, High |

Full list: README — MQTT and Home Assistant

What you need (honest scope)

This is moderate DIY, not a sealed product:

  • Balboa spa with RS485 access (ccutrer physical layer wiki)

  • 2.4 GHz Wi‑Fi, USB for first flash, PlatformIO build

  • Documented tub stack: M5 Atom Lite + Atomic RS485 Base (~$30–50 parts) or generic ESP32 + RS485 module (default UART GPIO 16/17 in config example)

  • Time to confirm traffic and controls on /status before you trust automations

Getting started checklist: Getting started · shomanjk/esp32_balboa_spa Wiki · GitHub

M5 stack + harness (what I used on BP501)

On my Balboa BP501, the cleanest tap was a Molex 0451320403 4‑circuit plug (DigiKey WM16117-ND) on the factory header on the main control board—short harness to the Atomic RS485 base VH‑3.96 terminals (12 V, GND, A, B). You still need the correct crimp terminals for that housing and must verify pinout against ccutrer physical layer and your board label before power-on. More community notes: Hardware field notes.

Power (tub install): The Atomic RS485 Base includes 12 V → 5 V for the Atom. On my setup it runs from the spa board’s accessory 12 Vno separate wall wart in the cabinet (USB is still fine on the bench for flashing). 12 V/GND are not the RS485 A/B pair—wire power and bus separately. Generic ESP32 + MAX485 builds may still need their own 3.3 V/5 V supply plan.

Screenshots

  1. /status page

  2. equipment / controller identity

  3. Home Assistant Balboa Spa device or dashboard


  4. Cabinet photo of ESP32 + RS485 wiring


Official Balboa app vs this gateway

This ESP32 gateway Balboa Spa Control app (typical)
Needs Balboa Wi‑Fi/cloud module? No — RS485 tap + ESP only for local HA/MQTT/web Often yes — usually via Balboa’s own connectivity hardware
Replaces main control board? No No

If you already use the official app with Balboa’s module, many tubs can run both (panel + app + ESP as RS485 peers). If you never had Balboa Wi‑Fi hardware, this project is how you get local/Home Assistant control without buying theirs—not a substitute for their cloud account features you never had.

Lineage

Built on the ESP32 port of the NorthernMan54 Balboa gateway line; active development on the fork above. Not affiliated with Balboa Water Group or M5Stack.

Ask

If you have already tapped RS485 on a Balboa board (e.g. BP501 family), I am collecting connector / harness field notes in the wiki: Hardware field notes · shomanjk/esp32_balboa_spa Wiki · GitHub — please reply with board label, connector part number, and PlatformIO env if you try this.

Questions welcome. I am happy to share what worked on my setup and what still varies by tub.

Hi,

Many thanks for sharing this project. Documentation detail is quite amazing.

I'm currently using this project on a Hot Tub that uses a Balboa GS523DZ and VL801D
https://github.com/Shuraxxx/-Balboa-GS523DZ-with-panel-VL801D-DeluxeSerie--MQTT

It has worked exellent for a couple of years but sometimes gets a corrupt temperature reading that I have not managed to resolve.
I built the hardware that sits been the display and control unit.

Do you know if your project would be suitable for this setup ?

Thanks

Your Shuraxxx setup intercepts the VL801D RJ45 serial panel cable on a GS523DZ — that’s a different integration path than this gateway, which speaks RS485 on BP-style controller buses (ccutrer protocol). I haven’t tested GS523DZ, and I’m not sure your inline wiring location would work with this firmware without a separate RS485 tap on the controller. If your GS board exposes RS485 somewhere, it might be worth a read-only experiment; otherwise you’re probably better staying on the GS-panel projects (Shuraxxx / micke85 / MagnusPer lineage).

Hi,

Thanks for the follow up. I'll stick with my setup for now.
Good luck with your project. Looks great.

Thanks [shomanjk] - You've motivated me to revisit getting Wifi control of my spa that I last tried and failed 2 years ago. The addin I was using then just kept throwing invalid message received and what I was seeing was close to what I'd read I should but I couldn't work it out.

I reconnected my EW11 RS-485 Bridge until my M5 Atom Lite and RS-485 module arrive so I can start some diags. What I've discovered is my Balboa Colossus board is running M100_2015 V5 and seems to be a bit different. I've captured data using some simple claude generated Python code and I have it worked out. I can sent light on and off commands, set the temp, turn pumps on and off from a telnet client that lets me send HEX "strings".

So now I just need to see if I can modify your code to talk to my spa - My WAF (wife appreciation factor) is going to be through the roof as we sit the spa on 38 when not in use but my wife likes it at 40 so turns it up an hour in advance of wanting a spa. Being able to do this from bed with a phone or even while out is going to be life changing!!!

Been looking for an excuse to play with an ESP32 too!

I have dabbled in code since learning basic when I was 7 45 years ago and I've played in Pascal, C++, VB.NET and Python little bits every now and then since so looking at existing code and modifying it is right up my alley - Always takes me a while to get my head round it as I usually go years without doing any - Using Claude to slap some telnet and dumping in hex that I could then look at and fix (Caude presented it with errors) again was a good way back into it.

Its a shame the code is different for different generations of Balboa kit as I mentioned I was looking into this to the retailer I got my spa from 2 years ago when I first tried and he was very interested as he said the Balboa Wifi modules were "crap" in his words.

Ps - Its part of a Balboa Colossus "Kit" - The board is an SIBP2P running M100_215 V5
The connector I plugged into is labelled J34 and is just below J33 where the spa Keypad is plugged in. Using the Mini ATX type connectors.

Sorry - So damn excited I had to come back. I've worked out temp, pump and lights. Used claude to bang out a simple program with 4 buttons that send hex "strings" via telnet with a simple 3 line prompt. Tweaked the IP, Port, Strings and button labels and voila - I can set the temp to 38 our non-using temp, 40 for use and turn the lights on and off with the push of a button on a laptop over wifi.

I am so grateful I stumbled on this post as it gave me the kick in the bum I needed. Can't wait for the M5 to turn up - Better start looking at your code and tweaking in readiness.

I went this way and had it working well for about 2 weeks. I suspect the RS485 interface failed/went bad as it just stopped receiving packets. I fully rebooted the spa controller and the M5 unit and it started working again for about 24 hours or less and stopped getting any packets again.

Plugged my Elfin EW11 back in and that worked like a dream - I’m using it now with an addin that works with the Elfin and an addin talking directly and not using MQQT at all and its been working for a few weeks.

My main feedback would be:

The information on the process to program the M5 was sparse - I got there in the end with lots of googling about what addins I needed on my Laptop to do the programming. No issue if you are already programming ESP32’s but starting from scratch was fiddly.

There is little configuration can be done to the programmed unit - I had details in the MQQT settings wrong which get hard coded so had to reprogram the unit to fix them. Then discovered the Timezone setting again burried hard coded and couldn’t be changed.

Before the RS485 started failing (or its link to the M5Stack Mini?) I got quite a few restarts of the device with Kernel panics - More than once a day - Could be something in my programming of the device or its something in the code?

Going back to the Elfin EW11 RS485->Wifi bridge and an addin talking to the spa was simpler and has been very reliable. My advice would be the Elfin road is simpler, cheaper and reliable. I’d go this way if MQQT is a deal breaker but otherwise its more complex and more places to break. Future updates might bring greater configuration once the device is going.

I might just be one of the unlucky ones with the RS485 failing - I know full well some hardware always fails and someone is going to be the unlucky person even if the failure rate is 1 in a thousand.

I’ll find something to use the M5Stack mini with - I might get some temp, humidity and air quality sensor addins and play with that.

As I said this project gave me the motivation to revisit linking to my spa after a prior failure to achieve success and while waiting for the M5Stack device to arrive I played with the Elfin EW11 talking to my spa with Python and wrote my own program that monitored and switched everything I needed so gained the knowledge on the Serial communications with the board.

Incredible project, thank you so much!

I am not a hardware expert. I deployed this on a WeAct CAN485 DevBoard ESP32 board. This board has 2 ports for power (ground / live), and 3 ports for data (ground / A / B). So I bought a Molex 2x2 pin adapter, and a 3 way Wago connector and split the ground coming from the spa, so I can pull it to both of my grounds on my board.

I used Copilot to adjust the config to match the pins on my board. It works perfectly. Thanks again! It was a fun project with high spouse approval.