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:
retr0
2026-05-07 09:58:48 +02:00
parent a9f33c8e9e
commit a361c30f1b
3 changed files with 11 additions and 5 deletions
+8 -3
View File
@@ -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_export = hist_data["_int_export"][-1][1] if hist_data.get("_int_export") else 0.0
last_grid_ts = time.time()
_fail_count = 0 # aufeinanderfolgende Lesefehler; erst ab >= 3 → offline
_OFFLINE_THRESHOLD = 3
while not stop.is_set():
t0 = time.time()
@@ -354,6 +356,7 @@ def _poll_loop(inv_cfg: Dict[str, Any], stop: threading.Event):
with State.lock:
d = State.inv_data.setdefault(inv_id, {"poll_count": 0})
if values is not None:
_fail_count = 0
d["values"] = values
d["last_update"] = time.time()
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_status("online", prefix)
else:
d["modbus_ok"] = False
if _publisher:
_publisher.publish_status("offline", prefix)
_fail_count += 1
if _fail_count >= _OFFLINE_THRESHOLD:
d["modbus_ok"] = False
if _publisher:
_publisher.publish_status("offline", prefix)
# Aggregate nach jedem erfolgreichen Poll neu berechnen und publizieren
if values is not None and _publisher: