TANK_DISTANZ_SENSOR + Datensatz sichern/laden mit echtem CSV-Import (Panel)

- Neuer optionaler Sensor TANK_DISTANZ_SENSOR ersetzt die eigene
  Kilometerstand-Subtraktion fuer die Tankvorgang-Strecke, wo zugeordnet
  (Live-Erkennung, manuelle Erfassung, historischer Import)
- "Fahrzeugprofil" und "Daten ausgeben" zu einer Kachel zusammengelegt:
  "Datensatz sichern" (4 Exporte wie bisher) / "Datensatz laden" (neu:
  echter CSV-Import fuer Fahrten/Tankvorgaenge/Wartungsplan)
- Import gleicht per ID ab (Fahrten/Tankvorgaenge) bzw. Datum+Art
  (Wartungsplan, hat keine eigene ID) und aktualisiert nur die in der CSV
  enthaltenen Spalten - alles andere am Datensatz bleibt unangetastet
- Nebenbei gefunden und behoben: belege.tankvorgang_aktualisieren()
  ueberschrieb bisher immer alle Felder, auch mit None, wenn irgendeins
  geaendert wurde - fuer den CSV-Import gefaehrlich, jetzt nur noch
  tatsaechlich uebergebene Felder
- Ebenfalls gefunden und behoben: Panel las das Import-Ergebnis per
  HASS.states direkt nach dem Dienstaufruf - ein Wettlauf mit dem
  state_changed-Push. Nutzt jetzt denselben HASS.callWS(get_states)-Weg
  wie der bestehende historie_importieren-Ablauf.

companion-app-Portierung von "Datensatz sichern/laden" steht noch aus.

Version 2026.8.28.3, live im Testcontainer verifiziert (alle drei
CSV-Datensatztypen: anlegen + aktualisieren per ID/Datum+Art getestet,
Testdaten danach geloescht).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
2026-08-28 10:19:06 +02:00
co-authored by Claude Sonnet 5
parent edefdd66d8
commit bfb7dec1e9
11 changed files with 521 additions and 76 deletions
@@ -143,6 +143,17 @@ async def tankvolumen_geaendert(k: Koordinator, neu: str | None) -> None:
await k.tiefststand_liter_setzen(aktuell)
async def distanz_seit_tankung(k: Koordinator, odometer_km: float | None) -> float | None:
"""Bevorzugt TANK_DISTANZ_SENSOR (vom Fahrzeug selbst berechnet), fällt
ohne ihn auf die eigene Kilometerstand-Subtraktion zurück - dieselbe
"Sensor bevorzugt, Berechnung als Rückfall"-Präferenz wie bei
TANK_LITER_SENSOR gegenüber TANK_SENSOR oben."""
sensor = _als_zahl(zustand_oder_none(k.hass, k.zuordnung.werte.TANK_DISTANZ_SENSOR))
if sensor is not None:
return sensor
return await k.ablage.distanz_seit_letzter_tankung(odometer_km)
async def _automatisch_anlegen(
k: Koordinator, anlass: str, liter_schaetzung: float | None = None
) -> None:
@@ -151,7 +162,7 @@ async def _automatisch_anlegen(
datetime.datetime.now(datetime.UTC).isoformat(), "auto"
)
tankvorgang["odometer_km"] = odometer_km
tankvorgang["distance_km"] = await k.ablage.distanz_seit_letzter_tankung(odometer_km)
tankvorgang["distance_km"] = await distanz_seit_tankung(k, odometer_km)
if liter_schaetzung is not None:
# Grobe Vorbelegung, keine feststehende Menge - der Status bleibt
# "unvollständig" (siehe leerer_tankvorgang), bis Preis/Tankstelle