No description
  • Python 99.6%
  • Shell 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
hubobel 66a7497257 Verworfene Cloud-Nullwerte aus Diagnosevergleich entfernen
Kennzeichne bei is_illegal=1 die HTTP-Telemetrie auch im Diagnosepfad als unbrauchbar, damit gültige Cloud-MQTT-Werte keine falsche Abweichungswarnung erzeugen. Zeige bei direktem MQTT-Abruf außerdem den tatsächlichen Broker als Quelle an und sichere das Verhalten mit einem Regressionstest ab.
2026-09-04 17:44:46 +02:00
static Logos und Presence 2026-08-14 15:33:59 +02:00
.env.example Marstek-Cloud-MQTT direkt als Livequelle anbinden 2026-09-04 17:40:33 +02:00
.gitignore UI optimiert f PV/Batterie/Haus 2026-08-11 17:55:41 +02:00
hame_cloud_api.py Verworfene Cloud-Nullwerte aus Diagnosevergleich entfernen 2026-09-04 17:44:46 +02:00
install-systemd.sh Authentik-OIDC-Anmeldung 2026-08-25 18:11:28 +02:00
README.md Marstek-Cloud-MQTT direkt als Livequelle anbinden 2026-09-04 17:40:33 +02:00
requirements.txt Marstek-Cloud-MQTT direkt als Livequelle anbinden 2026-09-04 17:40:33 +02:00
test_hame_cloud_api.py Verworfene Cloud-Nullwerte aus Diagnosevergleich entfernen 2026-09-04 17:44:46 +02:00
VERSION Add dashboard service-token access 2026-08-26 17:55:54 +02:00

Hintergassen Monitoring SERVICE

Der Dienst liest Leistungs- und Batteriedaten aus der inoffiziellen Hame/Marstek-Cloud-API. Er schreibt die Werte nativ nach InfluxDB, stellt sie direkt in einer Weboberfläche dar und kann sie optional an ioBroker übertragen.

Datenfluss

Marstek-Cloud → gemeinsamer Datensatz → InfluxDB (primär)
                                  ├→ Weboberfläche
                                  └→ ioBroker (optional)

Verwendet werden alle Marstek2ioBroker-Werte:

Feld Bedeutung Einheit
pv PV-Leistung W
load Hausverbrauch W
discharge Batterieentladung W
soc Ladezustand %
soc_kwh berechnete verbleibende Energie kWh

soc_kwh wird mit SOC × BATTERY_CAPACITY_KWH / 100 berechnet und auf zwei Nachkommastellen gerundet.

InfluxDB

InfluxDB v2 ist das primäre Speicherziel. Jeder Cloud-Abruf schreibt einen gemeinsamen Datenpunkt:

  • Bucket: hintergasse
  • Measurement: marstek
  • Fields: pv, load, discharge, soc, soc_kwh
  • Tags: device_id, device_name
  • Zeitstempel: Zeitpunkt des Abrufs

Die Übertragung verwendet das native InfluxDB-v2-HTTP-Protokoll. Zusätzliche Python-Pakete sind nicht erforderlich.

Weboberfläche

Im Dauerbetrieb ist die Oberfläche unter http://IP-DES-SERVERS:8321 erreichbar. Der Ladezustand erscheint als farbige Gauge mit dem höchsten am aktuellen Kalendertag gemessenen Füllstand. Der Tageswert wird unter logs/daily_soc_max.json gespeichert und überlebt Dienstneustarts. Dazu kommen PV-Leistung, Hausverbrauch, berechneter Batteriestatus, verbleibende Energie, Gerät und Zeitpunkt der letzten Cloud-Aktualisierung. Der Batterieausgang wird aus dem konfigurierten ioBroker-State gelesen. Ist der Batterieausgang größer als pv, speist die Batterie die Differenz ins Haus; ist pv größer, wird die Batterie mit der Differenz geladen. Der Hausverbrauch ergibt sich aus Netzleistung + Batterieausgang und wird mindestens mit 0 W dargestellt. Die Netz-Kachel behält das tatsächliche Vorzeichen der ioBroker-Netzleistung.

