Fix invalid enocean unique_id (#74508)

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
rhadamantys 2022-08-01 17:42:47 +02:00 committed by GitHub
parent 91384e07d0
commit 7141c36f8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 111 additions and 5 deletions

View File

@ -5,12 +5,14 @@ from enocean.utils import combine_hex
import voluptuous as vol
from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity
from homeassistant.const import CONF_ID, CONF_NAME
from homeassistant.const import CONF_ID, CONF_NAME, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from .const import DOMAIN, LOGGER
from .device import EnOceanEntity
CONF_CHANNEL = "channel"
@ -25,10 +27,40 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
)
def setup_platform(
def generate_unique_id(dev_id: list[int], channel: int) -> str:
"""Generate a valid unique id."""
return f"{combine_hex(dev_id)}-{channel}"
def _migrate_to_new_unique_id(hass: HomeAssistant, dev_id, channel) -> None:
"""Migrate old unique ids to new unique ids."""
old_unique_id = f"{combine_hex(dev_id)}"
ent_reg = entity_registry.async_get(hass)
entity_id = ent_reg.async_get_entity_id(Platform.SWITCH, DOMAIN, old_unique_id)
if entity_id is not None:
new_unique_id = generate_unique_id(dev_id, channel)
try:
ent_reg.async_update_entity(entity_id, new_unique_id=new_unique_id)
except ValueError:
LOGGER.warning(
"Skip migration of id [%s] to [%s] because it already exists",
old_unique_id,
new_unique_id,
)
else:
LOGGER.debug(
"Migrating unique_id from [%s] to [%s]",
old_unique_id,
new_unique_id,
)
async def async_setup_platform(
hass: HomeAssistant,
config: ConfigType,
add_entities: AddEntitiesCallback,
async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the EnOcean switch platform."""
@ -36,7 +68,8 @@ def setup_platform(
dev_id = config.get(CONF_ID)
dev_name = config.get(CONF_NAME)
add_entities([EnOceanSwitch(dev_id, dev_name, channel)])
_migrate_to_new_unique_id(hass, dev_id, channel)
async_add_entities([EnOceanSwitch(dev_id, dev_name, channel)])
class EnOceanSwitch(EnOceanEntity, SwitchEntity):
@ -49,7 +82,7 @@ class EnOceanSwitch(EnOceanEntity, SwitchEntity):
self._on_state = False
self._on_state2 = False
self.channel = channel
self._attr_unique_id = f"{combine_hex(dev_id)}"
self._attr_unique_id = generate_unique_id(dev_id, channel)
@property
def is_on(self):

View File

@ -0,0 +1,73 @@
"""Tests for the EnOcean switch platform."""
from enocean.utils import combine_hex
from homeassistant.components.enocean import DOMAIN as ENOCEAN_DOMAIN
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry, assert_setup_component
SWITCH_CONFIG = {
"switch": [
{
"platform": ENOCEAN_DOMAIN,
"id": [0xDE, 0xAD, 0xBE, 0xEF],
"channel": 1,
"name": "room0",
},
]
}
async def test_unique_id_migration(hass: HomeAssistant) -> None:
"""Test EnOcean switch ID migration."""
entity_name = SWITCH_CONFIG["switch"][0]["name"]
switch_entity_id = f"{SWITCH_DOMAIN}.{entity_name}"
dev_id = SWITCH_CONFIG["switch"][0]["id"]
channel = SWITCH_CONFIG["switch"][0]["channel"]
ent_reg = er.async_get(hass)
old_unique_id = f"{combine_hex(dev_id)}"
entry = MockConfigEntry(domain=ENOCEAN_DOMAIN, data={"device": "/dev/null"})
entry.add_to_hass(hass)
# Add a switch with an old unique_id to the entity registry
entity_entry = ent_reg.async_get_or_create(
SWITCH_DOMAIN,
ENOCEAN_DOMAIN,
old_unique_id,
suggested_object_id=entity_name,
config_entry=entry,
original_name=entity_name,
)
assert entity_entry.entity_id == switch_entity_id
assert entity_entry.unique_id == old_unique_id
# Now add the sensor to check, whether the old unique_id is migrated
with assert_setup_component(1, SWITCH_DOMAIN):
assert await async_setup_component(
hass,
SWITCH_DOMAIN,
SWITCH_CONFIG,
)
await hass.async_block_till_done()
# Check that new entry has a new unique_id
entity_entry = ent_reg.async_get(switch_entity_id)
new_unique_id = f"{combine_hex(dev_id)}-{channel}"
assert entity_entry.unique_id == new_unique_id
assert (
ent_reg.async_get_entity_id(SWITCH_DOMAIN, ENOCEAN_DOMAIN, old_unique_id)
is None
)