sphings-dev.de

Shelly-Energiezähler per Modbus TCP in Home Assistant – und warum die Saldierung fehlte

Wer einen Shelly-Zähler in Home Assistant einbindet, nimmt meist die offizielle Shelly-Integration, und das ist auch in Ordnung. Anders sieht es aus, wenn dasselbe Messgerät schon von einem Wechselrichter, einer SPS oder einer Loxone-Anlage per Modbus gelesen wird und Home Assistant dieselben Zahlen aus derselben Quelle sehen soll. Dafür gibt es shelly-modbus-home-assistant: eine HACS-Integration, die den Modbus-TCP-Server der Shelly-Firmware direkt abfragt – ohne Cloud-Konto, ohne MQTT-Broker und ohne RPC-Polling.

Was unterstützt wird

Gelesen werden Shelly-Geräte der Generationen 2 bis 4, deren Firmware einen Modbus-Server mitbringt. Bei den Energiezählern sind das die Pro-3EM-Varianten, das Pro EM 50, das 3EM-63 Gen3, das EM Gen3 sowie EM Mini und EM 63 Gen4. Dazu kommen Relais wie Shelly 1, 1L, 1PM und 2PM Gen4 samt Mini-Varianten; die Ausgänge lassen sich über Modbus-Coils schalten.

Nachgemessen habe ich zwei Geräte: einen Shelly Pro 3EM und ein 3EM-63 Gen3, beide mit Firmware 2.0.0. Für beide wurde jeder dekodierte Wert mit dem verglichen, was dasselbe Gerät über seine eigene RPC-Schnittstelle meldet. Alle anderen Modelle folgen Shellys veröffentlichten Registerkarten und sind nicht an echter Hardware bestätigt.

Das Modell wird beim Einrichten aus den Registern des Geräts erkannt und lässt sich überschreiben. Dasselbe gilt für das Messprofil: Dreiphasenzähler laufen als ein Dreiphasenzähler (triphase) oder als drei einzelne Einphasenzähler (monophase). Welches Profil aktiv ist, prüft die Integration durch Abfragen der Komponenten. Geräte im Netz werden per Zeroconf gefunden.

Drei Details, die Shellys Doku offenlässt

Drei Dinge in Shellys Modbus-Umsetzung sind in der Dokumentation nicht ausbuchstabiert. Alle drei sind an echter Hardware bestätigt:

  • Die dokumentierten Adressen sind nicht die Adressen auf dem Draht. Shelly nennt sie in der klassischen Schreibweise 3xxxx; gesendet wird die Zahl minus 30000. Aus dem dokumentierten Register 31020 (Spannung Phase A) wird also Input-Register 1020. Gelesen wird durchgehend mit Funktionscode 0x04, Holding-Register gibt es nicht.
  • 32-Bit-Werte (float32, uint32) liegen mit dem niederwertigen Wort zuerst in den Registern (CDAB). Im üblichen Big-Endian gelesen, ergibt das Registerpaar für 240,4 V den Wert 1,65e16.
  • Zeichenketten sind innerhalb jedes Registers byteweise vertauscht. Aus der MAC A0DD6CA0E0CC wird sonst 0ADDC60A0ECC.

Die Registerbeschreibungen liegen als YAML-Dateien im Repository. Ein weiteres Gerät aufzunehmen ist dadurch eine Datenänderung, keine Codeänderung.

Datenfluss vom Shelly-Gerät über Modbus-Client und Koordinator zu den Home-Assistant-Entitäten

Blockweise lesen

Die Register werden zu zusammenhängenden Blöcken gebündelt und mit je einer Anfrage gelesen. Ein Pro 3EM mit den Standardentitäten braucht pro Zyklus drei Modbus-Anfragen statt 69. Blöcke überschreiten keine Komponentengrenzen und nie 80 Register, das Limit der Firmware pro Anfrage. Deaktivierte Entitäten werden gar nicht erst gelesen; wer Entitäten abschaltet, senkt also tatsächlich den Modbus-Verkehr.

Die Abfrageintervalle sind in zwei Kategorien geteilt: schnelle Werte (Leistung, Spannung, Strom, Leistungsfaktor, Relaiszustand) und langsame Werte (Energiezähler, Frequenz, Fehler- und Diagnosemeldungen). Die Geräteidentität wird einmal beim Start gelesen.

Saldierte Netzwerte ab 1.1.0

Shelly zählt Energie pro Phase und addiert die Zähler nur auf. Ein saldierender Zweirichtungszähler, wie er in Deutschland üblich ist, rechnet dagegen über alle Phasen zusammen. Der Unterschied zeigt sich bei Photovoltaik: Speist die Anlage auf Phase A mit 600 W ein, während Phase B 50 W und Phase C 550 W beziehen, ist die Summe 0 W. Ein saldierender Zähler registriert nichts. Shellys Zähler verbuchen 600 Wh Einspeisung und gleichzeitig 600 Wh Bezug. Geprüft am Pro 3EM: total_act_power (Register 31013) ist korrekt saldiert, total_act_energy (31162) ist nur die Summe der Phasenzähler.

