Ortsnamen aus dem Backend, Verbrauchsfaktor aus dem Tankbeleg, Radzaehler ueber Fahrten
Ortsauflösung serverseitig (geokodierung.py): der Ort steht jetzt in der Fahrt statt im Zwischenspeicher jedes Geräts. Beide Oberflächen fragen nichts mehr ab. Verbrauchskorrektur (verbrauchskorrektur.py): Faktor = Beleg-Liter / Summe der Einzelfahrten, voll zu voll. Statt einer Schranke am Faktor wird der Nenner geprüft - decken die erkannten Fahrten 90-110 % der Tacho-Spanne ab? Ausgelöst beim Schreiben eines Tankvorgangs, nicht erst bei der nächsten Fahrt. Radzähler: summiert die Fahrten des montierten Satzes statt Tacho-Deltas. Der alte Weg hatte Fahrzeugwechsel als gefahrene Strecke verbucht (375.962 km bei einem Tacho von 61.823). Null heißt unbekannt: ein Kilometerstand von 0 oder ein leeres Feld werden zu None normalisiert, statt an sechs Lesestellen als "Tachostand null" zu gelten. Momentanwerte der Sensoren gelten nur für einen Tankvorgang von jetzt. Oberfläche, beide Codebasen: Wertespalte der Fahrtenliste ausgerichtet, Ort -> Ort in "Zuletzt", "Räder" statt "Reifen", "Termin vereinbart" entfernt, Markenlogo 20 % größer, Übersicht-Symbol auf volle Rasterbreite. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -31,6 +31,7 @@ import datetime
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from . import reifen, verbrauchskorrektur
|
||||
from .verlauf import (
|
||||
UNPLAUSIBLE_KMH,
|
||||
durchschnitt_kmh,
|
||||
@@ -148,6 +149,24 @@ async def durchfuehren(k: Koordinator) -> None:
|
||||
for fahrt in ohne_position:
|
||||
await _position_screenen(k, lat_sensor, lon_sensor, fahrt)
|
||||
|
||||
# Erst NACH der Positionsermittlung: eine Fahrt, die gerade eben ihre
|
||||
# Koordinaten bekommen hat, soll im selben Durchlauf auch ihren Ort
|
||||
# bekommen und nicht erst beim naechsten.
|
||||
k.geokodierung.durchlauf_beginnen()
|
||||
ohne_ort = [
|
||||
f
|
||||
for f in fahrten
|
||||
if (f.get("start_lat") is not None and not f.get("start_stadt"))
|
||||
or (f.get("end_lat") is not None and not f.get("end_stadt"))
|
||||
]
|
||||
# Neueste zuerst: die sieht der Nutzer als naechstes. Ist das Budget
|
||||
# aufgebraucht, warten die alten auf den naechsten Durchlauf.
|
||||
ohne_ort.sort(key=lambda f: f.get("ts_start") or "", reverse=True)
|
||||
for fahrt in ohne_ort:
|
||||
if k.geokodierung.rest <= 0:
|
||||
break
|
||||
await _orte_screenen(k, fahrt)
|
||||
|
||||
# Durchschnitt braucht keinen Sensor - er folgt aus Strecke und Dauer,
|
||||
# die beide schon dastehen. Deshalb vor dem Geschwindigkeitssensor und
|
||||
# unabhaengig davon, ob einer zugeordnet ist.
|
||||
@@ -180,11 +199,19 @@ async def durchfuehren(k: Koordinator) -> None:
|
||||
if tank_liter_sensor:
|
||||
ohne_verbrauch = [
|
||||
f for f in fahrten
|
||||
if f.get("verbrauch_l_100km") is None and f.get("distance_km")
|
||||
if f.get("verbrauch_roh_l_100km") is None and f.get("distance_km")
|
||||
]
|
||||
for fahrt in ohne_verbrauch:
|
||||
await _verbrauch_screenen(k, tank_liter_sensor, fahrt)
|
||||
|
||||
# Zuletzt: die Eichung braucht die Rohwerte aller Fahrten eines
|
||||
# Betankungsintervalls und ist damit auf alle Schritte davor angewiesen.
|
||||
await verbrauchskorrektur.anwenden(k)
|
||||
|
||||
# Die Laufleistung der Raeder ist die Summe der Fahrten - sie muss also
|
||||
# nachziehen, sobald eine Strecke dazukommt oder sich aendert.
|
||||
await reifen.nachtragen(k)
|
||||
|
||||
await _lueckenlos_verketten(k)
|
||||
await k.fahrten_veroeffentlichen()
|
||||
|
||||
@@ -324,6 +351,44 @@ async def _position_screenen(
|
||||
fahrt.update(aenderungen)
|
||||
|
||||
|
||||
async def _orte_screenen(k: Koordinator, fahrt: dict) -> None:
|
||||
"""Traegt Start- und Zielort nach, sobald die Koordinaten dastehen.
|
||||
|
||||
Der Ort gehoert zu den Fahrtdaten, nicht in den Zwischenspeicher jedes
|
||||
einzelnen Geraets - Begruendung im Kopf von geokodierung.py.
|
||||
|
||||
start_address/end_address stehen in fahrterkennung.HANDFELDER: eine von
|
||||
Hand eingetragene Anschrift ("Zuhause") darf hier nie ueberschrieben
|
||||
werden. Zwei Sperren dagegen, absichtlich beide: hier wird nur ein
|
||||
LEERES Feld gefuellt, und fahrt_aktualisieren() laesst ohnehin jedes
|
||||
Feld in edited_fields unberuehrt.
|
||||
|
||||
Der Ortsname (start_stadt) wird auch dann gesetzt, wenn die Anschrift
|
||||
von Hand stammt - er beschreibt die Koordinate, nicht die Eingabe, und
|
||||
die Liste braucht ihn zum Ausrichten der Spalten."""
|
||||
enden = (
|
||||
("start", fahrt.get("start_lat"), fahrt.get("start_lon")),
|
||||
("end", fahrt.get("end_lat"), fahrt.get("end_lon")),
|
||||
)
|
||||
aenderungen: dict = {}
|
||||
for seite, lat, lon in enden:
|
||||
if lat is None or lon is None:
|
||||
continue
|
||||
if fahrt.get(f"{seite}_address") and fahrt.get(f"{seite}_stadt"):
|
||||
continue
|
||||
ort = await k.geokodierung.aufloesen(lat, lon)
|
||||
if ort is None:
|
||||
continue
|
||||
if not fahrt.get(f"{seite}_address") and ort.get("anschrift"):
|
||||
aenderungen[f"{seite}_address"] = ort["anschrift"]
|
||||
if not fahrt.get(f"{seite}_stadt") and ort.get("stadt"):
|
||||
aenderungen[f"{seite}_stadt"] = ort["stadt"]
|
||||
|
||||
if aenderungen:
|
||||
await k.ablage.fahrt_aktualisieren(fahrt["trip_id"], aenderungen)
|
||||
fahrt.update(aenderungen)
|
||||
|
||||
|
||||
async def _verbrauch_screenen(
|
||||
k: Koordinator, tank_liter_sensor: str, fahrt: dict
|
||||
) -> None:
|
||||
@@ -346,9 +411,19 @@ async def _verbrauch_screenen(
|
||||
verbrauch = verbrauch_aus_literstaenden(
|
||||
wert_ab(verlauf, start), wert_bei(verlauf, ende), fahrt.get("distance_km")
|
||||
)
|
||||
if verbrauch is not None:
|
||||
await k.ablage.fahrt_aktualisieren(fahrt["trip_id"], {"verbrauch_l_100km": verbrauch})
|
||||
fahrt["verbrauch_l_100km"] = verbrauch
|
||||
if verbrauch is None:
|
||||
return
|
||||
|
||||
# Der Rohwert wird immer geschrieben, der Anzeigewert nur, solange noch
|
||||
# kein Faktor vorliegt - sonst ueberschriebe das Screening eine bereits
|
||||
# an den Betankungen geeichte Zahl mit der ungeeichten.
|
||||
aenderungen = {"verbrauch_roh_l_100km": verbrauch}
|
||||
faktor = fahrt.get("verbrauch_faktor")
|
||||
aenderungen["verbrauch_l_100km"] = (
|
||||
round(verbrauch * float(faktor), 1) if faktor else verbrauch
|
||||
)
|
||||
await k.ablage.fahrt_aktualisieren(fahrt["trip_id"], aenderungen)
|
||||
fahrt.update(aenderungen)
|
||||
|
||||
|
||||
async def _vmax_screenen(k: Koordinator, tempo_sensor: str, fahrt: dict) -> None:
|
||||
|
||||
Reference in New Issue
Block a user