Convert val to str when needed while calling zwave_js.set_value (#57216)
This commit is contained in:
parent
33b8130002
commit
3476b430db
2 changed files with 130 additions and 14 deletions
|
@ -408,7 +408,7 @@ class ZWaveServices:
|
|||
async def async_set_value(self, service: ServiceCall) -> None:
|
||||
"""Set a value on a node."""
|
||||
# pylint: disable=no-self-use
|
||||
nodes = service.data[const.ATTR_NODES]
|
||||
nodes: set[ZwaveNode] = service.data[const.ATTR_NODES]
|
||||
command_class = service.data[const.ATTR_COMMAND_CLASS]
|
||||
property_ = service.data[const.ATTR_PROPERTY]
|
||||
property_key = service.data.get(const.ATTR_PROPERTY_KEY)
|
||||
|
@ -418,15 +418,27 @@ class ZWaveServices:
|
|||
options = service.data.get(const.ATTR_OPTIONS)
|
||||
|
||||
for node in nodes:
|
||||
value_id = get_value_id(
|
||||
node,
|
||||
command_class,
|
||||
property_,
|
||||
endpoint=endpoint,
|
||||
property_key=property_key,
|
||||
)
|
||||
# If value has a string type but the new value is not a string, we need to
|
||||
# convert it to one. We use new variable `new_value_` to convert the data
|
||||
# so we can preserve the original `new_value` for every node.
|
||||
if (
|
||||
value_id in node.values
|
||||
and node.values[value_id].metadata.type == "string"
|
||||
and not isinstance(new_value, str)
|
||||
):
|
||||
new_value_ = str(new_value)
|
||||
else:
|
||||
new_value_ = new_value
|
||||
success = await node.async_set_value(
|
||||
get_value_id(
|
||||
node,
|
||||
command_class,
|
||||
property_,
|
||||
endpoint=endpoint,
|
||||
property_key=property_key,
|
||||
),
|
||||
new_value,
|
||||
value_id,
|
||||
new_value_,
|
||||
options=options,
|
||||
wait_for_result=wait_for_result,
|
||||
)
|
||||
|
@ -452,11 +464,16 @@ class ZWaveServices:
|
|||
await self.async_set_value(service)
|
||||
return
|
||||
|
||||
command_class = service.data[const.ATTR_COMMAND_CLASS]
|
||||
property_ = service.data[const.ATTR_PROPERTY]
|
||||
property_key = service.data.get(const.ATTR_PROPERTY_KEY)
|
||||
endpoint = service.data.get(const.ATTR_ENDPOINT)
|
||||
|
||||
value = {
|
||||
"commandClass": service.data[const.ATTR_COMMAND_CLASS],
|
||||
"property": service.data[const.ATTR_PROPERTY],
|
||||
"propertyKey": service.data.get(const.ATTR_PROPERTY_KEY),
|
||||
"endpoint": service.data.get(const.ATTR_ENDPOINT),
|
||||
"commandClass": command_class,
|
||||
"property": property_,
|
||||
"propertyKey": property_key,
|
||||
"endpoint": endpoint,
|
||||
}
|
||||
new_value = service.data[const.ATTR_VALUE]
|
||||
|
||||
|
@ -464,12 +481,30 @@ class ZWaveServices:
|
|||
# schema validation and can use that to get the client, otherwise we can just
|
||||
# get the client from the node.
|
||||
client: ZwaveClient = None
|
||||
first_node = next((node for node in nodes), None)
|
||||
first_node: ZwaveNode = next((node for node in nodes), None)
|
||||
if first_node:
|
||||
client = first_node.client
|
||||
else:
|
||||
entry_id = self._hass.config_entries.async_entries(const.DOMAIN)[0].entry_id
|
||||
client = self._hass.data[const.DOMAIN][entry_id][const.DATA_CLIENT]
|
||||
first_node = next(
|
||||
node
|
||||
for node in client.driver.controller.nodes.values()
|
||||
if get_value_id(node, command_class, property_, endpoint, property_key)
|
||||
in node.values
|
||||
)
|
||||
|
||||
# If value has a string type but the new value is not a string, we need to
|
||||
# convert it to one
|
||||
value_id = get_value_id(
|
||||
first_node, command_class, property_, endpoint, property_key
|
||||
)
|
||||
if (
|
||||
value_id in first_node.values
|
||||
and first_node.values[value_id].metadata.type == "string"
|
||||
and not isinstance(new_value, str)
|
||||
):
|
||||
new_value = str(new_value)
|
||||
|
||||
success = await async_multicast_set_value(
|
||||
client=client,
|
||||
|
|
|
@ -43,6 +43,7 @@ from .common import (
|
|||
CLIMATE_DANFOSS_LC13_ENTITY,
|
||||
CLIMATE_EUROTRONICS_SPIRIT_Z_ENTITY,
|
||||
CLIMATE_RADIO_THERMOSTAT_ENTITY,
|
||||
SCHLAGE_BE469_LOCK_ENTITY,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
@ -1021,6 +1022,51 @@ async def test_set_value(hass, client, climate_danfoss_lc_13, integration):
|
|||
)
|
||||
|
||||
|
||||
async def test_set_value_string(
|
||||
hass, client, climate_danfoss_lc_13, lock_schlage_be469, integration
|
||||
):
|
||||
"""Test set_value service converts number to string when needed."""
|
||||
client.async_send_command.return_value = {"success": True}
|
||||
|
||||
# Test that number gets converted to a string when needed
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SET_VALUE,
|
||||
{
|
||||
ATTR_ENTITY_ID: SCHLAGE_BE469_LOCK_ENTITY,
|
||||
ATTR_COMMAND_CLASS: 99,
|
||||
ATTR_PROPERTY: "userCode",
|
||||
ATTR_PROPERTY_KEY: 1,
|
||||
ATTR_VALUE: 12345,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(client.async_send_command.call_args_list) == 1
|
||||
args = client.async_send_command.call_args[0][0]
|
||||
assert args["command"] == "node.set_value"
|
||||
assert args["nodeId"] == lock_schlage_be469.node_id
|
||||
assert args["valueId"] == {
|
||||
"commandClassName": "User Code",
|
||||
"commandClass": 99,
|
||||
"endpoint": 0,
|
||||
"property": "userCode",
|
||||
"propertyName": "userCode",
|
||||
"propertyKey": 1,
|
||||
"propertyKeyName": "1",
|
||||
"metadata": {
|
||||
"type": "string",
|
||||
"readable": True,
|
||||
"writeable": True,
|
||||
"minLength": 4,
|
||||
"maxLength": 10,
|
||||
"label": "User Code (1)",
|
||||
},
|
||||
"value": "**********",
|
||||
}
|
||||
assert args["value"] == "12345"
|
||||
|
||||
|
||||
async def test_set_value_options(hass, client, aeon_smart_switch_6, integration):
|
||||
"""Test set_value service with options."""
|
||||
await hass.services.async_call(
|
||||
|
@ -1381,6 +1427,41 @@ async def test_multicast_set_value_options(
|
|||
client.async_send_command.reset_mock()
|
||||
|
||||
|
||||
async def test_multicast_set_value_string(
|
||||
hass,
|
||||
client,
|
||||
lock_id_lock_as_id150,
|
||||
lock_schlage_be469,
|
||||
integration,
|
||||
):
|
||||
"""Test multicast_set_value service converts number to string when needed."""
|
||||
client.async_send_command.return_value = {"success": True}
|
||||
|
||||
# Test that number gets converted to a string when needed
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_MULTICAST_SET_VALUE,
|
||||
{
|
||||
ATTR_BROADCAST: True,
|
||||
ATTR_COMMAND_CLASS: 99,
|
||||
ATTR_PROPERTY: "userCode",
|
||||
ATTR_PROPERTY_KEY: 1,
|
||||
ATTR_VALUE: 12345,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(client.async_send_command.call_args_list) == 1
|
||||
args = client.async_send_command.call_args[0][0]
|
||||
assert args["command"] == "broadcast_node.set_value"
|
||||
assert args["valueId"] == {
|
||||
"commandClass": 99,
|
||||
"property": "userCode",
|
||||
"propertyKey": 1,
|
||||
}
|
||||
assert args["value"] == "12345"
|
||||
|
||||
|
||||
async def test_ping(
|
||||
hass,
|
||||
client,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue