mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 10:13:52 -05:00
Migrate insteon to lookup devices scoped to config entry (#177964)
This commit is contained in:
committed by
Bram Kragten
parent
07f5bb8a0a
commit
c419da1eb7
@@ -12,6 +12,7 @@ from homeassistant.helpers import device_registry as dr
|
||||
|
||||
from ..const import DEVICE_ADDRESS, ID, INSTEON_DEVICE_NOT_FOUND, TYPE
|
||||
from ..utils import async_device_name
|
||||
from .config import get_insteon_config_entry
|
||||
from .device import notify_device_not_found
|
||||
|
||||
ALDB_RECORD = "record"
|
||||
@@ -32,7 +33,7 @@ ALDB_RECORD_SCHEMA = vol.Schema(
|
||||
)
|
||||
|
||||
|
||||
async def async_aldb_record_to_dict(dev_registry, record, dirty=False):
|
||||
async def async_aldb_record_to_dict(dev_registry, record, config_entry_id, dirty=False):
|
||||
"""Convert an ALDB record to a dict."""
|
||||
return ALDB_RECORD_SCHEMA(
|
||||
{
|
||||
@@ -42,7 +43,9 @@ async def async_aldb_record_to_dict(dev_registry, record, dirty=False):
|
||||
"highwater": record.is_high_water_mark,
|
||||
"group": record.group,
|
||||
"target": str(record.target),
|
||||
"target_name": await async_device_name(dev_registry, record.target),
|
||||
"target_name": await async_device_name(
|
||||
dev_registry, record.target, config_entry_id
|
||||
),
|
||||
"data1": record.data1,
|
||||
"data2": record.data2,
|
||||
"data3": record.data3,
|
||||
@@ -88,10 +91,11 @@ async def websocket_get_aldb(
|
||||
changed_records = list(device.aldb.pending_changes.keys())
|
||||
|
||||
dev_registry = dr.async_get(hass)
|
||||
config_entry_id = get_insteon_config_entry(hass).entry_id
|
||||
|
||||
records = [
|
||||
await async_aldb_record_to_dict(
|
||||
dev_registry, aldb[mem_addr], mem_addr in changed_records
|
||||
dev_registry, aldb[mem_addr], config_entry_id, mem_addr in changed_records
|
||||
)
|
||||
for mem_addr in aldb
|
||||
]
|
||||
|
||||
@@ -137,12 +137,16 @@ def remove_device_override(hass: HomeAssistant, address: Address):
|
||||
|
||||
|
||||
async def async_link_to_dict(
|
||||
address: Address, record: ALDBRecord, dev_registry: dr.DeviceRegistry, status=None
|
||||
address: Address,
|
||||
record: ALDBRecord,
|
||||
dev_registry: dr.DeviceRegistry,
|
||||
config_entry_id: str,
|
||||
status=None,
|
||||
) -> dict[str, str | int]:
|
||||
"""Convert a link to a dictionary."""
|
||||
link_dict: dict[str, str | int] = {}
|
||||
device_name = await async_device_name(dev_registry, address)
|
||||
target_name = await async_device_name(dev_registry, record.target)
|
||||
device_name = await async_device_name(dev_registry, address, config_entry_id)
|
||||
target_name = await async_device_name(dev_registry, record.target, config_entry_id)
|
||||
link_dict["address"] = str(address)
|
||||
link_dict["device_name"] = device_name or str(address)
|
||||
link_dict["mem_addr"] = record.mem_addr
|
||||
@@ -311,8 +315,9 @@ async def websocket_get_broken_links(
|
||||
"""Get any broken links between devices."""
|
||||
broken_links = get_broken_links(devices=devices)
|
||||
dev_registry = dr.async_get(hass)
|
||||
config_entry_id = get_insteon_config_entry(hass).entry_id
|
||||
broken_links_list = [
|
||||
await async_link_to_dict(address, record, dev_registry, status)
|
||||
await async_link_to_dict(address, record, dev_registry, config_entry_id, status)
|
||||
for address, record, status in broken_links
|
||||
if status != LinkStatus.MISSING_TARGET
|
||||
]
|
||||
|
||||
@@ -217,7 +217,10 @@ def async_setup_services(hass: HomeAssistant) -> None: # noqa: C901
|
||||
signal = f"{address.id}_{SIGNAL_REMOVE_ENTITY}"
|
||||
async_dispatcher_send(hass, signal)
|
||||
dev_registry = dr.async_get(hass)
|
||||
device = dev_registry.async_get_device(identifiers={(DOMAIN, str(address))})
|
||||
config_entry = hass.config_entries.async_entries(DOMAIN)[0]
|
||||
device = dev_registry.async_get_device_by_identifier(
|
||||
(DOMAIN, str(address)), config_entry.entry_id
|
||||
)
|
||||
if device:
|
||||
dev_registry.async_remove_device(device.id)
|
||||
|
||||
|
||||
@@ -190,9 +190,13 @@ def compute_device_name(ha_device) -> str:
|
||||
return ha_device.name_by_user or ha_device.name
|
||||
|
||||
|
||||
async def async_device_name(dev_registry: dr.DeviceRegistry, address: Address) -> str:
|
||||
async def async_device_name(
|
||||
dev_registry: dr.DeviceRegistry, address: Address, config_entry_id: str
|
||||
) -> str:
|
||||
"""Get the Insteon device name from a device registry id."""
|
||||
ha_device = dev_registry.async_get_device(identifiers={(DOMAIN, str(address))})
|
||||
ha_device = dev_registry.async_get_device_by_identifier(
|
||||
(DOMAIN, str(address)), config_entry_id
|
||||
)
|
||||
if not ha_device:
|
||||
if device := devices[address]:
|
||||
return f"{device.description} ({device.model})"
|
||||
|
||||
@@ -20,11 +20,13 @@ from homeassistant.components.insteon.api.aldb import (
|
||||
TYPE,
|
||||
)
|
||||
from homeassistant.components.insteon.api.device import INSTEON_DEVICE_NOT_FOUND
|
||||
from homeassistant.components.insteon.const import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import MOCK_USER_INPUT_PLM
|
||||
from .mock_devices import MockDevices
|
||||
|
||||
from tests.common import load_fixture
|
||||
from tests.common import MockConfigEntry, load_fixture
|
||||
from tests.typing import MockHAClientWebSocket, WebSocketGenerator
|
||||
|
||||
|
||||
@@ -38,6 +40,13 @@ async def _setup(
|
||||
hass: HomeAssistant, hass_ws_client: WebSocketGenerator, aldb_data: dict[str, Any]
|
||||
) -> tuple[MockHAClientWebSocket, MockDevices]:
|
||||
"""Set up tests."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
entry_id="abcde12345",
|
||||
data=MOCK_USER_INPUT_PLM,
|
||||
options={},
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
ws_client = await hass_ws_client(hass)
|
||||
devices = MockDevices()
|
||||
await devices.async_load()
|
||||
|
||||
@@ -123,14 +123,33 @@ async def test_get_ha_device_name(
|
||||
"""Test getting the HA device name from an Insteon address."""
|
||||
|
||||
_, devices, _, device_reg = await async_mock_setup(hass, hass_ws_client)
|
||||
config_entry_id = hass.config_entries.async_entries(DOMAIN)[0].entry_id
|
||||
|
||||
# Register a colliding device sharing the same identifier but owned by a second
|
||||
# config entry. The lookup must be scoped to the supplied config entry: an
|
||||
# unscoped lookup could return either device, so returning the correct name for
|
||||
# each config entry proves the config entry controls the lookup.
|
||||
other_config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_INPUT_PLM)
|
||||
other_config_entry.add_to_hass(hass)
|
||||
device_reg.async_get_or_create(
|
||||
config_entry_id=other_config_entry.entry_id,
|
||||
identifiers={(DOMAIN, "11.11.11")},
|
||||
name="Device 11.11.11 second entry",
|
||||
)
|
||||
|
||||
with patch.object(insteon.api.device, "devices", devices):
|
||||
# Test a real HA and Insteon device
|
||||
name = await async_device_name(device_reg, "11.11.11")
|
||||
# The scoped lookup returns the device owned by the supplied config entry
|
||||
name = await async_device_name(device_reg, "11.11.11", config_entry_id)
|
||||
assert name == "Device 11.11.11"
|
||||
|
||||
# The same identifier scoped to the second config entry returns its device
|
||||
name = await async_device_name(
|
||||
device_reg, "11.11.11", other_config_entry.entry_id
|
||||
)
|
||||
assert name == "Device 11.11.11 second entry"
|
||||
|
||||
# Test no HA or Insteon device
|
||||
name = await async_device_name(device_reg, "BB.BB.BB")
|
||||
name = await async_device_name(device_reg, "BB.BB.BB", config_entry_id)
|
||||
assert name == ""
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user