2026-04-17 17:04:30 -05:00
2026-04-17 17:04:30 -05:00
2026-04-17 17:04:30 -05:00

NVIDIA Shield

Home Assistant integration for the NVIDIA Shield TV — ADB media session tracking for now-playing state from any app, plus Google remote-protocol commands, Jellyfin rich metadata, and power monitoring.

This is a Shield-only fork of ltomes/ha-nvidia-shield (early 0.1.x), rebuilt around a different architecture: one integration, one device, ADB as the state source, and no dependency on separate androidtv / androidtv_remote integrations.

Status: early fork, actively rebuilt. Releases are date-based (v2026.10.08). Expect rough edges until the MVP phases land. The build-out plan is in docs/MVP_PLAN.md; device research is in docs/RESEARCH_SHIELD.md.

What we're building (the fork's goals)

The fork exists to make a single integration own the Shield end-to-end:

  1. Event-driven ADB media session tracking as the primary playback state source — dumpsys media_session over a persistent connection, not screen capture, not 10-second polling.
  2. Fallback state for apps without media sessions — e.g. TiviMate publishes none at all; foreground-app detection (mResumedActivity) + last-known-state
    • the "audio playback" hint from the same session dump close that gap.
  3. All-in-one device — absorb the Google remote protocol (androidtvremote2): a remote entity alongside the media player, play_media with media_content_type: channel for TiviMate channel-by-number, absolute volume, focused-app push events. ADB stays the playback-state source; ADB pairing stays intact.
  4. Retire the surrounding glue — the mediasession2mqtt bridge, universal media player templates, and external remote entity reading all become native integration behavior.

Phases 0–4 with files, risks, and definitions of done live in docs/MVP_PLAN.md.

Current features (inherited from upstream 0.1.x)

  • ADB Media Session — now-playing from any app that publishes a session (Spotify, Netflix, Plex, Wholphin, …)
  • Jellyfin rich metadata — title, series/episode, position, stream details (resolution, codec, HDR, audio format) via the HA Jellyfin integration's cache
  • Power monitoring — smart plug for reliable on/off with auto-discovered sibling sensors (watts, voltage, current)
  • Intent tracking — commands reflect in HA state immediately, self-heal against actual device state
  • Privacy mode — show only app name without media details for non-Jellyfin apps
  • Media DAG attributes — media_dag_* attributes for media-zone style orchestration

Changes inherited from upstream still apply in 0.1.x code: polling is timer-based, the ADB connection lives inside the media player entity, and fallback app state arrives in Phase 3.

State ladder and fallback semantics (Phase 3)

The media player state is decided top-down; each tier serves only when the ones above it are silent. Both transports live in the entry's ShieldConnectionManager (connection.py) — ADB is the state source, the remote protocol is the fast push/command path:

  1. Plug off — the power switch says off → off.
  2. Protocol power push (is_on) — False → off; None falls through.
  3. ADB wake (exact mWakefulness parse) — asleep → idle (standby).
  4. Intent — a just-sent command's target state, self-healing against reality within 30 s (retry goes over the transport that served it).
  5. Jellyfin — playing / paused while a Jellyfin session is active.
  6. ADB media session — playing / paused for apps that publish a session (foreground app preferred).
  7. Foreground fallback — an app is open (current_app protocol push, then the ADB mResumedActivity parse) but publishes no media session → on. Its identity comes from the TTL-capped last-known-state cache, the last channel entered, or the zero-cost "audio playback" hint (media recently active) — never resurrecting playing past the 60 s state TTL.
  8. On — powered, awake, nothing more specific.

TiviMate (ar.tvplayer.tv) is the documented no-session case: it publishes no MediaSession on Shield Android 11 (RESEARCH_SHIELD R2), so tiers 6–7 plus the audio hint are what keep it visible.

Migration from mediasession2mqtt + universal-player glue

The mediasession2mqtt bridge sensors and the universal media player YAML templates the fork replaces are retired by the ladder above: the media player entity already carries the DAG attributes (media_dag_running_apps with foreground/last-known enrichment, media_dag_now_playing with its source tag) that media-zone orchestration consumed from those sensors. See the appendix in docs/RESEARCH_SHIELD.md for the retirement mapping and the universal-player glue it replaces.

Releases

  • Date-based versioning: vYYYY.MM.DD (e.g. v2026.10.08).
  • Pushes to master on Gitea run the release workflow (.github/workflows/release.yml):
    • A plain push publishes the current day's release (same-day pushes are deduped).
    • Bumping version in custom_components/nvidia_shield/manifest.json forces that specific version's release before the date fallback kicks in.
  • Releases land on Gitea with the tag and a nvidia_shield.zip asset for manual installs. (No automatic mirroring — see the HACS note below.)

Installation

HACS

HACS only works with public GitHub repositories, so the Gitea repo cannot be added to HACS directly. If you set up a public GitHub mirror of the releases, add it as a custom repository:

  1. In HACS, open the overflow menu (⋮) → Custom repositories.
  2. Paste https://github.com/notexpectedyet/ha-nvidia-shield, pick type Integration, click Add.
  3. Find NVIDIA Shield in the HACS list and click Download.
  4. Restart Home Assistant.

Manual

Copy custom_components/nvidia_shield to your HA config/custom_components/ directory, restart, then add the integration from Settings → Devices & Services.

Configuration

  1. Settings > Devices & Services > Add Integration > "NVIDIA Shield"
  2. Select the Android TV Remote entity for your Shield
  3. Enable ADB if you want now-playing from all apps
  4. If ADB is enabled, the next step will pair — approve the prompt on the Shield
  5. Optionally configure Jellyfin, receiver, power switch

ADB Pairing

ADB is paired during setup via a dedicated config flow step. If you need to re-pair later (e.g. after factory reset), use the "Pair ADB" button on the device page in HA.

Requirements: Settings > Developer options > Network debugging enabled on the Shield.

Options

  • Jellyfin Media Player — auto-detected or manually selected
  • Receiver + Input — for media-zone coordination
  • Power Switch — smart plug entity
  • ADB Host/Port — override auto-detection if needed

Entities

Entity Type Description
Media Player media_player Main entity with playback controls and metadata
Current App sensor Currently running app
Now Playing sensor Formatted now-playing string
Pair ADB button Initiate or re-pair ADB connection

Development

  • Repository: Gitea — git.notexpectedyet.com/notexpectedyet/ha-nvidia-shield, branch master
  • CI/CD: Gitea Actions; every push to master releases (see .gitea/workflows/release.yml). Auth uses the job-provided GITEA_TOKEN — no extra secrets required.
  • Shared ADB helpers are vendored at custom_components/nvidia_shield/ha_adb_common/ (trimmed in this fork); dev extras in pyproject.toml (uv sync --extra dev).

License

MIT

S
Description
Home Assistant integration for NVIDIA Shield TV: ADB media session tracking, Jellyfin stream metadata, smart-plug power monitoring
Readme MIT
1.2 MiB
0 Stars 2 Watchers 0 Forks
v2026.10.12.2
Latest
2026-10-12 14:29:02 +01:00
Languages
Python 99.6%
Shell 0.4%