Setup-Menue: Sensorkennung ohne installationsspezifisches Praefix, Einheit statt Live-Wert

Korrektur zur letzten Aenderung, vom Nutzer live erkannt:
- "fmm003_" war hart einprogrammiert und liess trotzdem noch
  installationsspezifisches Rauschen stehen (Geraete-Slug, Instanzname der
  Integration). Jetzt wird das laengste gemeinsame Praefix ueber alle
  aktuell zugeordneten Sensoren berechnet (setupGemeinsamesPraefix()) -
  nichts mehr hartkodiert. Faellt bei einer einzelnen Entitaet aus
  anderer Quelle korrekt auf die volle ID zurueck, statt falsch zu kuerzen
  (live bestaetigt: TANK_DISTANZ_SENSOR zeigte den vollen Namen, weil er
  auf eine andere Integration zeigte).
- Der Live-Wert des Sensors gehoert nicht mehr neben die ID - stattdessen
  zeigt das Label selbst jetzt die ERWARTETE Art des Werts an
  ("Tankfuellstand [%]", "12V-Batteriespannung [V]"), statisch aus dem
  FELDER-Katalog abgeleitet, unabhaengig von einer aktuellen Zuordnung.

Version 2026.8.28.5, live im Testcontainer verifiziert (acht echte
Setup-Zeilen gegen die Nutzerbeispiele geprueft).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-28 10:45:45 +02:00
parent b1cd03be51
commit af64fc39e3
4 changed files with 132 additions and 66 deletions
+52 -28
View File
@@ -4178,44 +4178,68 @@ this round). The underlying stored data was never wrong (the panel and backend a
is needed — an existing Wartungsplan entry will display correctly the next time companion-app is rebuilt and
deployed with this fix.
## AF. Item 11: Setup-Menü zeigt jetzt den zugeordneten Sensor statt einer statischen Beschreibung (2026.8.28.4)
## AF. Item 11: Setup-Menü zeigt jetzt den zugeordneten Sensor statt einer statischen Beschreibung (2026.8.28.4/.5)
Panel only - the Setup menu (sensor-role mapping) is an HA-panel-only concept, no companion-app equivalent
exists to port this to (companion-app consumes the backend's already-resolved state, it has no Setup UI at
all - see the parity rule's own carve-out for this exact case).
Every field row in Setup used to show a static, developer-written description under the label ("on = Fahrt
läuft, erkennt Fahrtbeginn/-ende.", "Optional, vom CAN..."). Owner: replace it with something read from the
*actual* currently-mapped sensor instead - its technical ID (just the part after `fmm003_`, e.g.
`testintegratoin_engine_ignition_or_acc_status` instead of the full
`binary_sensor.testcar_b9_fmm003_testintegratoin_engine_ignition_or_acc_status`) and its live output value
with unit (`[on/off]`, `[%]`, `[l]`, `[km]`...), positioned next to the headline rather than stacked below it.
läuft, erkennt Fahrtbeginn/-ende.", "Optional, vom CAN..."). Owner: replace it with the *actual*
currently-mapped sensor's technical ID (just the part after the installation-specific noise) shown next to
the headline, plus a separate indicator of the KIND of value each field expects.
New `entitaetIdKurz(entityId)` (strips the domain prefix, then finds `"fmm003_"` case-insensitively and
returns everything after it - falls back to the domain-free ID if `"fmm003_"` isn't present, for other
brands/integrations) and `entitaetWertKurz(entityId)` (current `state` + `unit_of_measurement`, `null` for
`unavailable`/`unknown`/unmapped - the exact same zustand logic `entitaetZeilenMarkup()` already used for
the search-result list, just for one entity instead of a whole candidate list). `setupErwarteterSensor()`
combines both into one string (`"<id-suffix> · <value> <unit>"`), used in `setupFeldzeile()`'s header in
place of the old `feld.hinweis` read. List-type fields (four positions, e.g. door/window sensors) show
nothing in the shared header - there's no single "the" sensor to reference there, each position has its own
mapping and its own combo below.
**First version (`.4`) got two things wrong, both caught live by the owner before being accepted:**
1. Hardcoded searching for the literal substring `"fmm003_"` and keeping everything after it - the owner
pointed out this still leaves *other* installation-specific noise in the result (`"testintegratoin_..."` -
the flespi channel's own instance name, not part of the sensor's real, stable identity; a different
installation would have a different instance name here, making a hardcoded strip target wrong for anyone
but this one test container).
2. Combined the ID-suffix with the sensor's *current live reading* into one string next to the headline. The
owner: show only the expected sensor identity there - and separately, "next to the Sensor Headline",
show the *kind* of value the field expects (`Tankfüllstand [%]`, `Tankvolumen [l]`, `12V-Batteriespannung
[V]`), not a live reading.
`feld.hinweis` itself is untouched in the backend `FELDER` catalog (`einstellungen.py`) - still valid data,
simply no longer read at this one call site; not removed, since removing it wasn't asked and nothing else
depends on knowing it's now unused.
**Fixed in `.5`:**
- `entitaetIdKurz(entityId)` no longer searches for a hardcoded string. New `setupGemeinsamesPraefix()`
computes the longest character-for-character common prefix (case-insensitive, trimmed back to the last
shared `_`) across every entity ID currently assigned across the *entire* Setup catalog (domain-stripped),
requiring at least two mapped entities to compare. In this real installation that correctly resolves to
`"testcar_b9_fmm003_testintegratoin_"` - device slug, integration name, and instance name all stripped in
one step, none of it hardcoded. `entitaetIdKurz()` strips that computed prefix only when a given entity's
ID actually starts with it; otherwise it shows the full domain-stripped ID rather than an incorrect partial
strip. **This fallback path fired for real, unprompted, during live verification**: `TANK_DISTANZ_SENSOR`
(added the same day, section AC) had been auto-suggested to `sensor.audi_rs_4_avant_monthly_mileage` - a
genuinely different source (not FMM003) sharing no prefix with the rest - and correctly rendered the full,
unstripped ID instead of a wrong truncation. Confirms the graceful-degradation design works, not just the
common case.
- The live-value read (`entitaetWertKurz()`/`setupErwarteterSensor()`) is gone entirely - removed, not just
unused. In its place, new `feldEinheitAnzeige(feld)` derives a **static** "kind of value" label straight
from the field's own `FELDER` catalog entry (`einstellungen.py`) - `"on/off"` for every `binary_sensor`
role (HA's binary_sensor domain always reports the raw state as on/off regardless of `device_class` - that
only changes how *other* HA frontends translate it for display, not the raw value this app reads), the
first unit in `units` preferring a lowercase-distinct variant when more than one is listed (picks `"l"`
over `"L"` for `TANK_LITER_SENSOR`, `"km"` over `"mi"` elsewhere), `"Datum"` for `date`/`timestamp`
`device_classes`, nothing for a `button` role or a field with neither (GPS coordinates). This label is
appended to the field's own headline text (`"Tankfüllstand [%]"`) and is independent of whether anything is
currently mapped - unlike the ID-suffix hint, which needs a live mapping to have anything to show.
CSS: `.setup-feld-kopf` was `flex-direction: column` (label above the old description) - changed to a row
(`justify-content: space-between`) so the new content sits beside the label as requested, with
`text-overflow: ellipsis` on the right-hand span since a long ID-suffix-plus-value string won't always fit.
`feld.hinweis` itself is untouched in the backend `FELDER` catalog - still valid data, simply not read by
this UI anymore; not removed, since nothing else depends on knowing it's unused and removing it wasn't asked.
Verified live in `audi_ha_test` (not just read from source - this file's own section S lesson): four real
rows read via the shadow DOM after opening Setup for real (`ZUENDUNG_SENSOR`
`"testintegratoin_engine_ignition_or_acc_status · off"`, `KM_SENSOR` → `"...mileage_read_from_can · 21302
km"`, etc.) - label and the new span measured on the identical Y-coordinate (`sameRow: true`), confirming
the row layout actually changed, not just the text content. Confirmed a list field (`TUER_SENSOREN`,
"Türen") renders with no header span at all, as designed. `node --check` clean, manifest bumped to
`2026.8.28.4`, `audi_ha_test` restarted and confirmed clean via log.
CSS: `.setup-feld-kopf` changed from a column (label above the old description) to a row (space-between) so
the ID-suffix hint sits beside the label; new `.setup-feld-einheit` (a slightly dimmer `--fg3`) for the
bracketed unit label appended to the headline text itself.
Verified live in `audi_ha_test` both times (not just read from source - this file's own section S lesson).
First pass (`.4`): confirmed the row layout change itself (label and hint measured on the identical
Y-coordinate) before the owner's correction arrived. Second pass (`.5`), after the fix, read eight real Setup
rows via the shadow DOM in one pass and matched every one against the owner's own examples exactly:
`"Zündung/ACC-Status [on/off]"` / `"testcar_b9_fmm003_testintegratoin_engine_ignition_or_acc_status"`,
`"Tankfüllstand [%]"`, `"Tankvolumen (Liter) [l]"`, `"12V-Batteriespannung [V]"`, `"Außentemperatur [°C]"` -
plus the `TANK_DISTANZ_SENSOR` fallback case above and a screenshot confirming the visual layout. `node
--check` clean at each step, manifest bumped `2026.8.28.4` → `.5`, `audi_ha_test` restarted and confirmed
clean via log both times.
---