plan 0018: SensorEgg GATT link — the logger connects to the paired egg - #164
Open
TheAngryRaven wants to merge 2 commits into
Open
plan 0018: SensorEgg GATT link — the logger connects to the paired egg#164TheAngryRaven wants to merge 2 commits into
TheAngryRaven wants to merge 2 commits into
Conversation
…ers) parseDescriptor (strides by declared record_len — forward compat), parseSampleFrame, parseClock, sampleToReal (sentinel -> NaN before scaling), descriptor-driven role mapping (normative names + quantity, never hardcoded channel ids), fastestChannel, and the v1 clock fit (request/response midpoint anchor, boot_id epoch check, wrap-safe mapping both directions). Fixtures are byte-identical to the egg repo's pw_gatt_encode goldens — encode == decode pinned across repos, the sensoregg_protocol <-> pw_adv_encode discipline applied to the GATT contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AcdBRTn52QpCQWkyVm5Lkg
bleCoreEnsureInit grows a flag-gated central slot (begin(1,1) +
configCentralConn(247, 6, 1, 1) — 7.5 ms event cap so the pod link can
never crowd the camera; stock builds stay begin(1,0)). The scan
callback doubles as the connect trigger (paired connectable report
while WAIT_ADV -> Central.connect, no resume on that path); the
central connect callback runs the blocking bring-up sequence in the
callback task (documented deviation — client ops each wait a conn
interval and would stall the 25 Hz row engine on the main loop):
discover, MTU 247, read Descriptor, timed Clock read (the fit anchor),
enableNotify, ready-flag-last. The notify data plane keeps the
copy-only discipline: an 8-slot frame ring drained by SENSOREGG_LOOP,
which parses, epoch-checks boot_id (mismatch -> log + reconnect
re-anchors), routes the latest sample per frame by descriptor-driven
role mapping into the SAME eggReading surface the beacon feeds, and
feeds the zombie monitor from the fastest channel's frame seq only.
Gate split keeps plan-0012 discipline uniform: eggLinkWanted = radio
gate + paired; eggScanWanted = radio gate && (pairing window || no
link engaged) — streaming pays no scan duty; capturing a NEW egg
drops the old link. SENSOREGG_SLEEP cancels/drops the central link
(covers transfers + shutdown; the quiesce settle gives it airtime).
EGG TEST: rf:GATT state + live MTU. Stale be80-era central prose in
bluetooth.{h,ino} fixed; subsystem-14 radio-role rewritten (the
camera-priority rule survives as mechanism, not prohibition).
Verified: host suite green (fixtures byte-identical to the egg's
pw_gatt_encode goldens), sim goldens unchanged, both flag arms
compile (ON 47%/36%, OFF 45%).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AcdBRTn52QpCQWkyVm5Lkg
Coverage — host-testable units📂 Overall coverage
📄 File coverage
|
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.
Summary
The logger becomes BLE central toward the paired egg and consumes its PerchWerks Sensor Service end-to-end (design record:
docs/plans/0018-sensoregg-gatt-link.md; companion firmware: DovesSensorEgg PR #16 — flash that egg before benching this).sensoregg_gatt.{h,cpp}(host-tested): Descriptor decode (strides by declaredrecord_len— forward-compatible), Sample frame decode, Clock decode,sampleToReal(0x8000 sentinel → NaN before scaling), descriptor-driven role mapping (normative names + quantity — nothing egg-specific hardcoded; a future pod with different channels parses with zero logger changes), and the v1 clock fit (request/response midpoint anchor,boot_idepoch check, wrap-safe both directions). Fixtures are byte-identical to the egg repo'spw_gatt_encodegoldens — the wire contract pinned from both ends, exactly likesensoregg_protocol↔pw_adv_encodefor the beacon.bleCoreEnsureInit()runs flag-gatedBluefruit.begin(1, 1)withconfigCentralConn(247, 6, 1, 1)— a 7.5 ms event cap so the pod link can never crowd the camera; stock builds staybegin(1, 0).SENSOREGG_LOOP().eggReading/eggRxMs/eggSeqMonsurface the beacon feeds — every accessor, DOVEX column, race page and LED path untouched. Zombie detection feeds from the fastest channel's frame seq only. Aboot_idmismatch logs "pod rebooted", drops the link, and the reconnect re-anchors.SENSOREGG_SLEEP()cancels/drops the central link, which covers BLE transfer mode and shutdown for free. The beacon remains the unclaimed/disconnected fallback and the pairing transport.rf:GATTstate + liveM<mtu>; degradations recorded in the plan doc (tcFaultfalse while streaming — frames carry no MCP STATUS;protoVersion/pairingFlaghold last beacon values).bluetooth.{h,ino}fixed; subsystem-14's "do not improve this into a connection" rewritten — the camera-priority rule survives as mechanism (skinny params + gate + SLEEP), not prohibition.Type of change
How it was verified
ctest --test-dir tests/build) — newsensoregg_gattmatrix: golden descriptor/frame/clock (egg-identical bytes), stride-by-28 forward compat, role mapping, sentinel, fit anchor/epoch/millis-wrapclang-tidyclean — left to CIbegin(1,0)/(1,1)split makes flag-OFF a real risk)rf:GATT M247with live values; power-yank the egg →---within 1 s, auto-reconnect + "pod rebooted" log on return; unpair → beacon fallback (rf:OK); transfer mode drops the link, download throughput matches plan-0012 numbers; camera soak (headline risk): repeated connect/record cycles + one full download with the egg link streaming; shutdown/charge park with link up → clean System OFFChecklist
CHANGELOG.mdupdated under[Unreleased](if user-visible)ARCHITECTURE.md/CLAUDE.mdupdated (if a module or interface changed) — subsystem 6 + 14, file map, begin() notestests/Related issues
Companion: DovesSensorEgg PR #16 (Phases 2+3 — the service this consumes). Either merges first; bench together.
🤖 Generated with Claude Code
https://claude.ai/code/session_01AcdBRTn52QpCQWkyVm5Lkg
Generated by Claude Code