Regler stellt den Schlaf-Timeout des Dongles (2026.9.3.10)

Der Regler "Fahrt beenden" ist jetzt eine Zahl fuer zwei Dinge: unsere eigene
Wartezeit bis zum Fahrtende und der Schlaf-Timeout des FMM003 (103). So lange
bleibt der Dongle wach und wartet darauf, dass es gleich weitergeht; danach
schlaeft er. Die 180 s Ignition OFF Delay laufen davor und bleiben unsichtbar -
sie werden nur von der Fahrtdauer abgezogen. Der Regler geht deshalb von 1 bis
60 in Einerschritten; das Geraet kennt kein Timeout 0.

flespi.py liest und schreibt die Geraete-Konfiguration. Drei Annahmen sind an
der echten API gefallen und stehen als Messung im Modulkopf: der Wert liegt in
current (nicht value), die Einstellung heisst sleep_mode mit dem Wert eine Ebene
tiefer unter mode, und ein PUT braucht {"properties": ..., "address": ...}.

Die eigene Auftrags-Warteschlange ist wieder entfallen. Sie war fuer "das Geraet
schlaeft" gebaut - das gilt aber nur fuer das Geraet, nicht fuer die
Schnittstelle: die vollstaendige Konfiguration kam herein, waehrend das Fahrzeug
seit dem Vortag stand. flespi puffert selbst (pending + address=connection), ein
zweites Auftragsbuch waere eine zweite Warteschlange fuer dieselbe Aufgabe.

Gegengelesen wird nach jedem Schreiben; als Erfolg zaehlt current ODER pending -
letzteres ist bei stehendem Fahrzeug der Normalfall.

