Repository navigation
build(sync): sync the newly named firmware protocol values - #108
Merged
Merged
Conversation
Node-status rows, TELEM framing and PDU page offsets, heartbeat flags, the ESR split, the die-temp and NTC sentinels, and the calibration payload offsets, as typed name-keyed tables. constexprNum accepts a leading minus; parseOffsets checks an offset table ascends and fits its row. reference.test pins every new value.
…yped offsets nodes.ts, node-telem.ts and calibration.ts index rows and payloads by the generated NODE_STATUS_FIELD / NODE_TELEM_FIELD / PDU_*_FIELD / CAL_*_FIELD tables, and compare against the generated sentinels. settings-view checks GATEWAY_NODE_ID. Output is byte-identical: proven against the base decoders and by a base/head render compare.
Closed
5 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
R1.5 of the structure rewrite. Firmware PR OpenSkyHawk/OpenSkyhawk#347 gave names to nine protocol values that used to exist only as comments or bare literals. This PR syncs those names and swaps the client's hand-typed copies for them (plan §3.3 rows B2–B9 and B17). Nothing changes in behaviour: no UI, wording or output differs.
1. Pin bump: d29433ab → a78dd902
PIN.commitnow points ata78dd90276fffb820b64ba74b82f354ab167348a, the #347 merge. It is the only firmware commit between the two pins.The pin was bumped and
npm run syncrun in a commit of its own (c150ca8), before any generator change. That commit touches exactly one line in each of the 8 generated files: the// Source: … @ <commit>banner.node-names.generated.tsalso hasNODE_REGISTRY_SOURCE.commit. Every value is identical, and the registrydatestays 2026-10-16.2. What the sync now generates
These are additions to the existing generators. No new script.
constexprNumaccepts a leading-on its first term, which the two signed sentinels need. A newparseOffsetsreads an offset enum and checks two things: the offsets are strictly ascending, and each lies inside the row or payload it indexes. A relayout the decoders can't read field by field fails the sync instead of mis-decoding.node-status.generated.ts(fromNodeStatus.h):GATEWAY_NODE_ID= 0NODE_STATUS_ROW_BYTES= 14 andNODE_STATUS_FIELD{ID 0, PRESENT 1, HB_FLAGS 2, UPTIME 3, RX_COUNT 5, ESR 7, DIE_TEMP_C 9, HEALTH_FLAGS 10, FAULT_MASK 11, FAULT_ID 12, NODE_KIND 13}HEARTBEAT_FLAGS{BOFF 0x1, EPVF 0x2}HB_ESR_TEC_SHIFT= 0 andHB_ESR_REC_SHIFT= 8DIE_TEMP_UNAVAILABLE= -128NODE_TELEM_ROW_BYTES= 9 andNODE_TELEM_FIELD{ID 0, FRAME 1}PDU_RAIL_FIELD{FLAGS 1, V_AVG_MV 2, V_MIN_MV 4, I_AVG_MA 6}PDU_STATUS_FIELD{FLAGS 1, NTC_TEMP_DC 2, I12_PEAK_MA 4, I5_PEAK_MA 6}NTC_TEMP_UNAVAILABLE= -32768axis-cal.generated.ts(fromAxisCal.h):CAL_PROTO.dataRecBytes= 10, fromCAL_DATA_REC_BYTES.CAL_HELLO_ACK_FIELD,CAL_DATA_FIELD,CAL_DATA_REC_FIELD,CAL_SESSION_OPEN_FIELD,CAL_SESSION_ACK_FIELD,CAL_STREAM_SELECT_FIELD,CAL_COMMIT_FIELD,CAL_RESET_FIELD,CAL_ACK_FIELD,CAL_NACK_FIELD,CAL_RAW_FIELD. The type prefix is stripped from each entry, soCAL_COMMIT_MINbecomesCAL_COMMIT_FIELD.MIN. The sync fails if an entry lacks the expected prefix. Each table is bounded by its type's synced payload length; the per-axis record table is bounded byCAL_DATA_REC_BYTES.Every table is an
as constname-keyed object, so a misspelt field name doesn't compile. Each entry keeps the firmware's trailing comment (// u16: AxisCal::min).reference.test.tspins every new value at today's literal, so a future firmware relayout fails there.3. Client sites replaced
GATEWAY_NODE_ID(B2)shared/nodes.tsBRIDGE_NODE_ID = 0(export kept, now= GATEWAY_NODE_ID);tabs/settings/settings-view.tsnodeId === 0registryOnBusbase vs head over node IDs 0–70 × 4 models × link up/down. Settings › About › registry render identicalNODE_STATUS_ROW_BYTES+NODE_STATUS_FIELD(B3)nodes.tsHEX_LEN = 28, the{28}regex, and everyf(i, n)hex sliceparseNodeStatusbase vs head,toStrictEqual, over 89,949 rows (below)HEARTBEAT_FLAGS(B4)nodes.tsflags & 0x01/& 0x02HB_ESR_TEC_SHIFT/HB_ESR_REC_SHIFT(B5)nodes.tsesr & 0xff/(esr >> 8) & 0xffDIE_TEMP_UNAVAILABLE(B6)nodes.tstraw === 0x80NODE_TELEM_ROW_BYTES+NODE_TELEM_FIELD(B7)node-telem.tsHEX_LEN = 18, the{18}regex,slice(0, 2), the frame-byte slice2 + i*2,slice(4)for the unknown-page bodyparseNodeTelembase vs head,toStrictEqual, over 87,133 rows (below)PDU_RAIL_FIELD/PDU_STATUS_FIELD(B8)node-telem.tsb(1),u16(2/4/6),i16(2/6)NTC_TEMP_UNAVAILABLE(B9)node-telem.tsNTC_UNAVAILABLE = -0x8000CAL_HELLO_ACK_FIELD(B17)calibration.tsdecodeHelloAckp[0..5]CAL_DATA_FIELD+CAL_DATA_REC_FIELD+CAL_PROTO.dataRecBytes(B17)decodeCalDatap[0],p[1],2 + i * 10,o + 2/4/6/8CAL_SESSION_ACK_FIELD(B17)decodeSessionAcku16(p, 0),u16(p, 2),p[4]CAL_ACK_FIELD/CAL_NACK_FIELD/CAL_RAW_FIELD(B17)decodeAckp[0];decodeNackp[0..2];decodeRawp[0],u16(p, 1/3)CAL_COMMIT_FIELD(B17)encodeCommitp[0],put(1/3/5/7), andnew Uint8Array(9)→CAL_PAYLOAD_LEN[COMMIT](already synced, already pinned at 9)CAL_SESSION_OPEN_FIELD/CAL_STREAM_SELECT_FIELD/CAL_RESET_FIELD(B17)one(type, seq, byte)with its implicit offset 0 (Uint8Array.from([byte]))onenow sizes the payloadat + 1, so if the field ever moved off byte 0, buildFrame's length check would throw rather than send a zeroStatus-row corpus (89,949 rows):
statusRow()for node IDs 0–255 × present 0/1 × kinds 0–3, 4 and 0xff0x,+/-prefix, Arabic-Indic digitisLegacyNodeStatuswas compared over the same rows.Telemetry corpus (87,133 rows):
The proof tests were mutation-checked. With
esr >> 7andp[F.DETAIL]swapped in for the reason byte, they fail. They are throwaway files and are not committed.Render compare: each view is fed rows decoded through the decoders: a gateway row, panels with bus-off/error-passive, the die-temp sentinel, -40 °C and overheat+fault, a PDU, a removed node, rail/status/unknown TELEM pages including the NTC sentinel and an INT16_MIN current, and decoded CAL_DATA / SESSION_ACK / RAW. I dumped the HTML of 8 views: Cockpit, the Cockpit panel sheet, the Cockpit PDU sheet, Connection, HID, the Calibration dialog, Settings › About, and the Settings registry dialog. Head was dumped twice to confirm the output is deterministic. Then the four changed source files were swapped back to base and the views dumped again.
diff -rbase vs head: identical.4. Sign conventions
traw < 128 ? traw : traw - 256). It now converts first and compares the signed value withDIE_TEMP_UNAVAILABLE. That is the same test as the oldtraw === 0x80, because the signed value is -128 exactly when the byte is 0x80. Proven for all 256 byte values.reference.testalso pinsDIE_TEMP_UNAVAILABLE & 0xff === 0x80.i16()already produced the signed value, and the old constant was-0x8000, soNTC_TEMP_UNAVAILABLE(-32768) drops straight in. Proven for all 65,536 words.reference.testpins& 0xffff === 0x8000. Thei16sign conversion (v >= 0x8000 ? v - 0x10000 : v) is generic int16 handling, not the sentinel, so it stays.5. What stays hand-typed, and why
V2_HEX_LEN = 26innodes.ts. The legacy v2 row is detected client-side, only to say "this bridge is too old". The firmware no longer describes it, so there is nothing to sync from. A comment now says so.b(0). The firmware names no field for it;NodeTelemFieldsays "TelemPage at FRAME + 0".buildFrame/classify(type @4, seq @5, len @6–7, payload @8). The firmware has no envelope-field enum, and they were outside B17.6. Grep proof
Each pattern was grepped over
src/shared/nodes.ts,node-telem.ts,calibration.tsandrenderer/src/tabs/settings/settings-view.ts. Every count is 0:A repo-wide search for
0x80,0x8000,INT16_MIN,=== 0on node IDs and>> 8) & 0xffoutside tests and fixtures found only generic byte handling: LE writes, CRC, int16 sign conversion, and dcsbios export frames.Verification
npm run syncis idempotent at the new pin: the diff is byte-identical before and after a re-run. That is the CI freshness gate.npm run typecheck: clean.npm run lint: 0 errors. No warnings in the changed files.npm run lint:deps: 0 errors.npx vitest run: 62 files, 856 tests. That is 852 plus 4 new reference pins. Existing assertions are unchanged.npm run build: passes.Refs #98
Refs OpenSkyHawk/OpenSkyhawk#346