# 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) ```json { "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 1. Add scheduler mapping layer that computes effective desired_state per client timeline. 2. Add intent publisher with retained QoS1 delivery. 3. Generate unique intent_id for each semantic transition. 4. Emit issued_at/expires_at and event_window consistently in UTC. 5. Add group-vs-client precedence logic. 6. Add logs/metrics for publish success, retained payload age, and transition count. 7. Add integration tests for adjacent events and reconnect replay. ## Acceptance Criteria 1. Adjacent events do not create OFF gap intents. 2. Fresh client receives retained intent after reconnect and gets correct desired state. 3. Intent payloads are schema-valid, UTC-formatted, and include expiry. 4. 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.