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:
2026-09-03 21:03:17 +02:00
parent d4ba3bce7a
commit 2736c3d6e0
12 changed files with 148 additions and 22 deletions
+56
View File
@@ -9151,3 +9151,59 @@ flespi legt beim Schreiben das **ganze** Objekt als `pending` ab, also stand auc
unterscheidet. Gegen die echten Daten nachgewiesen (`flespi.py` einzeln geladen,
ohne Home Assistant): `Sleep Timeout (103): 10 → 15 unterwegs [wir: 15]`,
`Sleep Mode (102): 2` ohne Zusatz.
## CA. Audit nach dem Dongle-Umbau: vier Befunde, alle behoben (2026.9.3.12/.13)
Rundumblick auf Wunsch des Eigentümers. **Sauber:** 28 Backend-Dateien
`py_compile`, beide Frontend-Dateien als **Modul** geparst (Abschnitt AQ),
`tsc --noEmit`, `vite build`, 182/182 Tests. Dienste in `const.py`, `dienste.py`
(Schema und Registrierung) und `services.yaml` decken sich vollständig in beide
Richtungen; Katalog und Dataclass in `einstellungen.py` je 27 Einträge ohne
Abweichung, jedes Feld mit Beispielnamen, beide Listenfelder mit so vielen
Beispielen wie Positionen. Kein verwaister Name in `flespi.py`, und `ABSTAND_S`/
`_zu_alt`/`gelegenheit()` sind mit der Warteschlange restlos verschwunden.
**Befund 1 (schwer): jedes Profil-Speichern wartete auf flespi.**
`profil_schreiben` **awaitete** `wunsch_uebernehmen()` — bis zu drei HTTP-Runden
mit je 20 s Zeitlimit. Am Panel hängen **39 Aufrufstellen** von
`profilSpeichern()`, eine je Feldänderung: ein langsames flespi hätte die
Oberfläche bei jedem getippten Feld blockiert. Jetzt eine eigene Aufgabe
(`hass.async_create_task`) — das Speichern selbst ist zu dem Zeitpunkt längst
erledigt.
**Befund 2: ein gescheiterter Schreibversuch wurde bei jedem Speichern
wiederholt.** Der Fehlerstand hat kein `werte`, an dem der Wächter hätte
hängenbleiben können — mit abgelehntem Token wäre jede Feldänderung eine neue
Anfrage gewesen. Der Fehlerstand merkt sich jetzt unter `versucht`, WAS
gescheitert ist; ein neuer Reglerwert, ein erfolgreiches Lesen oder ein Neustart
heben die Sperre von selbst auf. Im selben Zug schreibt
`schlaf_timeout_schreiben()` nicht mehr, wenn der Wert bereits als `pending`
bereitliegt (ein **anderer** ausstehender Wert wird weiterhin überschrieben —
unserer ist der jüngere).
**Befund 3: die App behauptete etwas, das sie nicht wissen kann.** Der
Versionshinweis meldete „Diese Fassung ändert auch Natives — dafür muss die App
neu aufgespielt werden". Das war für `2026.9.3.11` schlicht falsch: eine reine
Backend-Korrektur, nur das Bündel war nach dem Versionssprung nicht neu gebaut.
Zwei echte Ursachen dahinter:
* `buendelPasst()` versprach im Kommentar, ein älteres Bündel abzulehnen
(„wäre ein Rückschritt"), prüfte aber nur `buendel.version !== eigene` — ein
**älteres** Bündel kam damit genauso durch wie ein neueres. Es vergleicht jetzt
zusätzlich gegen die Serverfassung; ohne bekannte Serverfassung (offline, altes
Backend) bleibt es beim alten Verhalten, denn ein Vergleich, den man nicht
anstellen kann, darf den Knopf nicht wegnehmen. **Drei Regressionstests**, der
entscheidende gegen den alten Stand als fehlschlagend nachgewiesen.
* Der Text sagt nicht mehr, *warum* nichts bereitliegt: „Dafür liegt hier kein
passendes Bündel — sie muss über Xcode neu aufgespielt werden."
**Befund 4, aus meiner eigenen Änderung desselben Tages:** das Regler-Minimum ist
von 0 auf 1 gewandert (das Gerät kennt kein Schlaf-Timeout unter einer Minute),
aber ein **bereits gespeicherter** Wert darunter lief ungeprüft durch — der
Daumen rastet bei 1 ein, die Anzeige daneben sagt „0 Min.". Beide Oberflächen
klemmen den gelesenen Wert jetzt auf 160.
**Merkposten, zum zweiten Mal in diesem Projekt (siehe BC und BV):** ein
Versionssprung ohne `npm run ota` lässt das Bündel zurück — und seit Befund 3
sagt die App dann wenigstens die Wahrheit darüber. Die Reihenfolge ist: erhöhen,
**dann** Bündel bauen, dann ausliefern.