Skip to content

Repository files navigation

FlowBridge

MQTT bridge for portable power stations by EcoFlow.
MQTT-Brücke für mobile Energiespeicher von EcoFlow.

English · Deutsch

Docker Hub Version License: Apache-2.0


FlowBridge reads your EcoFlow power station through the official EcoFlow IoT Open Platform and mirrors it onto your own MQTT broker — Mosquitto, Home Assistant, EisBär SCADA, whatever you run. Plus a web dashboard with live readings and control.

Your data stays in the house. FlowBridge talks to the EcoFlow cloud and to your broker. To nobody else — except the update check, which fetches a public list of versions and can be switched off.

The interface, this README and the Synology setup guide exist in English and German. The remaining reference documents in docs/ and the source comments are German only.

FlowBridge dashboard: readings, controls, history and energy balance

Readings and controls on the left, the history on the right — and below it the energy balance, showing how much of the mains power actually reaches the battery.

Quick start

The image is on Docker Hub and can be pulled directly:

docker pull cheetahlab/flowbridge:latest

Images are published for x86-64 and ARM64 under the same tag — a Synology or Intel NAS gets one, a Raspberry Pi 4/5 (64-bit OS) or a Mac with Apple Silicon the other, without you having to pick. There is no 32-bit image; an older Pi running armhf is out.

Or straight away as a compose.yaml:

services:
  flowbridge:
    image: cheetahlab/flowbridge:latest
    container_name: flowbridge
    restart: unless-stopped
    ports:
      - "8081:8080"
    environment:
      FLOWBRIDGE_CONFIG: /config/config.yaml
      TZ: Europe/Berlin
      FLOWBRIDGE_PASSWORD: "a-good-password"
    volumes:
      - ./data:/config
docker compose up -d

Then open http://<host>:8081 — the setup dialog takes care of the rest. You need an access key and a secret key from the EcoFlow developer portal; those are not your app credentials, they are generated there specifically.

FLOWBRIDGE_PASSWORD protects the interface from the very first start. FlowBridge can switch outputs — without a password anyone on the same network could. The line may go once it has run; the password is then stored hashed in the data folder.

Synology: there is a detailed step-by-step guide, in English and German — two installation routes, every dialog field named, and a troubleshooting section: docs/FlowBridge-Synology-EN.pdf · Deutsch

The PDF opens right here on GitHub. The HTML source next to it (docs/FlowBridge-Synology-EN.html) is the same text; download it and open it in a browser if you prefer that.

Supported devices

Model State
RIVER 2 Pro verified against real hardware
DELTA 2 under test on real hardware (field test running)

The DELTA 2 support was derived from documentation and is currently being tried on an actual device for the first time. Until that field test is evaluated it stays documented in the diagnostics report, not verified — the report knows only those two states, and a test in progress is not proof.

Other models will show their readings but may not accept commands. The diagnostics report says so explicitly (documented instead of verified) rather than glossing over it.

What it does

  • Live readings over MQTT push instead of polling — seconds, not minutes
  • Control: AC output, 12 V output, X-Boost, charge limit, discharge limit, charging power, charge pause — through the interface or over MQTT, both through the same code
  • Home Assistant discovery — devices appear on their own
  • Topic export for EisBär SCADA V3/V4 (channel CSV + payload profile XML)
  • Field inventory: records over months which fields your device actually delivers — this is what makes visible when a firmware quietly adds or drops one
  • Diagnostics package: report, masked configuration, topics and log in one ZIP — keys redacted, serial numbers replaced by placeholders
  • Interface in English and German, light and dark, persistently configurable

INV module tab: the raw values exactly as EcoFlow delivers them

Nothing hidden: behind the PD, BMS, EMS, INV and MPPT tabs sit the raw values exactly as EcoFlow delivers them — under their original names.

How it fits together

Topology: EcoFlow cloud → FlowBridge → local broker

What you don't see otherwise

The EcoFlow app shows you how many watts go in and how full the battery is. What it does not show: how much of that arrives.

FlowBridge works it out from measured values. Input, output and battery power come from the device itself, the rest is subtraction — none of it is estimated or modelled.

Measured on a River 2 Pro

AC charge rate at the input into the battery efficiency loss
100 W 105 W 61 W 58 % 42 W
200 W 205 W 157 W 77 % 48 W
500 W 500 W 435 W 87 % 65 W

The reason is the charger: its base draw is largely fixed. At 100 W it eats almost half of it; at 500 W nearly the same amount is spread over five times the energy.

The three measurements sit remarkably close to a straight line:

loss = 36 W + 5.8 % of the input power

  100 W  ->  measured 42 W,  line 42.1 W
  200 W  ->  measured 48 W,  line 47.9 W
  500 W  ->  measured 65 W,  line 65.0 W

Largest deviation 0.1 W. So the charger draws about 36 W simply for being switched on, plus just under 6 % of the power it passes through.

What that means for a full charge

The River 2 Pro holds 768 Wh. From empty to full, using the figures above:

Charge rate from the wall duration
100 W ~1320 Wh ~12.6 h
200 W ~1000 Wh ~4.9 h
500 W ~880 Wh ~1.8 h

Going from 100 to 200 W saves about 320 Wh — going from 200 to 500 W only another 115 or so. The big win is right at the bottom: charging at 100 W costs you a third extra per charge, and you wait two and a half times as long for it.

It runs against what many people bring along from phones and electric cars: charging slowly is not gentler here, it is simply more expensive.

Where the statement ends

What this measurement does not say: whether a high charge rate ages the cells faster. Cycle count and cell temperature are not available over the open API (see the next section). "Cheaper" is proven, "better overall" is not.

Two more caveats, so the numbers are read correctly:

  • The measured AC input includes any load on the AC output. With a consumer plugged in, the figure moves regardless of the charge setting.
  • The instantaneous value fluctuates because input (INV module) and battery power (BMS module) arrive at different moments. The figure over the period is the more reliable one — which is why the dashboard shows it too.

All numbers come from one device. Whether another River 2 Pro shows the same line, nobody knows — which is exactly why FlowBridge computes it for yours instead of claiming it.

What the device will not give you

Honesty belongs in the picture: some things the official interface simply does not provide, and FlowBridge does not pretend the fault is its own.

  • Battery temperature and charge cycles are not delivered by the EcoFlow IoT Open Platform — neither over REST nor over the push channel. Confirmed across a full charge cycle (eight hours, not a single new field). The device knows these values; the official interface just does not pass them on — an old payload set from the unofficial app protocol did contain them.
  • Setpoints that have been written cannot be read back on the River 2 Pro. FlowBridge therefore remembers what it last set.
  • The backup reserve is not accepted by the River 2 Pro over the open interface (measured on the device). It is therefore only displayed, not operated.
  • EcoFlow reports success even when the device silently discards a command. A green result is not proof — only a visible effect is.

Details in docs/quota-fields-river2.md (German).

Documentation

Synology setup — English step by step, two routes, troubleshooting · also as HTML
Synology-Einrichtung — Deutsch the same guide in German · also as HTML
MQTT topics complete topic list (German)
Field comparison River 2 Pro what the interface delivers — and what it does not (German)
Changelog what each version brought · Deutsch

This repository is a mirror, not a working directory: every published version stands here as one commit, the actual development happens elsewhere. What changed between two versions is therefore recorded in the changelog — the number for it is in VERSION and, as an immutable tag, on the matching image on Docker Hub.

Local development

Where things live

src/app.py FastAPI: endpoints, supervisor loop, state, serves the built frontend
src/ecoflow_client.py REST client (HMAC-SHA256 signing, certificate and quota retrieval)
src/ecoflow_mqtt.py push channel of the EcoFlow cloud
src/mqtt_bridge.py publish to the local broker + subscribe to commands
src/device.py normalisation of the quota fields — missing fields are left out, not invented
src/commands_*.py commands per model; what a device does not accept is marked NUR_LESBAR there
src/diagnostics.py log, redaction, diagnostics package
src/inventar.py field inventory
src/exporters.py, src/ha_discovery.py EisBär export, Home Assistant discovery
frontend/ React + Vite + TypeScript
tests/ 374 tests, pytest
pip install -r requirements.txt
cd src && uvicorn app:app --reload --port 8000
cd frontend
npm install
npm run dev

Enable the version hook (once per clone)

git config core.hooksPath scripts/githooks

The pre-commit hook writes the version number to VERSION and puts it into the same commit. Scheme YEAR.MONTH.DAY-COUNTER (e.g. 2026.08.13-02), the counter being how many commits that day. Without the hook enabled the number stays put and the interface reports an outdated version.

Before that, the hook runs every script in scripts/pre-commit.d/, if that folder exists — intended for your own additional steps. It is not needed for building or contributing; if it is absent, the step is skipped.

Access protection

FlowBridge is protected by one password (no user accounts — it is a device on your own network, not a multi-user service). On first start the interface requires you to set one; as long as none is set, the HTTP interface delivers no data at all.

In the container the password can be set on the very first start:

environment:
  - FLOWBRIDGE_PASSWORD=your-password

This removes the window in which FlowBridge is running but no password has been set yet. An existing password is not overwritten by it.

Forgotten it? Delete the auth block from config.yaml and restart.

Important: FlowBridge speaks HTTP. On your own LAN that is acceptable; over the internet it belongs behind a reverse proxy with TLS — otherwise the password travels in the clear.

This does not protect the MQTT side: whoever may write to your broker may also send commands. That is a matter of broker permissions (Mosquitto ACL), and that is where it belongs.

Diagnostics

If something does not work, the diagnostics package in the settings provides everything needed for remote analysis: version, masked configuration, the state of all three connections, field count per device and the log — as a single ZIP file to send.

The order matters: switch logging on → reproduce the fault → download the package.

The most recent lines are always kept in memory, even with logging switched off. Otherwise the switch would not help: whoever sees the fault switches on afterwards — and then it does not come back for an hour.

The log file sits next to config.yaml (inside the container therefore at /config/flowbridge.log), capped at 5 × 5 MB with rotation.

Rotation is by size, not by time. At the measured write rate it reaches back about three to four days; guaranteed are the four full files (~85 h), because right after a rotation the newest file is empty. Older states are deleted silently — an event from the week before last is no longer in there.

Keys, passwords and signatures are redacted before anything is written — already in the file on disk, not only when packing. That is not incidental: this file travels through the internet by e-mail, and with the EcoFlow keys the recipient would have control over the power station.

Serial number and EcoFlow account identifier appear as <GERAET-1> and <KONTO>, not in the clear. The package remains analysable regardless: which model is behind which placeholder is included as a separate mapping — that is the detail needed for analysis, and it identifies no device.

Field inventory

A second, independent record — not for troubleshooting but for long-term observation: which fields does EcoFlow actually deliver?

The occasion was a comparison on 13.08.2026: of 168 fields in an old payload set, 27 still arrive over the official interface. Such shifts happen quietly — EcoFlow rolls out firmware, and the data stream gets wider or narrower.

The trick: this does not need the data stream, it needs an inventory. Per field only first seen, last seen, count, value range — that is a few kilobytes, permanently. The file only grows when a new field appears; the first raw message is then recorded alongside.

  • New field → zuerst carries today's date
  • Field gone → zuletzt stays put and ages

Both channels are recorded with a note of origin (push / rest). That is not cosmetic: the MQTT push demonstrably delivers more fields than quota/all (29 against 20, measured on 13.08.2026).

Switched on in the settings, stored as feldinventar.json next to config.yaml — so it survives restarts and container updates.

Not redacted, unlike the diagnostics package: what is in here are field names and readings, no credentials.

Building it yourself

docker compose -f docker/flowbridge/compose.build.yaml up -d --build

Builds the image from this directory without touching a registry. For the version number inside the image the version hook must be active (see above) — otherwise the interface will report an outdated build.

Configuration

See src/config.example.yaml for reference. config.yaml is normally produced exclusively through the setup UI and is gitignored.

Feedback

Found a bug, got a suggestion, or ran FlowBridge on a device that is not listed above? Write to dirk@cheetahlab.de.

There is no public issue tracker — the repository is self-hosted and mail is the shorter path. For fault reports the diagnostics package is the most useful attachment: it carries version, masked configuration, connection state, topics and log in one ZIP, with keys redacted and serial numbers replaced by placeholders. For a device not yet covered, the field inventory is the interesting file — it shows which fields your unit actually delivers.

License

Apache License 2.0 — see LICENSE, copyright notice in NOTICE.md.

Use it, run it, adapt it, redistribute it, build it into your own software — freely, commercially and in closed products too. The three conditions from section 4 apply: include the license, include NOTICE.md, and mark modified files as modified. The source does not have to be disclosed.

The license also grants patent rights explicitly (section 3) — the point where it goes beyond MIT and BSD.

There is no second license, and none is needed: Apache-2.0 already permits everything a commercial license is usually bought for. The name and the logo are not licensed along with it (section 6), see NOTICE.md.

The libraries used are all permissively licensed (MIT, BSD-3, Apache-2.0, PSF) — which is what made the choice possible in the first place: permissive licenses impose no condition on the license of the whole work. paho-mqtt is dual-licensed and is used here under BSD-3-Clause, certifi is under MPL-2.0 (file-level copyleft) and is shipped unmodified. The complete list with versions is in THIRD-PARTY-NOTICES.md and is to be updated whenever requirements.txt or frontend/package.json changes.

Name and logo are not covered by the license. A derivative is welcome but should be called something else — otherwise two different programs carry the same name.

FlowBridge is an independent project and is not affiliated with EcoFlow. Use of the EcoFlow IoT Open Platform is subject to their own terms; the license of this project does not change that.

About

MQTT-Brücke für mobile Energiespeicher von EcoFlow — eigener Broker, Web-Dashboard, Steuerung. Als Container auf Docker Hub.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages