Files
ha-nvidia-shield/custom_components/nvidia_shield/ha_adb_common/intent.py
T
LeviandClaude Opus 4.7 0ad51879ae Initial release v0.1.0
Home Assistant custom integration for NVIDIA Shield TV that composes
the Android TV Remote, Jellyfin, smart plug, and receiver entities
into a single unified media player with ADB-based now-playing from
any app. Part of the Media Zone ecosystem.

Entities:
- media_player: power (with smart plug fallback), transport, input,
  volume routed to receiver, rich stream info overlay when Jellyfin
  is active
- sensor: DAG attributes and stream info
- button: Pair ADB

Config:
- Two-step flow: basic setup + optional ADB pairing on the Shield
- Configurable ADB port (default 5555)
- Pick an existing Jellyfin media_player entity — stream info is read
  from the HA Jellyfin integration's own DataUpdateCoordinator, so
  no server URL / API key / extra config needed here
- Privacy mode (adb_store_app_info=False) suppresses non-Jellyfin
  media details, showing only the app name

Ecosystem:
- Exposes media_dag_* attributes for ha-media-zone orchestration
- Exposes media_dag_running_apps and async_bring_to_foreground for
  the Media Zone card's app switcher

Shared ADB code lives in ltomes/ha-adb-common and is vendored at
custom_components/nvidia_shield/ha_adb_common/ for HACS installs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 17:04:30 -05:00

49 lines
1.5 KiB
Python

"""Playback intent tracking for optimistic UI updates.
Bridges the gap between instant commands and slow state polling.
"""
import time
from dataclasses import dataclass
@dataclass
class PlaybackIntent:
"""A pending user intent for playback state.
Attributes:
target_state: The MediaPlayerState we expect after the command.
command: The service/command name (for retries and logging).
created_at: Monotonic timestamp when the intent was created.
prior_state: The source state before the intent (for detecting external overrides).
retry_count: Number of retries attempted so far.
"""
target_state: str # MediaPlayerState value (e.g. "playing", "paused")
command: str
created_at: float
prior_state: str | None = None
retry_count: int = 0
@classmethod
def create(cls, target_state: str, command: str, prior_state: str | None = None) -> "PlaybackIntent":
return cls(
target_state=target_state,
command=command,
created_at=time.monotonic(),
prior_state=prior_state,
)
@property
def age_seconds(self) -> float:
return round(time.monotonic() - self.created_at, 1)
def to_debug_dict(self) -> dict:
"""Serialize for the _intent debug attribute."""
return {
"target": self.target_state,
"command": self.command,
"retries": self.retry_count,
"age_s": self.age_seconds,
}