Live gegen den echten Account belegt: Token sieht genau ein Geraet, 127
Einstellungen bei parkendem Fahrzeug gelesen, Regler 15 geschrieben und als
pending bestaetigt (Nachbarfelder unveraendert), zweiter Neustart ohne erneute
Anfrage.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-03 20:00:39 +02:00
co-authored by Claude Opus 5
parent 8c96d9b78e
commit 4d4890034a
18 changed files with 999 additions and 30 deletions
+111 -1
View File
@@ -1,6 +1,7 @@
# AGENTS.md — Project state, review findings, open items, and working rules
**Last updated: 2026-09-03** (Zugaenge: die Dienste-Token aus App und Panel bedienbar, der Wert kommt nie
**Last updated: 2026-09-03** (Der Regler stellt den Schlaf-Timeout des Dongles, flespi lesend und
schreibend, die eigene Warteschlange wieder entfallen, `2026.9.3.10`, Abschnitt BZ. Davor: Zugaenge: die Dienste-Token aus App und Panel bedienbar, der Wert kommt nie
zurueck, `2026.9.3.8`, Abschnitt BY. Davor: „Fahrt beenden“ auf Knopfdruck mit vorlaeufigem Ende, Schieberegler in
5-Minuten-Schritten und im Tagmodus sichtbar, `2026.9.3.7`, Abschnitt BX.
Davor: Die Fahrt endet wieder bei uns statt im Dongle - Zuendung als Ausloeser,
@@ -9002,3 +9003,112 @@ Passwortfeld mit passendem Platzhalter und die Knöpfe Speichern/Löschen. Einen
gesetzt → `gesetzt · …0000`, und **der Wert selbst taucht in den veröffentlichten Attributen
nirgends auf** (auf genau diese Zeichenkette geprüft, nicht nur angesehen). Danach über die
Sicherheitsabfrage „Token löschen?" entfernt → wieder `nicht gesetzt`, der Gitea-Token unberührt.
---
## BZ. Der Regler stellt den Schlaf-Timeout des Dongles (2026.9.3.10)
### Was der Regler jetzt bedeutet
„Fahrt beenden" in den Einstellungen ist **eine** Zahl für zwei Dinge, die
denselben Sachverhalt beschreiben (Vorgabe des Eigentümers):
* Schlaf-Timeout des FMM003 (`103`, Minuten). So lange bleibt der Dongle nach
dem Abstellen wach und wartet darauf, dass es gleich weitergeht. Danach
schläft er — das spart Strom, kostet beim Fortsetzen aber Sekunden fürs
Aufwachen.
* Unsere eigene Wartezeit, bevor eine Fahrt geschlossen wird.
Die 180 s `Ignition OFF Delay` (`400`) laufen davor. **Der Nutzer sieht sie
nicht** — sie werden nur von der Fahrtdauer abgezogen
(`fahrterkennung.ZUENDUNG_NACHLAUF_S`, unverändert).
Der Regler geht deshalb von **1 bis 60 in Einerschritten** statt 060 in
Fünferschritten: das Gerät kennt kein Timeout 0 (Minimum 1, Maximum 3000), und
„sofort" gibt es damit nicht mehr.
### Die gemessene API — drei Annahmen waren falsch
Alles im laufenden Container gegen den echten Account geprüft, nicht aus der
Dokumentation abgeschrieben:
| angenommen | tatsächlich |
|---|---|
| Wert unter `value` | Wert unter **`current`**, Ausstehendes unter **`pending`** |
| Einstellung `sleep_settings` mit `{mode, timeout}` | **`sleep_mode`**, Wert eine Ebene tiefer unter `mode` |
| PUT-Rumpf = der Wert | `{"properties": …, "address": …}` — ohne `address` kommt `400 the following properties are missing: address` |
`GET /gw/devices/{id}/settings/all` liefert die gefüllten Einträge; der Abruf
einer **einzelnen** Einstellung kam leer zurück (`current: null`). Gelesen wird
deshalb immer `all`.
Der `Ignition OFF Delay` (`400`) taucht unter keinem sicher zuzuordnenden Namen
auf und wird deshalb **nicht** angezeigt — lieber eine Zeile weniger als eine
falsch beschriftete. Verglichen werden `103` (gegen den Regler) und `11804`
(gegen `NACHLAUF_S`); dazu angezeigt: `102`, `11803`, `11806`.
### Die eigene Warteschlange ist wieder entfallen
Erst war ein Auftragsbuch im Koordinator gebaut, weil „Lesen und Schreiben gehen
nur bei aktiver Zündung — ausserhalb schläft der Dongle". **Das gilt für das
Gerät, nicht für diese Schnittstelle**, und das ist gemessen: die vollständige
Konfiguration kam herein, während das Fahrzeug seit dem Vortag stand.
flespi ist eine Ebene darüber. Es kennt `current` und `pending`, und
`"address": "connection"` heisst: zustellen, sobald sich das Gerät meldet. Ein
zweites Auftragsbuch bei uns wäre eine zweite Warteschlange für dieselbe
Aufgabe — und eine, die nur raten könnte, was die erste schon weiss.
Entfallen sind damit `flespi_auftrag`, `flespi_auftrag_setzen()`,
`wach_geworden()` und der Haken an beiden Zündungs-Beobachtern. Geblieben ist
`flespi_stand` (überlebt den Neustart) und `flespi_sperre`.
**Geschrieben wird jetzt sofort** — nach jedem Profil-Speichern und einmal nach
dem Start, über `wunsch_uebernehmen()`. Das ist bewusst zustandsvergleichend
statt ereignisgetrieben: es muss auch dann zum Ziel führen, wenn eine frühere
Änderung nie ankam. Der billige Vergleich gegen den gespeicherten Stand geht
voraus — stimmt er (auch über ein noch ausstehendes `pending`), kostet ein
Profil-Speichern **keine einzige Anfrage**. Live belegt: der zweite Neustart
schrieb keine Zeile mehr.
### Gegenlesen heisst hier zweierlei
Vorgabe des Eigentümers war: nach dem Schreiben lesen und belegen, dass sich
genau die eine Stelle geändert hat. Mit `pending` bekommt das eine zweite gültige
Ausprägung, und beide zählen als Erfolg:
* `current` trägt den neuen Wert → das Gerät war wach und hat ihn.
* `pending` trägt ihn → flespi hält ihn vor. **Der Normalfall bei stehendem
Fahrzeug.**
Steht er in keinem von beiden, ist der Vorgang nicht angekommen und das wird als
Fehler gemeldet. Ändert sich zusätzlich etwas ausserhalb von `sleep_mode`, gibt
es eine Warnung — kein Abbruch: geschrieben ist zu dem Zeitpunkt schon.
### Live nachgewiesen, und was nicht
Gegen den echten flespi-Account und den echten Dongle (Gerät 8767678):
* Token sieht **genau ein** Gerät → `geraet_finden()` löst die Nummer selbst
auf, in den Optionen muss nichts stehen.
* 127 Einstellungen gelesen, **bei parkendem Fahrzeug**.
* Regler 15 → PUT akzeptiert → `pending.mode.timeout = 15` bei flespi,
`current` blieb 10, und `type`/`bluetooth_on`/`periodic_wakeup` wurden
unverändert mitgeschrieben. Genau dafür wird das ganze Objekt
zurückgeschrieben statt nur des Feldes.
* Zweiter Neustart: keine erneute Anfrage (Idempotenz).
**Das Gerät hat dabei eine Änderung bekommen** — den Wert, den der Regler ohnehin
schon zeigte. Das ist die gewollte Selbstheilung, aber es ist eine Änderung am
Fahrzeug und steht deshalb hier.
**Nicht geprüft:** wie die neue Kachel aussieht. In dieser Sitzung gab es keinen
angemeldeten Browser; Panel und App sind über Modul-Parse, `tsc --noEmit` und
179/179 Tests belegt, nicht über einen Screenshot. Ebenfalls offen: ob das Gerät
das `pending` beim nächsten Verbinden wirklich übernimmt — das zeigt erst die
nächste Fahrt.
**Vorbestehende Lücke, nicht in diesem Zug geschlossen:** `translations/de.json`
kennt die zuletzt hinzugekommenen Dienste nicht (`fahrt_jetzt_beenden`,
`zugang_setzen`, `csv_importieren`, jetzt auch `dongle_lesen`). Sie erscheinen in
den Entwicklerwerkzeugen ohne Klarnamen.