aboutsummaryrefslogtreecommitdiff
path: root/shared/protocol.h
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2022-12-11 16:13:03 +0100
committerlonkaars <loek@pipeframe.xyz>2022-12-11 16:13:03 +0100
commitae3970ad5e1b3495726b70d5653c2424fccfba07 (patch)
tree0db610942b60ef1cf847d1de5107fd1c987ad6d2 /shared/protocol.h
parentc265bc642b33c15f8446ceef318373a2f2bdee1d (diff)
add serial parser from robotrun to project
Diffstat (limited to 'shared/protocol.h')
-rw-r--r--shared/protocol.h163
1 files changed, 163 insertions, 0 deletions
diff --git a/shared/protocol.h b/shared/protocol.h
new file mode 100644
index 0000000..e2b3b1c
--- /dev/null
+++ b/shared/protocol.h
@@ -0,0 +1,163 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @file protocol.h */
+
+#define CD_SERIAL_START_BYTE 0xff
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "bin.h"
+#include "consts.h"
+
+/** @brief mac address (00:11:22:33:44:55) */
+typedef uint8_t cd_mac_addr_t[6];
+/** @brief uuid (ffeeddcc-bbaa-9988-7766-554433221100) */
+typedef uint8_t cd_uuid_t[16];
+
+/** @brief command opcode (identifies message type) */
+typedef uint8_t cd_cmd_opcode_t;
+/** @brief command id (identifies messages uniquely) */
+typedef uint16_t cd_cmd_id_t;
+/** @brief smallest boolean type */
+typedef uint8_t cd_cmd_bool_t;
+
+/** @brief cmd handler function signature */
+typedef void (cd_cmd_handler)(cd_s_bin *data);
+
+#pragma pack(push, 1)
+
+typedef struct {
+ cd_cmd_opcode_t opcode; /** @brief cmd opcode */
+ cd_cmd_id_t id; /** @brief message id */
+} cd_s_cmd_ping;
+
+typedef struct {
+ cd_cmd_opcode_t opcode; /** @brief cmd opcode */
+ cd_cmd_id_t id; /** @brief message id */
+ cd_cmd_bool_t all; /** @brief get all known nodes */
+ cd_uuid_t uuid; /** @brief node uuid to get details from, ignored if `all` = `true` */
+} cd_s_cmd_get_node;
+
+typedef struct {
+ cd_cmd_opcode_t opcode; /** @brief cmd opcode */
+ cd_cmd_id_t id; /** @brief message id */
+ cd_cmd_bool_t on; /** @brief new led status */
+ cd_uuid_t uuid; /** @brief node uuid to set */
+} cd_s_cmd_post_led;
+
+typedef struct {
+ cd_cmd_opcode_t opcode; /** @brief cmd opcode */
+ cd_cmd_id_t id; /** @brief message id */
+} cd_s_cmd_post_link;
+
+typedef struct {
+ cd_cmd_opcode_t opcode; /** @brief cmd opcode */
+ cd_cmd_id_t id; /** @brief message id */
+ cd_uuid_t uuid; /** @brief node uuid */
+ cd_cmd_bool_t join; /** @brief `true` to join network, `false` to leave network */
+} cd_s_cmd_post_net;
+
+typedef struct {
+} cd_s_cmd_response_ping;
+
+/** @brief protocol node */
+typedef struct {
+ cd_uuid_t uuid; /** @brief node network uuid */
+ cd_mac_addr_t address; /** @brief node bluetooth mac address */
+ 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_s_cmd_node;
+
+typedef struct {
+ uint16_t node_count;
+ cd_s_cmd_node nodes[];
+} cd_s_cmd_response_get_node;
+
+typedef struct {
+} cd_s_cmd_response_post_led;
+
+typedef struct {
+} cd_s_cmd_response_post_link;
+
+typedef struct {
+} cd_s_cmd_response_post_net;
+
+typedef struct {
+ cd_cmd_opcode_t opcode; /** @brief cmd opcode */
+ cd_cmd_id_t id; /** @brief response message id */
+ cd_cmd_bool_t success; /** @brief `true` if some error occurred */
+ cd_cmd_id_t response_id; /** @brief original message id */
+ cd_cmd_opcode_t response_type; /** @brief response type, used to cast type of `response_info` */
+ uint16_t response_size; /** @brief size of remaining response */
+ uint8_t response_info[]; /** @brief (CAST) remaining response struct, not read if `response_size`=`0` */
+} cd_s_cmd_response;
+
+#pragma pack(pop)
+
+/** @brief global handler for complete messages */
+void cd_cmd_handle(uint8_t data[CD_SERIAL_READ_BUFFER_SIZE], uint8_t length);
+/** @brief calculate message length for any message */
+size_t cd_cmd_sizeof(uint8_t data[CD_SERIAL_READ_BUFFER_SIZE], uint8_t length);
+
+/** @brief calculate dynamic size of response message */
+size_t cd_cmd_response_sizeof(cd_s_bin* data);
+
+// down here is the garbage manual duplicate code section for constants
+
+#define CD_CMD_COUNT 6
+typedef enum {
+ CD_CMD_PING = 0x00, /** @brief send ping */
+ CD_CMD_GET_NODE = 0x01, /** @brief get node(s) */
+ CD_CMD_POST_LED = 0x02, /** @brief set led */
+ CD_CMD_POST_LINK = 0x03, /** @brief set/remove link */
+ CD_CMD_POST_NET = 0x04, /** @brief (un)register node with network */
+ CD_CMD_RESPONSE = 0x05, /** @brief response message */
+} cd_e_scmds;
+
+cd_cmd_handler cd_cmd_ping,
+ cd_cmd_get_node,
+ cd_cmd_post_led,
+ cd_cmd_post_link,
+ cd_cmd_post_net,
+ cd_cmd_response;
+
+/** @brief constant message sizes, 0 for dynamic size */
+static const size_t CD_CMD_HANDLERS_SIZE[CD_CMD_COUNT] = {
+ [CD_CMD_PING] = sizeof(cd_s_cmd_ping),
+ [CD_CMD_GET_NODE] = sizeof(cd_s_cmd_get_node),
+ [CD_CMD_POST_LED] = sizeof(cd_s_cmd_post_led),
+ [CD_CMD_POST_LINK] = sizeof(cd_s_cmd_post_link),
+ [CD_CMD_POST_NET] = sizeof(cd_s_cmd_post_net),
+ [CD_CMD_RESPONSE] = 0,
+};
+
+/** @brief constant message sizes, 0 for dynamic size */
+static size_t (* const CD_CMD_HANDLERS_SIZEOF[CD_CMD_COUNT])(cd_s_bin*) = {
+ [CD_CMD_PING] = NULL,
+ [CD_CMD_GET_NODE] = NULL,
+ [CD_CMD_POST_LED] = NULL,
+ [CD_CMD_POST_LINK] = NULL,
+ [CD_CMD_POST_NET] = NULL,
+ [CD_CMD_RESPONSE] = &cd_cmd_response_sizeof,
+};
+
+/** @brief stores message handlers in array with opcode as index */
+static cd_cmd_handler* const CD_CMD_HANDLERS[CD_CMD_COUNT] = {
+ [CD_CMD_PING] = &cd_cmd_ping,
+ [CD_CMD_GET_NODE] = &cd_cmd_get_node,
+ [CD_CMD_POST_LED] = &cd_cmd_post_led,
+ [CD_CMD_POST_LINK] = &cd_cmd_post_link,
+ [CD_CMD_POST_NET] = &cd_cmd_post_net,
+ [CD_CMD_RESPONSE] = &cd_cmd_response,
+};
+
+#ifdef __cplusplus
+}
+#endif