GoodWe GW5048D-ES mit evcc: RS485, AA55-Protokoll und PV-Überschussladen ohne zusätzlichen Smart Meter

GoodWe GW5048D-ES über RS485 mit evcc verbinden: AA55-Protokoll auslesen, Grid Power, PV, Batterie und SOC per MQTT übertragen und für PV-Überschussladen nutzen.

GoodWe GW5048D-ES mit evcc: RS485, AA55-Protokoll und PV-Überschussladen ohne zusätzlichen Smart Meter

GoodWe GW5048D-ES mit evcc: RS485, AA55-Protokoll und PV-Überschussladen ohne zusätzlichen Smart Meter

Ein GoodWe GW5048D-ES lässt sich nicht immer so einfach mit evcc verbinden, wie es zunächst aussieht. Das Problem: Das verbreitete goodwe-hybrid-Template arbeitet mit Modbus-Registern, die zu anderen GoodWe-Plattformen passen. Beim GW5048D-ES führen diese Abfragen teilweise zu Modbus exception 2 (illegal data address).

In diesem Beitrag zeige ich, wie ich den GoodWe GW5048D-ES über RS485 direkt ausgelesen, das AA55-Laufdatenprotokoll identifiziert, wichtige Messwerte verifiziert und diese anschließend über MQTT als Custom Meter an evcc übergeben habe.

Das Ergebnis ist eine funktionierende Datenkette:

GoodWe GW5048D-ES
        │
        │ RS485
        ▼
GoodWe ES AA55 Bridge
        │
        │ MQTT
        ▼
      evcc
        │
        ▼
PV-Überschussladen
Hinweis: Dieser Beitrag dokumentiert einen reproduzierten Test mit einem GoodWe GW5048D-ES. Andere Modelle und Firmware-Versionen können sich unterscheiden. Die hier beschriebene Lösung sollte deshalb als Community-Lösung und nicht als offizielle GoodWe- oder evcc-Dokumentation verstanden werden.

1. Ausgangssituation

Ziel war es, einen GoodWe GW5048D-ES Hybridwechselrichter mit evcc zu verbinden und die Informationen zu verwenden, die für späteres PV-Überschussladen einer Wallbox erforderlich sind.

Der zusätzliche Kauf bzw. Einbau eines separaten Smart Meters sollte möglichst vermieden werden.

Das Setup für den ersten Test:

  • GoodWe GW5048D-ES
  • USB-RS485-Adapter
  • Windows
  • COM3
  • 9600 Baud
  • 8N1
  • evcc 0.315.0
  • MQTT-Broker im lokalen Netzwerk

Der erste Ansatz war das in evcc vorhandene GoodWe-Hybrid-Template.


2. Das Problem mit goodwe-hybrid

Die Verbindung über RS485 funktionierte grundsätzlich.

Der GoodWe antwortete auf Modbus-Abfragen. Allerdings schlugen bestimmte Register mit:

modbus: exception '2' (illegal data address)

fehl.

Beispielsweise lieferte die Abfrage:

f7 03 b9 95 00 01 a5 ec

eine Modbus-Ausnahme.

0xB995 entspricht dabei Register 47509.

Auch weitere Bereiche wie 37000, 36000 und 47900 waren beim getesteten ES-Gerät nicht brauchbar.

Das war ein wichtiger Hinweis:

RS485 funktioniert, aber das verwendete Registermodell passt nicht zu diesem GoodWe.

Das ist nachvollziehbar, wenn man sich die unterschiedlichen GoodWe-Plattformen ansieht. Die aktuelle Python-Bibliothek goodwe unterscheidet unter anderem die ES-Familie von anderen Modellplattformen. In der aktuellen Implementierung gehören unter anderem ESU/EMU/ESA/BPS/BPU/EMJ/IJL zur Plattform 105.


3. Erste erfolgreiche Modbus-Register

Bevor das AA55-Protokoll gefunden wurde, konnten einige klassische Modbus-Register erfolgreich gelesen werden.

Unter anderem:

35105–35118
35191–35192

Das bewies endgültig, dass die Kommunikation mit:

Slave ID: 247
Baudrate: 9600
Format: 8N1

funktioniert.

Eine interessante Beobachtung war außerdem ein Wert im Bereich um Register 35172, der sich bei einer Laständerung deutlich veränderte.

Mit einem Heizgerät/Fön mit ungefähr 2 kW Leistung konnte die Last beispielsweise von ungefähr:

~800 W

auf ungefähr:

~2700–3000 W

steigen.

