Audit nach dem Dongle-Umbau: vier Befunde (2026.9.3.13)
1. profil_schreiben awaitete wunsch_uebernehmen und damit bis zu drei HTTP-Runden zu flespi - bei 39 Aufrufstellen von profilSpeichern() im Panel je Feldaenderung. Laeuft jetzt als eigene Aufgabe. 2. Ein gescheiterter Schreibversuch wurde bei jedem Speichern wiederholt, weil der Fehlerstand kein "werte" hat. Er merkt sich jetzt unter "versucht", was gescheitert ist. Dazu: kein zweites Schreiben, wenn der Wert schon als pending bereitliegt. 3. buendelPasst() versprach im Kommentar, ein aelteres Buendel abzulehnen, pruefte aber nur Ungleichheit - deshalb meldete die App "diese Fassung aendert auch Natives", obwohl nur das Buendel nach einem Versionssprung nicht neu gebaut war. Vergleicht jetzt gegen die Serverfassung, drei Regressionstests (der entscheidende gegen den alten Stand rot). Der Text behauptet keine Ursache mehr, die die App nicht kennen kann. 4. Das Regler-Minimum ging heute von 0 auf 1, ein bereits gespeicherter Wert darunter lief ungeprueft durch. Beide Oberflaechen klemmen jetzt auf 1-60. 182/182 Tests, 28 Backend-Dateien py_compile, beide Frontends als Modul geparst, Dienst- und Katalog-Konsistenz in beide Richtungen geprueft, Buendel auf derselben Fassung wie das Manifest. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -242,11 +242,15 @@ def registrieren(hass: HomeAssistant, k: Koordinator) -> None:
|
||||
await identitaet.fin_ableiten_und_uebernehmen(k.hass, k.zuordnung, k.ablage)
|
||||
await k.profil_veroeffentlichen()
|
||||
# Die Reglerstellung "Fahrt beenden" ist zugleich der Sollwert für den
|
||||
# Schlaf-Timeout des Dongles (103). Vorgemerkt statt geschrieben:
|
||||
# schreiben geht nur bei wachem Gerät, siehe flespi.py. Muss NACH
|
||||
# profil_veroeffentlichen() stehen - erst dort liest der Koordinator
|
||||
# Schlaf-Timeout des Dongles (103) - siehe flespi.py. Muss NACH
|
||||
# profil_veroeffentlichen() stehen: erst dort liest der Koordinator
|
||||
# die neue Reglerstellung mit.
|
||||
await flespi.wunsch_uebernehmen(k)
|
||||
#
|
||||
# Als eigene Aufgabe und ausdrücklich NICHT abgewartet: an diesem
|
||||
# Dienst hängen ~40 Aufrufstellen im Panel, eine je Feldänderung, und
|
||||
# jede würde sonst auf bis zu drei HTTP-Runden zu flespi warten. Das
|
||||
# Speichern selbst ist zu diesem Zeitpunkt längst erledigt.
|
||||
k.hass.async_create_task(flespi.wunsch_uebernehmen(k))
|
||||
|
||||
async def dongle_lesen(_aufruf: ServiceCall) -> None:
|
||||
"""Liest die Konfiguration des Dongles - auf ausdrücklichen Knopfdruck.
|
||||
|
||||
@@ -415,11 +415,20 @@ async def schlaf_timeout_schreiben(k: Koordinator, minuten: int) -> dict:
|
||||
vorher_roh = await _alle_einstellungen(k.hass, token, geraet)
|
||||
vorher = _sicht(vorher_roh, "current")
|
||||
offen_vorher = _sicht(vorher_roh, "pending")
|
||||
if (
|
||||
schon_da = (
|
||||
vorher.get(SCHLAF_SCHLUESSEL) == minuten
|
||||
and offen_vorher.get(SCHLAF_SCHLUESSEL) is None
|
||||
):
|
||||
_LOGGER.debug("Sleep Timeout steht bereits auf %s Min. - nichts zu tun", minuten)
|
||||
)
|
||||
# Liegt der Wert schon bereit, waere ein zweites Schreiben nur Funkzeit.
|
||||
# Ein ANDERER ausstehender Wert wird dagegen ueberschrieben - unserer ist
|
||||
# der juengere.
|
||||
unterwegs = offen_vorher.get(SCHLAF_SCHLUESSEL) == minuten
|
||||
if schon_da or unterwegs:
|
||||
_LOGGER.debug(
|
||||
"Sleep Timeout %s Min. steht bereits %s - nichts zu tun",
|
||||
minuten,
|
||||
"am Gerät" if schon_da else "bereit",
|
||||
)
|
||||
return _stand(geraet, vorher_roh, wunsch_timeout(k))
|
||||
|
||||
# Das ganze Objekt zurückschreiben, nur mit geändertem Feld: `type` und die
|
||||
@@ -498,6 +507,11 @@ async def wunsch_uebernehmen(k: Koordinator) -> None:
|
||||
# ausstehender Wert (`offen`) zählt dabei wie ein gesetzter - er ist schon
|
||||
# unterwegs.
|
||||
if k.flespi_stand:
|
||||
# Schon einmal mit genau diesem Ziel gescheitert: nicht bei jeder
|
||||
# Gelegenheit erneut anrennen. Ein neuer Reglerwert, ein erfolgreiches
|
||||
# Lesen oder ein Neustart heben die Sperre von selbst auf.
|
||||
if k.flespi_stand.get("versucht") == ziel:
|
||||
return
|
||||
for zeile in k.flespi_stand.get("werte", []):
|
||||
if zeile["schluessel"] != SCHLAF_SCHLUESSEL:
|
||||
continue
|
||||
@@ -512,8 +526,13 @@ async def wunsch_uebernehmen(k: Koordinator) -> None:
|
||||
stand = await schlaf_timeout_schreiben(k, ziel)
|
||||
except FlespiFehler as fehler:
|
||||
_LOGGER.warning("Sleep Timeout konnte nicht gesetzt werden: %s", fehler)
|
||||
# "versucht" haelt fest, WAS gescheitert ist. Ohne das versuchte
|
||||
# es der Waechter unten bei jedem Profil-Speichern erneut - der
|
||||
# Fehlerstand hat kein "werte", an dem er haengenbleiben koennte,
|
||||
# und ein kaputter Token haette so jede Feldaenderung eine Anfrage
|
||||
# gekostet.
|
||||
await k.flespi_stand_setzen(
|
||||
{"fehler": str(fehler), "gelesen_am": jetzt_iso()}
|
||||
{"fehler": str(fehler), "gelesen_am": jetzt_iso(), "versucht": ziel}
|
||||
)
|
||||
return
|
||||
await k.flespi_stand_setzen(stand)
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":"2026.9.3.10","sha256":"f1a9a5c2ff1ef7fbd29c679e1b1a374d77c57da4f49f864b3758219483bbb013","bytes":269156,"gebaut":"2026-09-03T17:59:17Z"}
|
||||
{"version":"2026.9.3.13","sha256":"9b8881ea19de328d9b239f93edadc14927e33478565b66679ead690362b8ccf3","bytes":269175,"gebaut":"2026-09-03T19:02:24Z"}
|
||||
Binary file not shown.
@@ -203,8 +203,12 @@ function profilZuConfig(p) {
|
||||
// Der Wert hat die Zeit ueberlebt, in der die Einstellung nicht
|
||||
// angeboten wurde (31.08. bis 03.09.2026); der Standard greift nur bei
|
||||
// neuen Profilen. Siehe fahrterkennung._pausenzeit_s im Backend.
|
||||
// Auf den Bereich des Reglers geklemmt: der ging bis zum 03.09.2026 ab 0
|
||||
// ("sofort"), das Geraet kennt aber kein Schlaf-Timeout unter einer
|
||||
// Minute. Ein gespeicherter alter Wert stuende sonst als "0 Min." neben
|
||||
// einem Daumen, der bei 1 einrastet.
|
||||
pausenzeit: Number.isFinite(p.einstellungen.fahrten_pausenzeit_min)
|
||||
? p.einstellungen.fahrten_pausenzeit_min : 15,
|
||||
? Math.min(60, Math.max(1, p.einstellungen.fahrten_pausenzeit_min)) : 15,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"domain": "audi_dashboard",
|
||||
"name": "Audi Dashboard",
|
||||
"version": "2026.9.3.11",
|
||||
"version": "2026.9.3.13",
|
||||
"documentation": "https://gitea.nothaft.cloud/paul/audi-app/src/branch/main/README.md",
|
||||
"issue_tracker": "https://gitea.nothaft.cloud/paul/audi-app/issues",
|
||||
"codeowners": ["@paul"],
|
||||
|
||||
Reference in New Issue
Block a user