Zendure (external integration) — presentation + recap up to v1.3.0
Hello everyone ![]()
I realize I’ve never opened a dedicated topic for the Zendure external integration, even though it’s been around since this summer (first version on July 19, 2026). I’m making up for lost time: here’s a complete presentation and a recap of the versions up to v1.3.0, which has just been released. This topic will then be used to announce new features and gather your feedback.
What is it?
An external Gladys integration for Zendure SolarFlow / Hyper solar batteries. It runs in its own container, is installed from the integrations catalog (Energy section) and sends the telemetry of your batteries to Gladys, from the Zendure cloud and, if you wish, directly from the local MQTT of each device.
What is supported
- Models: SolarFlow 800, 800 Pro, 1600 AC+, 2400 AC+, 2400 AC, 2400 Pro, and Hyper 2000 (experimental).
- 5 measurements per battery (read-only), categorized in Gladys’s energy categories since v1.3.0:
- Battery level, charging power, and discharging power → Storage battery;
- power to the house → Home output sensor;
- solar input power → Energy production sensor.
- Local MQTT (optional): values refreshed every 1 to 3 seconds instead of about 30 seconds via the cloud, and telemetry continues during a Zendure cloud or internet outage.
- Automatic cloud fallback, device by device: if a battery goes silent locally, the integration automatically switches to the cloud, then returns to local as soon as messages resume.
- Transport badges on each device: Local, Cloud, Cloud + orange dot (degraded: the device should be local but is running on cloud fallback, the reason is displayed on hover) and Unreachable.
- Connection status on the configuration screen (missing key, unreachable cloud, or invalid key).
- Publication of values paced under the Gladys core’s request limit, which slows itself down if the core is saturated, to handle a large fleet (I run with about fifteen SolarFlows).
Installation
- In the Zendure mobile app, developer / Home Assistant integration section: generate (or copy) your authorization key (the “HA key”).
- In Gladys: Integrations → search for Zendure → Install.
- Configuration tab: paste the key, adjust the refresh interval if needed (30 seconds by default), optionally enable local MQTT (zenSDK), then Save configuration.
- Create your batteries from the Discovery tab.
The complete step-by-step guide is in the integration documentation (link “Documentation” on the configuration screen).
Version recap
- v1.0.1 (July 19): first version: discovery of SolarFlow 800 Pro via Zendure cloud, read-only telemetry, periodic polling, and real-time MQTT.
- v1.1.0 (July 21): local MQTT with cloud fallback per device and automatic return to local, transport badges, connection status, and 6 additional SolarFlow / Hyper models.
- v1.2.0 (July 24):
- degraded badge (orange dot) when a battery runs on cloud fallback;
- FR/EN documentation and “Getting Started” section on the configuration screen;
- adaptive publication rate under the core limit;
- reliability: our own MQTT request echoes no longer distort telemetry, empty or invalid interval → 30 seconds, 15-second delay on the cloud, no cached values republished during an outage.
- v1.3.0 (October 16):
- measurements move to Gladys’s energy categories (Storage battery, Home output sensor, Energy production sensor): your home battery no longer counts in Gladys’s “low battery” alerts;
- the pack powers are now called Charging power and Discharging power: the old names (“Battery input/output power”) were read backwards compared to what they measure;
- categorized in the Energy section of the catalog;
- the entire integration in French, English, German, and Spanish (configuration, messages, documentation);
- technical upgrade (SDK 0.15, release tooling, version notes on GitHub).
Prerequisites
- Gladys ≥ 4.86.0 for v1.3.0.
- A Zendure account with your batteries already online in the app.
- For local MQTT: enable it in the Zendure app (developer mode).
Did you already have your batteries before v1.3.0?
After the update (Update button in the Supervision tab), your batteries keep their old categories until you apply the new definition: in the Discovery tab, click Update on each battery (marked Already added). Features are updated in place: history, scenes, and dashboards are preserved.
Good to know
- One cloud consumer per Zendure account: if Home Assistant or a second Gladys instance uses the cloud connection of the same account, they compete for it and the telemetry becomes intermittent. For a second consumer, use local MQTT, which has no such limit. The integration signals this situation once in its logs when it detects it.
- A battery in “Cloud (degraded)” while local MQTT is enabled: its firmware may have stopped publishing locally without warning. In the Zendure app, disable then re-enable MQTT control for this battery, and it will restart in less than a minute.
- Integration stuck in “degraded” right after installation, with WebSocket timeouts in the logs: check that the machine’s firewall allows the port used by external integrations to reach Gladys (see this topic).
What’s next
- Control of the batteries (charge/discharge setpoints, output limits): this is the next big step.
- Additional measurements (charge/discharge index, remaining energy, emergency output) once their names are confirmed on real telemetry.
Feedback welcome
-
Do you have a SolarFlow 1600 AC+, 2400 AC+, 2400 AC, 2400 Pro, or a Hyper 2000? Their model identifiers are not yet confirmed on real hardware: let me know if they are properly discovered and if the values are consistent.
-
Is local MQTT and cloud fallback working well for you?
-
After v1.3.0: does the move to Storage battery and the Update button work well?
-
German / Spanish translations, for those who use Gladys in these languages.
-
Code and issues: GitHub - Terdious/gladys-zendure: Gladys Assistant Integration template for a JS external integration · GitHub
-
Changelog: gladys-zendure/CHANGELOG.md at master · Terdious/gladys-zendure · GitHub
Thanks in advance for your feedback ![]()