Während der Entladung wird außerdem eine geschätzte Restlaufzeit aus der Energie oberhalb des konfigurierten Mindestladezustands und der aktuellen Entladeleistung berechnet. Die Reserve beträgt standardmäßig 20 Prozent.

API-Endpunkte:

  • /api/data – letzter vollständiger Marstek-Datensatz
  • /api/health – Status und letzter Datensatz
  • /api/version – Version, Git-Stand und Update-Status
  • /api/update – sicher geprüftes Fast-Forward-Update (POST, nur Linux)
  • /maintenance – Wartungsseite für MarstekCloud, InfluxDB und ioBroker
  • /auth/login, /auth/callback und /auth/logout – optionale zentrale Anmeldung über Authentik OIDC
  • /api/config – Konfiguration lesen oder validiert speichern

Auf der Wartungsseite lässt sich außerdem das Logo der Netzkachel aus zehn gängigen deutschen Energieversorgern auswählen, darunter auch Entega, ESWE, TWL und Yello. Über den Stift lässt sich das Logo jedes Anbieters durch ein eigenes PNG-, JPEG- oder WebP-Logo bis 2 MB ersetzen. Die Auswahl „Eigener Anbieter“ erlaubt ein vollständig eigenes Logo. Uploads werden im Laufzeitordner logs/ gespeichert und bleiben dadurch von Git-Updates getrennt.

Die Fußzeile zeigt Version, Commit und Commit-Datum. Sie prüft alle fünf Minuten den konfigurierten Git-Upstream. Liegt der Server zurück, kann das Update direkt aus der Fußzeile gestartet werden. Lokale Änderungen, eigene Commits oder ein abweichender Branch blockieren den Vorgang. Zulässige Updates verwenden ausschließlich git pull --ff-only und starten anschließend den systemd-Dienst marstek2iobroker neu.

Installation

Voraussetzungen:

  • Python 3.10 oder neuer
  • Netzwerkzugriff auf https://eu.hamedata.com
  • erreichbare InfluxDB-v2-Instanz
  • Hame-/Marstek-Konto mit Zugriff auf das Gerät

Konfiguration anlegen:

cp .env.example .env
nano .env
chmod 600 .env

Mindestens diese Werte müssen angepasst werden:

HAME_MAILBOX=second-account@example.com
HAME_PASSWORD=replace-me

INFLUX_ENABLED=true
INFLUX_URL=http://10.0.1.134:9086
INFLUX_ORG=iobroker
INFLUX_BUCKET=hintergasse
INFLUX_MEASUREMENT=marstek
INFLUX_TOKEN=replace-me

Der InfluxDB-Token benötigt Schreibberechtigung für das Bucket hintergasse. Die .env enthält Zugangsdaten und wird nicht committed.

Wenn Authentik aktiviert ist und ein internes Dashboard die Energie-Lesedaten abrufen soll, zusätzlich ein langes, zufälliges Service-Token setzen:

DASHBOARD_API_TOKEN=replace-with-a-random-token

Das Token gilt ausschließlich für /api/data und /api/house-day-history. Alle übrigen API- und Webpfade bleiben durch Authentik geschützt.

Einmaliger Funktionstest:

python3 hame_cloud_api.py --once

Dauerbetrieb:

python3 hame_cloud_api.py

Optionale ioBroker-Ausgabe

Das Lesen der Netzleistung und das Übertragen der Marstek-Werte sind getrennt konfigurierbar. Die Netzleistung wird standardmäßig gelesen, die Ausgabe ist standardmäßig ausgeschaltet:

IOBROKER_ENABLED=true
IOBROKER_GRID_ENABLED=true
IOBROKER_URL=http://10.0.1.122:8087

Dann werden folgende States geschrieben:

Cloud-Feld ioBroker-State
discharge javascript.0.Variablen.Marstek_discharge
load javascript.0.Variablen.Marstek_load
pv javascript.0.Variablen.Marstek_pv
soc javascript.0.Variablen.Marstek_soc
soc_kwh javascript.0.Variablen.Marstek_soc_kwh

Ein Fehler der optionalen ioBroker-Ausgabe stoppt weder InfluxDB noch die Weboberfläche.

Konfiguration

Variable Bedeutung Standard
HAME_MAILBOX E-Mail-Adresse des Cloud-Kontos interaktive Eingabe
HAME_PASSWORD Passwort des Cloud-Kontos interaktive Eingabe
HAME_BASE_URL regionale Cloud-URL https://eu.hamedata.com
BATTERY_CAPACITY_KWH nutzbare Batteriekapazität 2.228571
BATTERY_MIN_SOC_PERCENT Mindestladezustand für die Restlaufzeitberechnung 20
INFLUX_ENABLED InfluxDB-Ausgabe aktivieren true
INFLUX_URL InfluxDB-Basis-URL http://10.0.1.134:9086
INFLUX_ORG InfluxDB-Organisation iobroker
INFLUX_BUCKET InfluxDB-Bucket hintergasse
INFLUX_MEASUREMENT Measurement-Name marstek
INFLUX_TOKEN InfluxDB-Schreib-Token erforderlich
IOBROKER_ENABLED optionale ioBroker-Ausgabe false
IOBROKER_GRID_ENABLED Netzleistung aus ioBroker lesen true
IOBROKER_URL ioBroker Simple API http://10.0.1.122:8087
IOBROKER_GRID_POWER_STATE ioBroker-State der Netzleistung (positiv Bezug, negativ Einspeisung) alias.0.Hintergasse.Energie.ELECTRIC_POWER
GRID_FEED_IN_ZERO_THRESHOLD_W Negative Netzwerte bis zu diesem Betrag als 0 W behandeln 15
IOBROKER_BATTERY_OUTPUT_STATE ioBroker-State der aktuellen Leistung am Batterieausgang mqtt.0.solar.114174918577.0.powerdc
IOBROKER_MARSTEK_RAW_STATE Optionaler, von hame-relay im Cloud-Modus aktualisierter B2500-Rohdaten-State; Ersatzquelle bei is_illegal=1 leer
MARSTEK_MQTT_BROKER Lokaler MQTT-Broker für direkte cd=1-Abfragen über hame-relay leer
IOBROKER_GAS_DAILY_STATE ioBroker-State des Gas-Tagesverbrauchs javascript.0.Variablen.Tagesverbrauch_Gas
IOBROKER_WATER_DAILY_STATE ioBroker-State des Wasser-Tagesverbrauchs javascript.0.Variablen.Tagesverbrauch_H2O
INFLUX_GAS_DAILY_FIELD InfluxDB-Feld des Gas-Tagesverbrauchs Tagesverbrauch_Gas
INFLUX_WATER_DAILY_FIELD InfluxDB-Feld des Wasser-Tagesverbrauchs Tagesverbrauch_H2O
WATER_POSTAL_CODE Postleitzahl des Wasseranschlusses 55234
WATER_CITY Ort des Wasseranschlusses Albig
WATER_PROVIDER_NAME Bestätigter Wasserversorger Wasserversorgung Rheinhessen-Pfalz GmbH
GRID_LOGO_PROVIDER Logo der Netzkachel (eon, rwe, enbw, vattenfall, mainova, rheinenergie, enviam, swm, enercity, mvv, entega, eswe, twl, yello oder custom) eon
ELECTRICITY_CONTRACT_NUMBER Vertragsnummer des Stromvertrags leer
ELECTRICITY_METER_NUMBER Nummer des Stromzählers leer
ELECTRICITY_BASE_PRICE_EUR_MONTH Monatlicher Grundpreis in Euro 0
ELECTRICITY_WORK_PRICE_CENT_KWH Arbeitspreis in Cent je kWh 0
PV_PEAK_POWER_W Maximale Leistung der PV-Anlage; Basis der standortbezogenen PVGIS-Prognose für 55234 Albig 600
GAS_LOGO_PROVIDER Logo der Gaskachel (eon, rwe, enbw, vattenfall, mainova, rheinenergie, enviam, swm, enercity, mvv, entega, eswe, twl, yello, gasag, ewe oder custom) gasag
GAS_CONTRACT_NUMBER / GAS_METER_NUMBER Vertrags- und Zählernummer Gas leer
GAS_BASE_PRICE_EUR_MONTH Gas-Grundpreis pro Monat 0
GAS_WORK_PRICE_CENT_KWH Gas-Arbeitspreis in Cent je kWh 0
GAS_KWH_PER_M3 Umrechnungsfaktor von m³ in kWh 10
WATER_CONTRACT_NUMBER / WATER_METER_NUMBER Vertrags- und Zählernummer Wasser leer
WATER_BASE_PRICE_EUR_MONTH Wasser-Grundpreis pro Monat 0
WATER_WORK_PRICE_EUR_M3 Wasser-Arbeitspreis in Euro je m³ 0
WATER_WASTEWATER_PRICE_EUR_M3 Abwasserpreis in Euro je m³ 0
WATER_RAIN_FEE_EUR_M2 Niederschlagsgebühr in Euro je m² 0
WATER_RAIN_AREA_M2 Für Niederschlagswasser berechnete Fläche in m² 128
WEB_ENABLED Weboberfläche aktivieren true
WEB_HOST Bind-Adresse 0.0.0.0
WEB_PORT Web-Port 8321
LOG_LEVEL Mindeststufe des Loggings INFO
LOG_FILE Logdatei logs/hame_cloud_api.log

Aufrufoptionen

--interval SEKUNDEN   Zeit zwischen Cloud-Abfragen (Standard: 60)
--once                genau eine Abfrage durchführen und beenden
--timeout SEKUNDEN    Zeitlimit je HTTP-Aufruf (Standard: 15)
--retries ANZAHL      Wiederholungen bei temporären Fehlern (Standard: 3)
--base-url URL        Cloud-Basis-URL überschreiben
--visible-password    Passwort bei Eingabe sichtbar anzeigen

Das Mindestintervall beträgt zehn Sekunden. Ein Cloud-Token wird automatisch erneuert, wenn er abläuft. Bei Fehlern steigt die Wartezeit bis maximal fünf Minuten.

Die Netzleistung wird unabhängig davon alle fünf Sekunden direkt aus ioBroker aktualisiert; Cloud sowie Gas- und Wasserwerte folgen weiterhin dem eingestellten Abfrageintervall.

Das Haus-Overlay zeigt zusätzlich den heutigen elektrischen Hausverbrauch als 24-Stunden-Leistungsprofil aus dem InfluxDB-Feld load. Der Verlauf wird bei geöffnetem Overlay minütlich aktualisiert.

Alle Tagesverlaufsdiagramme lassen sich über Plus/Minus, Mausrad oder Touchpad horizontal vergrößern. Der vergrößerte Ausschnitt kann durch Ziehen verschoben und über 1:1 vollständig zurückgesetzt werden. Beim Überfahren eines Datenbalkens zeigt ein Tooltip unmittelbar Uhrzeit und konkreten Messwert samt Einheit an.

Das Plus an der Hauskachel blendet die drei Verbraucher mit der aktuell höchsten Leistung ein. Die zwölf hinterlegten ioBroker-Leistungsstates werden parallel im fünfsekündigen Netzzyklus gelesen; aktive Verbraucher sind mit animierten Linien zur Hauskachel verbunden. Leistungen unter 10 W werden ignoriert. Die höchstens drei verbleibenden Kacheln stehen horizontal in einer Reihe; ihre Verbindungslinien sind bewusst langsam und dezent animiert. Das Dashboard nutzt die verfügbare Browserbreite responsiv bis 1600 px; die Energieflussgrafik wächst dabei sowohl horizontal als auch kontrolliert in der Höhe mit. Die Verbindungslinien werden aus den tatsächlichen Kachelpositionen dynamisch berechnet, docken direkt an den Rahmen an und behalten bei jeder Fenstergröße eine schlanke, nicht mitskalierende Strichstärke. Ein Klick auf eine eingeblendete Verbraucherkachel öffnet deren 24-Stunden- Leistungsverlauf aus InfluxDB. Zusätzlich zeigt das Overlay den aufsummierten Monatsverbrauch, dessen Kosten nur anhand des Strom-Arbeitspreises sowie eine auf zwölf Monate skalierte Jahreshochrechnung für Verbrauch und Kosten. Der direkt aus ioBroker gemessene Momentanverbrauch steht im Overlay als große Live-Kennzahl und wird bei geöffneter Ansicht alle fünf Sekunden aktualisiert.

Der positive Netzbezug wird lokal zu Tages-, Wochen- und Monatswerten summiert und in logs/grid_consumption.json neustartfest gespeichert. Einspeisung zählt nicht zum Verbrauch. Die Monatskosten bestehen aus Grundpreis plus Monatsverbrauch mal Arbeitspreis; die Erfassung beginnt mit dem Einsatz dieser Version. Der Tagesverlauf im Netz-Overlay wird in Fünf-Minuten-Mittelwerten direkt aus dem InfluxDB-Feld grid_power geladen. Netzbezug und Einspeisung werden farblich getrennt an einer gemeinsamen Nulllinie dargestellt. Gas- und Wasserstände werden ebenfalls zu Wochen- und Monatswerten verdichtet, neustartfest gespeichert und in anklickbaren Kachel-Overlays mit Kosten und InfluxDB-Tagesverlauf angezeigt. Gas- und Wasserverläufe unterstützen dabei sowohl den ioBroker-üblichen State-Namen als Measurement als auch ältere Ablagen mit dem State-Namen als Feld. Bei Wasser entsprechen sich Frisch- und Abwassermenge. Die monatliche Anzeige addiert Grundpreis, Frischwasser, Abwasser und ein Zwölftel der jährlichen Niederschlagskosten für die konfigurierte Fläche. Das Eingabefeld der Niederschlagsgebühr bleibt in Euro je m². Im Haus-Overlay können Monate über den nativen Browserkalender ausgewählt werden. Eine Auswahl ohne InfluxDB-Werte wird erkannt und ohne falsche Summen als nicht verfügbar gemeldet. Historische Verbräuche stammen aus InfluxDB; ihre Kosten werden mit den aktuell in der Wartung hinterlegten Tarifen berechnet. Die Kapsel Jahresprognose zeigt eine Hochrechnung für das vollständige Kalenderjahr. Strom und Wasser werden unabhängig voneinander aus ihrem bisherigen Tagesmittel hochgerechnet. Die Gasprognose gewichtet die Monate zusätzlich mit typischen Gradtagsanteilen für die Region Albig und berücksichtigt einen witterungsunabhängigen Grundverbrauch. Die Kosten verwenden die in der Wartung hinterlegten Grund- und Arbeitspreise. Noch nicht erfasste zurückliegende Monate werden dabei ebenso geschätzt wie die kommenden Monate und sind deshalb Bestandteil der vollständigen Jahressumme. Solange noch wenig eigene Messhistorie vorliegt, wird die Hochrechnung zu 75 Prozent mit den konfigurierbaren historischen Jahresverbräuchen und zu 25 Prozent mit dem aktuellen Verbrauchstrend kalibriert. Voreingestellt sind 3.000 kWh Strom, 10.000 kWh Gas und 120 m³ Wasser pro Jahr. In den Wartungsreitern Strom, Gas und Wasser kann außerdem der aktuelle Monatsabschlag hinterlegt werden. Die Jahresprognose vergleicht zwölf Abschläge mit den prognostizierten Jahreskosten. Ein grüner Haken kennzeichnet einen ausreichenden Abschlag, ein rotes Ausrufezeichen eine voraussichtliche Nachzahlung; der Tooltip zeigt die jeweilige Differenz. Zusätzlich zeigt die Hausübersicht die gesamte über battery_output an das Haus abgegebene Energie als PV-Einsparung und bewertet den dadurch vermiedenen Netzbezug zum aktuellen Arbeitspreis. Diese Werte werden für den laufenden Monat neustartfest erfasst und historisch aus battery_output in InfluxDB rekonstruiert. Die Batterie wird ausschließlich aus PV geladen; eine gemeldete Ladeleistung wird deshalb grundsätzlich auf die gleichzeitig verfügbare PV-Leistung begrenzt. Ein Klick auf die PV-Kachel öffnet den aus InfluxDB gelesenen Tagesverlauf. Der Tagesertrag wird aus den Leistungswerten integriert und mit dem aktuellen Strom-Arbeitspreis zusätzlich in Euro bewertet. Der bis dahin aufsummierte Tagesertrag wird außerdem direkt in der PV-Kachel angezeigt und minütlich aus den InfluxDB-Werten aktualisiert. Über die Kalenderauswahl können auch historische Tage aus InfluxDB angezeigt werden; nur der aktuelle Tag wird automatisch minütlich aktualisiert.

systemd

chmod +x install-systemd.sh
sudo ./install-systemd.sh

Das Skript installiert und startet marstek2iobroker.service.

sudo systemctl status marstek2iobroker.service
sudo journalctl -u marstek2iobroker.service -f
sudo systemctl restart marstek2iobroker.service

Tests

python3 -m unittest -v

Die Hame/Marstek-Cloud-API ist nicht offiziell dokumentiert und kann sich ohne Ankündigung ändern. Das Standardintervall von 60 Sekunden sollte nicht unnötig verkürzt werden.

Zur Diagnose des PV-/Batteriemappings schreibt jeder Cloud-Zyklus eine strukturierte Logzeile mit dem Präfix ENERGY_DIAGNOSTIC. Sie enthält ausschließlich Geräte-ID, die fünf relevanten Cloud-Rohfelder, MQTT-Wert und -Zeitstempel sowie die daraus berechneten Leistungswerte. Zugangsdaten und vollständige API-Antworten werden nicht protokolliert. Weil die Hersteller-API undokumentiert ist, werden außerdem die Cloud-Feldnamen und rekursiv ausschließlich numerische Feldwerte aufgenommen. So lassen sich umbenannte oder verschobene Messwerte erkennen, ohne persönliche Textwerte zu protokollieren. Auffällige Vorzeichen, Werte über DIAGNOSTIC_MAX_POWER_W (Standard: 5000 W), unplausible SOC-Werte, alte MQTT-Daten und Abweichungen zwischen Cloud- und berechneter Entladung erscheinen zusätzlich im Feld warnings und als Warnmeldung. Cloud-Gerätedatensätze mit is_illegal=1 werden vollständig verworfen, weil der Endpunkt in diesem Zustand nur Nullwerte statt Telemetrie liefert. Dadurch gelangen aus einem verweigerten Cloud-Zugriff keine erfundenen PV- oder Batteriewerte nach ioBroker und InfluxDB. Ist IOBROKER_MARSTEK_RAW_STATE gesetzt, wird stattdessen ein höchstens fünf Minuten alter cd=01-Datensatz verwendet, den hame-relay aus Marsteks Cloud-MQTT in den lokalen Broker spiegelt. Der Speicher bleibt dabei auf dem Hersteller-Broker; sein lokaler MQTT-Modus wird nicht aktiviert. Das Mapping lautet w1+w2 = PV, pe = SOC und g1+g2 = Batterie-/Wechselrichterausgang. Bevorzugt wird MARSTEK_MQTT_BROKER=mqtt://127.0.0.1:1883 gesetzt. Das Programm abonniert dann das lokale Gerätetopic, veröffentlicht selbst cd=1 und verarbeitet die über hame-relay zurückkommende Antwort unmittelbar. Benutzername und Passwort können bei Bedarf als mqtt://benutzer:passwort@host:port angegeben werden.