2.7 KiB
2.7 KiB
Server Handoff: TV Power Coordination
Purpose
Implement server-side MQTT power intent publishing so clients can keep TVs on across adjacent events and power off safely after schedules end.
Source of Truth
- Shared full plan: TV_POWER_COORDINATION_TASKLIST.md
Scope (Server Team)
- Scheduler-to-intent mapping
- MQTT publishing semantics (retain, QoS, expiry)
- Conflict handling (group vs client)
- Observability for intent lifecycle
MQTT Contract (Server Responsibilities)
Topics
- Primary (per-client): infoscreen/{client_id}/power/intent
- Optional (group-level): infoscreen/groups/{group_id}/power/intent
Delivery Semantics
- QoS: 1
- retained: true
- Always publish UTC timestamps (ISO 8601 with Z)
Intent Payload (v1)
{
"schema_version": "1.0",
"intent_id": "uuid-or-monotonic-id",
"issued_at": "2026-03-31T12:00:00Z",
"expires_at": "2026-03-31T12:10:00Z",
"target": {
"client_id": "optional-if-group-topic",
"group_id": "optional"
},
"power": {
"desired_state": "on",
"reason": "event_window_active",
"grace_seconds": 30
},
"event_window": {
"start": "2026-03-31T12:00:00Z",
"end": "2026-03-31T13:00:00Z"
}
}
Required Behavior
Adjacent/Overlapping Events
- Never publish an intermediate off intent when windows are contiguous/overlapping.
- Maintain continuous desired_state=on coverage across adjacent windows.
Reconnect/Restart
- On scheduler restart, republish effective retained intent.
- On event edits/cancellations, replace retained intent with a fresh intent_id.
Conflict Policy
- If both group and client intent exist: per-client overrides group.
Expiry Safety
- expires_at must be set for every intent.
- Server should avoid publishing already-expired intents.
Implementation Tasks
- Add scheduler mapping layer that computes effective desired_state per client timeline.
- Add intent publisher with retained QoS1 delivery.
- Generate unique intent_id for each semantic transition.
- Emit issued_at/expires_at and event_window consistently in UTC.
- Add group-vs-client precedence logic.
- Add logs/metrics for publish success, retained payload age, and transition count.
- Add integration tests for adjacent events and reconnect replay.
Acceptance Criteria
- Adjacent events do not create OFF gap intents.
- Fresh client receives retained intent after reconnect and gets correct desired state.
- Intent payloads are schema-valid, UTC-formatted, and include expiry.
- Publish logs and metrics allow intent timeline reconstruction.
Operational Notes
- Keep intent publishing idempotent and deterministic.
- Preserve backward compatibility while clients run in hybrid mode.