Skip to content

Commit ecd6ade

Browse files
committed
UIC-3657: add CLI interface for setting priority route
Enables the use of the CLI to set the priority route, as defined in the Z-Wave Host API Specification 4.4.3.14. Initially introduced in #96 Origin: #156
1 parent 534ceef commit ecd6ade

File tree

10 files changed

+225
-1
lines changed

10 files changed

+225
-1
lines changed

applications/zpc/components/zpc_stdin/src/zpc_stdin_command_handling.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ static sl_status_t handle_zwave_reset_mpan(const handle_args_t &arg);
9898
static sl_status_t handle_zwave_home_id(const handle_args_t &arg);
9999
static sl_status_t handle_enable_nls(const handle_args_t &arg);
100100
static sl_status_t handle_get_nls_state(const handle_args_t &arg);
101+
static sl_status_t handle_set_priority_route(const handle_args_t &arg);
101102

102103
/// Map that holds all the commands (used for printing help)
103104
///
@@ -168,6 +169,10 @@ const std::map<std::string, std::pair<std::string, handler_func>> commands = {
168169
&handle_add_zwave_node_abort}},
169170
{"zwave_add_node",
170171
{" :Add a Z-Wave node to the network", &handle_add_zwave_node}},
172+
{"zwave_set_priority_route",
173+
{" :Set the priority route to a destination node",
174+
&handle_set_priority_route}},
175+
171176
{"zwave_grant_keys",
172177
{COLOR_START
173178
"<1/0 to accept/reject the requested keys>,<Set of keys to"
@@ -620,6 +625,61 @@ static sl_status_t handle_zwave_learn_mode(const handle_args_t &arg)
620625
return SL_STATUS_OK;
621626
}
622627

628+
static sl_status_t handle_set_priority_route(const handle_args_t &arg)
629+
{
630+
zwave_node_id_t dst_node_id = 0;
631+
uint8_t route[PRIORITY_ROUTE_SIZE] = {0};
632+
const int max_node_id = 0xE8;
633+
634+
if (arg.size() != 7) {
635+
dprintf(out_stream,
636+
"Invalid number of arguments, expected args:"
637+
"<Dst NodeID>,<Hop 1>,<Hop 2>,<Hop 3>,<Hop 4>,<Speed> "
638+
"all values in hexadecimal\n");
639+
640+
return SL_STATUS_FAIL;
641+
}
642+
643+
try {
644+
dst_node_id
645+
= static_cast<zwave_node_id_t>(std::stoi(arg[1].c_str(), nullptr, 16));
646+
for (size_t i = 0; i < 5; ++i) {
647+
route[i]
648+
= static_cast<uint8_t>(std::stoi(arg[i + 2].c_str(), nullptr, 16));
649+
}
650+
} catch (const std::invalid_argument &e) {
651+
dprintf(out_stream, "Invalid argument: %s\n", e.what());
652+
return SL_STATUS_FAIL;
653+
}
654+
655+
if (dst_node_id <= 0 || dst_node_id > max_node_id) {
656+
dprintf(out_stream, "Invalid destination node id\n");
657+
return SL_STATUS_FAIL;
658+
}
659+
660+
bool previous_hop_was_direct = false;
661+
for (size_t i = 0; i < 4; ++i) {
662+
if (route[i] < 0 || route[i] > max_node_id) {
663+
dprintf(out_stream, "Invalid hop node id\n");
664+
return SL_STATUS_FAIL;
665+
}
666+
if (previous_hop_was_direct && route[i] != 0) {
667+
dprintf(out_stream, "Invalid route. Cannot set a node id after a zero\n");
668+
return SL_STATUS_FAIL;
669+
}
670+
if (0 == route[i]) {
671+
previous_hop_was_direct = true;
672+
}
673+
}
674+
675+
if (route[4] <= 0 || route[4] > 3) {
676+
dprintf(out_stream, "Invalid Route Speed.\n");
677+
return SL_STATUS_FAIL;
678+
}
679+
680+
return zwave_network_management_set_priority_route(dst_node_id, route);
681+
}
682+
623683
static sl_status_t handle_add_zwave_node(const handle_args_t &arg)
624684
{
625685
return zwave_network_management_add_node();

applications/zpc/components/zpc_stdin/test/zpc_stdin_test.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,3 +545,106 @@ void test_zwave_command_handler_dispatch()
545545
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);
546546
}
547547

548+
void test_zwave_set_priority_route_should_return_ok_with_valid_arguments(void)
549+
{
550+
sl_status_t state = SL_STATUS_FAIL;
551+
552+
zwave_network_management_set_priority_route_IgnoreAndReturn(SL_STATUS_OK);
553+
state
554+
= uic_stdin_handle_command("zwave_set_priority_route 02,01,00,00,00,01");
555+
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);
556+
557+
state
558+
= uic_stdin_handle_command("zwave_set_priority_route 01,02,03,04,05,01");
559+
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);
560+
561+
state
562+
= uic_stdin_handle_command("zwave_set_priority_route E8,02,03,04,05,01");
563+
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);
564+
565+
state
566+
= uic_stdin_handle_command("zwave_set_priority_route E8,E7,E8,E7,E0,01");
567+
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);
568+
}
569+
570+
void test_zwave_set_priority_route_should_return_fail_with_invalid_argument_count(
571+
void)
572+
{
573+
sl_status_t state = SL_STATUS_OK;
574+
575+
state = uic_stdin_handle_command("zwave_set_priority_route");
576+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
577+
578+
state = uic_stdin_handle_command("zwave_set_priority_route ,,,,");
579+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
580+
581+
state = uic_stdin_handle_command("zwave_set_priority_route 01");
582+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
583+
584+
state = uic_stdin_handle_command("zwave_set_priority_route 01,02,03,04,05");
585+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
586+
}
587+
588+
void test_zwave_set_priority_route_should_return_fail_with_wrong_argument_order(
589+
void)
590+
{
591+
sl_status_t state = SL_STATUS_OK;
592+
593+
state
594+
= uic_stdin_handle_command("zwave_set_priority_route 02,00,02,03,04,01");
595+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
596+
597+
state
598+
= uic_stdin_handle_command("zwave_set_priority_route 01,02,03,00,04,01");
599+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
600+
}
601+
602+
void test_zwave_set_priority_route_should_return_ok_with_valid_route(void)
603+
{
604+
uint8_t expected_route[] = {0x2, 0x3, 0x4, 0x5, 0x1};
605+
sl_status_t state = SL_STATUS_FAIL;
606+
607+
zwave_network_management_set_priority_route_ExpectAndReturn(0x01,
608+
expected_route,
609+
SL_STATUS_OK);
610+
state
611+
= uic_stdin_handle_command("zwave_set_priority_route 01,02,03,04,05,01");
612+
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);
613+
614+
expected_route[0] = 0xE7;
615+
expected_route[1] = 0xE6;
616+
expected_route[2] = 0xE5;
617+
expected_route[4] = 0xE4;
618+
expected_route[3] = 0x01;
619+
zwave_network_management_set_priority_route_ExpectAndReturn(0xE8,
620+
expected_route,
621+
SL_STATUS_OK);
622+
state
623+
= uic_stdin_handle_command("zwave_set_priority_route E8,E7,E6,E5,E4,01");
624+
TEST_ASSERT_EQUAL(SL_STATUS_OK, state);
625+
}
626+
627+
void test_zwave_set_priority_route_should_return_fail_with_invalid_node_id(void)
628+
{
629+
sl_status_t state = SL_STATUS_OK;
630+
631+
state
632+
= uic_stdin_handle_command("zwave_set_priority_route -1,02,03,04,05,01");
633+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
634+
635+
state
636+
= uic_stdin_handle_command("zwave_set_priority_route FF,02,03,04,05,01");
637+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
638+
639+
state
640+
= uic_stdin_handle_command("zwave_set_priority_route 01,FF,03,04,05,01");
641+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
642+
643+
state
644+
= uic_stdin_handle_command("zwave_set_priority_route E9,FF,03,04,05,01");
645+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
646+
647+
state
648+
= uic_stdin_handle_command("zwave_set_priority_route 01,E9,03,04,05,01");
649+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL, state);
650+
}

applications/zpc/components/zwave/zwave_network_management/include/zwave_network_management.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,24 @@ bool zwave_network_management_is_busy();
333333
*/
334334
bool we_have_return_routes_to_assign(zwave_node_id_t node_id);
335335

336+
/**
337+
* @brief Assign a priority route to a node.
338+
*
339+
* This function will set a priority route to a given node. The priority route
340+
* is a list with the NodeID of the hops that the Z-Wave controller will use as
341+
* a preferred route to the node. The last byte is the route speed. See Z-Wave
342+
* Host API Specification, section 4.4.3.14 for more information.
343+
*
344+
* @param node_id NodeID for which the priority route will be set
345+
* @param priority_route Array of 4 NodeIDs for the priority route + 1 byte
346+
* for the route speed.
347+
*
348+
* @returns sl_status_t SL_STATUS_OK if the operation was accepted, any other
349+
* code in case of failure.
350+
*/
351+
sl_status_t zwave_network_management_set_priority_route(
352+
zwave_node_id_t node_id, const uint8_t *const priority_route);
353+
336354
/* An application MUST time out waiting for the
337355
* ADD_NODE_STATUS_NODE_FOUND status if it does not receive the indication
338356
* after calling AddNodeToNetwork(ADD_NODE_ANY).
@@ -369,6 +387,9 @@ bool we_have_return_routes_to_assign(zwave_node_id_t node_id);
369387
#define ADD_NODE_PROTOCOL_NEIGHBOR_DISCOVERY_TIMEOUT \
370388
(76000 + ZW_MAX_NODES * (3517 + 732))
371389

390+
/// 4 hops + speed
391+
#define PRIORITY_ROUTE_SIZE 5
392+
372393
#ifdef __cplusplus
373394
}
374395
#endif

applications/zpc/components/zwave/zwave_network_management/src/nm_state_machine.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,11 @@ void nm_fsm_post_event(nm_event_t ev, void *event_data)
457457
== zwave_network_management_return_route_assign_next()) {
458458
nms.state = NM_ASSIGNING_RETURN_ROUTE;
459459
}
460+
} else if (ev == NM_EV_SET_PRIORITY_ROUTE) {
461+
route_event_data_t *priority_route_data
462+
= (route_event_data_t *)(event_data);
463+
zwapi_set_priority_route(priority_route_data->node_id,
464+
priority_route_data->route);
460465
}
461466
break;
462467
// End of case NM_IDLE:

applications/zpc/components/zwave/zwave_network_management/src/nm_state_machine.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ typedef struct smartstart_event_data {
9393
zwave_protocol_t preferred_inclusion;
9494
} smartstart_event_data_t;
9595

96+
typedef struct route_event_data {
97+
zwave_node_id_t node_id;
98+
uint8_t route[PRIORITY_ROUTE_SIZE];
99+
} route_event_data_t;
100+
96101
void nm_fsm_post_event(nm_event_t ev, void *event_data);
97102
/*****************************************************************************/
98103
/**

applications/zpc/components/zwave/zwave_network_management/src/state_logging.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ const char *nm_event_name(nm_event_t event)
107107
STR_CASE(NM_EV_LEARN_DONE)
108108
STR_CASE(NM_EV_ASSIGN_RETURN_ROUTE_START)
109109
STR_CASE(NM_EV_ASSIGN_RETURN_ROUTE_COMPLETED)
110+
STR_CASE(NM_EV_SET_PRIORITY_ROUTE)
110111
STR_CASE(NM_EV_MAX)
111112

112113
default:

applications/zpc/components/zwave/zwave_network_management/src/zwave_network_management.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#define LOG_TAG "zwave_network_managment"
3535

3636
static smartstart_event_data_t smartstart_event_data;
37+
static route_event_data_t priority_route_event_data;
3738

3839
void zwave_network_management_enable_smart_start_add_mode(bool enabled)
3940
{
@@ -333,3 +334,25 @@ zwave_keyset_t zwave_network_management_get_granted_keys()
333334
{
334335
return zwave_s2_keystore_get_assigned_keys();
335336
}
337+
338+
sl_status_t zwave_network_management_set_priority_route(
339+
zwave_node_id_t node_id, const uint8_t *const priority_route)
340+
{
341+
if (false == network_management_is_ready_for_a_new_operation()) {
342+
sl_log_info(LOG_TAG,
343+
"Network management is not ready for a new operation. "
344+
"Ignoring Set Priority Route.\n");
345+
return SL_STATUS_FAIL;
346+
}
347+
348+
sl_log_info(LOG_TAG, "Setting Priority Route\n");
349+
priority_route_event_data.node_id = node_id;
350+
351+
memcpy(priority_route_event_data.route, priority_route, PRIORITY_ROUTE_SIZE);
352+
353+
process_post(&zwave_network_management_process,
354+
NM_EV_SET_PRIORITY_ROUTE,
355+
(void *)&priority_route_event_data);
356+
357+
return SL_STATUS_OK;
358+
}

applications/zpc/components/zwave/zwave_network_management/src/zwave_network_management_process.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ typedef enum {
9494
NM_EV_REQUEST_NODE_NEIGHBOR_REQUEST_COMPLETE,
9595
NM_EV_ASSIGN_RETURN_ROUTE_START,
9696
NM_EV_ASSIGN_RETURN_ROUTE_COMPLETED,
97+
NM_EV_SET_PRIORITY_ROUTE,
9798
NM_EV_MAX, //This MUST always to be last entry in this enum
9899
} nm_event_t;
99100

applications/zpc/components/zwave/zwave_network_management/test/zwave_network_management_state_logging_test.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ void test_zwave_network_management_state_event_logging_test()
109109
TEST_ASSERT_EQUAL_STRING("NM_EV_LEARN_DONE", nm_event_name(NM_EV_LEARN_DONE));
110110
TEST_ASSERT_EQUAL_STRING("NM_EV_ASSIGN_RETURN_ROUTE_START", nm_event_name(NM_EV_ASSIGN_RETURN_ROUTE_START));
111111
TEST_ASSERT_EQUAL_STRING("NM_EV_ASSIGN_RETURN_ROUTE_COMPLETED", nm_event_name(NM_EV_ASSIGN_RETURN_ROUTE_COMPLETED));
112+
TEST_ASSERT_EQUAL_STRING("NM_EV_SET_PRIORITY_ROUTE", nm_event_name(NM_EV_SET_PRIORITY_ROUTE));
112113
TEST_ASSERT_EQUAL_STRING("NM_EV_MAX", nm_event_name(NM_EV_MAX));
113114
TEST_ASSERT_EQUAL_STRING("Unknown", nm_event_name(NM_EV_MAX+1));
114-
}
115+
}

applications/zpc/release_notes.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# ZPC Release Notes
22

3+
## [Next]
4+
5+
* [Support command Set Priority Route Command](https://github.com/SiliconLabsSoftware/z-wave-protocol-controller/pull/156)
6+
37
## [1.7.0] - Feb 2025
48

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

0 commit comments

Comments
 (0)