Damit ließ sich zumindest empirisch bestätigen, dass Daten aus dem Gerät die tatsächliche Laständerung abbilden.

Für die endgültige Lösung war dieser Ansatz aber nicht der richtige.


4. Der entscheidende Hinweis: GoodWe AA55

Der Durchbruch kam durch die Analyse der GoodWe-ES-Unterstützung der Open-Source-Python-Bibliothek goodwe.

Die aktuelle goodwe-Implementierung verwendet für die ES/EM/BP-Familie ein anderes Protokoll als die ET-Familie.

Für die Laufdaten wird dort das AA55-Protokoll verwendet:

Request: 010600
Response: 0186

Die entsprechende Implementierung befindet sich in goodwe/es.py. Dort sind auch die Datenfelder des Running-Data-Frames definiert.

Damit ergab sich ein komplett anderer Ansatz:

Nicht mehr versuchen, die falschen GoodWe-Modbus-Register zu erraten, sondern direkt das AA55-Running-Data-Telegramm des ES auslesen.

5. Das funktionierende AA55-Telegramm

Mit dem RS485-Adapter an COM3 konnte folgende Anfrage erfolgreich gesendet werden:

AA 55 C0 7F 01 06 00 02 45

Der Wechselrichter antwortete mit einem 149 Byte langen Telegramm.

Ein Beispiel:

aa 55 7f c0 01 86 8c 00 00 00 00 00 00 00 00 00 00
01 ff 00 02 00 50 00 f0 00 00 00 50 00 64 00 00 0e
00 0e 5f 01 00 00 01 09 37 00 05 01 8f 13 83 01 09 37
00 03 01 6e 13 83 01 02 01 08 00 00 00 00 00 04 04 68
00 00 8e 04 00 9c 00 b9 00 02 e6 ef ff e1 01 00 30 02
00 00 00 01 00 00 fc 89 11 08 00 06 00 00 1a 09 03 16
20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 01 04 6e 00 00 fe 8f 02 00 00 00
00 00 00 13 e8

Länge:

149 Bytes

Damit war die komplette Kommunikationskette zum GoodWe bewiesen.


6. Die Struktur des AA55-Frames

Das Telegramm beginnt mit einem Header:

AA 55 7F C0 01 86 8C

Danach beginnt der eigentliche Datenbereich.

Die Offsets der aktuellen goodwe/es.py-Implementierung beziehen sich auf diesen Datenbereich.

Einige der wichtigsten Felder:

OffsetFeldBedeutung
0vpv1PV1-Spannung
2ipv1PV1-Strom
5vpv2PV2-Spannung
7ipv2PV2-Strom
10vbattery1Batteriespannung
18ibattery1Batteriestrom
26battery_socBatterie-SOC
29battery_sohBatterie-SOH
30battery_modeBatteriemodus
34vgridNetzspannung
36igridNetzstrom
38–39pgridNetzleistung
40fgridNetzfrequenz
43vloadBackup-/Load-Spannung
45iloadBackup-/Load-Strom
47ploadBackup-/Load-Leistung
49floadBackup-/Load-Frequenz
53temperatureWechselrichtertemperatur
67e_dayPV-Energie heute
69e_load_dayLoad-Energie heute
80grid_in_outNetzrichtung

Die Felddefinitionen entsprechen der aktuellen Open-Source-Implementierung für die GoodWe-ES-Plattform.


7. Der wichtigste Treffer: Battery SOC

Ein sehr guter Test für die korrekte Dekodierung war der Batterie-SOC.

Im getesteten Telegramm liegt am entsprechenden Offset:

0E

also:

14

Der Wechselrichter meldete gleichzeitig in SolarGo:

Batterie: 14 %

Damit war die SOC-Dekodierung eindeutig bestätigt.


8. Der entscheidende Treffer: Netzleistung

Noch wichtiger war die Netzleistung.

Im AA55-Datenbereich liegt pgrid bei Offset 38–39.

Das Telegramm enthielt:

01 8F

Das entspricht:

399 W

Zusätzlich enthält Offset 80 die Richtung des Netzflusses.

Im Test:

Grid direction code = 2

Die GoodWe-Implementierung interpretiert diesen Zustand als Netzbezug und gibt entsprechend eine negative Leistung aus.

Damit wurde:

Grid power = -399 W

ermittelt.

Gleichzeitig zeigte SolarGo:

Strom importieren ≈ 0,40 kW

Damit konnte die Netzleistung unabhängig verifiziert werden.

Das war der entscheidende Beweis, dass die AA55-Laufdaten nicht nur syntaktisch korrekt gelesen werden, sondern tatsächlich die relevanten realen Messwerte des Wechselrichters enthalten.


9. Eigener Python-Decoder

Für die weitere Entwicklung wurde zunächst ein eigener Decoder geschrieben.

Die Grundidee:

REQUEST = bytes.fromhex(
    "AA 55 C0 7F 01 06 00 02 45"
)

Danach wird die Antwort ab Byte 7 als Datenbereich interpretiert.

Beispielhafte Dekodierung:

data = frame[7:]

battery_soc = data[26]

grid_power = int.from_bytes(
    data[38:40],
    "big",
    signed=True
)

grid_direction = data[80]

if grid_direction == 2:
    grid_power = -abs(grid_power)
else:
    grid_power = abs(grid_power)

Die eigentliche GoodWe-Implementierung berücksichtigt zusätzlich die jeweiligen Skalierungen und Vorzeichen der einzelnen Werte.


10. Ergebnis des Decoders

Ein realer Test lieferte:

=== GOODWE ES ===
PV1 voltage             : 0.0
PV1 current             : 0.0
PV1 power               : 0
PV2 voltage             : 0.0
PV2 current             : 0.0
PV2 power               : 0
Battery voltage         : 51.1
Battery current         : 0.0
Battery power           : 0
Battery SOC             : 14
Battery SOH             : 95
Battery mode            : 1
Grid voltage            : 235.9
Grid current            : 0.5
Grid power              : -399
Grid frequency          : 49.95
Grid mode               : 1
Backup voltage          : 235.9
Backup current          : 0.3
Backup power            : 366
Backup frequency        : 49.95
Inverter temperature    : 26.4
Today's PV energy       : 15.6
Today's load energy     : 18.5
Grid direction code     : 2
House consumption       : 399

Besonders relevant:

Battery SOC:       14 %
Grid power:      -399 W
Grid voltage:    235,9 V
Grid frequency:   49,95 Hz
Battery voltage:  51,1 V

11. Belastungstest mit einem ca. 2-kW-Fön

Um die Netzleistungsmessung nicht nur im Leerlauf zu testen, wurde eine größere elektrische Last zugeschaltet.

Die Bridge meldete zunächst:

Grid -374 W
Load  374 W

Danach:

Grid -1556 W
Load 1556 W

und anschließend:

Grid -2151 W
Load 2151 W

Grid -2166 W
Load 2166 W

Grid -2171 W
Load 2171 W

Die Änderung liegt damit sehr nahe an der erwarteten Leistung des Heizgeräts.

Dieser Test ist wichtig, weil er zeigt:

Die Messung reagiert nicht nur auf einen einzelnen festen Wert, sondern folgt der tatsächlichen elektrischen Last.

12. Von GoodWe zu MQTT

Nachdem die direkte AA55-Kommunikation funktionierte, wurde daraus eine kleine Bridge.

Aufbau:

GoodWe GW5048D-ES
        │
        │ RS485
        ▼
goodwe_es_bridge.py
        │
        │ MQTT
        ▼
MQTT Broker

Die Bridge läuft zunächst unter Windows mit:

COM3
9600 Baud
8N1

und verbindet sich anschließend mit dem MQTT-Broker.

Beispiel:

MQTT Broker:
192.168.178.21:1883

Die Bridge liest die GoodWe-Daten zyklisch aus und veröffentlicht die Werte per MQTT.


13. Vorzeichenkonvention für evcc

Ein wichtiger Punkt war die Anpassung der Vorzeichen.

Der GoodWe-Decoder liefert Netzbezug in diesem Test zunächst als:

-399 W

evcc verwendet für einen Netzzähler dagegen:

positiv  = Netzbezug
negativ  = Einspeisung

Diese Konvention ist in der aktuellen evcc-Dokumentation für Zähler explizit beschrieben. Für einen grid-Zähler bedeutet ein positiver power-Wert Netzbezug; beim Batterie-Zähler bedeutet positiv Entladen und negativ Laden.

Deshalb konvertiert die Bridge den GoodWe-Netzwert für evcc.

Aus:

GoodWe:
-211 W

wird:

evcc:
+211 W

Das war später im evcc-Webinterface direkt sichtbar.


14. MQTT-Datenpunkte

Die Bridge stellt unter anderem folgende Daten bereit:

goodwe/grid_power
goodwe/pv_power
goodwe/battery_power
goodwe/battery_soc
goodwe/house_consumption

Zusätzlich können weitere Messwerte veröffentlicht werden, zum Beispiel:

goodwe/grid_voltage
goodwe/grid_current
goodwe/grid_frequency

goodwe/pv1/power
goodwe/pv2/power

goodwe/battery_voltage
goodwe/battery_current

goodwe/load_power

Damit ist die Bridge nicht nur für evcc interessant, sondern grundsätzlich auch für andere Systeme, die MQTT lesen können.


15. Integration in evcc

evcc unterstützt benutzerdefinierte Geräte und Zähler über type: custom. Als Datenquelle kann unter anderem MQTT verwendet werden. Ein Custom-Meter kann beispielsweise seine aktuelle Leistung über ein MQTT-Topic beziehen. Auch ein Batterie-Zähler kann zusätzlich soc aus MQTT lesen.

Die erste Konfiguration war bewusst klein:

mqtt:
  broker: 192.168.178.21:1883
  topic: evcc

meters:
  - name: goodwe_grid
    type: custom
    power:
      source: mqtt
      topic: goodwe/grid_power
      timeout: 30s

site:
  title: Home
  meters:
    grid: goodwe_grid

Anschließend meldete evcc:

meters: grid ✓

und im Webinterface erschien der tatsächliche Netzbezug.


16. PV und Batterie ergänzen

Nachdem der Grid-Meter funktionierte, wurden PV und Batterie ebenfalls als Custom-Meter eingebunden.

Die Konfiguration:

mqtt:
  broker: 192.168.178.21:1883
  topic: evcc

meters:
  - name: goodwe_grid
    type: custom
    power:
      source: mqtt
      topic: goodwe/grid_power
      timeout: 30s

  - name: goodwe_pv
    type: custom
    power:
      source: mqtt
      topic: goodwe/pv_power
      timeout: 30s

  - name: goodwe_battery
    type: custom
    power:
      source: mqtt
      topic: goodwe/battery_power
      timeout: 30s
    soc:
      source: mqtt
      topic: goodwe/battery_soc
      timeout: 30s

site:
  title: Home
  meters:
    grid: goodwe_grid
    pv: goodwe_pv
    battery: goodwe_battery

evcc bestätigte daraufhin:

site config:
  meters:      grid ✓ pv ✓ battery ✓
    grid:      power ✓
    pv 1:      power ✓
    battery 1: power ✓ soc ✓

Damit waren alle für das grundlegende Energieflussmodell benötigten Messwerte vorhanden.


17. Was evcc aktuell tatsächlich sieht

Der aktuelle Testzustand sieht beispielsweise so aus:

Grid       +177 W
PV            0 W
Battery       0 W
Battery SOC  14 %
Load        177 W

Im evcc-Webinterface:

Erzeugung       0 W
Netzbezug      177 W
Verbrauch      177 W
Ladepunkt        0 W
Einspeisung      0 W

Damit funktioniert die komplette Strecke:

GoodWe
  ↓
RS485
  ↓
AA55
  ↓
Python Bridge
  ↓
MQTT
  ↓
evcc
  ↓
Webinterface

18. Welche Werte brauchen wir für PV-Überschussladen?

Für das eigentliche PV-Überschussladen ist der Netzleistungswert der zentrale Messwert.

evcc muss wissen, ob gerade:

Netzbezug

oder

Einspeisung

stattfindet.

Die zusätzlichen Messwerte machen das Energieflussmodell vollständiger:

Grid Power       ✅
PV Power         ✅
Battery Power    ✅
Battery SOC      ✅
House Load       ✅

Damit kann evcc erkennen, wie die Energie gerade im Haus verteilt wird.

Die aktuellen evcc-Custom-Meter unterstützen power als erforderliches Messattribut sowie optional energy und beim Batteriezähler soc.


19. Was noch nicht getestet wurde

Zum Zeitpunkt dieses Tests war noch keine Wallbox angeschlossen.

Deshalb ist das eigentliche Laden noch nicht praktisch getestet.

Die GoodWe-Seite ist jedoch bereits soweit vorbereitet, dass die später benötigten Energieinformationen über MQTT zur Verfügung stehen.

Der nächste Schritt ist daher die Integration der eigentlichen Wallbox in evcc.

Dabei kommen zusätzlich Wallbox-spezifische Werte und Steuerbefehle ins Spiel, insbesondere:

Ladeleistung
Ladestrom
Status
1-/3-Phasen-Betrieb
Ein/Aus
maximaler Ladestrom

Diese Informationen stammen von der Wallbox selbst und sind unabhängig vom GoodWe-Teil.


20. Ein wichtiger Punkt: Phasenmessung

Der bisherige GoodWe-Test arbeitet mit einer Gesamtleistung.

Für eine spätere Wallbox mit 1-/3-Phasen-Umschaltung können Phasenwerte interessant werden.

Die aktuelle evcc-Dokumentation unterstützt für Netzzähler und Wallboxen auch:

currents
voltages
powers

als dreiphasige Werte.

Für den ersten Überschusslade-Test ist das aber nicht zwingend erforderlich.


21. Warum MQTT statt eines evcc-Forks?

Die Lösung wurde bewusst als eigenständige Bridge aufgebaut.

Damit bleibt die Architektur:

GoodWe-spezifische Kommunikation
            ↓
        Bridge
            ↓
           MQTT
            ↓
          evcc

Der Vorteil:

  • evcc muss nicht gepatcht werden
  • evcc-Updates bleiben einfach
  • die GoodWe-Kommunikation ist unabhängig
  • dieselben Daten können später auch von Home Assistant oder anderen Systemen verwendet werden
  • die Bridge kann unter Windows und Linux betrieben werden
  • Docker ist problemlos möglich

evcc stellt für benutzerdefinierte Geräte und Zähler ausdrücklich MQTT als Plugin-Quelle bereit.


22. Linux und Docker

Die Bridge wurde deshalb nicht als reines Windows-Provisorium aufgebaut.

Unter Windows ist der serielle Port:

COM3

Unter Linux wird der USB-RS485-Adapter typischerweise als Gerät wie:

/dev/ttyUSB0

oder

/dev/ttyACM0

sichtbar.

Die spätere Docker-Architektur kann daher ungefähr so aussehen:

Linux Host
│
├── USB-RS485
│       │
│       ▼
│   /dev/ttyUSB0
│       │
│       ▼
│  ┌────────────────┐
│  │ GoodWe ES      │
│  │ Bridge         │
│  └───────┬────────┘
│          │
│          │ MQTT
│          ▼
│  ┌────────────────┐
│  │ MQTT Broker    │
│  └───────┬────────┘
│          │
│          ▼
│  ┌────────────────┐
│  │ evcc            │
│  └────────────────┘
│
└────────────────────

Der Vorteil ist, dass sich am eigentlichen GoodWe-Protokoll nichts ändern muss. Nur der serielle Gerätepfad wird von COM3 auf /dev/ttyUSB0 angepasst.


23. Aktueller Stand

Der bisherige Entwicklungsstand lässt sich so zusammenfassen:

FunktionStatus
RS485 Kommunikation
GoodWe ID 247
9600 / 8N1
AA55 Running Data
PV-Daten
Batterie-Spannung
Batterie-Leistung
Batterie-SOC
Batterie-SOH
Netzspannung
Netzstrom
Netzleistung
Netzrichtung
Netzfrequenz
Load/Backup
Wechselrichtertemperatur
PV-Energie heute
Load-Energie heute
MQTT-Ausgabe
evcc Grid Meter
evcc PV Meter
evcc Batterie Meter
evcc Battery SOC
Wallbox
echtes PV-Überschussladen
Docker unter Linux

24. Was wir gelernt haben

Die wichtigste Erkenntnis aus dem gesamten Test war:

Beim GoodWe GW5048D-ES sollte man nicht automatisch davon ausgehen, dass die Modbus-Register anderer GoodWe-Hybridmodelle verwendet werden können.

Beim hier getesteten Gerät waren viele der zunächst getesteten Register nicht erreichbar.

Der funktionierende Weg war dagegen:

GoodWe GW5048D-ES
        ↓
RS485
        ↓
AA55 Running Data
        ↓
Python Decoder
        ↓
MQTT
        ↓
evcc

Besonders hilfreich war, dass sich die Daten mit SolarGo gegenprüfen ließen.

Der SOC von:

14 %

und ein Netzbezug von ungefähr:

400 W

stimmten mit den aus dem AA55-Telegramm dekodierten Daten überein.

Der Lasttest mit einem ungefähr 2-kW-Verbraucher bestätigte zusätzlich, dass die Messwerte dynamisch auf die reale Last reagieren.


25. Quellen und weiterführende Informationen

Die GoodWe-Python-Bibliothek enthält aktuell eine eigene Implementierung für die ES/EM/BP-Familie und beschreibt die entsprechenden Datenfelder des ES-Running-Data-Protokolls:

Die GoodWe-Bibliothek ist ein Open-Source-Projekt und unterstützt verschiedene GoodWe-Geräte und Protokollvarianten. Eine entsprechende ES/AA55-Kommunikation wurde auch bereits von anderen Nutzern in der Entwicklung bzw. in Issues thematisiert.