feat(core): board-profile catalog and versioned blob serializer - #35
Merged
Conversation
Contributor
Author
|
Note captured from review (not blocking — the waveshare_s3_28 profile is an intentional placeholder to fill when the board is in hand):
|
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.
Slice G of the runtime-board-config pivot (CANShift/canshift-firmware#68): the shared source of truth for
BoardProfile. The tuner writes the blob, firmware reads it.src/board-profile/= types + catalog + serializer.Field list I settled on (cross-checked against firmware
include/board_profile.h)I mirrored the current C++ struct field-for-field (not #68's prose, which diverges) so a future struct↔TS parity check stays green. snake_case blob keys ↔ camelCase TS domain via
boardProfileFromWire/boardProfileToWire(the boundary-mapper convention).board_id,board_name,chip_family,lcd,backlight,touch,can,storage,conndriver,pin_mosi,pin_miso,pin_sclk,pin_cs,pin_dc,pin_rst,pin_bl,freq_write_hz,panel_width,panel_height,memory_width,memory_height,default_rotation,rgb_order_bgr,invert,bus_shared_with_touch,readable,color_depthpresent,pwm_channel,pwm_freq_hz,default_duty,invertdriver,pin_cs,pin_irq,freq_hz,needs_calibration,pin_sda,pin_sclcontroller,pin_tx,pin_rx,default_speed_kbpsspiffs_present,spiffs_size_kb,sd_present,sd_pin_cswifi_supported,ble_supported,psram_presentEnums (string slugs):
chip_familyesp32|esp32s3; lcddriverili9341|st7789|ili9488|gc9a01; touchdrivernone|xpt2046|ft6336|gt911|cst816s; cancontrollernone|esp_twai.Three points to reconcile with firmware slice #70 (flagged so you can align the struct):
chip_familyis not in the current struct. #68 requires it (picks the universal firmware per chip) and the struct becomes the runtime type in #70 — I added it top-level; the struct needs the matching field.lcd/conn(notdisplay/connectivity),bus_shared_with_touch(notbus_shared),pin_sda/pin_sclfor I2C touch (not ani2c_addr), and backlightpresent/default_duty(nopin— the backlight pin islcd.pin_bl). I matched the struct; these differ from the task/#68 prose.readableandcolor_depthfields even though #68's prose omittedcolor_depth.Blob envelope
Versioned magic envelope, gated before shape (magic + formatVersion), reusing the #21
__proto__hardening:{ "magic": "CANSHIFT_BOARD", "schema": "board-profile", "formatVersion": 1, "profile": { …snake_case… } }serializeBoardProfile(profile): string— validates via the wire schema, wraps, pretty-prints; deterministic (Zod canonical key order → byte-stable round-trip).parseBoardProfile(raw): BoardProfileResult— discriminated result mirroringparseUsbStatus/parseCanshiftFile:ok/invalid_json/not_an_object/unsupported_blob_version/wrong_shape. Pipeline:JSON.parsewith a forbidden-key reviver → magic gate (wrong magic →wrong_shapewith a["magic"]issue) →formatVersiontoo-new gate → strict envelope+profile validation. Numeric fields are range-checked to the struct's C widths (int8 pins, uint16 dims, uint32 freqs).Catalog
BOARD_PROFILES+getBoardProfile(id):crowpanel_28,generic_ili9341,generic_ili9341_gt911— exact pin maps copied from the firmware board headers (include/boards/*.h).waveshare_s3_28(incoming — ST7789T3 SPI + CST816 I2C, esp32s3, 240×320): all pins are placeholder-1andfreq_write_hzis a provisional 40 MHz. TODO: fill the real Waveshare pin map when the board arrives / slice-B stabilizes — the round-trip test still validates the shape, so a later pin correction is a one-line data change.Schema version
No
CURRENT_SCHEMA_VERSIONbump — a board profile is device-provisioning data with its own independent blobformatVersion, not persistedDashboardConfig. The dashboard-schema migration rule does not apply.Test plan
npm run build/npm run lint/npm run format:check— cleannpm test— 1054 passed, 3 skipped (unrelated); firmware-parity suites green with the sibling checkout. 15 new tests:getBoardProfilehit/misswrong_shape, newerformatVersion→unsupported_blob_version, out-of-range pin, unknown driver enum, strict extra key__proto__stripped,Object.prototypenever pollutedCloses #34. Part of CANShift/canshift-firmware#68 (slice G). Do not merge — ready for review; the field list above is the proposal to reconcile with firmware slice #70.