- Python 99.6%
- Shell 0.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
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. |
||
| static | ||
| .env.example | ||
| .gitignore | ||
| hame_cloud_api.py | ||
| install-systemd.sh | ||
| README.md | ||
| requirements.txt | ||
| test_hame_cloud_api.py | ||
| VERSION | ||
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/callbackund/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.