mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Expand zwave_js.set_config_parameter
with additional parameters (#102092)
This commit is contained in:
parent
1a51d863cf
commit
f511a8a26a
@ -106,6 +106,8 @@ ATTR_NODES = "nodes"
|
|||||||
ATTR_CONFIG_PARAMETER = "parameter"
|
ATTR_CONFIG_PARAMETER = "parameter"
|
||||||
ATTR_CONFIG_PARAMETER_BITMASK = "bitmask"
|
ATTR_CONFIG_PARAMETER_BITMASK = "bitmask"
|
||||||
ATTR_CONFIG_VALUE = "value"
|
ATTR_CONFIG_VALUE = "value"
|
||||||
|
ATTR_VALUE_SIZE = "value_size"
|
||||||
|
ATTR_VALUE_FORMAT = "value_format"
|
||||||
# refresh value
|
# refresh value
|
||||||
ATTR_REFRESH_ALL_VALUES = "refresh_all_values"
|
ATTR_REFRESH_ALL_VALUES = "refresh_all_values"
|
||||||
# multicast
|
# multicast
|
||||||
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
import asyncio
|
import asyncio
|
||||||
from collections.abc import Generator, Sequence
|
from collections.abc import Generator, Sequence
|
||||||
import logging
|
import logging
|
||||||
|
import math
|
||||||
from typing import Any, TypeVar
|
from typing import Any, TypeVar
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -13,7 +14,11 @@ from zwave_js_server.const.command_class.notification import NotificationType
|
|||||||
from zwave_js_server.exceptions import FailedZWaveCommand, SetValueFailed
|
from zwave_js_server.exceptions import FailedZWaveCommand, SetValueFailed
|
||||||
from zwave_js_server.model.endpoint import Endpoint
|
from zwave_js_server.model.endpoint import Endpoint
|
||||||
from zwave_js_server.model.node import Node as ZwaveNode
|
from zwave_js_server.model.node import Node as ZwaveNode
|
||||||
from zwave_js_server.model.value import ValueDataType, get_value_id_str
|
from zwave_js_server.model.value import (
|
||||||
|
ConfigurationValueFormat,
|
||||||
|
ValueDataType,
|
||||||
|
get_value_id_str,
|
||||||
|
)
|
||||||
from zwave_js_server.util.multicast import async_multicast_set_value
|
from zwave_js_server.util.multicast import async_multicast_set_value
|
||||||
from zwave_js_server.util.node import (
|
from zwave_js_server.util.node import (
|
||||||
async_bulk_set_partial_config_parameters,
|
async_bulk_set_partial_config_parameters,
|
||||||
@ -58,6 +63,13 @@ def parameter_name_does_not_need_bitmask(
|
|||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
def check_base_2(val: int) -> int:
|
||||||
|
"""Check if value is a power of 2."""
|
||||||
|
if not math.log2(val).is_integer():
|
||||||
|
raise vol.Invalid("Value must be a power of 2.")
|
||||||
|
return val
|
||||||
|
|
||||||
|
|
||||||
def broadcast_command(val: dict[str, Any]) -> dict[str, Any]:
|
def broadcast_command(val: dict[str, Any]) -> dict[str, Any]:
|
||||||
"""Validate that the service call is for a broadcast command."""
|
"""Validate that the service call is for a broadcast command."""
|
||||||
if val.get(const.ATTR_BROADCAST):
|
if val.get(const.ATTR_BROADCAST):
|
||||||
@ -78,10 +90,10 @@ def get_valid_responses_from_results(
|
|||||||
|
|
||||||
|
|
||||||
def raise_exceptions_from_results(
|
def raise_exceptions_from_results(
|
||||||
zwave_objects: Sequence[ZwaveNode | Endpoint],
|
zwave_objects: Sequence[T], results: Sequence[Any]
|
||||||
results: Sequence[Any],
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Raise list of exceptions from a list of results."""
|
"""Raise list of exceptions from a list of results."""
|
||||||
|
errors: Sequence[tuple[T, Any]]
|
||||||
if errors := [
|
if errors := [
|
||||||
tup for tup in zip(zwave_objects, results) if isinstance(tup[1], Exception)
|
tup for tup in zip(zwave_objects, results) if isinstance(tup[1], Exception)
|
||||||
]:
|
]:
|
||||||
@ -263,10 +275,19 @@ class ZWaveServices:
|
|||||||
vol.Required(const.ATTR_CONFIG_VALUE): vol.Any(
|
vol.Required(const.ATTR_CONFIG_VALUE): vol.Any(
|
||||||
vol.Coerce(int), BITMASK_SCHEMA, cv.string
|
vol.Coerce(int), BITMASK_SCHEMA, cv.string
|
||||||
),
|
),
|
||||||
|
vol.Inclusive(const.ATTR_VALUE_SIZE, "raw"): vol.All(
|
||||||
|
vol.Coerce(int), vol.Range(min=1, max=4), check_base_2
|
||||||
|
),
|
||||||
|
vol.Inclusive(const.ATTR_VALUE_FORMAT, "raw"): vol.Coerce(
|
||||||
|
ConfigurationValueFormat
|
||||||
|
),
|
||||||
},
|
},
|
||||||
cv.has_at_least_one_key(
|
cv.has_at_least_one_key(
|
||||||
ATTR_DEVICE_ID, ATTR_ENTITY_ID, ATTR_AREA_ID
|
ATTR_DEVICE_ID, ATTR_ENTITY_ID, ATTR_AREA_ID
|
||||||
),
|
),
|
||||||
|
cv.has_at_most_one_key(
|
||||||
|
const.ATTR_CONFIG_PARAMETER_BITMASK, const.ATTR_VALUE_SIZE
|
||||||
|
),
|
||||||
parameter_name_does_not_need_bitmask,
|
parameter_name_does_not_need_bitmask,
|
||||||
get_nodes_from_service_data,
|
get_nodes_from_service_data,
|
||||||
has_at_least_one_node,
|
has_at_least_one_node,
|
||||||
@ -487,7 +508,33 @@ class ZWaveServices:
|
|||||||
property_or_property_name = service.data[const.ATTR_CONFIG_PARAMETER]
|
property_or_property_name = service.data[const.ATTR_CONFIG_PARAMETER]
|
||||||
property_key = service.data.get(const.ATTR_CONFIG_PARAMETER_BITMASK)
|
property_key = service.data.get(const.ATTR_CONFIG_PARAMETER_BITMASK)
|
||||||
new_value = service.data[const.ATTR_CONFIG_VALUE]
|
new_value = service.data[const.ATTR_CONFIG_VALUE]
|
||||||
|
value_size = service.data.get(const.ATTR_VALUE_SIZE)
|
||||||
|
value_format = service.data.get(const.ATTR_VALUE_FORMAT)
|
||||||
|
|
||||||
|
nodes_without_endpoints: set[ZwaveNode] = set()
|
||||||
|
# Remove nodes that don't have the specified endpoint
|
||||||
|
for node in nodes:
|
||||||
|
if endpoint not in node.endpoints:
|
||||||
|
nodes_without_endpoints.add(node)
|
||||||
|
nodes = nodes.difference(nodes_without_endpoints)
|
||||||
|
if not nodes:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
"None of the specified nodes have the specified endpoint"
|
||||||
|
)
|
||||||
|
if nodes_without_endpoints and _LOGGER.isEnabledFor(logging.WARNING):
|
||||||
|
_LOGGER.warning(
|
||||||
|
(
|
||||||
|
"The following nodes do not have endpoint %x and will be "
|
||||||
|
"skipped: %s"
|
||||||
|
),
|
||||||
|
endpoint,
|
||||||
|
nodes_without_endpoints,
|
||||||
|
)
|
||||||
|
|
||||||
|
# If value_size isn't provided, we will use the utility function which includes
|
||||||
|
# additional checks and protections. If it is provided, we will use the
|
||||||
|
# node.async_set_raw_config_parameter_value method which calls the
|
||||||
|
# Configuration CC set API.
|
||||||
results = await asyncio.gather(
|
results = await asyncio.gather(
|
||||||
*(
|
*(
|
||||||
async_set_config_parameter(
|
async_set_config_parameter(
|
||||||
@ -497,23 +544,42 @@ class ZWaveServices:
|
|||||||
property_key=property_key,
|
property_key=property_key,
|
||||||
endpoint=endpoint,
|
endpoint=endpoint,
|
||||||
)
|
)
|
||||||
|
if value_size is None
|
||||||
|
else node.endpoints[endpoint].async_set_raw_config_parameter_value(
|
||||||
|
new_value,
|
||||||
|
property_or_property_name,
|
||||||
|
property_key=property_key,
|
||||||
|
value_size=value_size,
|
||||||
|
value_format=value_format,
|
||||||
|
)
|
||||||
for node in nodes
|
for node in nodes
|
||||||
),
|
),
|
||||||
return_exceptions=True,
|
return_exceptions=True,
|
||||||
)
|
)
|
||||||
nodes_list = list(nodes)
|
|
||||||
for node, result in get_valid_responses_from_results(nodes_list, results):
|
def process_results(
|
||||||
zwave_value = result[0]
|
nodes_or_endpoints_list: list[T], _results: list[Any]
|
||||||
cmd_status = result[1]
|
) -> None:
|
||||||
if cmd_status == CommandStatus.ACCEPTED:
|
"""Process results for given nodes or endpoints."""
|
||||||
msg = "Set configuration parameter %s on Node %s with value %s"
|
for node_or_endpoint, result in get_valid_responses_from_results(
|
||||||
else:
|
nodes_or_endpoints_list, _results
|
||||||
msg = (
|
):
|
||||||
"Added command to queue to set configuration parameter %s on Node "
|
zwave_value = result[0]
|
||||||
"%s with value %s. Parameter will be set when the device wakes up"
|
cmd_status = result[1]
|
||||||
)
|
if cmd_status.status == CommandStatus.ACCEPTED:
|
||||||
_LOGGER.info(msg, zwave_value, node, new_value)
|
msg = "Set configuration parameter %s on Node %s with value %s"
|
||||||
raise_exceptions_from_results(nodes_list, results)
|
else:
|
||||||
|
msg = (
|
||||||
|
"Added command to queue to set configuration parameter %s on %s "
|
||||||
|
"with value %s. Parameter will be set when the device wakes up"
|
||||||
|
)
|
||||||
|
_LOGGER.info(msg, zwave_value, node_or_endpoint, new_value)
|
||||||
|
raise_exceptions_from_results(nodes_or_endpoints_list, _results)
|
||||||
|
|
||||||
|
if value_size is None:
|
||||||
|
process_results(list(nodes), results)
|
||||||
|
else:
|
||||||
|
process_results([node.endpoints[endpoint] for node in nodes], results)
|
||||||
|
|
||||||
async def async_bulk_set_partial_config_parameters(
|
async def async_bulk_set_partial_config_parameters(
|
||||||
self, service: ServiceCall
|
self, service: ServiceCall
|
||||||
@ -605,7 +671,7 @@ class ZWaveServices:
|
|||||||
results = await asyncio.gather(*coros, return_exceptions=True)
|
results = await asyncio.gather(*coros, return_exceptions=True)
|
||||||
nodes_list = list(nodes)
|
nodes_list = list(nodes)
|
||||||
# multiple set_values my fail so we will track the entire list
|
# multiple set_values my fail so we will track the entire list
|
||||||
set_value_failed_nodes_list: list[ZwaveNode | Endpoint] = []
|
set_value_failed_nodes_list: list[ZwaveNode] = []
|
||||||
set_value_failed_error_list: list[SetValueFailed] = []
|
set_value_failed_error_list: list[SetValueFailed] = []
|
||||||
for node_, result in get_valid_responses_from_results(nodes_list, results):
|
for node_, result in get_valid_responses_from_results(nodes_list, results):
|
||||||
if result and result.status not in SET_VALUE_SUCCESS:
|
if result and result.status not in SET_VALUE_SUCCESS:
|
||||||
|
@ -54,6 +54,18 @@ set_config_parameter:
|
|||||||
required: true
|
required: true
|
||||||
selector:
|
selector:
|
||||||
text:
|
text:
|
||||||
|
value_size:
|
||||||
|
example: 1
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
min: 1
|
||||||
|
max: 4
|
||||||
|
value_format:
|
||||||
|
example: 1
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
min: 0
|
||||||
|
max: 3
|
||||||
|
|
||||||
bulk_set_partial_config_parameters:
|
bulk_set_partial_config_parameters:
|
||||||
target:
|
target:
|
||||||
|
@ -216,11 +216,19 @@
|
|||||||
},
|
},
|
||||||
"bitmask": {
|
"bitmask": {
|
||||||
"name": "Bitmask",
|
"name": "Bitmask",
|
||||||
"description": "Target a specific bitmask (see the documentation for more information)."
|
"description": "Target a specific bitmask (see the documentation for more information). Cannot be combined with value_size or value_format."
|
||||||
},
|
},
|
||||||
"value": {
|
"value": {
|
||||||
"name": "Value",
|
"name": "Value",
|
||||||
"description": "The new value to set for this configuration parameter."
|
"description": "The new value to set for this configuration parameter."
|
||||||
|
},
|
||||||
|
"value_size": {
|
||||||
|
"name": "Value size",
|
||||||
|
"description": "Size of the value, either 1, 2, or 4. Used in combination with value_format when a config parameter is not defined in your device's configuration file. Cannot be combined with bitmask."
|
||||||
|
},
|
||||||
|
"value_format": {
|
||||||
|
"name": "Value format",
|
||||||
|
"description": "Format of the value, 0 for signed integer, 1 for unsigned integer, 2 for enumerated, 3 for bitfield. Used in combination with value_size when a config parameter is not defined in your device's configuration file. Cannot be combined with bitmask."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -4,6 +4,7 @@ from unittest.mock import MagicMock, patch
|
|||||||
import pytest
|
import pytest
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from zwave_js_server.exceptions import FailedZWaveCommand
|
from zwave_js_server.exceptions import FailedZWaveCommand
|
||||||
|
from zwave_js_server.model.value import SetConfigParameterResult
|
||||||
|
|
||||||
from homeassistant.components.group import Group
|
from homeassistant.components.group import Group
|
||||||
from homeassistant.components.zwave_js.const import (
|
from homeassistant.components.zwave_js.const import (
|
||||||
@ -22,6 +23,8 @@ from homeassistant.components.zwave_js.const import (
|
|||||||
ATTR_PROPERTY_KEY,
|
ATTR_PROPERTY_KEY,
|
||||||
ATTR_REFRESH_ALL_VALUES,
|
ATTR_REFRESH_ALL_VALUES,
|
||||||
ATTR_VALUE,
|
ATTR_VALUE,
|
||||||
|
ATTR_VALUE_FORMAT,
|
||||||
|
ATTR_VALUE_SIZE,
|
||||||
ATTR_WAIT_FOR_RESULT,
|
ATTR_WAIT_FOR_RESULT,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
SERVICE_BULK_SET_PARTIAL_CONFIG_PARAMETERS,
|
SERVICE_BULK_SET_PARTIAL_CONFIG_PARAMETERS,
|
||||||
@ -56,7 +59,12 @@ from tests.common import MockConfigEntry
|
|||||||
|
|
||||||
|
|
||||||
async def test_set_config_parameter(
|
async def test_set_config_parameter(
|
||||||
hass: HomeAssistant, client, multisensor_6, integration
|
hass: HomeAssistant,
|
||||||
|
client,
|
||||||
|
multisensor_6,
|
||||||
|
aeotec_zw164_siren,
|
||||||
|
integration,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test the set_config_parameter service."""
|
"""Test the set_config_parameter service."""
|
||||||
dev_reg = async_get_dev_reg(hass)
|
dev_reg = async_get_dev_reg(hass)
|
||||||
@ -225,6 +233,63 @@ async def test_set_config_parameter(
|
|||||||
|
|
||||||
client.async_send_command_no_wait.reset_mock()
|
client.async_send_command_no_wait.reset_mock()
|
||||||
|
|
||||||
|
# Test setting parameter by value_size
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_SET_CONFIG_PARAMETER,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: AIR_TEMPERATURE_SENSOR,
|
||||||
|
ATTR_CONFIG_PARAMETER: 2,
|
||||||
|
ATTR_VALUE_SIZE: 2,
|
||||||
|
ATTR_VALUE_FORMAT: 1,
|
||||||
|
ATTR_CONFIG_VALUE: 1,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(client.async_send_command_no_wait.call_args_list) == 1
|
||||||
|
args = client.async_send_command_no_wait.call_args[0][0]
|
||||||
|
assert args["command"] == "endpoint.set_raw_config_parameter_value"
|
||||||
|
assert args["nodeId"] == 52
|
||||||
|
assert args["endpoint"] == 0
|
||||||
|
options = args["options"]
|
||||||
|
assert options["parameter"] == 2
|
||||||
|
assert options["value"] == 1
|
||||||
|
assert options["valueSize"] == 2
|
||||||
|
assert options["valueFormat"] == 1
|
||||||
|
|
||||||
|
client.async_send_command_no_wait.reset_mock()
|
||||||
|
|
||||||
|
# Test setting parameter when one node has endpoint and other doesn't
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_SET_CONFIG_PARAMETER,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: [AIR_TEMPERATURE_SENSOR, "siren.indoor_siren_6_tone_id"],
|
||||||
|
ATTR_ENDPOINT: 1,
|
||||||
|
ATTR_CONFIG_PARAMETER: 32,
|
||||||
|
ATTR_VALUE_SIZE: 2,
|
||||||
|
ATTR_VALUE_FORMAT: 1,
|
||||||
|
ATTR_CONFIG_VALUE: 1,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(client.async_send_command_no_wait.call_args_list) == 0
|
||||||
|
assert len(client.async_send_command.call_args_list) == 1
|
||||||
|
args = client.async_send_command.call_args[0][0]
|
||||||
|
assert args["command"] == "endpoint.set_raw_config_parameter_value"
|
||||||
|
assert args["nodeId"] == 2
|
||||||
|
assert args["endpoint"] == 1
|
||||||
|
options = args["options"]
|
||||||
|
assert options["parameter"] == 32
|
||||||
|
assert options["value"] == 1
|
||||||
|
assert options["valueSize"] == 2
|
||||||
|
assert options["valueFormat"] == 1
|
||||||
|
|
||||||
|
client.async_send_command_no_wait.reset_mock()
|
||||||
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
# Test groups get expanded
|
# Test groups get expanded
|
||||||
assert await async_setup_component(hass, "group", {})
|
assert await async_setup_component(hass, "group", {})
|
||||||
await Group.async_create_group(
|
await Group.async_create_group(
|
||||||
@ -296,6 +361,54 @@ async def test_set_config_parameter(
|
|||||||
config_entry=non_zwave_js_config_entry,
|
config_entry=non_zwave_js_config_entry,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Test unknown endpoint throws error when None are remaining
|
||||||
|
with pytest.raises(HomeAssistantError):
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_SET_CONFIG_PARAMETER,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: AIR_TEMPERATURE_SENSOR,
|
||||||
|
ATTR_ENDPOINT: 5,
|
||||||
|
ATTR_CONFIG_PARAMETER: 2,
|
||||||
|
ATTR_VALUE_SIZE: 2,
|
||||||
|
ATTR_VALUE_FORMAT: 1,
|
||||||
|
ATTR_CONFIG_VALUE: 1,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test that we can't include bitmask and value size and value format
|
||||||
|
with pytest.raises(vol.Invalid):
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_SET_CONFIG_PARAMETER,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: AIR_TEMPERATURE_SENSOR,
|
||||||
|
ATTR_CONFIG_PARAMETER: 102,
|
||||||
|
ATTR_CONFIG_PARAMETER_BITMASK: 1,
|
||||||
|
ATTR_CONFIG_VALUE: "Fahrenheit",
|
||||||
|
ATTR_VALUE_FORMAT: 1,
|
||||||
|
ATTR_VALUE_SIZE: 2,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test that value size must be 1, 2, or 4 (not 3)
|
||||||
|
with pytest.raises(vol.Invalid):
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_SET_CONFIG_PARAMETER,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: AIR_TEMPERATURE_SENSOR,
|
||||||
|
ATTR_CONFIG_PARAMETER: 102,
|
||||||
|
ATTR_CONFIG_PARAMETER_BITMASK: 1,
|
||||||
|
ATTR_CONFIG_VALUE: "Fahrenheit",
|
||||||
|
ATTR_VALUE_FORMAT: 1,
|
||||||
|
ATTR_VALUE_SIZE: 3,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
# Test that a Z-Wave JS device with an invalid node ID, non Z-Wave JS entity,
|
# Test that a Z-Wave JS device with an invalid node ID, non Z-Wave JS entity,
|
||||||
# non Z-Wave JS device, invalid device_id, and invalid node_id gets filtered out.
|
# non Z-Wave JS device, invalid device_id, and invalid node_id gets filtered out.
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
@ -376,6 +489,75 @@ async def test_set_config_parameter(
|
|||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
client.async_send_command_no_wait.reset_mock()
|
||||||
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
config_value = aeotec_zw164_siren.values["2-112-0-32"]
|
||||||
|
cmd_result = SetConfigParameterResult("accepted", {"status": 255})
|
||||||
|
|
||||||
|
# Test accepted return
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.zwave_js.services.Endpoint.async_set_raw_config_parameter_value",
|
||||||
|
return_value=(config_value, cmd_result),
|
||||||
|
) as mock_set_raw_config_parameter_value:
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_SET_CONFIG_PARAMETER,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: ["siren.indoor_siren_6_tone_id"],
|
||||||
|
ATTR_ENDPOINT: 0,
|
||||||
|
ATTR_CONFIG_PARAMETER: 32,
|
||||||
|
ATTR_VALUE_SIZE: 2,
|
||||||
|
ATTR_VALUE_FORMAT: 1,
|
||||||
|
ATTR_CONFIG_VALUE: 1,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
assert len(mock_set_raw_config_parameter_value.call_args_list) == 1
|
||||||
|
assert mock_set_raw_config_parameter_value.call_args[0][0] == 1
|
||||||
|
assert mock_set_raw_config_parameter_value.call_args[0][1] == 32
|
||||||
|
assert mock_set_raw_config_parameter_value.call_args[1] == {
|
||||||
|
"property_key": None,
|
||||||
|
"value_size": 2,
|
||||||
|
"value_format": 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert "Set configuration parameter" in caplog.text
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
# Test queued return
|
||||||
|
cmd_result.status = "queued"
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.zwave_js.services.Endpoint.async_set_raw_config_parameter_value",
|
||||||
|
return_value=(config_value, cmd_result),
|
||||||
|
) as mock_set_raw_config_parameter_value:
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_SET_CONFIG_PARAMETER,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: ["siren.indoor_siren_6_tone_id"],
|
||||||
|
ATTR_ENDPOINT: 0,
|
||||||
|
ATTR_CONFIG_PARAMETER: 32,
|
||||||
|
ATTR_VALUE_SIZE: 2,
|
||||||
|
ATTR_VALUE_FORMAT: 1,
|
||||||
|
ATTR_CONFIG_VALUE: 1,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
assert len(mock_set_raw_config_parameter_value.call_args_list) == 1
|
||||||
|
assert mock_set_raw_config_parameter_value.call_args[0][0] == 1
|
||||||
|
assert mock_set_raw_config_parameter_value.call_args[0][1] == 32
|
||||||
|
assert mock_set_raw_config_parameter_value.call_args[1] == {
|
||||||
|
"property_key": None,
|
||||||
|
"value_size": 2,
|
||||||
|
"value_format": 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert "Added command to queue" in caplog.text
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
|
||||||
async def test_set_config_parameter_gather(
|
async def test_set_config_parameter_gather(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user