GoodWe GW5048D-ES mit evcc: RS485, Modbus RTU 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, Modbus RTU und PV-Überschussladen ohne zusätzlichen Smart Meter
Test mit USB auf RS485 Konverter und evcc

Update 12.10.2026: Die Batterieleistung in Register 0x0547 hat bei meinem Gerät entgegen der Protokollbeschreibung kein Vorzeichen. Was das bedeutet und wie ich es löse, steht im Abschnitt „Batterieleistung: Vorsicht beim Vorzeichen“.

Einleitung

Ich wollte meinen GoodWe GW5048D-ES mit [evcc] verbinden, um die Messwerte des Wechselrichters lokal für Energiemanagement und später auch für PV-Überschussladen verwenden zu können.

Dabei bin ich zunächst über die üblichen GoodWe-Modbus-Register gestolpert: Der Wechselrichter antwortete zwar grundsätzlich auf Modbus-Anfragen, aber die Registerbereiche, die von der üblichen goodwe-hybrid-Integration verwendet werden, passten bei meinem Gerät nicht.

Nach einigen Tests ergab sich schließlich ein deutlich besseres Bild:

Der GW5048D-ES kann lokal über RS485 und Modbus RTU ausgelesen werden.

Zusätzlich funktioniert bei diesem Gerät auch das GoodWe-interne AA55-Protokoll. Für die aktuelle Lösung ist Modbus RTU allerdings der deutlich interessantere Weg, weil GoodWe dafür einen eigenen ES-Registerbereich dokumentiert.

Getestet wurde das Ganze mit:

  • GoodWe GW5048D-ES
  • Firmware 2121C
  • RS485
  • Slave-ID 247
  • 9600 Baud, 8N1
  • USB-RS485-Adapter unter Windows
  • evcc 0.315.0
  • MQTT als Schnittstelle zwischen eigener Bridge und evcc

Die Kommunikation erfolgt dabei bewusst lokal. Ich verwende für die Messwerterfassung weder WLAN noch SEMS-Cloud.


Warum nicht einfach goodwe-hybrid in evcc?

Mein erster Versuch war die normale GoodWe-Hybrid-Konfiguration in evcc.

Das Ergebnis war ernüchternd: Einige Register konnten gelesen werden, andere nicht.

Unter anderem führten Abfragen in Bereichen wie 37000 oder 475xx zu Modbus-Fehlern wie:

modbus: exception '2' (illegal data address)

Damit war klar, dass die verwendete Registerzuordnung nicht zu meinem GW5048D-ES passte.

Das ist wichtig: Das bedeutet nicht, dass Modbus am Wechselrichter nicht funktioniert. Es bedeutet lediglich, dass die abgefragten Register für dieses Gerät bzw. diese Plattform nicht die richtigen sind.


RS485-Anschluss am GoodWe

Am unteren Bereich des Wechselrichters befindet sich hinter einer Abdeckung mit der Beschriftung RS485 eine RJ45-Buchse.

Ich habe dafür ein normales Netzwerkkabel verwendet, dieses aufgetrennt und zwei Adern auf meinen USB-RS485-Adapter geführt.

Bei meinem getesteten GW5048D-ES funktionieren:

  • RJ45 Pin 1 → Orange/Weiß
  • RJ45 Pin 2 → Orange

Diese Zuordnung bezieht sich ausdrücklich auf meinen getesteten GW5048D-ES. Ich würde sie nicht pauschal auf andere GoodWe-Modelle oder andere Kommunikationsbuchsen übertragen.

Als USB-RS485-Adapter kommt ein Waveshare Industrial USB to RS485 zum Einsatz.

Die Verbindung läuft mit:

9600 Baud
8 Datenbits
keine Parität
1 Stopbit
Slave-ID 247

Ein Vertauschen der beiden RS485-Leitungen führte bei meinem Test zu einem Timeout. Mit der oben beschriebenen Belegung antwortet der Wechselrichter.


Der entscheidende Fund: ES-Modbus-Register ab 0x0500

