Commit Graph
4 Commits
Author SHA1 Message Date
James Mackay 9461d69469 fix(connection): a label dump that returned nothing is a FAILED fetch (t57 UNIT 0)
t59 F1 (HIGH). `ShieldAdbPoller.shell` swallows its error and answers None
(adb_client.py:144-155), and `_fetch_app_label` read that as "the dump
ran and found no label" → `cache_app_label(pkg, None)` → `('', stamp,
resolved=True)`. That is a DEFINITIVE negative for APP_LABEL_TTL = 24 h,
so after ONE transient failure `app_label()` never re-enqueued, exactly
one `pm dump` was ever attempted, and a later good dump could not
recover the label — `sensor.native_value` and `media_player.app_name`
stayed on the package id for every later render.

The dump now carries an exit marker (`; echo __NSH_EXIT:$?`), so the
three outcomes are distinguishable:

* output with an `application-label` → cache the label;
* output that ran and carried none (the marker is still there) → cache
  the empty string, the definitive negative that keeps t24 F1's
  zero-round-trip rule for a genuinely label-less package;
* no output at all (`None`, or blank) → cache NOTHING and let the next
  render re-enqueue, logged at debug.

The `resolved` flag goes with it: `cache_app_label` was its only writer
and always passed True, so an entry in `_app_labels` is now simply "a
fetch RAN" and the dead third field (`(label, stamp, True)`) is gone.

Tests drive the FakePoller-returns-None AND returns-'' shapes through
the sensor and through `media_player.app_name`, plus the label-less
package that must still be negatively cached. The stub poller now models
both real outcomes of a dump (an answer, or a transport that delivered
nothing) instead of conflating them — which is why the old tests could
only pin the raising-shell branch that already worked. 4 of the new
tests fail on the pre-fix tree, showing `('', stamp, True)` stamped.

Also in this commit:
- t59 F3: running_apps.py set `app["state"] = "paused"` twice — one line.
- t59 F4: no captured fixture contains state=6, so the "the Shield's own
  sessions report 6 like stock Android" wording in README and the
  media_session/media_player docstrings is reworded as INFERRED from the
  `state=PlaybackState {state=N, …}` line shape. A `git notes` entry on
  07682ff records the same correction against the t55 commit body.
2026-10-12 07:21:34 +01:00
James Mackay 07682ff082 feat(media_session): map Android PlaybackState 6 to buffering (t55)
The media session parser only understood states 2 (paused) and 3
(playing), so a session refilling its buffer (Android state 6, which the
Shield's own ExoPlayer/MediaSession sessions report exactly like stock
Android) read as "idle" or vanished into the foreground tier.

MediaSessionInfo gains an independent `buffering` flag (playing/paused/
buffering are now three flags off one integer), the session sort puts
buffering right behind playing — it is mid-playback, so it outranks a
paused session when the ladder picks one — and the running-apps
enrichment names a buffering live/last-known session "buffering" instead
of falling into "idle".

The MediaPlayerState stub gains BUFFERING and STANDBY so an in-suite
reference to a member real HA does not have fails here (real HA 2026.10
exposes off/on/idle/playing/paused/standby/buffering).
2026-10-12 06:52:58 +01:00
James Mackay 1f0a4b2021 feat(running_apps): media_dag_running_apps enrichment — TTL-capped last_known_state/last_known_title for apps without a live session (P3-3b) 2026-10-08 10:42:41 +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