From d8a9d9119df43b163ab6b6799b50f1f04811132a Mon Sep 17 00:00:00 2001 From: lonkaars Date: Mon, 12 Dec 2022 16:20:35 +0100 Subject: serial communication *should* work --- shared/pclient.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 shared/pclient.c (limited to 'shared/pclient.c') diff --git a/shared/pclient.c b/shared/pclient.c new file mode 100644 index 0000000..41ace27 --- /dev/null +++ b/shared/pclient.c @@ -0,0 +1,122 @@ +#include + +#include "protocol.h" +#include "pclient.h" +#include "bin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +cd_s_bin* cd_cmd_gen_ping() { + CD_CREATE_MSG_BIN(cd_s_cmd_ping, msg, bin); + + msg->opcode = CD_CMD_PING; + msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); + + return bin; +} + +cd_s_bin* cd_cmd_gen_get_node(bool all, cd_uuid_t uuid) { + CD_CREATE_MSG_BIN(cd_s_cmd_get_node, msg, bin); + + msg->opcode = CD_CMD_GET_NODE; + msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); + msg->all = all; + memcpy(&msg->uuid, &uuid, sizeof(cd_uuid_t)); + + return bin; +} + +cd_s_bin* cd_cmd_gen_post_led(bool on, cd_uuid_t uuid) { + CD_CREATE_MSG_BIN(cd_s_cmd_post_led, msg, bin); + + msg->opcode = CD_CMD_POST_LED; + msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); + msg->on = on; + memcpy(&msg->uuid, &uuid, sizeof(cd_uuid_t)); + + return bin; +} + +cd_s_bin* cd_cmd_gen_post_link_add(cd_uuid_t button, cd_uuid_t light, cd_e_cmd_link_type type) { + CD_CREATE_MSG_BIN(cd_s_cmd_post_link, msg, bin); + + msg->opcode = CD_CMD_POST_LINK; + msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); + msg->add = true; + memcpy(&msg->button, &button, sizeof(cd_uuid_t)); + memcpy(&msg->led, &light, sizeof(cd_uuid_t)); + msg->type = type; + + return bin; +} + +cd_s_bin* cd_cmd_gen_post_link_rm(cd_uuid_t button, cd_uuid_t light) { + CD_CREATE_MSG_BIN(cd_s_cmd_post_link, msg, bin); + + msg->opcode = CD_CMD_POST_LINK; + msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); + msg->add = false; + memcpy(&msg->button, &button, sizeof(cd_uuid_t)); + memcpy(&msg->led, &light, sizeof(cd_uuid_t)); + + return bin; +} + +cd_s_bin* cd_cmd_gen_post_net_add(cd_uuid_t uuid) { + CD_CREATE_MSG_BIN(cd_s_cmd_post_net, msg, bin); + + msg->opcode = CD_CMD_POST_NET; + msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); + msg->join = true; + memcpy(&msg->uuid, &uuid, sizeof(cd_uuid_t)); + + return bin; +} + +cd_s_bin* cd_cmd_gen_post_net_rm(cd_uuid_t uuid) { + CD_CREATE_MSG_BIN(cd_s_cmd_post_net, msg, bin); + + msg->opcode = CD_CMD_POST_NET; + msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); + msg->join = false; + memcpy(&msg->uuid, &uuid, sizeof(cd_uuid_t)); + + return bin; +} + +cd_s_bin* cd_cmd_res_status(cd_e_scmds cmd, cd_cmd_id_t id, bool error) { + CD_CREATE_MSG_BIN(cd_s_cmd_response, msg, bin); + + msg->opcode = CD_CMD_RESPONSE; + msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); + msg->response_type = cmd; + msg->response_id = id; + msg->error = error; + msg->response_size = 0; + + return bin; +} + +cd_s_bin* cd_cmd_res_get_node(cd_e_scmds cmd, cd_cmd_id_t id, uint16_t node_count, cd_s_cmd_node* nodes) { + CD_CREATE_MSG_BIN(cd_s_cmd_response, msg, bin); + + msg->opcode = CD_CMD_RESPONSE; + msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); + msg->response_type = cmd; + msg->response_id = id; + msg->error = false; + + // TODO: test this?? + msg->response_size = sizeof(cd_s_cmd_response_get_node) + sizeof(cd_s_cmd_node) * node_count; + cd_s_cmd_response_get_node* get_node_response_ptr = (cd_s_cmd_response_get_node*) msg->response_info; + memcpy(get_node_response_ptr->nodes, nodes, sizeof(cd_s_cmd_node) * node_count); + + return bin; +} + +#ifdef __cplusplus +} +#endif + -- cgit v1.2.3 From 2c2ff814653f37947f8c253b29f8b08520ae71b7 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Tue, 13 Dec 2022 18:09:23 +0100 Subject: [WIP] node with pub/sub address and uuid --- confui/serial.cpp | 23 +++++++++++++++++++---- shared/bin.h | 2 +- shared/pclient.c | 31 ++++++++++++++++++++++++------- shared/pclient.h | 17 +++++++++++++---- shared/protocol.h | 17 ++++++++++++++++- 5 files changed, 73 insertions(+), 17 deletions(-) (limited to 'shared/pclient.c') diff --git a/confui/serial.cpp b/confui/serial.cpp index 1518abd..09bd7db 100644 --- a/confui/serial.cpp +++ b/confui/serial.cpp @@ -92,10 +92,25 @@ void cd_cmd_ping(cd_s_bin* data) { std::cout << "ping request with id " << cast->id << " received!" << std::endl; - cd_s_bin* response = cd_cmd_res_status((cd_e_scmds) cast->opcode, cast->id, false); - cd_pclient_send(response); - free(response); - response = nullptr; + // cd_s_bin* response = cd_cmd_res_status((cd_e_scmds) cast->opcode, cast->id, false); + // cd_pclient_send(response); + // free(response); + // response = nullptr; + + cd_uuid_t light_addrs[] = { + { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00 }, + }; + cd_s_cmd_node* test = cd_cmd_node_alloc({ + .uuid = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00 }, + .address = { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, }, + .light_on = false, + .provisioned = false, + .button_pub = 0xdeadbeef, + }, "gert", 1, light_addrs); + cd_s_bin* testres = cd_cmd_res(CD_CMD_GET_NODE, 0xf88f, test->size, (uint8_t*) test); + cd_pclient_send(testres); + free(testres); + free(test); } void cd_cmd_response(cd_s_bin* data) { diff --git a/shared/bin.h b/shared/bin.h index 0e16ec0..7506655 100644 --- a/shared/bin.h +++ b/shared/bin.h @@ -18,7 +18,7 @@ extern "C" { extern uint8_t g_cd_endianness; -/** cast `in.data` to `type out` */ +/** @brief cast `in.data` to `type out` */ #define CD_CAST_BIN(type, in, out) type *out = (type *)&in->data; #define CD_CREATE_MSG_BIN(type, normal, bin) CD_CREATE_MSG_SIZE_BIN(type, sizeof(type), normal, bin) /** @brief */ diff --git a/shared/pclient.c b/shared/pclient.c index 41ace27..0464428 100644 --- a/shared/pclient.c +++ b/shared/pclient.c @@ -99,23 +99,40 @@ cd_s_bin* cd_cmd_res_status(cd_e_scmds cmd, cd_cmd_id_t id, bool error) { return bin; } -cd_s_bin* cd_cmd_res_get_node(cd_e_scmds cmd, cd_cmd_id_t id, uint16_t node_count, cd_s_cmd_node* nodes) { - CD_CREATE_MSG_BIN(cd_s_cmd_response, msg, bin); +cd_s_bin* cd_cmd_res(cd_e_scmds cmd, cd_cmd_id_t id, uint16_t len, uint8_t* data) { + CD_CREATE_MSG_SIZE_BIN(cd_s_cmd_response, sizeof(cd_s_cmd_response) + len, msg, bin); msg->opcode = CD_CMD_RESPONSE; msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); msg->response_type = cmd; msg->response_id = id; msg->error = false; - - // TODO: test this?? - msg->response_size = sizeof(cd_s_cmd_response_get_node) + sizeof(cd_s_cmd_node) * node_count; - cd_s_cmd_response_get_node* get_node_response_ptr = (cd_s_cmd_response_get_node*) msg->response_info; - memcpy(get_node_response_ptr->nodes, nodes, sizeof(cd_s_cmd_node) * node_count); + msg->response_size = len; + memcpy(msg->response_info, data, len); return bin; } +cd_s_cmd_node* cd_cmd_node_alloc(cd_s_cmd_node base, const char* name, uint16_t link_count, cd_uuid_t* links) { + size_t name_len = strlen(name); + size_t links_len = sizeof(cd_uuid_t) * link_count; + size_t size = sizeof(cd_s_cmd_node) + sizeof(char) * name_len + links_len; + cd_s_cmd_node* node = malloc(size); + + memcpy(&node->uuid, &base.uuid, sizeof(cd_uuid_t)); + memcpy(&node->address, &base.address, sizeof(cd_mac_addr_t)); + node->name_len = name_len; + node->light_on = base.light_on; + node->provisioned = base.provisioned; + node->button_pub = cd_bin_hton32(base.button_pub); + node->link_count = cd_bin_hton16(link_count); + node->size = cd_bin_hton16(size); + memcpy((void *)&node->data_remainder, name, name_len); // copy name + memcpy((void *)&node->data_remainder + name_len, links, links_len); // copy links + + return node; +} + #ifdef __cplusplus } #endif diff --git a/shared/pclient.h b/shared/pclient.h index cf0f182..d0ddeb7 100644 --- a/shared/pclient.h +++ b/shared/pclient.h @@ -59,13 +59,22 @@ cd_s_bin* cd_cmd_gen_post_net_rm(cd_uuid_t uuid); */ cd_s_bin* cd_cmd_res_status(cd_e_scmds cmd, cd_cmd_id_t id, bool error); /** - * @brief generate RESPONSE command with GET_NODE response_info + * @brief generate RESPONSE command with response_info * @param cmd original command opcode * @param id original command id - * @param node_count amount of nodes in `nodes` - * @param nodes pointer to array of `cd_s_cmd_node` + * @param len size of `data` in bytes + * @param data pointer to data */ -cd_s_bin* cd_cmd_res_get_node(cd_e_scmds cmd, cd_cmd_id_t id, uint16_t node_count, cd_s_cmd_node* nodes); +cd_s_bin* cd_cmd_res(cd_e_scmds cmd, cd_cmd_id_t id, uint16_t len, uint8_t* data); +/** + * @brief allocate and fill cd_s_cmd_node struct + * + * @param base base struct with values that can be initialized using an initialization list + * @param name node name (length is calculated at runtime using strlen()) + * @param link_count amount of lights this node controls + * @param links array of light node uuids + */ +cd_s_cmd_node* cd_cmd_node_alloc(cd_s_cmd_node base, const char* name, uint16_t link_count, cd_uuid_t* links); #ifdef __cplusplus } diff --git a/shared/protocol.h b/shared/protocol.h index 63b4a9e..6f9697f 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -19,6 +19,9 @@ typedef uint8_t cd_mac_addr_t[6]; /** @brief uuid (ffeeddcc-bbaa-9988-7766-554433221100) */ typedef uint8_t cd_uuid_t[16]; +/** @brief pub/sub address type */ +typedef uint32_t cd_mesh_psub_addr; + /** @brief command opcode (identifies message type) */ typedef uint8_t cd_cmd_opcode_t; /** @brief command id (identifies messages uniquely) */ @@ -85,7 +88,19 @@ typedef struct { uint8_t name_len; /** @brief name length in bytes */ cd_cmd_bool_t light_on; /** @brief state of light on node */ cd_cmd_bool_t provisioned; /** @brief whether the node is provisioned into the network */ - const char name[]; /** @brief user-friendly node name */ + cd_mesh_psub_addr button_pub; /** @brief button publish address */ + uint16_t link_count; /** @brief amount of addresses to publish button press to */ + uint16_t size; /** @brief calculated size for convenience */ + const uint8_t data_remainder[]; /** + * @brief remaining data (name and link array) + * + * this data is stored adjacently in memory + * and is cast when reading/writing this + * struct + * + * 1. char[] name + * 2. cd_uuid_t[] light_publish_addresses; + */ } cd_s_cmd_node; typedef struct { -- cgit v1.2.3 From 4e4b35df42044c0f72a6f50a7f0158db4f379748 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 5 Jan 2023 13:51:33 +0100 Subject: fix `cd_s_cmd_node` alloc/create function --- confui/makefile | 3 +++ confui/serial.cpp | 9 +++++---- shared/pclient.c | 18 ++++++++++-------- shared/pclient.h | 4 +++- shared/protocol.h | 4 ++-- 5 files changed, 23 insertions(+), 15 deletions(-) (limited to 'shared/pclient.c') diff --git a/confui/makefile b/confui/makefile index e1faed6..2e22e20 100644 --- a/confui/makefile +++ b/confui/makefile @@ -18,3 +18,6 @@ FMT_FILES := $(filter-out %.pro,$(FMT_FILES)) # filter *.pro format: clang-format -i $(FMT_FILES) clang-tidy --fix-errors $(FMT_FILES) + +compile_commands: + compiledb make -Bn diff --git a/confui/serial.cpp b/confui/serial.cpp index 09bd7db..c0e686b 100644 --- a/confui/serial.cpp +++ b/confui/serial.cpp @@ -100,17 +100,18 @@ void cd_cmd_ping(cd_s_bin* data) { cd_uuid_t light_addrs[] = { { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00 }, }; - cd_s_cmd_node* test = cd_cmd_node_alloc({ + cd_s_cmd_node* test = cd_cmd_node_alloc("gert", { .uuid = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00 }, .address = { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, }, .light_on = false, .provisioned = false, .button_pub = 0xdeadbeef, - }, "gert", 1, light_addrs); - cd_s_bin* testres = cd_cmd_res(CD_CMD_GET_NODE, 0xf88f, test->size, (uint8_t*) test); + }, 1, light_addrs); + cd_s_bin* testres = cd_cmd_res(CD_CMD_GET_NODE, 0xf88f, cd_cmd_node_sizeof(test), (uint8_t*) test); + free(test); + cd_pclient_send(testres); free(testres); - free(test); } void cd_cmd_response(cd_s_bin* data) { diff --git a/shared/pclient.c b/shared/pclient.c index 0464428..be0e0a7 100644 --- a/shared/pclient.c +++ b/shared/pclient.c @@ -107,17 +107,17 @@ cd_s_bin* cd_cmd_res(cd_e_scmds cmd, cd_cmd_id_t id, uint16_t len, uint8_t* data msg->response_type = cmd; msg->response_id = id; msg->error = false; - msg->response_size = len; + msg->response_size = cd_bin_hton16(len); memcpy(msg->response_info, data, len); return bin; } -cd_s_cmd_node* cd_cmd_node_alloc(cd_s_cmd_node base, const char* name, uint16_t link_count, cd_uuid_t* links) { +cd_s_cmd_node* cd_cmd_node_alloc(const char* name, cd_s_cmd_node base, uint16_t link_count, cd_uuid_t* links) { size_t name_len = strlen(name); - size_t links_len = sizeof(cd_uuid_t) * link_count; - size_t size = sizeof(cd_s_cmd_node) + sizeof(char) * name_len + links_len; - cd_s_cmd_node* node = malloc(size); + size_t links_size = sizeof(cd_uuid_t) * link_count; + size_t remaining_size = sizeof(char) * name_len + links_size; + cd_s_cmd_node* node = malloc(sizeof(cd_s_cmd_node) + remaining_size); memcpy(&node->uuid, &base.uuid, sizeof(cd_uuid_t)); memcpy(&node->address, &base.address, sizeof(cd_mac_addr_t)); @@ -126,9 +126,11 @@ cd_s_cmd_node* cd_cmd_node_alloc(cd_s_cmd_node base, const char* name, uint16_t node->provisioned = base.provisioned; node->button_pub = cd_bin_hton32(base.button_pub); node->link_count = cd_bin_hton16(link_count); - node->size = cd_bin_hton16(size); - memcpy((void *)&node->data_remainder, name, name_len); // copy name - memcpy((void *)&node->data_remainder + name_len, links, links_len); // copy links + node->remaining_size = cd_bin_hton16(remaining_size); + void* cursor = (void*) &node->remaining_data[0]; + memcpy(cursor, name, name_len); // copy name + cursor += name_len; + memcpy(cursor, links, links_size); // copy links return node; } diff --git a/shared/pclient.h b/shared/pclient.h index d0ddeb7..e1bb7e7 100644 --- a/shared/pclient.h +++ b/shared/pclient.h @@ -74,7 +74,9 @@ cd_s_bin* cd_cmd_res(cd_e_scmds cmd, cd_cmd_id_t id, uint16_t len, uint8_t* data * @param link_count amount of lights this node controls * @param links array of light node uuids */ -cd_s_cmd_node* cd_cmd_node_alloc(cd_s_cmd_node base, const char* name, uint16_t link_count, cd_uuid_t* links); +cd_s_cmd_node* cd_cmd_node_alloc(const char* name, cd_s_cmd_node base, uint16_t link_count, cd_uuid_t* links); + +#define cd_cmd_node_sizeof(node) ((sizeof(cd_s_cmd_node) + cd_bin_ntoh16(node->remaining_size)) /* NOLINT */) #ifdef __cplusplus } diff --git a/shared/protocol.h b/shared/protocol.h index 6f9697f..dd5bcc6 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -90,8 +90,8 @@ typedef struct { cd_cmd_bool_t provisioned; /** @brief whether the node is provisioned into the network */ cd_mesh_psub_addr button_pub; /** @brief button publish address */ uint16_t link_count; /** @brief amount of addresses to publish button press to */ - uint16_t size; /** @brief calculated size for convenience */ - const uint8_t data_remainder[]; /** + uint16_t remaining_size; /** @brief calculated size of remaining_data for convenience */ + const uint8_t remaining_data[]; /** * @brief remaining data (name and link array) * * this data is stored adjacently in memory -- cgit v1.2.3 From 759d73e4ef0167c654535637488bdfcd423015a0 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 5 Jan 2023 15:03:58 +0100 Subject: improve parseability of get-nodes response --- confui/serial.cpp | 19 +++--- shared/pclient.c | 21 +++++++ shared/pclient.h | 10 ++- shared/protocol-tests/get-node-response.src | 98 +++++++++++++++-------------- shared/protocol.h | 5 +- 5 files changed, 95 insertions(+), 58 deletions(-) (limited to 'shared/pclient.c') diff --git a/confui/serial.cpp b/confui/serial.cpp index c0e686b..dd2a702 100644 --- a/confui/serial.cpp +++ b/confui/serial.cpp @@ -97,21 +97,26 @@ void cd_cmd_ping(cd_s_bin* data) { // free(response); // response = nullptr; - cd_uuid_t light_addrs[] = { + cd_uuid_t test_node_light_addrs[] = { { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00 }, }; - cd_s_cmd_node* test = cd_cmd_node_alloc("gert", { + cd_s_cmd_node* test_node = cd_cmd_node_alloc("gert", { .uuid = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00 }, .address = { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, }, .light_on = false, .provisioned = false, .button_pub = 0xdeadbeef, - }, 1, light_addrs); - cd_s_bin* testres = cd_cmd_res(CD_CMD_GET_NODE, 0xf88f, cd_cmd_node_sizeof(test), (uint8_t*) test); - free(test); + }, 1, test_node_light_addrs); - cd_pclient_send(testres); - free(testres); + cd_s_cmd_node* nodes[] = { test_node }; + cd_s_cmd_response_get_node* response_get_nodes = cd_cmd_get_node_res_from_node_arr(1, nodes); + free(test_node); + + cd_s_bin* response = cd_cmd_res(CD_CMD_GET_NODE, 0xf88f, cd_cmd_response_get_node_sizeof(response_get_nodes), (uint8_t*) response_get_nodes); + free(response_get_nodes); + + cd_pclient_send(response); + free(response); } void cd_cmd_response(cd_s_bin* data) { diff --git a/shared/pclient.c b/shared/pclient.c index be0e0a7..728bfa0 100644 --- a/shared/pclient.c +++ b/shared/pclient.c @@ -135,6 +135,27 @@ cd_s_cmd_node* cd_cmd_node_alloc(const char* name, cd_s_cmd_node base, uint16_t return node; } +cd_s_cmd_response_get_node* cd_cmd_get_node_res_from_node_arr(uint16_t size, cd_s_cmd_node* arr[]) { + size_t remaining_size = 0; + + for (unsigned int i = 0; i < size; i++) { + remaining_size += sizeof(cd_s_cmd_node) + cd_bin_ntoh16(arr[i]->remaining_size); + } + + cd_s_cmd_response_get_node* response = malloc(sizeof(cd_s_cmd_response_get_node) + remaining_size); + response->node_count = cd_bin_hton16(size); + response->remaining_size = cd_bin_hton16(remaining_size); + + void* cursor = response->nodes; + for (unsigned int i = 0; i < size; i++) { + size_t size = sizeof(cd_s_cmd_node) + cd_bin_ntoh16(arr[i]->remaining_size); + memcpy(cursor, arr[i], size); + cursor += size; + } + + return response; +} + #ifdef __cplusplus } #endif diff --git a/shared/pclient.h b/shared/pclient.h index e1bb7e7..03a8a25 100644 --- a/shared/pclient.h +++ b/shared/pclient.h @@ -66,6 +66,12 @@ cd_s_bin* cd_cmd_res_status(cd_e_scmds cmd, cd_cmd_id_t id, bool error); * @param data pointer to data */ cd_s_bin* cd_cmd_res(cd_e_scmds cmd, cd_cmd_id_t id, uint16_t len, uint8_t* data); +/** + * @brief generate cd_s_cmd_response_get_node struct from array of cd_s_cmd_node pointers + * @param size length of array + * @param arr array of pointer to cd_s_cmd_node + */ +cd_s_cmd_response_get_node* cd_cmd_get_node_res_from_node_arr(uint16_t size, cd_s_cmd_node* arr[]); /** * @brief allocate and fill cd_s_cmd_node struct * @@ -76,7 +82,9 @@ cd_s_bin* cd_cmd_res(cd_e_scmds cmd, cd_cmd_id_t id, uint16_t len, uint8_t* data */ cd_s_cmd_node* cd_cmd_node_alloc(const char* name, cd_s_cmd_node base, uint16_t link_count, cd_uuid_t* links); -#define cd_cmd_node_sizeof(node) ((sizeof(cd_s_cmd_node) + cd_bin_ntoh16(node->remaining_size)) /* NOLINT */) +#define cd_remaining_sizeof(type, input_struct) ((sizeof(type) + cd_bin_ntoh16(input_struct->remaining_size)) /* NOLINT */) +#define cd_cmd_node_sizeof(node) (cd_remaining_sizeof(cd_s_cmd_node, node) /* NOLINT */) +#define cd_cmd_response_get_node_sizeof(res) (cd_remaining_sizeof(cd_s_cmd_response_get_node, res) /* NOLINT */) #ifdef __cplusplus } diff --git a/shared/protocol-tests/get-node-response.src b/shared/protocol-tests/get-node-response.src index f10ffe0..31bf1ff 100644 --- a/shared/protocol-tests/get-node-response.src +++ b/shared/protocol-tests/get-node-response.src @@ -6,74 +6,76 @@ 05: 01 ; response type (0x01 = get node) 06: 8f ; original message id (0x8ff8) 07: f8 ; ^ -08: 00 ; remaining response size (0x35 = 53 bytes) -09: 35 ; ^ +08: 00 ; remaining response size (0x39 = 57 bytes) +09: 39 ; ^ -------; |- remaining response (cd_s_cmd_response_get_node) 0a: 00 ; | node count (0x0001 = 1) 0b: 01 ; | ^ +0c: 00 ; | remaining response size (0x35 = 53 bytes) +0d: 35 ; | ^ -------; | |- remaining response (cd_s_cmd_node[1]) -0c: ff ; | | [esc] -0d: ff ; | | uuid (ffffffff-0000-0000-dead-beef00000000) 0e: ff ; | | [esc] -0f: ff ; | | ^ +0f: ff ; | | uuid (ffffffff-0000-0000-dead-beef00000000) 10: ff ; | | [esc] 11: ff ; | | ^ 12: ff ; | | [esc] 13: ff ; | | ^ -14: 00 ; | | ^ -15: 00 ; | | ^ +14: ff ; | | [esc] +15: ff ; | | ^ 16: 00 ; | | ^ 17: 00 ; | | ^ -18: de ; | | ^ -19: ad ; | | ^ -1a: be ; | | ^ -1b: ef ; | | ^ -1c: 00 ; | | ^ -1d: 00 ; | | ^ +18: 00 ; | | ^ +19: 00 ; | | ^ +1a: de ; | | ^ +1b: ad ; | | ^ +1c: be ; | | ^ +1d: ef ; | | ^ 1e: 00 ; | | ^ 1f: 00 ; | | ^ -20: ff ; | | [esc] -21: ff ; | | mac address (ff:00:ff:00:ff:00) -22: 00 ; | | ^ -23: ff ; | | [esc] -24: ff ; | | ^ -25: 00 ; | | ^ -26: ff ; | | [esc] -27: ff ; | | ^ -28: 00 ; | | ^ -29: 04 ; | | name length (0x04 = 4) -2a: 00 ; | | light on (0x00 = false) -2b: 00 ; | | provisioned (0x00 = false) -2c: de ; | | button publish address (0xdeadbeef) -2d: ad ; | | ^ -2e: be ; | | ^ -2f: ef ; | | ^ -30: 00 ; | | link count (0x0001 = 1) -31: 01 ; | | ^ -32: 00 ; | | remaining size (0x14 = 20 bytes) -33: 14 ; | | ^ +20: 00 ; | | ^ +21: 00 ; | | ^ +22: ff ; | | [esc] +23: ff ; | | mac address (ff:00:ff:00:ff:00) +24: 00 ; | | ^ +25: ff ; | | [esc] +26: ff ; | | ^ +27: 00 ; | | ^ +28: ff ; | | [esc] +29: ff ; | | ^ +2a: 00 ; | | ^ +2b: 04 ; | | name length (0x04 = 4) +2c: 00 ; | | light on (0x00 = false) +2d: 00 ; | | provisioned (0x00 = false) +2e: de ; | | button publish address (0xdeadbeef) +2f: ad ; | | ^ +30: be ; | | ^ +31: ef ; | | ^ +32: 00 ; | | link count (0x0001 = 1) +33: 01 ; | | ^ +34: 00 ; | | remaining size (0x14 = 20 bytes) +35: 14 ; | | ^ -------; | | |- remaining response (char[4], cd_uuid_t[1]) -34: 67 ; | | | node name ("gert") -35: 65 ; | | | ^ -36: 72 ; | | | ^ -37: 74 ; | | | ^ -38: ff ; | | | [esc] -39: ff ; | | | link[0] uuid (ffffffff-0000-0000-dead-beef00000000) +36: 67 ; | | | node name ("gert") +37: 65 ; | | | ^ +38: 72 ; | | | ^ +39: 74 ; | | | ^ 3a: ff ; | | | [esc] -3b: ff ; | | | ^ +3b: ff ; | | | link[0] uuid (ffffffff-0000-0000-dead-beef00000000) 3c: ff ; | | | [esc] 3d: ff ; | | | ^ 3e: ff ; | | | [esc] 3f: ff ; | | | ^ -40: 00 ; | | | ^ -41: 00 ; | | | ^ +40: ff ; | | | [esc] +41: ff ; | | | ^ 42: 00 ; | | | ^ 43: 00 ; | | | ^ -44: de ; | | | ^ -45: ad ; | | | ^ -46: be ; | | | ^ -47: ef ; | | | ^ -48: 00 ; | | | ^ -49: 00 ; | | | ^ +44: 00 ; | | | ^ +45: 00 ; | | | ^ +46: de ; | | | ^ +47: ad ; | | | ^ +48: be ; | | | ^ +49: ef ; | | | ^ 4a: 00 ; | | | ^ 4b: 00 ; | | | ^ +4c: 00 ; | | | ^ +4d: 00 ; | | | ^ diff --git a/shared/protocol.h b/shared/protocol.h index dd5bcc6..cad9a1c 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -104,8 +104,9 @@ typedef struct { } cd_s_cmd_node; typedef struct { - uint16_t node_count; - cd_s_cmd_node nodes[]; + uint16_t node_count; /** amount of nodes in nodes[] */ + uint16_t remaining_size; /** remaining size (for convenience) */ + cd_s_cmd_node nodes[]; /** nodes adjacent in memory (should be accessed using pointer arithmetic) */ } cd_s_cmd_response_get_node; typedef struct { -- cgit v1.2.3 From b155a5fa4b97f6f5f63f7079c671b5965db9d022 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 6 Jan 2023 15:29:26 +0100 Subject: send POST_LINK --- confui/mesh_connector.cpp | 26 ++++++++++++++++++++------ confui/mesh_connector.h | 21 +++++++++++---------- confui/ui_automation.cpp | 4 ++-- confui/ui_node.cpp | 2 +- shared/pclient.c | 9 +++++---- shared/protocol.h | 8 ++++---- 6 files changed, 43 insertions(+), 27 deletions(-) (limited to 'shared/pclient.c') diff --git a/confui/mesh_connector.cpp b/confui/mesh_connector.cpp index 2630da6..c77c159 100644 --- a/confui/mesh_connector.cpp +++ b/confui/mesh_connector.cpp @@ -4,6 +4,7 @@ #include #include +#include "../shared/pclient.h" #include "mesh_connector.h" using std::pair; @@ -99,7 +100,7 @@ map CDMeshConnector::get_links(bool valid) { return links; } -void CDMeshConnector::update_link(cd_s_automation *automation) { +void CDMeshConnector::update_link(cd_s_automation *automation, bool publish) { printf("link[%d]", automation->id); if (automation->valid) { printf(" = %.*s %s %.*s", (int)automation->button->name_len, automation->button->name, @@ -111,9 +112,16 @@ void CDMeshConnector::update_link(cd_s_automation *automation) { printf(" (invalid)"); } printf("\n"); + + if (!publish) return; + if (!automation->valid) return; + + cd_s_bin* msg = cd_cmd_gen_post_link_add(automation->button->uuid, automation->light->uuid, automation->type); + cd_pclient_send(msg); + free(msg); } -cd_link_t CDMeshConnector::create_link(cd_uid_t button, cd_uid_t light, enum cd_e_automation_type type) { +cd_link_t CDMeshConnector::create_link(cd_uid_t button, cd_uid_t light, cd_e_automation_type type) { cd_link_t id = get_new_link_id(); cd_s_automation *automation = (cd_s_automation *)malloc(sizeof(cd_s_automation)); @@ -147,11 +155,17 @@ cd_link_t CDMeshConnector::create_link() { return id; } -void CDMeshConnector::remove_link(cd_link_t link_handle) { +void CDMeshConnector::remove_link(cd_link_t link_handle, bool publish) { printf("remove link[%d]\n", link_handle); - if (_links[link_handle] != nullptr) free(_links[link_handle]); + if (_links.count(link_handle) == 0) return; // invalid handle + if (_links[link_handle] == nullptr) return; // already removed link + + cd_s_bin* msg = cd_cmd_gen_post_link_rm(_links[link_handle]->button->uuid, _links[link_handle]->light->uuid); + cd_pclient_send(msg); + free(msg); + + free(_links[link_handle]); _links[link_handle] = nullptr; - return; } void CDMeshConnector::remove_node(cd_uid_t node_handle) { @@ -161,7 +175,7 @@ void CDMeshConnector::remove_node(cd_uid_t node_handle) { return; } -void CDMeshConnector::update_node(cd_s_node *node_ptr) { +void CDMeshConnector::update_node(cd_s_node *node_ptr, bool publish) { printf("turning %.*s %s\n", (int)node_ptr->name_len, node_ptr->name, node_ptr->light_on ? "on" : "off"); return; } diff --git a/confui/mesh_connector.h b/confui/mesh_connector.h index 64ab471..8c1fc91 100644 --- a/confui/mesh_connector.h +++ b/confui/mesh_connector.h @@ -18,12 +18,10 @@ typedef uint32_t cd_uid_t; /** @brief link/automation id type */ typedef uint32_t cd_link_t; -/** @brief automation types/actions */ -enum cd_e_automation_type { - CD_AUTOMATION_TYPE_TOGGLE, /** @brief button toggles light */ - CD_AUTOMATION_TYPE_TURN_ON, /** @brief button always turns on light (regardless of previous state) */ - CD_AUTOMATION_TYPE_TURN_OFF, /** @brief button always turns off light (regardless of previous state) */ -}; +typedef cd_e_cmd_link_type cd_e_automation_type; +#define CD_AUTOMATION_TYPE_TOGGLE CD_CMD_LINK_TYPE_TOGGLE +#define CD_AUTOMATION_TYPE_TURN_ON CD_CMD_LINK_TYPE_TURN_ON +#define CD_AUTOMATION_TYPE_TURN_OFF CD_CMD_LINK_TYPE_TURN_OFF /** @brief GUI node representation */ typedef struct { @@ -117,7 +115,7 @@ public: * @param light node id for node whose light will be used for this automation. * @param action action/automation type (toggle, on, off). */ - virtual cd_link_t create_link(cd_uid_t button, cd_uid_t light, enum cd_e_automation_type action); + virtual cd_link_t create_link(cd_uid_t button, cd_uid_t light, cd_e_automation_type action); /** * @brief overwrite link id with new automation and update on network. * @@ -126,14 +124,16 @@ public: * properties. * * @param automation pointer to automation struct (with new/modified values) + * @param publish `true` to send POST_LINK command */ - virtual void update_link(cd_s_automation *automation); + virtual void update_link(cd_s_automation *automation, bool publish = false); /** * @brief remove automation and update on network. * * @param link_handle automation id + * @param publish `true` to send POST_LINK command */ - virtual void remove_link(cd_link_t link_handle); + virtual void remove_link(cd_link_t link_handle, bool publish = false); /** * @brief overwrite node id with new node and update on network. @@ -142,8 +142,9 @@ public: * allocated using malloc()). used to update existing node properties. * * @param node_ptr pointer to node struct (with new/modified state) + * @param publish `true` to send POST_LED command */ - virtual void update_node(cd_s_node *node_ptr); + virtual void update_node(cd_s_node *node_ptr, bool publish = false); /** * @brief provision node into network * diff --git a/confui/ui_automation.cpp b/confui/ui_automation.cpp index eb6e1f6..2ade734 100644 --- a/confui/ui_automation.cpp +++ b/confui/ui_automation.cpp @@ -74,11 +74,11 @@ void CDAutomationWidget::apply() { if (!conf_valid()) return; _automation->button = g_cd_mesh_connector->get_node(dropdown_button->findData(dropdown_button->currentIndex())); - _automation->type = (enum cd_e_automation_type)dropdown_action->findData(dropdown_action->currentIndex()); + _automation->type = (cd_e_automation_type) dropdown_action->findData(dropdown_action->currentIndex()); _automation->light = g_cd_mesh_connector->get_node(dropdown_light->findData(dropdown_light->currentIndex())); _automation->valid = true; - g_cd_mesh_connector->update_link(_automation); + g_cd_mesh_connector->update_link(_automation, true); } void CDAutomationWidget::remove() { diff --git a/confui/ui_node.cpp b/confui/ui_node.cpp index 552b62a..56ff004 100644 --- a/confui/ui_node.cpp +++ b/confui/ui_node.cpp @@ -54,7 +54,7 @@ void CDNodeWidget::toggle_provision() { void CDNodeWidget::update_led(bool on) { _node->light_on = on; - g_cd_mesh_connector->update_node(_node); + g_cd_mesh_connector->update_node(_node, true); update(); } diff --git a/shared/pclient.c b/shared/pclient.c index 728bfa0..ff2315c 100644 --- a/shared/pclient.c +++ b/shared/pclient.c @@ -45,8 +45,8 @@ cd_s_bin* cd_cmd_gen_post_link_add(cd_uuid_t button, cd_uuid_t light, cd_e_cmd_l msg->opcode = CD_CMD_POST_LINK; msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); msg->add = true; - memcpy(&msg->button, &button, sizeof(cd_uuid_t)); - memcpy(&msg->led, &light, sizeof(cd_uuid_t)); + memcpy(msg->button, button, sizeof(cd_uuid_t)); + memcpy(msg->led, light, sizeof(cd_uuid_t)); msg->type = type; return bin; @@ -58,8 +58,9 @@ cd_s_bin* cd_cmd_gen_post_link_rm(cd_uuid_t button, cd_uuid_t light) { msg->opcode = CD_CMD_POST_LINK; msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); msg->add = false; - memcpy(&msg->button, &button, sizeof(cd_uuid_t)); - memcpy(&msg->led, &light, sizeof(cd_uuid_t)); + memcpy(msg->button, button, sizeof(cd_uuid_t)); + memcpy(msg->led, light, sizeof(cd_uuid_t)); + msg->type = 0; return bin; } diff --git a/shared/protocol.h b/shared/protocol.h index cad9a1c..b9a2c93 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -60,9 +60,9 @@ typedef struct { } cd_s_cmd_post_led; typedef enum { - CD_CMD_LINK_TYPE_TOGGLE = 0x00, - CD_CMD_LINK_TYPE_TURN_ON = 0x01, - CD_CMD_LINK_TYPE_TURN_OFF = 0x02, + CD_CMD_LINK_TYPE_TOGGLE = 0x00, /** @brief button toggles light */ + CD_CMD_LINK_TYPE_TURN_ON = 0x01, /** @brief button always turns on light (regardless of previous state) */ + CD_CMD_LINK_TYPE_TURN_OFF = 0x02, /** @brief button always turns off light (regardless of previous state) */ } cd_e_cmd_link_type; typedef struct { @@ -71,7 +71,7 @@ typedef struct { cd_uuid_t button; /** @brief uuid of button node */ cd_uuid_t led; /** @brief uuid of led node */ cd_cmd_bool_t add; /** @brief `true` to create/overwrite link, `false` to remove link */ - cd_e_cmd_link_type type; /** @brief link type */ + uint8_t type; /** @brief link type cd_e_cmd_link_type */ } cd_s_cmd_post_link; typedef struct { -- cgit v1.2.3 From 847b4a5d588ec504865398c21c3bcb73a6fc1fab Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sat, 7 Jan 2023 13:47:41 +0100 Subject: implement get node --- confui/mainwindow.cpp | 5 +++++ confui/ui_node.cpp | 5 +++++ shared/pclient.c | 13 +++++++------ shared/protocol.h | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) (limited to 'shared/pclient.c') diff --git a/confui/mainwindow.cpp b/confui/mainwindow.cpp index b5bbdf0..4c9b857 100644 --- a/confui/mainwindow.cpp +++ b/confui/mainwindow.cpp @@ -7,6 +7,7 @@ #include "ui_tab_automations.h" #include "ui_tab_node_overview.h" #include "serial.h" +#include "../shared/pclient.h" #include "main.h" CDMeshConnector *g_cd_mesh_connector = nullptr; @@ -73,6 +74,10 @@ void CDMainWindow::update() { QAction* menu_port = menu_options_serialport->addAction(QString::fromStdString(port)); connect(menu_port, &QAction::triggered, this, [this, port](){ menu_set_serial_port(port); }); } + + cd_s_bin* msg = cd_cmd_gen_get_node(true, NULL); + cd_pclient_send(msg); + free(msg); } void CDMainWindow::menu_refresh() { update(); } diff --git a/confui/ui_node.cpp b/confui/ui_node.cpp index 56ff004..09daaaa 100644 --- a/confui/ui_node.cpp +++ b/confui/ui_node.cpp @@ -1,4 +1,5 @@ #include "ui_node.h" +#include "../shared/pclient.h" CDNodeWidget::~CDNodeWidget() {} CDNodeWidget::CDNodeWidget(QWidget *parent) : QWidget(parent) { @@ -43,6 +44,10 @@ void CDNodeWidget::update() { switch_on_off->setChecked(_node->light_on); button_add_remove->setText(_node->provisioned ? "Remove from network" : "Join network"); + + cd_s_bin* msg = cd_cmd_gen_get_node(false, this->_node->uuid); + cd_pclient_send(msg); + free(msg); } void CDNodeWidget::toggle_provision() { diff --git a/shared/pclient.c b/shared/pclient.c index ff2315c..1b8e4e5 100644 --- a/shared/pclient.c +++ b/shared/pclient.c @@ -23,7 +23,8 @@ cd_s_bin* cd_cmd_gen_get_node(bool all, cd_uuid_t uuid) { msg->opcode = CD_CMD_GET_NODE; msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); msg->all = all; - memcpy(&msg->uuid, &uuid, sizeof(cd_uuid_t)); + if (uuid != NULL) memcpy(msg->uuid, uuid, sizeof(cd_uuid_t)); + else memset(msg->uuid, 0, sizeof(cd_uuid_t)); return bin; } @@ -34,7 +35,7 @@ cd_s_bin* cd_cmd_gen_post_led(bool on, cd_uuid_t uuid) { msg->opcode = CD_CMD_POST_LED; msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); msg->on = on; - memcpy(&msg->uuid, &uuid, sizeof(cd_uuid_t)); + memcpy(msg->uuid, uuid, sizeof(cd_uuid_t)); return bin; } @@ -71,7 +72,7 @@ cd_s_bin* cd_cmd_gen_post_net_add(cd_uuid_t uuid) { msg->opcode = CD_CMD_POST_NET; msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); msg->join = true; - memcpy(&msg->uuid, &uuid, sizeof(cd_uuid_t)); + memcpy(msg->uuid, uuid, sizeof(cd_uuid_t)); return bin; } @@ -82,7 +83,7 @@ cd_s_bin* cd_cmd_gen_post_net_rm(cd_uuid_t uuid) { msg->opcode = CD_CMD_POST_NET; msg->id = cd_bin_hton16(cd_protocol_fresh_message_id()); msg->join = false; - memcpy(&msg->uuid, &uuid, sizeof(cd_uuid_t)); + memcpy(msg->uuid, uuid, sizeof(cd_uuid_t)); return bin; } @@ -120,8 +121,8 @@ cd_s_cmd_node* cd_cmd_node_alloc(const char* name, cd_s_cmd_node base, uint16_t size_t remaining_size = sizeof(char) * name_len + links_size; cd_s_cmd_node* node = malloc(sizeof(cd_s_cmd_node) + remaining_size); - memcpy(&node->uuid, &base.uuid, sizeof(cd_uuid_t)); - memcpy(&node->address, &base.address, sizeof(cd_mac_addr_t)); + memcpy(node->uuid, base.uuid, sizeof(cd_uuid_t)); + memcpy(node->address, base.address, sizeof(cd_mac_addr_t)); node->name_len = name_len; node->light_on = base.light_on; node->provisioned = base.provisioned; diff --git a/shared/protocol.h b/shared/protocol.h index 3ec9838..c742c82 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -171,7 +171,7 @@ static size_t (* const CD_CMD_HANDLERS_SIZEOF[CD_CMD_COUNT])(cd_s_bin*) = { /** @brief stores message handlers in array with opcode as index */ static cd_cmd_handler_t* const CD_CMD_HANDLERS[CD_CMD_COUNT] = { [CD_CMD_PING] = &cd_cmd_ping, // implemented - [CD_CMD_GET_NODE] = &cd_cmd_get_node, + [CD_CMD_GET_NODE] = &cd_cmd_get_node, // implemented [CD_CMD_POST_LED] = &cd_cmd_post_led, [CD_CMD_POST_LINK] = &cd_cmd_post_link, // implemented [CD_CMD_POST_NET] = &cd_cmd_post_net, -- cgit v1.2.3