Nachdem die üblichen Registerbereiche nicht passten, habe ich einen anderen Registerbereich getestet.

Dabei antwortete der Wechselrichter auf einen normalen Modbus-RTU-FC03-Request:

F7 03 05 00 00 32 D0 45

Das entspricht:

Slave:       247
Function:    03
Start:       0x0500
Anzahl:      50 Register

Die Antwort enthielt die erwarteten 100 Datenbytes und hatte einen gültigen Modbus-CRC.

Noch interessanter wurde es beim Abgleich mit dem GoodWe-Protokoll.

Das von mir vorliegende GoodWe-Protokoll beschreibt für Hybrid-Inverter genau diesen Bereich als Hybrid Inverter Running Data. Die Register beginnen bei 0x0500 und enthalten unter anderem PV-, Batterie-, Netz- und Lastwerte.

Damit war klar:

Der GW5048D-ES spricht nicht nur irgendein proprietäres Protokoll – er liefert seine ES-spezifischen Betriebsdaten auch direkt über normales Modbus RTU.


Die wichtigsten Register

Die für evcc interessanten Werte liegen im Bereich 0x0500 bis 0x0547.

RegisterBedeutungEinheit
0x0500PV1 Spannung0,1 V
0x0501PV1 Strom0,1 A
0x0503PV2 Spannung0,1 V
0x0504PV2 Strom0,1 A
0x0506Batteriespannung0,1 V
0x050ABatteriestrom0,1 A
0x050EBatterie SOC%
0x0511Batterie SOH%
0x0516Netzspannung0,1 V
0x0517Netzstrom0,1 A
0x0518NetzleistungW
0x0519Netzfrequenz0,01 Hz
0x051BBackup-Spannung0,1 V
0x051CBackup-Strom0,1 A
0x051DOn-Grid Load PowerW
0x0521Wechselrichtertemperatur0,1 °C
0x052CTotal PowerW
0x052FNetzrichtungCode
0x0530Backup Load PowerW
0x0544PV1 LeistungW
0x0545PV2 LeistungW
0x0547Batterie-LeistungW

Diese Zuordnung ist im GoodWe-Protokoll direkt dokumentiert. Besonders interessant sind 0x050E für den SOC, 0x0518 für die Netzleistung sowie 0x0544, 0x0545 und 0x0547 für die direkten Leistungswerte.


Netzleistung und Vorzeichen

Bei 0x0518 verwendet GoodWe folgende Richtung:

positiv = Einspeisung ins Netz
negativ = Netzbezug

Das Protokoll beschreibt dies explizit so.

evcc verwendet dagegen die umgekehrte Konvention:

positiv = Netzbezug
negativ = Einspeisung

Deshalb wird in meiner Bridge lediglich das Vorzeichen gedreht:

grid_power_evcc = -goodwe_grid_power

Damit sieht evcc beispielsweise:

GoodWe -500 W  → evcc +500 W Netzbezug
GoodWe +500 W  → evcc -500 W Einspeisung

Batterieleistung: Vorsicht beim Vorzeichen

Ein weiterer Vorteil des RTU-Registersatzes ist 0x0547.

Dort liefert der Wechselrichter direkt die Batterieleistung.

Das Protokoll definiert:

positiv = Batterie entlädt
negativ = Batterie wird geladen

In der Praxis gilt das bei meinem GW5048D-ES (Firmware 2121C) aber nicht. Das Protokoll führt 0x0547 selbst als INT16U, und genau so verhält sich das Register auch: Der Wert bleibt beim Laden positiv. Aufgefallen ist mir das beim Abgleich mit meinem JK-BMS, das die Batterie über CAN unabhängig misst, und mit der Energiebilanz aus PV, Wechselrichter-Ausgang und Netz.

Die Richtung muss also aus einer anderen Quelle kommen. Naheliegend ist der Batteriemodus in 0x0512 (Tabelle 8-9 im Protokoll):

0 = keine Batterie
1 = Standby (weder Laden noch Entladen)
2 = Entladen
3 = Laden
4 = wartet auf Laden
5 = wartet auf Entladen

