Remove individual lcn devices for each entity (#136450)
parent
15ca2fe489
commit
800fe1b01e
|
@ -49,6 +49,7 @@ from .helpers import (
|
|||
InputType,
|
||||
async_update_config_entry,
|
||||
generate_unique_id,
|
||||
purge_device_registry,
|
||||
register_lcn_address_devices,
|
||||
register_lcn_host_device,
|
||||
)
|
||||
|
@ -120,6 +121,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
|||
register_lcn_host_device(hass, config_entry)
|
||||
register_lcn_address_devices(hass, config_entry)
|
||||
|
||||
# clean up orphaned devices
|
||||
purge_device_registry(hass, config_entry.entry_id, {**config_entry.data})
|
||||
|
||||
# forward config_entry to components
|
||||
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
|
||||
|
||||
|
|
|
@ -3,19 +3,18 @@
|
|||
from collections.abc import Callable
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_NAME, CONF_RESOURCE
|
||||
from homeassistant.const import CONF_ADDRESS, CONF_NAME, CONF_RESOURCE
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import CONF_DOMAIN_DATA, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .helpers import (
|
||||
AddressType,
|
||||
DeviceConnectionType,
|
||||
InputType,
|
||||
generate_unique_id,
|
||||
get_device_connection,
|
||||
get_device_model,
|
||||
)
|
||||
|
||||
|
||||
|
@ -36,6 +35,14 @@ class LcnEntity(Entity):
|
|||
self.address: AddressType = config[CONF_ADDRESS]
|
||||
self._unregister_for_inputs: Callable | None = None
|
||||
self._name: str = config[CONF_NAME]
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={
|
||||
(
|
||||
DOMAIN,
|
||||
generate_unique_id(self.config_entry.entry_id, self.address),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
|
@ -44,28 +51,6 @@ class LcnEntity(Entity):
|
|||
self.config_entry.entry_id, self.address, self.config[CONF_RESOURCE]
|
||||
)
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo | None:
|
||||
"""Return device specific attributes."""
|
||||
address = f"{'g' if self.address[2] else 'm'}{self.address[0]:03d}{self.address[1]:03d}"
|
||||
model = (
|
||||
"LCN resource"
|
||||
f" ({get_device_model(self.config[CONF_DOMAIN], self.config[CONF_DOMAIN_DATA])})"
|
||||
)
|
||||
|
||||
return DeviceInfo(
|
||||
identifiers={(DOMAIN, self.unique_id)},
|
||||
name=f"{address}.{self.config[CONF_RESOURCE]}",
|
||||
model=model,
|
||||
manufacturer="Issendorff",
|
||||
via_device=(
|
||||
DOMAIN,
|
||||
generate_unique_id(
|
||||
self.config_entry.entry_id, self.config[CONF_ADDRESS]
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Run when entity about to be added to hass."""
|
||||
self.device_connection = get_device_connection(
|
||||
|
|
|
@ -4,7 +4,6 @@ from __future__ import annotations
|
|||
|
||||
import asyncio
|
||||
from copy import deepcopy
|
||||
from itertools import chain
|
||||
import re
|
||||
from typing import cast
|
||||
|
||||
|
@ -22,7 +21,6 @@ from homeassistant.const import (
|
|||
CONF_NAME,
|
||||
CONF_RESOURCE,
|
||||
CONF_SENSORS,
|
||||
CONF_SOURCE,
|
||||
CONF_SWITCHES,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
@ -30,23 +28,14 @@ from homeassistant.helpers import device_registry as dr, entity_registry as er
|
|||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import (
|
||||
BINSENSOR_PORTS,
|
||||
CONF_CLIMATES,
|
||||
CONF_HARDWARE_SERIAL,
|
||||
CONF_HARDWARE_TYPE,
|
||||
CONF_OUTPUT,
|
||||
CONF_SCENES,
|
||||
CONF_SOFTWARE_SERIAL,
|
||||
CONNECTION,
|
||||
DEVICE_CONNECTIONS,
|
||||
DOMAIN,
|
||||
LED_PORTS,
|
||||
LOGICOP_PORTS,
|
||||
OUTPUT_PORTS,
|
||||
S0_INPUTS,
|
||||
SETPOINTS,
|
||||
THRESHOLDS,
|
||||
VARIABLES,
|
||||
)
|
||||
|
||||
# typing
|
||||
|
@ -96,31 +85,6 @@ def get_resource(domain_name: str, domain_data: ConfigType) -> str:
|
|||
raise ValueError("Unknown domain")
|
||||
|
||||
|
||||
def get_device_model(domain_name: str, domain_data: ConfigType) -> str:
|
||||
"""Return the model for the specified domain_data."""
|
||||
if domain_name in ("switch", "light"):
|
||||
return "Output" if domain_data[CONF_OUTPUT] in OUTPUT_PORTS else "Relay"
|
||||
if domain_name in ("binary_sensor", "sensor"):
|
||||
if domain_data[CONF_SOURCE] in BINSENSOR_PORTS:
|
||||
return "Binary Sensor"
|
||||
if domain_data[CONF_SOURCE] in chain(
|
||||
VARIABLES, SETPOINTS, THRESHOLDS, S0_INPUTS
|
||||
):
|
||||
return "Variable"
|
||||
if domain_data[CONF_SOURCE] in LED_PORTS:
|
||||
return "Led"
|
||||
if domain_data[CONF_SOURCE] in LOGICOP_PORTS:
|
||||
return "Logical Operation"
|
||||
return "Key"
|
||||
if domain_name == "cover":
|
||||
return "Motor"
|
||||
if domain_name == "climate":
|
||||
return "Regulator"
|
||||
if domain_name == "scene":
|
||||
return "Scene"
|
||||
raise ValueError("Unknown domain")
|
||||
|
||||
|
||||
def generate_unique_id(
|
||||
entry_id: str,
|
||||
address: AddressType,
|
||||
|
@ -169,13 +133,6 @@ def purge_device_registry(
|
|||
) -> None:
|
||||
"""Remove orphans from device registry which are not in entry data."""
|
||||
device_registry = dr.async_get(hass)
|
||||
entity_registry = er.async_get(hass)
|
||||
|
||||
# Find all devices that are referenced in the entity registry.
|
||||
references_entities = {
|
||||
entry.device_id
|
||||
for entry in entity_registry.entities.get_entries_for_config_entry_id(entry_id)
|
||||
}
|
||||
|
||||
# Find device that references the host.
|
||||
references_host = set()
|
||||
|
@ -198,7 +155,6 @@ def purge_device_registry(
|
|||
entry.id
|
||||
for entry in dr.async_entries_for_config_entry(device_registry, entry_id)
|
||||
}
|
||||
- references_entities
|
||||
- references_host
|
||||
- references_entry_data
|
||||
)
|
||||
|
|
|
@ -45,9 +45,14 @@ async def test_get_triggers_module_device(
|
|||
)
|
||||
]
|
||||
|
||||
triggers = await async_get_device_automations(
|
||||
hass, DeviceAutomationType.TRIGGER, device.id
|
||||
)
|
||||
triggers = [
|
||||
trigger
|
||||
for trigger in await async_get_device_automations(
|
||||
hass, DeviceAutomationType.TRIGGER, device.id
|
||||
)
|
||||
if trigger[CONF_DOMAIN] == DOMAIN
|
||||
]
|
||||
|
||||
assert triggers == unordered(expected_triggers)
|
||||
|
||||
|
||||
|
@ -63,11 +68,8 @@ async def test_get_triggers_non_module_device(
|
|||
identifiers={(DOMAIN, entry.entry_id)}
|
||||
)
|
||||
group_device = get_device(hass, entry, (0, 5, True))
|
||||
resource_device = device_registry.async_get_device(
|
||||
identifiers={(DOMAIN, f"{entry.entry_id}-m000007-output1")}
|
||||
)
|
||||
|
||||
for device in (host_device, group_device, resource_device):
|
||||
for device in (host_device, group_device):
|
||||
triggers = await async_get_device_automations(
|
||||
hass, DeviceAutomationType.TRIGGER, device.id
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue