Short version: firmware for an ESP32-S3 that sits next to any inverter with an RS485 port, reads it in whatever protocol that inverter happens to speak, and republishes it as MQTT with HA discovery, Modbus TCP, REST/JSON and Prometheus. The point is to be brand-agnostic. Right now the coverage doesn’t match that ambition yet, which is why I’m posting.
Why build it this way
There are a lot of good ESPHome configs and integrations out there, and I’ve used several. But they’re generally one project per brand, and each one reimplements the same stack: read the bus, decode the fields, publish somewhere. So the moment you have a second inverter, or a brand nobody bothered with, you’re starting over.
Heliograph splits it: transport → driver → a canonical measurement model → output adapters. Brand knowledge lives only in the driver. Everything downstream sees canonical measurements, so a new driver gets MQTT, HA discovery, Modbus TCP, REST and Prometheus for free without touching any of that code. For Modbus devices, adding one is a data file rather than C++.
And it’s deliberately not tied to a single protocol family. Modbus RTU is in there, but so is EverSolar’s proprietary AA55/PMU framing, because plenty of hardware predates anyone standardising on anything. That’s the whole idea, the stuff SunSpec covers is the easy half.
There’s a discovery wizard too: wire A/B, run it, it fingerprints the device and picks the driver. That matters more as coverage grows.
Where the coverage actually is
| Family | Connection | Status |
|---|---|---|
| EverSolar / Zeversolar legacy (TL series) | RS485 (PMU/AA55) | **Stable** — in production, validated over eight consecutive unassisted sunrises |
| Sungrow SH residential hybrid | Modbus RTU | Experimental, best-sourced here — vendor’s own protocol spec, cross-checked register by register against a widely deployed integration |
| Deye/Sunsynk SUN-xK-SG · Solis/Ginlong RHI · Sofar HYD EP and 3PH · Growatt MIC TL-X and MIN TL-X | Modbus RTU | Experimental, two-sourced — every mapped row corroborated by two independent implementations that agree |
| Growatt SPH hybrid · Huawei SUN2000 (± LUNA2000) · GoodWe ET/EH/BT/BH | Modbus RTU | Experimental, single-sourced |
| SolarMax S/C/MT/TS | RS485 (MaxTalk) | Experimental — vendor went bankrupt and took the portal with it, so this is the only way these report anything. No SolarMax has ever answered the driver |
| SolaX X1 Mini G1/G2/G3 | RS485 | Experimental — first attempt on real hardware returned no data at all |
| Anything implementing SunSpec | Modbus RTU | Experimental — one generic driver for the published standard |
That’s it, and I want to be straight about it. It started with EverSolar because that’s what’s on my wall, a 2009 TL whose monitoring portal died with the company. ZeverCloud is gone, and the HA integration reads home.cgi, a plain text blob where the field you want sits at a position that shifts between firmware revisions, which is where all those `invalid literal for int() with base 10: ‘ZL’` reports come from. Talking RS485 directly sidesteps all of that and gives you far more than two values.
But it was never meant to be an EverSolar tool. The architecture is the point; EverSolar is just the first thing that proved it.
The ask
I own one inverter. Everything below that first row is educated guesswork until it meets real hardware, and the roadmap: Deye/Sunsynk, Sungrow, GoodWe, Huawei SUN2000, more of the SolaX and Growatt range, is going to stay a roadmap unless people with those boxes get involved.
So: if you have an inverter with an RS485 port and you’re willing to hook this up and report back, I’d be really grateful. Even “it connects and then returns garbage” is useful! garbage tells me where the framing is wrong. If your brand isn’t listed at all but you know something about its protocol, tell me and let’s see whether it fits; that’s a more interesting conversation than another Growatt config.
What it costs you: a Waveshare board (~€25), a cable to the COM port, twenty minutes. I’ll debug it with you rather than dumping it on you. Issues and discussions are open on the repo, or just reply here.
Everything is read-only. I’m not writing setpoints to somebody’s inverter based on a register map I haven’t verified on hardware. Worst case for a tester is that nothing shows up.
One deliberate choice worth mentioning: a value that couldn’t be read is published as absent, never zero. Zeros end up in your energy dashboard looking like the sun went out for five minutes.
Practical bits
Hardware is a Waveshare ESP32-S3-RS485-CAN a transceiver on board, so no MAX485 module to wire up backwards. Easiest way in is the web installer at Heliograph — web installer → plug in over USB-C and click connect. Chrome and Edge, and as of Firefox 151 that works too (desktop only, Web Serial finally landed). Otherwise take the factory bin from releases and flash it with esptool. OTA after that, with a watchdog-backed bootloader rollback that has already earned its keep once.
The protocol core runs on the host, so pio test -e native gives you 390-odd tests with nothing plugged in, and a mock environment feeds a simulated inverter through the entire output stack, you can work on the MQTT/HA side without an RS485 bus on your desk.
Obvious disclaimer: the COM port is on a box with live DC behind it. Know what you’re doing, or get someone who does.