Skip to content

add CLI interface for setting priority route #96

New issue

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

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

Already on GitHub? # to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ static sl_status_t handle_zwave_reset_mpan(const handle_args_t &arg);
static sl_status_t handle_zwave_home_id(const handle_args_t &arg);
static sl_status_t handle_enable_nls(const handle_args_t &arg);
static sl_status_t handle_get_nls_state(const handle_args_t &arg);
static sl_status_t handle_set_priority_route(const handle_args_t &arg);

/// Map that holds all the commands (used for printing help)
///
Expand Down Expand Up @@ -168,6 +169,10 @@ const std::map<std::string, std::pair<std::string, handler_func>> commands = {
&handle_add_zwave_node_abort}},
{"zwave_add_node",
{" :Add a Z-Wave node to the network", &handle_add_zwave_node}},
{"zwave_set_priority_route",
{" :Set the priority route to a destination node",
&handle_set_priority_route}},

{"zwave_grant_keys",
{COLOR_START
"<1/0 to accept/reject the requested keys>,<Set of keys to"
Expand Down Expand Up @@ -620,6 +625,61 @@ static sl_status_t handle_zwave_learn_mode(const handle_args_t &arg)
return SL_STATUS_OK;
}

static sl_status_t handle_set_priority_route(const handle_args_t &arg)
{
zwave_node_id_t dst_node_id = 0;
uint8_t route[PRIORITY_ROUTE_SIZE] = {0};
const int max_node_id = 0xE8;

if (arg.size() != 7) {
dprintf(out_stream,
"Invalid number of arguments, expected args:"
"<Dst NodeID>,<Hop 1>,<Hop 2>,<Hop 3>,<Hop 4>,<Speed> "
"all values in hexadecimal\n");

return SL_STATUS_FAIL;
}

try {
dst_node_id
= static_cast<zwave_node_id_t>(std::stoi(arg[1].c_str(), nullptr, 16));
for (size_t i = 0; i < 5; ++i) {
route[i]
= static_cast<uint8_t>(std::stoi(arg[i + 2].c_str(), nullptr, 16));
}
} catch (const std::invalid_argument &e) {
dprintf(out_stream, "Invalid argument: %s\n", e.what());
return SL_STATUS_FAIL;
}

if (dst_node_id <= 0 || dst_node_id > max_node_id) {
dprintf(out_stream, "Invalid destination node id\n");
return SL_STATUS_FAIL;
}

bool previous_hop_was_direct = false;
for (size_t i = 0; i < 4; ++i) {
if (route[i] < 0 || route[i] > max_node_id) {
dprintf(out_stream, "Invalid hop node id\n");
return SL_STATUS_FAIL;
}
if (previous_hop_was_direct && route[i] != 0) {
dprintf(out_stream, "Invalid route. Cannot set a node id after a zero\n");
return SL_STATUS_FAIL;
}
if (0 == route[i]) {
previous_hop_was_direct = true;
}
}

if (route[4] <= 0 || route[4] > 3) {
dprintf(out_stream, "Invalid Route Speed.\n");
return SL_STATUS_FAIL;
}

return zwave_network_management_set_priority_route(dst_node_id, route);
}

static sl_status_t handle_add_zwave_node(const handle_args_t &arg)
{
return zwave_network_management_add_node();
Expand Down
103 changes: 103 additions & 0 deletions applications/zpc/components/zpc_stdin/test/zpc_stdin_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,3 +543,106 @@ void test_zwave_command_handler_dispatch()
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);
}

void test_zwave_set_priority_route_should_return_ok_with_valid_arguments(void)
{
sl_status_t state = SL_STATUS_FAIL;

zwave_network_management_set_priority_route_IgnoreAndReturn(SL_STATUS_OK);
state
= uic_stdin_handle_command("zwave_set_priority_route 02,01,00,00,00,01");
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);

state
= uic_stdin_handle_command("zwave_set_priority_route 01,02,03,04,05,01");
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);

state
= uic_stdin_handle_command("zwave_set_priority_route E8,02,03,04,05,01");
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);

state
= uic_stdin_handle_command("zwave_set_priority_route E8,E7,E8,E7,E0,01");
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);
}

