fix(station): Signiervariante aus Produkt-ID und Version bestimmen
Eine Entwicklungs-G95 meldete sich am 2026-09-15 mit einer Produkt-ID OHNE
"-dev", aber einer Version MIT "-dev". products.py leitete die Variante
ausschliesslich aus der Produkt-ID ab, die Lampe galt als Produktionsgeraet,
bekam das produktionssigniertes Image und lehnte es ab - ihr Bootloader prueft
gegen den Entwicklungsschluessel.
Die Variante ist damit keine Eigenschaft der Produkt-ID, sondern der Anfrage.
PRODUCTS bildet nur noch auf Geraetetyp und Anzeigename ab; beide Schreibweisen
der Produkt-ID fuehren auf denselben Eintrag. classify_variant() in
parse_request() wertet Produkt-ID UND Version aus: "-dev" an einer der beiden
Stellen bedeutet Entwicklungsgeraet, in der Version nur als ganzes Wort
("-devel"/"-dev2" zaehlen nicht).
Damit eine Fehlklassifikation nicht wieder erst an der Lampe auffaellt, fuehren
status.json (last_seen und jeder recent-Eintrag) und das Panel die Quelle der
Einstufung mit: "g95_cw (dev/Ver)", "dev/ID", "dev/ID+Ver" oder "prod".
Tests: die drei am Geraet mitgeschnittenen Anfragen plus die vierte denkbare
Kombination, die Wortgrenze in der Version, zwei Ende-zu-Ende-Tests im Server
(dev-Image statt prod-Image) und die Panel-Beschriftung.
This commit is contained in:
@@ -167,6 +167,25 @@ PHASE_LABELS = {"auto": "AUTO", "listen": "LISTEN"}
|
||||
ARMED_LABEL = "FREIGEGEBEN"
|
||||
ARMED_DETAIL_PREFIX = "Freigabe: "
|
||||
|
||||
# Woraus die Station die Signiervariante abgeleitet hat (products.classify_variant):
|
||||
# "-dev" kann in der Produkt-ID stehen, in der Version, oder in beiden. Die Quelle steht
|
||||
# mit auf dem Panel, weil genau hier am 2026-09-15 ein falsch signiertes Image
|
||||
# ausgeliefert wurde: wer vor der Freigabe sieht, dass "dev" nur aus der Version kommt
|
||||
# (oder dass "prod" bedeutet: nirgends ein "-dev"), kann eine Fehlklassifikation abfangen,
|
||||
# bevor die Lampe das Image ablehnt. Kurzformen, weil die Beiwerkzeile schmal ist.
|
||||
VARIANT_SOURCE_LABELS = {"both": "ID+Ver", "product_id": "ID", "version": "Ver"}
|
||||
|
||||
|
||||
def _variant_label(last_seen: dict) -> str:
|
||||
""""dev/Ver", "dev/ID", "dev/ID+Ver", "prod" - die Quelle nur, wo sie etwas aussagt.
|
||||
Bei "prod" gibt es keine ("none"), und eine aeltere Serverfassung ohne das Feld
|
||||
liefert wie bisher nur die Variante."""
|
||||
variant = str(last_seen.get("variant") or "?")
|
||||
label = VARIANT_SOURCE_LABELS.get(last_seen.get("variant_source"))
|
||||
if not label:
|
||||
return variant
|
||||
return variant + "/" + label
|
||||
|
||||
|
||||
def _hhmm(ts: object) -> str:
|
||||
""""2026-09-13T13:04:02Z" -> "13:04". Alles andere (fehlt, falsch geformt, aus einer
|
||||
@@ -275,7 +294,8 @@ def blocks(state: dict) -> list[tuple[str, str]]:
|
||||
target = last_seen.get("target")
|
||||
variant = last_seen.get("variant")
|
||||
if target or variant:
|
||||
out.append((f"{target or '?'} ({variant or '?'})", ROLE_DETAIL))
|
||||
out.append(("{} ({})".format(target or "?", _variant_label(last_seen)),
|
||||
ROLE_DETAIL))
|
||||
lamp_version = last_seen.get("lamp_version")
|
||||
if lamp_version:
|
||||
out.append((f"FW: {lamp_version}", ROLE_DETAIL))
|
||||
|
||||
Reference in New Issue
Block a user