"""Produkt-IDs der alten Klyqa-Firmware und ihre Zuordnung zu ninlight-Zielen. Vollstaendig uebernommen aus qcl_product_info.c der alten Firmware (~/workspace/qcx-w600-firmware). Der "-dev"-Anhang entscheidet zugleich ueber den Signierschluessel: Lampen mit Dev-Produkt-ID akzeptieren nur den Entwicklungs-, Produktionslampen nur den Produktionsschluessel. """ import re from collections import namedtuple Product = namedtuple("Product", "product_id target variant name") ParsedRequest = namedtuple("ParsedRequest", "product_id lamp_version product") # (Produkt-ID ohne "@", Ziel, Anzeigename) - die Dev-Variante wird darunter erzeugt. _BASE = [ ("klyqa.lighting.rgb-cw-ww.e27", "e27_rgb", "Klyqa E27 RGB CW/WW"), ("klyqa.lighting.rgb-cw-ww.e14", "e14_rgb", "Klyqa E14 RGB CW/WW"), ("klyqa.lighting.rgb-cw-ww.gu10", "gu10_rgb", "Klyqa GU10 RGB CW/WW"), ("klyqa.lighting.cw-ww.e27", "e27_cw", "Klyqa E27 CW/WW"), ("klyqa.lighting.cw-ww.e14", "e14_cw", "Klyqa E14 CW/WW"), ("klyqa.lighting.cw-ww.gu10", "gu10_cw", "Klyqa GU10 CW/WW"), ("klyqa.lighting.cw-ww.g95", "g95_cw", "Klyqa G95 Vintage CW/WW"), ] _UNSAFE = re.compile(r"[^0-9A-Za-z+\-_.]") # Die Produkt-ID darf kein "_" enthalten - daran trennen wir Version und ID. _PATH = re.compile(r"^/qcx_firmware_([^/_]+)_([^/_]+)_ota_light\.img$") def websafe(product_id): """Ersetzt jedes Zeichen ausserhalb [0-9A-Za-z+-_.] durch '-', wie BuildOTAURL() in qc_ota.c der alten Firmware. Praktisch betrifft das nur das fuehrende '@'.""" return _UNSAFE.sub("-", product_id) def _build(): t = {} for pid, target, name in _BASE: for suffix, variant in (("", "prod"), ("-dev", "dev")): key = websafe("@" + pid + suffix) t[key] = Product(key, target, variant, name) # Das EVK hat nur eine Produktions-ID. Im Dev-Build meldet es sich laut # qcl_product_info.c als "@klyqa.lighting.rgb-cw-ww.e27-dev" - die EVK-Zeile ist dort # auskommentiert und durch die E27 ersetzt. Ein dev-signiertes EVK ist damit von einer # dev-signierten E27 RGB NICHT unterscheidbar und bekommt deren Image. Das EVK wird # ohnehin seriell geflasht; die Zeile steht nur der Vollstaendigkeit halber hier. key = websafe("@klyqa.lighting.w600.evk1.2") t[key] = Product(key, "evk", "prod", "W600 EVK v1.2") return t PRODUCTS = _build() def parse_request(path): """Zerlegt einen angefragten Pfad. Gibt None zurueck, wenn er nicht dem Muster der alten Firmware entspricht, sonst ParsedRequest - dessen .product ist None, wenn die Produkt-ID unbekannt ist. Unbekannt heisst 404, nicht raten.""" m = _PATH.match(path) if not m: return None pid, version = m.group(1), m.group(2) if pid != websafe(pid) or "/" in pid or ".." in pid.split("."): return None return ParsedRequest(pid, version, PRODUCTS.get(pid))