void test_zwave_set_priority_route_should_return_fail_with_invalid_argument_count(
void)
{
sl_status_t state = SL_STATUS_OK;

state = uic_stdin_handle_command("zwave_set_priority_route");
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);

state = uic_stdin_handle_command("zwave_set_priority_route ,,,,");
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);

state = uic_stdin_handle_command("zwave_set_priority_route 01");
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);

state = uic_stdin_handle_command("zwave_set_priority_route 01,02,03,04,05");
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
}

void test_zwave_set_priority_route_should_return_fail_with_wrong_argument_order(
void)
{
sl_status_t state = SL_STATUS_OK;

state
= uic_stdin_handle_command("zwave_set_priority_route 02,00,02,03,04,01");
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);

state
= uic_stdin_handle_command("zwave_set_priority_route 01,02,03,00,04,01");
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
}

void test_zwave_set_priority_route_should_return_ok_with_valid_route(void)
{
uint8_t expected_route[] = {0x2, 0x3, 0x4, 0x5, 0x1};
sl_status_t state = SL_STATUS_FAIL;

zwave_network_management_set_priority_route_ExpectAndReturn(0x01,
expected_route,
SL_STATUS_OK);
state
= uic_stdin_handle_command("zwave_set_priority_route 01,02,03,04,05,01");
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);

expected_route[0] = 0xE7;
expected_route[1] = 0xE6;
expected_route[2] = 0xE5;
expected_route[4] = 0xE4;
expected_route[3] = 0x01;
zwave_network_management_set_priority_route_ExpectAndReturn(0xE8,
expected_route,
SL_STATUS_OK);
state
= uic_stdin_handle_command("zwave_set_priority_route E8,E7,E6,E5,E4,01");
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);
}

void test_zwave_set_priority_route_should_return_fail_with_invalid_node_id(void)
{
sl_status_t state = SL_STATUS_OK;

state
= uic_stdin_handle_command("zwave_set_priority_route -1,02,03,04,05,01");
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);

state
= uic_stdin_handle_command("zwave_set_priority_route FF,02,03,04,05,01");
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);

state
= uic_stdin_handle_command("zwave_set_priority_route 01,FF,03,04,05,01");
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);

state
= uic_stdin_handle_command("zwave_set_priority_route E9,FF,03,04,05,01");
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);

state
= uic_stdin_handle_command("zwave_set_priority_route 01,E9,03,04,05,01");
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
}
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,24 @@ bool zwave_network_management_is_busy();
*/
bool we_have_return_routes_to_assign(zwave_node_id_t node_id);

/**
* @brief Assign a priority route to a node.
*
* This function will set a priority route to a given node. The priority route
* is a list with the NodeID of the hops that the Z-Wave controller will use as
* a preferred route to the node. The last byte is the route speed. See Z-Wave
* Host API Specification, section 4.4.3.14 for more information.
*
* @param node_id NodeID for which the priority route will be set
* @param priority_route Array of 4 NodeIDs for the priority route + 1 byte
* for the route speed.
*
* @returns sl_status_t SL_STATUS_OK if the operation was accepted, any other
* code in case of failure.
*/
sl_status_t zwave_network_management_set_priority_route(
zwave_node_id_t node_id, const uint8_t *const priority_route);

