Files
infoscreen/docs/archive/TV_POWER_PHASE_1_SERVER_HANDOFF.md

1.9 KiB

Server Handoff: TV Power Coordination

Status

Server PR-1 is implemented and merged (Phase 1).

Source of Truth

  • Contract: TV_POWER_INTENT_SERVER_CONTRACT_V1.md
  • Implementation: scheduler/scheduler.py and scheduler/db_utils.py
  • Validation checklist: TV_POWER_PHASE_1_CANARY_VALIDATION.md

Active Phase 1 Scope

  • Topic: infoscreen/groups/{group_id}/power/intent
  • QoS: 1
  • Retained: true
  • Scope: group-level only
  • Per-client intent/state topics: deferred to Phase 2

Publish Semantics (Implemented)

  • Semantic transition (desired_state or reason changed): new intent_id and immediate publish
  • Heartbeat (no semantic change): same intent_id, refreshed issued_at and expires_at
  • Scheduler startup: immediate publish before first poll wait
  • MQTT reconnect: immediate retained republish of cached intents

Payload Contract (Phase 1)

{
  "schema_version": "1.0",
  "intent_id": "uuid4",
  "group_id": 12,
  "desired_state": "on",
  "reason": "active_event",
  "issued_at": "2026-04-01T06:00:03.496Z",
  "expires_at": "2026-04-01T06:01:33.496Z",
  "poll_interval_sec": 15,
  "active_event_ids": [148],
  "event_window_start": "2026-04-01T06:00:00Z",
  "event_window_end": "2026-04-01T07:00:00Z"
}

Expiry rule:

  • expires_at = issued_at + max(3 x poll_interval_sec, 90 seconds)

Operational Notes

  • Adjacent/overlapping events are merged into one active coverage window; no OFF blip at boundaries.
  • Feature flag defaults are safe for rollout:
    • POWER_INTENT_PUBLISH_ENABLED=false
    • POWER_INTENT_HEARTBEAT_ENABLED=true
    • POWER_INTENT_EXPIRY_MULTIPLIER=3
    • POWER_INTENT_MIN_EXPIRY_SECONDS=90
  • Keep this handoff concise and defer full details to the stable contract document.

Phase 2 (Deferred)

  • Per-client override topic: infoscreen/{client_uuid}/power/intent
  • Client power state topic and acknowledgments
  • Listener persistence of client-level power state