boxwart: Update-Verlauf zeigt das echte Ergebnis je Baustein, festgehaltene Bausteine sichtbar
Ampel / ampel (push) Failing after 22s

Der Verlauf las bisher nur den Hermes-Cron-Status ("Skript lief") und zeigte die
Laeufe vom 06. und 13.09. als "durchgelaufen", obwohl dort zurueckgerollt und
festgehalten wurde; ein abgebrochener Lauf stand als "laeuft" da. Jetzt kommt der
Verlauf aus dem Meldeprotokoll (~/mc2-notify.log), also aus dem, was autoupdate.sh
selbst je Baustein meldet.

Festgehaltene Bausteine (Pin-Register) werden zum Waechter-Hinweis mit Knopf
"Freigeben", auf der Updates-Seite markiert und in der Updates-Lampe gezaehlt.
Hermes zeigt seine laufende Version und die Zahl der neuen Aenderungen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-09-23 21:56:19 +02:00
co-authored by Claude Opus 5.5
parent f3af2adec3
commit 790de19f1a
21 changed files with 544 additions and 80 deletions
+29 -6
View File
@@ -6,8 +6,10 @@ Box-Wart-Schnittstellen (Umbau 09/2026): alles, was der Cockpit-Startbildschirm
POST /api/hinweise/{id}/aktion/{aktion} Knopf eines Hinweises ausführen
GET /api/modelle/nutzung Wer nutzt die Modelle (7 Tage, 24 h je Stunde)
GET /api/zeitplan Heute gelaufen / demnächst geplant
GET /api/updates/verlauf Was die letzten Update-Läufe wirklich gebracht haben
POST /api/updates/festgehalten/{b}/freigeben Festgehaltenen Baustein wieder freigeben
Dünn: die Logik liegt in services/waechter.py, modell_nutzung.py, zeitplan.py.
Dünn: die Logik liegt in services/waechter.py, modell_nutzung.py, zeitplan.py, update_verlauf.py.
"""
import os
@@ -19,7 +21,16 @@ from zoneinfo import ZoneInfo
import psutil
from config import MODELS_DIR
from fastapi import APIRouter, HTTPException
from services import backup, llamaswap, maintenance, modell_nutzung, system, waechter, zeitplan
from services import (
backup,
llamaswap,
maintenance,
modell_nutzung,
system,
update_verlauf,
waechter,
zeitplan,
)
router = APIRouter(prefix="/api", tags=["boxwart"])
LOCAL_TZ = ZoneInfo(os.environ.get("MC_LOCAL_TZ", "Europe/Berlin"))
@@ -115,7 +126,11 @@ def _lampen(stand: dict, u: dict) -> list[dict]:
lampen.append(lampe("platte", "Platte", zustand, f"{platte:.0f} %" if platte is not None else ""))
n = len(_bausteine(u))
lampen.append(lampe("updates", "Updates", "info" if n else "ok", f"{n} bereit" if n else "aktuell"))
fest = len(update_verlauf.festgehalten())
if fest:
lampen.append(lampe("updates", "Updates", "warn", f"{fest} festgehalten"))
else:
lampen.append(lampe("updates", "Updates", "info" if n else "ok", f"{n} bereit" if n else "aktuell"))
return lampen
@@ -150,7 +165,8 @@ def start() -> dict:
"verlauf": stand["verlauf"][:20],
"lampen": _lampen(stand, u),
"box": _box(),
"updates": {"bausteine": _bausteine(u), "modelle": u.get("model_list") or []},
"updates": {"bausteine": _bausteine(u), "modelle": u.get("model_list") or [],
"festgehalten": update_verlauf.festgehalten()},
"flugplan": zeitplan.flugplan(),
}
@@ -180,5 +196,12 @@ def zeitplan_route() -> dict:
@router.get("/updates/verlauf")
def updates_verlauf(anzahl: int = 8) -> dict:
"""Die letzten Läufe des Sonntags-Updates (Hermes-Cron, executions.db nur lesend)."""
return {"laeufe": waechter.update_laeufe(max(1, min(anzahl, 30)))}
"""Die letzten Update-Läufe mit dem Ergebnis je Baustein (aus dem Meldeprotokoll der Box)."""
return {"laeufe": update_verlauf.laeufe(max(1, min(anzahl, 30)))}
@router.post("/updates/festgehalten/{baustein}/freigeben")
def festgehalten_freigeben(baustein: str) -> dict:
if not update_verlauf.freigeben(baustein):
raise HTTPException(status_code=404, detail="Dieser Baustein ist nicht festgehalten.")
return {"ok": True, "text": update_verlauf.FREIGEGEBEN_TEXT}