Local-first EMS control for Zendure SolarFlow systems. It reads local grid meter and Zendure telemetry, controls inverter output, and provides a local dashboard.
Tip
New to EMS SolarFlow? Read the Project Overview for a non-technical introduction to the main features, supported setups, dashboards, energy management, and system administration.
EMS controls real power hardware. Read the safety guide before enabling live writes.
Each device carries one status — Validated, Family-supported, Reverse-engineered or User-reported. The maintainer validates on a SolarFlow 800 Pro 2 and a Shelly Pro; wider coverage needs community reports. Definitions and the full matrix live in docs/user/supported-setups.md.
| Hardware / integration | Connection | Status |
|---|---|---|
| SolarFlow ZenSDK inverters — 800 Pro 2, plus 800 / 800 Plus / 800 Pro / 1600 AC+ / 2400 AC / 2400 AC+ / SolarFlow 2400 Pro / 4000 AC+ | Local API (ZenSDK) + Zendure cloud MQTT | 800 Pro 2 Validated; rest Family-supported |
| Older Hub / Hyper / AIO / Ace MQTT devices — Hub 1200/2000, Hyper 2000, AIO 2400, Ace 1500 | Local or Zendure cloud MQTT | Reverse-engineered |
| Any Zendure device via API key | Zendure cloud MQTT | Telemetry for any device; control needs an exact supported model |
| Zendure & Shelly grid meters — Shelly Pro, Zendure Smart Meter 3CT / Smart Meter D0 (Local API) | HTTP | Shelly Pro Validated; Zendure meters Reverse-engineered |
| Other HTTP / MQTT grid meters — Shelly Plus/Gen2/Gen3, Shelly 3EM Gen1, everHome EcoTracker, Tasmota, generic MQTT, D0 over local MQTT | HTTP / MQTT | Family-supported / Reverse-engineered |
| Home Assistant entity as a load signal | HA API | Legacy; not recommended for new setups |
MQTT control is an implemented EMS transport, not a future feature: a supported inverter joins the same control loop, target calculation and safety gates as the Local API, over a local broker or Zendure cloud MQTT. ZenSDK cloud control is Validated on the SolarFlow 800 Pro 2; the older legacy-JSON write path is Reverse-engineered and still needs broader hardware validation — the Roadmap is confirming it on more device generations, not building the feature. Every write still requires an exact supported model, a verified write protocol, the per-device control capability and the transport write gate. Device compatibility reports (working or broken) are very welcome.
The machine EMS runs on — 64-bit arm64 or amd64.
| RAM | Recommended configuration |
|---|---|
| 512 MB | EMS without InfluxDB |
| 1 GB | EMS with InfluxDB |
| >1 GB | Additional headroom |
InfluxDB stores energy history and is optional — control does not need it. Pi matrix.
The appliance image turns the board into a box that runs EMS and nothing else: flash one card, plug in Ethernet, power on. No shell to learn and no operating system to maintain by hand.
One writable root, patched in place by apt, on a 16 GB card or larger. Built
for the Raspberry Pi 3, 3B+, 4 and 5 — one image file per board. A failed
operating-system update is recovered by you, at the machine, or by writing the
card again and restoring a backup, which is why the backup matters more than the
update does.
The image is not confirmed on physical hardware yet; read what that means before you rely on it.
Download the newest image → — one file per board, always the current build. Not under Packages: that holds the container images the appliance fetches by itself.
Flashing the card · First start · All appliance guides
Tip
New here? Start with the Admin Console — the recommended path for most users. Browser-guided setup, hardware discovery, updates, backups and maintenance, with no shell or config-file editing. It finds your devices and sets up the connection for you.
Install and start it in a local EMS folder:
mkdir -p ems-solarflow-api-control
cd ems-solarflow-api-control
curl -fsSLO https://raw.githubusercontent.com/basecubedev/ems-solarflow-api-control/main/deploy/admin/install-admin-console.sh
sh install-admin-console.shThen open http://127.0.0.1:8090 and create the shared EMS/Admin password in
the browser. Host networking is the default (best for local discovery); add
--bridge only if you need Docker bridge networking.
Full guide, with demo videos of a fresh install and a guided update: docs/user/admin-console.md
Prefer the shell? These converge on the same config/config.json, so you can
switch later.
| Path | Choose this if |
|---|---|
| Docker Bootstrap | Shell-only Docker setup |
| Developer Setup | Develop, debug or build from source |
The Admin Console picks the right one during discovery — you don't choose upfront. EMS reaches your devices over any one of:
- Local API (ZenSDK) — newer SolarFlow / ZenSDK models on your LAN. Fastest, fully local.
- Local MQTT — devices re-pointed to your own broker. Low latency, no cloud.
- Zendure MQTT (cloud) — any Zendure device via your Zendure API key. Higher latency over the internet.

