fix: Offline-Flapping — erst nach 3 aufeinanderfolgenden Lesefehlern offline
Ein einzelner UDP-Paketverlust (Goodwe) oder TCP-Timeout (Modbus) hat sofort MQTT-Status "offline" getriggert. Bei 10s Poll-Rate reicht ein Ausreißer. Fix: _fail_count pro Poll-Loop, OFFLINE_THRESHOLD=3. Erst wenn 3 Reads in Folge scheitern (≥30s bei 10s Interval) wird offline publiziert. Erfolg resettet den Zähler auf 0 und stellt online sofort wieder her. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+2
-1
@@ -97,4 +97,5 @@
|
|||||||
| v1.8.20 | 2026-05-05 | Fix: Eigenversorgungskarte bei PV offline, Stromtarif-Einstellungen gehen nicht verloren |
|
| 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.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.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 |
|
| v1.8.23 | 2026-05-07 | Fix: Goodwe Netzbezug-Periode zeigt 0 kWh — integrierter grid_power-Zähler statt e_total_imp-Delta |
|
||||||
|
| v1.8.24 | 2026-05-07 | Fix: WR/Wallbox-Offline-Flapping — erst nach 3 aufeinanderfolgenden Lesefehlern offline schalten |
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: ShineBridge
|
name: ShineBridge
|
||||||
version: "1.8.23"
|
version: "1.8.24"
|
||||||
slug: shinebridge
|
slug: shinebridge
|
||||||
description: Growatt Wechselrichter lokal in Home Assistant — Modbus TCP via ShineLAN-X, MQTT Discovery, Web UI
|
description: Growatt Wechselrichter lokal in Home Assistant — Modbus TCP via ShineLAN-X, MQTT Discovery, Web UI
|
||||||
url: https://gitea.bitfire.work/retr0/shinebridge
|
url: https://gitea.bitfire.work/retr0/shinebridge
|
||||||
|
|||||||
@@ -314,6 +314,8 @@ def _poll_loop(inv_cfg: Dict[str, Any], stop: threading.Event):
|
|||||||
inv_int_import = hist_data["_int_import"][-1][1] if hist_data.get("_int_import") else 0.0
|
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
|
inv_int_export = hist_data["_int_export"][-1][1] if hist_data.get("_int_export") else 0.0
|
||||||
last_grid_ts = time.time()
|
last_grid_ts = time.time()
|
||||||
|
_fail_count = 0 # aufeinanderfolgende Lesefehler; erst ab >= 3 → offline
|
||||||
|
_OFFLINE_THRESHOLD = 3
|
||||||
|
|
||||||
while not stop.is_set():
|
while not stop.is_set():
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
@@ -354,6 +356,7 @@ def _poll_loop(inv_cfg: Dict[str, Any], stop: threading.Event):
|
|||||||
with State.lock:
|
with State.lock:
|
||||||
d = State.inv_data.setdefault(inv_id, {"poll_count": 0})
|
d = State.inv_data.setdefault(inv_id, {"poll_count": 0})
|
||||||
if values is not None:
|
if values is not None:
|
||||||
|
_fail_count = 0
|
||||||
d["values"] = values
|
d["values"] = values
|
||||||
d["last_update"] = time.time()
|
d["last_update"] = time.time()
|
||||||
d["modbus_ok"] = True
|
d["modbus_ok"] = True
|
||||||
@@ -369,9 +372,11 @@ def _poll_loop(inv_cfg: Dict[str, Any], stop: threading.Event):
|
|||||||
_publisher.publish_data(pub_values, prefix)
|
_publisher.publish_data(pub_values, prefix)
|
||||||
_publisher.publish_status("online", prefix)
|
_publisher.publish_status("online", prefix)
|
||||||
else:
|
else:
|
||||||
d["modbus_ok"] = False
|
_fail_count += 1
|
||||||
if _publisher:
|
if _fail_count >= _OFFLINE_THRESHOLD:
|
||||||
_publisher.publish_status("offline", prefix)
|
d["modbus_ok"] = False
|
||||||
|
if _publisher:
|
||||||
|
_publisher.publish_status("offline", prefix)
|
||||||
|
|
||||||
# Aggregate nach jedem erfolgreichen Poll neu berechnen und publizieren
|
# Aggregate nach jedem erfolgreichen Poll neu berechnen und publizieren
|
||||||
if values is not None and _publisher:
|
if values is not None and _publisher:
|
||||||
|
|||||||
Reference in New Issue
Block a user