Skip to content

perf(ble): return early on VCSEC actuation ACKs#59

Merged
Bre77 merged 3 commits into
mainfrom
fm/tfa-ble-ack-latency-design
Jul 10, 2026
Merged

perf(ble): return early on VCSEC actuation ACKs#59
Bre77 merged 3 commits into
mainfrom
fm/tfa-ble-ack-latency-design

Conversation

@Bre77

@Bre77 Bre77 commented Jul 10, 2026

Copy link
Copy Markdown
Member

Intent

Shorten BLE actuation latency: a VCSEC actuation (RKE/closure/wake via _sendVehicleSecurity) replies with a single bare terminal ACK and no data frame, whereas a VCSEC read replies with a bare ACK then a data frame. _send cannot distinguish them at transport level, so every successful actuation waited out the full _ack_followup_timeout (~2s) before returning, and a lost ack blocked the full 5s outer timeout - the ack tax dominates all BLE actuation latency (live testing: lock/unlock ~6s issue-to-confirm while the physical change completes in <1s).

Design (captain-approved, converged by two independent investigations): the caller knows what it sent, so thread an explicit expects_data hint from the command layer into _send. _sendVehicleSecurity passes expects_data=False through _command into _send; everything else keeps the default expects_data=True. With expects_data=False, _send returns immediately on the matching terminal ACK instead of waiting the follow-up window (kills the flat ~2s tax on every VCSEC actuation), and on a lost ack raises BluetoothTimeout after a shorter _actuation_timeout (2s) instead of _default_timeout (5s) - the documented verify-by-state contract makes a longer wait pointless.

Deliberate scope decisions a reviewer should not mistake for errors: (1) Reads (_getVehicleSecurity), all infotainment commands, _handshake, and pair intentionally keep expects_data=True and today's exact behavior byte-for-byte. (2) Infotainment actuations were deliberately NOT changed - their actionStatus rides in protobuf_message_as_bytes so _send already returns on that data frame; they never paid the tax, so only the bare-ACK-only VCSEC path benefits. (3) The WAIT/fault retry in _command threads expects_data through unchanged on purpose - the documented double-execute retry semantics are intentionally preserved, not altered. (4) In the BLE _send override, timeout was made keyword-only and placed after expects_data so positional params match the abstract base (pyright reportIncompatibleMethodOverride); pair was updated to pass timeout= by keyword. (5) signed.py and bluetooth._command signatures gained expects_data purely to satisfy the shared contract; signed.py ignores it (Fleet API replies are singular). (6) Corrected a pre-existing copy-paste docstring on _sendVehicleSecurity ('Infotainment computer' -> 'Vehicle Security computer'). (7) Introduced named class constants _default_timeout (5) and _actuation_timeout (2) for clarity/testability. Tests drive the real _send state machine plus expects_data threading and the unchanged WAIT retry over the repo's mocked transport; live verification was intentionally out of scope for this PR.

What Changed

  • Threaded an expects_data hint through signed BLE command dispatch so VCSEC actuations can return on terminal ACKs without waiting for a follow-up data frame, while preserving existing data-wait behavior for reads, infotainment, pairing, and handshakes.
  • Added shorter BLE actuation timeout handling and named timeout constants for the bare-ACK actuation path.
  • Documented the BLE actuation ACK behavior and added targeted tests for expects_data threading, early ACK return, timeout behavior, and retry preservation.

Risk Assessment

✅ Low: The change is narrowly scoped to BLE signed-command reply waiting, keeps read/infotainment paths on the existing default behavior, and adds focused coverage for the new actuation ACK and timeout paths.

Testing

Inspected the BLE-focused diff, ran the targeted pytest files covering expects_data threading and the real _send ACK/follow-up state machine, then recorded a timing transcript showing VCSEC actuation ACKs return immediately, reads still wait for follow-up data, and lost actuation ACKs use the shorter timeout. All exercised checks passed; transient uv/pytest artifacts were removed from the worktree.

Evidence: BLE ACK latency transcript

BLE VCSEC ACK latency evidence actuation expects_data=False returned matching ACK in 0.000s (0.50s follow-up window configured) read expects_data=True returned same bare ACK after follow-up wait in 0.201s (0.20s follow-up window configured) lost actuation ACK raised BluetoothTimeout in 0.050s with _actuation_timeout=0.05s and _default_timeout=5s actuation ACK matched request UUID: True read ACK matched request UUID: True

BLE VCSEC ACK latency evidence
actuation expects_data=False returned matching ACK in 0.000s (0.50s follow-up window configured)
read expects_data=True returned same bare ACK after follow-up wait in 0.201s (0.20s follow-up window configured)
lost actuation ACK raised BluetoothTimeout in 0.050s with _actuation_timeout=0.05s and _default_timeout=5s
actuation ACK matched request UUID: True
read ACK matched request UUID: True

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • git diff --stat 0800251ef2b03a358f8a413d904a1cc857f90f8e..47669db5537aad976fba751bc1b924e1f2735566 and targeted diff reads to understand scope and intent
  • uv run pytest tests/test_ble_expects_data.py tests/test_ble_send_transport.py
  • uv run python - <<'PY' | tee /tmp/no-mistakes-evidence/01KX4ZM40S1ZJN2NJ5XNTWAA66/ble_ack_latency_transcript.txt
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

firstmate crewmate added 3 commits July 10, 2026 13:00
A VCSEC actuation (RKE/closure/wake via _sendVehicleSecurity) replies with
a single bare ACK and no data frame, whereas a VCSEC read replies with a
bare ACK then a data frame. _send cannot tell the two apart at transport
level, so every successful actuation waited out the full _ack_followup_timeout
(~2s) before returning, and a lost ack blocked the full 5s outer timeout.

The caller knows what it sent, so thread an explicit expects_data hint from
_sendVehicleSecurity (expects_data=False) through _command into _send. With
expects_data=False, _send returns immediately on the matching terminal ack
and, on a lost ack, raises BluetoothTimeout after a shorter _actuation_timeout
(2s) instead of _default_timeout (5s) - the verify-by-state contract makes a
longer wait pointless. Reads, infotainment commands, handshake and pair keep
expects_data=True and today's exact behavior. The WAIT/fault retry threads the
hint through unchanged.

Tests drive the real _send state machine (immediate terminal-ack return,
read follow-up wait unchanged, shortened lost-ack timeout for actuations,
default timeout preserved for reads) plus the expects_data threading and
unchanged WAIT retry over the mocked transport.
@Bre77
Bre77 merged commit 628bfae into main Jul 10, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant