mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
Bump zwave-js-server-python to 0.21.0 (#47408)
Co-authored-by: Tobias Sauerwein <cgtobi@users.noreply.github.com>
This commit is contained in:
parent
a1faba29f0
commit
ee69e93b46
@ -48,7 +48,8 @@ from .const import (
|
||||
ZWAVE_JS_EVENT,
|
||||
)
|
||||
from .discovery import async_discover_values
|
||||
from .helpers import get_device_id, get_old_value_id, get_unique_id
|
||||
from .helpers import get_device_id
|
||||
from .migrate import async_migrate_discovered_value
|
||||
from .services import ZWaveServices
|
||||
|
||||
CONNECT_TIMEOUT = 10
|
||||
@ -98,31 +99,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
dev_reg = await device_registry.async_get_registry(hass)
|
||||
ent_reg = entity_registry.async_get(hass)
|
||||
|
||||
@callback
|
||||
def migrate_entity(platform: str, old_unique_id: str, new_unique_id: str) -> None:
|
||||
"""Check if entity with old unique ID exists, and if so migrate it to new ID."""
|
||||
if entity_id := ent_reg.async_get_entity_id(platform, DOMAIN, old_unique_id):
|
||||
LOGGER.debug(
|
||||
"Migrating entity %s from old unique ID '%s' to new unique ID '%s'",
|
||||
entity_id,
|
||||
old_unique_id,
|
||||
new_unique_id,
|
||||
)
|
||||
try:
|
||||
ent_reg.async_update_entity(
|
||||
entity_id,
|
||||
new_unique_id=new_unique_id,
|
||||
)
|
||||
except ValueError:
|
||||
LOGGER.debug(
|
||||
(
|
||||
"Entity %s can't be migrated because the unique ID is taken. "
|
||||
"Cleaning it up since it is likely no longer valid."
|
||||
),
|
||||
entity_id,
|
||||
)
|
||||
ent_reg.async_remove(entity_id)
|
||||
|
||||
@callback
|
||||
def async_on_node_ready(node: ZwaveNode) -> None:
|
||||
"""Handle node ready event."""
|
||||
@ -136,49 +112,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
LOGGER.debug("Discovered entity: %s", disc_info)
|
||||
|
||||
# This migration logic was added in 2021.3 to handle a breaking change to
|
||||
# the value_id format. Some time in the future, this code block
|
||||
# (as well as get_old_value_id helper and migrate_entity closure) can be
|
||||
# removed.
|
||||
value_ids = [
|
||||
# 2021.2.* format
|
||||
get_old_value_id(disc_info.primary_value),
|
||||
# 2021.3.0b0 format
|
||||
disc_info.primary_value.value_id,
|
||||
]
|
||||
|
||||
new_unique_id = get_unique_id(
|
||||
client.driver.controller.home_id,
|
||||
disc_info.primary_value.value_id,
|
||||
)
|
||||
|
||||
for value_id in value_ids:
|
||||
old_unique_id = get_unique_id(
|
||||
client.driver.controller.home_id,
|
||||
f"{disc_info.primary_value.node.node_id}.{value_id}",
|
||||
)
|
||||
# Most entities have the same ID format, but notification binary sensors
|
||||
# have a state key in their ID so we need to handle them differently
|
||||
if (
|
||||
disc_info.platform == "binary_sensor"
|
||||
and disc_info.platform_hint == "notification"
|
||||
):
|
||||
for state_key in disc_info.primary_value.metadata.states:
|
||||
# ignore idle key (0)
|
||||
if state_key == "0":
|
||||
continue
|
||||
|
||||
migrate_entity(
|
||||
disc_info.platform,
|
||||
f"{old_unique_id}.{state_key}",
|
||||
f"{new_unique_id}.{state_key}",
|
||||
)
|
||||
|
||||
# Once we've iterated through all state keys, we can move on to the
|
||||
# next item
|
||||
continue
|
||||
|
||||
migrate_entity(disc_info.platform, old_unique_id, new_unique_id)
|
||||
|
||||
# the value_id format. Some time in the future, this call (as well as the
|
||||
# helper functions) can be removed.
|
||||
async_migrate_discovered_value(ent_reg, client, disc_info)
|
||||
async_dispatcher_send(
|
||||
hass, f"{DOMAIN}_{entry.entry_id}_add_{disc_info.platform}", disc_info
|
||||
)
|
||||
|
@ -125,18 +125,10 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity):
|
||||
)
|
||||
self._setpoint_values: Dict[ThermostatSetpointType, ZwaveValue] = {}
|
||||
for enum in ThermostatSetpointType:
|
||||
# Some devices don't include a property key so we need to check for value
|
||||
# ID's, both with and without the property key
|
||||
self._setpoint_values[enum] = self.get_zwave_value(
|
||||
THERMOSTAT_SETPOINT_PROPERTY,
|
||||
command_class=CommandClass.THERMOSTAT_SETPOINT,
|
||||
value_property_key=enum.value.key,
|
||||
value_property_key_name=enum.value.name,
|
||||
add_to_watched_value_ids=True,
|
||||
) or self.get_zwave_value(
|
||||
THERMOSTAT_SETPOINT_PROPERTY,
|
||||
command_class=CommandClass.THERMOSTAT_SETPOINT,
|
||||
value_property_key_name=enum.value.name,
|
||||
add_to_watched_value_ids=True,
|
||||
)
|
||||
# Use the first found setpoint value to always determine the temperature unit
|
||||
|
@ -169,7 +169,6 @@ class ZWaveBaseEntity(Entity):
|
||||
command_class: Optional[int] = None,
|
||||
endpoint: Optional[int] = None,
|
||||
value_property_key: Optional[int] = None,
|
||||
value_property_key_name: Optional[str] = None,
|
||||
add_to_watched_value_ids: bool = True,
|
||||
check_all_endpoints: bool = False,
|
||||
) -> Optional[ZwaveValue]:
|
||||
@ -188,7 +187,6 @@ class ZWaveBaseEntity(Entity):
|
||||
value_property,
|
||||
endpoint=endpoint,
|
||||
property_key=value_property_key,
|
||||
property_key_name=value_property_key_name,
|
||||
)
|
||||
return_value = self.info.node.values.get(value_id)
|
||||
|
||||
@ -203,7 +201,6 @@ class ZWaveBaseEntity(Entity):
|
||||
value_property,
|
||||
endpoint=endpoint_.index,
|
||||
property_key=value_property_key,
|
||||
property_key_name=value_property_key_name,
|
||||
)
|
||||
return_value = self.info.node.values.get(value_id)
|
||||
if return_value:
|
||||
|
@ -3,7 +3,6 @@ from typing import List, Tuple, cast
|
||||
|
||||
from zwave_js_server.client import Client as ZwaveClient
|
||||
from zwave_js_server.model.node import Node as ZwaveNode
|
||||
from zwave_js_server.model.value import Value as ZwaveValue
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
@ -13,16 +12,6 @@ from homeassistant.helpers.entity_registry import async_get as async_get_ent_reg
|
||||
from .const import DATA_CLIENT, DOMAIN
|
||||
|
||||
|
||||
@callback
|
||||
def get_old_value_id(value: ZwaveValue) -> str:
|
||||
"""Get old value ID so we can migrate entity unique ID."""
|
||||
command_class = value.command_class
|
||||
endpoint = value.endpoint or "00"
|
||||
property_ = value.property_
|
||||
property_key_name = value.property_key_name or "00"
|
||||
return f"{value.node.node_id}-{command_class}-{endpoint}-{property_}-{property_key_name}"
|
||||
|
||||
|
||||
@callback
|
||||
def get_unique_id(home_id: str, value_id: str) -> str:
|
||||
"""Get unique ID from home ID and value ID."""
|
||||
|
@ -228,7 +228,6 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
||||
"targetColor",
|
||||
CommandClass.SWITCH_COLOR,
|
||||
value_property_key=None,
|
||||
value_property_key_name=None,
|
||||
)
|
||||
if combined_color_val and isinstance(combined_color_val.value, dict):
|
||||
colors_dict = {}
|
||||
@ -252,7 +251,6 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
||||
"targetColor",
|
||||
CommandClass.SWITCH_COLOR,
|
||||
value_property_key=property_key.key,
|
||||
value_property_key_name=property_key.name,
|
||||
)
|
||||
if target_zwave_value is None:
|
||||
# guard for unsupported color
|
||||
@ -318,31 +316,26 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
||||
"currentColor",
|
||||
CommandClass.SWITCH_COLOR,
|
||||
value_property_key=ColorComponent.RED.value.key,
|
||||
value_property_key_name=ColorComponent.RED.value.name,
|
||||
)
|
||||
green_val = self.get_zwave_value(
|
||||
"currentColor",
|
||||
CommandClass.SWITCH_COLOR,
|
||||
value_property_key=ColorComponent.GREEN.value.key,
|
||||
value_property_key_name=ColorComponent.GREEN.value.name,
|
||||
)
|
||||
blue_val = self.get_zwave_value(
|
||||
"currentColor",
|
||||
CommandClass.SWITCH_COLOR,
|
||||
value_property_key=ColorComponent.BLUE.value.key,
|
||||
value_property_key_name=ColorComponent.BLUE.value.name,
|
||||
)
|
||||
ww_val = self.get_zwave_value(
|
||||
"currentColor",
|
||||
CommandClass.SWITCH_COLOR,
|
||||
value_property_key=ColorComponent.WARM_WHITE.value.key,
|
||||
value_property_key_name=ColorComponent.WARM_WHITE.value.name,
|
||||
)
|
||||
cw_val = self.get_zwave_value(
|
||||
"currentColor",
|
||||
CommandClass.SWITCH_COLOR,
|
||||
value_property_key=ColorComponent.COLD_WHITE.value.key,
|
||||
value_property_key_name=ColorComponent.COLD_WHITE.value.name,
|
||||
)
|
||||
# prefer the (new) combined color property
|
||||
# https://github.com/zwave-js/node-zwave-js/pull/1782
|
||||
@ -350,7 +343,6 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
||||
"currentColor",
|
||||
CommandClass.SWITCH_COLOR,
|
||||
value_property_key=None,
|
||||
value_property_key_name=None,
|
||||
)
|
||||
if combined_color_val and isinstance(combined_color_val.value, dict):
|
||||
multi_color = combined_color_val.value
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Z-Wave JS",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/zwave_js",
|
||||
"requirements": ["zwave-js-server-python==0.20.1"],
|
||||
"requirements": ["zwave-js-server-python==0.21.0"],
|
||||
"codeowners": ["@home-assistant/z-wave"],
|
||||
"dependencies": ["http", "websocket_api"]
|
||||
}
|
||||
|
113
homeassistant/components/zwave_js/migrate.py
Normal file
113
homeassistant/components/zwave_js/migrate.py
Normal file
@ -0,0 +1,113 @@
|
||||
"""Functions used to migrate unique IDs for Z-Wave JS entities."""
|
||||
import logging
|
||||
from typing import List
|
||||
|
||||
from zwave_js_server.client import Client as ZwaveClient
|
||||
from zwave_js_server.model.value import Value as ZwaveValue
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.entity_registry import EntityRegistry
|
||||
|
||||
from .const import DOMAIN
|
||||
from .discovery import ZwaveDiscoveryInfo
|
||||
from .helpers import get_unique_id
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@callback
|
||||
def async_migrate_entity(
|
||||
ent_reg: EntityRegistry, platform: str, old_unique_id: str, new_unique_id: str
|
||||
) -> None:
|
||||
"""Check if entity with old unique ID exists, and if so migrate it to new ID."""
|
||||
if entity_id := ent_reg.async_get_entity_id(platform, DOMAIN, old_unique_id):
|
||||
_LOGGER.debug(
|
||||
"Migrating entity %s from old unique ID '%s' to new unique ID '%s'",
|
||||
entity_id,
|
||||
old_unique_id,
|
||||
new_unique_id,
|
||||
)
|
||||
try:
|
||||
ent_reg.async_update_entity(
|
||||
entity_id,
|
||||
new_unique_id=new_unique_id,
|
||||
)
|
||||
except ValueError:
|
||||
_LOGGER.debug(
|
||||
(
|
||||
"Entity %s can't be migrated because the unique ID is taken. "
|
||||
"Cleaning it up since it is likely no longer valid."
|
||||
),
|
||||
entity_id,
|
||||
)
|
||||
ent_reg.async_remove(entity_id)
|
||||
|
||||
|
||||
@callback
|
||||
def async_migrate_discovered_value(
|
||||
ent_reg: EntityRegistry, client: ZwaveClient, disc_info: ZwaveDiscoveryInfo
|
||||
) -> None:
|
||||
"""Migrate unique ID for entity/entities tied to discovered value."""
|
||||
new_unique_id = get_unique_id(
|
||||
client.driver.controller.home_id,
|
||||
disc_info.primary_value.value_id,
|
||||
)
|
||||
|
||||
# 2021.2.*, 2021.3.0b0, and 2021.3.0 formats
|
||||
for value_id in get_old_value_ids(disc_info.primary_value):
|
||||
old_unique_id = get_unique_id(
|
||||
client.driver.controller.home_id,
|
||||
value_id,
|
||||
)
|
||||
# Most entities have the same ID format, but notification binary sensors
|
||||
# have a state key in their ID so we need to handle them differently
|
||||
if (
|
||||
disc_info.platform == "binary_sensor"
|
||||
and disc_info.platform_hint == "notification"
|
||||
):
|
||||
for state_key in disc_info.primary_value.metadata.states:
|
||||
# ignore idle key (0)
|
||||
if state_key == "0":
|
||||
continue
|
||||
|
||||
async_migrate_entity(
|
||||
ent_reg,
|
||||
disc_info.platform,
|
||||
f"{old_unique_id}.{state_key}",
|
||||
f"{new_unique_id}.{state_key}",
|
||||
)
|
||||
|
||||
# Once we've iterated through all state keys, we can move on to the
|
||||
# next item
|
||||
continue
|
||||
|
||||
async_migrate_entity(ent_reg, disc_info.platform, old_unique_id, new_unique_id)
|
||||
|
||||
|
||||
@callback
|
||||
def get_old_value_ids(value: ZwaveValue) -> List[str]:
|
||||
"""Get old value IDs so we can migrate entity unique ID."""
|
||||
value_ids = []
|
||||
|
||||
# Pre 2021.3.0 value ID
|
||||
command_class = value.command_class
|
||||
endpoint = value.endpoint or "00"
|
||||
property_ = value.property_
|
||||
property_key_name = value.property_key_name or "00"
|
||||
value_ids.append(
|
||||
f"{value.node.node_id}.{value.node.node_id}-{command_class}-{endpoint}-"
|
||||
f"{property_}-{property_key_name}"
|
||||
)
|
||||
|
||||
endpoint = "00" if value.endpoint is None else value.endpoint
|
||||
property_key = "00" if value.property_key is None else value.property_key
|
||||
property_key_name = value.property_key_name or "00"
|
||||
|
||||
value_id = (
|
||||
f"{value.node.node_id}-{command_class}-{endpoint}-"
|
||||
f"{property_}-{property_key}-{property_key_name}"
|
||||
)
|
||||
# 2021.3.0b0 and 2021.3.0 value IDs
|
||||
value_ids.extend([f"{value.node.node_id}.{value_id}", value_id])
|
||||
|
||||
return value_ids
|
@ -2394,4 +2394,4 @@ zigpy==0.32.0
|
||||
zm-py==0.5.2
|
||||
|
||||
# homeassistant.components.zwave_js
|
||||
zwave-js-server-python==0.20.1
|
||||
zwave-js-server-python==0.21.0
|
||||
|
@ -1231,4 +1231,4 @@ zigpy-znp==0.4.0
|
||||
zigpy==0.32.0
|
||||
|
||||
# homeassistant.components.zwave_js
|
||||
zwave-js-server-python==0.20.1
|
||||
zwave-js-server-python==0.21.0
|
||||
|
@ -71,7 +71,7 @@ async def test_websocket_api(hass, integration, multisensor_6, hass_ws_client):
|
||||
result = msg["result"]
|
||||
|
||||
assert len(result) == 61
|
||||
key = "52-112-0-2-00-00"
|
||||
key = "52-112-0-2"
|
||||
assert result[key]["property"] == 2
|
||||
assert result[key]["metadata"]["type"] == "number"
|
||||
assert result[key]["configuration_value_type"] == "enumerated"
|
||||
|
@ -405,7 +405,7 @@ async def test_setpoint_thermostat(hass, client, climate_danfoss_lc_13, integrat
|
||||
|
||||
assert state
|
||||
assert state.state == HVAC_MODE_HEAT
|
||||
assert state.attributes[ATTR_TEMPERATURE] == 25
|
||||
assert state.attributes[ATTR_TEMPERATURE] == 14
|
||||
assert state.attributes[ATTR_HVAC_MODES] == [HVAC_MODE_HEAT]
|
||||
assert state.attributes[ATTR_PRESET_MODE] == PRESET_NONE
|
||||
|
||||
@ -432,6 +432,7 @@ async def test_setpoint_thermostat(hass, client, climate_danfoss_lc_13, integrat
|
||||
"commandClassName": "Thermostat Setpoint",
|
||||
"property": "setpoint",
|
||||
"propertyName": "setpoint",
|
||||
"propertyKey": 1,
|
||||
"propertyKeyName": "Heating",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
@ -441,7 +442,7 @@ async def test_setpoint_thermostat(hass, client, climate_danfoss_lc_13, integrat
|
||||
"unit": "\u00b0C",
|
||||
"ccSpecific": {"setpointType": 1},
|
||||
},
|
||||
"value": 25,
|
||||
"value": 14,
|
||||
}
|
||||
assert args["value"] == 21.5
|
||||
|
||||
@ -459,6 +460,7 @@ async def test_setpoint_thermostat(hass, client, climate_danfoss_lc_13, integrat
|
||||
"commandClass": 67,
|
||||
"endpoint": 0,
|
||||
"property": "setpoint",
|
||||
"propertyKey": 1,
|
||||
"propertyKeyName": "Heating",
|
||||
"propertyName": "setpoint",
|
||||
"newValue": 23,
|
||||
|
@ -160,7 +160,7 @@ async def test_unique_id_migration_dupes(
|
||||
|
||||
# Check that new RegistryEntry is using new unique ID format
|
||||
entity_entry = ent_reg.async_get(AIR_TEMPERATURE_SENSOR)
|
||||
new_unique_id = f"{client.driver.controller.home_id}.52-49-0-Air temperature-00-00"
|
||||
new_unique_id = f"{client.driver.controller.home_id}.52-49-0-Air temperature"
|
||||
assert entity_entry.unique_id == new_unique_id
|
||||
|
||||
assert ent_reg.async_get(f"{AIR_TEMPERATURE_SENSOR}_1") is None
|
||||
@ -195,7 +195,7 @@ async def test_unique_id_migration_v1(hass, multisensor_6_state, client, integra
|
||||
|
||||
# Check that new RegistryEntry is using new unique ID format
|
||||
entity_entry = ent_reg.async_get(AIR_TEMPERATURE_SENSOR)
|
||||
new_unique_id = f"{client.driver.controller.home_id}.52-49-0-Air temperature-00-00"
|
||||
new_unique_id = f"{client.driver.controller.home_id}.52-49-0-Air temperature"
|
||||
assert entity_entry.unique_id == new_unique_id
|
||||
|
||||
|
||||
@ -228,7 +228,147 @@ async def test_unique_id_migration_v2(hass, multisensor_6_state, client, integra
|
||||
|
||||
# Check that new RegistryEntry is using new unique ID format
|
||||
entity_entry = ent_reg.async_get(ILLUMINANCE_SENSOR)
|
||||
new_unique_id = f"{client.driver.controller.home_id}.52-49-0-Illuminance-00-00"
|
||||
new_unique_id = f"{client.driver.controller.home_id}.52-49-0-Illuminance"
|
||||
assert entity_entry.unique_id == new_unique_id
|
||||
|
||||
|
||||
async def test_unique_id_migration_v3(hass, multisensor_6_state, client, integration):
|
||||
"""Test unique ID is migrated from old format to new (version 3)."""
|
||||
ent_reg = entity_registry.async_get(hass)
|
||||
# Migrate version 2
|
||||
ILLUMINANCE_SENSOR = "sensor.multisensor_6_illuminance"
|
||||
entity_name = ILLUMINANCE_SENSOR.split(".")[1]
|
||||
|
||||
# Create entity RegistryEntry using old unique ID format
|
||||
old_unique_id = f"{client.driver.controller.home_id}.52-49-0-Illuminance-00-00"
|
||||
entity_entry = ent_reg.async_get_or_create(
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
old_unique_id,
|
||||
suggested_object_id=entity_name,
|
||||
config_entry=integration,
|
||||
original_name=entity_name,
|
||||
)
|
||||
assert entity_entry.entity_id == ILLUMINANCE_SENSOR
|
||||
assert entity_entry.unique_id == old_unique_id
|
||||
|
||||
# Add a ready node, unique ID should be migrated
|
||||
node = Node(client, multisensor_6_state)
|
||||
event = {"node": node}
|
||||
|
||||
client.driver.controller.emit("node added", event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check that new RegistryEntry is using new unique ID format
|
||||
entity_entry = ent_reg.async_get(ILLUMINANCE_SENSOR)
|
||||
new_unique_id = f"{client.driver.controller.home_id}.52-49-0-Illuminance"
|
||||
assert entity_entry.unique_id == new_unique_id
|
||||
|
||||
|
||||
async def test_unique_id_migration_property_key_v1(
|
||||
hass, hank_binary_switch_state, client, integration
|
||||
):
|
||||
"""Test unique ID with property key is migrated from old format to new (version 1)."""
|
||||
ent_reg = entity_registry.async_get(hass)
|
||||
|
||||
SENSOR_NAME = "sensor.smart_plug_with_two_usb_ports_value_electric_consumed"
|
||||
entity_name = SENSOR_NAME.split(".")[1]
|
||||
|
||||
# Create entity RegistryEntry using old unique ID format
|
||||
old_unique_id = f"{client.driver.controller.home_id}.32.32-50-00-value-W_Consumed"
|
||||
entity_entry = ent_reg.async_get_or_create(
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
old_unique_id,
|
||||
suggested_object_id=entity_name,
|
||||
config_entry=integration,
|
||||
original_name=entity_name,
|
||||
)
|
||||
assert entity_entry.entity_id == SENSOR_NAME
|
||||
assert entity_entry.unique_id == old_unique_id
|
||||
|
||||
# Add a ready node, unique ID should be migrated
|
||||
node = Node(client, hank_binary_switch_state)
|
||||
event = {"node": node}
|
||||
|
||||
client.driver.controller.emit("node added", event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check that new RegistryEntry is using new unique ID format
|
||||
entity_entry = ent_reg.async_get(SENSOR_NAME)
|
||||
new_unique_id = f"{client.driver.controller.home_id}.32-50-0-value-66049"
|
||||
assert entity_entry.unique_id == new_unique_id
|
||||
|
||||
|
||||
async def test_unique_id_migration_property_key_v2(
|
||||
hass, hank_binary_switch_state, client, integration
|
||||
):
|
||||
"""Test unique ID with property key is migrated from old format to new (version 2)."""
|
||||
ent_reg = entity_registry.async_get(hass)
|
||||
|
||||
SENSOR_NAME = "sensor.smart_plug_with_two_usb_ports_value_electric_consumed"
|
||||
entity_name = SENSOR_NAME.split(".")[1]
|
||||
|
||||
# Create entity RegistryEntry using old unique ID format
|
||||
old_unique_id = (
|
||||
f"{client.driver.controller.home_id}.32.32-50-0-value-66049-W_Consumed"
|
||||
)
|
||||
entity_entry = ent_reg.async_get_or_create(
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
old_unique_id,
|
||||
suggested_object_id=entity_name,
|
||||
config_entry=integration,
|
||||
original_name=entity_name,
|
||||
)
|
||||
assert entity_entry.entity_id == SENSOR_NAME
|
||||
assert entity_entry.unique_id == old_unique_id
|
||||
|
||||
# Add a ready node, unique ID should be migrated
|
||||
node = Node(client, hank_binary_switch_state)
|
||||
event = {"node": node}
|
||||
|
||||
client.driver.controller.emit("node added", event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check that new RegistryEntry is using new unique ID format
|
||||
entity_entry = ent_reg.async_get(SENSOR_NAME)
|
||||
new_unique_id = f"{client.driver.controller.home_id}.32-50-0-value-66049"
|
||||
assert entity_entry.unique_id == new_unique_id
|
||||
|
||||
|
||||
async def test_unique_id_migration_property_key_v3(
|
||||
hass, hank_binary_switch_state, client, integration
|
||||
):
|
||||
"""Test unique ID with property key is migrated from old format to new (version 3)."""
|
||||
ent_reg = entity_registry.async_get(hass)
|
||||
|
||||
SENSOR_NAME = "sensor.smart_plug_with_two_usb_ports_value_electric_consumed"
|
||||
entity_name = SENSOR_NAME.split(".")[1]
|
||||
|
||||
# Create entity RegistryEntry using old unique ID format
|
||||
old_unique_id = f"{client.driver.controller.home_id}.32-50-0-value-66049-W_Consumed"
|
||||
entity_entry = ent_reg.async_get_or_create(
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
old_unique_id,
|
||||
suggested_object_id=entity_name,
|
||||
config_entry=integration,
|
||||
original_name=entity_name,
|
||||
)
|
||||
assert entity_entry.entity_id == SENSOR_NAME
|
||||
assert entity_entry.unique_id == old_unique_id
|
||||
|
||||
# Add a ready node, unique ID should be migrated
|
||||
node = Node(client, hank_binary_switch_state)
|
||||
event = {"node": node}
|
||||
|
||||
client.driver.controller.emit("node added", event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check that new RegistryEntry is using new unique ID format
|
||||
entity_entry = ent_reg.async_get(SENSOR_NAME)
|
||||
new_unique_id = f"{client.driver.controller.home_id}.32-50-0-value-66049"
|
||||
assert entity_entry.unique_id == new_unique_id
|
||||
|
||||
|
||||
@ -262,7 +402,7 @@ async def test_unique_id_migration_notification_binary_sensor(
|
||||
|
||||
# Check that new RegistryEntry is using new unique ID format
|
||||
entity_entry = ent_reg.async_get(NOTIFICATION_MOTION_BINARY_SENSOR)
|
||||
new_unique_id = f"{client.driver.controller.home_id}.52-113-0-Home Security-Motion sensor status-Motion sensor status.8"
|
||||
new_unique_id = f"{client.driver.controller.home_id}.52-113-0-Home Security-Motion sensor status.8"
|
||||
assert entity_entry.unique_id == new_unique_id
|
||||
|
||||
|
||||
|
@ -4,11 +4,25 @@
|
||||
"status": 1,
|
||||
"ready": true,
|
||||
"deviceClass": {
|
||||
"basic": {"key": 4, "label":"Routing Slave"},
|
||||
"generic": {"key": 8, "label":"Thermostat"},
|
||||
"specific": {"key": 4, "label":"Setpoint Thermostat"},
|
||||
"mandatorySupportedCCs": [],
|
||||
"mandatoryControlCCs": []
|
||||
"basic": {
|
||||
"key": 4,
|
||||
"label": "Routing Slave"
|
||||
},
|
||||
"generic": {
|
||||
"key": 8,
|
||||
"label": "Thermostat"
|
||||
},
|
||||
"specific": {
|
||||
"key": 4,
|
||||
"label": "Setpoint Thermostat"
|
||||
},
|
||||
"mandatorySupportedCCs": [
|
||||
114,
|
||||
143,
|
||||
67,
|
||||
134
|
||||
],
|
||||
"mandatoryControlledCCs": []
|
||||
},
|
||||
"isListening": false,
|
||||
"isFrequentListening": false,
|
||||
@ -22,6 +36,7 @@
|
||||
"productType": 5,
|
||||
"firmwareVersion": "1.1",
|
||||
"deviceConfig": {
|
||||
"filename": "/usr/src/app/node_modules/@zwave-js/config/config/devices/0x0002/lc-13.json",
|
||||
"manufacturerId": 2,
|
||||
"manufacturer": "Danfoss",
|
||||
"label": "LC-13",
|
||||
@ -66,19 +81,76 @@
|
||||
14
|
||||
],
|
||||
"interviewAttempts": 1,
|
||||
"interviewStage": 7,
|
||||
"commandClasses": [
|
||||
{
|
||||
"id": 67,
|
||||
"name": "Thermostat Setpoint",
|
||||
"version": 2,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 70,
|
||||
"name": "Climate Control Schedule",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 114,
|
||||
"name": "Manufacturer Specific",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 117,
|
||||
"name": "Protection",
|
||||
"version": 2,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 128,
|
||||
"name": "Battery",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 129,
|
||||
"name": "Clock",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 132,
|
||||
"name": "Wake Up",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 134,
|
||||
"name": "Version",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 143,
|
||||
"name": "Multi Command",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
}
|
||||
],
|
||||
"endpoints": [
|
||||
{
|
||||
"nodeId": 5,
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
"commandClasses": [],
|
||||
"values": [
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 67,
|
||||
"commandClassName": "Thermostat Setpoint",
|
||||
"property": "setpoint",
|
||||
"propertyKey": 1,
|
||||
"propertyName": "setpoint",
|
||||
"propertyKeyName": "Heating",
|
||||
"ccVersion": 2,
|
||||
@ -91,7 +163,7 @@
|
||||
"setpointType": 1
|
||||
}
|
||||
},
|
||||
"value": 25
|
||||
"value": 14
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
@ -262,7 +334,7 @@
|
||||
"unit": "%",
|
||||
"label": "Battery level"
|
||||
},
|
||||
"value": 53
|
||||
"value": 49
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
@ -361,4 +433,4 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -837,6 +837,7 @@
|
||||
"commandClassName": "Thermostat Setpoint",
|
||||
"property": "setpoint",
|
||||
"propertyName": "setpoint",
|
||||
"propertyKey": 1,
|
||||
"propertyKeyName": "Heating",
|
||||
"ccVersion": 3,
|
||||
"metadata": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user