7.5 KiB
7.5 KiB
TV Power Coordination Task List (Server + Client)
Goal
Prevent unintended TV power-off during adjacent events while enabling coordinated, server-driven power intent via MQTT with robust client-side fallback.
Scope
- Server publishes explicit TV power intent and event-window context.
- Client executes HDMI-CEC power actions with timer-safe behavior.
- Client falls back to local schedule/end-time logic if server intent is missing or stale.
- Existing event playback behavior remains backward compatible.
Ownership Proposal
- Server team: Scheduler integration, power-intent publisher, reliability semantics.
- Client team: MQTT handler, state machine, CEC execution, fallback and observability.
Server PR-1 Pointer
- For the strict, agreed server-first implementation path, use:
TV_POWER_SERVER_PR1_IMPLEMENTATION_CHECKLIST.md
- Treat that checklist as the execution source of truth for Phase 1.
1. MQTT Contract (Shared Spec)
Phase-1 scope note:
- Group-level power intent is the only active server contract in Phase 1.
- Per-client power intent and client power state topics are deferred to Phase 2.
1.1 Topics
- Command/intent topic (retained):
- infoscreen/groups/{group_id}/power/intent
Phase-2 (deferred):
- Optional per-client command/intent topic (retained):
- infoscreen/{client_id}/power/intent
- Client state/ack topic:
- infoscreen/{client_id}/power/state
1.2 QoS and retain
- intent topics: QoS 1, retained=true
- state topic: QoS 0 or 1 (recommend QoS 0 initially), retained=false (Phase 2)
1.3 Intent payload schema (v1)
{
"schema_version": "1.0",
"intent_id": "uuid-or-monotonic-id",
"group_id": 12,
"desired_state": "on",
"reason": "active_event",
"issued_at": "2026-03-31T12:00:00Z",
"expires_at": "2026-03-31T12:01:30Z",
"poll_interval_sec": 15,
"event_window_start": "2026-03-31T12:00:00Z",
"event_window_end": "2026-03-31T13:00:00Z",
"source": "scheduler"
}
1.4 State payload schema (client -> server)
Phase-2 (deferred).
{
"schema_version": "1.0",
"intent_id": "last-applied-intent-id",
"client_id": "...",
"reported_at": "2026-03-31T12:00:01Z",
"power": {
"applied_state": "on",
"source": "mqtt_intent|local_fallback",
"result": "ok|skipped|error",
"detail": "free text"
}
}
1.5 Idempotency and ordering rules
- Client applies only newest valid intent by issued_at then intent_id tie-break.
- Duplicate intent_id must be ignored after first successful apply.
- Expired intents must not trigger new actions.
- Retained intent must be immediately usable after client reconnect.
1.6 Safety rules
- desired_state=on cancels any pending delayed-off timer before action.
- desired_state=off may schedule delayed-off, never immediate off during an active event window.
- If payload is malformed, client logs and ignores it.
2. Server Team Task List
2.1 Contract + scheduler mapping
- Finalize field names and UTC timestamp format with client team.
- Define when scheduler emits on/off intents for adjacent/overlapping events.
- Ensure contiguous events produce uninterrupted desired_state=on coverage.
2.2 Publisher implementation
- Add publisher for infoscreen/groups/{group_id}/power/intent.
- Support retained messages and QoS 1.
- Include expires_at based on scheduler poll interval (
max(3 x poll, 90s)). - Emit new intent_id only for semantic state transitions.
2.3 Reconnect and replay behavior
- On scheduler restart, republish current effective intent as retained.
- On event edits/cancellations, publish replacement retained intent.
2.4 Conflict policy
- Phase 1: not applicable (group-only intent).
- Phase 2: define precedence when both group and per-client intents exist.
- Recommended for Phase 2: per-client overrides group intent.
2.5 Monitoring and diagnostics
- Record publish attempts, broker ack results, and active retained payload.
- Add operational dashboard panels for intent age and last transition.
2.6 Server acceptance criteria
- Adjacent event windows do not produce off intent between events.
- Reconnect test: fresh client receives retained intent and powers correctly.
- Expired intent is never acted on by a conforming client.
3. Client Team Task List
3.1 MQTT subscription + parsing
- Phase 1: Subscribe to infoscreen/groups/{group_id}/power/intent.
- Phase 2 (optional): Subscribe to infoscreen/{client_id}/power/intent for per-device overrides.
- Parse schema_version=1.0 payload with strict validation.
3.2 Power state controller integration
- Add power-intent handler in display manager path that owns HDMI-CEC decisions.
- On desired_state=on:
- cancel delayed-off timer
- call CEC on only if needed
- On desired_state=off:
- schedule delayed off using configured grace_seconds (or local default)
- re-check active event before executing off
3.3 Fallback behavior (critical)
- If MQTT unreachable, intent missing, invalid, or expired:
- fall back to existing local event-time logic
- use event end as off trigger with existing delayed-off safety
- If local logic sees active event, enforce cancel of pending off timer.
3.4 Adjacent-event race hardening
- Guarantee pending off timer is canceled on any newly active event.
- Ensure event switch path never requests off while next event is active.
- Add explicit logging for timer create/cancel/fire with reason and event_id.
3.5 State publishing
- Publish apply results to infoscreen/{client_id}/power/state.
- Include source=mqtt_intent or local_fallback.
- Include last intent_id and result details for troubleshooting.
3.6 Config flags
- Add feature toggle:
- POWER_CONTROL_MODE=local|mqtt|hybrid (recommend default: hybrid)
- hybrid behavior:
- prefer valid mqtt intent
- automatically fall back to local logic
3.7 Client acceptance criteria
- Adjacent events: no unintended off between two active windows.
- Broker outage during event: TV remains on via local fallback.
- Broker recovery: retained intent reconciles state without oscillation.
- Duplicate/old intents do not cause repeated CEC toggles.
4. Integration Test Matrix (Joint)
4.1 Happy paths
- Single event start -> on intent -> TV on.
- Event end -> off intent -> delayed off -> TV off.
- Adjacent events (end==start or small gap) -> uninterrupted TV on.
4.2 Failure paths
- Broker down before event start.
- Broker down during active event.
- Malformed retained intent at reconnect.
- Delayed off armed, then new event starts before timer fires.
4.3 Consistency checks
- Client state topic reflects actual applied source and result.
- Logs include intent_id correlation across server and client.
5. Rollout Plan
Phase 1: Contract and feature flags
- Freeze schema and topic naming for group-only intent.
- Ship client support behind POWER_CONTROL_MODE=hybrid.
Phase 2: Server publisher rollout
- Enable publishing for test group only.
- Verify retained and reconnect behavior.
Phase 3: Production enablement
- Enable hybrid mode fleet-wide.
- Observe for 1 week: off-between-adjacent-events incidents must be zero.
Phase 4: Optional tightening
- If metrics are stable, evaluate mqtt-first policy while retaining local safety fallback.
6. Definition of Done
- Shared MQTT contract approved by both teams.
- Server and client implementations merged with tests.
- Adjacent-event regression test added and passing.
- Operational runbook updated (topics, payloads, fallback behavior, troubleshooting).
- Production monitoring confirms no unintended mid-schedule TV power-off.