Review des aktuellen Stands und Plan fuer die native HA-Integration
Zwei Dokumente, beide reine Analyse - kein Code geaendert.
REVIEW_main_2026-08-13.md: 15 Befunde aus den Commits c66ed82..d5562c7,
nach Schaden sortiert, jeder mit Datei-Zeile und der Kette vom Ausloeser zur
Auswirkung. Die drei schwersten liegen im neuen Setup-Menue:
1. Speichern, solange der Katalog noch nicht geladen ist, ueberschreibt
entitaeten.json mit {} und loescht alle Zuordnungen. Faellt erst beim
naechsten Neustart auf, weil die setattr-Werte im Prozess bestehen
bleiben - und entitaeten.json wird von backup.py nicht gesichert.
2. "Zuruecksetzen" wirkt bei 15 von 17 Feldern nicht, weil
overrides_anwenden() leere Werte ueberspringt und der Standardwert bei
fast allen Feldern leer ist. Isoliert nachgestellt.
3. Alle vier Listenpositionen bekommen denselben Sensor, weil der
Vorschlag den Index nicht auswertet. Folge: der Sicherheitscheck prueft
viermal dieselbe Tuer und meldet "Sicher abgestellt", obwohl drei Tueren
nie geprueft wurden.
Jeder Befund ist als belegt oder plausibel gekennzeichnet.
ha_install.md: Plan fuer die Umstellung von pyscript auf eine eigene
Integration mit Konfigurationsdialog - Einrichtung komplett ueber die
Oberflaeche, kein YAML, Updates als Knopfdruck. Alle genannten
Schnittstellen sind an der laufenden 2026.8.1-Instanz geprueft, inklusive
Signaturen.
Zur Verteilung: HACS kann ausschliesslich GitHub und scheidet fuer das
Gitea-Repository aus. App-Repositories akzeptieren zwar beliebige Git-URLs,
Apps sind aber Docker-Container und damit der falsche Behaelter fuer eine
Integration. Nativ bleibt eine eigene UpdateEntity, deren Logik in
updateverwaltung.py bereits zu grossen Teilen existiert.
Festgehalten ist ausserdem, welche der Review-Befunde die Umstellung
konstruktionsbedingt aufloest - unter anderem alle drei oben genannten sowie
die Token-Datei im Klartext, weil eine Integration den Recorder direkt
abfragen kann statt sich selbst ueber HTTP.
This commit is contained in:
@@ -0,0 +1,391 @@
|
||||
# Review: Branch `main`, Commits `c66ed82..d5562c7`
|
||||
|
||||
**Datum:** 2026-08-13 · **Umfang:** 18 Commits, 24 Dateien, +2752/−259 Zeilen
|
||||
**Gegenstand:** Setup-Menü zur Sensor-Zuordnung, Umstellung von WLAN/VAG auf FMM003,
|
||||
Standort-Kachel mit Live-Position, iOS-/Großbildschirm-Optikauflage, DuckDNS und Zertifikate.
|
||||
|
||||
Geprüft wurde gegen eine Arbeitskopie von `origin/main`. Die mit **[belegt]** markierten Befunde
|
||||
sind am Code nachvollzogen oder nachgestellt; **[plausibel]** heißt: aus dem Code abgeleitet, aber
|
||||
nicht im Browser reproduziert.
|
||||
|
||||
---
|
||||
|
||||
## Gesamteindruck
|
||||
|
||||
Handwerklich stark. Das Setup-Menü ersetzt „vor der Installation `einstellungen.py` editieren"
|
||||
durch eine Oberfläche mit Live-Wertvorschau, Unavailable-Warnung, Duplikat-Prüfung und einem
|
||||
ehrlichen Neustart-Hinweis für die drei triggergebundenen Felder. Der Kniff dahinter — `setattr`
|
||||
auf dem laufenden Modul-Objekt, weil alle Leser `einstellungen.KM_SENSOR` als lebenden
|
||||
Attributzugriff machen — ist elegant und im Kopfkommentar sauber begründet.
|
||||
|
||||
Positiv außerdem: Escaping ist im neuen Code durchgängig (kein XSS gefunden), Karten-Ebenen werden
|
||||
vor dem Neuaufbau entfernt, die Haversine-Distanz ist mathematisch korrekt, Listenfelder sind gegen
|
||||
zu kurze Arrays abgesichert, und die Python-Syntax aller acht geänderten pyscript-Dateien ist in
|
||||
Ordnung.
|
||||
|
||||
Die Fehler unten liegen fast alle im selben Bereich — dem neuen Setup-Menü — und **drei davon
|
||||
werden erst nach einem Neustart sichtbar**, also mit maximalem zeitlichem Abstand zur Ursache.
|
||||
|
||||
## Übersicht
|
||||
|
||||
| # | Befund | Wirkung | Ort |
|
||||
|---|---|---|---|
|
||||
| 1 | Speichern bei fehlendem Katalog löscht alle Zuordnungen | Datenverlust | `audi-dashboard-app.js:1773, 2031` |
|
||||
| 2 | „Zurücksetzen" wirkt bei 15 von 17 Feldern nicht | falscher Zustand | `entitaeten.py:188` |
|
||||
| 3 | Alle vier Listenpositionen bekommen denselben Sensor | falsche Sicherheitsaussage | `audi-dashboard-app.js:1976` |
|
||||
| 4 | Vorschlagsschwelle akzeptiert beliebige Sensoren | falscher Fahrt-Trigger | `audi-dashboard-app.js:1980` |
|
||||
| 5 | Geleerte Listen setzen `["","","",""]` | Status dauerhaft „unbekannt" | `entitaeten.py:188` |
|
||||
| 6 | Zuordnung wird nirgends gesichert | Verlust bei Wiederherstellung | `backup.py:32` |
|
||||
| 7 | Kaputte `entitaeten.json` legt das Panel lahm | Totalausfall | `entitaeten.py:159` |
|
||||
| 8 | Standortabfrage im Dauerfeuer bei abgelehnter Freigabe | Akku, Netz | `audi-dashboard-app.js:553/557` |
|
||||
| 9 | Kein Tastaturweg in die Einstellungen unter 860 px | Bedienbarkeit | `audi-dashboard-app.js:3849` |
|
||||
| 10 | `.navmarke` nur in der iOS-Auflage versteckt | Tab-Leiste zerfällt | `audi-dashboard-ios.css:194` |
|
||||
|
||||
---
|
||||
|
||||
# Schwerwiegend
|
||||
|
||||
## 1. Speichern bei fehlendem Katalog löscht die gesamte Zuordnung [belegt]
|
||||
|
||||
**Kette:**
|
||||
|
||||
1. `ENTITAETEN` wird an genau einer Stelle gefüllt (`audi-dashboard-app.js:3723`), aus `hass.states`.
|
||||
2. Der Nachlade-Pfad nach einem HA-Neustart (`:3699-3703`) holt Profil, Fahrten, Tankvorgänge,
|
||||
Status und Batterieverlauf nach — **nicht** aber `pyscript.audi_dashboard_entitaeten`.
|
||||
3. `DATEN_GELADEN` hängt allein am Profil. Die App gilt also als geladen, während der Katalog fehlt.
|
||||
4. Der Knopf „Setup — Sensoren zuordnen" (`:1773`) ist nur an `einrichtenOffen` gekoppelt, nicht an
|
||||
den Katalog. `setupKatalog()` liefert `[]`, das Popup öffnet **ohne eine Zeile und ohne
|
||||
Fehlermeldung**, `setupZuordnung` bleibt `{}`.
|
||||
5. „Speichern" schickt `"{}"` (`:2031`). `overrides_schreiben()` ersetzt die Datei vollständig,
|
||||
ohne Zusammenführen (`entitaeten.py:166-173`).
|
||||
|
||||
**Auswirkung:** `data/entitaeten.json` enthält danach `{}`. Weil die `setattr`-Werte im laufenden
|
||||
Prozess bestehen bleiben, fällt der Verlust **erst beim nächsten Neustart** auf. Zusammen mit
|
||||
Befund 6 (keine Sicherung) gibt es dann nichts zurückzuholen.
|
||||
|
||||
**Vorschlag:** Setup-Knopf sperren, solange `ENTITAETEN` null ist, und in
|
||||
`setupSpeichernAusfuehren()` abbrechen, wenn `setupZuordnung` leer ist. Zusätzlich die Entität in
|
||||
den Nachlade-Pfad aufnehmen.
|
||||
|
||||
## 2. „Zurücksetzen" wirkt bei 15 von 17 Feldern nicht [belegt, nachgestellt]
|
||||
|
||||
`entitaeten.py:188` überspringt leere Werte:
|
||||
|
||||
```python
|
||||
if wert in (None, "", []):
|
||||
continue
|
||||
```
|
||||
|
||||
Der Kopfkommentar derselben Datei beschreibt das Problem exakt richtig — `setattr` verändert das
|
||||
Modul dauerhaft, „Zurücksetzen" muss den Standardwert *aktiv* zurückschreiben. Das Frontend tut das
|
||||
auch (`setupStandardwert`). Nur ist der Standardwert bei 15 der 17 Katalogfelder `""` oder `[]` —
|
||||
und genau die werden übersprungen.
|
||||
|
||||
Nachgestellt:
|
||||
|
||||
```
|
||||
nach Zuordnung: KM_SENSOR = 'sensor.alt_vag_mileage'
|
||||
nach Zurücksetzen: KM_SENSOR = 'sensor.alt_vag_mileage' ← erwartet: ''
|
||||
```
|
||||
|
||||
**Auswirkung:** Für den Nutzer sieht es aus, als hätte das Speichern versagt — `aktueller_stand()`
|
||||
liest aus dem laufenden Modul, das Feld zeigt beim nächsten Zeichnen wieder den alten Wert.
|
||||
Funktioniert nur bei `ZUENDUNG_SENSOR`, `BATTERIE_SENSOR` und `STANDORT_TRACKER`, den drei Feldern
|
||||
mit nicht-leerem Standard.
|
||||
|
||||
## 3. Alle vier Listenpositionen bekommen denselben Sensor [belegt]
|
||||
|
||||
`audi-dashboard-app.js:1976-1981`:
|
||||
|
||||
```js
|
||||
zuordnung[feld.key] = feld.positionen.map((_, i) => {
|
||||
const vorhanden = (werte[feld.key] || [])[i];
|
||||
if (vorhanden) return vorhanden;
|
||||
const vorschlag = entitaetKandidaten(feld.key, "", "")[0]; // i geht nicht ein
|
||||
return vorschlag && entitaetScore(feld, vorschlag, "") >= 3 ? vorschlag.id : "";
|
||||
});
|
||||
```
|
||||
|
||||
`entitaetKandidaten()` hängt nicht vom Index ab und schließt bereits vergebene IDs nicht aus —
|
||||
alle vier Positionen bekommen dieselbe Entität. Betrifft `TUER_SENSOREN`, `FENSTER_SENSOREN`,
|
||||
`TUERSCHLOSS_SENSOREN`.
|
||||
|
||||
**Auswirkung:** Bei einer Frischinstallation (genau der Fall, für den das Menü gebaut wurde) prüft
|
||||
`_sicherheitscheck()` danach viermal dieselbe Tür. **„Sicher abgestellt" meldet gesichert, obwohl
|
||||
drei Türen nie geprüft wurden.** Die Duplikat-Warnung fängt das beim Speichern ab, ist aber mit
|
||||
„Trotzdem speichern" wegklickbar.
|
||||
|
||||
## 4. Die Vorschlagsschwelle akzeptiert beliebige Sensoren [belegt]
|
||||
|
||||
`entitaetScore()` (`:1936`) vergibt: Stichwort +5, Domain +3, device_class +3, Einheit +2. Die
|
||||
Schwelle ist `>= 3` — **ein Domain-Treffer allein genügt**, ohne dass ein einziges Stichwort passt.
|
||||
Verschärfend: `setupNurPassend` wird zwei Zeilen vorher auf `true` gesetzt (`:1971`), wodurch
|
||||
`entitaetKandidaten()` ohnehin hart auf die Domain filtert. Die Schwelle ist damit *immer* erfüllt.
|
||||
Die Reihenfolge kommt aus `Object.keys(HASS.states)`, ist also faktisch willkürlich.
|
||||
|
||||
**Auswirkung:** Ohne passenden Zündungssensor wird `ZUENDUNG_SENSOR` stumm mit dem erstbesten
|
||||
`binary_sensor.*` vorbelegt — Bewegungsmelder, Fensterkontakt, was zuerst kommt. Das Feld sieht
|
||||
ausgefüllt aus, wird mitgespeichert, und **die gesamte Fahrterkennung hängt an einem
|
||||
Zufallssensor**. Bei Einzelfeldern greift keine Duplikat-Warnung. Dasselbe für `TANK_SENSOR` (jeder
|
||||
%-Sensor, etwa Luftfeuchte) und `REFRESH_BUTTON` (jedes `button.*`).
|
||||
|
||||
**Vorschlag:** Schwelle auf `>= 5` — also mindestens ein Stichworttreffer.
|
||||
|
||||
## 5. Geleerte Listenfelder setzen `["","","",""]` [belegt]
|
||||
|
||||
Die Skip-Regel aus Befund 2 prüft auf `[]`. Ein Array aus vier leeren Zeichenketten ist das nicht:
|
||||
|
||||
```python
|
||||
["","","",""] in (None, "", []) # False -> wird per setattr gesetzt
|
||||
```
|
||||
|
||||
`_sicherheitscheck()` zippt dann über vier leere Entity-IDs und erzeugt vier „unbekannt"-Zeilen —
|
||||
mal drei Listen sind das zwölf.
|
||||
|
||||
**Auswirkung:** Weil die Gesamtaussage bewusst `None` wird, sobald *eine* Prüfung unbekannt ist,
|
||||
steht die Übersicht danach **dauerhaft auf „Zustand unbekannt"** statt auf grün.
|
||||
|
||||
Kurios ist die Kombination mit Befund 2: Bei Einzelfeldern wirkt „Zurücksetzen" gar nicht, bei
|
||||
Listenfeldern zu stark. Beides verschwindet mit demselben Fix — statt leere Werte zu überspringen,
|
||||
immer den Standardwert aus `_STANDARDWERTE` zurückschreiben:
|
||||
|
||||
```python
|
||||
def overrides_anwenden():
|
||||
overrides = overrides_lesen()
|
||||
for key in _SCHLUESSEL:
|
||||
wert = overrides.get(key)
|
||||
leer = wert in (None, "", []) or (isinstance(wert, list) and not any(wert))
|
||||
setattr(einstellungen, key, _STANDARDWERTE[key] if leer else wert)
|
||||
```
|
||||
|
||||
## 6. Die Sensor-Zuordnung wird nirgends gesichert [belegt]
|
||||
|
||||
`backup.py:32` sichert `fahrzeugprofil.json`, `fahrten.jsonl`, `tankvorgaenge.jsonl` —
|
||||
`entitaeten.json` fehlt. Auch `audi_dashboard_backup_wiederherstellen` kennt es nicht, `update.ps1`
|
||||
fasst `data/` bewusst nicht an, und in `homeassistant/.gitignore` steht es nicht neben den anderen
|
||||
Laufzeitdateien.
|
||||
|
||||
**Auswirkung:** Nach einer Wiederherstellung ist die komplette Sensor-Zuordnung still weg. In
|
||||
Verbindung mit Befund 1 gibt es keinen Rückweg.
|
||||
|
||||
## 7. Eine beschädigte `entitaeten.json` legt das Panel lahm [belegt]
|
||||
|
||||
`overrides_lesen()` (`entitaeten.py:159`) ruft `json.loads` ohne Absicherung. Der Aufruf steht in
|
||||
`beim_start()` **vor** `alles_veroeffentlichen()` — wirft er, wird gar nichts veröffentlicht, das
|
||||
Panel bleibt komplett leer.
|
||||
|
||||
Geschrieben wird zwar atomar über `.tmp` + `os.replace`, das Risiko ist also gering — der Ausfall
|
||||
wäre aber total. Dieselbe Fehlerklasse, die im Branch `umsetzung-datametric360` bei `profil_lesen()`
|
||||
bereits abgefangen wurde.
|
||||
|
||||
---
|
||||
|
||||
# Mittel
|
||||
|
||||
## 8. Standortabfrage im Dauerfeuer, Karte bei jedem Render neu [belegt]
|
||||
|
||||
`USER_POS_TS` wird nur im Erfolgs-Callback gesetzt (`:553`), nicht im Fehlerfall (`:557`). Die
|
||||
30-Sekunden-Drossel in `standortErfassenFallsNoetig()` (`:560`) greift damit nie, wenn der Nutzer
|
||||
die Standortfreigabe ablehnt oder kein Fix zustande kommt.
|
||||
|
||||
Parallel dazu zerstört `render()` die Vorschaukarte und baut sie neu (`:2879-2880`), sobald die
|
||||
Route `home` ist — bei **jedem** Backend-Update.
|
||||
|
||||
**Auswirkung:** Mit einem GPS-Tracker als Quelle (genau der FMM003-Fall) sind das dutzende
|
||||
`getCurrentPosition({enableHighAccuracy:true})`-Anfragen pro Stunde plus sichtbares Kachelflackern.
|
||||
|
||||
**Vorschlag:** `USER_POS_TS = Date.now()` auch im Fehlerpfad; Karte nur bei echtem Ansichtswechsel
|
||||
neu bauen — die Variable `gleicheAnsicht` gibt es in `render()` bereits.
|
||||
|
||||
## 9. Kein Tastaturweg in die Einstellungen unter 860 px [belegt]
|
||||
|
||||
`audi-dashboard-ios.css:81` versteckt `.profilbtn` — den echten `<button aria-label="Einstellungen">` —
|
||||
und holt ihn erst in der Container-Abfrage ab 860 px zurück (`:230`). Der Ersatz ist ein
|
||||
Klick-Handler auf `#marke` (`:2965`), und das ist ein `<div class="rings" aria-label="Audi">`
|
||||
(`:3849`): ohne `role`, ohne `tabindex`.
|
||||
|
||||
**Auswirkung:** In Telefonbreite gibt es für Tastatur- und Screenreader-Nutzer **keinen** Zugang zu
|
||||
den Einstellungen. Ein `<div>` mit `aria-label` ohne Rolle wird von den meisten Screenreadern nicht
|
||||
einmal angesagt. Gleiche Fehlerklasse wie das Swipe-Löschen aus `AUDIT_2026-08-10.md`.
|
||||
|
||||
**Vorschlag:** `#marke` zu einem `<button aria-label="Einstellungen">` machen; dann kann auch
|
||||
`pointer-events:auto` in `audi-dashboard-ios.css:78` entfallen.
|
||||
|
||||
## 10. `.navmarke` nur in der iOS-Auflage versteckt [belegt]
|
||||
|
||||
`audi-dashboard-app.js:2956-2963` hängt den Ringklon **unbedingt** in `#tabbar`.
|
||||
`.navmarke{display:none}` steht ausschließlich in `audi-dashboard-ios.css:194`. `.tabbar` ist ein
|
||||
`display:grid` mit `repeat(5, 1fr)` (`audi-dashboard.css:211`).
|
||||
|
||||
**Auswirkung:** Lädt `/local/audi-dashboard-ios.css` nicht (404, Cache), wird der Klon ein sechstes
|
||||
Grid-Element — alle Tabs rutschen eine Spalte weiter, „Tanken" fällt in eine zweite Zeile, die
|
||||
Menüleiste zerfällt. Kein theoretischer Fall: Commit `3548f77` dokumentiert genau dieses
|
||||
Deployment-Loch.
|
||||
|
||||
**Vorschlag:** `.navmarke{display:none}` gehört in die Basis-CSS, die Sichtbarkeit in die Auflage.
|
||||
|
||||
## 11. Standort-Menü ohne `pointercancel` [belegt]
|
||||
|
||||
`standortMenuVerdrahten()` (`:706-731`) setzt `smY0` nur in `pointerup` zurück. Alle drei anderen
|
||||
Zeigergesten der Datei haben einen `pointercancel`-Handler (`:2929`, `:3055`, `:3122`), diese nicht.
|
||||
|
||||
**Auswirkung:** Übernimmt das System die Berührung (iOS-Randgeste, Multitouch, eingehender Anruf),
|
||||
bleibt `smY0` gesetzt. Der `pointermove`-Handler ruft dann `preventDefault()` für jede weitere
|
||||
Bewegung — **Scrollen ist in der ganzen App blockiert**, bis irgendwo ein `pointerup` kommt, der
|
||||
dann ein `dy` aus einem veralteten Startpunkt auswertet.
|
||||
|
||||
## 12. Fehlgeschlagenes Reverse-Geocoding wird dauerhaft gecacht [belegt]
|
||||
|
||||
`:572-586` setzt `STANDORT_ADRESSE_KEY` auch im `catch`-Zweig.
|
||||
|
||||
**Auswirkung:** Ein einziger fehlgeschlagener Nominatim-Abruf (Rate-Limit, kurzer Netzausfall) für
|
||||
eine Zelle führt dazu, dass für dieselbe Zelle die **gesamte Sitzung** lang nur Koordinaten
|
||||
angezeigt werden, auch wenn das Netz längst wieder da ist.
|
||||
|
||||
**Vorschlag:** Key nur im Erfolgsfall setzen.
|
||||
|
||||
## 13. Setup-Popup hält den `role="dialog"`-Vertrag nicht ein [belegt]
|
||||
|
||||
`:2774` deklariert `role="dialog" aria-modal="true"`. Es fehlen: Escape zum Schließen (in der Datei
|
||||
gibt es keinen `keydown`-Handler), eine Fokusfalle (Tab wandert in den überdeckten Hintergrund),
|
||||
und der Schalter „Nur passende Sensoren anzeigen" (`:2779`) hat keinen zugänglichen Namen — der
|
||||
Beschriftungstext steht im Geschwister-`<span>` außerhalb des `<label>`.
|
||||
|
||||
Dazu: Die Entitäts-Auswahl öffnet ausschließlich im `click`-Handler (`:3181`). Wer per Tab ins Feld
|
||||
springt und tippt, löst zwar den `input`-Handler aus, der bricht aber ab, weil `setupSucheOffen`
|
||||
noch `null` ist — sichtbar passiert nichts. `role="combobox"`, `aria-expanded` und `aria-controls`
|
||||
fehlen ebenfalls.
|
||||
|
||||
## 14. Standort-Menü nicht per Tastatur bedienbar [belegt]
|
||||
|
||||
Im eingeklappten Zustand steht das Blatt per `transform` überwiegend außerhalb des Sichtbereichs,
|
||||
bleibt aber vollständig im DOM und im Tab-Fokus — Adresse, Route-Link und Teilen-Knopf sind
|
||||
fokussierbar, ohne sichtbar zu sein (kein `inert`, kein `aria-hidden`). Öffnen geht gar nicht per
|
||||
Tastatur: `.standortmenu-griffzone` ist ein `<div>` mit reinen Pointer-Handlern. Der Umschalter
|
||||
Straße/Satellit (`:773`) hat kein `aria-pressed`, sein Label bleibt in beiden Zuständen gleich.
|
||||
|
||||
## 15. `disconnectedCallback()` räumt nur eine von drei Karten ab [belegt]
|
||||
|
||||
`:3815-3817` zerstört `MAP`, nicht aber `SMAP`/`TMAP`. Wird das Panel abgehängt, während Standort-
|
||||
oder Übersichtsseite offen ist, bleibt eine Leaflet-Instanz samt Resize-Listener und
|
||||
Kachel-Abrufen am Leben.
|
||||
|
||||
---
|
||||
|
||||
# Klein
|
||||
|
||||
| Ort | Befund |
|
||||
|---|---|
|
||||
| `audi-dashboard-ios.css:88, 208` | `main{padding:…}` (0,0,1) verliert gegen `main#view` (1,0,1) in `audi-dashboard.css:197`. Auf Großbildschirmen bleibt der Seitenrand bei 20 px statt der beabsichtigten 44 px. **Achtung:** `.standort-vollbild{margin:0 -20px}` (`audi-dashboard.css:704`) passt heute genau dazu — beides gehört zusammen angefasst. |
|
||||
| `audi-dashboard-app.js:3190/3612` | „Nur passende Sensoren anzeigen" wirkt nicht, solange ein Dropdown offen ist: Der Klick-Handler ersetzt das Overlay-DOM, bevor das `change`-Event des Kontrollkästchens ausgeliefert wird. [plausibel] |
|
||||
| `audi-dashboard-app.js:2966` | Theme-Umschalten ruft kein `render()` — die Leaflet-Kacheln bleiben bis zum nächsten Backend-Update im alten Stil. Durch die neue Dauerkarte auf der Übersicht deutlich sichtbarer als früher. |
|
||||
| `audi-dashboard-app.js:804` | `${de(CAR.tankPct)} %` zeigt ohne Tanksensor „0 %“, während direkt daneben korrekt „Reichweite unbekannt“ steht. |
|
||||
| `audi-dashboard-app.js:496, 518, 117` | Toter Code: `fahrzeugGlyphPfade()` nie aufgerufen, `zustand.parkplatz` nie gelesen, `standortGenauigkeitM`/`standortZeit` gemappt aber ungenutzt. Kommentare behaupten das Gegenteil. |
|
||||
| `audi-dashboard-app.js:595` | Einzige Interpolation im neuen Code, die ohne `esc()` in ein Attribut geht. Heute nicht ausnutzbar, weil `_zu_zahl()` im Backend nur Zahlen durchlässt — als Härtung trotzdem sinnvoll, ebenso `Number.isFinite` in `standortBekannt()`. |
|
||||
|
||||
---
|
||||
|
||||
# Dokumentation
|
||||
|
||||
## AGENTS.md widerspricht sich an sechs Stellen [belegt]
|
||||
|
||||
Die Datei ist auf 427 Zeilen gewachsen; neue Einträge wurden angehängt statt eingearbeitet.
|
||||
|
||||
| Stelle | Aussage | Widerspruch |
|
||||
|---|---|---|
|
||||
| Z. 94 | „trip detection via the iPhone WLAN sensor" | Z. 249 ff.: läuft über `ZUENDUNG_SENSOR`, WLAN „fully removed" |
|
||||
| Z. 110 | „Codec JSON → MQTT/TLS → Mosquitto" | Z. 227 ff.: Schwenk auf flespi, „not MQTT at all" |
|
||||
| Z. 93 | „4 modules" | tatsächlich 5 (`entitaeten.py` neu) |
|
||||
| Z. 97 | „3.130 lines" | tatsächlich 3.873 |
|
||||
| Z. 100 | „`einstellungen.py` — the one file edited before install" | genau das ersetzt jetzt das Setup-Menü |
|
||||
| Z. 320 | `STANDORT_TRACKER` „left empty" | steht auf `device_tracker.testzone_fmm003` |
|
||||
|
||||
Dazu veraltete Codeverweise: `fakeTrack()` liegt bei `:421` statt `:414`, die Statistik-Behauptung
|
||||
in `INSTALL.md` bei Z. 229 statt Z. 204.
|
||||
|
||||
Die Datei verlangt selbst „nicht festhalten, was Code und Git-History schon zeigen" (Z. 47) —
|
||||
Z. 282–401 sind 120 Zeilen Changelog-Prosa für fünf Einträge, und Z. 249–279 dupliziert inhaltlich
|
||||
Z. 133–153.
|
||||
|
||||
## INSTALL.md [belegt]
|
||||
|
||||
- **Zirkuläre Schrittfolge:** Schritt 4 verweist auf „siehe Schritt 9 zuerst" (Z. 96), Schritt 7
|
||||
setzt Schritt 4 voraus (Z. 176). Die Reihenfolge 4→9→7→4 wird nirgends aufgelöst.
|
||||
- **Ausgelieferte Default-Entities werden verschwiegen:** `ZUENDUNG_SENSOR`, `BATTERIE_SENSOR` und
|
||||
`STANDORT_TRACKER` sind mit den `testzone_fmm003`-Entities der Autoren-Instanz vorbelegt. Bei
|
||||
einer Frischinstallation zeigen sie ins Leere. Z. 108–110 behauptet nur für KM/TANK/RANGE
|
||||
„unbelegt".
|
||||
- **Override-Datei nicht benannt:** Z. 104 spricht von „einer Override-Datei" — der Pfad
|
||||
`/config/audi_dashboard/entitaeten.json` steht nirgends, und ihre fehlende Sicherung (Befund 6)
|
||||
ist nicht erwähnt.
|
||||
- Schritt 2 verweist auf `fahrzeugprofil.example.json`, deren Z. 2 weiterhin den „WLAN-Namen"
|
||||
verlangt, obwohl `fahrzeug.wlan_name` im selben Branch entfernt wurde.
|
||||
|
||||
## WLAN-Reste in der übrigen Doku [belegt]
|
||||
|
||||
Im Code ist die Entfernung vollständig (keine Fundstelle). In der Doku nicht:
|
||||
`SPECIFICATION.md` (Z. 16, 147, 181, 196, 217), `homeassistant/README.md:106` und die Profilvorlage
|
||||
nennen WLAN-Sensor und `TommiG1/HA_VAG-EU-Data-Act` weiterhin als aktuellen Stand.
|
||||
|
||||
## `update.ps1` [belegt]
|
||||
|
||||
Für `www/` ist das Skript nach dem Fix **vollständig** — `audi-dashboard-ios.css` und `badges/`
|
||||
sind ergänzt, Cache-Busting greift auch für die neue CSS-Datei.
|
||||
|
||||
**Verbleibende Lücke:** `homeassistant/data/shell_beleg_parser.py` ist Code, kein Datenbestand —
|
||||
`belegverarbeitung.py:41` lädt ihn aus `/config/audi_dashboard/`. `update.ps1` schließt `data/`
|
||||
pauschal aus, `INSTALL.md` behandelt ihn als Einmal-Kopie. **Änderungen am Beleg-Parser, dem
|
||||
einzigen getesteten Teil des Repos, kämen auf keiner Instanz an.**
|
||||
|
||||
## `design/` [belegt]
|
||||
|
||||
`dm360-host.html` lädt `audi-dashboard-app.js` (Z. 12) und `audi-dashboard-ios.css` (Z. 33) — beide
|
||||
existieren in `design/` nicht. Aus der Repo-Kopie ist das Board funktionslos; es läuft nur im
|
||||
Claude-Design-Projekt. Nirgends dokumentiert.
|
||||
|
||||
`design/README.md:19` führt `audi-dashboard-ios.css` in der Inhaltstabelle des Ordners (die Datei
|
||||
liegt in `homeassistant/www/`) und behauptet, die Auflage „rührt `audi-dashboard-app.js` nicht an" —
|
||||
Z. 57–59 derselben Datei beschreibt, dass genau dort der Stylesheet-Loader ergänzt wurde.
|
||||
|
||||
**Markenassets:** Der Diff fügt keine neuen Binärdateien hinzu. `DataMetric360 Board.dc.html`
|
||||
verwendet die vorhandenen Audi-Type-Dateien per `@font-face` — das Lizenzrisiko bleibt unverändert,
|
||||
nicht erhöht.
|
||||
|
||||
## `.gitignore` [belegt]
|
||||
|
||||
`installationspaket/` ist korrekt ergänzt und schließt nichts Getracktes aus. Es fehlt
|
||||
`data/entitaeten.json` neben den anderen drei Laufzeitdateien — heute harmlos, weil die Datei nur
|
||||
unter `/config/audi_dashboard/` entsteht, aber inkonsistent zum eigenen Grundsatz der Datei.
|
||||
|
||||
---
|
||||
|
||||
# Was den Branch `umsetzung-datametric360` betrifft
|
||||
|
||||
**Der flespi-Schwenk macht `homeassistant/FMM003_MAPPING.md` überholt.** Das Dokument beschreibt
|
||||
Codec JSON über MQTT/TLS mit eigener CA und einem `mosquitto_sub`-Mitschnitt. Mit flespi läuft es
|
||||
über den nativen Codec8/TCP-Kanal mit IMEI-Authentifizierung, ohne Zertifikate und ohne eingehenden
|
||||
Port; die Feldzuordnung entstünde aus der flespi-REST-API. Beim Zusammenführen anpassen oder
|
||||
ersetzen.
|
||||
|
||||
**Das CORS-Rätsel ist damit auch erklärt.** Die Notiz auf `main`, der `http:`-Block sei aus der
|
||||
`configuration.yaml` entfernt worden, „nachdem HA angefangen hat, ihn zu migrieren beziehungsweise
|
||||
zu ignorieren", erklärt, warum `cors_allowed_origins` in HA 2026.8 wirkungslos blieb — auch bei
|
||||
gleichem Ursprung. Gehört in `homeassistant/REVERSE_PROXY.md` nachgetragen.
|
||||
|
||||
**Die Falle beim Zusammenführen** steht bereits in `AGENTS.md` dieses Branches: `profil_lesen()`
|
||||
gibt hier bei fehlender Profildatei `None` zurück, `profil.py` ist auf `main` unverändert und geht
|
||||
konfliktfrei durch — die dortigen Aufrufstellen prüfen das aber nicht.
|
||||
|
||||
---
|
||||
|
||||
# Empfehlung
|
||||
|
||||
Reihenfolge nach Schaden:
|
||||
|
||||
1. **Befund 1** (Datenverlust) — zwei Riegel, wenige Zeilen.
|
||||
2. **Befunde 2 und 5** (Zurücksetzen) — ein gemeinsamer Fix in `overrides_anwenden()`.
|
||||
3. **Befunde 3 und 4** (falsche Vorbelegung) — Index in den Vorschlag einbeziehen, Schwelle auf 5.
|
||||
4. **Befund 6** (Sicherung) — eine Zeile in `backup.py`, plus Wiederherstellung.
|
||||
5. **Befund 7** (Absicherung beim Lesen), **8** (Akku), **9/10** (Bedienbarkeit, Robustheit).
|
||||
|
||||
Die Punkte 1 bis 4 betreffen alle das neue Setup-Menü und lassen sich in einem Zug erledigen.
|
||||
Reference in New Issue
Block a user