Auch das ist nur eingeschränkt verlässlich. Bei niedrigem SoC an der Entladegrenze meldet mein Gerät beim Laden teilweise Modus 1, und der Modus springt im Sekundentakt zwischen 1, 2 und 3. Die BMS-Bits „Charging“/„DisCharging“ in 0x0508 setzt mein Wechselrichter überhaupt nicht.

Meine Bridge leitet das Vorzeichen deshalb weiterhin aus dem Modus ab und veröffentlicht zusätzlich den Rohwert als goodwe/battery_power_raw:

battery_power = abs(battery_power_raw) * (-1 if battery_mode == 3 else 1)

Wer ein BMS mit eigener Strommessung hat, sollte die Batterieleistung mit Vorzeichen besser von dort übernehmen. In Home Assistant mache ich das inzwischen so.

Für Energiezähler und Hausverbrauch gibt es zum Glück Werte, die gar kein Batterie-Vorzeichen brauchen:

  • 0x0540/0x0541 und 0x0542/0x0543: kumulierte Lade- bzw. Entladeenergie in 0,1 kWh, direkt vom Wechselrichter
  • 0x052C (Total Power, INT16S) minus Netzleistung: Hausverbrauch auf der AC-Seite, ohne Wandlerverluste
  • 0x0532/0x0533 (Tabelle 8-14): Diagnose-Bits, z. B. „SOC low“ oder „BMS Charge Immediately“. Damit erkennt man, wenn der Wechselrichter an der Entladegrenze zwangsweise nachlädt
house_consumption_ac = total_power - grid_power_goodwe

Warum ich trotzdem auf AA55 gestoßen bin

Während der Untersuchung bin ich zusätzlich auf das GoodWe-AA55-Protokoll gestoßen.

Das war zunächst der entscheidende Durchbruch, weil sich damit die Running Data des ES-Geräts auslesen ließen.

Ein funktionierender Request war:

AA 55 C0 7F 01 06 00 02 45

Die Antwort enthielt unter anderem:

  • Batteriespannung
  • Batterie-SOC
  • Netzspannung
  • Netzleistung
  • PV-Daten
  • Backup/Load-Daten

Der ausgelesene SOC stimmte beispielsweise mit dem Wert aus SolarGo überein.

Auch die Netzleistung konnte mit den angezeigten Werten abgeglichen werden.

Die AA55-Variante war deshalb wichtig, um zunächst zu beweisen, dass die Daten tatsächlich korrekt aus dem Wechselrichter kommen.


Modbus RTU ist jetzt die bevorzugte Lösung

Nachdem ich anschließend den dokumentierten ES-Modbus-Bereich gefunden und erfolgreich gelesen habe, ist AA55 für die eigentliche Bridge nicht mehr notwendig.

Die aktuelle Bridge verwendet deshalb:

Modbus RTU
Function Code 03
Startregister 0x0500

und liest den kompletten relevanten ES-Running-Data-Bereich.

Der prinzipielle Aufbau sieht damit so aus:

GoodWe GW5048D-ES
        │
        │ RS485
        │
        ▼
USB → RS485
        │
        ▼
Python Modbus-Bridge
        │
        │ MQTT
        ▼
      evcc

MQTT als Verbindung zu evcc

Die Python-Bridge liest die GoodWe-Register und veröffentlicht die Werte per MQTT.

Beispielsweise:

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

Zusätzlich werden weitere Werte wie Spannung, Strom, Frequenz, PV1/PV2, SOH und Temperatur veröffentlicht.

Der Vorteil dieser Lösung ist die klare Trennung:

GoodWe
   ↓
Modbus RTU
   ↓
Bridge
   ↓
MQTT
   ↓
evcc

evcc muss dabei nicht selbst die proprietäre GoodWe-Kommunikation verstehen.


Beispielkonfiguration für evcc

In evcc können die MQTT-Werte als benutzerdefinierte Zähler eingebunden werden:

mqtt:
  broker: <MQTT-BROKER>: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

Damit kann evcc bereits:

  • Netzbezug erkennen
  • Einspeisung erkennen
  • PV-Leistung anzeigen
  • Batterie-Leistung anzeigen
  • Batterie-SOC anzeigen
  • Hausverbrauch aus den Messwerten ableiten

Ergebnis

Mit dieser Lösung funktioniert bei meinem GW5048D-ES die komplette lokale Messkette:

GW5048D-ES
     │
     │ RS485
     ▼
Modbus RTU / FC03
     │
     ▼
0x0500 ... 0x0547
     │
     ▼
Python Bridge
     │
     │ MQTT
     ▼
    evcc

Bei meinem Test konnten unter anderem folgende Werte direkt aus dem Wechselrichter gelesen werden:

Batteriespannung
Batterie-SOC
Batterie-SOH
Netzspannung
Netzstrom
Netzleistung
Netzfrequenz
PV1-Leistung
PV2-Leistung
Batterieleistung
Backup/Load
Wechselrichtertemperatur

Die Kommunikation erfolgt dabei vollständig lokal.


Kein WLAN und keine SEMS-Cloud

Für diese Lösung habe ich mich bewusst gegen die Abfrage über WLAN bzw. SEMS-Cloud entschieden.

Das hat bei mir einen praktischen Hintergrund: Bei meinen eigenen Versuchen mit der Abfrage über WLAN/Cloud kam es wiederholt dazu, dass der GoodWe seine komplette Cloud-Verbindung verlor. Das war für mich schlicht zu nervig.

Deshalb wollte ich die Messwerte unabhängig von der Cloud direkt am Wechselrichter auslesen.

Das hier beschriebene Verhalten ist meine persönliche Erfahrung und keine allgemeingültige Aussage über alle GoodWe-Firmwarestände oder WLAN-Module.

Für eine Regelung wie PV-Überschussladen ist eine lokale Messung außerdem grundsätzlich interessanter, weil keine Cloud-Verbindung zwischen Messwert und Regelung liegen muss.


Und funktioniert damit PV-Überschussladen?

Die Messwertseite funktioniert.

evcc bekommt:

  • PV-Leistung
  • Netzleistung
  • Batterie-Leistung
  • Batterie-SOC
  • Hausverbrauch

Damit ist die Grundlage für PV-Überschussladen vorhanden.

Eine Wallbox habe ich aktuell allerdings noch nicht angeschlossen. Das eigentliche Überschussladen konnte ich deshalb mit diesem Setup noch nicht praktisch testen.

Der aktuelle Stand ist also:

GoodWe → RS485 → Modbus RTU → MQTT → evcc
                         ✓

und die Messwerte stehen in evcc zur Verfügung. Zur Richtung der Batterieleistung siehe den Abschnitt zum Vorzeichen weiter oben.

Der nächste praktische Schritt wäre die Kombination mit einer kompatiblen Wallbox und die Überprüfung der Regelung unter realen PV-Bedingungen.


Fazit

Der wichtigste Punkt meiner Untersuchung war letztlich nicht AA55, sondern die Erkenntnis, dass der GW5048D-ES einen eigenen ES-Modbus-Registerbereich ab 0x0500 besitzt und diesen per normalem Modbus RTU / Function Code 03 ausliefert.

AA55 war auf dem Weg dorthin ein sehr hilfreicher alternativer Zugriff und hat gezeigt, dass die Running Data des Wechselrichters lokal verfügbar sind.

Für die dauerhafte Bridge ist der dokumentierte Modbus-RTU-Zugriff aber die sauberere Lösung:

  • kein GoodWe-Cloud-Zugriff
  • kein WLAN erforderlich
  • kein zusätzlicher Smart Meter notwendig
  • direkte Registerwerte
  • SOC direkt verfügbar
  • Netzleistung direkt verfügbar
  • PV-Leistung direkt verfügbar
  • Batterieleistung direkt verfügbar (Richtung über den Batteriemodus, siehe oben)
  • MQTT als einfache Schnittstelle zu evcc

Damit lässt sich der GW5048D-ES lokal und transparent in eine evcc-Installation integrieren.