Fix Shelly entity removal (#147665)

This commit is contained in:
Shay Levy 2025-06-27 18:50:35 +03:00 committed by GitHub
parent 8ee5c30754
commit 2120ff6a0a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 61 additions and 7 deletions

View File

@ -192,8 +192,12 @@ def async_setup_rpc_attribute_entities(
if description.removal_condition and description.removal_condition( if description.removal_condition and description.removal_condition(
coordinator.device.config, coordinator.device.status, key coordinator.device.config, coordinator.device.status, key
): ):
domain = sensor_class.__module__.split(".")[-1] entity_class = get_entity_class(sensor_class, description)
unique_id = f"{coordinator.mac}-{key}-{sensor_id}" domain = entity_class.__module__.split(".")[-1]
unique_id = entity_class(
coordinator, key, sensor_id, description
).unique_id
LOGGER.debug("Removing Shelly entity with unique_id: %s", unique_id)
async_remove_shelly_entity(hass, domain, unique_id) async_remove_shelly_entity(hass, domain, unique_id)
elif description.use_polling_coordinator: elif description.use_polling_coordinator:
if not sleep_period: if not sleep_period:

View File

@ -1,15 +1,18 @@
"""Tests for Shelly switch platform.""" """Tests for Shelly switch platform."""
from copy import deepcopy from copy import deepcopy
from datetime import timedelta
from unittest.mock import AsyncMock, Mock from unittest.mock import AsyncMock, Mock
from aioshelly.const import MODEL_1PM, MODEL_GAS, MODEL_MOTION from aioshelly.const import MODEL_1PM, MODEL_GAS, MODEL_MOTION
from aioshelly.exceptions import DeviceConnectionError, InvalidAuthError, RpcCallError from aioshelly.exceptions import DeviceConnectionError, InvalidAuthError, RpcCallError
from freezegun.api import FrozenDateTimeFactory
import pytest import pytest
from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN
from homeassistant.components.shelly.const import ( from homeassistant.components.shelly.const import (
DOMAIN, DOMAIN,
ENTRY_RELOAD_COOLDOWN,
MODEL_WALL_DISPLAY, MODEL_WALL_DISPLAY,
MOTION_MODELS, MOTION_MODELS,
) )
@ -28,9 +31,14 @@ from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.device_registry import DeviceRegistry from homeassistant.helpers.device_registry import DeviceRegistry
from homeassistant.helpers.entity_registry import EntityRegistry from homeassistant.helpers.entity_registry import EntityRegistry
from . import init_integration, register_device, register_entity from . import (
init_integration,
inject_rpc_device_event,
register_device,
register_entity,
)
from tests.common import mock_restore_cache from tests.common import async_fire_time_changed, mock_restore_cache
RELAY_BLOCK_ID = 0 RELAY_BLOCK_ID = 0
GAS_VALVE_BLOCK_ID = 6 GAS_VALVE_BLOCK_ID = 6
@ -374,15 +382,57 @@ async def test_rpc_device_unique_ids(
async def test_rpc_device_switch_type_lights_mode( async def test_rpc_device_switch_type_lights_mode(
hass: HomeAssistant, mock_rpc_device: Mock, monkeypatch: pytest.MonkeyPatch hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
mock_rpc_device: Mock,
monkeypatch: pytest.MonkeyPatch,
) -> None: ) -> None:
"""Test RPC device with switch in consumption type lights mode.""" """Test RPC device with switch in consumption type lights mode."""
switch_entity_id = "switch.test_name_test_switch_0"
light_entity_id = "light.test_name_test_switch_0"
monkeypatch.delitem(mock_rpc_device.status, "cover:0")
monkeypatch.setitem(mock_rpc_device.status["sys"], "relay_in_thermostat", False)
await init_integration(hass, 2)
# Entity is created as switch
assert hass.states.get(switch_entity_id)
assert hass.states.get(light_entity_id) is None
# Generate config change from switch to light
monkeypatch.setitem( monkeypatch.setitem(
mock_rpc_device.config["sys"]["ui_data"], "consumption_types", ["lights"] mock_rpc_device.config["sys"]["ui_data"], "consumption_types", ["lights"]
) )
await init_integration(hass, 2) inject_rpc_device_event(
monkeypatch,
mock_rpc_device,
{
"events": [
{
"data": [],
"event": "config_changed",
"id": 1,
"ts": 1668522399.2,
},
{
"data": [],
"id": 2,
"ts": 1668522399.2,
},
],
"ts": 1668522399.2,
},
)
await hass.async_block_till_done()
assert hass.states.get("switch.test_switch_0") is None # Wait for debouncer
freezer.tick(timedelta(seconds=ENTRY_RELOAD_COOLDOWN))
async_fire_time_changed(hass)
await hass.async_block_till_done()
# Switch entity should be removed and light entity created
assert hass.states.get(switch_entity_id) is None
assert hass.states.get(light_entity_id)
@pytest.mark.parametrize( @pytest.mark.parametrize(