Sync to Pi: alle Features die live deployed sind
Aus dem Backup und Live-Pull vom Pi (10.11.3.144): - dashboard.py: Grid-Linien nur im freien Hintergrund (nicht durch Widgets) - templates/index.html: komplett redesigned mit Sidebar + Topbar + Toast + Modal - plugins/clock.py: responsive Layout (1x1 bis 4x4) - plugins/system.py, weather.py, minimax.py: mit Threshold-Bars und Color-Variants - plugins/base.py: NEU — fetch_with_retry Helper (3x retry mit backoff) + render_error_banner für fehlgeschlagene API-Plugins (grosses rotes "!" Icon mit Plugin-Name und Fehler statt Crash) Cleanup: Helfer-Chaos (renderer.py/2/3, design_a/b/c.html, clock_classic.py, 23x clock_*.png, alte test_*.py) wurde bereits im vorherigen Commit entfernt. Co-Authored-By: Hermes <noreply@hermes.local>
This commit is contained in:
co-authored by
Hermes
parent
af9a99a379
commit
1f142f5245
@@ -229,9 +229,50 @@ def is_wifi_connected() -> bool:
|
||||
return "connected" in out.lower()
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Recovery threshold helper (used by admin.py)
|
||||
# ============================================================================
|
||||
def get_recovery_threshold() -> int:
|
||||
"""Liest recovery_threshold_s aus config.json (default 60s)."""
|
||||
try:
|
||||
from pathlib import Path as _P
|
||||
cfg_path = _P("/home/koptikp/epaper-dashboard/port/config.json")
|
||||
if cfg_path.exists():
|
||||
import json as _json
|
||||
cfg = _json.loads(cfg_path.read_text())
|
||||
return int(cfg.get("recovery_threshold_s", 60))
|
||||
except Exception:
|
||||
pass
|
||||
return 60
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Watchdog
|
||||
# ============================================================================
|
||||
def _check_recovery_needed(state: dict, threshold_s: int) -> dict:
|
||||
"""Entscheidet, ob die Recovery-Info UI angezeigt werden soll.
|
||||
|
||||
Returns dict mit:
|
||||
show: bool
|
||||
reason: 'offline' | 'ap_active' | 'connecting_timeout' | 'no_ip'
|
||||
duration_s: Sekunden im aktuellen (nicht-client) Zustand
|
||||
"""
|
||||
mode = state.get("mode", "unknown")
|
||||
if mode == "client":
|
||||
return {"show": False, "reason": "client", "duration_s": 0}
|
||||
# Im AP-Modus: immer anzeigen
|
||||
if mode == "ap":
|
||||
return {"show": True, "reason": "ap_active", "duration_s": state.get("since_change_s", 0)}
|
||||
if mode == "offline":
|
||||
return {"show": True, "reason": "offline", "duration_s": state.get("since_change_s", 0)}
|
||||
if mode == "connecting":
|
||||
# Connecting dauert zu lange? Zeige info.
|
||||
return {"show": state.get("since_change_s", 0) > threshold_s,
|
||||
"reason": "connecting_timeout",
|
||||
"duration_s": state.get("since_change_s", 0)}
|
||||
return {"show": False, "reason": "unknown", "duration_s": state.get("since_change_s", 0)}
|
||||
|
||||
|
||||
class Watchdog:
|
||||
def __init__(self):
|
||||
self.state = NetState()
|
||||
|
||||
Reference in New Issue
Block a user