Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-30: Add an attribute store flag to control supervision #30

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -201,8 +201,7 @@ static sl_status_t assign_multicast_pool(attribute_store_node_t node)
}

bool use_supervision
= zwave_node_supports_command_class(COMMAND_CLASS_SUPERVISION,
node_id,
= zwave_node_want_supervision_frame(node_id,
endpoint_id);

// Node details validation. can this node be part of a multicast?
Expand Down
Expand Up @@ -83,8 +83,7 @@ sl_status_t attribute_resolver_send(attribute_store_node_t node,
zwave_tx_session_id_t tx_session_id = NULL;
if (is_set == true
&& true
== zwave_node_supports_command_class(COMMAND_CLASS_SUPERVISION,
node_id,
== zwave_node_want_supervision_frame(node_id,
endpoint_id)) {
// Send with Supervision
send_status = zwave_command_class_supervision_send_data(
Expand Down
Expand Up @@ -352,8 +352,7 @@ void test_zpc_attribute_resolver_send_send_status_fail_with_supervision()
zwave_tx_scheme_get_node_tx_options_IgnoreArg_tx_options();
zwave_tx_scheme_get_node_tx_options_ReturnThruPtr_tx_options(&tx_options_2);

zwave_node_supports_command_class_ExpectAndReturn(0x6C,
zwave_node_id_2,
zwave_node_want_supervision_frame_ExpectAndReturn(zwave_node_id_2,
zwave_endpoint_id_2,
true);

Expand Down Expand Up @@ -426,8 +425,7 @@ void test_zpc_attribute_resolver_send_set_no_supervision_happy_case()
zwave_tx_scheme_get_node_tx_options_IgnoreArg_tx_options();
zwave_tx_scheme_get_node_tx_options_ReturnThruPtr_tx_options(&tx_options_1);

zwave_node_supports_command_class_ExpectAndReturn(0x6C,
zwave_node_id_1,
zwave_node_want_supervision_frame_ExpectAndReturn(zwave_node_id_1,
zwave_endpoint_id_1,
false);

Expand Down Expand Up @@ -508,8 +506,7 @@ void test_zpc_attribute_resolver_send_set_supervision_working_happy_case()
zwave_tx_scheme_get_node_tx_options_IgnoreArg_tx_options();
zwave_tx_scheme_get_node_tx_options_ReturnThruPtr_tx_options(&tx_options_1);

zwave_node_supports_command_class_ExpectAndReturn(0x6C,
zwave_node_id_1,
zwave_node_want_supervision_frame_ExpectAndReturn(zwave_node_id_1,
zwave_endpoint_id_1,
true);

Expand Down Expand Up @@ -617,11 +614,9 @@ void test_zpc_attribute_resolver_group_2_nodes_happy_case()
attribute_store_get_node_type_ExpectAndReturn(test_node_2, test_node_2_type);
attribute_resolver_set_function_ExpectAndReturn(test_node_2_type,
&rule_function_stub);
zwave_node_supports_command_class_ExpectAndReturn(0x6C,
zwave_node_id_2,
zwave_node_want_supervision_frame_ExpectAndReturn(zwave_node_id_2,
zwave_endpoint_id_1,
true);

// assigning test_node_1 in a multicast pool
is_node_or_parent_paused_ExpectAndReturn(test_node_1, false);
attribute_store_is_value_defined_ExpectAndReturn(test_node_1,
Expand All @@ -647,8 +642,7 @@ void test_zpc_attribute_resolver_group_2_nodes_happy_case()
attribute_store_get_node_type_ExpectAndReturn(test_node_1, test_node_1_type);
attribute_resolver_set_function_ExpectAndReturn(test_node_1_type,
&rule_function_stub);
zwave_node_supports_command_class_ExpectAndReturn(0x6C,
zwave_node_id_1,
zwave_node_want_supervision_frame_ExpectAndReturn(zwave_node_id_1,
zwave_endpoint_id_1,
true);

Expand Down Expand Up @@ -857,8 +851,7 @@ void test_zpc_attribute_resolver_group_unknown_protocol()
attribute_store_get_node_type_ExpectAndReturn(test_node_1, test_node_1_type);
attribute_resolver_set_function_ExpectAndReturn(test_node_1_type,
&rule_function_stub);
zwave_node_supports_command_class_ExpectAndReturn(0x6C,
zwave_node_id_1,
zwave_node_want_supervision_frame_ExpectAndReturn(zwave_node_id_1,
zwave_endpoint_id_1,
true);

Expand Down Expand Up @@ -889,9 +882,7 @@ void test_zpc_attribute_resolver_group_unknown_protocol()
NULL);
zwave_tx_scheme_get_node_tx_options_IgnoreArg_tx_options();
zwave_tx_scheme_get_node_tx_options_ReturnThruPtr_tx_options(&tx_options_1);

zwave_node_supports_command_class_ExpectAndReturn(0x6C,
zwave_node_id_1,
zwave_node_want_supervision_frame_ExpectAndReturn(zwave_node_id_1,
zwave_endpoint_id_1,
false);

Expand Down Expand Up @@ -988,8 +979,7 @@ void test_zpc_attribute_resolver_group_no_reported_value()
attribute_store_get_node_type_ExpectAndReturn(test_node_1, test_node_1_type);
attribute_resolver_set_function_ExpectAndReturn(test_node_1_type,
&rule_function_stub);
zwave_node_supports_command_class_ExpectAndReturn(0x6C,
zwave_node_id_1,
zwave_node_want_supervision_frame_ExpectAndReturn(zwave_node_id_1,
zwave_endpoint_id_1,
true);

Expand Down Expand Up @@ -1021,8 +1011,7 @@ void test_zpc_attribute_resolver_group_no_reported_value()
zwave_tx_scheme_get_node_tx_options_IgnoreArg_tx_options();
zwave_tx_scheme_get_node_tx_options_ReturnThruPtr_tx_options(&tx_options_1);

zwave_node_supports_command_class_ExpectAndReturn(0x6C,
zwave_node_id_1,
zwave_node_want_supervision_frame_ExpectAndReturn(zwave_node_id_1,
zwave_endpoint_id_1,
false);

Expand Down Expand Up @@ -1105,8 +1094,7 @@ void test_zpc_attribute_resolver_register_custom_handler()
zwave_tx_scheme_get_node_tx_options_IgnoreArg_tx_options();
zwave_tx_scheme_get_node_tx_options_ReturnThruPtr_tx_options(&tx_options_1);

zwave_node_supports_command_class_ExpectAndReturn(0x6C,
zwave_node_id_1,
zwave_node_want_supervision_frame_ExpectAndReturn(zwave_node_id_1,
zwave_endpoint_id_1,
false);

Expand Down Expand Up @@ -1196,8 +1184,7 @@ void test_zpc_attribute_resolver_send_set_abort_pending()
zwave_tx_scheme_get_node_tx_options_IgnoreArg_tx_options();
zwave_tx_scheme_get_node_tx_options_ReturnThruPtr_tx_options(&tx_options_1);

zwave_node_supports_command_class_ExpectAndReturn(0x6C,
zwave_node_id_1,
zwave_node_want_supervision_frame_ExpectAndReturn(zwave_node_id_1,
zwave_endpoint_id_1,
true);

Expand Down
Expand Up @@ -650,6 +650,9 @@ DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_NOTIFICATION_V1_ALARM_LEVEL,
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SUPERVISION_VERSION,
ZWAVE_CC_VERSION_ATTRIBUTE(COMMAND_CLASS_SUPERVISION))

DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SUPERVISION_ENABLED,
((COMMAND_CLASS_SUPERVISION << 8) | 0x02))

/////////////////////////////////////////////////
// Thermostat Mode Command Class
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_MODE_VERSION,
Expand Down
Expand Up @@ -122,6 +122,20 @@ bool zwave_node_supports_command_class(zwave_command_class_t command_class,
zwave_node_id_t node_id,
zwave_endpoint_id_t endpoint_id);

/**
* @brief Verify whether a node/endpoint supports Supervision CC
* AND wants to use it.
*
* @param node_id The NodeID to verify for support.
* @param endpoint_id The Endpoint to verify for support.

* @returns
* - true if the node/endpoint supports the Supervision CC + has the enabled supervision flag (or if the flag is not defined)
* - false otherwise
*/
bool zwave_node_want_supervision_frame(zwave_node_id_t node_id,
zwave_endpoint_id_t endpoint_id);

/**
* @brief Return the version of a Command Class implemented by a node.
*
Expand Down
Expand Up @@ -306,6 +306,8 @@ static const std::vector<attribute_schema_t> attribute_schema = {
// Supervision Command Class attributes
/////////////////////////////////////////////////////////////////////
{ATTRIBUTE_COMMAND_CLASS_SUPERVISION_VERSION, "Supervision Version", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE},
{ATTRIBUTE_COMMAND_CLASS_SUPERVISION_ENABLED, "Supervision Enabled flag", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE},

/////////////////////////////////////////////////////////////////////
// Wake Up Command Class attributes
/////////////////////////////////////////////////////////////////////
Expand Down
35 changes: 35 additions & 0 deletions applications/zpc/components/zpc_attribute_store/src/zwave_utils.c
Expand Up @@ -160,6 +160,41 @@ sl_status_t zwave_get_node_granted_keys(zwave_node_id_t node_id,
sizeof(zwave_keyset_t));
}

bool zwave_node_want_supervision_frame(zwave_node_id_t node_id,
zwave_endpoint_id_t endpoint_id)
{
// First we check if node supports supervision
if (!zwave_node_supports_command_class(COMMAND_CLASS_SUPERVISION,
node_id,
endpoint_id)) {
return false;
}

// If it is, we check if the supervision flag is set

// Find out the UNID of the node
unid_t unid;
zwave_unid_from_node_id(node_id, unid);

attribute_store_node_t endpoint_node
= attribute_store_network_helper_get_endpoint_node(unid, endpoint_id);

uint8_t supervision_flag;
sl_status_t result = attribute_store_get_child_reported(
endpoint_node,
ATTRIBUTE_COMMAND_CLASS_SUPERVISION_ENABLED,
&supervision_flag,
sizeof(supervision_flag));

// If enabled attribute is not defined we send a supervision frame anyway
// This behavior can be changed in future release, but for now we try to enable supervision frame by default to maintain compatibility with previous versions
if (result != SL_STATUS_OK) {
return true;
}

return (supervision_flag == 1);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also suggest here to send on any non-zero value

Suggested change
return (supervision_flag == 1);
return (supervision_flag != 0);

}

bool zwave_node_supports_command_class(zwave_command_class_t command_class,
zwave_node_id_t node_id,
zwave_endpoint_id_t endpoint_id)
Expand Down
Expand Up @@ -1023,4 +1023,125 @@ void test_is_command_in_array()
is_command_in_array(0x01, 0x02, command_list_4, sizeof(command_list_4)));
TEST_ASSERT_TRUE(
is_command_in_array(0x9F, 0x12, command_list_4, sizeof(command_list_4)));
}


void zwave_node_supports_command_class_mock_helper() {
attribute_store_network_helper_get_endpoint_node_ExpectAndReturn(
test_unid,
test_endpoint_id,
test_endpoint_node);

attribute_store_get_node_child_by_type_ExpectAndReturn(
test_endpoint_node,
ATTRIBUTE_ZWAVE_NIF,
0,
test_non_secure_nif_node);

attribute_store_get_node_attribute_value_ExpectAndReturn(
test_non_secure_nif_node,
REPORTED_ATTRIBUTE,
NULL,
NULL,
SL_STATUS_OK);
attribute_store_get_node_attribute_value_IgnoreArg_value();
attribute_store_get_node_attribute_value_IgnoreArg_value_size();
attribute_store_get_node_attribute_value_ReturnMemThruPtr_value(
test_nif,
(uint8_t)sizeof(test_nif));
attribute_store_get_node_attribute_value_ReturnThruPtr_value_size(
&test_nif_length);
is_command_class_in_supported_list_ExpectAndReturn(COMMAND_CLASS_SUPERVISION,
test_nif,
test_nif_length,
1);
}

void test_zwave_node_want_supervision_frame_no_defined_flag_happy_case() {
// Set mock support of COMMAND_CLASS_SUPERVISION
zwave_node_supports_command_class_mock_helper();

attribute_store_network_helper_get_endpoint_node_IgnoreAndReturn(0);
// Set child reported to SL_STATUS_FAIL so we can simulate no flag
attribute_store_get_child_reported_IgnoreAndReturn(SL_STATUS_FAIL);
TEST_ASSERT_TRUE(
zwave_node_want_supervision_frame(test_node_id, test_endpoint_id));
}

void test_zwave_node_want_supervision_frame_flag_happy_case() {
// Set mock support of COMMAND_CLASS_SUPERVISION
zwave_node_supports_command_class_mock_helper();

// Simulate flag == 1
attribute_store_node_t endpoint_node = 12;
uint8_t supervision_flag = 1;
attribute_store_network_helper_get_endpoint_node_IgnoreAndReturn(endpoint_node);
attribute_store_get_child_reported_ExpectAndReturn(
endpoint_node,
ATTRIBUTE_COMMAND_CLASS_SUPERVISION_ENABLED,
NULL,
sizeof(supervision_flag),
SL_STATUS_OK);
attribute_store_get_child_reported_IgnoreArg_value();
attribute_store_get_child_reported_ReturnThruPtr_value(&supervision_flag);

TEST_ASSERT_TRUE(
zwave_node_want_supervision_frame(test_node_id, test_endpoint_id));
}

void test_zwave_node_want_supervision_frame_flag_false_happy_case() {
// Set mock support of COMMAND_CLASS_SUPERVISION
zwave_node_supports_command_class_mock_helper();

// Simulate flag == 0
attribute_store_node_t endpoint_node = 12;
uint8_t supervision_flag = 0;
attribute_store_network_helper_get_endpoint_node_IgnoreAndReturn(endpoint_node);
attribute_store_get_child_reported_ExpectAndReturn(
endpoint_node,
ATTRIBUTE_COMMAND_CLASS_SUPERVISION_ENABLED,
NULL,
sizeof(supervision_flag),
SL_STATUS_OK);
attribute_store_get_child_reported_IgnoreArg_value();
attribute_store_get_child_reported_ReturnThruPtr_value(&supervision_flag);

TEST_ASSERT_FALSE(
zwave_node_want_supervision_frame(test_node_id, test_endpoint_id));
}

void test_zwave_node_want_supervision_no_supervision_cc_in_nif_happy_case() {
attribute_store_network_helper_get_endpoint_node_ExpectAndReturn(
test_unid,
test_endpoint_id,
test_endpoint_node);

attribute_store_get_node_child_by_type_ExpectAndReturn(
test_endpoint_node,
ATTRIBUTE_ZWAVE_NIF,
0,
test_non_secure_nif_node);

attribute_store_get_node_attribute_value_ExpectAndReturn(
test_non_secure_nif_node,
REPORTED_ATTRIBUTE,
NULL,
NULL,
SL_STATUS_OK);
attribute_store_get_node_attribute_value_IgnoreArg_value();
attribute_store_get_node_attribute_value_IgnoreArg_value_size();
attribute_store_get_node_attribute_value_ReturnMemThruPtr_value(
test_nif,
(uint8_t)sizeof(test_nif));
attribute_store_get_node_attribute_value_ReturnThruPtr_value_size(
&test_nif_length);
is_command_class_in_supported_list_ExpectAndReturn(COMMAND_CLASS_SUPERVISION,
test_nif,
test_nif_length,
false);
attribute_store_get_node_child_by_type_IgnoreAndReturn(ATTRIBUTE_STORE_INVALID_NODE);


TEST_ASSERT_FALSE(
zwave_node_want_supervision_frame(test_node_id, test_endpoint_id));
}