mirror of
https://github.com/home-assistant/core.git
synced 2025-07-11 23:37:18 +00:00
Convert val to str when needed while calling zwave_js.set_value (#57216)
This commit is contained in:
parent
33b8130002
commit
3476b430db
@ -408,7 +408,7 @@ class ZWaveServices:
|
|||||||
async def async_set_value(self, service: ServiceCall) -> None:
|
async def async_set_value(self, service: ServiceCall) -> None:
|
||||||
"""Set a value on a node."""
|
"""Set a value on a node."""
|
||||||
# pylint: disable=no-self-use
|
# 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]
|
command_class = service.data[const.ATTR_COMMAND_CLASS]
|
||||||
property_ = service.data[const.ATTR_PROPERTY]
|
property_ = service.data[const.ATTR_PROPERTY]
|
||||||
property_key = service.data.get(const.ATTR_PROPERTY_KEY)
|
property_key = service.data.get(const.ATTR_PROPERTY_KEY)
|
||||||
@ -418,15 +418,27 @@ class ZWaveServices:
|
|||||||
options = service.data.get(const.ATTR_OPTIONS)
|
options = service.data.get(const.ATTR_OPTIONS)
|
||||||
|
|
||||||
for node in nodes:
|
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(
|
success = await node.async_set_value(
|
||||||
get_value_id(
|
value_id,
|
||||||
node,
|
new_value_,
|
||||||
command_class,
|
|
||||||
property_,
|
|
||||||
endpoint=endpoint,
|
|
||||||
property_key=property_key,
|
|
||||||
),
|
|
||||||
new_value,
|
|
||||||
options=options,
|
options=options,
|
||||||
wait_for_result=wait_for_result,
|
wait_for_result=wait_for_result,
|
||||||
)
|
)
|
||||||
@ -452,11 +464,16 @@ class ZWaveServices:
|
|||||||
await self.async_set_value(service)
|
await self.async_set_value(service)
|
||||||
return
|
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 = {
|
value = {
|
||||||
"commandClass": service.data[const.ATTR_COMMAND_CLASS],
|
"commandClass": command_class,
|
||||||
"property": service.data[const.ATTR_PROPERTY],
|
"property": property_,
|
||||||
"propertyKey": service.data.get(const.ATTR_PROPERTY_KEY),
|
"propertyKey": property_key,
|
||||||
"endpoint": service.data.get(const.ATTR_ENDPOINT),
|
"endpoint": endpoint,
|
||||||
}
|
}
|
||||||
new_value = service.data[const.ATTR_VALUE]
|
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
|
# schema validation and can use that to get the client, otherwise we can just
|
||||||
# get the client from the node.
|
# get the client from the node.
|
||||||
client: ZwaveClient = None
|
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:
|
if first_node:
|
||||||
client = first_node.client
|
client = first_node.client
|
||||||
else:
|
else:
|
||||||
entry_id = self._hass.config_entries.async_entries(const.DOMAIN)[0].entry_id
|
entry_id = self._hass.config_entries.async_entries(const.DOMAIN)[0].entry_id
|
||||||
client = self._hass.data[const.DOMAIN][entry_id][const.DATA_CLIENT]
|
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(
|
success = await async_multicast_set_value(
|
||||||
client=client,
|
client=client,
|
||||||
|
@ -43,6 +43,7 @@ from .common import (
|
|||||||
CLIMATE_DANFOSS_LC13_ENTITY,
|
CLIMATE_DANFOSS_LC13_ENTITY,
|
||||||
CLIMATE_EUROTRONICS_SPIRIT_Z_ENTITY,
|
CLIMATE_EUROTRONICS_SPIRIT_Z_ENTITY,
|
||||||
CLIMATE_RADIO_THERMOSTAT_ENTITY,
|
CLIMATE_RADIO_THERMOSTAT_ENTITY,
|
||||||
|
SCHLAGE_BE469_LOCK_ENTITY,
|
||||||
)
|
)
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
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):
|
async def test_set_value_options(hass, client, aeon_smart_switch_6, integration):
|
||||||
"""Test set_value service with options."""
|
"""Test set_value service with options."""
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
@ -1381,6 +1427,41 @@ async def test_multicast_set_value_options(
|
|||||||
client.async_send_command.reset_mock()
|
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(
|
async def test_ping(
|
||||||
hass,
|
hass,
|
||||||
client,
|
client,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user