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>
This commit is contained in:
LeviandClaude Opus 4.7 committed 2026-04-17 17:04:30 -05:00
commit 0ad51879ae
24 files changed
+2538

No files matched your search

+60
View File
@@ -0,0 +1,60 @@
"""Power monitoring helpers — discover sibling sensors from a power switch entity."""
import logging
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
_LOGGER = logging.getLogger(__name__)
# Map unit_of_measurement to a friendly key
_UNIT_TO_KEY = {
"W": "power_w",
"kWh": "energy_kwh",
"V": "voltage_v",
"A": "current_a",
}
def discover_power_siblings(
hass: HomeAssistant, power_entity_id: str
) -> dict[str, str]:
"""Given a power switch entity_id, find sibling sensor entities on the same device.
Returns a dict like:
{
"switch": "switch.wall_plug_switch",
"power_w": "sensor.wall_plug_switch_electric_consumption_w",
"energy_kwh": "sensor.wall_plug_switch_electric_consumption_kwh",
"voltage_v": "sensor.wall_plug_switch_electric_consumption_v",
"current_a": "sensor.wall_plug_switch_electric_consumption_a",
}
"""
registry = er.async_get(hass)
result = {"switch": power_entity_id}
# Find the device_id for the power entity
power_entry = registry.async_get(power_entity_id)
if not power_entry or not power_entry.device_id:
_LOGGER.debug("Power entity %s has no device_id", power_entity_id)
return result
device_id = power_entry.device_id
# Find all sensor siblings on the same device
for entry in registry.entities.values():
if entry.device_id != device_id:
continue
if entry.domain != "sensor":
continue
if entry.disabled_by is not None:
continue
unit = entry.unit_of_measurement
if unit in _UNIT_TO_KEY:
key = _UNIT_TO_KEY[unit]
if key not in result: # first match wins
result[key] = entry.entity_id
_LOGGER.debug("Power siblings for %s: %s", power_entity_id, result)
return result