Files
Tobias GesellchenandClaude Opus 4.8 603765b644 test(http-client): broaden speaker-contract coverage from recordings (refs #451)
Build the regression net the API route layout note calls for, before any
route refactoring: mine real recorded speaker traffic (Bose_Lisa UA) into a
coverage checklist and fill the high-priority, dependency-free gaps.

- COVERAGE.md: inventory of frozen speaker routes (method + status) mapped to
  covering .http files, with the remaining gaps classified by priority.
- New flows, all asserting status/content-type/structure with the firmware UA:
  - GET  /v1/auth                              (app-key probe)
  - POST /v1/scmudc/{deviceId}                 (telemetry upload)
  - GET  /core02/.../orion/station             (Orion custom-stream adapter)
  - GET  /custom/v1/playback/{encodedURL}      (LOCAL_INTERNET_RADIO / ding)
  - POST /bmx/tunein/v1/report                 (STOP -> {}, START -> nextReportIn)
  - GET  /media/aftertouch-ding.wav            (binary: status + content-type)
  - GET  /media/bmx-icons/{provider}/{file}    (binary: status + content-type)

All request/response values use placeholder / RFC-5737 data; no recorded
bodies are committed. make test-http-client: 57 requests, 0 failed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 19:11:24 +02:00

26 lines
1.3 KiB
HTTP

### GET /custom/v1/playback/{encodedURL} (LOCAL_INTERNET_RADIO / ding / TTS replay)
###
### Frozen route. The speaker replays presets/notifications whose stored location
### is /custom/v1/playback/<base64 stream URL>; the service decodes it and returns
### playable audio JSON pointing at that URL (HandleCustomPlayback ->
### bmx.BuildCustomStreamResponse). Pure decode, no upstream call.
###
### encodedURL decodes to: http://192.0.2.10:8000/stream
GET {{host}}/custom/v1/playback/aHR0cDovLzE5Mi4wLjIuMTA6ODAwMC9zdHJlYW0=?name=Doc%20Radio
User-Agent: Bose_Lisa/27.0.6
Accept: */*
> {%
client.test("Response is 200 OK with JSON", function() {
client.assert(response.status === 200, "Response status is not 200, got " + response.status);
client.assert(response.contentType.mimeType === "application/json",
"Expected application/json, got '" + response.contentType.mimeType + "'");
});
client.test("Response echoes the decoded stream URL as playable audio", function() {
client.assert(response.body.hasOwnProperty("audio"), "Response missing 'audio'");
client.assert(response.body.audio.streamUrl === "http://192.0.2.10:8000/stream",
"audio.streamUrl should echo the decoded URL, got '" + response.body.audio.streamUrl + "'");
});
%}