sphings-dev.de

Marstek Modbus Suite 1.4: Venus A aus der Firmware, Pack 7, Laufzeiten

Mit 1.4 hat die Marstek Modbus Suite ihre erste Registerkarte für die Venus A bekommen, die aus der Firmware stammt statt aus einer CSV-Tabelle, die Venus D sieben Packs, und es gibt vier berechnete Sensoren für Laufzeit und Verschleiß. Davor steht ein kleiner Fehler, durch den zwei Sensoren nie gelesen wurden.

1.3.3: eine halbe Umbenennung

Aus einem Upstream-Log mit einer Venus E: 805 Mal innerhalb eines Logs, etwa alle zwölf Sekunden, die Warnung sensor 'device_ip' has no scan_interval defined, skipping this poll. Die Standardintervalle waren auf zwei Namen zusammengefasst worden, high (10 s) und low (60 s). Zwei Definitionen in e_v3.yaml, device_ip und gateway_ip, sagten aber noch very_low und damit etwas, das es nicht mehr gab. Die Warnung war deshalb kein Lärm: Beide Sensoren wurden nie gelesen. Die Normalisierung von very_low auf low wirkte nur auf die gespeicherten Optionen, nicht auf die Registerdefinitionen. Jetzt stehen beide auf low, werden also alle 60 Sekunden gelesen, und die Warnung erscheint einmal je Schlüssel und nennt den ungültigen Wert und die bekannten Namen. Betroffen waren nur Venus E v3 mit eingeschalteten Sensoren, denn beide sind standardmäßig deaktiviert.

Die Venus A bekommt die Karte der Venus D

a.yaml war aus einer CSV erzeugt worden und trug seitdem den Kopf „Venus A registers are untested“. Mit 1.4.0-beta.1 wird sie aus d.yaml abgeleitet, weil beide Firmwares dieselbe Modbus-Tabelle ausliefern. Belegt ist das mit demselben Verfahren wie bei der Venus D: Die Deskriptortabelle wurde aus dem Firmware-Image der Venus A entpackt (ein LZ77-gepackter .data-Block am Flash-Ende) und mit der der Venus D verglichen.

  • 246 Einträge, Register 30000 bis 38014.
  • Register, die nur in der A oder nur in der D vorkommen: keine.
  • Einträge, die sich in Typ, Skalierung, Elementgröße oder Anzahl unterscheiden: 0 von 246.
  • Unterschiede gibt es nur bei den Quellzeigern (29 von 246 gleich), was ein Build-Detail ist.

Geprüft wurde außerdem, dass jedes Leseregister aus d.yaml, auch alle 132 DEV-Register, in der A-Tabelle existiert und keine Definition über ihren Eintrag hinausliest. Die neue a.yaml ist d.yaml abzüglich genau zweier Dinge. Erstens hat die A 13 Zellen pro Pack statt 16: Die Firmware deklariert 34018 count=16 auf beiden Modellen, die 13 sind eine Eigenschaft der A-Hardware, Zellen 14 bis 16 würden 0 lesen. Zweitens gibt es keine DEV-Abschnitte, weil auf einer A nichts davon gemessen wurde.

Das macht 294 Definitionen statt 182, 117 davon neu: alle Packs mit Spannung, Strom, Zyklen, MOS-Status, Zellextremen, Schutzwörtern, BMS-Version und Temperaturen, die Fehler- und Alarmwörter mit Klartext, Zelldelta pro Pack, Netzleistung, BMS-Batterieleistung sowie Geräte- und Gateway-IP. Die Übersetzungen mussten nicht angefasst werden, weil der Schlüsselraum modellunabhängig ist und alle 294 Schlüssel in en, de und nl schon existierten.

Fünf CSV-Altlasten verschwinden, jede gegen die Quellzeiger der A-Firmware bestätigt: max_cell_voltage und min_cell_voltage (das Pack-1-Problem aus der Venus D), ac_current (liest ac_power, ist kein Strom), ac_offgrid_current (die Off-Grid-Spannung) und internal_mos2_temperature. Wer diese Entitäten hatte, findet sie nach dem Update als nicht mehr bereitgestellt vor. Als Beta ausgeliefert wurde die Karte, weil unbelegt ist, ob die A jedes dieser Register tatsächlich befüllt.

Pack 7

Die Firmware kennt auf A und D sieben Packblöcke, die YAML-Dateien beschrieben sechs. Beta.2 klärt es für die Venus D: Pack 7 antwortet, Basisregister 34600 nach dem Schema 34000 + 100 × (N−1). Es bekommt dieselben 33 Entitäten wie die Packs 2 bis 6 (Spannung, Strom, Ladezustand, Zyklen, MOS-Status, Zellextreme, Schutzwörter, BMS-Version, Temperaturen, 16 Zellspannungen, berechnetes Zelldelta), alle standardmäßig deaktiviert. Die drei geratenen DEV-Register für Pack 7 entfallen, und battery_power_bms addiert nun auch dessen Strom – bisher wurde das siebte Pack still ignoriert. Dazu wurde die README korrigiert: Dort stand für Zelle 1 von Pack 2 noch Register 34031, tatsächlich antwortet das Gerät bei 34118. Die vier Gerätespalten der Registertabelle werden jetzt aus den YAML-Dateien erzeugt. Bestehende Entitäten behalten ihre IDs.

Laufzeit und Verschleiß als berechnete Sensoren

1.4.0 ergänzt vier Sensoren, die das Gerät nicht liefert. runtime_to_empty und runtime_to_full schätzen die Stunden bis leer oder voll bei der Leistung, mit der der Speicher sich gerade bewegt. Jeder zählt nur in seiner Richtung: Beim Entladen steht runtime_to_full auf 0 und umgekehrt. Alles unter 5 W gilt als Leerlauf, sonst ergäbe die Standby-Aufnahme Laufzeiten von Tausenden Stunden, und das Ergebnis ist bei 999 h gedeckelt. Beide lesen nur Werte, die ohnehin abgefragt werden (battery_soc, battery_total_energy, battery_power), erzeugen also keinen zusätzlichen Modbus-Verkehr.

remaining_cycles und battery_health leiten den Verschleiß aus der insgesamt entladenen Energie geteilt durch die Packkapazität ab und messen ihn an einem rated_cycles in der Registerdatei:

remaining_cycles:
    rated_cycles: 6000

Das ist die Herstellerangabe für die LFP-Zellen. Das Gerät meldet sie nicht, daher sind beide Sensoren Schätzungen, als Diagnose markiert und standardmäßig deaktiviert. Gegen die Template-Helfer, die sie ersetzen, wurde auf einer Venus D nachgerechnet; remaining_cycles und battery_health stimmen auf die Stelle, nur ein Langzeitlauf auf echter Hardware steht noch aus. Die Laufzeiten rechnen bis 0 und 100 Prozent, nicht bis zu den eingestellten Grenzen, weil charging_cutoff_capacity und discharging_cutoff_capacity nur die Venus E v1/v2 hat. Wer eine Entladereserve von 12 Prozent eingestellt hat, hat also real weniger Laufzeit, als der Sensor nennt. Das einstellbar zu machen, war der nächste Schritt.

Mit 1.4.0 steht das Projekt auch formal für sich: manifest.json zeigt auf dieses Repository mit @sphings79 als Codeowner, die LICENSE führt das ursprüngliche Urheberrecht und die Weiterentwicklung nebeneinander, das Upstream-Divergenzprotokoll und die Fork-Hinweise in den READMEs sind entfernt.

1.4.1: Sensoren, die auf keiner Installation erschienen

1.4.0 lieferte die vier Sensoren aus, aber sie konnten auf keiner Installation entstehen. get_registers() lädt die ganze Registerdatei und baut den Rückgabewert dann aus einer handgeschriebenen Liste von Abschnittsnamen. RUNTIME_SENSOR_DEFINITIONS und BATTERY_LIFE_SENSOR_DEFINITIONS standen in allen vier Registerdateien und der Koordinator fragte sie ab, aber auf der Liste fehlten sie. Beide Abfragen fielen auf den Standard zurück:

self.RUNTIME_SENSOR_DEFINITIONS = data.get("RUNTIME_SENSOR_DEFINITIONS", [])

Eine leere Liste ist ein gültiger Abschnitt. Die Sensor-Plattform iterierte über nichts, legte keine Entitäten an und loggte nichts. HACS meldete 1.4.0, die Integration stand auf „geladen“, und die Entitäten fehlten schlicht. Beide Abschnitte stehen jetzt im Rückgabewert und im Docstring, der die Schlüssel auflistet und der einzige Index dafür ist. Zu beachten beim Update: Home Assistant muss komplett neu gestartet werden, ein Neuladen der Integration reicht nicht, denn dabei bleiben die alten Python-Module in sys.modules und der alte Code läuft weiter – mit identischem Symptom. Danach sind die Laufzeitsensoren aktiv, remaining_cycles und battery_health erscheinen deaktiviert und müssen einmal eingeschaltet werden.

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