fix(goodwe): Netzbezug-Periode zeigt 0 kWh — integrierter grid_power-Zähler
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
+22
-3
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user