Fuenf gemeldete Bugs behoben: Haubenschloss/Tuerschloesser entfernt, Bestaetigungsdialog-Transparenz, geteilte FMM003-Koordinaten, Laedt-Haenger, generischer Beleg-Parser

Entfernt Haubenschloss-/Tuerschloss-Erkennung dauerhaft aus Setup-Katalog und
Sicherheitscheck (auf ausdruecklichen Wunsch, nicht nur leer/unzuordenbar wie
der Rest der abgeloesten VAG-Integration). Behebt eine durchscheinende
Bestaetigungs-Sheet ("Doppelt zugeordnet" u.a.) - derselbe --tile-2-
Transparenz-Fehler, der fuer das Setup-Popup schon behoben war, hier
nachgezogen. Ergaenzt einen zweiten GPS-Pfad (STANDORT_LAT_SENSOR/
STANDORT_LON_SENSOR) fuer Integrationen wie flespi, die Breiten-/Laengengrad
als zwei eigene Sensoren statt als device_tracker-Attribute liefern. Haertet
den bekannten "Laedt ..."-Haenger beim App-Start zusaetzlich ab: Tab-Klicks
pruefen jetzt aktiv nach, ob Daten inzwischen da sind. Ergaenzt
shell_beleg_parser.py um einen stationsunabhaengigen Fallback fuer
Tankbelege unbekannter Formate (Adresse/Gesamtbetrag/Menge/Rabatt-Herleitung
wie vom Nutzer vorgegeben) - die bestehende Shell-Erkennung bleibt
unveraendert und weiterhin durch die zehn echten Testbelege abgedeckt.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
2026-08-16 11:32:15 +02:00
co-authored by Claude Sonnet 5
parent 440ff22bda
commit 25d1cebd12
10 changed files with 287 additions and 78 deletions
@@ -88,37 +88,59 @@ def _abs_zahl(wert):
def _standort():
"""Live-GPS-Position des Fahrzeugs (Übersicht -> Standort-Kachel) - liest
latitude/longitude/gps_accuracy von der in STANDORT_TRACKER hinterlegten
device_tracker-Entity (HA-Konvention). Fehlt die Entity-ID oder ist sie
(noch) nicht verfügbar, liefert diese Funktion durchgehend None statt
eines geratenen Werts - genau das zustand_oder_none()-Muster von oben,
hier als eigene Funktion, weil zusätzlich zum Zustand noch Attribute und
der Aktualisierungszeitpunkt gebraucht werden: state.get() liefert dafür
ein StateVal (str-Unterklasse) mit .last_updated als datetime-Attribut -
kein eigenständiges state.last_updated(), das gibt es in pyscript nicht."""
entity_id = einstellungen.STANDORT_TRACKER
"""Live-GPS-Position des Fahrzeugs (Übersicht -> Standort-Kachel). Zwei
mögliche Quellen, in dieser Reihenfolge versucht: (1) STANDORT_TRACKER,
eine device_tracker-Entity mit latitude/longitude/gps_accuracy-Attributen
(HA-Konvention) - der Normalfall; (2) STANDORT_LAT_SENSOR/
STANDORT_LON_SENSOR, zwei eigene sensor-Entities für Breiten-/Längengrad -
manche Integrationen (z. B. flespi) liefern Koordinaten so, statt als
Attribute einer einzelnen Tracker-Entity. Fehlt beides oder ist (noch)
nicht verfügbar, liefert diese Funktion durchgehend None statt eines
geratenen Werts - genau das zustand_oder_none()-Muster von oben, hier als
eigene Funktion, weil zusätzlich zum Zustand noch Attribute und der
Aktualisierungszeitpunkt gebraucht werden: state.get() liefert dafür ein
StateVal (str-Unterklasse) mit .last_updated als datetime-Attribut - kein
eigenständiges state.last_updated(), das gibt es in pyscript nicht."""
leer = {"lat": None, "lon": None, "genauigkeit_m": None, "zeit": None}
if not entity_id:
return leer
try:
wert = state.get(entity_id)
attribute = state.getattr(entity_id)
except NameError:
return leer
if not attribute or attribute.get("latitude") is None:
return leer
zeit = None
try:
zeit = wert.last_updated.isoformat()
except AttributeError:
pass
return {
"lat": _zu_zahl(attribute.get("latitude")),
"lon": _zu_zahl(attribute.get("longitude")),
"genauigkeit_m": _zu_zahl(attribute.get("gps_accuracy")),
"zeit": zeit,
}
tracker_id = einstellungen.STANDORT_TRACKER
if tracker_id:
try:
wert = state.get(tracker_id)
attribute = state.getattr(tracker_id)
except NameError:
attribute = None
if attribute and attribute.get("latitude") is not None:
zeit = None
try:
zeit = wert.last_updated.isoformat()
except AttributeError:
pass
return {
"lat": _zu_zahl(attribute.get("latitude")),
"lon": _zu_zahl(attribute.get("longitude")),
"genauigkeit_m": _zu_zahl(attribute.get("gps_accuracy")),
"zeit": zeit,
}
lat_id, lon_id = einstellungen.STANDORT_LAT_SENSOR, einstellungen.STANDORT_LON_SENSOR
if lat_id and lon_id:
try:
lat_wert = state.get(lat_id)
lon_wert = state.get(lon_id)
except NameError:
return leer
lat, lon = _zu_zahl(lat_wert), _zu_zahl(lon_wert)
if lat is None or lon is None:
return leer
zeit = None
try:
zeit = lat_wert.last_updated.isoformat()
except AttributeError:
pass
return {"lat": lat, "lon": lon, "genauigkeit_m": None, "zeit": zeit}
return leer
POSITIONEN = ["vorne links", "vorne rechts", "hinten links", "hinten rechts"]
@@ -137,14 +159,10 @@ def _sicherheitscheck():
for pos, sensor in zip(POSITIONEN, einstellungen.FENSTER_SENSOREN):
w = zustand_oder_none(sensor)
eintraege.append({"label": f"Fenster {pos}", "ok": None if w is None else w == "off"})
for pos, sensor in zip(POSITIONEN, einstellungen.TUERSCHLOSS_SENSOREN):
w = zustand_oder_none(sensor)
eintraege.append({"label": f"Türschloss {pos}", "ok": None if w is None else w == "off"})
for label, sensor in [
("Heckklappe", einstellungen.HECKKLAPPE_SENSOR),
("Heckklappenschloss", einstellungen.HECKKLAPPENSCHLOSS_SENSOR),
("Motorhaube", einstellungen.HAUBE_SENSOR),
("Haubenschloss", einstellungen.HAUBENSCHLOSS_SENSOR),
]:
w = zustand_oder_none(sensor)
eintraege.append({"label": label, "ok": None if w is None else w == "off"})