From a9f33c8e9e3639b1b00ec9e056d8713b9b976823 Mon Sep 17 00:00:00 2001 From: retr0 <42kdesigners@gmail.com> Date: Thu, 7 May 2026 09:55:24 +0200 Subject: [PATCH] =?UTF-8?q?fix(goodwe):=20Netzbezug-Periode=20zeigt=200=20?= =?UTF-8?q?kWh=20=E2=80=94=20integrierter=20grid=5Fpower-Z=C3=A4hler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit e_total_imp vom Goodwe-WR ist ein Lifetime-Zähler seit Inbetriebnahme. Beim ersten Verbinden speichert save_period_start_if_new() den aktuellen Wert als Periodenstart → Delta = 0. Fix: _int_import/_int_export werden je Poll-Zyklus aus grid_power integriert (W × dt / 3.600.000 → kWh), in der measurements-DB persistiert und beim Neustart aus der DB wiederhergestellt. AGG_SENSOR_IDS bevorzugt nun _int_import vor e_total_imp, SDM-630 (import_kwh) bleibt erste Wahl. Private Keys (Prefix _) werden nicht an MQTT gepublished. Co-Authored-By: Claude Sonnet 4.6 --- ROADMAP.md | 1 + haos-addon/config.yaml | 2 +- haos-addon/src/main.py | 25 ++++++++++++++++++++++--- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 87a152b..1e85b42 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -97,3 +97,4 @@ | v1.8.20 | 2026-05-05 | Fix: Eigenversorgungskarte bei PV offline, Stromtarif-Einstellungen gehen nicht verloren | | v1.8.21 | 2026-05-05 | Fix: Finanzen-Tab bleibt nicht bei "Lade..." hängen (fEur/fKwh Scope-Bug) | | v1.8.22 | 2026-05-06 | Fix: Stromtarif-Einstellungen bleiben nach Neustart erhalten; Finanzen-Tab Layout | +| v1.8.23 | 2026-05-06 | Fix: Goodwe Netzbezug-Periode zeigt 0 kWh — integrierter grid_power-Zähler statt e_total_imp-Delta | diff --git a/haos-addon/config.yaml b/haos-addon/config.yaml index fc4a1ce..3d0666a 100644 --- a/haos-addon/config.yaml +++ b/haos-addon/config.yaml @@ -1,5 +1,5 @@ name: ShineBridge -version: "1.8.22" +version: "1.8.23" slug: shinebridge description: Growatt Wechselrichter lokal in Home Assistant — Modbus TCP via ShineLAN-X, MQTT Discovery, Web UI url: https://gitea.bitfire.work/retr0/shinebridge diff --git a/haos-addon/src/main.py b/haos-addon/src/main.py index 29b2cdb..2ff021b 100644 --- a/haos-addon/src/main.py +++ b/haos-addon/src/main.py @@ -55,8 +55,8 @@ AGG_SENSOR_IDS: Dict[str, List[str]] = { "total_energy_today": ["energy_today", "e_day"], "total_energy_total": ["energy_total", "e_total"], "grid_power": ["grid_power"], - "grid_import_kwh": ["import_kwh", "e_total_imp"], - "grid_export_kwh": ["export_kwh", "e_total_exp"], + "grid_import_kwh": ["import_kwh", "_int_import", "e_total_imp"], + "grid_export_kwh": ["export_kwh", "_int_export", "e_total_exp"], "bat_charge_power": ["bat_charge_power"], "bat_discharge_power": ["bat_discharge_power"], "bat_charge_total": ["bat_charge_total", "e_bat_charge_total"], @@ -310,6 +310,11 @@ def _poll_loop(inv_cfg: Dict[str, Any], stop: threading.Event): q.append(pt) log.info("[%s] %d Sensoren aus DB geladen", inv_id, len(hist_data)) + # Integrierte Grid-Zähler — starten bei 0, wachsen mit jedem Poll, persistieren in DB + inv_int_import = hist_data["_int_import"][-1][1] if hist_data.get("_int_import") else 0.0 + inv_int_export = hist_data["_int_export"][-1][1] if hist_data.get("_int_export") else 0.0 + last_grid_ts = time.time() + while not stop.is_set(): t0 = time.time() values = reader.read(inverter) @@ -322,6 +327,19 @@ def _poll_loop(inv_cfg: Dict[str, Any], stop: threading.Event): if values and "grid_power" not in values and "import_kwh" in values and "total_power" in values: values["grid_power"] = values["total_power"] + # grid_power integrieren → interne kWh-Zähler (Periodenberechnung für Goodwe / kein SDM-630) + if values is not None and "grid_power" in values: + dt_s = t0 - last_grid_ts + if 0 < dt_s < 300: + gp = values["grid_power"] + if gp > 0: + inv_int_import = round(inv_int_import + gp * dt_s / 3_600_000, 6) + elif gp < 0: + inv_int_export = round(inv_int_export + (-gp) * dt_s / 3_600_000, 6) + values["_int_import"] = inv_int_import + values["_int_export"] = inv_int_export + last_grid_ts = t0 + # EMS: PV-Überschuss aus anderen Geräten holen und Ladestrom regeln if ems is not None and values is not None and inv_cfg.get("ems_enabled", True): pv_surplus = _get_pv_surplus() @@ -347,7 +365,8 @@ def _poll_loop(inv_cfg: Dict[str, Any], stop: threading.Event): q.append((now, val)) history.write_batch(inv_id, now, values) if _publisher: - _publisher.publish_data(values, prefix) + pub_values = {k: v for k, v in values.items() if not k.startswith("_")} + _publisher.publish_data(pub_values, prefix) _publisher.publish_status("online", prefix) else: d["modbus_ok"] = False