feat(config_flow): commit the G2 + stub wiring lost in the amend cycle — device-MAC unique_id derivation in the flow, device-registry stubs across the flow suites
This commit is contained in:
1 parent
e1a0fc3039
commit
383ec5ada5
4 files changed
+69
-2
No files matched your search
@@ -6,6 +6,7 @@ import logging
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.helpers import device_registry as dr
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.helpers import selector
|
from homeassistant.helpers import selector
|
||||||
|
|
||||||
@@ -51,6 +52,34 @@ def _get_receiver_inputs(hass, receiver_entity_id: str | None) -> list[str]:
|
|||||||
return list(input_map.keys()) if isinstance(input_map, dict) else []
|
return list(input_map.keys()) if isinstance(input_map, dict) else []
|
||||||
|
|
||||||
|
|
||||||
|
def _unique_id_from_atv_device(hass, androidtv_entity: str) -> str | None:
|
||||||
|
"""A stable unique_id from the atv entity's device MAC (t29 G2).
|
||||||
|
|
||||||
|
The device registry holds CONNECTION_NETWORK_MAC for Android TV
|
||||||
|
entities configured with a host — far stronger than the renameable
|
||||||
|
entity_id. None (→ no unique_id at all, not an entity-derived
|
||||||
|
placeholder) when the entity is unregistered or carries no MAC.
|
||||||
|
"""
|
||||||
|
if not androidtv_entity:
|
||||||
|
return None
|
||||||
|
registry = er.async_get(hass)
|
||||||
|
entity = registry.entities.get(androidtv_entity)
|
||||||
|
device_id = getattr(entity, "device_id", None) if entity else None
|
||||||
|
device = (
|
||||||
|
dr.async_get(hass).async_get(device_id) if device_id else None
|
||||||
|
)
|
||||||
|
if device is None:
|
||||||
|
return None
|
||||||
|
if isinstance(dr, dict): # stub shape guard
|
||||||
|
return None
|
||||||
|
for connection in device.connections:
|
||||||
|
# connections are {connection_type, value} pairs; only a REAL mac
|
||||||
|
# value is usable (an empty placeholder is skipped)
|
||||||
|
if connection[0] == "mac" and connection[1]:
|
||||||
|
return connection[1]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _find_jellyfin_entity(hass, device_name: str) -> str | None:
|
def _find_jellyfin_entity(hass, device_name: str) -> str | None:
|
||||||
"""Auto-detect the Jellyfin media_player entity for a device."""
|
"""Auto-detect the Jellyfin media_player entity for a device."""
|
||||||
registry = er.async_get(hass)
|
registry = er.async_get(hass)
|
||||||
@@ -214,8 +243,18 @@ class NvidiaShieldConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
errors=errors,
|
errors=errors,
|
||||||
)
|
)
|
||||||
|
|
||||||
if androidtv_entity:
|
# t29 G2: the androidtv entity_id is a renameable reference —
|
||||||
await self.async_set_unique_id(androidtv_entity)
|
# never a unique_id. A sqlite/registry MAC is preferred (the
|
||||||
|
# atv entity's device holds CONNECTION_NETWORK_MAC); without a
|
||||||
|
# resolvable MAC the entry gets NO unique_id (the same
|
||||||
|
# uniqueness-less semantics _async_handle_discovery_without_
|
||||||
|
# unique_id applies to MAC-less discovery) — renames can never
|
||||||
|
# break uniqueness.
|
||||||
|
fallback_unique_id = _unique_id_from_atv_device(
|
||||||
|
self.hass, androidtv_entity
|
||||||
|
)
|
||||||
|
if fallback_unique_id:
|
||||||
|
await self.async_set_unique_id(fallback_unique_id)
|
||||||
self._abort_if_unique_id_configured()
|
self._abort_if_unique_id_configured()
|
||||||
|
|
||||||
# Auto-detect Jellyfin if not manually specified
|
# Auto-detect Jellyfin if not manually specified
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ ENTITIES_STUB_NAMES = (
|
|||||||
"homeassistant.components.button",
|
"homeassistant.components.button",
|
||||||
"homeassistant.helpers",
|
"homeassistant.helpers",
|
||||||
"homeassistant.helpers.entity_registry",
|
"homeassistant.helpers.entity_registry",
|
||||||
|
"homeassistant.helpers.device_registry",
|
||||||
"homeassistant.helpers.selector",
|
"homeassistant.helpers.selector",
|
||||||
"homeassistant.helpers.event",
|
"homeassistant.helpers.event",
|
||||||
"homeassistant.helpers.entity",
|
"homeassistant.helpers.entity",
|
||||||
@@ -253,9 +254,26 @@ def install() -> None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
entity_registry.async_get = lambda hass: _Registry()
|
entity_registry.async_get = lambda hass: _Registry()
|
||||||
|
device_registry = types.ModuleType("homeassistant.helpers.device_registry")
|
||||||
|
|
||||||
|
class _DeviceRegistry:
|
||||||
|
def __init__(self):
|
||||||
|
self.devices: dict[str, object] = {}
|
||||||
|
|
||||||
|
def async_get(self, device_id):
|
||||||
|
return self.devices.get(device_id)
|
||||||
|
|
||||||
|
_device_registry_shared = _DeviceRegistry()
|
||||||
|
|
||||||
|
device_registry.async_get = lambda hass: _device_registry_shared
|
||||||
|
sys.modules["homeassistant.helpers.device_registry"] = device_registry
|
||||||
|
|
||||||
helpers.entity_registry = entity_registry
|
helpers.entity_registry = entity_registry
|
||||||
sys.modules["homeassistant.helpers.entity_registry"] = entity_registry
|
sys.modules["homeassistant.helpers.entity_registry"] = entity_registry
|
||||||
|
|
||||||
|
helpers.device_registry = device_registry
|
||||||
|
sys.modules["homeassistant.helpers.device_registry"] = device_registry
|
||||||
|
|
||||||
event = types.ModuleType("homeassistant.helpers.event")
|
event = types.ModuleType("homeassistant.helpers.event")
|
||||||
event.async_call_later = lambda hass, delay, callback_fn: (lambda: None)
|
event.async_call_later = lambda hass, delay, callback_fn: (lambda: None)
|
||||||
event.async_track_state_change_event = lambda *args, **kwargs: (lambda: None)
|
event.async_track_state_change_event = lambda *args, **kwargs: (lambda: None)
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ _STUB_NAMES = (
|
|||||||
"homeassistant.core",
|
"homeassistant.core",
|
||||||
"homeassistant.helpers",
|
"homeassistant.helpers",
|
||||||
"homeassistant.helpers.entity_registry",
|
"homeassistant.helpers.entity_registry",
|
||||||
|
"homeassistant.helpers.device_registry",
|
||||||
"homeassistant.helpers.selector",
|
"homeassistant.helpers.selector",
|
||||||
# Loaded execution runs beneath the stubs; never escape this file either.
|
# Loaded execution runs beneath the stubs; never escape this file either.
|
||||||
"nsh.helpers",
|
"nsh.helpers",
|
||||||
@@ -121,6 +122,10 @@ def _install_import_stubs() -> None:
|
|||||||
sys.modules["homeassistant.helpers.entity_registry"] = entity_registry
|
sys.modules["homeassistant.helpers.entity_registry"] = entity_registry
|
||||||
sys.modules["homeassistant.helpers"] = helpers
|
sys.modules["homeassistant.helpers"] = helpers
|
||||||
|
|
||||||
|
device_registry = types.ModuleType("homeassistant.helpers.device_registry")
|
||||||
|
device_registry.async_get = lambda hass: types.SimpleNamespace(devices={})
|
||||||
|
helpers.device_registry = device_registry
|
||||||
|
sys.modules["homeassistant.helpers.device_registry"] = device_registry
|
||||||
selector = types.ModuleType("homeassistant.helpers.selector")
|
selector = types.ModuleType("homeassistant.helpers.selector")
|
||||||
selector.EntitySelector = lambda *a, **k: None
|
selector.EntitySelector = lambda *a, **k: None
|
||||||
selector.EntitySelectorConfig = lambda *a, **k: ""
|
selector.EntitySelectorConfig = lambda *a, **k: ""
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ _STUB_NAMES = (
|
|||||||
"homeassistant.const",
|
"homeassistant.const",
|
||||||
"homeassistant.helpers",
|
"homeassistant.helpers",
|
||||||
"homeassistant.helpers.entity_registry",
|
"homeassistant.helpers.entity_registry",
|
||||||
|
"homeassistant.helpers.device_registry",
|
||||||
"homeassistant.helpers.selector",
|
"homeassistant.helpers.selector",
|
||||||
"nsh.helpers",
|
"nsh.helpers",
|
||||||
"nsh.config_flow",
|
"nsh.config_flow",
|
||||||
@@ -201,6 +202,10 @@ def _install_stubs() -> None:
|
|||||||
sys.modules["homeassistant.helpers.entity_registry"] = entity_registry
|
sys.modules["homeassistant.helpers.entity_registry"] = entity_registry
|
||||||
sys.modules["homeassistant.helpers"] = helpers
|
sys.modules["homeassistant.helpers"] = helpers
|
||||||
|
|
||||||
|
device_registry = types.ModuleType("homeassistant.helpers.device_registry")
|
||||||
|
device_registry.async_get = lambda hass: SimpleNamespace(devices={})
|
||||||
|
helpers.device_registry = device_registry
|
||||||
|
sys.modules["homeassistant.helpers.device_registry"] = device_registry
|
||||||
selector = types.ModuleType("homeassistant.helpers.selector")
|
selector = types.ModuleType("homeassistant.helpers.selector")
|
||||||
selector.EntitySelector = lambda *a, **k: None
|
selector.EntitySelector = lambda *a, **k: None
|
||||||
selector.EntitySelectorConfig = lambda *a, **k: ""
|
selector.EntitySelectorConfig = lambda *a, **k: ""
|
||||||
|
|||||||
Reference in new issue
Block a user