Remove Shelly empty sub-devices (#152251)

This commit is contained in:
Shay Levy
2025-09-14 23:43:37 +03:00
committed by GitHub
parent 2f4c69bbd5
commit e40ecdfb00
4 changed files with 57 additions and 4 deletions
@@ -67,6 +67,7 @@ from .utils import (
get_http_port,
get_rpc_scripts_event_types,
get_ws_context,
remove_empty_sub_devices,
remove_stale_blu_trv_devices,
)
@@ -223,6 +224,7 @@ async def _async_setup_block_entry(
await hass.config_entries.async_forward_entry_setups(
entry, runtime_data.platforms
)
remove_empty_sub_devices(hass, entry)
elif (
sleep_period is None
or device_entry is None
@@ -334,6 +336,7 @@ async def _async_setup_rpc_entry(hass: HomeAssistant, entry: ShellyConfigEntry)
hass,
entry,
)
remove_empty_sub_devices(hass, entry)
elif (
sleep_period is None
or device_entry is None
+24
View File
@@ -884,3 +884,27 @@ def remove_stale_blu_trv_devices(
LOGGER.debug("Removing stale BLU TRV device %s", device.name)
dev_reg.async_update_device(device.id, remove_config_entry_id=entry.entry_id)
@callback
def remove_empty_sub_devices(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Remove sub devices without entities."""
dev_reg = dr.async_get(hass)
entity_reg = er.async_get(hass)
devices = dev_reg.devices.get_devices_for_config_entry_id(entry.entry_id)
for device in devices:
if not device.via_device_id:
# Device is not a sub-device, skip
continue
if er.async_entries_for_device(entity_reg, device.id, True):
# Device has entities, skip
continue
if any(identifier[0] == DOMAIN for identifier in device.identifiers):
LOGGER.debug("Removing empty sub-device %s", device.name)
dev_reg.async_update_device(
device.id, remove_config_entry_id=entry.entry_id
)
+2 -3
View File
@@ -26,7 +26,6 @@ from homeassistant.helpers.device_registry import (
CONNECTION_NETWORK_MAC,
DeviceEntry,
DeviceRegistry,
format_mac,
)
from tests.common import MockConfigEntry, async_fire_time_changed
@@ -152,7 +151,7 @@ def register_device(
"""Register Shelly device."""
return device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(CONNECTION_NETWORK_MAC, format_mac(MOCK_MAC))},
connections={(CONNECTION_NETWORK_MAC, MOCK_MAC)},
)
@@ -163,7 +162,7 @@ def register_sub_device(
return device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, f"{MOCK_MAC}-{unique_id}")},
via_device=(DOMAIN, format_mac(MOCK_MAC)),
via_device=(DOMAIN, MOCK_MAC),
)
+28 -1
View File
@@ -41,7 +41,7 @@ from homeassistant.helpers.device_registry import DeviceRegistry, format_mac
from homeassistant.helpers.entity_registry import EntityRegistry
from homeassistant.setup import async_setup_component
from . import MOCK_MAC, init_integration, mutate_rpc_device_status
from . import MOCK_MAC, init_integration, mutate_rpc_device_status, register_sub_device
async def test_custom_coap_port(
@@ -653,3 +653,30 @@ async def test_blu_trv_stale_device_removal(
assert hass.states.get(trv_201_entity_id) is None
assert device_registry.async_get(trv_201_entry.device_id) is None
async def test_empty_device_removal(
hass: HomeAssistant,
entity_registry: EntityRegistry,
device_registry: DeviceRegistry,
mock_rpc_device: Mock,
) -> None:
"""Test removal of empty devices due to device configuration changes."""
config_entry = await init_integration(hass, 3)
# create empty sub-device
sub_device_entry = register_sub_device(
device_registry,
config_entry,
"boolean:201-boolean",
)
# verify that the sub-device is created
assert device_registry.async_get(sub_device_entry.id) is not None
# device config change triggers a reload
await hass.config_entries.async_reload(config_entry.entry_id)
await hass.async_block_till_done()
# verify that the empty sub-device is removed
assert device_registry.async_get(sub_device_entry.id) is None