Zendure RestAPI – local zero-export control for SolarFlow batteries

I’ve been running a Zendure SolarFlow 3000 Mix AC+ in Home Assistant for a few months, controlled entirely over the local zenSDK HTTP API — no cloud account, no MQTT broker, no YAML packages to copy. It has grown into a full integration, now on HACS.

What it does

  • 100% local. Talks straight to the battery’s own HTTP server. Keeps working when the internet or the Zendure cloud does not.
  • Zero-export control, once a second. A fast loop follows your P1 meter every second; a slower one handles direction and safety.
  • Seven operation modes — standby, smart_matching, smart charge-only / discharge-only, quick charge / discharge and manual. One select, so your own price automation can drive it.
  • Your own meter. HomeWizard P1 (found automatically), YouLess LS120, Zendure P1 / Smart Meter 3CT, EcoTracker, Shelly Pro 3EM — or any power sensor Home Assistant already has.
  • Low standby draw, measured. Hands the battery back to its low-power state when there is nothing to do: about 5 W instead of 29–36 W.
  • Spares the flash memory. The smart modes write their limits to RAM, not flash.
  • Leaves a full battery alone. At the device’s own SOC bounds nothing is ordered into the closed direction, and the status says why.
  • Everything visible. Ready-made dashboard, a controller status with the reason behind every decision, charge and discharge efficiency as sensors, and an optional per-second CSV trace.
  • Eleven languages for setup screens and states.

Every change to the control loop is replayed against recorded per-second runs before release. The measurements behind it — meter delay, efficiency, standby draw, and where the device differs from Zendure’s documentation — are in the technical reference (README2) in the repository.

Supported devices

Device Status
SolarFlow 3000 Mix AC+ tested daily
SolarFlow 4000 Mix AC+ · 2400 AC · 2400 AC+ · 1600 AC+ supported — same AC-coupled layout
SolarFlow 800 / 800 Plus / 800 Pro / 800 Pro 2 · 2400 Pro · 4000 Mix Pro works; smart modes experimental (solar on the device)
Hyper 2000 · Hub 1200/2000 · AIO 2400 · Ace 1500 no local API on these models

Getting started

  1. Enable the local API. Under EN 18031 it is off by default: in the Zendure app, add HEMS, then close the app.
  2. Install via HACS. The submission to the HACS default list is pending; until then: HACS → ⋮ → Custom repositories → add the repository above, category Integration. Install Zendure RestAPI and restart Home Assistant.
  3. Add the battery. It is usually discovered under Settings → Devices & services. Set Operation mode to smart_matching.

Looking for testers

Only the 3000 Mix AC+ has been run by me. If you have any other SolarFlow model, a New model report issue with the diagnostics download attached (device page → ⋮ → Download diagnostics; serial numbers and addresses are redacted) is enough to move a model from experimental to supported — whether it works or not.

Questions and feedback welcome here or as a GitHub issue.

v1.6.0 – Dynamic tariffs with a day plan

No change to the control loop. Everything new sits next to it, in a device of its own: Price Control. Off by default.

What it does

Over the Nord Pool prices of today and tomorrow, Price Control works out per quarter of an hour whether to charge, discharge or do neither. It weighs:

  • separate import and export prices (spot × factor + surcharge, so your own contract fits)
  • conversion losses on both sides, wear per kWh, and a minimum margin a cycle has to clear

Where there is a real spread, it charges with quick_charge and discharges with quick_discharge at the battery’s full power. Between those blocks the battery holds the grid at zero, or rests (see net metering below).

Net metering (Dutch salderen) built in

While a kWh you export is worth the import price, switch on Net metering. The plan then values export at the import price. Between the blocks the net metering mode applies, standby by default: under net metering, moving energy through the battery earns nothing and only costs losses and wear. When net metering ends (NL: 1 January 2027), switch it off. The export formula and the normal in-between mode (smart_matching) take over, with no other changes.

Replay: 30 days of a real installation (3000 Mix AC+, Dutch dynamic contract)

Control per day, with net metering per day, 2027 rules
smart_matching only € 0.07 € 0.41
fixed cheap/expensive prices € 0.21 € 0.49
day plan, cover the house only € 0.33 € 0.54
day plan, trading € 1.58 € 0.83

On the same days, the day plan earned as much as the full home-energy planner I had been running myself.

Also in 1.6.0

  • Dashboard created for you on request, with a Price Control tab and a day-plan chart. An existing dashboard is never overwritten.
  • Entity names in eleven languages (EN, NL, DE, FR, ES, IT, PL, PT, CS, DA, SV). Entity IDs stay English, so automations and dashboards work in every language.
  • Fixed prices still work with any price sensor.

Needs

  • Nord Pool (HACS) for the day plan
  • ApexCharts Card (HACS) for the chart. Without it, the chart is simply left out.

Update through HACS and restart Home Assistant. Setup steps for Nord Pool and the tariff settings per country are in README2.

Release notes: Release v1.6.0 - Dynamic tariffs with a day plan, eleven languages and a dashboard · windsurf/hassio-zendure-restapi · GitHub

Tested on the 3000 Mix AC+. Own a 2400 AC, 1600 AC+ or 4000 Mix? A New model report with the diagnostics attached moves your model from :test_tube: to :white_check_mark:.