A small, dependency-light Go bridge that connects Zendure devices (e.g. the SolarFlow 2400 AC) to a local MQTT broker, with Home Assistant auto-discovery. It works locally over the device's on-board HTTP API (the zenSDK protocol) or via the Zendure cloud — both feed the same normalised MQTT topic tree. Verified end-to-end against a real SolarFlow 2400 AC.
Twin of go-daikin2mqtt and
go-mtec2mqtt; shares their project
setup (pure Go, custom MQTT client, declarative catalog, distroless image).
- Two transports, one pipeline —
localpolls each device's HTTP API (GET /properties/report);cloudstreams telemetry over a TLS MQTT session to the Zendure cloud broker. Both resolve through the same catalog/coordinator. - Bidirectional — Home Assistant
…/setcommands are written back to the device, with an immediate re-read so the state reflects the change sub-second. - Declarative catalog —
zendure.yamlmaps raw properties to topics/units/HA entities (offset/scale, English/German value maps); adding a property is a data change. - Home Assistant discovery — sensors, numbers, selects and switches with
default_entity_id(English, stable) and localized display names; battery packs become their own sub-devices with rich device-registry info. - Virtual charge/discharge switches — synthetic HA switches that write a mode
- power-limit property set and derive their state from the report.
- Diagnostic web UI — optional read-only embedded SPA over
/api/health+/api/snapshot(Home Assistant Ingress-friendly). - mDNS discovery + a diagnostic CLI (
zendure2mqtt-util). - Home Assistant add-on — installable from this repo (see addon/).
- Pure Go — only
gopkg.in/yaml.v3andgolang.org/x/sync;CGO_ENABLED=0, static distroless image.
make build # → bin/zendure2mqtt, bin/zendure2mqtt-util
cp config-template.yaml config.yaml
# local mode: set MQTT_SERVER + LOCAL_DEVICES (SN + HOST)
# cloud mode: set CONNECTION: cloud + CLOUD_APP_TOKEN (from the Zendure app)
./bin/zendure2mqtt --config ./config.yamlOr install the Home Assistant add-on: Settings → Add-ons → Add-on Store →
⋮ → Repositories → add https://github.com/SukramJ/go-zendure2mqtt, then install
go-zendure2mqtt. See addon/DOCS.md.
Local (connection: local) |
Cloud (connection: cloud) |
|
|---|---|---|
| Reach | device IP on the LAN (LOCAL_DEVICES) |
Zendure cloud (CLOUD_APP_TOKEN) |
| Telemetry | HTTP poll (REFRESH) |
TLS MQTT stream |
| Control | POST /properties/write |
MQTT publish |
The Zendure cloud broker enforces a single session per credential and drops it every ~1 s, so cloud mode only trickles telemetry — local mode is the recommended path. The reconnect is hardened (event-driven, stability-aware backoff). The cloud cert is non-standard, so
CLOUD_TLS_VERIFYdefaults off (the connection stays TLS-encrypted).
zendure2mqtt-util discover # browse mDNS for devices
zendure2mqtt-util report --host 192.168.1.50 # dump /properties/report
zendure2mqtt-util resolve --host 192.168.1.50 --lang de # catalog-resolved preview
zendure2mqtt-util set --host 192.168.1.50 --sn SF... --prop acMode --value 2
zendure2mqtt-util cloud-login --token <app-token> # test the cloud login
zendure2mqtt-util catalog-check --catalog zendure.yaml # validate the catalogAll scalar keys in config-template.yaml can be
overridden via ZENDURE_* environment variables (e.g. ZENDURE_MQTT_PASSWORD).
Booleans accept true/false. With the web UI enabled (WEB_ENABLE), a
read-only dashboard is served on WEB_BIND (default 127.0.0.1:8080).
go build ./...
go test ./...
make check # vet + fmt-check + lint + test (needs dev tools, see `make setup`)See docs/konzept.md for the architecture and design notes.
Parts of go-zendure2mqtt are developed with agentic AI assistance, primarily Claude Code. Incoming issues are likewise triaged and analysed with AI help. Every change is still reviewed by a human maintainer and has to pass the project's test suite before it lands — AI accelerates the work, it does not replace the review gate. If you want to contribute — with or without AI assistance — please read the AI contribution policy first.
This project is primarily based on the official
Zendure zenSDK — Zendure's own
documentation of the local device control protocol (properties/report /
properties/write and the device API used by the local backend).
The Zendure/zendure-ha Home Assistant
integration by peteS-UK (MIT licensed) was additionally used as a supporting
reference, mainly for the cloud-side details — the signed deviceList login
(HAKEY, the SHA1 signature scheme) and the zenHa client id. Many thanks to
peteS-UK and the contributors of that project.
The Home Assistant add-on icon (addon/icon.png) is the Zendure brand logo,
taken from the home-assistant/brands
repository (custom_integrations/zendure_ha/icon.png). It is a Zendure trademark
and remains the property of Zendure; it is used here only to identify the
supported hardware and is not covered by this project's MIT license.
MIT — see LICENSE. This project follows the official Zendure
zenSDK protocol and additionally used
Zendure/zendure-ha (MIT, Copyright (c)
2024 peteS-UK) as a supporting reference; see LICENSE for the upstream
attribution.