Skip to content

STATUS parsers drop the DSP firmware version (second FW-header line) #84

Description

@caidurbin

Summary

The STATUS response header spreads the firmware version over two lines:

      FW Version:MCU_Main V1.5.0/Web_GUI V1.4.0a
                 DSP V1.5.9

Every parser captures only the first line, so the DSP version is silently dropped. status (JSON and human output) reports firmware_version: "MCU_Main V1.5.0/Web_GUI V1.4.0a" with no DSP component. The DSP version is real, independently-revved firmware (fixtures show DSP V1.5.7 and V1.5.9 against the same MCU V1.5.0), so under-reporting it loses meaningful device state.

Observed against a live device on firmware MCU_Main V1.5.0 / Web_GUI V1.4.0a / DSP V1.5.9; reproducible offline with the committed fixtures.

Affected code

The single-line assumption is replicated in three parsers and asserted by the shared drift-gate vector, so this is a protocol-contract fix, not a one-file fix:

  • blustream/devices/dmp168/status_parser.py:70-81_parse_firmware returns the FW Version: line only; the indented DSP Vx.y.z continuation line matches nothing.
  • blustream/devices/dmp168/parser.py:130-137 — legacy parser, same logic (re.search(r"FW Version:([^\n]+)"), then break).
  • control4/dmp168/src/status_parser.lua:75-81 — Lua parse_firmware, same single-line capture.
  • spec/vectors/fixtures/status_full_routing.txt:11-12 vs status_full_routing.expected.yaml:9 — the input fixture contains DSP V1.5.7, but the expected output pins firmware_version: "MCU_Main V1.5.0/Web_GUI V1.5.0", encoding the bug into the cross-implementation contract (ADR-0007).

Repro: uv run python -c "from pathlib import Path; from blustream.devices.dmp168.status_parser import parse_status; print(parse_status(Path('tests/fixtures/status_live_full.txt').read_text())['firmware_version'])" → no DSP component, while the fixture's header (lines 3–4) carries DSP V1.5.9.

Open design decision

How to surface the DSP version — append to the existing string (e.g. MCU_Main V1.5.0/Web_GUI V1.4.0a/DSP V1.5.9) or add a separate field (e.g. dsp_version) to SystemStatus (blustream/devices/dmp168/models.py:105) and the Lua result table. A separate field is cleaner but changes the model/JSON shape consumers see; appending keeps the shape but overloads the string.

Acceptance criteria

  • status_parser.py captures the DSP version from the continuation line
  • parser.py (legacy) agrees with status_parser.py
  • control4/dmp168/src/status_parser.lua has parity with the Python parsers
  • spec/vectors/fixtures/status_full_routing.expected.yaml updated so the shared vectors enforce the new contract in both runtimes
  • SystemStatus model / to_dict / formatter output expose the DSP version (per the design decision above)
  • Tests cover the two-line header, including a response with no DSP line (graceful degradation)
  • Downstream consumers audited (CLI output, HA integration surfaces that display firmware_version)

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageMaintainer needs to evaluate this issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions