docs(api-reference): status/playback is republished on every MQTT connect (firmware F-066)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-29 20:11:20 +03:00
co-authored by Claude Opus 5.5
parent adec979182
commit 9d9b46056a
@@ -19,7 +19,7 @@ const TRANSPORTS_V2 = [
{ transport: 'MQTT', address: 'vesper/{device_id}/control/ack', direction: 'Outbound, QoS 1', switch: 'command', notes: 'Strictly replies to commands (incl. pong) — nothing unsolicited is ever published here. Echoes req_id when the request sent one.' }, { transport: 'MQTT', address: 'vesper/{device_id}/control/ack', direction: 'Outbound, QoS 1', switch: 'command', notes: 'Strictly replies to commands (incl. pong) — nothing unsolicited is ever published here. Echoes req_id when the request sent one.' },
{ transport: 'MQTT', address: 'vesper/{device_id}/control/reports', direction: 'Outbound, QoS 1', switch: 'reports', notes: 'Critical, unsolicited, time-sensitive board-initiated events (e.g. bell_overload). Not retained.' }, { transport: 'MQTT', address: 'vesper/{device_id}/control/reports', direction: 'Outbound, QoS 1', switch: 'reports', notes: 'Critical, unsolicited, time-sensitive board-initiated events (e.g. bell_overload). Not retained.' },
{ transport: 'MQTT', address: 'vesper/{device_id}/status/heartbeat', direction: 'Outbound, retained, QoS 1', switch: 'heartbeat', notes: 'Every 30 s. Also carries LWT — broker publishes {"state":"offline","ok":false} on an unclean disconnect.' }, { transport: 'MQTT', address: 'vesper/{device_id}/status/heartbeat', direction: 'Outbound, retained, QoS 1', switch: 'heartbeat', notes: 'Every 30 s. Also carries LWT — broker publishes {"state":"offline","ok":false} on an unclean disconnect.' },
{ transport: 'MQTT', address: 'vesper/{device_id}/status/playback', direction: 'Outbound, retained, QoS 1', switch: 'playback', notes: 'Playback state transitions (playing/paused/stopping/idle) with pid, speed, duration, started_at, source, ts. Published on transition, not polled. Source of truth for what the board is doing.' }, { transport: 'MQTT', address: 'vesper/{device_id}/status/playback', direction: 'Outbound, retained, QoS 1', switch: 'playback', notes: 'Playback state transitions (playing/paused/stopping/idle) with pid, speed, duration, started_at, source, ts. Published on transition, not polled — plus on every MQTT (re)connect with the current real state, so a stale retained "playing" never outlives a reboot. Source of truth for what the board is doing.' },
{ transport: 'MQTT', address: 'vesper/{device_id}/system/alerts', direction: 'Outbound, retained until cleared, QoS 1', switch: 'alerts', notes: 'Subsystem state changes (WARNING / CRITICAL / FAILED / CLEARED). Published on transition only.' }, { transport: 'MQTT', address: 'vesper/{device_id}/system/alerts', direction: 'Outbound, retained until cleared, QoS 1', switch: 'alerts', notes: 'Subsystem state changes (WARNING / CRITICAL / FAILED / CLEARED). Published on transition only.' },
{ transport: 'MQTT', address: 'vesper/{device_id}/system/info', direction: 'Outbound, retained, QoS 1', switch: 'info', notes: 'Discrete system events, e.g. boot_report on every boot.' }, { transport: 'MQTT', address: 'vesper/{device_id}/system/info', direction: 'Outbound, retained, QoS 1', switch: 'info', notes: 'Discrete system events, e.g. boot_report on every boot.' },
{ transport: 'MQTT', address: 'vesper/{device_id}/system/logs', direction: 'Outbound, QoS 0', switch: 'logs', notes: 'Full log stream, mirrors serial output. Also gated by the log.set_mqtt level, independently of this switch.' }, { transport: 'MQTT', address: 'vesper/{device_id}/system/logs', direction: 'Outbound, QoS 0', switch: 'logs', notes: 'Full log stream, mirrors serial output. Also gated by the log.set_mqtt level, independently of this switch.' },
@@ -1850,7 +1850,7 @@ function TransportsV2() {
</div> </div>
</Card> </Card>
<Card title="Playback Payload" subtitle="Published on every playback transition to vesper/{device_id}/status/playback — retained, QoS 1"> <Card title="Playback Payload" subtitle="Published on every playback transition, and on every MQTT (re)connect, to vesper/{device_id}/status/playback — retained, QoS 1">
<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-4)' }}> <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-4)' }}>
<MonoBlock code={'{\n "action": "playing",\n "time_elapsed": 12,\n "projected_run_time": 45000,\n "pid": "westminster",\n "speed": 400,\n "duration": 120000,\n "started_at": 1790000000,\n "source": "app",\n "ts": 1790000012\n}\n\n// idle\n{ "action": "idle", "time_elapsed": 0, "projected_run_time": 0, "pid": "", "speed": 0, "duration": 0, "started_at": 0, "source": "", "ts": 1790000130 }'} /> <MonoBlock code={'{\n "action": "playing",\n "time_elapsed": 12,\n "projected_run_time": 45000,\n "pid": "westminster",\n "speed": 400,\n "duration": 120000,\n "started_at": 1790000000,\n "source": "app",\n "ts": 1790000012\n}\n\n// idle\n{ "action": "idle", "time_elapsed": 0, "projected_run_time": 0, "pid": "", "speed": 0, "duration": 0, "started_at": 0, "source": "", "ts": 1790000130 }'} />
<p style={{ margin: 0, fontSize: 'var(--font-size-sm)', color: 'var(--color-text-secondary)' }}> <p style={{ margin: 0, fontSize: 'var(--font-size-sm)', color: 'var(--color-text-secondary)' }}>