Fahrtzeiten vom Geraet, Trip und Zuendung getrennt (2026.9.1.3)

Enthaelt 2026.9.1.2, das nie einzeln ausgeliefert wurde.

FAHRT- UND TANKZEITEN KOMMEN VOM GERAET

Fahrtbeginn war datetime.now() - die Uhrzeit, zu der Home Assistant den
Wechsel verarbeitet. Hat das Geraet gepuffert (Funkloch, Tiefgarage,
Tiefschlaf), liegt die Wahrheit beliebig weit davor. Gemessen: ein Datensatz
mit Fahrtende trug die Geraetezeit 07:29:04 und kam um 07:35:23 an.

Neue Sensorrolle MELDEZEIT_SENSOR (message_timestamp, Unix-Sekunden). Der
Wert ist UTC, keine Ortszeit - nachgemessen lag der Versatz zur UTC-Uhr von
HA bei Sekunden, nicht bei zwei Stunden; eine Zeitzonenumrechnung baute einen
Zwei-Stunden-Fehler ein.

geraetezeit() liegt in verlauf.py, weil Fahrt- und Tankerkennung denselben
Zeitstempel bestimmen muessen. tankerkennung._automatisch_anlegen() stempelte
bisher ebenfalls mit now(); ein aus einem gepufferten Datensatz erkannter
Tankvorgang trug damit die Uhrzeit des Auftauchens.

Die flespi-Integration setzt die Entitaeten eines Datensatzes nacheinander -
gemessen Zuendung 07:35:23.633, zugehoerige Meldezeit 2 ms spaeter. Wer
sofort liest, bekommt den vorigen Datensatz: beim Fahren zehn Sekunden
daneben, im Stand Stunden (On Stop Min Period = 43200 s). geraetezeit()
wartet deshalb bis zu 2 s auf den passenden Wert. Zwei Notbremsen, beide live
ausgeloest: Zeitstempel in der Zukunft und Ende vor dem Beginn.

TRIP UND ZUENDUNG SIND ZWEI ROLLEN

ZUENDUNG_SENSOR zeigte auf das Trip-Signal; im Setup stand "Zuendung/ACC" ueber
einer Trip-Entitaet und die echte Zuendung war nirgends zugeordnet. Neu:
TRIP_SENSOR loest Fahrten aus, ZUENDUNG_SENSOR liefert nur noch die Anzeige
"faehrt/steht". verlauf.fahrtsignal() ist die eine Stelle, die entscheidet -
Trip-Status wenn zugeordnet, sonst Zuendung, damit bestehende Installationen
unveraendert weiterlaufen und Livepfad und Rueckblick nicht auseinanderlaufen.

VERIFIZIERT in audi_ha_test, jeder Weg einzeln:
- Fahrtbeginn 08:30:03 (Geraetezeit) statt 08:38:27 (Ankunft)
- Fahrtende 08:04:40 -> 08:09:22 statt 08:11:04 -> 08:11:24
- Tankvorgang 08:18:45 statt 08:38:51 - 20 Minuten frueher
- Meldezeit in der Zukunft und Ende vor Beginn: Warnung, Ankunft genommen
- Zuendung schalten legt keine Fahrt mehr an, Trip-Signal schon

Der Livetest fing dabei einen NameError, den py_compile nicht sehen konnte:
der Import von geraetezeit in tankerkennung.py fehlte. Kompiliert ist nicht
verifiziert. Alle Testdatensaetze wurden ueber die eigenen Dienste wieder
entfernt; Bestand unveraendert 11 Fahrten, 13 Tankvorgaenge, keine offene Fahrt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-01 10:40:21 +02:00
parent ff5a334e95
commit 4cc91c461b
8 changed files with 363 additions and 24 deletions
@@ -47,7 +47,16 @@ from homeassistant.helpers.event import (
from homeassistant.helpers.start import async_at_started
from homeassistant.helpers.storage import Store
from . import batterie, fahrterkennung, identitaet, reifen, screening, sicherung, tankerkennung
from . import (
batterie,
fahrterkennung,
identitaet,
reifen,
screening,
sicherung,
tankerkennung,
verlauf,
)
from .ablage import Ablage
from .const import (
BUENDEL_INFO,
@@ -207,7 +216,13 @@ class Koordinator:
self._beobachter.clear()
werte = self.zuordnung.werte
self._beobachten(werte.ZUENDUNG_SENSOR, self._zuendung_geaendert)
# Fahrten löst der Trip-Status aus (oder die Zündung, wenn er fehlt).
self._beobachten(verlauf.fahrtsignal(werte), self._fahrtsignal_geaendert)
# Die Zündung selbst nur noch für die Anzeige "fährt/steht" - sofort
# neu veröffentlichen, statt bis zum nächsten 20-Sekunden-Takt zu
# warten. Entfällt, wenn sie ohnehin schon das Fahrtsignal ist.
if werte.ZUENDUNG_SENSOR != verlauf.fahrtsignal(werte):
self._beobachten(werte.ZUENDUNG_SENSOR, self._zuendung_angezeigt)
self._beobachten(werte.KM_SENSOR, self._kilometerstand_geaendert)
self._beobachten(werte.TANK_SENSOR, self._tankfuellstand_geaendert)
self._beobachten(werte.TANK_LITER_SENSOR, self._tankvolumen_geaendert)
@@ -227,9 +242,18 @@ class Koordinator:
neu = ereignis.data["new_state"]
return (neu.state if neu else None, alt.state if alt else None)
async def _zuendung_geaendert(self, ereignis: Event[EventStateChangedData]) -> None:
async def _zuendung_angezeigt(self, _ereignis: Event[EventStateChangedData]) -> None:
await self.fahrzeugstatus_veroeffentlichen()
async def _fahrtsignal_geaendert(self, ereignis: Event[EventStateChangedData]) -> None:
neu, alt = self._zustaende(ereignis)
await fahrterkennung.zuendung_geaendert(self, neu, alt)
# Der Zeitpunkt, zu dem Home Assistant diesen Wechsel gesehen hat -
# nicht "jetzt". Die Fahrterkennung braucht ihn, um die Meldezeit des
# Geräts demselben Datensatz zuzuordnen (siehe _geraetezeit dort).
zustand = ereignis.data["new_state"]
await fahrterkennung.zuendung_geaendert(
self, neu, alt, zustand.last_updated if zustand else None
)
async def _kilometerstand_geaendert(self, ereignis: Event[EventStateChangedData]) -> None:
neu, alt = self._zustaende(ereignis)
@@ -240,11 +264,17 @@ class Koordinator:
async def _tankfuellstand_geaendert(self, ereignis: Event[EventStateChangedData]) -> None:
neu, _alt = self._zustaende(ereignis)
await tankerkennung.fuellstand_geaendert(self, neu)
zustand = ereignis.data["new_state"]
await tankerkennung.fuellstand_geaendert(
self, neu, zustand.last_updated if zustand else None
)
async def _tankvolumen_geaendert(self, ereignis: Event[EventStateChangedData]) -> None:
neu, _alt = self._zustaende(ereignis)
await tankerkennung.tankvolumen_geaendert(self, neu)
zustand = ereignis.data["new_state"]
await tankerkennung.tankvolumen_geaendert(
self, neu, zustand.last_updated if zustand else None
)
# ------------------------------------------------- Laufende Fahrt merken