Skip to content

test(vehicle): cover BLE media commands over mocked transport - #53

Merged
Bre77 merged 4 commits into
mainfrom
fm/tfa-ble-pr6-media-v8
Jul 9, 2026
Merged

test(vehicle): cover BLE media commands over mocked transport#53
Bre77 merged 4 commits into
mainfrom
fm/tfa-ble-pr6-media-v8

Conversation

@Bre77

@Bre77 Bre77 commented Jul 9, 2026

Copy link
Copy Markdown
Member

Intent

Live-verify the BLE media command group (PR-6 of the BLE production-readiness program): adjust_volume, media_volume_up/down, media_toggle_playback, media_next_track/media_prev_track, media_next_fav/media_prev_fav, all inherited Commands methods routed over VehicleBluetooth's BLE transport, exercised via a mocked-transport regression test per command asserting the correct signed VehicleAction proto is built and the OK reply decodes correctly. remote_boombox is intentionally CAPTAIN-PRESENT-ONLY (plays sound through the external speaker) so it is covered by a mocked-transport test only and was deliberately never actuated live, per standing safety policy for this program.

Live actuation against the real test car (VIN LRW3F7EK4NC716336, over an ESPHome BLE proxy at m5-btproxy.local) was attempted per the standard snapshot->act->verify->restore->confirm methodology used by the sibling PRs in this program. It was deferred, not completed: the first live write (adjust_volume) reliably hit a GATT write-response timeout (aioesphomeapi TimeoutAPIError) across 5 separate fresh connections/retries in one session (including retries explicitly requested by the supervising session after a fresh wake_up()), while plain BLE reads over the same connections succeeded normally every time. After every failed attempt the car's state was re-read and reconfirmed unchanged (audio_volume still 2.0, media_playback_status still Playing, nothing left mutated) - so this is a transport reliability issue, not a botched command. This asymmetry (writes fail, reads succeed) is recorded in AGENTS.md as a finding for whoever runs the next live-verify attempt on this rig, along with a separate, unrelated discovery that MediaState/MediaDetailState track-identity fields (artist/title/album/station) read empty on this car while Spotify is the active source, meaning media_next_track/prev_track/next_fav/prev_fav are not state-observable via those readers on this rig+source and should be verified by command ACK plus a paired restore call instead of an exact state match.

