shrink root README into a landing page with a docs map and focused contributor guidance add TV_POWER_RUNBOOK as the canonical TV power rollout and canary runbook add CHANGELOG and move project history out of README-style docs refactor src README into a developer-focused guide (architecture, runtime files, MQTT, debugging) prune redundant older HDMI docs and keep a canonical HDMI_CEC_SETUP path update copilot instructions to a high-signal policy format with strict anti-shadow-README design rules align references across docs to current files, scripts, and TV power behavior
3.1 KiB
3.1 KiB
Client Handoff: TV Power Coordination
Purpose
Implement robust client-side TV power control that applies server MQTT intents when valid and falls back to local event timing when server/broker data is missing or stale.
Source of Truth
- Shared full plan: TV_POWER_COORDINATION_TASKLIST.md
Scope (Client Team)
- Intent subscription/validation
- CEC state transitions and timer cancellation safety
- Hybrid fallback using local event windows
- Power state acknowledgment publishing
MQTT Contract (Client Responsibilities)
Subscribe
- infoscreen/{client_id}/power/intent
- Optional: infoscreen/groups/{group_id}/power/intent
Publish state
- infoscreen/{client_id}/power/state
State Payload (v1)
{
"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"
}
}
Required Runtime Rules
Intent Validation and Ordering
- Accept only schema_version=1.0 (or explicitly version-gated supported set).
- Ignore malformed payloads.
- Ignore expired intents (expires_at in past).
- Apply only newest valid intent by issued_at, intent_id tie-break.
- Deduplicate already-applied intent_id.
Power Action Safety
- desired_state=on:
- cancel pending delayed-off timer immediately
- turn on via CEC only if needed
- desired_state=off:
- schedule delayed off (grace_seconds or local default)
- re-check active event before executing actual off
Fallback (Critical)
- If MQTT unavailable, intent missing, invalid, or stale:
- use existing local event start/end logic
- use event end as off trigger plus delayed-off safety
- Any active event must cancel pending off timers.
Configuration
- Add POWER_CONTROL_MODE with values:
- local
- mqtt
- hybrid (recommended default)
Hybrid Mode
- Prefer valid MQTT intent.
- Automatically fall back to local schedule logic when intent channel is not trustworthy.
Implementation Tasks
- Add intent topic handlers and schema validation.
- Integrate intent application into display power control path.
- Add timer race hardening for adjacent event transitions.
- Add fallback decision branch for stale/missing intents.
- Add power state publisher with intent_id/source/result.
- Add logs for timer arm/cancel/fire with reason and event_id.
- Add tests for adjacent events, broker outage, reconnect, duplicate intent.
Acceptance Criteria
- No unintended TV off between adjacent events.
- Broker outage during active event does not power off TV prematurely.
- Reconnect with retained intent reconciles state without oscillation.
- Duplicate/old intents do not trigger repeated CEC toggles.
- State messages clearly show mqtt_intent vs local_fallback source.
Target Integration Points
- Main runtime orchestration: src/display_manager.py
- MQTT plumbing and topic handlers: src/simclient.py
Operational Notes
- Keep fallback logic enabled even after MQTT rollout.
- Ensure all new timestamps are UTC ISO format.