From 33c6a15644c6b512d219cf5d7f7fd6c4f7b028ad Mon Sep 17 00:00:00 2001 From: retr0 <42kdesigners@gmail.com> Date: Sun, 26 Apr 2026 17:07:14 +0200 Subject: [PATCH] Feature: Eastron SDM-630 Support + Float32 Decode (v1.1.5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - inverters.py: data_type Feld in Sensor (uint16/uint32/float32) + SDM-630 Definition (16 Sensoren: U/I/P L1-L3, PF, Freq, kWh) + read_ranges: [(0, 76)] — alle Sensoren in einem Batch - modbus_client.py: Float32 IEEE 754 Decode via struct.unpack (SDM-630 liefert Floats, Growatt liefert skalierte Integer) - index.html: "Wechselrichter" → "Gerät" — Add-on unterstützt jetzt beliebige Modbus-Geräte, nicht nur Wechselrichter Co-Authored-By: Claude Sonnet 4.6 --- haos-addon/config.yaml | 2 +- haos-addon/src/inverters.py | 32 +++++++++++++++++++++++++++++++- haos-addon/src/modbus_client.py | 17 ++++++++++++----- haos-addon/src/web/index.html | 20 ++++++++++---------- 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/haos-addon/config.yaml b/haos-addon/config.yaml index 97ac4cf..0eb132e 100644 --- a/haos-addon/config.yaml +++ b/haos-addon/config.yaml @@ -1,5 +1,5 @@ name: ShineBridge -version: "1.1.4" +version: "1.1.5" slug: shinebridge description: Growatt Wechselrichter lokal in Home Assistant — Modbus TCP via ShineLAN-X, MQTT Discovery, Web UI url: https://gitea.bitfire.work/retr0/Growatt-Wechselrichter-HAOS diff --git a/haos-addon/src/inverters.py b/haos-addon/src/inverters.py index dde608a..952f4b9 100644 --- a/haos-addon/src/inverters.py +++ b/haos-addon/src/inverters.py @@ -7,12 +7,13 @@ class Sensor: id: str name: str reg: int - count: int # 1 = uint16, 2 = uint32 (high word first) + count: int # number of 16-bit registers (1 or 2) scale: float unit: str device_class: Optional[str] state_class: str icon: str + data_type: str = "uint16" # "uint16", "uint32", "float32" @dataclass @@ -95,6 +96,28 @@ def _mod_sensors() -> List[Sensor]: ] +def _sdm630_sensors() -> List[Sensor]: + f = "float32" + return [ + Sensor("voltage_l1", "Spannung L1", 0, 2, 1.0, "V", "voltage", "measurement", "mdi:flash", f), + Sensor("voltage_l2", "Spannung L2", 2, 2, 1.0, "V", "voltage", "measurement", "mdi:flash", f), + Sensor("voltage_l3", "Spannung L3", 4, 2, 1.0, "V", "voltage", "measurement", "mdi:flash", f), + Sensor("current_l1", "Strom L1", 6, 2, 1.0, "A", "current", "measurement", "mdi:flash", f), + Sensor("current_l2", "Strom L2", 8, 2, 1.0, "A", "current", "measurement", "mdi:flash", f), + Sensor("current_l3", "Strom L3", 10, 2, 1.0, "A", "current", "measurement", "mdi:flash", f), + Sensor("power_l1", "Wirkleistung L1", 12, 2, 1.0, "W", "power", "measurement", "mdi:flash", f), + Sensor("power_l2", "Wirkleistung L2", 14, 2, 1.0, "W", "power", "measurement", "mdi:flash", f), + Sensor("power_l3", "Wirkleistung L3", 16, 2, 1.0, "W", "power", "measurement", "mdi:flash", f), + Sensor("power_factor_l1", "Leistungsfaktor L1", 30, 2, 1.0, "", None, "measurement", "mdi:sine-wave", f), + Sensor("power_factor_l2", "Leistungsfaktor L2", 32, 2, 1.0, "", None, "measurement", "mdi:sine-wave", f), + Sensor("power_factor_l3", "Leistungsfaktor L3", 34, 2, 1.0, "", None, "measurement", "mdi:sine-wave", f), + Sensor("total_power", "Gesamtwirkleistung", 48, 2, 1.0, "W", "power", "measurement", "mdi:transmission-tower", f), + Sensor("frequency", "Frequenz", 70, 2, 1.0, "Hz", "frequency", "measurement", "mdi:sine-wave", f), + Sensor("import_kwh", "Bezug Gesamt", 72, 2, 1.0, "kWh", "energy", "total_increasing", "mdi:transmission-tower-import", f), + Sensor("export_kwh", "Einspeisung Gesamt", 74, 2, 1.0, "kWh", "energy", "total_increasing", "mdi:transmission-tower-export", f), + ] + + INVERTERS = { "MIC_1500_TL_X": Inverter( id="MIC_1500_TL_X", @@ -124,4 +147,11 @@ INVERTERS = { sensors=_mod_sensors(), read_ranges=[(3, 91), (93, 1)], ), + "SDM_630": Inverter( + id="SDM_630", + name="Eastron SDM-630", + manufacturer="Eastron", + sensors=_sdm630_sensors(), + read_ranges=[(0, 76)], # regs 0-75, alle 16 Sensoren + ), } diff --git a/haos-addon/src/modbus_client.py b/haos-addon/src/modbus_client.py index 857c1cf..974080d 100644 --- a/haos-addon/src/modbus_client.py +++ b/haos-addon/src/modbus_client.py @@ -1,4 +1,5 @@ import logging +import struct import time from typing import Dict, Optional @@ -66,12 +67,18 @@ def _extract_sensors(sensors: list, regs: Dict[int, int]) -> Dict[str, float]: if s.reg not in regs: log.warning("Register %d fehlt in Antwort (%s)", s.reg, s.id) continue - if s.count == 2: + data_type = getattr(s, "data_type", "uint16") + if data_type == "float32": if s.reg + 1 not in regs: - log.warning("Register %d (high word) fehlt (%s)", s.reg + 1, s.id) + log.warning("Register %d+1 fehlt (%s)", s.reg, s.id) continue - raw = (regs[s.reg] << 16) | regs[s.reg + 1] + raw_val = struct.unpack(">f", struct.pack(">HH", regs[s.reg], regs[s.reg + 1]))[0] + elif s.count == 2: + if s.reg + 1 not in regs: + log.warning("Register %d+1 fehlt (%s)", s.reg, s.id) + continue + raw_val = ((regs[s.reg] << 16) | regs[s.reg + 1]) * s.scale else: - raw = regs[s.reg] - values[s.id] = round(raw * s.scale, 3) + raw_val = regs[s.reg] * s.scale + values[s.id] = round(raw_val, 3) return values diff --git a/haos-addon/src/web/index.html b/haos-addon/src/web/index.html index 370f08b..a778b65 100644 --- a/haos-addon/src/web/index.html +++ b/haos-addon/src/web/index.html @@ -161,7 +161,7 @@
Live-Daten
-
Wechselrichter
+
Geräte
Einstellungen
@@ -195,11 +195,11 @@