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 <[email protected]>
This commit is contained in:
2026-08-28 00:05:58 +02:00
co-authored by Claude Sonnet 5
parent 8ba3519090
commit 90fff7b305
12 changed files with 223 additions and 69 deletions
+6 -1
View File
@@ -93,7 +93,12 @@ export function Batterie({ geheZu }: { geheZu: (name: SeitenName) => void }) {
if (!verlauf) return <div className="dm-laden">Verlauf wird geladen </div>
const messwerte = verlauf.filter((t) => t.min != null)
// Wie bvPunkte im Panel: Werte über AGM_RUHE_MAX_V sind Generatorspannung,
// keine Ruhespannung - ausgeschlossen von Kopfzeile, Trend UND Diagramm
// (eine einzige gefilterte Liste, kein separater "alle Messungen"-Bestand).
// Ohne diesen Filter hätte ein Tag, an dem das Fahrzeug nie lange genug
// stand, seine Generatorspannung fälschlich als "Ruhespannung" gezeigt.
const messwerte = verlauf.filter((t) => t.min != null && t.min <= AGM_RUHE_MAX_V)
if (messwerte.length === 0) {
return (
+1 -1
View File
@@ -133,7 +133,7 @@ export function Statistik() {
/>
<ProgressBar
segments={[
{ value: a.arbeitKm, color: "var(--red)", label: `Arbeitsweg · ${de(a.arbeitKm)} km` },
{ value: a.arbeitKm, color: "var(--fg)", label: `Arbeitsweg · ${de(a.arbeitKm)} km` },
{ value: a.privatKm, color: "var(--fg3)", label: `Privat · ${de(a.privatKm)} km` },
]}
/>