Marstek Offline Endpoint: Schluss mit dem 30-Minuten-Reset
Home Assistant meldet die Batterie in schöner Regelmäßigkeit als nicht verfügbar, Modbus TCP läuft in Zeitüberschreitungen, und selbst Ping bleibt für zwei bis fünf Sekunden aus. Es liegt weder am Netzwerk noch am Switch noch an der Modbus-Integration, sondern an der Firmware des Speichers. Der Marstek Offline Endpoint ist ein Container, der das abstellt.
Woran man es erkennt
- Der Marstek Venus verschwindet alle 30 Minuten für wenige Sekunden aus dem Netz.
- Fehler wie
Cannot connect to Modbus device at …:502,Timeout writing to register 0xA410oderNo response received after 0 retries. - Es begann nach dem Update auf Firmware v150, oder es passiert immer dann, wenn die Batterie das Internet nicht erreicht.
Die Ursache
Auf der Control-Firmware v150 sammelt das Gerät Telemetrie-Datensätze und lädt sie zur Marstek-Cloud hoch. Wird der Puffer dabei nicht geleert, setzt die Firmware ihren Netzwerkchip nach einem festen Timer per Hardware zurück:
- Ethernet (CH395): nach 1800 s, sobald mehr als ein Datensatz wartet.
- WLAN (FC41D): nach 900 s, sobald überhaupt einer wartet.
Während der Chip im Reset ist, ist das Gerät schlicht nicht da. Das WLAN ist also die härtere Variante, kein Ausweg. Die vollständige Herleitung mit Firmware-Adressen und Aufrufkette steht im Issue 2 der Modbus Suite.

Was der Container macht
Zwei DNS-Einträge schicken die Batterie auf die eigene Maschine. Der Container beantwortet, worauf die Firmware wartet; der Puffer baut sich nicht auf, der Reset feuert nicht. An der Batterie ändert sich nichts, es gibt nichts umzustellen und nichts zu flashen. Als Nebeneffekt landen die Telemetriedaten lokal in einer JSONL-Datei, rund siebzig Felder je Upload.
docker run -d --name marstek-offline-endpoint --restart unless-stopped \
-p 443:443 -p 80:80 \
-e TZ=Europe/Berlin \
-v "$PWD/data:/data" -v "$PWD/certs:/certs" \
ghcr.io/sphings79/marstek-offline-endpoint:latestDie Ports 443 und 80 müssen auf dem Host frei sein; beim ersten Start entsteht ein selbstsigniertes Zertifikat in ./certs. TZ sollte unbedingt gesetzt werden: Der echte Endpunkt antwortet auf Zeitabfragen in der Ortszeit des Geräts, ohne TZ rechnet der Container in UTC. Die DNS-Umleitung gelingt in dnsmasq, Pi-hole oder AdGuard Home so:
address=/marstekcloud.com/192.168.x.y
address=/hamedata.com/192.168.x.yIgnoriert die Batterie den DNS-Server, geht auch eine Firewall-Regel, die Port 443 und 80 von der Batterie-IP auf den Container umlenkt. Den MQTT-Broker darf man nicht umleiten: Dort prüft das Gerät das Zertifikat des Brokers und legt ein eigenes Client-Zertifikat vor, das sich nicht fälschen lässt. Ein angenommener, dann abgebrochener Verbindungsversuch bringt das Gerät dazu, alle 5,5 Sekunden neu zu verbinden.
Warum es erst nach einem Tag funktionierte
Das Gerät akzeptiert eine funktional gleichwertige Antwort nicht. Ein von Node zusammengebauter Reply mit gleichem Rumpf und gleichem Chunked-Framing, aber einer zusätzlichen Kopfzeile Keep-Alive: timeout=5 und anderer Reihenfolge der Header, wurde verworfen: Das Gerät fragte vier Mal im Abstand von 20 Sekunden und gab auf, ohne seine Uhr zu stellen. Der Container reproduziert deshalb die Antworten byte-genau aus Rohmitschnitten der echten Endpunkte – 232 Bytes mit denselben Headern in derselben Reihenfolge, nur Date, Trace-Id und Zeitstempel unterscheiden sich. Den Weg dahin mit seinen vier falschen Fährten beschreibt HOW-WE-FOUND-IT im Repository.

Messergebnis
Auf einer Venus D mit Control v150 über LAN verschwand die Batterie vorher alle 1804 bis 1836 Sekunden. Nach der Korrektur blieb sie sieben Stunden lang durchgehend erreichbar, und der Upload pendelte sich auf einen Rhythmus von 300 Sekunden ein – ein Upload je Datensatz, so sieht ein leerer Puffer aus. Das Register 42000 war seit dem Umstellen unverändert. Ein zweites Gerät in einem anderen Haushalt mit openHAB statt Home Assistant bestätigte das mit einem Paketmitschnitt über 12,8 Stunden: 785 ARP-Proben, ein einziger Bruch im Minutentakt – der Neustart des Besitzers.
Was bleibt: der TLS-Handshake
Eine zweite, kleinere Unterbrechung verschwindet nicht. Seit v150 läuft der Upload über TLS; jeder Upload kostet das Gerät einen Schlüsselaustausch von etwa vier Sekunden, in denen es kein Modbus beantwortet, aber Ping und ARP weiter bedient – so unterscheidet man es vom Reset. Auf dem zweiten Gerät fielen über 11,7 Stunden alle 141 Modbus-Lücken über 3,5 s mit einem TLS-Handshake zusammen, zwölf pro Stunde, längste 6,9 s. Der Container trägt dazu nichts bei, die Rechenzeit geht beim Gerät drauf. Die Konsequenz: Das Antwort-Timeout des Modbus-Clients sollte über 8 Sekunden liegen, sonst gibt es alle fünf Minuten einen Fehler im Log.
Laufzeit und Plattformen
Der Container muss durchlaufen. Alle fünf Minuten kommt ein Datensatz in den Puffer, und er wird nur durch einen beantworteten Upload entfernt. Bleibt mehr als einer offen, wenn der 1800-Sekunden-Timer abläuft, beginnen die Resets, und die Firmware drosselt dann auf einen Upload pro 60 Sekunden. Gemessen dauerte es nach dem Wiederanlauf rund 45 Minuten, bis sich das Gerät beruhigte. --restart unless-stopped und ein beim Booten startendes Docker sind deshalb Pflicht.
Mit 1.0.1 kamen zwei Plattformen dazu, das Image gibt es nun für amd64, 386, arm64, armv7 und armv6. Pro Stunde sind es etwa zwanzig Anfragen, der älteste Raspberry Pi reicht. Eine Schritt-für-Schritt-Anleitung auf Deutsch und Englisch führt von der leeren SD-Karte über Docker bis zum DNS-Eintrag. Die Home-Assistant-Seite deckt die Marstek Modbus Suite ab; sie kann die Abbrüche nicht verhindern, erholt sich aber in Sekunden statt Minuten. Offen bleibt, welche Kopfzeile genau die Firmware stört – ebenso, wie sich andere Firmware-Versionen und andere Geräte verhalten. Tests auf weiterer Hardware sind ausdrücklich willkommen, auch mit negativem Ergebnis.
Zum Projekt
-
Marstek Offline Endpoint
Selbst gehosteter Container, der den Telemetrie-Upload eines Marstek Venus lokal beantwortet. Die 30-Minuten-Netzwerk-Resets der Firmware, die Modbus TCP und Home Assistant stören, bleiben damit aus.
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 PizzaWeitere Beiträge
- Rollladen-Steuerung pro Raum: Taster, Fenster, Kälte und Regen Eine Automation pro Raum, die Taster, Fensterkontakt, Kälte, Regen und die Zeit vor Sonnenaufgang zusammenführt. Zwei Merker-Helfer verhindern, dass sich die Auslöser gegenseitig überfahren.
- Stromausfall erkennen und Geräte wiederherstellen in Home Assistant Nach einem Stromausfall booten Lampen und Steckdosen in zufälligen Zuständen. Drei Erkennungswege, ein gemeinsames Script und ein Wiederherstellungsfenster bringen alles wieder in den gewünschten Zustand.
- Rauchmelder löst aus: Alle Rollläden fahren hoch (Home Assistant) Bei Rauchalarm sollen die Rollläden im ganzen Haus hochfahren, damit Fenster als Fluchtweg frei sind. Die Automation ist kurz – aber ein fehlendes „from“ im Trigger entscheidet darüber, ob sie im Ernstfall überhaupt feuert.