fix(availability): F3 — any usable transport keeps the entities up (t40)
Reported from a live install: with ADB enabled but unreachable and a paired, healthy protocol transport, the media player went unavailable even though the protocol still served power/app/volume. The old rule was ``manager.connected or manager.awake is not None or not manager.available`` — i.e. "a configured ADB manager that is down ⇒ the whole entity is down" (t5-F2), which ignored transport B entirely. The ladder is now: * protocol transport wired and not reported unreachable — usable; * or ADB connected — usable; * or fresh wake data (the poller has spoken) — usable; * or a passive manager (no ADB configured at all) — usable, because nothing to transport is not a broken transport. Unavailable only when a CONFIGURED transport is actively down and no usable data exists. One implementation, ``entity_available`` (media_player.py), is used by the media player, the remote (whose ladder previously duplicated a weaker version of this rule) and the diagnostics payload. Diagnostics grew ``transport.entity_available`` plus ``adb.configured`` so a support dump answers "why is my entity unavailable?" — the ladder inputs and its verdict are now in the same place. Pinned by tests: the exact user case (ADB configured+down, protocol up ⇒ available), all-down (⇒ unavailable), wake-data rescue, connected ADB without a protocol, the passive manager, a configured-but-down transport with no data, the remote following the same ladder, and the diagnostics verdict. Verified: 310 passed / 2 skipped, 311 passed / 1 skipped (androidtvremote2), 16 passed in the HA drift suite, ruff clean.
This commit is contained in:
1 parent
dd23d01a88
commit
60d884b76a
4 files changed
+144
-17
No files matched your search
@@ -153,6 +153,35 @@ async def _migrate_legacy_unique_id(hass, entry) -> None:
|
||||
_LOGGER.info("P5-1: legacy unique_id %r migrated to %r", legacy, new_id)
|
||||
|
||||
|
||||
def entity_available(manager: ShieldConnectionManager | None) -> bool:
|
||||
"""Is ANY usable transport healthy for this entry? (t40 live install)
|
||||
|
||||
The single ladder behind ``media_player.available``, ``remote.available``
|
||||
and the diagnostics payload, so the three cannot disagree:
|
||||
|
||||
* the protocol transport is wired and has not reported the device
|
||||
unreachable — it serves power/app/volume even when ADB is down;
|
||||
* or ADB is connected (live state data);
|
||||
* or fresh wake data exists (the poller has spoken at least once);
|
||||
* or the manager is passive (no ADB configured at all): nothing to
|
||||
transport is not a broken transport.
|
||||
|
||||
Unavailable only when a CONFIGURED transport is actively down and no usable
|
||||
data exists. The t5-F2 rule ("an ADB manager that is down means unreliable
|
||||
state") took the whole entity down while a healthy paired protocol transport
|
||||
was still serving commands — the reported defect.
|
||||
"""
|
||||
if not isinstance(manager, ShieldConnectionManager):
|
||||
return True
|
||||
if manager.protocol_active and manager.is_available is not False:
|
||||
return True
|
||||
if manager.connected:
|
||||
return True
|
||||
if manager.awake is not None:
|
||||
return True
|
||||
return not manager.available
|
||||
|
||||
|
||||
def resolve_app_name(
|
||||
package: str | None,
|
||||
app_name_map,
|
||||
@@ -225,15 +254,13 @@ class NvidiaShieldMediaPlayer(MediaPlayerEntity):
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""The bridge entities stay functional without ADB (passive manager).
|
||||
"""Available while ANY usable transport is healthy (t40 live install).
|
||||
|
||||
Unavailable only while an active ADB manager is down — its data is
|
||||
unreliable until the watchdog reconnects (t5-F2).
|
||||
ADB enabled but unreachable no longer takes the entity down: a paired,
|
||||
available protocol transport still serves power/app/volume. The ladder
|
||||
is shared with the remote and diagnostics (``entity_available``).
|
||||
"""
|
||||
manager = getattr(self._entry, "runtime_data", None)
|
||||
if not isinstance(manager, ShieldConnectionManager):
|
||||
return True
|
||||
return manager.connected or manager.awake is not None or not manager.available
|
||||
return entity_available(getattr(self._entry, "runtime_data", None))
|
||||
|
||||
@property
|
||||
def _jellyfin_entity(self) -> str | None:
|
||||
|
||||
Reference in new issue
Block a user