From 751d9a5065dcd2c189b3e19c4427c47f5bfec474 Mon Sep 17 00:00:00 2001 From: raman325 <7243222+raman325@users.noreply.github.com> Date: Thu, 8 Apr 2021 13:06:14 -0400 Subject: [PATCH 1/5] Support property names in bulk_set_partial_config_parameters --- test/util/test_node.py | 30 ++++++++++++++++++ zwave_js_server/util/node.py | 60 ++++++++++++++++++++++++------------ 2 files changed, 71 insertions(+), 19 deletions(-) diff --git a/test/util/test_node.py b/test/util/test_node.py index 9ac656018..416423819 100644 --- a/test/util/test_node.py +++ b/test/util/test_node.py @@ -174,6 +174,30 @@ async def test_bulk_set_partial_config_parameters(multisensor_6, uuid4, mock_com "messageId": uuid4, } + # Use property key names instead of bitmasks for dict key + cmd_status = await async_bulk_set_partial_config_parameters( + node, + 101, + { + "Group 1: Send humidity reports": 1, + "Group 1: Send temperature reports": 1, + "Group 1: Send ultraviolet reports": 1, + "Group 1: Send battery reports": 1, + }, + ) + assert cmd_status == CommandStatus.QUEUED + assert len(ack_commands) == 4 + assert ack_commands[3] == { + "command": "node.set_value", + "nodeId": node.node_id, + "valueId": { + "commandClass": CommandClass.CONFIGURATION.value, + "property": 101, + }, + "value": 241, + "messageId": uuid4, + } + # Use an invalid property with pytest.raises(NotFoundError): await async_bulk_set_partial_config_parameters(node, 999, 99) @@ -184,6 +208,12 @@ async def test_bulk_set_partial_config_parameters(multisensor_6, uuid4, mock_com node, 101, {128: 1, 64: 1, 32: 1, 16: 1, 2: 1} ) + # use an invalid property name + with pytest.raises(NotFoundError): + await async_bulk_set_partial_config_parameters( + node, 101, {"Invalid property name": 1} + ) + # Try to bulkset a property that isn't broken into partials with a dictionary with pytest.raises(ValueTypeError): await async_bulk_set_partial_config_parameters(node, 252, {1: 1}) diff --git a/zwave_js_server/util/node.py b/zwave_js_server/util/node.py index 96de00f87..63c5d6b60 100644 --- a/zwave_js_server/util/node.py +++ b/zwave_js_server/util/node.py @@ -81,7 +81,7 @@ async def async_set_config_parameter( async def async_bulk_set_partial_config_parameters( node: Node, property_: int, - new_value: Union[int, Dict[int, Union[int, str]]], + new_value: Union[int, Dict[Union[int, str], Union[int, str]]], ) -> CommandStatus: """Bulk set partial configuration values on this node.""" config_values = node.get_configuration_values() @@ -222,33 +222,55 @@ def _get_int_from_partials_dict( node: Node, partial_param_values: Dict[str, ConfigurationValue], property_: int, - new_value: Dict[int, Union[int, str]], + new_value: Dict[Union[int, str], Union[int, str]], ) -> int: """Take an input dict for a set of partial values and compute the raw int value.""" int_value = 0 + provided_partial_values = [] # For each property key provided, we bit shift the partial value using the # property_key - for property_key, partial_value in new_value.items(): - value_id = get_value_id( - node, CommandClass.CONFIGURATION, property_, property_key=property_key - ) - if value_id not in partial_param_values: - raise NotFoundError( - f"Bitmask {property_key} ({hex(property_key)}) not found for " - f"parameter {property_}" + for property_key_or_name, partial_value in new_value.items(): + # If the dict key is a property key, we can generate the value ID to find the + # partial value + if isinstance(property_key_or_name, int): + value_id = get_value_id( + node, + CommandClass.CONFIGURATION, + property_, + property_key=property_key_or_name, ) - partial_value = _validate_and_transform_new_value( - partial_param_values[value_id], partial_value - ) - int_value += partial_value << partial_param_bit_shift(property_key) + if value_id not in partial_param_values: + raise NotFoundError( + f"Bitmask {property_key_or_name} ({hex(property_key_or_name)}) " + f"not found for parameter {property_}" + ) + zwave_value = partial_param_values[value_id] + # If the dict key is a property name, we have to find the value from the list + # of partial param values + else: + try: + zwave_value = next( + value + for value in partial_param_values.values() + if value.property_name == property_key_or_name + ) + except StopIteration: + raise NotFoundError( + f"Partial parameter with label '{property_key_or_name}'" + f"not found for parameter {property_}" + ) from None + + provided_partial_values.append(zwave_value) + partial_value = _validate_and_transform_new_value(zwave_value, partial_value) + int_value += partial_value << partial_param_bit_shift(zwave_value.property_key) # To set partial parameters in bulk, we also have to include cached values for # property keys that haven't been specified - for property_value in partial_param_values.values(): - if property_value.property_key not in new_value: - int_value += cast(int, property_value.value) << partial_param_bit_shift( - cast(int, property_value.property_key) - ) + missing_values = set(partial_param_values.values()) - set(provided_partial_values) + for property_value in missing_values: + int_value += cast(int, property_value.value) << partial_param_bit_shift( + cast(int, property_value.property_key) + ) return int_value From fcf9511760ba533bfb823511d75da7dc9bbd909a Mon Sep 17 00:00:00 2001 From: raman325 <7243222+raman325@users.noreply.github.com> Date: Thu, 8 Apr 2021 13:36:48 -0400 Subject: [PATCH 2/5] ignore type error because we know the property key for partial values will always be an int --- zwave_js_server/util/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zwave_js_server/util/node.py b/zwave_js_server/util/node.py index 63c5d6b60..3772d97e8 100644 --- a/zwave_js_server/util/node.py +++ b/zwave_js_server/util/node.py @@ -262,7 +262,7 @@ def _get_int_from_partials_dict( provided_partial_values.append(zwave_value) partial_value = _validate_and_transform_new_value(zwave_value, partial_value) - int_value += partial_value << partial_param_bit_shift(zwave_value.property_key) + int_value += partial_value << partial_param_bit_shift(zwave_value.property_key) #type: ignore # To set partial parameters in bulk, we also have to include cached values for # property keys that haven't been specified From 764720b4cc5002a3ffcfb44d793cee2078a6ea01 Mon Sep 17 00:00:00 2001 From: raman325 <7243222+raman325@users.noreply.github.com> Date: Thu, 8 Apr 2021 13:37:55 -0400 Subject: [PATCH 3/5] fix formatting --- zwave_js_server/util/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zwave_js_server/util/node.py b/zwave_js_server/util/node.py index 3772d97e8..6457c8c06 100644 --- a/zwave_js_server/util/node.py +++ b/zwave_js_server/util/node.py @@ -262,7 +262,7 @@ def _get_int_from_partials_dict( provided_partial_values.append(zwave_value) partial_value = _validate_and_transform_new_value(zwave_value, partial_value) - int_value += partial_value << partial_param_bit_shift(zwave_value.property_key) #type: ignore + int_value += partial_value << partial_param_bit_shift(zwave_value.property_key) # type: ignore # To set partial parameters in bulk, we also have to include cached values for # property keys that haven't been specified From b1c5a246693ef7df59b6e91375cd08c5b60d6daf Mon Sep 17 00:00:00 2001 From: raman325 <7243222+raman325@users.noreply.github.com> Date: Thu, 8 Apr 2021 13:39:51 -0400 Subject: [PATCH 4/5] lint --- zwave_js_server/util/node.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zwave_js_server/util/node.py b/zwave_js_server/util/node.py index 6457c8c06..6bec310a8 100644 --- a/zwave_js_server/util/node.py +++ b/zwave_js_server/util/node.py @@ -262,7 +262,8 @@ def _get_int_from_partials_dict( provided_partial_values.append(zwave_value) partial_value = _validate_and_transform_new_value(zwave_value, partial_value) - int_value += partial_value << partial_param_bit_shift(zwave_value.property_key) # type: ignore + bit_shift = partial_param_bit_shift(zwave_value.property_key) # type: ignore + int_value += partial_value << bit_shift # To set partial parameters in bulk, we also have to include cached values for # property keys that haven't been specified From bdc2b66b2c928c2254a045a07ca16ba1ad69c537 Mon Sep 17 00:00:00 2001 From: raman325 <7243222+raman325@users.noreply.github.com> Date: Thu, 8 Apr 2021 14:25:27 -0400 Subject: [PATCH 5/5] switch to list comprehension and cast property_key instead of ignoring type --- zwave_js_server/util/node.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/zwave_js_server/util/node.py b/zwave_js_server/util/node.py index 6bec310a8..83653c7da 100644 --- a/zwave_js_server/util/node.py +++ b/zwave_js_server/util/node.py @@ -262,16 +262,17 @@ def _get_int_from_partials_dict( provided_partial_values.append(zwave_value) partial_value = _validate_and_transform_new_value(zwave_value, partial_value) - bit_shift = partial_param_bit_shift(zwave_value.property_key) # type: ignore + bit_shift = partial_param_bit_shift(cast(int, zwave_value.property_key)) int_value += partial_value << bit_shift # To set partial parameters in bulk, we also have to include cached values for # property keys that haven't been specified missing_values = set(partial_param_values.values()) - set(provided_partial_values) - for property_value in missing_values: - int_value += cast(int, property_value.value) << partial_param_bit_shift( - cast(int, property_value.property_key) - ) + int_value += sum( + cast(int, property_value.value) + << partial_param_bit_shift(cast(int, property_value.property_key)) + for property_value in missing_values + ) return int_value