Given the deferred live-verify, this PR intentionally ships as tests-only (all 105 existing tests plus the new suite pass, ruff and pyright clean) with no behavior changes to any source file - only new test coverage and two AGENTS.md documentation notes. No commands were added or modified; VehicleBluetooth already inherits every one of these methods from the shared Commands ABC (this program's premise throughout: BLE work is verification, not implementation).

What Changed

  • Added mocked BLE transport regression coverage for INFO-domain media commands, asserting the signed VehicleAction payloads and OK acknowledgement decoding for volume, playback, track/favorite navigation, and remote_boombox.
  • Documented BLE media command behavior, verification limits, and timeout handling in docs/bluetooth_vehicles.md.
  • Recorded agent-facing BLE media observability and write-vs-read transport caveats for future live verification attempts.

Risk Assessment

✅ Low: The branch only adds mocked BLE media-command regression tests plus AGENTS.md notes, with no production source changes and no material review issues found.

Testing

Targeted mocked BLE media tests and the full 105-test suite passed; the generated JSON evidence shows each end-user media method call routed to DOMAIN_INFOTAINMENT, the signed VehicleAction oneof/fields, and the decoded OK reply. I also cleaned transient uv/Python test artifacts from the worktree and left evidence only under /tmp/no-mistakes-evidence/01KX38YCWX7KDC7Q3G1XEHS68T.

Evidence: BLE media command payload evidence
[
  {
    "args": [
      5.0
    ],
    "decoded_reply": {
      "response": {
        "reason": "",
        "result": true
      }
    },
    "fields": {
      "populated_fields": [
        "volume_absolute_float"
      ],
      "volume_absolute_float": 5.0,
      "volume_delta": 0
    },
    "method_called": "adjust_volume",
    "routed_domain": "DOMAIN_INFOTAINMENT",
    "vehicle_action_oneof": "mediaUpdateVolume"
  },
  {
    "args": [],
    "decoded_reply": {
      "response": {
        "reason": "",
        "result": true
      }
    },
    "fields": {
      "populated_fields": [
        "volume_delta"
      ],
      "volume_absolute_float": 0.0,
      "volume_delta": 1
    },
    "method_called": "media_volume_up",
    "routed_domain": "DOMAIN_INFOTAINMENT",
    "vehicle_action_oneof": "mediaUpdateVolume"
  },
  {
    "args": [],
    "decoded_reply": {
      "response": {
        "reason": "",
        "result": true
      }
    },
    "fields": {
      "populated_fields": [
        "volume_delta"
      ],
      "volume_absolute_float": 0.0,
      "volume_delta": -1
    },
    "method_called": "media_volume_down",
    "routed_domain": "DOMAIN_INFOTAINMENT",
    "vehicle_action_oneof": "mediaUpdateVolume"
  },
  {
    "args": [],
    "decoded_reply": {
      "response": {
        "reason": "",
        "result": true
      }
    },
    "fields": {},
    "method_called": "media_toggle_playback",
    "routed_domain": "DOMAIN_INFOTAINMENT",
    "vehicle_action_oneof": "mediaPlayAction"
  },
  {
    "args": [],
    "decoded_reply": {
      "response": {
        "reason": "",
        "result": true
      }
    },
    "fields": {},
    "method_called": "media_next_track",
    "routed_domain": "DOMAIN_INFOTAINMENT",
    "vehicle_action_oneof": "mediaNextTrack"
  },
  {
    "args": [],
    "decoded_reply": {
      "response": {
        "reason": "",
        "result": true
      }
    },
    "fields": {},
    "method_called": "media_prev_track",
    "routed_domain": "DOMAIN_INFOTAINMENT",
    "vehicle_action_oneof": "mediaPreviousTrack"
  },
  {
    "args": [],
    "decoded_reply": {
      "response": {
        "reason": "",
        "result": true
      }
    },
    "fields": {},
    "method_called": "media_next_fav",
    "routed_domain": "DOMAIN_INFOTAINMENT",
    "vehicle_action_oneof": "mediaNextFavorite"
  },
  {
    "args": [],
    "decoded_reply": {
      "response": {
        "reason": "",
        "result": true
      }
    },
    "fields": {},
    "method_called": "media_prev_fav",
    "routed_domain": "DOMAIN_INFOTAINMENT",
    "vehicle_action_oneof": "mediaPreviousFavorite"
  },
  {
    "args": [
      2
    ],
    "decoded_reply": {
      "response": {
        "reason": "",
        "result": true
      }
    },
    "fields": {
      "sound": 2
    },
    "method_called": "remote_boombox",
    "routed_domain": "DOMAIN_INFOTAINMENT",
    "vehicle_action_oneof": "boomboxAction"
  }
]

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.

  • uv run pytest tests/test_ble_mocked_media_commands.py
  • uv run pytest tests
  • python - <<'PY' ... evidence generation attempt from repo root, which failed because python was not on PATH
  • uv run python - <<'PY' ... evidence generation attempt from tests/, which exposed and corrected a bad evidence-script assumption about a non-existent proto oneof
  • uv run python - <<'PY' ... from tests/ to call adjust_volume, media_volume_up, media_volume_down, media_toggle_playback, media_next_track, media_prev_track, media_next_fav, media_prev_fav, and remote_boombox through VehicleBluetooth mocked transport, decrypt the sent command, and write payload evidence
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@Bre77
Bre77 force-pushed the fm/tfa-ble-pr6-media-v8 branch from 1c0af0f to 6267027 Compare July 9, 2026 11:16
firstmate crewmate added 4 commits July 9, 2026 21:20
Regression tests for adjust_volume, media_volume_up/down,
media_toggle_playback, media_next/prev_track, media_next/prev_fav, and
remote_boombox (captain-present-only, mocked transport only).

Live-verify against the test car is blocked tonight by BLE transport
reliability (GATT write-response timeouts / error 133 on the proxy rig) -
see the status file for evidence. Document the discovered media
state-observability gap (Spotify leaves MediaState/MediaDetailState track
fields empty) in AGENTS.md for the next live-verify attempt.
…finding

Two further fresh-connection retries (per firstmate guidance) reproduced the
same GATT write-response timeout on the first signed-command write; a
same-session plain read succeeded immediately after. Car state reconfirmed
unmutated. Not forcing further live attempts tonight - shipping the green
mocked-transport suite and deferring live-verify pending a stable connection.
@Bre77
Bre77 force-pushed the fm/tfa-ble-pr6-media-v8 branch from 6267027 to e22c230 Compare July 9, 2026 11:20
@Bre77
Bre77 merged commit 2395c81 into main Jul 9, 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