Commit Graph
6 Commits
Author SHA1 Message Date
James Mackay 75ebeb40b0 refactor(config): one Shield IP field for both transports (t41)
The two address fields were the same Shield spelled twice, and every bug in the
zeroconf/IP-change path came from keeping them in sync. One field now:

* const.CONF_HOST replaces CONF_ADB_HOST / CONF_PROTOCOL_HOST in the setup form,
  the options page, the pairing forms, the reconfigure/reauth seeding and the
  description copy. ADB port 5555 stays the only port field;
* helpers.entry_host(entry) is the single resolver (options first, then data);
  resolve_adb_config and the protocol settings both go through it, so both
  transports read the same value at call time (the t32 F1 factory re-read keeps
  working: the NEXT built poller sees the new address);
* helpers.seed_host / seed_adb_enabled own the YAML seed's shape rule. A block
  may use `host` or the legacy protocol_host/adb_host keys — t41 keeps the old
  spelling working — and t32 F4's outcome is unchanged: a protocol-only block
  leaves ADB off, an address (or an explicit adb_enabled) turns it on;
* the zeroconf IP-change path collapses the t21-F2 per-host dance into one rule:
  the discovery address IS the entry's address, so the entry is updated when it
  differs and left alone when it matches. The blank-self-heal and
  deliberately-different-ADB-host cases are gone with the duplication — a
  second address field cannot express them anymore, and the tests now pin that
  (previously "an explicit override is never clobbered");
* the options page exposes the protocol toggle it never had (the page could turn
  ADB off but not the protocol);
* button.py (granted to this task) reads the entry's own address instead of
  another integration's entity.

The v3 entry migration that maps existing adb_host/protocol_host onto CONF_HOST
and drops the androidtv key lands in the next commit; HA runs migrations before
setup, so an existing entry is never read with the old shape.

Verified: 311 passed / 2 skipped, 312 / 1 with androidtvremote2, ruff clean,
drift engine exit 0 on HEAD. The UI-copy contract tests (every rendered field
has a label in strings.json AND translations/en.json, key trees identical, host
errors name the field) drove the string edits.
2026-10-11 06:18:22 +01:00
James Mackay 86aa2827a2 refactor(config): drop the androidtv media_player entity path end-to-end (t41)
The user ruling: this integration REPLACES both old integrations, so nothing may
depend on an androidtv/androidtv_remote entity anymore.

Removed:
* the setup-form field + its entity selector (CONF_ANDROIDTV_ENTITY is no longer
  offered, only read by the migration that drops it);
* the entity-derived unique_id derivation (_unique_id_from_atv_device, t29 G2)
  and, with it, every registry lookup for another integration's devices — the
  user step now sets NO unique_id at all; the protocol MAC learned during
  pairing is the identity;
* the Jellyfin auto-detect's second tier (the atv entity's friendly_name) — it
  now uses the entry name the user typed or the device name from discovery;
* the app-name and app-id tiers (media_player.app_name/app_id + the shared
  resolve_app_name chain, the Current App sensor, the sensor's state-change
  listener and its `_androidtv_state` helper) — the manager's store is the only
  source;
* the "transitional external entity" command tier in every path: `_cmd` and the
  pan-media_player service call are gone, and so is the fallback in _media_cmd,
  _remote_key_cmd, the §7 channel-digit sequence and the intent self-heal retry
  (an intent no transport served now surrenders to the truth instead of
  delegating);
* the entity-derived power signal (`_on_source_change`'s "device off clears the
  intent" check no longer watches another integration's entity; the power
  LADDER — protocol is_on → ADB wake → power switch — is unchanged).

turn_on/turn_off are native now: they send the protocol POWER key and, like the
remote entity, send nothing when the known state already matches (no superfluous
toggle). An ADB-only entry (protocol skipped) has no power write path — the
manager owns the socket and exposes no device-keyevent, which is what the old
delegation used to cover.

helpers.discover_adb_host — the one helper that derived a host from another
integration's config entry — is deleted; button.py (granted to this task) reads
the entry's own address fields instead of the entity, so the Pair ADB button
keeps working.

Present-day entries that still carry the key are unaffected (nothing reads it);
the v3 migration that drops it lands with the host unification.

Verified: 309 passed / 2 skipped, 310 / 1 with androidtvremote2, ruff clean,
drift engine exit 0 on HEAD (13 modules, 58 imports, 35 call arguments, 6
awaited HA calls) and 16 passed in the real-HA drift suite. The stub harness's
legacy service recorder became a watchdog: any HA service call from the media
player now fails the routing tests instead of being the expected outcome.
2026-10-11 06:09:43 +01:00
James Mackay 194a97ce34 feat(button,media_player): Pair ADB carries entity_category CONFIG (t30 G11) + BrowseMediaSource domain parameter at root and children (t30 G18, 2026-05-20 blog contract); stubs/tests pin both 2026-10-09 07:17:14 +01:00
James Mackay 6b4227cb40 refactor: centralize ADB host/key resolution in helpers.py; drop the three duplicated resolvers 2026-10-08 07:48:30 +01:00
James Mackay d3afda0a25 fix: make ADB poll failures visible and stop stale-state cling; cancel tracked poll tasks on unload (B2, B5-prep); lint cleanups across daemon modules 2026-10-08 07:45:45 +01:00
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