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
@@ -33,6 +33,7 @@ from . import (
bilder,
csv_import,
fahrterkennung,
flespi,
historienimport,
identitaet,
reifen,
@@ -53,6 +54,7 @@ from .const import (
D_ENTITAETEN_SCHREIBEN,
D_FAHRT_AKTUALISIEREN,
D_FAHRT_JETZT_BEENDEN,
D_DONGLE_LESEN,
D_ZUGANG_SETZEN,
D_FAHRT_LOESCHEN,
D_FAHRT_MANUELL_ANLEGEN,
@@ -136,6 +138,7 @@ SCHEMATA: dict[str, vol.Schema] = {
}),
D_FAHRT_LOESCHEN: vol.Schema({vol.Required("trip_id"): cv.string}),
D_FAHRT_JETZT_BEENDEN: vol.Schema({}),
D_DONGLE_LESEN: vol.Schema({}),
D_ZUGANG_SETZEN: vol.Schema({
vol.Required("dienst"): cv.string,
# Leerer Text loescht - ein eigener Loesch-Dienst waere ein zweiter Weg
@@ -238,6 +241,30 @@ def registrieren(hass: HomeAssistant, k: Koordinator) -> None:
await k.ablage.profil_schreiben(_objekt(aufruf.data["profil_json"]))
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
# die neue Reglerstellung mit.
await flespi.wunsch_uebernehmen(k)
async def dongle_lesen(_aufruf: ServiceCall) -> None:
"""Liest die Konfiguration des Dongles - auf ausdrücklichen Knopfdruck.
Nötig ist der Knopf nicht: flespi antwortet auch bei schlafendem Gerät
aus seinem eigenen Speicher (siehe flespi.py). Er ist dafür da,
nachzusehen, ob eine geschriebene Änderung inzwischen am Gerät
angekommen ist.
Ein Fehler wird als Anzeigestand hinterlegt statt geworfen: er gehört
in die Kachel, aus der der Knopf gedrückt wurde, nicht ins Protokoll."""
try:
await flespi.jetzt_lesen(k)
except flespi.FlespiFehler as fehler:
_LOGGER.warning("Geräte-Konfiguration nicht gelesen: %s", fehler)
await k.flespi_stand_setzen(
{"fehler": str(fehler), "gelesen_am": flespi.jetzt_iso()}
)
async def entitaeten_schreiben(aufruf: ServiceCall) -> None:
"""Speichert die im Setup-Menü gewählte Sensor-Zuordnung, wendet sie
@@ -362,6 +389,7 @@ def registrieren(hass: HomeAssistant, k: Koordinator) -> None:
D_ZUGANG_SETZEN: _als_dienst(
lambda a: zugaenge.setzen(k, a.data["dienst"], a.data.get("token", ""))
),
D_DONGLE_LESEN: dongle_lesen,
D_FAHRT_LOESCHEN: _als_dienst(
lambda a: fahrterkennung.loeschen(k, a.data["trip_id"])
),