Fahrgestellnummer (FIN) automatisch aus den zugeordneten Sensoren ableiten
Neues identitaet.py: durchsucht das Geräte-Register der aktuell im Setup zugeordneten Sensoren (cupra_eu_data_act, FMM003, ...) nach einem VIN-förmigen Geräte-Identifier/Seriennummer, statt ein eigenes Setup-Feld zu verlangen. Mehrere übereinstimmende Quellen werden akzeptiert, abweichende nur geloggt statt geraten; eine bereits von Hand eingetragene FIN wird nie überschrieben. Läuft nach jedem Start und nach jeder Setup-Änderung (koordinator.py/dienste.py). Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
@@ -4394,6 +4394,56 @@ Verified live: `getBoundingClientRect()` on both real rendered `.v` blocks now r
|
||||
Verified: `node --check` clean at both steps, manifest bumped `2026.8.28.12` → `.13` → `.14`, `audi_ha_test`
|
||||
restarted and confirmed clean via log each time.
|
||||
|
||||
## AG. Fahrgestellnummer (FIN/VIN) automatisch aus den zugeordneten Sensoren abgeleitet (2026.8.28.15)
|
||||
|
||||
Owner: "It shall be available at the EU Data Act as well as FMM003. Read it from all sensors (check which
|
||||
sensors are used in setup) and compare the VIN if it is matching. If VIN is empty, than use just the one
|
||||
available." The FIN was, until now, a purely manual profile field (`fahrzeugprofil.json`'s `fahrzeug.fin`,
|
||||
edited via "Fahrzeug einrichten") - no sensor role for it existed at all.
|
||||
|
||||
Investigated the real data in `audi_ha_test` before designing anything, rather than assuming a dedicated VIN
|
||||
*entity* exists on either integration: neither `cupra_eu_data_act` nor the FMM003 device expose a `sensor.*`
|
||||
with "vin"/"fahrgestell"/"chassis" in its name or a matching state attribute (checked via a live
|
||||
`hass.callWS` scan of every entity on both devices). The VIN **is** present, though - on the
|
||||
`cupra_eu_data_act` device itself, in the HA **device registry**: `identifiers: [["cupra_eu_data_act",
|
||||
"WUAZZZF48PA902804"]]` and `serial_number: "WUAZZZF48PA902804"`, exactly matching this test profile's own
|
||||
manually-entered FIN. The FMM003 device in this specific test container does not carry a VIN-shaped
|
||||
identifier (its own identifier is just its configured integration name) - real hardware may differ depending
|
||||
on firmware/channel configuration (Teltonika Codec8 Extended has a dedicated VIN AVL parameter), which is
|
||||
exactly why the owner asked for "check both, don't assume one".
|
||||
|
||||
Built on that finding rather than adding a new Setup field: a new `identitaet.py` derives the FIN from the
|
||||
**device registry of whichever sensors are already mapped** in Setup, no separate FIN sensor role to pick.
|
||||
`_zugeordnete_entity_ids()` walks every field of the live `Sensorzuordnung` dataclass generically (via
|
||||
`dataclasses.fields()`, list-typed fields like `TUER_SENSOREN` included) to get every entity ID currently in
|
||||
use; for each, its owning device is resolved (entity registry → device registry) and checked for a
|
||||
VIN-shaped identifier/serial number (`_SIEHT_AUS_WIE_FIN`: 17 chars, A-Z minus I/O/Q plus digits - the real
|
||||
VIN standard's own exclusion of those three letters, chosen specifically so an unrelated device identifier
|
||||
like "FMM003 - Testintegratoin" can never false-match). Distinct candidates found across all mapped devices
|
||||
are collected into a set: zero → no-op (nothing found yet); exactly one → adopted automatically, but **only
|
||||
if the profile's own FIN is still empty** (a manually-entered value is never overwritten - matches this
|
||||
project's "human input always wins over automation" precedent, e.g. `_fahrt_screenen()`'s `edited_fields`
|
||||
protection); more than one distinct value → logged as a warning naming both, deliberately not guessed at
|
||||
(same "no suggestion beats a wrong one" stance as `entitaetIdKurz()`'s own fallback). Wired into two places
|
||||
so it re-attempts whenever it has a real chance of succeeding: once after every HA start (`koordinator.py`'s
|
||||
`_nach_start()`, alongside `fahrterkennung.nach_neustart_fortsetzen()` - deliberately not in `starten()`
|
||||
itself, for the same device/entity-registry-not-ready-yet reason `trigger_neu_binden()`'s own docstring
|
||||
already explains) and again after every Setup-menu save (`dienste.py`'s `entitaeten_schreiben` - a mapping
|
||||
change may be exactly what makes derivation newly possible). Both call sites re-publish the profile
|
||||
afterward so a freshly-derived FIN reaches the frontend immediately, not after the next 60s safety-net tick.
|
||||
|
||||
**Verified live, not just read from source** (this file's own section S lesson): backed up the test
|
||||
container's real `fahrzeugprofil.json`, blanked `fahrzeug.fin`, restarted - log showed
|
||||
`Fahrgestellnummer automatisch aus den zugeordneten Sensoren übernommen: WUAZZZF48PA902804`, the on-disk
|
||||
file and the published `sensor.audi_dashboard_profil` entity both confirmed via direct query, no stale
|
||||
frontend needed. Restored the original file byte-for-byte afterward and restarted once more to confirm a
|
||||
clean, silent (no re-derivation - the guard against overwriting an already-set FIN held) boot. `py_compile`
|
||||
clean on all three touched files (`identitaet.py` new, `koordinator.py`, `dienste.py`). No `services.yaml`
|
||||
change needed (no new service, just two existing handlers doing more internally) and no frontend change
|
||||
needed either - the "Fahrgestellnummer (FIN)" field in "Fahrzeug einrichten" already reads/writes this exact
|
||||
profile field, so it now simply arrives pre-filled instead of blank, and stays fully editable/correctable by
|
||||
hand same as before.
|
||||
|
||||
Verified live in `audi_ha_test` at every step (`.6` then `.7`), each time reading the actual rendered Setup
|
||||
popup fresh after a real restart (not a stale tab - confirmed via `performance.getEntriesByType('resource')`
|
||||
showing the new `?v=` served with a nonzero transfer size each time). Final state (`.7`), all 20 single-value
|
||||
|
||||
Reference in New Issue
Block a user