Vollaudit: sechs echte Fehler in Backend, Panel und companion-app behoben
- companion-app Batterie.tsx: Generatorspannung zeigte sich faelschlich als Ruhespannung/verzerrte den SOH-Trend, Panel-Filter (AGM_RUHE_MAX_V) fehlte - Manuell angelegte Fahrten/Tankvorgaenge trugen naive Zeitstempel und wurden von der Import-Dublettenpruefung stillschweigend uebersprungen; neue gemeinsame zeit_normalisiert() in verlauf.py schliesst die Luecke - Batteriespannungsverlauf fehlte im Backup (sicherung.py) - Tankvorgangs-Import verlor stillschweigend aeltere Tankvorgaenge vor Beginn der Litersensor-Historie; laeuft jetzt zweigleisig (Prozent + Liter) - Panel-Statistikseite behauptete faelschlich, der Verbrauch je Fahrt komme vom Fahrzeug (OBD) - ist eine Naeherung aus dem Tankfuellstand - companion-app Statistik.tsx: Arbeitsweg-Segment war noch rot statt neutral Version 2026.8.27.19, OTA-Buendel neu gebaut, im Testcontainer verifiziert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -78,6 +78,29 @@ async def verlauf_lesen(
|
||||
return []
|
||||
|
||||
|
||||
def zeit_normalisiert(wert: object) -> datetime.datetime | None:
|
||||
"""Akzeptiert ISO-Zeit mit oder ohne Zeitzone und normalisiert auf UTC.
|
||||
|
||||
Ohne Zeitzone gilt die lokale Zeit von Home Assistant - die Oberfläche
|
||||
schickt sowohl bei manueller Eingabe (Fahrt/Tankvorgang von Hand anlegen
|
||||
oder bearbeiten, fahrterkennung.py/belege.py) als auch beim rückwirkenden
|
||||
Import (historienimport.py) Ortszeit, nie UTC. Ohne diese Normalisierung
|
||||
bliebe ein von Hand erfasster Zeitstempel naiv (kein tzinfo) - und
|
||||
historienimport.py's eigene Dublettenprüfung (_ueberschneidet() für
|
||||
Fahrten, bekannte_zeiten für Tankvorgänge) überspringt jeden Datensatz mit
|
||||
naivem Zeitstempel stillschweigend, statt ihn auf Überschneidung zu
|
||||
prüfen. Ein von Hand angelegter oder bearbeiteter Datensatz wäre dadurch
|
||||
nie vor einem doppelten Import geschützt - genau die Lücke, die diese
|
||||
gemeinsame Funktion schließt, indem jeder Schreibpfad dieselbe
|
||||
Normalisierung durchläuft."""
|
||||
if not wert:
|
||||
return None
|
||||
ts = datetime.datetime.fromisoformat(str(wert))
|
||||
if ts.tzinfo is None:
|
||||
ts = ts.astimezone()
|
||||
return ts.astimezone(datetime.UTC)
|
||||
|
||||
|
||||
def zahl(wert: object) -> float | None:
|
||||
try:
|
||||
return float(wert) # type: ignore[arg-type]
|
||||
|
||||
Reference in New Issue
Block a user