Fahrten: Verbrauch-Näherung, 0V-Zustandsanzeige gefiltert, Plausibilitätsgrenze für die Live-Vervollständigung
Verbrauch (l/100km) war bislang totes Schema - kein Codepfad füllte verbrauch_l_100km je. Jetzt aus der Literstand-Differenz (TANK_LITER_SENSOR) über die Distanz genähert, live und beim Import, in beiden Frontends. Die "Zustand"-Kachel zeigte die Batteriespannung ungefiltert direkt vom Sensor, unabhängig von der Plausibilitätsgrenze der Verlaufsaufzeichnung - ein Sensorausreißer (0V) zeigte sich dort weiterhin, obwohl die Messwertliste ihn längst verwarf. Dieselbe Grenze gilt jetzt auch für diesen Anzeigepfad. Reale Fahrtendaten zeigten eine Fahrt mit 22km in 67s (~1180 km/h) - die Live-Vervollständigung (screening.py) hatte anders als der Import keine Plausibilitätsprüfung der Durchschnittsgeschwindigkeit. Jetzt gemeinsam in verlauf.py (UNPLAUSIBLE_KMH/durchschnitt_kmh) für beide Pfade. Dabei einen zweiten echten Bug gefunden: _fahrt_screenen() zog sein Ergebnis nie ins In-Memory-Objekt nach (nur in die Ablage) - eine im selben Durchlauf gerade erst ermittelte Distanz blieb für spätere Schritte (z. B. Verbrauch) bis zum nächsten Screening unsichtbar. Beide Stellen jetzt behoben. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -44,7 +44,16 @@ from typing import TYPE_CHECKING
|
||||
from .batterie import SPANNUNG_MIN_V
|
||||
from .fahrterkennung import leere_fahrt, pausenzeit_sekunden
|
||||
from .tankerkennung import LITER_SCHWELLE, leerer_tankvorgang, schwelle_prozent
|
||||
from .verlauf import Verlaufspunkt, route_aus_verlauf, verlauf_lesen, wert_bei, zahl
|
||||
from .verlauf import (
|
||||
UNPLAUSIBLE_KMH,
|
||||
Verlaufspunkt,
|
||||
durchschnitt_kmh,
|
||||
route_aus_verlauf,
|
||||
verbrauch_aus_literstaenden,
|
||||
verlauf_lesen,
|
||||
wert_bei,
|
||||
zahl,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .koordinator import Koordinator
|
||||
@@ -61,14 +70,11 @@ TANK_DUBLETTE_MIN = 90
|
||||
# fluten sie den Bestand aber mit Nulleinträgen. Bewusst konservativ.
|
||||
MINDESTDAUER_S = 60
|
||||
|
||||
# Kein Auto dieser Art erreicht diesen Schnitt. Eine errechnete
|
||||
# Durchschnittsgeschwindigkeit darüber ist kein Beleg für eine schnelle
|
||||
# Fahrt, sondern für einen fehlerhaften Kilometerstand-Sprung am Fahrtrand
|
||||
# (z. B. ein Ausreißer im Verlauf oder ein knapp daneben liegender
|
||||
# wert_bei()-Treffer über eine Lücke hinweg). Die Strecke wird dann verworfen
|
||||
# statt eine physikalisch unmögliche Fahrt anzuzeigen - die Fahrt bleibt
|
||||
# "offen", genau wie bei fehlendem Kilometerstand.
|
||||
UNPLAUSIBLE_KMH = 300
|
||||
# UNPLAUSIBLE_KMH selbst lebt in verlauf.py - gemeinsam mit screening.py, das
|
||||
# dieselbe Prüfung seit 2026.8.27 auch für die Live-Vervollständigung nutzt
|
||||
# (siehe dortiges _vollstaendig()). Die Strecke wird dann verworfen statt
|
||||
# eine physikalisch unmögliche Fahrt anzuzeigen - die Fahrt bleibt "offen",
|
||||
# genau wie bei fehlendem Kilometerstand.
|
||||
|
||||
|
||||
def als_zeit(wert: object) -> datetime.datetime | None:
|
||||
@@ -150,6 +156,7 @@ async def _fahrten_importieren(k: Koordinator, verlaeufe: dict) -> dict:
|
||||
km_verlauf = verlaeufe["km"]
|
||||
lat_verlauf = verlaeufe["lat"]
|
||||
lon_verlauf = verlaeufe["lon"]
|
||||
tank_liter_verlauf = verlaeufe["tank_liter"]
|
||||
|
||||
angelegt = uebersprungen = zu_kurz = 0
|
||||
neue: list[dict] = []
|
||||
@@ -169,19 +176,17 @@ async def _fahrten_importieren(k: Koordinator, verlaeufe: dict) -> dict:
|
||||
if odo_start is not None and odo_end is not None and odo_end >= odo_start:
|
||||
distanz = round(odo_end - odo_start, 1)
|
||||
|
||||
durchschnitt = None
|
||||
if distanz is not None and dauer_s > 0:
|
||||
durchschnitt = round(distanz / (dauer_s / 3600.0), 1)
|
||||
if durchschnitt > UNPLAUSIBLE_KMH:
|
||||
_LOGGER.warning(
|
||||
"Kilometerstand für Fahrt %s bis %s verworfen: unmögliche %s km/h "
|
||||
"im Schnitt (%s km in %s s) - vermutlich ein Ausreißer im Verlauf. "
|
||||
"Die Fahrt wird trotzdem angelegt, bleibt aber ohne Strecke.",
|
||||
f_start.isoformat(), f_ende.isoformat(), durchschnitt, distanz, dauer_s,
|
||||
)
|
||||
distanz = None
|
||||
odo_start = odo_end = None
|
||||
durchschnitt = None
|
||||
durchschnitt = durchschnitt_kmh(distanz, dauer_s)
|
||||
if durchschnitt is not None and durchschnitt > UNPLAUSIBLE_KMH:
|
||||
_LOGGER.warning(
|
||||
"Kilometerstand für Fahrt %s bis %s verworfen: unmögliche %s km/h "
|
||||
"im Schnitt (%s km in %s s) - vermutlich ein Ausreißer im Verlauf. "
|
||||
"Die Fahrt wird trotzdem angelegt, bleibt aber ohne Strecke.",
|
||||
f_start.isoformat(), f_ende.isoformat(), durchschnitt, distanz, dauer_s,
|
||||
)
|
||||
distanz = None
|
||||
odo_start = odo_end = None
|
||||
durchschnitt = None
|
||||
|
||||
fahrt = leere_fahrt(f_start, f_ende, "import")
|
||||
fahrt.update({
|
||||
@@ -195,6 +200,9 @@ async def _fahrten_importieren(k: Koordinator, verlaeufe: dict) -> dict:
|
||||
"end_lat": wert_bei(lat_verlauf, f_ende),
|
||||
"end_lon": wert_bei(lon_verlauf, f_ende),
|
||||
"route": route_aus_verlauf(lat_verlauf, lon_verlauf, f_start, f_ende),
|
||||
"verbrauch_l_100km": verbrauch_aus_literstaenden(
|
||||
wert_bei(tank_liter_verlauf, f_start), wert_bei(tank_liter_verlauf, f_ende), distanz
|
||||
),
|
||||
"status": "vollständig" if distanz is not None else "offen",
|
||||
})
|
||||
neue.append(fahrt)
|
||||
|
||||
Reference in New Issue
Block a user