/* An application MUST time out waiting for the
* ADD_NODE_STATUS_NODE_FOUND status if it does not receive the indication
* after calling AddNodeToNetwork(ADD_NODE_ANY).
Expand Down Expand Up @@ -369,6 +387,9 @@ bool we_have_return_routes_to_assign(zwave_node_id_t node_id);
#define ADD_NODE_PROTOCOL_NEIGHBOR_DISCOVERY_TIMEOUT \
(76000 + ZW_MAX_NODES * (3517 + 732))

/// 4 hops + speed
#define PRIORITY_ROUTE_SIZE 5

#ifdef __cplusplus
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,11 @@ void nm_fsm_post_event(nm_event_t ev, void *event_data)
== zwave_network_management_return_route_assign_next()) {
nms.state = NM_ASSIGNING_RETURN_ROUTE;
}
} else if (ev == NM_EV_SET_PRIORITY_ROUTE) {
route_event_data_t *priority_route_data
= (route_event_data_t *)(event_data);
zwapi_set_priority_route(priority_route_data->node_id,
priority_route_data->route);
}
break;
// End of case NM_IDLE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ typedef struct smartstart_event_data {
zwave_protocol_t preferred_inclusion;
} smartstart_event_data_t;

typedef struct route_event_data {
zwave_node_id_t node_id;
uint8_t route[PRIORITY_ROUTE_SIZE];
} route_event_data_t;

void nm_fsm_post_event(nm_event_t ev, void *event_data);
/*****************************************************************************/
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ const char *nm_event_name(nm_event_t event)
STR_CASE(NM_EV_LEARN_DONE)
STR_CASE(NM_EV_ASSIGN_RETURN_ROUTE_START)
STR_CASE(NM_EV_ASSIGN_RETURN_ROUTE_COMPLETED)
STR_CASE(NM_EV_SET_PRIORITY_ROUTE)
STR_CASE(NM_EV_MAX)

default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#define LOG_TAG "zwave_network_managment"

static smartstart_event_data_t smartstart_event_data;
static route_event_data_t priority_route_event_data;

void zwave_network_management_enable_smart_start_add_mode(bool enabled)
{
Expand Down Expand Up @@ -333,3 +334,25 @@ zwave_keyset_t zwave_network_management_get_granted_keys()
{
return zwave_s2_keystore_get_assigned_keys();
}

sl_status_t zwave_network_management_set_priority_route(
zwave_node_id_t node_id, const uint8_t *const priority_route)
{
if (false == network_management_is_ready_for_a_new_operation()) {
sl_log_info(LOG_TAG,
"Network management is not ready for a new operation. "
"Ignoring Set Priority Route.\n");
return SL_STATUS_FAIL;
}

sl_log_info(LOG_TAG, "Setting Priority Route\n");
priority_route_event_data.node_id = node_id;

memcpy(priority_route_event_data.route, priority_route, PRIORITY_ROUTE_SIZE);

process_post(&zwave_network_management_process,
NM_EV_SET_PRIORITY_ROUTE,
(void *)&priority_route_event_data);

return SL_STATUS_OK;
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ typedef enum {
NM_EV_REQUEST_NODE_NEIGHBOR_REQUEST_COMPLETE,
NM_EV_ASSIGN_RETURN_ROUTE_START,
NM_EV_ASSIGN_RETURN_ROUTE_COMPLETED,
NM_EV_SET_PRIORITY_ROUTE,
NM_EV_MAX, //This MUST always to be last entry in this enum
} nm_event_t;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ void test_zwave_network_management_state_event_logging_test()
TEST_ASSERT_EQUAL_STRING("NM_EV_LEARN_DONE", nm_event_name(NM_EV_LEARN_DONE));
TEST_ASSERT_EQUAL_STRING("NM_EV_ASSIGN_RETURN_ROUTE_START", nm_event_name(NM_EV_ASSIGN_RETURN_ROUTE_START));
TEST_ASSERT_EQUAL_STRING("NM_EV_ASSIGN_RETURN_ROUTE_COMPLETED", nm_event_name(NM_EV_ASSIGN_RETURN_ROUTE_COMPLETED));
TEST_ASSERT_EQUAL_STRING("NM_EV_SET_PRIORITY_ROUTE", nm_event_name(NM_EV_SET_PRIORITY_ROUTE));
TEST_ASSERT_EQUAL_STRING("NM_EV_MAX", nm_event_name(NM_EV_MAX));
TEST_ASSERT_EQUAL_STRING("Unknown", nm_event_name(NM_EV_MAX+1));
}
}
4 changes: 4 additions & 0 deletions applications/zpc/release_notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# ZPC Release Notes

## [Next]

* [Support command Set Priority Route Command](https://github.com/SiliconLabsSoftware/z-wave-protocol-controller/pull/96)

## [1.7.0] - Feb 2025

**BREAKING**: ZPC has been relocated outside of UnifySDK and is now dependent on it.
Expand Down
Loading