Fahrtstrecke auf 100 m: CAN als Anker, GNSS als Nachkommastelle (2026.9.1.10)

Zwei echte Fahrten am 01.09.2026 haben die Datenform geliefert, auf die
2026.9.1.5 gewartet hat.

strecke_aus_zaehler() summiert die Zuwaechse des geraeteeigenen
Kilometerzaehlers und behandelt einen Ruecksprung als Ruecksetzung. Weder der
rohe Zaehler noch die Teilstrecken taugen allein: der Zaehler verliert bei
einer Ruecksetzung alles Vorherige (Fahrt 1: 0,415 km), die Teilstrecken
verlieren einzelne Datensaetze (Fahrt 2: 4 von 50 null, 0,2 km zu wenig). An
jedem Datensatz sind beide identisch - sie gehen nur verschieden kaputt.

_gnss_verfeinern() ersetzt die grobe Strecke nur, wenn die feine innerhalb der
Rundungsunschaerfe des Ankers liegt (GNSS_TOLERANZ_KM = 1.0; beide Enden des
CAN-Werts sind auf ganze Kilometer gerundet). Sonst behaelt der Fahrzeugwert
recht.

VERIFIZIERT gegen die echten Fahrten:
- Fahrt 1 (mit Ruecksetzung): 6,958 km, Google Maps sagt 7,1
- Fahrt 2 (sauber): 6,816 km
- live: 'Strecke auf 6.896 km verfeinert (Kilometerstand sagte 7.0 km)'
- drei aeltere Fahrten korrekt abgelehnt (209178 km gegen 21 km Anker)
- sechs Randfaelle: zwei Ruecksetzungen, ein Punkt, leer, unlesbare Werte

