https://github.com/mavnezz/charge44
Home Assistant custom integration: zero-export regulation for Zendure SolarFlow 800 Pro + Shelly 3EM Pro via local MQTT, with Tibber-priced cheap charging and Forecast.Solar smart-skip
https://github.com/mavnezz/charge44
hacs home-assistant mqtt photovoltaic shelly solarflow tibber zendure zero-export
Last synced: about 2 months ago
JSON representation
Home Assistant custom integration: zero-export regulation for Zendure SolarFlow 800 Pro + Shelly 3EM Pro via local MQTT, with Tibber-priced cheap charging and Forecast.Solar smart-skip
- Host: GitHub
- URL: https://github.com/mavnezz/charge44
- Owner: mavnezz
- License: mit
- Created: 2026-04-23T11:16:11.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-04-23T14:23:10.000Z (about 2 months ago)
- Last Synced: 2026-04-23T14:35:07.848Z (about 2 months ago)
- Topics: hacs, home-assistant, mqtt, photovoltaic, shelly, solarflow, tibber, zendure, zero-export
- Language: Python
- Size: 22.5 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# charge44
[](https://github.com/mavnezz/charge44/releases)
[](LICENSE)
[](https://hacs.xyz)
[](https://github.com/mavnezz/charge44/actions/workflows/validate.yaml)
Home Assistant Custom Integration zur Steuerung einer **Zendure SolarFlow 800 Pro** per lokalem MQTT. Kombiniert dynamische Nulleinspeisung (Regelung gegen einen Shelly 3EM Pro) mit preisbasiertem Netzladen (Tibber) und Solar-Prognose-Abgleich (Forecast.Solar).
Keine Cloud, keine Zwischenschicht — direkt auf dem eigenen MQTT-Broker.
## Was kann das Plugin
### 1. Nulleinspeisung (Regelung)
Liest die Live-Netzleistung vom Shelly 3EM Pro und regelt `outputLimit` der Zendure so, dass der Bezug/die Einspeisung in der Nähe eines konfigurierbaren Zielwerts bleibt (Default 0 W).
### 2. Preisbasiertes Netzladen (Cheap-Charge)
Mit Tibber-API-Token holt das Plugin die Strompreise der nächsten 24 Stunden. In den N günstigsten Stunden wird die Zendure auf **Input mode** geschaltet und mit `inputLimit` aus dem Netz geladen — vorausgesetzt der Spread zwischen aktuellem Preis und Tagesmax lohnt sich unter Berücksichtigung des Wirkungsgrads.
### 3. Smart-Skip via Solar-Prognose
Wenn die `forecast_solar`-Integration in HA installiert ist, wird die erwartete Solarerzeugung des Resttages gegen den Ladebedarf gerechnet. **Reicht die Sonne alleine zum Erreichen des Ziel-SOC → kein Netzladen, auch wenn der Preis gerade günstig ist.**
## Hardware-Voraussetzungen
- Zendure SolarFlow 800 Pro mit aktivierter lokaler MQTT-Konfiguration (direkt am Gerät eingetragen). Das Gerät muss auf Topics wie `Zendure/sensor//...` publizieren und auf `.../set` lauschen.
- Shelly 3EM Pro (oder kompatibel), der `total_act_power` in `/events/rpc` publiziert.
- Beide Geräte am selben MQTT-Broker wie Home Assistant.
- (Optional) Tibber-Account + API-Token für preisbasiertes Laden.
- (Optional) Forecast.Solar-Integration für Smart-Skip.
## Installation
### HACS (empfohlen)
1. HACS → Integrationen → ⋮ → **Benutzerdefinierte Repositories**
2. URL `https://github.com/mavnezz/charge44` als Typ *Integration* hinzufügen
3. charge44 in der Liste auswählen und installieren
4. Home Assistant neu starten
5. Einstellungen → Geräte & Dienste → **Integration hinzufügen** → charge44
### Manuell
Ordner `custom_components/charge44/` nach `/custom_components/charge44/` kopieren, HA neu starten.
## Einrichtung
Drei Schritte im Config-Flow:
1. **Geräte** — Das Plugin scannt MQTT 3 Sekunden lang und bietet gefundene Zendure-SNs und Shelly-IDs als Dropdown an. Manuelle Eingabe möglich falls nicht erkannt.
2. **Tibber + Solar-Prognose** (beide optional) — Token eingeben und Solar-Sensor auswählen. Leer lassen, wenn nur Nulleinspeisung genutzt werden soll.
3. **Tibber-Zuhause** — nur wenn mehrere Homes am Account hängen.
## Entitäten
### Sensoren
| Entity | Beschreibung |
|---|---|
| `sensor.charge44_grid_power` | Netz-Saldo (Shelly) |
| `sensor.charge44_grid_import` / `_export` | Nur positiver Bezug/Export, für Energy Dashboard |
| `sensor.charge44_battery_soc` | SOC % |
| `sensor.charge44_battery_charging` / `_discharging` / `_net_flow` | Batterie-Fluss (W) |
| `sensor.charge44_solar_input` | PV-Eingang |
| `sensor.charge44_output_to_home` | Zendure → Haus |
| `sensor.charge44_output_limit_device` | aktueller Zendure-Setpoint |
| `sensor.charge44_regulation_setpoint` / `_error` | Plugin-Regler |
| `sensor.charge44_pack_state`, `_temperature` | Status + Temperatur |
| `sensor.charge44_current_price` | Aktueller Strompreis (ct/kWh) |
| `sensor.charge44_cheap_hour` | "yes"/"no" — aktuelle Stunde im Cheap-Fenster |
| `sensor.charge44_cheap_charge_active` | "on"/"off" — Gerät gerade im Ladezyklus |
| `sensor.charge44_next_cheap_window` | Timestamp der nächsten Cheap-Stunde |
| `sensor.charge44_solar_forecast_remaining` | kWh Sonne bis Tagesende |
| `sensor.charge44_grid_charge_needed` | Shortfall zum Erreichen des Ziel-SOC |
| `sensor.charge44_today_min_price` / `_max_price` | Tagesmin/-max (ct/kWh) |
| `sensor.charge44_spread_now` | aktuelle Differenz Tagesmax − jetzt |
| `sensor.charge44_required_spread` | benötigter Spread laut Min-Spread + Break-Even |
| `sensor.charge44_charge_profitable` | "yes"/"no" — Laden würde sich lohnen |
### Einstellungen (Number)
| Entity | Default | Bedeutung |
|---|---|---|
| `number.charge44_grid_bias_target` | 0 W | Sollwert des Netzsaldos (negativ = leichte Einspeisung erlaubt) |
| `number.charge44_max_output` | 800 W | Obergrenze für outputLimit |
| `number.charge44_minimum_soc` | 10 % | Plugin-seitige Entlade-Untergrenze |
| `number.charge44_controller_gain_kp` | 0,5 | P-Regler-Verstärkung |
| `number.charge44_cheap_hours_per_day` | 6 | Wie viele günstigste Stunden pro 24h zählen als "cheap" |
| `number.charge44_charge_target_soc` | 80 % | Obergrenze für Cheap-Charge |
| `number.charge44_cheap_charge_power` | 800 W | `inputLimit` beim Netzladen |
| `number.charge44_min_price_spread` | 10 ct/kWh | Mindestspread (Tagesmax − aktuell) für Lohnenswert |
| `number.charge44_round_trip_efficiency` | 85 % | Wirkungsgrad für Break-Even-Berechnung |
| `number.charge44_battery_capacity` | 1,92 kWh | Akkukapazität (für Ladebedarf-Schätzung) |
### Schalter
- `switch.charge44_regulation` — Nulleinspeisung an/aus
- `switch.charge44_cheap_charge` — Automatisches Cheap-Charging an/aus
## Logik im Detail
### Regelung (pro Shelly-Tick, ~5 s)
```
error = grid_power - grid_bias
setpoint += error × Kp
setpoint = clamp(0, max_output)
→ Zendure/number//outputLimit/set
```
Hysterese: nur publizieren wenn Änderung > Deadzone (5 W) UND letzter Publish ≥ 3 s her.
### Cheap-Charge-Entscheidung (pro Minute)
```
cheap_hour = current_price ist in N günstigsten der nächsten 24 h
spread_now = today_max - current_price
break_even = current_price × (1 / efficiency - 1)
required_spread = max(min_spread_ct, break_even)
profitable = spread_now ≥ required_spread
needed_kwh = (target_soc - soc) / 100 × battery_capacity
forecast_kwh = Forecast.Solar-Sensor (kWh remaining today)
gap = max(0, needed_kwh - forecast_kwh)
charge, wenn: cheap_charge_enabled
∧ cheap_hour
∧ profitable
∧ soc < target_soc
∧ gap > 0
```
### Modus-Wechsel
Beim Eintritt in Cheap-Charge publiziert das Plugin:
```
Zendure/select//acMode/set → "Input mode"
Zendure/number//inputLimit/set → charge_power
```
Beim Verlassen umgekehrt. Die Nulleinspeisungs-Regelung pausiert während Cheap-Mode aktiv ist.
## Bekannte Einschränkungen
- Einzelne Instanz (single_instance_allowed)
- Aktuell nur für **Zendure 800 Pro** + **Shelly 3EM Pro** getestet; andere Geräte mit gleicher Topic-Struktur sollten funktionieren, sind aber nicht verifiziert
- Keine Options-Flow-Nachkonfiguration; zum Ändern von Tibber-Token oder Forecast-Entity aktuell Integration entfernen und neu hinzufügen
## Versionen
Siehe [GitHub Releases](https://github.com/mavnezz/charge44/releases).
## Lizenz
MIT