Dreiphasige Zähler bekommen deshalb vier zusätzliche Sensoren, die standardmäßig aktiv sind: Netzbezug und Netzeinspeisung jeweils als Leistung (W) und als Energie (kWh), jeweils mit dem Zusatz „(saldiert)“. Die Leistungswerte entstehen aus der bereits saldierten vorzeichenbehafteten Gesamtleistung. Die Energiezähler integrieren sie nach der Trapezregel, wie es auch der Riemann-Summen-Helfer von Home Assistant tut. Es muss also kein Helfer angelegt werden; die beiden kWh-Sensoren lassen sich direkt im Energie-Dashboard unter „Netzbezug“ und „Netzeinspeisung“ eintragen.

Die Zähler überstehen Neustarts. Eine fehlgeschlagene Messung oder eine Lücke von mehr als 15 Minuten unterbricht die Kette, statt über die Lücke zu integrieren – ein Ausfall kann so keine Energie erfinden. Die saldierten Zähler beginnen bei null; vergangene saldierte Werte lassen sich aus den Gerätezählern nicht rekonstruieren. Die rohen Phasenzähler laufen unverändert daneben weiter. Bei Geräten, die mehrere unabhängige Stromkreise messen, etwa dem Pro EM 50, gibt es die Sensoren nicht, weil eine Summe dort sinnlos wäre.

Schnelleres Standardintervall

Mit 1.1.0 sank das Standardintervall für schnelle Werte von 10 auf 5 Sekunden. Ein schneller Zyklus am Pro 3EM dauert 70 bis 100 ms; das Gerät ist damit zu etwa 2 % ausgelastet, bei 3 s zu etwa 3 %, bei 1 s zu etwa 10 %. Wer einen Einspeisebegrenzer oder einen Speicher aus diesen Werten steuert, kann also auf 1–2 s gehen. Bestehende Installationen behalten ihr gespeichertes Intervall und müssen unter „Konfigurieren“ von Hand umgestellt werden.

Nachbesserungen in 1.1.1 und 1.1.2

Beim Einrichten auf einer echten Home-Assistant-Instanz zeigte sich in 1.1.1 ein Fehler, den Tests ohne Hardware nicht erreichten: Meldete Zeroconf ein Gerät mit IPv6-Adresse, bekam die configuration_url die Adresse ohne eckige Klammern. Home Assistant las die Doppelpunkte als Portangabe und lehnte die URL ab; die Geräteregistrierung schlug fehl, und mit ihr alle Entitäten, obwohl die Integration als geladen galt. IPv6-Adressen werden jetzt eingeklammert, und Zeroconf bevorzugt IPv4, wenn die Ankündigung eine enthält. Außerdem wird die YAML-Registerdatei nicht mehr blockierend im Event-Loop gelesen, und der Options-Listener lädt den Config-Eintrag neu, wie es Home Assistant ab 2026.12 verlangt.

Die Version 1.1.2 begrenzt, wie lange die Integration auf ein hängendes Gerät wartet. Ein Gerät, das die TCP-Verbindung annimmt, aber nie antwortet, kostete bisher retries × (Verbindung + Lesen) pro Anfrage. Jetzt teilen sich alle Versuche einer Anfrage ein Zeitbudget vom Dreifachen des Client-Timeouts, bei der Voreinstellung 15 s. Ein Zyklus endet, sobald ein Block fehlschlägt und die Verbindung weg ist. Wenn die Einrichtung scheitert, gibt sie außerdem den geöffneten Socket wieder frei; vorher blieb pro Wiederholung einer liegen.

Installation

  1. In HACS unter „Benutzerdefinierte Repositories“ die Adresse https://github.com/sphings79/shelly-modbus-home-assistant mit der Kategorie „Integration“ hinzufügen.
  2. Nach „Shelly Modbus“ suchen, installieren und Home Assistant neu starten.
  3. Am Shelly unter Einstellungen → Modbus den Server aktivieren (ab Werk ist er aus), danach in Home Assistant die Integration hinzufügen.

Voraussetzung ist Home Assistant 2025.9 oder neuer. Nicht unterstützt sind Shelly-Geräte ohne Modbus-Server wie Plus 1PM, Plus Plug S oder Pro 4PM sowie alle Gen1-Geräte; dafür bleibt die offizielle Integration. Die Integration steht unter MIT-Lizenz, Oberfläche und Dokumentation gibt es auf Deutsch und Englisch.

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