Files
audi-app/homeassistant/pyscript/tankerkennung.py
T
tobias 9794193803 Setup-Menü für Sensor-Zuordnung + Umstellung von WLAN/VAG-Integration auf FMM003
Setup-Menü (Einstellungen -> Fahrzeug einrichten -> Setup): ordnet alle von
der App genutzten Sensor-Rollen echten HA-Entitäten zu, statt sie in
einstellungen.py von Hand einzutragen - durchsuchbares Dropdown je Feld,
Vorauswahl aus vorhandenen Entitäten, Schalter für "nur passende Sensoren".
Neues Modul entitaeten.py (Katalog + JSON-Override, zur Laufzeit über
setattr() auf einstellungen angewendet, kein Neustart nötig außer für die
drei trigger-gebundenen Felder).

Zusätzlich: Fahrzeug-WLAN-Erkennung und alle Entity-IDs der nicht mehr
genutzten TommiG1/HA_VAG-EU-Data-Act-Integration entfernt. Fahrterkennung
läuft jetzt über den Zündungs-/ACC-Status des neu angebundenen Teltonika
FMM003 (ersetzt die WLAN-Verbindungserkennung); Standort und 12V-
Batteriespannung kommen ebenfalls vom FMM003. Kilometerstand, Tankfüllstand,
Reichweite, Türen/Fenster/Schlösser sowie Ölwechsel-/Inspektionsdaten haben
dadurch vorerst keine Quelle mehr und zeigen "unbekannt" - die Funktionen
selbst bleiben erhalten und lassen sich über das neue Setup-Menü jederzeit
neu zuordnen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 15:55:59 +02:00

121 lines
4.5 KiB
Python

"""Automatische Tankerkennung über den Füllstandssensor (Erweiterung zu §7.7/§5.5,
nach dem ursprünglichen Bau nachträglich verlangt).
Beobachtung des Nutzers: der Füllstand (TANK_SENSOR, in Prozent) springt beim
Fahren nie nach oben, er sinkt nur - jeder Anstieg ist also ein Tankvorgang.
Schwelle nach Nutzervorgabe: ab +5 Liter ODER +9 Prozentpunkten Anstieg gilt
als nachgetankt. Die 5-Liter-Vorgabe wird über fahrzeug.tankvolumen_liter aus
dem Fahrzeugprofil in Prozentpunkte umgerechnet, damit beide Angaben auf
derselben Einheit (Prozent) verglichen werden können; es gilt jeweils die
empfindlichere (kleinere) der beiden Schwellen.
Tiefststand-Tracking statt einfachem Vorher/Nachher-Vergleich: die
Integration liefert einen Tankvorgang oft in mehreren kleinen Schritten
(z. B. 40% -> 45% -> 60%), von denen keiner allein die Schwelle
überschreiten muss. Deshalb wird der zuletzt bekannte Tiefststand
gespeichert und der Anstieg dagegen gemessen, nicht gegen den unmittelbar
vorherigen Wert. Nach Anlage eines Tankvorgangs wird der Tiefststand auf den
aktuellen Wert zurückgesetzt, damit derselbe Vorgang nicht mehrfach neue
Datensätze erzeugt, wenn der Sensor währenddessen weiter ansteigt.
Der so angelegte Tankvorgang ist bewusst ein unvollständiger Platzhalter
(status "unvollständig", ohne Liter/Kosten/Station) - siehe §10 Punkt 5 der
letzten Rückmeldung: die Erwartung ist ein automatisch erkannter Tankvorgang
mit Zeitstempel, Kilometerstand und gefahrener Distanz, den der Nutzer später
per Beleg-Nachtrag (audi_dashboard_beleg_hochladen mit tank_id, siehe
belegverarbeitung.py) vervollständigt.
EINSCHRÄNKUNG: der Tiefststand (_tiefststand_pct) lebt nur im Arbeitsspeicher
dieses Skripts, analog zur bekannten Einschränkung in fahrterkennung.py
(_fahrt_start_ts). Ein HA-Neustart während oder kurz vor einem Tankvorgang
verliert den bisherigen Tiefststand - der nächste Anstieg wird dann gegen den
ersten nach dem Neustart gemeldeten Wert gemessen. Bewusst nicht gehärtet,
aus demselben Grund wie dort.
Entity-IDs stehen zentral in pyscript/modules/einstellungen.py.
"""
import datetime
import einstellungen
import frontend_veroeffentlichung
import profil
LITER_SCHWELLE = 5
PROZENT_SCHWELLE = 9
STANDARD_TANKVOLUMEN_LITER = 58 # Fallback, falls im Profil nicht hinterlegt
_tiefststand_pct = None
def _als_zahl(wert):
try:
return float(wert)
except (TypeError, ValueError):
return None
def _schwelle_prozent():
p = profil.profil_lesen()
tankvolumen = p.get("fahrzeug", {}).get("tankvolumen_liter") or STANDARD_TANKVOLUMEN_LITER
liter_als_prozent = (LITER_SCHWELLE / tankvolumen) * 100
return min(liter_als_prozent, PROZENT_SCHWELLE)
@time_trigger("startup")
def beim_start():
profil.ordner_sicherstellen()
# Ohne konfigurierten Tankfüllstand-Sensor keinen Trigger registrieren -
# eine leere Entity-ID als @state_trigger-Ausdruck ist ungetestetes
# Verhalten, siehe gleiches Muster in fahrterkennung.py.
if einstellungen.TANK_SENSOR:
@state_trigger(f"{einstellungen.TANK_SENSOR}")
def tankfuellstand_geaendert(value=None, old_value=None):
global _tiefststand_pct
aktuell = _als_zahl(value)
if aktuell is None:
return
if _tiefststand_pct is None:
_tiefststand_pct = aktuell
return
if aktuell <= _tiefststand_pct:
_tiefststand_pct = aktuell
return
anstieg = aktuell - _tiefststand_pct
if anstieg >= _schwelle_prozent():
_tankvorgang_automatisch_anlegen(anstieg)
_tiefststand_pct = aktuell
def _tankvorgang_automatisch_anlegen(anstieg_pct):
odometer_km = frontend_veroeffentlichung.zustand_oder_none(einstellungen.KM_SENSOR)
tankvorgang = {
"tank_id": profil.neue_id("f"),
"receipt_key": None,
"ts": datetime.datetime.now(datetime.timezone.utc).isoformat(),
"liters": None,
"fuel_total_eur": None,
"price_per_l": None,
"discount": None,
"station_name": None,
"odometer_km": odometer_km,
"distance_km": profil.distanz_seit_letzter_tankung(odometer_km),
"fuel_type": None,
"source": "auto",
"status": "unvollständig",
"receipt_file": None,
"edited_fields": [],
}
profil.tankvorgang_anhaengen(tankvorgang)
frontend_veroeffentlichung.tankvorgaenge_veroeffentlichen()
log.info(
f"audi_dashboard: Tankvorgang {tankvorgang['tank_id']} automatisch erkannt "
f"(Füllstandsanstieg {round(anstieg_pct, 1)} Prozentpunkte)"
)