"""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() if p is None: tankvolumen = STANDARD_TANKVOLUMEN_LITER else: 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)" )