"""Firmware identification from the boot log. The app version string is "1.0" in every build seen so far, so builds are told apart by the ELF SHA256 prefix printed by app_init. Boxes receive new firmware over OTA; an unknown SHA usually means a box has already updated. """ from __future__ import annotations import re from dataclasses import dataclass, field @dataclass(frozen=True) class KnownFirmware: name: str source: str sd_wifi: bool # reads SSID/PASSWORD from ENV.TXT setup_portal: bool # short press -> Wi-Fi setup portal KNOWN: dict[str, KnownFirmware] = { "45fa9d5b9": KnownFirmware( name="v1.0 (built Jun 29 2026)", source="factory image new_system.bin", sd_wifi=False, setup_portal=False, ), } _ELF = re.compile(r"app_init: ELF file SHA256:\s+(?P[0-9a-f]{6,})") _VER = re.compile(r"app_init: App version:\s+(?P\S+)") _BUILT = re.compile(r"app_init: Compile time:\s+(?P.+)$") _IDF = re.compile(r"app_init: ESP-IDF:\s+(?P\S+)") # Evidence of features, for builds not in KNOWN. _FEATURE_SD_WIFI = re.compile(r"WIFI_CREDENTIALS: ") _FEATURE_PORTAL = re.compile(r"WIFI_PROVISIONING: |Short press: ") # Deployed v1.0 logs the SD mount under the INFLUX_BUFFER tag. _LEGACY_SD_TAG = re.compile(r"INFLUX_BUFFER: SD card mounted") @dataclass class FirmwareInfo: elf_sha: str | None = None version: str | None = None built: str | None = None idf: str | None = None evidence: set[str] = field(default_factory=set) def observe(self, text: str) -> None: if m := _ELF.search(text): self.elf_sha = m.group("sha") elif m := _VER.search(text): self.version = m.group("v") elif m := _BUILT.search(text): self.built = m.group("t").strip() elif m := _IDF.search(text): self.idf = m.group("v") if _FEATURE_SD_WIFI.search(text): self.evidence.add("sd_wifi") if _FEATURE_PORTAL.search(text): self.evidence.add("setup_portal") if _LEGACY_SD_TAG.search(text): self.evidence.add("legacy_v1") @property def known(self) -> KnownFirmware | None: if not self.elf_sha: return None return next((k for sha, k in KNOWN.items() if self.elf_sha.startswith(sha)), None) @property def supports_sd_wifi(self) -> bool | None: """True/False when determinable, None when unknown (no boot seen).""" if k := self.known: return k.sd_wifi if "sd_wifi" in self.evidence: return True if "legacy_v1" in self.evidence: return False return None def describe(self) -> str: if k := self.known: return f"{k.name} - {k.source}" if self.elf_sha: built = f", built {self.built}" if self.built else "" return f"Unknown build {self.elf_sha[:9]}{built} (probably updated over OTA)" if "legacy_v1" in self.evidence: return "Probably v1.0 factory image (press Reset & capture to confirm)" return "Not identified yet - press Reset & capture"