Nebenbei bestaetigt: NACHLAUF_S = 900 (Zuendung aus 16:33:39, Trip-Signal aus
16:48:44, gespeichertes Ende 16:33:36); der Rueckwaertssprung-Schutz griff live
beim Fahrzeugwechsel (-147361 km verworfen, Fahrt blieb offen); die
RPM-Zuendung prellt nicht; das Bewegungstor meldet wieder Stillstand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-01 17:31:33 +02:00
parent 0124254ea9
commit af83805c34
7 changed files with 186 additions and 4 deletions
+79 -1
View File
@@ -1,6 +1,7 @@
# AGENTS.md — Project state, review findings, open items, and working rules
**Last updated: 2026-09-01** (Nachlauf-Abzug nur mit zugeordnetem `TRIP_SENSOR`, `2026.9.1.9`;
**Last updated: 2026-09-01** (Fahrtstrecke auf 100 m: CAN als Anker, GNSS als Nachkommastelle,
`2026.9.1.10`, Abschnitt BE. Davor: Nachlauf-Abzug nur mit zugeordnetem `TRIP_SENSOR`, `2026.9.1.9`;
davor „502" beim Neustart entschärft, OTA-Bündel auf `2026.9.1.8`
nachgezogen, Abschnitt BC. Davor: „Geparkt seit" kommt von der Zündung und wird nach einem Neustart
aus der Aufzeichnung nachgeholt, Manifest `2026.9.1.7`,
@@ -6728,6 +6729,83 @@ Nachgewiesen: Manifest, `bundle.json` und die ausgelieferte Zip tragen alle `202
denselben SHA-256 `c2f9192e…`; `tsc --noEmit` sauber, 165/165 Tests grün, Panel als **Modul**
geparst (Abschnitt AQ), `audi_ha_test` fehlerfrei gestartet.
## BE. Die Fahrtstrecke auf 100 Meter: CAN als Anker, GNSS als Nachkommastelle (2026.9.1.10)
Zwei echte Fahrten am 01.09.2026 haben die Datenform geliefert, auf die Abschnitt BA gewartet hat.
Beide Male schließt die Rechnung, und beide Male auf eine andere Weise — deshalb war das Warten
richtig.
### Was gemessen wurde
| Quelle | Fahrt 1 (13:42, mit Rücksetzung) | Fahrt 2 (16:20, sauber) |
|---|---|---|
| **Zählerzuwächse mit Rücksprungbehandlung** | **6,958** | **6,816** |
| GPS-Spur | 7,01 | 6,74 |
| Geschwindigkeit integriert | 6,91 | 6,70 |
| Teilstrecken summiert | 6,928 | 6,614 |
| CAN-Kilometerstand (ganze km) | 7 | 6 |
| Google Maps | 7,1 | — |
### Der Zähler, nicht die Teilstrecken — und warum ich zweimal falsch lag
Erst hielt ich den **Gesamtzähler** für robuster (Abschnitt BA), nach Fahrt 1 die **Teilstrecken**,
nach Fahrt 2 wieder den Zähler. Die Auflösung: es sind keine zwei Messungen. An jedem einzelnen
Datensatz gilt `Teilstrecke == Differenz des Zählers`, auf drei Nachkommastellen genau. Sie
unterscheiden sich nur darin, **wie sie kaputtgehen**:
- Der **Zähler** verliert bei einer Rücksetzung alles Vorherige (Fahrt 1: 0,415 km).
- Die **Teilstrecken** verlieren einzelne Datensätze — in Fahrt 2 waren **4 von 50 null**, obwohl
gefahren wurde, Summe dadurch 0,2 km zu niedrig.
`strecke_aus_zaehler()` summiert deshalb die **Zuwächse** und behandelt einen Rücksprung als
Rücksetzung (der neue Wert ist dann selbst der Zuwachs). Damit fällt beides weg: unempfindlich
gegen Rücksetzungen, und keine verlorenen Datensätze. Ohne Rücksetzung degeneriert es zu Ende
minus Anfang.
Der Eigentümer hat dazu angemerkt, dass im Endzustand alle Fahrten wie Fahrt 2 verlaufen — er
steckt den Dongle nur in der Entwicklungsphase um. Die Rücksprungbehandlung ist damit kein
Kernstück mehr, sondern ein billiges Netz für Batteriewechsel und Werkstattbesuch.
### Woher die Rücksetzung mitten in der Fahrt kam
Um 13:43:20, bei 65 km/h und laufendem Motor, ging `total_calculated_mileage` von 0,415 auf 0. Im
**selben Datensatz** zählte `total_vehicle_mileage_read_from_can` zum ersten Mal hoch
(61809 → 61810), ebenso `distance_traveled_since_codes_cleared`. Kein Verbindungsabbruch, kein
Neustart, Bordspannung stabil bei 14,4 V — das Gerät übernahm offenbar seinen konfigurierten
Startwert (`11807 = 0`), als der CAN-Kilometerstand erstmals gültig wurde. Nicht bewiesen; ein
Prüfstein wäre, `11807` auf den echten Kilometerstand zu setzen und zu sehen, ob der Sprung dann
dorthin geht statt auf null.
### Die Verfeinerung ersetzt nicht, sie prüft
`_gnss_verfeinern()` setzt `distance_km` nur dann auf den feinen Wert, wenn er **innerhalb der
Rundungsunschärfe des Ankers** liegt (`GNSS_TOLERANZ_KM = 1.0` — beide Enden des CAN-Werts sind auf
ganze Kilometer gerundet). Sonst behält der Fahrzeugwert recht und es bleibt bei `"odometer"`.
Live nachgewiesen, beides im selben Lauf:
- Fahrt 2: `Strecke auf 6.896 km verfeinert (Kilometerstand sagte 7.0 km)`, `km_quelle` jetzt
`"odometer+gnss"`.
- Drei ältere Fahrten aus der Zeit vor der GNSS-Umstellung: `GNSS-Strecke 209178.0 km weicht um
mehr als 1.0 km vom Kilometerstand (21.0 km) ab - der Fahrzeugwert bleibt stehen`. Genau dafür
ist die Schranke da.
### Nebenbei bestätigt
- **`NACHLAUF_S = 900` stimmt.** Fahrt 2: Zündung aus 16:33:39, Trip-Signal aus 16:48:44 — 905 s
Abstand. Das gespeicherte Fahrtende steht auf **16:33:36**, also drei Sekunden neben der
tatsächlichen Zündung.
- **Der Rückwärtssprung-Schutz griff live** und genau wie vorhergesagt: Fahrt 1 lief über einen
Fahrzeugwechsel (209177 → 61816), `-147361 km` wurden verworfen, die Fahrt blieb „offen".
- **Die RPM-Zündung prellt nicht** — zwei echte Wechsel über beide Fahrten, kein Paar unter zwei
Sekunden. `Avg Const = 10` (1 s) bleibt.
- **Das Bewegungstor funktioniert** seit `138 = 10` (Beschleunigungssensor + CAN Speed statt GNSS):
`movement` meldet wieder Stillstand, vorher hing es tagelang auf „on".
Verifiziert: `strecke_aus_zaehler()` gegen beide echten Fahrten plus sechs Randfälle
(zwei Rücksetzungen, ein Punkt, leer, unlesbare Werte); `py_compile`, `tsc --noEmit` sauber,
Bündel und Manifest auf `2026.9.1.10` mit demselben SHA-256.
## Working conventions (observed — keep them)
- German is the project language: identifiers, comments, commits, UI texts. Exceptions: