Field value store and page descriptor model #58
Labels
No labels
area:companion
area:docs
area:shared
area:tooling
area:watchapp
blocker
kind:chore
kind:feature
kind:spike
kind:test
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Blocks
Depends on
#9 Default page definitions: Ride, Effort, Progress
robert/PedalPebble
#10 HRM integration with sample-period lifecycle
robert/PedalPebble
#46 Lap function
robert/PedalPebble
#59 Page template renderer: HERO1, HERO2, QUAD, GRID6
robert/PedalPebble
#60 Page carousel navigation with long-press jumps
robert/PedalPebble
#61 Configure watch pages from the phone
robert/PedalPebble
#68 Host-side unit tests for the watchapp logic
robert/PedalPebble
Reference
robert/PedalPebble#58
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
Make pages data rather than layout code. This is the foundation that lets the phone configure screens later without rewriting the views, and it must land before any view hard-codes a layout.
Acceptance criteria
FieldIdenum covering every metric: speed, average and max speed; distance, elapsed, clock; HR, average HR, HR zone; power, 3 s power, average and normalised power; cadence and average cadence; ETA, remaining, distance to turn; lap number, distance, time and average speedFieldId, updated as messages arrive, each entry carrying its last-update timestampPageDescriptor { template, fields[6] }with descriptors held in persistent storage--- never a stale value, never zeroFiles
watchapp/src/c/fields.cwatchapp/src/c/fields.hwatchapp/src/c/page.hNotes
See docs/DESIGN.md sections 1 and 2. Getting this in before #9 is the whole point - a hard-coded layout makes the later phone configuration a rewrite.
Update — 2026-09-01: every field needs a producer and a wire key
The enum defined
MAX_SPEED,AVG_HR,HR_ZONE,AVG_CADENCEandNORM_POWERwith nothinganywhere in the plan computing them — fields that could only ever render
--. #65 now produces themand
docs/PROTOCOL.mdgives them wire keys (D28).FieldIdmaps to a key in docs/PROTOCOL.md, or is documented as watch-local (HR,CLOCK)cadence and power
Update — 2026-09-02: stale and unavailable are two states
The store already carries a last-update timestamp per entry, and the criteria above ask for both
--and greying. Those are different states and were being conflated (D44).--means there is no source. It is signalled by the phone with the type's sentinel,never inferred from silence
not against that key's own last arrival. Under changed-keys-only updates a constant value —
speed of zero at a traffic light, distance while paused — stops being sent and would otherwise
grey out while perfectly fresh
10 s, far too coarse to catch a 3 s gap
Closed by PR #81 (merged): FieldId enum, group-heartbeat value store (D44: unavailable vs stale are separate states), per-field formatter table (units live in the label per DESIGN.md rule 5, never appended by field_format), PageDescriptor + page_has_live_field() (the primitive #60 needs), wire/persisted packing matching PROTOCOL.md 2.6 byte-for-byte, and the three default pages (Ride/Effort/Progress) from DESIGN.md section 4.
pebble buildrun clean for emery/gabbro/basalt; fields.c/.h additionally compiled and smoke-tested standalone with host gcc. Staleness thresholds, ETA-as-duration, and the single-blob persist layout are design calls flagged in the PR body for review. #68's host-test harness intentionally left unbuilt — fields.c/.h are proven host-compilable but page.c mixes in persist_* calls, so a clean split/stub is #68's own call to make.