Skip to content

Commit b15b4e4

Browse files
authored
Fix Shelly virtual components roles migration (home-assistant#153987)
1 parent dddf6d5 commit b15b4e4

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed

homeassistant/components/shelly/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ class BLEScannerMode(StrEnum):
270270

271271
CONF_GEN = "gen"
272272

273-
VIRTUAL_COMPONENTS = ("boolean", "button", "enum", "input", "number", "text")
273+
VIRTUAL_COMPONENTS = ("boolean", "button", "enum", "number", "text")
274274
VIRTUAL_COMPONENTS_MAP = {
275275
"binary_sensor": {"types": ["boolean"], "modes": ["label"]},
276276
"button": {"types": ["button"], "modes": ["button"]},

homeassistant/components/shelly/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,12 +402,12 @@ def get_rpc_channel_name(device: RpcDevice, key: str) -> str | None:
402402
if key in device.config and key != "em:0":
403403
# workaround for Pro 3EM, we don't want to get name for em:0
404404
if component_name := device.config[key].get("name"):
405-
if component in (*VIRTUAL_COMPONENTS, "presencezone", "script"):
405+
if component in (*VIRTUAL_COMPONENTS, "input", "presencezone", "script"):
406406
return cast(str, component_name)
407407

408408
return cast(str, component_name) if instances == 1 else None
409409

410-
if component in VIRTUAL_COMPONENTS:
410+
if component in (*VIRTUAL_COMPONENTS, "input"):
411411
return f"{component.title()} {component_id}"
412412

413413
return None

tests/components/shelly/test_binary_sensor.py

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from syrupy.assertion import SnapshotAssertion
1010

1111
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
12-
from homeassistant.components.shelly.const import UPDATE_PERIOD_MULTIPLIER
12+
from homeassistant.components.shelly.const import DOMAIN, UPDATE_PERIOD_MULTIPLIER
1313
from homeassistant.const import (
1414
STATE_OFF,
1515
STATE_ON,
@@ -22,6 +22,7 @@
2222
from homeassistant.helpers.entity_registry import EntityRegistry
2323

2424
from . import (
25+
MOCK_MAC,
2526
init_integration,
2627
mock_rest_update,
2728
mutate_rpc_device_status,
@@ -670,3 +671,57 @@ async def test_rpc_presencezone_component(
670671

671672
assert (state := hass.states.get(entity_id))
672673
assert state.state == STATE_UNAVAILABLE
674+
675+
676+
@pytest.mark.parametrize(
677+
("old_id", "new_id", "role"),
678+
[
679+
("boolean", "boolean_generic", None),
680+
("boolean", "boolean_has_power", "has_power"),
681+
("input", "input", None), # negative test, input is not a virtual component
682+
],
683+
)
684+
async def test_migrate_unique_id_virtual_components_roles(
685+
hass: HomeAssistant,
686+
mock_rpc_device: Mock,
687+
entity_registry: EntityRegistry,
688+
caplog: pytest.LogCaptureFixture,
689+
monkeypatch: pytest.MonkeyPatch,
690+
old_id: str,
691+
new_id: str,
692+
role: str | None,
693+
) -> None:
694+
"""Test migration of unique_id for virtual components to include role."""
695+
entry = await init_integration(hass, 3, skip_setup=True)
696+
unique_base = f"{MOCK_MAC}-{old_id}:200"
697+
old_unique_id = f"{unique_base}-{old_id}"
698+
new_unique_id = f"{unique_base}-{new_id}"
699+
config = deepcopy(mock_rpc_device.config)
700+
if role:
701+
config[f"{old_id}:200"] = {
702+
"role": role,
703+
}
704+
else:
705+
config[f"{old_id}:200"] = {}
706+
monkeypatch.setattr(mock_rpc_device, "config", config)
707+
708+
entity = entity_registry.async_get_or_create(
709+
suggested_object_id="test_name_test_sensor",
710+
disabled_by=None,
711+
domain=BINARY_SENSOR_DOMAIN,
712+
platform=DOMAIN,
713+
unique_id=old_unique_id,
714+
config_entry=entry,
715+
)
716+
assert entity.unique_id == old_unique_id
717+
718+
await hass.config_entries.async_setup(entry.entry_id)
719+
await hass.async_block_till_done()
720+
721+
entity_entry = entity_registry.async_get("binary_sensor.test_name_test_sensor")
722+
assert entity_entry
723+
assert entity_entry.unique_id == new_unique_id
724+
725+
assert (
726+
"Migrating unique_id for binary_sensor.test_name_test_sensor" in caplog.text
727+
) == (old_id != new_id)

0 commit comments

Comments
 (0)