sphings-dev.de

Marstek Modbus Suite 1.1: Die Venus D gegen die Firmware geprüft

Die Marstek Modbus Suite ist als Fork der Integration Marstek Venus Modbus von ViperRNMC gestartet, mit der Venus D im Mittelpunkt. Der Anlass waren Aussetzer, bei denen der Modbus-Dienst des Speichers nicht mehr antwortete. Die Pre-Releases 1.0.0-dev bis 1.0.6-dev und das erste reguläre Release 1.1.0 beschreiben den Weg von „sehr viele neue Register“ zu „jedes Register ist belegt und nachgemessen“.

Ausgangspunkt: 186 neue Entitäten für die Venus D

1.0.0-dev baut auf dem Upstream-Stand 2026.8.1.b1 auf. Die Registerdatei der Venus D wächst von 113 auf 299 Definitionen. Pro Pack (1 bis 6, im Abstand von 0x100 ab Register 34000) kommen Ladezustand, Spannung, Strom, Zykluszähler, MOS-Status, BMS-Version, die Zellspannungsextreme, zwei Schutz-Bitmasken, Umgebungs- und MOSFET-Temperatur sowie vier Zell-NTC-Werte dazu. Hinzu kommen 96 Einzelzellspannungen, 16 je Pack.

Nur zwei der 186 neuen Entitäten sind standardmäßig aktiv: fault_status und solar_power_total. Alles andere ist deaktiviert, mit gutem Grund. Dazu eine offene Warnung: Das Einschalten der Zellspannungsblöcke (34018–34033 plus 0x100 je Pack) den Modbus des Geräts blockieren. Außerdem gibt es drei bekannte Transportfehler, die noch offen waren: Der pymodbus-Client lief ohne Timeout, das Backoff schloss einzelne Register nicht aus Blockzugriffen aus, und Modbus-Ausnahmeantworten wurden nicht von Timeouts unterschieden.

Illustration der Geräteseite in Home Assistant mit den Sensoren, die die Marstek Modbus Suite anlegt
Illustration, kein Foto einer laufenden Instanz.

Eine Tabelle aus der Firmware statt Vermutungen

Der Wendepunkt ist 1.0.2-dev. Die Modbus-Deskriptortabelle der Firmware v150 liegt vollständig dekodiert vor, und jeder Eintrag nennt den SRAM-Zeiger, aus dem das Register liest. Zeigen zwei Register auf dieselbe Adresse, sind sie nachweislich dieselbe Messung. Daraus folgte, dass sieben Sensoren entfallen mussten:

  • max_cell_voltage und min_cell_voltage (37007/37008) lasen dieselben Wörter wie die Extremwerte von Pack 1. Sie sahen aus wie Gerätewerte, waren aber nur Pack 1. Eine gerätweite minimale oder maximale Zellspannung gibt es im gesamten Registersatz nicht.
  • ac_current (37004) las die Netzleistung, mit 0,004 skaliert und als Ampere beschriftet. Der Sensor war standardmäßig aktiv, also zeigte jede Venus-D-Installation diesen Wert.
  • ac_offgrid_current (32301) war die Off-Grid-Spannung, dasselbe Wort wie Register 32300.
  • internal_mos2_temperature (35002) war derselbe Kühlkörpersensor wie MOS1. Das Gerät hat nur einen.

Dazu kamen zwei Register, die in 1.0.1-dev als eigener Backup-Ausgang aufgenommen worden waren (30005 und 30007). Eine Registernotiz führte sie als separaten Messpunkt, eine andere als Duplikate – ich habe das ausdrücklich als offene Frage festgehalten und die Sensoren deaktiviert ausgeliefert. Die Deskriptortabelle klärte es: Es sind alternative Adressen auf Off-Grid-Spannung und -Leistung. Die Sensoren wurden zurückgezogen.

Wichtig fürs Update: Home Assistant löscht Entitäten nicht, wenn eine Integration sie nicht mehr liefert. Sie bleiben als „nicht verfügbar“ in der Registry und müssen auf der Geräteseite von Hand entfernt werden.

Der Auslöser der Aussetzer: ein Register, das es nicht gibt

1.0.5-dev behob die eigentliche Ursache der Hänger. ac_offgrid_power war als int32 mit count: 2 deklariert, also fragte jeder Durchlauf die Register 32302 und 32303 ab. Die Firmware kennt 32302 als einzelnes i16-Register und hat für 32303 gar keinen Eintrag. Der Lesezugriff lief über das Ende der Deskriptorregion hinaus, und der Modbus-Stack des Geräts antwortete nicht mehr. Zwei unabhängige Fehlerlogs nennen 32302 als erste Fehlerstelle, binnen 200 ms folgt jeweils „Not connected“ beim nächsten, unbeteiligten Read.

Alle Leseregister wurden danach gegen die Tabelle geprüft; ac_offgrid_power war die einzige Definition, die über ihren Eintrag hinauslas. Dass es so lange unentdeckt blieb, liegt daran, dass der Sensor standardmäßig deaktiviert ist – der Fehler tritt erst auf, wenn jemand die Off-Grid-Werte einschaltet, also ausgerechnet dann, wenn man sich für den Backup-Ausgang interessiert. Korrigiert ist das in d.yaml und a.yaml; die Venus A teilt die Firmware-Basis. e_v12.yaml blieb mit Absicht unangetastet, weil die Venus E v1/v2 auf einer völlig anderen Firmware läuft und nichts aus A-, D- oder E3-Firmware dorthin übertragen wird, ohne es dort zu bestätigen.

Die drei Transportfehler sind damit nicht die Ursache, aber sie machen einen unerwarteten Hänger unwiederbringlich: Ohne Timeout wartet die Anfrage ewig, und die tote Verbindung wird nie verworfen.

Werte, die das Gerät nur auf seinem Display rechnet

1.0.6-dev ergänzt zwei Leistungswerte, für die das Gerät kein Register veröffentlicht, die es aber für seine Bluetooth-Anzeige selbst berechnet. Beide sind aus den Formeln der Firmware nachgebaut. grid_power ist die Leistung am Netzanschluss, positiv bei Einspeisung:

if grid_sample_power == 0:
    base = off_grid_power if inverter_state == 4 else 0
else:
    base = grid_sample_power
grid_power = base - off_grid_power

Die Fallunterscheidung hat einen Grund. Im Bypass wird der Backup-Ausgang direkt aus dem Netz gespeist, die Netzmessung des Wechselrichters liest dort null, und die Backup-Last ist genau das, was das Netz trägt. Gegen zwei Messpunkte und die Anzeige des Geräts geprüft: 601 / 49 / Discharge ergibt 552, 0 / 48 / Bypass ergibt −48.

battery_power_bms ist BMS-Spannung mal Packstrom, als zweiter Leistungswert neben battery_power (Register 30001, Messung des Wechselrichters). Im Betrieb liegen beide innerhalb eines halben Prozents, im Leerlauf unterscheiden sie sich um den Eigenverbrauch des Geräts, den nur einer der beiden sieht: 34 W gegen 16 W. Nachgerechnet: 53,38 V × −0,3 A ergibt −16 W, 53,37 V × −12,2 A ergibt −651 W, beides wie auf dem Display.

Der Strom kommt aus den Packregistern und nicht aus Register 32101, und das hat einen Firmware-Grund. Die Lesefunktion legt den Wert in eine vorzeichenlose Variable und wendet danach den Skalierungscode an. Das Vorzeichen wird korrekt erweitert, aber die Division durch zehn rechnet dann mit 4294967174 statt mit −122, und die unteren 16 Bit davon gehen in die Antwort. Aus −122 wird 39309, aus −3 wird 39321. Positive Werte sind unauffällig, der Fehler tritt also nur beim Entladen auf. In der Firmware v150 kombiniert genau einer von 246 Deskriptoren einen vorzeichenbehafteten Typ mit einer Division, deshalb ist 32101 das einzige betroffene Register. Die Integration liest es nicht; der Defekt ist dem Hersteller gemeldet.

Fehlerstatus im Klartext und Zelldeltas

Die Fehler meldet das Gerät als Bitmaske über vier Register, von denen bisher eines als nackte Zahl sichtbar war. Seit 1.0.4-dev liefert jeder numerische Fehlersensor einen Begleiter mit den gesetzten Bits im Klartext, die Zahl selbst bleibt unverändert:

Fault Status                32
Fault Status Description    32 - BMS reports a fault (check pack firmware versions)

1056  ->  1056 - BMS reports a fault (...), unknown bit 10
0     ->  0 - OK

Unbekannte Bits werden benannt statt verschluckt, damit ein unerwarteter Fehler nicht als „OK“ durchgeht. Als Attribute stehen raw_value, active_bits, active_faults und undecoded_bits bereit, sodass eine Automation einzelne Bits prüfen kann. Neu lesbar sind außerdem die niederwertigen Hälften der 32-Bit-Fehlerwörter. In Register 36101 steckt Bit 7, das gesetzt ist, wenn der Backup-Ausgang nicht anläuft; es ist über mehrere Hardware-Logs bestätigt und fault_status_low deshalb standardmäßig aktiv. Das zweite Fehlerwort ist dagegen nur aus der Firmware abgeleitet, blieb in allen Logs bei null und ist deaktiviert.

Ab 1.0.3-dev gibt es außerdem sechs Zellspannungsdeltas, je eines pro Pack, mit drei Nachkommastellen und aus den Registern genau dieses Packs berechnet. Ein wachsendes Delta ist das übliche Frühzeichen einer schwächelnden Zelle. In derselben Version wurde solar_power_total repariert, das in jeder Standardinstallation bei jedem Durchlauf „missing required value(s)“ ins Log schrieb, weil die vier MPPT-Leistungen nicht als Abhängigkeiten gesammelt wurden – betroffen waren Venus A und D.

1.1.0: gegen Hardware verifiziert

Das erste Release ohne Namenszusatz fasst die Dev-Stände zusammen. Geprüft wurde an einer Venus D mit sechs Packs in drei Betriebszuständen – Bypass, 600 W Entladen und 600 W Laden –, mit der Bluetooth-Anzeige des Geräts als unabhängiger Referenz. Zusätzlich wurden Entitätskategorien und State-Klassen über alle Definitionen geprüft: Drei Messwerte standen fälschlich unter „Diagnose“, monotone Zykluszähler waren als Messwert statt als Zähler geführt, und wifi_signal_strength erzeugte gar keine Langzeitstatistik. Berechnete Sensoren holen ihre Eingangsregister außerdem nicht mehr, solange sie selbst deaktiviert sind.

Die Änderungen betreffen nur die Venus D (und die Korrektur von 32302 die Venus A). Alle anderen Registerdateien blieben unverändert. Installiert wird als benutzerdefiniertes HACS-Repository. Die -dev-Releases sind damit abgelöst.

Tags

Zum Projekt

Unterstützen

Diese Tools entstehen in meiner Freizeit und bleiben kostenlos, offen und cloud-frei. Wenn dir eins davon einen Nachmittag gespart hat, freue ich mich über einen Kaffee oder ein Stück Pizza.

Kaffee oder Pizza

Weitere Beiträge