Repository navigation
feat: node status v4 — tolerant row parsing and the 0xFF00 roster request (firmware #359 re-sync) #170
Description
Summary
Firmware's v1.0 freeze review (OpenSkyHawk/OpenSkyhawk#295, PR OpenSkyHawk/OpenSkyhawk#359) changes the node-status contract the client reads. Today's client breaks against it: node-status-wire.ts:53 accepts exactly 28 hex characters, so every v4 row is dropped and the Cockpit goes empty with no message (only the old 26-character v2 length gets an alert). This ticket is the minimum to keep the Cockpit working against it: re-sync, parse v4 rows tolerantly, send the roster request at 0xFF00. Showing the new per-board versions is a follow-up ticket (see below).
Pin: sync to current OpenSkyhawk main (e82ac6eb7c6ada62135e39a065ddf652eaf35eaf at the time of writing, or newer if main has moved when the PR is cut), not #359's commit. The boards send that layout now: #359 plus #365's bootloader fields.
Scope (2026-10-26): this ticket is the whole firmware re-sync. It generates everything new in the contract, including the DIAG constants that #169 uses. #169 is the link-health feature on top and has no sync work of its own.
Until this lands: don't run a Gateway flashed with #359's firmware against the client.
Wire changes (all from npm run sync, never hand-copied)
| What | Before | After |
|---|---|---|
NODE_STATUS_PROTO_VERSION |
3 | 4 |
NODE_STATUS_ROW_BYTES |
14 (28 hex) | 19 (38 hex) |
New NodeStatusField |
— | FW_MAJOR 14, FW_MINOR 15, FW_PATCH 16, BOOTLOADER 17, BOOT_STATE 18 (u8 each; the last two from OpenSkyHawk/OpenSkyhawk#365) |
NODE_STATUS_REQ_ADDR (roster request) |
0x86FE |
0xFF00 |
- Firmware version per board: each STM32 node now sends its release version in
READY_n; the bridge caches it and appends it to the node's row. The node-0 row carries the bridge's own build.00 00 00= not reported: no READY seen since the bridge booted, or older firmware. When an alive node's version changes (a reflash inside the 3 s heartbeat timeout), the bridge pushes a_NODE_STATUSdelta. - Roster request moved to
0xFF00:0x86FEis a live DCS-BIOS address for the AH-64D (PLT_VIDEO_FLIR_GAIN) and the Mirage F1 (P_VOR_01_G), so flying either made the bridge answer every export of that control with a roster burst. No DCS-BIOS module uses0xFF00. The client already sends whatevernode-status.generated.tssays, so the re-sync is the whole change. - Node status is now on by default in PanelBridge firmware.
Compatibility rules the client must follow (firmware decision D22)
Within a major, firmware only appends fields, values and pages. Each 1.x addition then stays readable by an older client, which isn't true today:
- Accept longer rows: a well-formed
_NODE_STATUSrow at least as long as the layout the client knows → parse the known fields, ignore the rest. - Shorter well-formed row → "Gateway firmware too old" alert, once (replaces the hard-coded 26-character v2 check). Never drop rows silently.
- Unknown values (
NodeKind,NodeFaultCode,TelemPage, flag bits) → show as "unknown (0xNN)", never an error. - Malformed lines: drop, debug log only.
Changes
- Sync: re-point the firmware pin to current
main; regenerate (node-status.generated.ts: proto 4, row bytes 19, the five new fields,reqAddress0xFF00). — fix(nodes): node status v4 — re-sync to firmware main, tolerant rows, roster request at 0xFF00 #178 - Sync fix: the payload-length table reads
return len == <number>only. Firmware now writesreturn len == CAL_DIAG_BYTES, which today is silently given the next group's length. Resolve named constants fromAxisCal.h, and fail the sync on any it can't resolve. — fix(nodes): node status v4 — re-sync to firmware main, tolerant rows, roster request at 0xFF00 #178 - Sync: generate
CalDiagField,CAL_DIAG_BYTESandCalDiagResetReason(moved here from feat: read and show the Gateway's link-health counters (GET_DIAG) #169; nothing uses them until feat: read and show the Gateway's link-health counters (GET_DIAG) #169). — fix(nodes): node status v4 — re-sync to firmware main, tolerant rows, roster request at 0xFF00 #178 - Parser: accept well-formed rows of 38 or more hex characters and parse the known prefix. Decode
fwMajor/fwMinor/fwPatch,bootloaderandbootStateinto the node model (displayed by feat: show each board's firmware version and warn on a major mismatch #171). A row in an older bridge's layout (v2 = 26 hex, v3 = 28 hex) triggers the "Gateway firmware too old" alert once, replacing the hard-coded v2 check; that bridge's_NODE_STATUS_ENDstays ignored, and a current row clears it. Any other short row is malformed (dropped, debug log only), so one line cut short can't read as a too-old bridge. — fix(nodes): node status v4 — re-sync to firmware main, tolerant rows, roster request at 0xFF00 #178 - Calibration demux: the re-sync adds the firmware-upload types; refuse a candidate larger than
CAL_MAX_FRAME(UPL_DATAis 260 bytes, client-only), so the carry bound holds. — fix(nodes): node status v4 — re-sync to firmware main, tolerant rows, roster request at 0xFF00 #178 - Roster request uses the synced
0xFF00(no code change beyond the sync; verify, including that a reply clears "not responding"). — fix(nodes): node status v4 — re-sync to firmware main, tolerant rows, roster request at 0xFF00 #178 - Unknown values (
NodeKind,NodeFaultCode, flag bits) pass through as unknown, never an error. Tests cover it. — fix(nodes): node status v4 — re-sync to firmware main, tolerant rows, roster request at 0xFF00 #178 (2026-10-27: unknown flag bits are ignored rather than shown, which D22 allows; the "Unknown … (n)" wording moves to hex,0xNN, per D22, in a client cleanup task.) - Tests: v4 row fixtures (version fields,
000000, bootloader fields), a longer-than-v4 row parsed by prefix, short rows (26 / 28 / other) alerting once, unknown enum values, roster request encoded at0xFF00. — fix(nodes): node status v4 — re-sync to firmware main, tolerant rows, roster request at 0xFF00 #178
Out of scope
- Showing per-board firmware versions and the mismatch warnings: feat: show each board's firmware version and warn on a major mismatch #171.
- Aircraft detection preferring
_ACFT_NAME: fix: identify the aircraft by _ACFT_NAME, not by export address range #172. - Reading and showing
DIAG: feat: read and show the Gateway's link-health counters (GET_DIAG) #169 (its constants come from this ticket's sync). - The exact wording for unknown values: today "unknown board type 9" and "Fault 12"; D22 says "unknown (0xNN)". To be checked against D22 with the firmware session.
- The bridge "forget node" request at
0xFF04: feat: update a board over CAN from a firmware release #175 ("Forget this board"). - Firmware upload: tracked in the separate upload-utilities design.
Activity
[-]feat: node status v4 — per-board firmware versions, tolerant row parsing, roster request at 0xFF00[/-][+]feat: node status v4 — tolerant row parsing and the 0xFF00 roster request (firmware #359 re-sync)[/+]fix(cockpit): keep the Adopt dialog's footer on screen with many new …