diff --git a/app.py b/app.py index 8dc2e6e..269afe1 100644 --- a/app.py +++ b/app.py @@ -38,9 +38,13 @@ async def lifespan(application: FastAPI): # Start background polling interval = int(database.get_setting("poll_interval", "15")) bg_scheduler.add_job(scheduler.poll_status, "interval", seconds=interval, id="poll") + bg_scheduler.add_job(scheduler.check_devices, "interval", seconds=240, id="device_check") bg_scheduler.start() logger.info("Polling gestartet (Intervall: %ds)", interval) + # Initial device check + scheduler.check_devices() + yield bg_scheduler.shutdown() @@ -195,8 +199,13 @@ async def devices_page(request: Request): devices = conn.execute( "SELECT * FROM wled_devices ORDER BY name, hostname" ).fetchall() + last_check_row = conn.execute( + "SELECT MAX(last_check) as lc FROM wled_devices WHERE last_check IS NOT NULL" + ).fetchone() conn.close() - return templates.TemplateResponse(*_ctx(request, "devices", devices=devices)) + last_check = last_check_row["lc"] if last_check_row and last_check_row["lc"] else None + return templates.TemplateResponse(*_ctx(request, "devices", + devices=devices, last_check=last_check)) @app.post("/api/devices") @@ -241,15 +250,10 @@ async def delete_device(device_id: int): return RedirectResponse("/devices", status_code=303) -@app.get("/api/devices/{device_id}/status") -async def device_status(device_id: int): - from wled_client import get_wled_info - conn = database.get_db() - dev = conn.execute("SELECT hostname FROM wled_devices WHERE id=?", (device_id,)).fetchone() - conn.close() - if not dev: - return {"online": False} - return get_wled_info(dev["hostname"]) +@app.post("/api/devices/check-all") +async def check_all_devices(): + scheduler.check_devices() + return RedirectResponse("/devices", status_code=303) # ── Assignments ──────────────────────────────────────────────────────────── diff --git a/database.py b/database.py index c0d0365..e814b61 100644 --- a/database.py +++ b/database.py @@ -32,7 +32,11 @@ def init_db(): id INTEGER PRIMARY KEY AUTOINCREMENT, hostname TEXT NOT NULL UNIQUE, name TEXT DEFAULT '', - segment_count INTEGER NOT NULL DEFAULT 2 + segment_count INTEGER NOT NULL DEFAULT 2, + online INTEGER DEFAULT 0, + leds INTEGER DEFAULT 0, + version TEXT DEFAULT '', + last_check TIMESTAMP ); CREATE TABLE IF NOT EXISTS assignments ( @@ -71,6 +75,24 @@ def init_db(): ); """) + # Migrate: add columns if missing (for existing databases) + try: + conn.execute("ALTER TABLE wled_devices ADD COLUMN online INTEGER DEFAULT 0") + except Exception: + pass + try: + conn.execute("ALTER TABLE wled_devices ADD COLUMN leds INTEGER DEFAULT 0") + except Exception: + pass + try: + conn.execute("ALTER TABLE wled_devices ADD COLUMN version TEXT DEFAULT ''") + except Exception: + pass + try: + conn.execute("ALTER TABLE wled_devices ADD COLUMN last_check TIMESTAMP") + except Exception: + pass + defaults = { "azure_client_id": "", "azure_client_secret": "", diff --git a/scheduler.py b/scheduler.py index f8277a1..422eceb 100644 --- a/scheduler.py +++ b/scheduler.py @@ -3,7 +3,7 @@ import os from datetime import datetime from database import get_db, get_setting, log_activity -from wled_client import build_wled_url, call_wled +from wled_client import build_wled_url, call_wled, get_wled_info logger = logging.getLogger(__name__) @@ -197,3 +197,29 @@ def _process_user(user, aida_lines, settings, conn): display_name, aida_status or "-", teams_status, "aktualisiert" if wled_changed else "nur Dashboard", ) + + +def check_devices(): + """Check all WLED devices and store status in DB. Called periodically.""" + conn = get_db() + try: + devices = conn.execute("SELECT id, hostname FROM wled_devices").fetchall() + for dev in devices: + info = get_wled_info(dev["hostname"]) + conn.execute(""" + UPDATE wled_devices + SET online=?, leds=?, version=?, last_check=? + WHERE id=? + """, ( + 1 if info.get("online") else 0, + info.get("leds", 0) if info.get("online") else 0, + info.get("version", "") if info.get("online") else "", + datetime.now(), + dev["id"], + )) + conn.commit() + logger.info("Device-Check: %d Geraete geprueft", len(devices)) + except Exception as e: + logger.error("Device-Check Fehler: %s", e) + finally: + conn.close() diff --git a/templates/devices.html b/templates/devices.html index db6d95b..8311691 100644 --- a/templates/devices.html +++ b/templates/devices.html @@ -4,9 +4,16 @@ {% block content %}

WLED-Geraete

- +
+
+ +
+ {% if last_check %} + Letzte Pruefung: {{ last_check }} + {% endif %} +
@@ -30,20 +37,24 @@ {% for device in devices %} - + {% if device.last_check %} + {% if device.online %} + + {% else %} + + {% endif %} + {% else %} + + {% endif %} {{ device.hostname }} {{ device.name }} - - - - + {{ device.leds if device.leds else '-' }} + {{ device.version if device.version else '-' }} {{ device.segment_count }} -
+
+ {{ devices|length }} Geraete | Status wird alle 4 Minuten automatisch geprueft +
@@ -139,44 +153,3 @@
{% endblock %} - -{% block scripts %} - -{% endblock %}