From 385b47211ea8674f97f014537d694bb2efbd6ab9 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 13 Oct 2022 15:59:14 +0200 Subject: WIP protocol implementation --- shared/bin.h | 12 ++++++++ shared/main | Bin 0 -> 21456 bytes shared/makefile | 24 +++++++++++++++ shared/protocol.c | 72 +++++++++++++++++++++++++++++++++++++++++++++ shared/protocol.h | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++ shared/protocol.md | 54 ++++++++++++++++++++++++++++++++++ shared/test.c | 36 +++++++++++++++++++++++ shared/testcmd | 1 + 8 files changed, 284 insertions(+) create mode 100644 shared/bin.h create mode 100755 shared/main create mode 100644 shared/makefile create mode 100644 shared/protocol.c create mode 100644 shared/protocol.h create mode 100644 shared/protocol.md create mode 100644 shared/test.c create mode 100644 shared/testcmd diff --git a/shared/bin.h b/shared/bin.h new file mode 100644 index 0000000..c7405be --- /dev/null +++ b/shared/bin.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +typedef struct { + uint16_t bytes; + uint8_t data[]; +} ws_s_bin; + +/** allocate new ws_s_bin struct and fill with `*data` for `bytes` bytes */ +ws_s_bin *ws_bin_s_alloc(uint16_t bytes, uint8_t *data); + diff --git a/shared/main b/shared/main new file mode 100755 index 0000000..7d7b7fe Binary files /dev/null and b/shared/main differ diff --git a/shared/makefile b/shared/makefile new file mode 100644 index 0000000..4d538da --- /dev/null +++ b/shared/makefile @@ -0,0 +1,24 @@ +CC = gcc +LD = gcc +RM = rm -f +CFLAGS = +LFLAGS = +TARGET = main + +SRCS := $(wildcard *.c) +OBJS := $(patsubst %.c,%.o, $(SRCS)) + +all: main + +%.o: %.c + $(CC) -c $(CFLAGS) $< -o $@ + +$(TARGET): $(OBJS) + $(LD) $^ $(LFLAGS) -o $@ + +clean: + $(RM) $(TARGET) $(OBJS) + +compile_commands: clean + compiledb make + diff --git a/shared/protocol.c b/shared/protocol.c new file mode 100644 index 0000000..85b320f --- /dev/null +++ b/shared/protocol.c @@ -0,0 +1,72 @@ +#include +#include + +#include "protocol.h" + +void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { + switch(input) { + case WS_PROTOCOL_C_NEWLINE: { + if (!state->valid) return; + break; + } + + case WS_PROTOCOL_C_SPACE: { + if (!state->valid) return; + printf("argument delimiter\n"); + return; + } + + case WS_PROTOCOL_C_NULL: { + state->valid = false; + return; + } + + default: { + if (!state->valid) return; + printf("recv byte 0x%02x, (\"%c\")\n", input, input); + state->cmd[state->cmd_len++] = input; + state->args_len[state->arg_len] += 1; + if (state->cmd_len == WS_PROTOCOL_CMD_BUFFER_LEN) state->valid = false; + return; + } + } + + printf("command done!\n"); +} + +void ws_protocol_parse_bytes(ws_s_protocol_parser_state* state, char* input, unsigned int length) { + for (unsigned int i = 0; i < length; i++) ws_protocol_parse_byte(state, input[i]); +} + +ws_s_protocol_parser_state* ws_protocol_parser_alloc() { + ws_s_protocol_parser_state* parser_state = malloc(sizeof(ws_s_protocol_parser_state) + sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); + parser_state->cmd = malloc(sizeof(char) * WS_PROTOCOL_CMD_BUFFER_LEN); + parser_state->valid = true; + parser_state->cmd_len = 0; + parser_state->arg_len = 0; + parser_state->target = NULL; + return parser_state; +} + +void ws_protocol_cmd_init(ws_s_protocol_parser_state* state) { + state->target = malloc(sizeof(ws_s_protocol_parsed_cmd) + sizeof(char*) * state->arg_len); + for (unsigned int i = 0; i < state->arg_len; i++) + state->target->argv[i] = malloc(sizeof(char) * state->args_len[i]); + state->target->argc = state->arg_len; +} + +void ws_protocol_parser_free(ws_s_protocol_parser_state* state) { + if (state == NULL) return; + if (state->target != NULL) ws_protocol_cmd_free(state->target); + free(state->cmd); + free(state); + state = NULL; + return; +} +void ws_protocol_cmd_free(ws_s_protocol_parsed_cmd* cmd) { + for (unsigned int i = 0; i < cmd->argc; i++) + free(cmd->argv[i]); + free(cmd); + cmd = NULL; + return; +} diff --git a/shared/protocol.h b/shared/protocol.h new file mode 100644 index 0000000..5cf7ac6 --- /dev/null +++ b/shared/protocol.h @@ -0,0 +1,85 @@ +#pragma once + +#include +#include + +#include "bin.h" + +#define WS_PROTOCOL_CMD_MAX_ARGUMENTS (1) +#define WS_PROTOCOL_CMD_BUFFER_LEN (40) + +#define WS_PROTOCOL_CMD_AMOUNT (1) + +#define WS_PROTOCOL_C_NEWLINE (0x0a) +#define WS_PROTOCOL_C_SPACE (0x20) +#define WS_PROTOCOL_C_NULL (0x00) + +typedef struct { + int argc; + char* argv[]; +} ws_s_protocol_parsed_cmd; + +typedef struct { + ws_s_protocol_parsed_cmd* target; + bool valid; + char* cmd; + uint16_t cmd_len; + uint16_t arg_len; + uint16_t args_len[]; +} ws_s_protocol_parser_state; + +//TODO: document +ws_s_protocol_parser_state* ws_protocol_parser_alloc(); +void ws_protocol_parser_free(ws_s_protocol_parser_state* state); +void ws_protocol_cmd_init(ws_s_protocol_parser_state* state); +void ws_protocol_cmd_free(ws_s_protocol_parsed_cmd* cmd); + +/** + * @brief parse incoming data byte by byte until a finished command is detected + * + * @remark [server] + * + * @param state parser state object, each incoming request should have it's own parser state + * @param input input byte + */ +void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input); +/** + * @brief parse incoming data chunk + * + * @remark [server] + * + * @param state parser state object, each incoming request should have it's own parser state + * @param input input byte array + * @param length input byte array length + */ +void ws_protocol_parse_bytes(ws_s_protocol_parser_state* state, char* input, unsigned int length); + +/** + * @brief create a `last-records` request command + * @remark [client] + * @return ws_s_bin containing the command string + */ +ws_s_bin* ws_protocol_req_last_records(unsigned int record_amount); + +/** + * @brief `last-records` response handler + * + * @remark [server] + * + * gets fired when the weather station receives a complete `last-records` + * command, and returns the response string + * + * @param parsed_cmd complete parsed command from ws_protocol_parse_* + * + * @return ws_s_bin containing response string + */ +ws_s_bin* ws_protocol_res_last_records(ws_s_protocol_parsed_cmd* parsed_cmd); + +typedef enum { + WS_PROTOCOL_CMD_LAST_RECORDS = 0, +} ws_e_protocol_cmd; + +static ws_s_bin* (*g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMOUNT])(ws_s_protocol_parsed_cmd* parsed_cmd) = { + [WS_PROTOCOL_CMD_LAST_RECORDS] = &ws_protocol_res_last_records +}; + diff --git a/shared/protocol.md b/shared/protocol.md new file mode 100644 index 0000000..bafec4d --- /dev/null +++ b/shared/protocol.md @@ -0,0 +1,54 @@ +# Protocol spec + +This is a brief overview of the protocol specifications that the weather +station uses to send and receive data between the weather station and qt +client. This protocol is text-based, and used over a TCP connection. This +document will only go into detail about the data sent over this connection, not +requirements about the connection itself. + +The protocol is only used in a request-response fashion, so all commands are +assumed to be sent by the qt client, and responded to by the weather station. + +Functions for generating commands and parsing incoming data are provided by the +protocol.c and protocol.h files. See [code +implementation](#code-implementation) section for more details about naming +conventions. + +- LF for newline instead of CRLF +- Commands are single-line +- Spaces used for separating command arguments +- Commands with malformed data are discarded and return error +- Response consist of `ok` or `error`, a comma, and the byte length of the + remaining response (if any) +- Numbers are sent as hexadecimal + +## Commands + +### `last-records ` + +Returns the last `n` records in csv format. The first line has the csv table +header, with the fields `id`, `temperature`, `humidity`, and +`atmospheric_pressure`. The rest of the response consists of 1 record per line. +When `n` is 0, or no records exist yet, the csv header is still returned, but +without any records. + +## Example transaction + +In the following example, newlines are indicated by `<0a>`, request by lines +starting with `<`, and response by lines starting with `>`. + +``` +< last-records 5<0a> +> ok,115<0a> +> id,temperature,humidity,atmospheric_pressure<0a> +> 10dc,2f,c5,7f<0a> +> 10dd,30,c6,7f<0a> +> 10de,31,c7,7f<0a> +> 10df,35,ca,7e<0a> +> 10e0,34,c9,7e<0a> +``` + +## Code implementation + + + diff --git a/shared/test.c b/shared/test.c new file mode 100644 index 0000000..788dc94 --- /dev/null +++ b/shared/test.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include + +#include "protocol.h" + +ws_s_bin* ws_protocol_res_last_records(ws_s_protocol_parsed_cmd* parsed_cmd) { + return NULL; +} + +int main() { + // disable echo and enable raw mode + fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); + struct termios term; + tcgetattr(STDIN_FILENO, &term); + term.c_lflag &= ~(ECHO | ICANON); + term.c_cc[VTIME] = 0; + term.c_cc[VMIN] = 1; + tcsetattr(STDIN_FILENO, 0, &term); + + ws_s_protocol_parser_state* parser1 = ws_protocol_parser_alloc(); + + for(;;) { + fflush(stdout); + + char byte; + while(read(STDIN_FILENO, &byte, 1) > 0) + ws_protocol_parse_byte(parser1, byte); + } + + ws_protocol_parser_free(parser1); + + return 0; +} diff --git a/shared/testcmd b/shared/testcmd new file mode 100644 index 0000000..17f8842 --- /dev/null +++ b/shared/testcmd @@ -0,0 +1 @@ +last-records 5 -- cgit v1.2.3 From 78f8f18e48d25547e837630d8317ef029bba6d72 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 13 Oct 2022 20:37:23 +0200 Subject: more protocol parsing done --- shared/bin.c | 11 ++++++++++ shared/bin.h | 5 +++-- shared/main | Bin 21456 -> 28568 bytes shared/makefile | 2 +- shared/protocol.c | 42 ++++++++++++++++++++++++++++++++---- shared/protocol.h | 63 ++++++++++++++++++++++++++++++++++++++++++++++-------- 6 files changed, 107 insertions(+), 16 deletions(-) create mode 100644 shared/bin.c diff --git a/shared/bin.c b/shared/bin.c new file mode 100644 index 0000000..def2aa8 --- /dev/null +++ b/shared/bin.c @@ -0,0 +1,11 @@ +#include +#include +#include + +#include "bin.h" + +ws_s_bin *ws_bin_s_alloc(uint16_t bytes) { + ws_s_bin *temp = malloc(sizeof(ws_s_bin) + sizeof(uint8_t) * bytes); + temp->bytes = bytes; + return temp; +} diff --git a/shared/bin.h b/shared/bin.h index c7405be..bfcda0c 100644 --- a/shared/bin.h +++ b/shared/bin.h @@ -2,11 +2,12 @@ #include +/** @brief binary data container with length */ typedef struct { uint16_t bytes; uint8_t data[]; } ws_s_bin; -/** allocate new ws_s_bin struct and fill with `*data` for `bytes` bytes */ -ws_s_bin *ws_bin_s_alloc(uint16_t bytes, uint8_t *data); +/** @brief allocate new ws_s_bin struct */ +ws_s_bin *ws_bin_s_alloc(uint16_t bytes); diff --git a/shared/main b/shared/main index 7d7b7fe..10b0d3c 100755 Binary files a/shared/main and b/shared/main differ diff --git a/shared/makefile b/shared/makefile index 4d538da..2ca254c 100644 --- a/shared/makefile +++ b/shared/makefile @@ -1,7 +1,7 @@ CC = gcc LD = gcc RM = rm -f -CFLAGS = +CFLAGS = -g LFLAGS = TARGET = main diff --git a/shared/protocol.c b/shared/protocol.c index 85b320f..49d1795 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -1,5 +1,6 @@ #include #include +#include #include "protocol.h" @@ -12,7 +13,7 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { case WS_PROTOCOL_C_SPACE: { if (!state->valid) return; - printf("argument delimiter\n"); + state->arg_len++; return; } @@ -23,15 +24,39 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { default: { if (!state->valid) return; - printf("recv byte 0x%02x, (\"%c\")\n", input, input); state->cmd[state->cmd_len++] = input; state->args_len[state->arg_len] += 1; if (state->cmd_len == WS_PROTOCOL_CMD_BUFFER_LEN) state->valid = false; return; } } + // arg_len is used as an index while parsing, so add 1 to get length + state->arg_len++; - printf("command done!\n"); + // parse cmd into argc and argv + ws_protocol_cmd_init(state); + // create response + ws_s_protocol_response* response = ws_protocol_parse_finished(state->target); + + //TODO: send response + + free(response->msg); + free(response); + + return; +} + +ws_s_protocol_response* ws_protocol_parse_finished(ws_s_protocol_parsed_cmd* parsed_cmd) { + ws_s_protocol_response* response = malloc(sizeof(ws_s_protocol_response)); + + if (strncmp("last-records", parsed_cmd->argv[0], 12) == 0) { + printf("last-records found!\n"); + } + + response->msg = ws_bin_s_alloc(50); + strncpy((char*) response->msg->data, "hello world!\n\0", 14); + + return response; } void ws_protocol_parse_bytes(ws_s_protocol_parser_state* state, char* input, unsigned int length) { @@ -51,8 +76,16 @@ ws_s_protocol_parser_state* ws_protocol_parser_alloc() { void ws_protocol_cmd_init(ws_s_protocol_parser_state* state) { state->target = malloc(sizeof(ws_s_protocol_parsed_cmd) + sizeof(char*) * state->arg_len); for (unsigned int i = 0; i < state->arg_len; i++) - state->target->argv[i] = malloc(sizeof(char) * state->args_len[i]); + state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); + state->target->argc = state->arg_len; + + unsigned int head = 0; + for (unsigned int i = 0; i < state->arg_len; i++) { + strncpy(state->target->argv[i], &state->cmd[head], state->args_len[i]); + state->target->argv[i][state->args_len[i]] = 0x00; // terminate argument with null byte + head += state->args_len[i]; + } } void ws_protocol_parser_free(ws_s_protocol_parser_state* state) { @@ -63,6 +96,7 @@ void ws_protocol_parser_free(ws_s_protocol_parser_state* state) { state = NULL; return; } + void ws_protocol_cmd_free(ws_s_protocol_parsed_cmd* cmd) { for (unsigned int i = 0; i < cmd->argc; i++) free(cmd->argv[i]); diff --git a/shared/protocol.h b/shared/protocol.h index 5cf7ac6..3082af4 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -14,24 +14,54 @@ #define WS_PROTOCOL_C_SPACE (0x20) #define WS_PROTOCOL_C_NULL (0x00) +/** + * @brief parsed cmd struct, holds arguments similar to argc and argv provided + * to `int main()` + */ typedef struct { - int argc; - char* argv[]; + int argc; /** argument count */ + char* argv[]; /** argument array, null terminated strings */ } ws_s_protocol_parsed_cmd; +/** + * @brief holds parser state variables for `ws_protocol_parse_byte` function. + * each incoming tcp request should get it's own parser 'instance' + */ typedef struct { - ws_s_protocol_parsed_cmd* target; - bool valid; - char* cmd; - uint16_t cmd_len; - uint16_t arg_len; - uint16_t args_len[]; + ws_s_protocol_parsed_cmd* target; /** parsed cmd reference */ + bool valid; /** command still valid flag */ + char* cmd; /** raw cmd */ + uint16_t cmd_len; /** raw cmd string length */ + uint16_t arg_len; /** amount of arguments */ + uint16_t args_len[]; /** array of argument lengths */ } ws_s_protocol_parser_state; -//TODO: document +/** @brief return values for command handlers */ +typedef enum { + WS_PROTOCOL_CMD_RETURN_OK = 0, + WS_PROTOCOL_CMD_RETURN_ERROR = 1, +} ws_e_protocol_cmd_return_value; + +/** @brief request response data struct */ +typedef struct { + ws_e_protocol_cmd_return_value success; + ws_s_bin* msg; +} ws_s_protocol_response; + +/** + * @brief allocate parser struct + * + * @return pointer to newly allocated struct + */ ws_s_protocol_parser_state* ws_protocol_parser_alloc(); +/** @brief deallocate parser struct, automatically frees all child pointers */ void ws_protocol_parser_free(ws_s_protocol_parser_state* state); +/** + * @brief initialize ws_s_protocol_parsed_cmd struct pointer of + * ws_s_protocol_parser_state (internal only) + */ void ws_protocol_cmd_init(ws_s_protocol_parser_state* state); +/** @brief deallocate ws_s_protocol_parsed_cmd struct pointer (internal only) */ void ws_protocol_cmd_free(ws_s_protocol_parsed_cmd* cmd); /** @@ -53,6 +83,21 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input); * @param length input byte array length */ void ws_protocol_parse_bytes(ws_s_protocol_parser_state* state, char* input, unsigned int length); +/** + * @brief handle complete command + * + * this function gets called when ws_protocol_parse_byte has detected a + * finished command. this function decides which command handler gets called, + * given that argv[0] contains a valid command. command argument parsing is + * handled by the command handler function. + * + * @remark [server] + * + * @return response + * + * @param parsed_cmd cmd parsed into ws_s_protocol_parsed_cmd struct + */ +ws_s_protocol_response* ws_protocol_parse_finished(ws_s_protocol_parsed_cmd* parsed_cmd); /** * @brief create a `last-records` request command -- cgit v1.2.3 From 0b05974d6462780030802a2991a9c929059b722a Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 14 Oct 2022 14:11:23 +0200 Subject: add printf macro util.h --- stm32f091/util.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 stm32f091/util.h diff --git a/stm32f091/util.h b/stm32f091/util.h new file mode 100644 index 0000000..8e3258f --- /dev/null +++ b/stm32f091/util.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include +#include + +#include "setup.h" + +#define ws_usb_printf(fmt, ...) { \ + char temp[255]; \ + sprintf(temp, fmt, ##__VA_ARGS__); \ + HAL_UART_Transmit(&huart2, (uint8_t*) temp, sizeof(char) * strlen(temp), HAL_MAX_DELAY); \ +} + -- cgit v1.2.3 From 137f62eb368101dd0371f0c54e1a4a2a7be48890 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 14 Oct 2022 15:57:47 +0200 Subject: remove executable from git --- .gitignore | 1 + shared/main | Bin 28568 -> 0 bytes 2 files changed, 1 insertion(+) delete mode 100755 shared/main diff --git a/.gitignore b/.gitignore index 1c68c8a..aba4463 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,6 @@ stm32f091/main.bin client/makefile client/client client/moc_* +shared/main .qmake.stash .vscode/.cortex-debug.registers.state.json diff --git a/shared/main b/shared/main deleted file mode 100755 index 10b0d3c..0000000 Binary files a/shared/main and /dev/null differ -- cgit v1.2.3 From f58ed35f0b73e933b6dd1f98472941c1d5d7ce9c Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 14 Oct 2022 16:21:21 +0200 Subject: request handler function executed --- shared/makefile | 2 +- shared/protocol.c | 26 +++++++++++++++++++++----- shared/protocol.h | 11 +++++++---- shared/test.c | 4 ++-- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/shared/makefile b/shared/makefile index 2ca254c..2093f00 100644 --- a/shared/makefile +++ b/shared/makefile @@ -1,7 +1,7 @@ CC = gcc LD = gcc RM = rm -f -CFLAGS = -g +CFLAGS = -g -std=c11 LFLAGS = TARGET = main diff --git a/shared/protocol.c b/shared/protocol.c index 49d1795..6e3bc73 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -46,16 +46,32 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { return; } +#define WS_CMD_MAP(parsed_cmd, name, code) \ + if (strlen(parsed_cmd->argv[0]) == strlen(name) && strncmp(parsed_cmd->argv[0], name, strlen(name)) == 0) return code; + +static ws_e_protocol_cmd ws_protocol_get_cmd_code(ws_s_protocol_parsed_cmd* parsed_cmd) { + WS_CMD_MAP(parsed_cmd, "last-records", WS_PROTOCOL_CMD_LAST_RECORDS); + + return WS_PROTOCOL_CMD_UNKNOWN; +} + ws_s_protocol_response* ws_protocol_parse_finished(ws_s_protocol_parsed_cmd* parsed_cmd) { ws_s_protocol_response* response = malloc(sizeof(ws_s_protocol_response)); + response->success = WS_PROTOCOL_CMD_RETURN_ERROR; + response->msg = NULL; - if (strncmp("last-records", parsed_cmd->argv[0], 12) == 0) { - printf("last-records found!\n"); - } + ws_e_protocol_cmd cmd_code = ws_protocol_get_cmd_code(parsed_cmd); + if (cmd_code == WS_PROTOCOL_CMD_UNKNOWN) goto ws_protocol_parse_exit; + if (cmd_code >= WS_PROTOCOL_CMD_AMOUNT) goto ws_protocol_parse_exit; + + void (*ws_protocol_res_handler)(ws_s_protocol_parsed_cmd*, ws_s_protocol_response*) = + g_ws_protocol_res_handlers[cmd_code]; + if (ws_protocol_res_handler == NULL) goto ws_protocol_parse_exit; + (*ws_protocol_res_handler)(parsed_cmd, response); - response->msg = ws_bin_s_alloc(50); - strncpy((char*) response->msg->data, "hello world!\n\0", 14); +ws_protocol_parse_exit: + if (response->msg == NULL) response->msg = ws_bin_s_alloc(0); return response; } diff --git a/shared/protocol.h b/shared/protocol.h index 3082af4..a19fe48 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -115,16 +115,19 @@ ws_s_bin* ws_protocol_req_last_records(unsigned int record_amount); * command, and returns the response string * * @param parsed_cmd complete parsed command from ws_protocol_parse_* - * - * @return ws_s_bin containing response string + * @param response response struct with uninitialized pointer to msg */ -ws_s_bin* ws_protocol_res_last_records(ws_s_protocol_parsed_cmd* parsed_cmd); +void ws_protocol_res_last_records(ws_s_protocol_parsed_cmd* parsed_cmd, ws_s_protocol_response* response); +/** @brief cmd codes (used to call handlers) */ typedef enum { + WS_PROTOCOL_CMD_UNKNOWN = -1, + WS_PROTOCOL_CMD_LAST_RECORDS = 0, } ws_e_protocol_cmd; -static ws_s_bin* (*g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMOUNT])(ws_s_protocol_parsed_cmd* parsed_cmd) = { +/** @brief response handlers, called when a command is parsed */ +static void (*g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMOUNT])(ws_s_protocol_parsed_cmd*, ws_s_protocol_response*) = { [WS_PROTOCOL_CMD_LAST_RECORDS] = &ws_protocol_res_last_records }; diff --git a/shared/test.c b/shared/test.c index 788dc94..5f2cd60 100644 --- a/shared/test.c +++ b/shared/test.c @@ -6,8 +6,8 @@ #include "protocol.h" -ws_s_bin* ws_protocol_res_last_records(ws_s_protocol_parsed_cmd* parsed_cmd) { - return NULL; +void ws_protocol_res_last_records(ws_s_protocol_parsed_cmd* parsed_cmd, ws_s_protocol_response* response) { + printf("last-records detected!\n"); } int main() { -- cgit v1.2.3 From ec475b0469104a0a76542c52286ed08933ac750c Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 14 Oct 2022 16:47:12 +0200 Subject: more protocol stuff working --- shared/protocol.c | 9 +++++++++ shared/protocol.h | 9 +++++++++ shared/test.c | 16 +++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/shared/protocol.c b/shared/protocol.c index 6e3bc73..bcb764e 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -39,10 +39,19 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { ws_s_protocol_response* response = ws_protocol_parse_finished(state->target); //TODO: send response + char response_first_line[16]; + sprintf(response_first_line, "%s,%x\n", response->success == WS_PROTOCOL_CMD_RETURN_OK ? "ok" : "error", response->msg->bytes); + ws_s_bin* response_first_line_bin = ws_bin_s_alloc(strlen(response_first_line)); + strncpy((char*) response_first_line_bin->data, response_first_line, strlen(response_first_line)); + ws_protocol_send_data(response_first_line_bin); + ws_protocol_send_data(response->msg); + free(response_first_line_bin); free(response->msg); free(response); + //TODO: reset command in parser_state for next command + return; } diff --git a/shared/protocol.h b/shared/protocol.h index a19fe48..74b289c 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -119,6 +119,15 @@ ws_s_bin* ws_protocol_req_last_records(unsigned int record_amount); */ void ws_protocol_res_last_records(ws_s_protocol_parsed_cmd* parsed_cmd, ws_s_protocol_response* response); +/** + * @brief data sender wrapper + * + * this function should be implemented in the source files of each target + * platform, as the send interface will be different on desktop and on the + * stm32. + */ +void ws_protocol_send_data(ws_s_bin* data); + /** @brief cmd codes (used to call handlers) */ typedef enum { WS_PROTOCOL_CMD_UNKNOWN = -1, diff --git a/shared/test.c b/shared/test.c index 5f2cd60..2c3c3a3 100644 --- a/shared/test.c +++ b/shared/test.c @@ -3,11 +3,25 @@ #include #include #include +#include #include "protocol.h" void ws_protocol_res_last_records(ws_s_protocol_parsed_cmd* parsed_cmd, ws_s_protocol_response* response) { - printf("last-records detected!\n"); + const char* response_text = "" + "id,temperature,humidity,atmospheric_pressure\n" + "10dc,2f,c5,7f\n" + "10dd,30,c6,7f\n" + "10de,31,c7,7f\n" + "10df,35,ca,7e\n" + "10e0,34,c9,7e\n"; + response->success = WS_PROTOCOL_CMD_RETURN_OK; + response->msg = ws_bin_s_alloc(strlen(response_text)); + strncpy((char*) response->msg->data, response_text, strlen(response_text)); +} + +void ws_protocol_send_data(ws_s_bin* data) { + printf("%.*s", data->bytes, data->data); } int main() { -- cgit v1.2.3 From a8ec533f4e548601e283cee628aaf5ffc1e7d662 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 14 Oct 2022 17:06:02 +0200 Subject: parser done --- shared/protocol.c | 27 +++++++++++++++++---------- shared/protocol.h | 2 ++ shared/test.c | 1 + 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/shared/protocol.c b/shared/protocol.c index bcb764e..377e79e 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -7,7 +7,6 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { switch(input) { case WS_PROTOCOL_C_NEWLINE: { - if (!state->valid) return; break; } @@ -34,11 +33,11 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { state->arg_len++; // parse cmd into argc and argv - ws_protocol_cmd_init(state); + if (state->valid) ws_protocol_cmd_init(state); // create response ws_s_protocol_response* response = ws_protocol_parse_finished(state->target); - //TODO: send response + // send response char response_first_line[16]; sprintf(response_first_line, "%s,%x\n", response->success == WS_PROTOCOL_CMD_RETURN_OK ? "ok" : "error", response->msg->bytes); ws_s_bin* response_first_line_bin = ws_bin_s_alloc(strlen(response_first_line)); @@ -46,11 +45,13 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { ws_protocol_send_data(response_first_line_bin); ws_protocol_send_data(response->msg); + // free response data containers free(response_first_line_bin); free(response->msg); free(response); - //TODO: reset command in parser_state for next command + // reset parser + ws_protocol_parser_reset(state); return; } @@ -59,6 +60,7 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { if (strlen(parsed_cmd->argv[0]) == strlen(name) && strncmp(parsed_cmd->argv[0], name, strlen(name)) == 0) return code; static ws_e_protocol_cmd ws_protocol_get_cmd_code(ws_s_protocol_parsed_cmd* parsed_cmd) { + if (parsed_cmd == NULL) return WS_PROTOCOL_CMD_UNKNOWN; // invalid command WS_CMD_MAP(parsed_cmd, "last-records", WS_PROTOCOL_CMD_LAST_RECORDS); return WS_PROTOCOL_CMD_UNKNOWN; @@ -91,10 +93,7 @@ void ws_protocol_parse_bytes(ws_s_protocol_parser_state* state, char* input, uns ws_s_protocol_parser_state* ws_protocol_parser_alloc() { ws_s_protocol_parser_state* parser_state = malloc(sizeof(ws_s_protocol_parser_state) + sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); parser_state->cmd = malloc(sizeof(char) * WS_PROTOCOL_CMD_BUFFER_LEN); - parser_state->valid = true; - parser_state->cmd_len = 0; - parser_state->arg_len = 0; - parser_state->target = NULL; + ws_protocol_parser_reset(parser_state); return parser_state; } @@ -116,16 +115,24 @@ void ws_protocol_cmd_init(ws_s_protocol_parser_state* state) { void ws_protocol_parser_free(ws_s_protocol_parser_state* state) { if (state == NULL) return; if (state->target != NULL) ws_protocol_cmd_free(state->target); + state->target = NULL; free(state->cmd); free(state); - state = NULL; return; } +void ws_protocol_parser_reset(ws_s_protocol_parser_state* state) { + if (state->target != NULL) ws_protocol_cmd_free(state->target); + state->target = NULL; + state->valid = true; + state->cmd_len = 0; + state->arg_len = 0; + memset(state->args_len, 0, sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); +} + void ws_protocol_cmd_free(ws_s_protocol_parsed_cmd* cmd) { for (unsigned int i = 0; i < cmd->argc; i++) free(cmd->argv[i]); free(cmd); - cmd = NULL; return; } diff --git a/shared/protocol.h b/shared/protocol.h index 74b289c..b7b92bb 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -56,6 +56,8 @@ typedef struct { ws_s_protocol_parser_state* ws_protocol_parser_alloc(); /** @brief deallocate parser struct, automatically frees all child pointers */ void ws_protocol_parser_free(ws_s_protocol_parser_state* state); +/** @brief reset parser state to parse a new request */ +void ws_protocol_parser_reset(ws_s_protocol_parser_state* state); /** * @brief initialize ws_s_protocol_parsed_cmd struct pointer of * ws_s_protocol_parser_state (internal only) diff --git a/shared/test.c b/shared/test.c index 2c3c3a3..588cd16 100644 --- a/shared/test.c +++ b/shared/test.c @@ -45,6 +45,7 @@ int main() { } ws_protocol_parser_free(parser1); + parser1 = NULL; return 0; } -- cgit v1.2.3 From 42bf616eac96eba1846c64123a4b3822061b418c Mon Sep 17 00:00:00 2001 From: lonkaars Date: Mon, 17 Oct 2022 12:11:37 +0200 Subject: update naming scheme in protocol.{c,h} --- shared/protocol.c | 44 +++++++++++++++++++++--------------------- shared/protocol.h | 57 +++++++++++++++++++++++-------------------------------- shared/test.c | 16 +++++++--------- 3 files changed, 53 insertions(+), 64 deletions(-) diff --git a/shared/protocol.c b/shared/protocol.c index 377e79e..6795197 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -4,9 +4,9 @@ #include "protocol.h" -void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { +void ws_protocol_parse_req_byte(ws_s_protocol_req_parser_state* state, char input) { switch(input) { - case WS_PROTOCOL_C_NEWLINE: { + case WS_PROTOCOL_C_EOL: { break; } @@ -33,9 +33,9 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { state->arg_len++; // parse cmd into argc and argv - if (state->valid) ws_protocol_cmd_init(state); + if (state->valid) ws_protocol_req_cmd_init(state); // create response - ws_s_protocol_response* response = ws_protocol_parse_finished(state->target); + ws_s_protocol_res* response = ws_protocol_parse_req_finished(state->target); // send response char response_first_line[16]; @@ -51,7 +51,7 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { free(response); // reset parser - ws_protocol_parser_reset(state); + ws_protocol_req_parser_reset(state); return; } @@ -59,23 +59,23 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) { #define WS_CMD_MAP(parsed_cmd, name, code) \ if (strlen(parsed_cmd->argv[0]) == strlen(name) && strncmp(parsed_cmd->argv[0], name, strlen(name)) == 0) return code; -static ws_e_protocol_cmd ws_protocol_get_cmd_code(ws_s_protocol_parsed_cmd* parsed_cmd) { +static ws_e_protocol_cmd ws_protocol_get_req_cmd_code(ws_s_protocol_parsed_req_cmd* parsed_cmd) { if (parsed_cmd == NULL) return WS_PROTOCOL_CMD_UNKNOWN; // invalid command WS_CMD_MAP(parsed_cmd, "last-records", WS_PROTOCOL_CMD_LAST_RECORDS); return WS_PROTOCOL_CMD_UNKNOWN; } -ws_s_protocol_response* ws_protocol_parse_finished(ws_s_protocol_parsed_cmd* parsed_cmd) { - ws_s_protocol_response* response = malloc(sizeof(ws_s_protocol_response)); +ws_s_protocol_res* ws_protocol_parse_req_finished(ws_s_protocol_parsed_req_cmd* parsed_cmd) { + ws_s_protocol_res* response = malloc(sizeof(ws_s_protocol_res)); response->success = WS_PROTOCOL_CMD_RETURN_ERROR; response->msg = NULL; - ws_e_protocol_cmd cmd_code = ws_protocol_get_cmd_code(parsed_cmd); + ws_e_protocol_cmd cmd_code = ws_protocol_get_req_cmd_code(parsed_cmd); if (cmd_code == WS_PROTOCOL_CMD_UNKNOWN) goto ws_protocol_parse_exit; if (cmd_code >= WS_PROTOCOL_CMD_AMOUNT) goto ws_protocol_parse_exit; - void (*ws_protocol_res_handler)(ws_s_protocol_parsed_cmd*, ws_s_protocol_response*) = + void (*ws_protocol_res_handler)(ws_s_protocol_parsed_req_cmd*, ws_s_protocol_res*) = g_ws_protocol_res_handlers[cmd_code]; if (ws_protocol_res_handler == NULL) goto ws_protocol_parse_exit; (*ws_protocol_res_handler)(parsed_cmd, response); @@ -86,19 +86,19 @@ ws_protocol_parse_exit: return response; } -void ws_protocol_parse_bytes(ws_s_protocol_parser_state* state, char* input, unsigned int length) { - for (unsigned int i = 0; i < length; i++) ws_protocol_parse_byte(state, input[i]); +void ws_protocol_parse_req_bytes(ws_s_protocol_req_parser_state* state, char* input, unsigned int length) { + for (unsigned int i = 0; i < length; i++) ws_protocol_parse_req_byte(state, input[i]); } -ws_s_protocol_parser_state* ws_protocol_parser_alloc() { - ws_s_protocol_parser_state* parser_state = malloc(sizeof(ws_s_protocol_parser_state) + sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); +ws_s_protocol_req_parser_state* ws_protocol_req_parser_alloc() { + ws_s_protocol_req_parser_state* parser_state = malloc(sizeof(ws_s_protocol_req_parser_state) + sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); parser_state->cmd = malloc(sizeof(char) * WS_PROTOCOL_CMD_BUFFER_LEN); - ws_protocol_parser_reset(parser_state); + ws_protocol_req_parser_reset(parser_state); return parser_state; } -void ws_protocol_cmd_init(ws_s_protocol_parser_state* state) { - state->target = malloc(sizeof(ws_s_protocol_parsed_cmd) + sizeof(char*) * state->arg_len); +void ws_protocol_req_cmd_init(ws_s_protocol_req_parser_state* state) { + state->target = malloc(sizeof(ws_s_protocol_parsed_req_cmd) + sizeof(char*) * state->arg_len); for (unsigned int i = 0; i < state->arg_len; i++) state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); @@ -112,17 +112,17 @@ void ws_protocol_cmd_init(ws_s_protocol_parser_state* state) { } } -void ws_protocol_parser_free(ws_s_protocol_parser_state* state) { +void ws_protocol_req_parser_free(ws_s_protocol_req_parser_state* state) { if (state == NULL) return; - if (state->target != NULL) ws_protocol_cmd_free(state->target); + if (state->target != NULL) ws_protocol_req_cmd_free(state->target); state->target = NULL; free(state->cmd); free(state); return; } -void ws_protocol_parser_reset(ws_s_protocol_parser_state* state) { - if (state->target != NULL) ws_protocol_cmd_free(state->target); +void ws_protocol_req_parser_reset(ws_s_protocol_req_parser_state* state) { + if (state->target != NULL) ws_protocol_req_cmd_free(state->target); state->target = NULL; state->valid = true; state->cmd_len = 0; @@ -130,7 +130,7 @@ void ws_protocol_parser_reset(ws_s_protocol_parser_state* state) { memset(state->args_len, 0, sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); } -void ws_protocol_cmd_free(ws_s_protocol_parsed_cmd* cmd) { +void ws_protocol_req_cmd_free(ws_s_protocol_parsed_req_cmd* cmd) { for (unsigned int i = 0; i < cmd->argc; i++) free(cmd->argv[i]); free(cmd); diff --git a/shared/protocol.h b/shared/protocol.h index b7b92bb..9f17e8d 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -10,31 +10,31 @@ #define WS_PROTOCOL_CMD_AMOUNT (1) -#define WS_PROTOCOL_C_NEWLINE (0x0a) +#define WS_PROTOCOL_C_EOL (0x0a) #define WS_PROTOCOL_C_SPACE (0x20) #define WS_PROTOCOL_C_NULL (0x00) /** - * @brief parsed cmd struct, holds arguments similar to argc and argv provided - * to `int main()` + * @brief parsed request cmd struct, holds arguments similar to argc and argv + * provided to `int main()` */ typedef struct { int argc; /** argument count */ char* argv[]; /** argument array, null terminated strings */ -} ws_s_protocol_parsed_cmd; +} ws_s_protocol_parsed_req_cmd; /** - * @brief holds parser state variables for `ws_protocol_parse_byte` function. + * @brief holds parser state variables for `ws_protocol_parse_req_byte` function. * each incoming tcp request should get it's own parser 'instance' */ typedef struct { - ws_s_protocol_parsed_cmd* target; /** parsed cmd reference */ + ws_s_protocol_parsed_req_cmd* target; /** parsed cmd reference */ bool valid; /** command still valid flag */ char* cmd; /** raw cmd */ uint16_t cmd_len; /** raw cmd string length */ uint16_t arg_len; /** amount of arguments */ uint16_t args_len[]; /** array of argument lengths */ -} ws_s_protocol_parser_state; +} ws_s_protocol_req_parser_state; /** @brief return values for command handlers */ typedef enum { @@ -46,64 +46,57 @@ typedef enum { typedef struct { ws_e_protocol_cmd_return_value success; ws_s_bin* msg; -} ws_s_protocol_response; +} ws_s_protocol_res; /** * @brief allocate parser struct * * @return pointer to newly allocated struct */ -ws_s_protocol_parser_state* ws_protocol_parser_alloc(); +ws_s_protocol_req_parser_state* ws_protocol_req_parser_alloc(); /** @brief deallocate parser struct, automatically frees all child pointers */ -void ws_protocol_parser_free(ws_s_protocol_parser_state* state); +void ws_protocol_req_parser_free(ws_s_protocol_req_parser_state* state); /** @brief reset parser state to parse a new request */ -void ws_protocol_parser_reset(ws_s_protocol_parser_state* state); +void ws_protocol_req_parser_reset(ws_s_protocol_req_parser_state* state); /** - * @brief initialize ws_s_protocol_parsed_cmd struct pointer of - * ws_s_protocol_parser_state (internal only) + * @brief initialize ws_s_protocol_parsed_req_cmd struct pointer of + * ws_s_protocol_req_parser_state (internal only) */ -void ws_protocol_cmd_init(ws_s_protocol_parser_state* state); -/** @brief deallocate ws_s_protocol_parsed_cmd struct pointer (internal only) */ -void ws_protocol_cmd_free(ws_s_protocol_parsed_cmd* cmd); +void ws_protocol_req_cmd_init(ws_s_protocol_req_parser_state* state); +/** @brief deallocate ws_s_protocol_parsed_req_cmd struct pointer (internal only) */ +void ws_protocol_req_cmd_free(ws_s_protocol_parsed_req_cmd* cmd); /** * @brief parse incoming data byte by byte until a finished command is detected * - * @remark [server] - * * @param state parser state object, each incoming request should have it's own parser state * @param input input byte */ -void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input); +void ws_protocol_parse_req_byte(ws_s_protocol_req_parser_state* state, char input); /** * @brief parse incoming data chunk * - * @remark [server] - * * @param state parser state object, each incoming request should have it's own parser state * @param input input byte array * @param length input byte array length */ -void ws_protocol_parse_bytes(ws_s_protocol_parser_state* state, char* input, unsigned int length); +void ws_protocol_parse_req_bytes(ws_s_protocol_req_parser_state* state, char* input, unsigned int length); /** * @brief handle complete command * - * this function gets called when ws_protocol_parse_byte has detected a + * this function gets called when ws_protocol_parse_req_byte(s) has detected a * finished command. this function decides which command handler gets called, * given that argv[0] contains a valid command. command argument parsing is * handled by the command handler function. * - * @remark [server] - * * @return response * - * @param parsed_cmd cmd parsed into ws_s_protocol_parsed_cmd struct + * @param parsed_cmd cmd parsed into ws_s_protocol_parsed_req_cmd struct */ -ws_s_protocol_response* ws_protocol_parse_finished(ws_s_protocol_parsed_cmd* parsed_cmd); +ws_s_protocol_res* ws_protocol_parse_req_finished(ws_s_protocol_parsed_req_cmd* parsed_cmd); /** * @brief create a `last-records` request command - * @remark [client] * @return ws_s_bin containing the command string */ ws_s_bin* ws_protocol_req_last_records(unsigned int record_amount); @@ -111,15 +104,13 @@ ws_s_bin* ws_protocol_req_last_records(unsigned int record_amount); /** * @brief `last-records` response handler * - * @remark [server] - * * gets fired when the weather station receives a complete `last-records` * command, and returns the response string * - * @param parsed_cmd complete parsed command from ws_protocol_parse_* + * @param parsed_cmd complete parsed command from ws_protocol_parse_req_* * @param response response struct with uninitialized pointer to msg */ -void ws_protocol_res_last_records(ws_s_protocol_parsed_cmd* parsed_cmd, ws_s_protocol_response* response); +void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response); /** * @brief data sender wrapper @@ -138,7 +129,7 @@ typedef enum { } ws_e_protocol_cmd; /** @brief response handlers, called when a command is parsed */ -static void (*g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMOUNT])(ws_s_protocol_parsed_cmd*, ws_s_protocol_response*) = { +static void (*g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMOUNT])(ws_s_protocol_parsed_req_cmd*, ws_s_protocol_res*) = { [WS_PROTOCOL_CMD_LAST_RECORDS] = &ws_protocol_res_last_records }; diff --git a/shared/test.c b/shared/test.c index 588cd16..f9d4bbc 100644 --- a/shared/test.c +++ b/shared/test.c @@ -7,7 +7,7 @@ #include "protocol.h" -void ws_protocol_res_last_records(ws_s_protocol_parsed_cmd* parsed_cmd, ws_s_protocol_response* response) { +void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response) { const char* response_text = "" "id,temperature,humidity,atmospheric_pressure\n" "10dc,2f,c5,7f\n" @@ -34,17 +34,15 @@ int main() { term.c_cc[VMIN] = 1; tcsetattr(STDIN_FILENO, 0, &term); - ws_s_protocol_parser_state* parser1 = ws_protocol_parser_alloc(); + ws_s_protocol_req_parser_state* parser1 = ws_protocol_req_parser_alloc(); - for(;;) { - fflush(stdout); + fflush(stdout); - char byte; - while(read(STDIN_FILENO, &byte, 1) > 0) - ws_protocol_parse_byte(parser1, byte); - } + char byte; + while(read(STDIN_FILENO, &byte, 1) > 0) + ws_protocol_parse_req_byte(parser1, byte); - ws_protocol_parser_free(parser1); + ws_protocol_req_parser_free(parser1); parser1 = NULL; return 0; -- cgit v1.2.3 From e555b5b5e0ad94279ef62d16feacee4976e2970d Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 19 Oct 2022 16:38:11 +0200 Subject: custom response data send handlers implemented --- shared/protocol.c | 35 ++++++++++++++++++----------------- shared/protocol.h | 42 +++++++++++++++++++++++++++--------------- shared/test.c | 17 +++++++++++++---- 3 files changed, 58 insertions(+), 36 deletions(-) diff --git a/shared/protocol.c b/shared/protocol.c index 6795197..225b46f 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -4,6 +4,16 @@ #include "protocol.h" +#define WS_CMD_MAP(parsed_cmd, name, code) \ + if (strlen(parsed_cmd->argv[0]) == strlen(name) && strncmp(parsed_cmd->argv[0], name, strlen(name)) == 0) return code; + +static ws_e_protocol_cmd ws_protocol_get_req_cmd_code(ws_s_protocol_parsed_req_cmd* parsed_cmd) { + if (parsed_cmd == NULL) return WS_PROTOCOL_CMD_UNKNOWN; // invalid command + WS_CMD_MAP(parsed_cmd, "last-records", WS_PROTOCOL_CMD_LAST_RECORDS); + + return WS_PROTOCOL_CMD_UNKNOWN; +} + void ws_protocol_parse_req_byte(ws_s_protocol_req_parser_state* state, char input) { switch(input) { case WS_PROTOCOL_C_EOL: { @@ -43,7 +53,8 @@ void ws_protocol_parse_req_byte(ws_s_protocol_req_parser_state* state, char inpu ws_s_bin* response_first_line_bin = ws_bin_s_alloc(strlen(response_first_line)); strncpy((char*) response_first_line_bin->data, response_first_line, strlen(response_first_line)); ws_protocol_send_data(response_first_line_bin); - ws_protocol_send_data(response->msg); + if (!response->csh) ws_protocol_send_data(response->msg); + else (*g_ws_protocol_res_handlers[response->cmd_code])(state->target, response, true); // free response data containers free(response_first_line_bin); @@ -56,29 +67,19 @@ void ws_protocol_parse_req_byte(ws_s_protocol_req_parser_state* state, char inpu return; } -#define WS_CMD_MAP(parsed_cmd, name, code) \ - if (strlen(parsed_cmd->argv[0]) == strlen(name) && strncmp(parsed_cmd->argv[0], name, strlen(name)) == 0) return code; - -static ws_e_protocol_cmd ws_protocol_get_req_cmd_code(ws_s_protocol_parsed_req_cmd* parsed_cmd) { - if (parsed_cmd == NULL) return WS_PROTOCOL_CMD_UNKNOWN; // invalid command - WS_CMD_MAP(parsed_cmd, "last-records", WS_PROTOCOL_CMD_LAST_RECORDS); - - return WS_PROTOCOL_CMD_UNKNOWN; -} - ws_s_protocol_res* ws_protocol_parse_req_finished(ws_s_protocol_parsed_req_cmd* parsed_cmd) { ws_s_protocol_res* response = malloc(sizeof(ws_s_protocol_res)); response->success = WS_PROTOCOL_CMD_RETURN_ERROR; + response->csh = false; response->msg = NULL; + response->cmd_code = ws_protocol_get_req_cmd_code(parsed_cmd); - ws_e_protocol_cmd cmd_code = ws_protocol_get_req_cmd_code(parsed_cmd); - if (cmd_code == WS_PROTOCOL_CMD_UNKNOWN) goto ws_protocol_parse_exit; - if (cmd_code >= WS_PROTOCOL_CMD_AMOUNT) goto ws_protocol_parse_exit; + if (response->cmd_code == WS_PROTOCOL_CMD_UNKNOWN) goto ws_protocol_parse_exit; + if (response->cmd_code >= WS_PROTOCOL_CMD_AMOUNT) goto ws_protocol_parse_exit; - void (*ws_protocol_res_handler)(ws_s_protocol_parsed_req_cmd*, ws_s_protocol_res*) = - g_ws_protocol_res_handlers[cmd_code]; + ws_protocol_res_handler_t* ws_protocol_res_handler = g_ws_protocol_res_handlers[response->cmd_code]; if (ws_protocol_res_handler == NULL) goto ws_protocol_parse_exit; - (*ws_protocol_res_handler)(parsed_cmd, response); + (*ws_protocol_res_handler)(parsed_cmd, response, false); ws_protocol_parse_exit: diff --git a/shared/protocol.h b/shared/protocol.h index 9f17e8d..c31ebc6 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -42,10 +42,22 @@ typedef enum { WS_PROTOCOL_CMD_RETURN_ERROR = 1, } ws_e_protocol_cmd_return_value; +/** @brief cmd codes (used to call handlers) */ +typedef enum { + WS_PROTOCOL_CMD_UNKNOWN = -1, + + WS_PROTOCOL_CMD_LAST_RECORDS = 0, +} ws_e_protocol_cmd; + /** @brief request response data struct */ typedef struct { - ws_e_protocol_cmd_return_value success; - ws_s_bin* msg; + ws_e_protocol_cmd_return_value success; /** status code for response + validity, defaults to + WS_PROTOCOL_CMD_RETURN_ERROR */ + bool csh; /** whether the response handler has logic for a custom send + handler, false by default */ + ws_s_bin* msg; /** pointer to response data, uninitialized by default */ + ws_e_protocol_cmd cmd_code; /** cmd code */ } ws_s_protocol_res; /** @@ -102,15 +114,22 @@ ws_s_protocol_res* ws_protocol_parse_req_finished(ws_s_protocol_parsed_req_cmd* ws_s_bin* ws_protocol_req_last_records(unsigned int record_amount); /** - * @brief `last-records` response handler + * @brief response handler * - * gets fired when the weather station receives a complete `last-records` - * command, and returns the response string + * gets fired when the weather station receives a complete command, and returns + * a response struct with a success code and an optional message. if + * response->csh is set to `true` within the handler, it gets fired a second + * time after the response header is sent, but with the `send` parameter set to + * `true`. this is so response handlers can send large amounts of data without + * allocating large areas of memory. * * @param parsed_cmd complete parsed command from ws_protocol_parse_req_* * @param response response struct with uninitialized pointer to msg + * @param send `false` on first run, `true` on second run if `response->csh` was set to true */ -void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response); +typedef void ws_protocol_res_handler_t(ws_s_protocol_parsed_req_cmd*, ws_s_protocol_res*, bool); + +ws_protocol_res_handler_t ws_protocol_res_last_records; /** * @brief data sender wrapper @@ -121,15 +140,8 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s */ void ws_protocol_send_data(ws_s_bin* data); -/** @brief cmd codes (used to call handlers) */ -typedef enum { - WS_PROTOCOL_CMD_UNKNOWN = -1, - - WS_PROTOCOL_CMD_LAST_RECORDS = 0, -} ws_e_protocol_cmd; - /** @brief response handlers, called when a command is parsed */ -static void (*g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMOUNT])(ws_s_protocol_parsed_req_cmd*, ws_s_protocol_res*) = { - [WS_PROTOCOL_CMD_LAST_RECORDS] = &ws_protocol_res_last_records +static ws_protocol_res_handler_t* g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMOUNT] = { + [WS_PROTOCOL_CMD_LAST_RECORDS] = &ws_protocol_res_last_records, }; diff --git a/shared/test.c b/shared/test.c index f9d4bbc..0968252 100644 --- a/shared/test.c +++ b/shared/test.c @@ -7,7 +7,7 @@ #include "protocol.h" -void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response) { +void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response, bool send) { const char* response_text = "" "id,temperature,humidity,atmospheric_pressure\n" "10dc,2f,c5,7f\n" @@ -15,9 +15,18 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s "10de,31,c7,7f\n" "10df,35,ca,7e\n" "10e0,34,c9,7e\n"; - response->success = WS_PROTOCOL_CMD_RETURN_OK; - response->msg = ws_bin_s_alloc(strlen(response_text)); - strncpy((char*) response->msg->data, response_text, strlen(response_text)); + + if (!send) { + response->success = WS_PROTOCOL_CMD_RETURN_OK; + response->csh = true; + response->msg = ws_bin_s_alloc(0); + response->msg->bytes = strlen(response_text); + } else { + // example send routine + ws_s_bin* response_test = ws_bin_s_alloc(strlen(response_text)); + strncpy((char*) response_test->data, response_text, strlen(response_text)); + ws_protocol_send_data(response_test); + } } void ws_protocol_send_data(ws_s_bin* data) { -- cgit v1.2.3 From 89b8217435286081dc0fe481559da3ee5c20c72a Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 19 Oct 2022 18:15:36 +0200 Subject: last-records response handler implemented --- shared/backlog.c | 47 ++++++++++++++++++++++++++++++++++++++++++ shared/backlog.h | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ shared/protocol.c | 7 ++----- shared/protocol.h | 5 ++++- shared/test.c | 50 +++++++++++++++++++++++++++++++++------------ shared/util.h | 4 ++++ stm32f091/backlog.c | 41 ++++++++++++++++++++++++------------- stm32f091/backlog.h | 4 +++- 8 files changed, 183 insertions(+), 34 deletions(-) create mode 100644 shared/backlog.c create mode 100644 shared/backlog.h create mode 100644 shared/util.h diff --git a/shared/backlog.c b/shared/backlog.c new file mode 100644 index 0000000..926ccad --- /dev/null +++ b/shared/backlog.c @@ -0,0 +1,47 @@ +#include + +#include "backlog.h" + +ws_s_backlog_database* g_ws_backlog_database = NULL; + +void ws_backlog_alloc(uint16_t record_amt) { + g_ws_backlog_database = malloc(sizeof(ws_s_backlog_database) + sizeof(ws_s_backlog_record) * record_amt); + g_ws_backlog_database->buffer_size = record_amt; + g_ws_backlog_database->buffer_start = 0; + g_ws_backlog_database->buffer_end = 0; +} + +void ws_backlog_add_record(ws_s_backlog_record record) { + static uint16_t id = 0; + + g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].id = id++; + g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_atm_pressure = record.sens_atm_pressure; + g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_humidity = record.sens_humidity; + g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_temperature = record.sens_temperature; + + // shift buffer start/end + g_ws_backlog_database->buffer_end = (g_ws_backlog_database->buffer_end + 1) % g_ws_backlog_database->buffer_size; + if (g_ws_backlog_database->buffer_end == g_ws_backlog_database->buffer_start) + g_ws_backlog_database->buffer_start = (g_ws_backlog_database->buffer_start + 1) % g_ws_backlog_database->buffer_size; +} + +ws_s_backlog_record* ws_backlog_get_record(uint16_t record_index) { + return &g_ws_backlog_database->records[record_index]; +} + +ws_s_backlog_record* ws_backlog_get_last_record(uint16_t record_offset) { + return ws_backlog_get_record((g_ws_backlog_database->buffer_end - record_offset - 1) % g_ws_backlog_database->buffer_size); +} + +static uint16_t mod(uint16_t a, uint16_t b) { + uint16_t m = a % b; + return m < 0 ? (b < 0) ? m - b : m + b : m; +} + +uint16_t ws_backlog_get_record_count() { + // add buffer_size to the result of the modulo operation if it's result is negative + // (only works when buffer_size is less than 2^15) + // this is a consequence of the way in which c handles negative numbers in modulo operations + int16_t mod = (g_ws_backlog_database->buffer_end - g_ws_backlog_database->buffer_start) % g_ws_backlog_database->buffer_size; + return mod < 0 ? mod + g_ws_backlog_database->buffer_size : mod; +} diff --git a/shared/backlog.h b/shared/backlog.h new file mode 100644 index 0000000..c8ea019 --- /dev/null +++ b/shared/backlog.h @@ -0,0 +1,59 @@ +#pragma once + +#include + +/** + * @brief allocate backlog buffer and set global backlog pointer + * @param record_amt amount of records to keep before overwriting oldest record + */ +void ws_backlog_alloc(uint16_t record_amt); + +// enable struct packing +#pragma pack(push, 1) + +/** @brief backlog record */ +typedef struct { + uint16_t id; /**< unique record identifier, numbered sequentially */ + uint8_t sens_temperature; /**< temperature reading */ + uint8_t sens_humidity; /**< humidity reading */ + uint8_t sens_atm_pressure; /**< atmospheric pressure reading */ +} ws_s_backlog_record; + +typedef struct { + uint16_t buffer_size; /**< buffer size (amount of records) */ + uint16_t buffer_start; /** first record index */ + uint16_t buffer_end; /** last record index */ + ws_s_backlog_record records[]; /** record array */ +} ws_s_backlog_database; + +// disable struct packing +#pragma pack(pop) + +/** @brief global record backlog database pointer */ +extern ws_s_backlog_database* g_ws_backlog_database; + +/** + * @brief add record to database + * + * automatically sets record.id, pushes buffer_end forwards and overwrites the + * last record if the buffer is full + */ +void ws_backlog_add_record(ws_s_backlog_record record); + +/** + * there's intentionally no function to retrieve multiple records as an array, + * as this would either require + * (a) copying the selection which is not possible with the current memory + * constraints, or + * (b) giving a direct pointer, but this would cause undefined behavior at the + * ring buffer seam + */ + +/** @brief get pointer to record with index `record_index` from the database */ +ws_s_backlog_record* ws_backlog_get_record(uint16_t record_index); + +/** @brief get pointer to last record with offset `record_offset` from the database */ +ws_s_backlog_record* ws_backlog_get_last_record(uint16_t record_offset); + +/** @brief return amount of valid records in database */ +uint16_t ws_backlog_get_record_count(); diff --git a/shared/protocol.c b/shared/protocol.c index 225b46f..55e6759 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -50,14 +50,11 @@ void ws_protocol_parse_req_byte(ws_s_protocol_req_parser_state* state, char inpu // send response char response_first_line[16]; sprintf(response_first_line, "%s,%x\n", response->success == WS_PROTOCOL_CMD_RETURN_OK ? "ok" : "error", response->msg->bytes); - ws_s_bin* response_first_line_bin = ws_bin_s_alloc(strlen(response_first_line)); - strncpy((char*) response_first_line_bin->data, response_first_line, strlen(response_first_line)); - ws_protocol_send_data(response_first_line_bin); - if (!response->csh) ws_protocol_send_data(response->msg); + ws_protocol_send_data(response_first_line, strlen(response_first_line)); + if (!response->csh) ws_protocol_send_data((char*) response->msg->data, response->msg->bytes); else (*g_ws_protocol_res_handlers[response->cmd_code])(state->target, response, true); // free response data containers - free(response_first_line_bin); free(response->msg); free(response); diff --git a/shared/protocol.h b/shared/protocol.h index c31ebc6..fbe29d6 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -137,8 +137,11 @@ ws_protocol_res_handler_t ws_protocol_res_last_records; * this function should be implemented in the source files of each target * platform, as the send interface will be different on desktop and on the * stm32. + * + * @param data pointer to data char array + * @param length length of data array */ -void ws_protocol_send_data(ws_s_bin* data); +void ws_protocol_send_data(const char* data, unsigned int length); /** @brief response handlers, called when a command is parsed */ static ws_protocol_res_handler_t* g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMOUNT] = { diff --git a/shared/test.c b/shared/test.c index 0968252..287332a 100644 --- a/shared/test.c +++ b/shared/test.c @@ -6,34 +6,40 @@ #include #include "protocol.h" +#include "backlog.h" +#include "util.h" void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response, bool send) { - const char* response_text = "" - "id,temperature,humidity,atmospheric_pressure\n" - "10dc,2f,c5,7f\n" - "10dd,30,c6,7f\n" - "10de,31,c7,7f\n" - "10df,35,ca,7e\n" - "10e0,34,c9,7e\n"; + static unsigned int record_amount = 0; + const char* response_header = "id,temperature,humidity,atmospheric_pressure\n"; + const size_t response_line_size = sizeof("xxxx,xx,xx,xx\n"); if (!send) { response->success = WS_PROTOCOL_CMD_RETURN_OK; + if (sscanf(parsed_cmd->argv[1], "%u", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; + record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); response->csh = true; response->msg = ws_bin_s_alloc(0); - response->msg->bytes = strlen(response_text); + response->msg->bytes = strlen(response_header) + response_line_size * record_amount; } else { // example send routine - ws_s_bin* response_test = ws_bin_s_alloc(strlen(response_text)); - strncpy((char*) response_test->data, response_text, strlen(response_text)); - ws_protocol_send_data(response_test); + ws_protocol_send_data(response_header, strlen(response_header)); + char line[response_line_size + 1]; // +1 for null terminator -> sprintf + for (unsigned int i = 0; i < record_amount; i++) { + ws_s_backlog_record* record = ws_backlog_get_last_record(i); + sprintf(line, "%04x,%02x,%02x,%02x\n", record->id, record->sens_temperature, record->sens_humidity, record->sens_atm_pressure); + ws_protocol_send_data(line, response_line_size); + } } } -void ws_protocol_send_data(ws_s_bin* data) { - printf("%.*s", data->bytes, data->data); +void ws_protocol_send_data(const char* data, unsigned int length) { + printf("%.*s", length, data); } int main() { + ws_backlog_alloc(10); + // disable echo and enable raw mode fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); struct termios term; @@ -45,6 +51,24 @@ int main() { ws_s_protocol_req_parser_state* parser1 = ws_protocol_req_parser_alloc(); + ws_backlog_add_record((ws_s_backlog_record) { + .sens_temperature = 0x29, + .sens_humidity = 0x34, + .sens_atm_pressure = 0x69, + }); + + ws_backlog_add_record((ws_s_backlog_record) { + .sens_temperature = 0x00, + .sens_humidity = 0x00, + .sens_atm_pressure = 0x00, + }); + + ws_backlog_add_record((ws_s_backlog_record) { + .sens_temperature = 0x01, + .sens_humidity = 0x01, + .sens_atm_pressure = 0x01, + }); + fflush(stdout); char byte; diff --git a/shared/util.h b/shared/util.h new file mode 100644 index 0000000..f39ff34 --- /dev/null +++ b/shared/util.h @@ -0,0 +1,4 @@ +#pragma once + +#define WS_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define WS_MAX(a, b) (((a) > (b)) ? (a) : (b)) diff --git a/stm32f091/backlog.c b/stm32f091/backlog.c index 3f21924..926ccad 100644 --- a/stm32f091/backlog.c +++ b/stm32f091/backlog.c @@ -2,33 +2,46 @@ #include "backlog.h" -ws_s_backlog_database* WS_G_BACKLOG_DATABASE = NULL; +ws_s_backlog_database* g_ws_backlog_database = NULL; void ws_backlog_alloc(uint16_t record_amt) { - WS_G_BACKLOG_DATABASE = malloc(sizeof(ws_s_backlog_database) + sizeof(ws_s_backlog_record) * record_amt); - WS_G_BACKLOG_DATABASE->buffer_size = record_amt; - WS_G_BACKLOG_DATABASE->buffer_start = 0; - WS_G_BACKLOG_DATABASE->buffer_end = 0; + g_ws_backlog_database = malloc(sizeof(ws_s_backlog_database) + sizeof(ws_s_backlog_record) * record_amt); + g_ws_backlog_database->buffer_size = record_amt; + g_ws_backlog_database->buffer_start = 0; + g_ws_backlog_database->buffer_end = 0; } void ws_backlog_add_record(ws_s_backlog_record record) { static uint16_t id = 0; - WS_G_BACKLOG_DATABASE->records[WS_G_BACKLOG_DATABASE->buffer_end].id = id++; - WS_G_BACKLOG_DATABASE->records[WS_G_BACKLOG_DATABASE->buffer_end].sens_atm_pressure = record.sens_atm_pressure; - WS_G_BACKLOG_DATABASE->records[WS_G_BACKLOG_DATABASE->buffer_end].sens_humidity = record.sens_humidity; - WS_G_BACKLOG_DATABASE->records[WS_G_BACKLOG_DATABASE->buffer_end].sens_temperature = record.sens_temperature; + g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].id = id++; + g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_atm_pressure = record.sens_atm_pressure; + g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_humidity = record.sens_humidity; + g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_temperature = record.sens_temperature; // shift buffer start/end - WS_G_BACKLOG_DATABASE->buffer_end = (WS_G_BACKLOG_DATABASE->buffer_end + 1) % WS_G_BACKLOG_DATABASE->buffer_size; - if (WS_G_BACKLOG_DATABASE->buffer_end == WS_G_BACKLOG_DATABASE->buffer_start) - WS_G_BACKLOG_DATABASE->buffer_start = (WS_G_BACKLOG_DATABASE->buffer_start + 1) % WS_G_BACKLOG_DATABASE->buffer_size; + g_ws_backlog_database->buffer_end = (g_ws_backlog_database->buffer_end + 1) % g_ws_backlog_database->buffer_size; + if (g_ws_backlog_database->buffer_end == g_ws_backlog_database->buffer_start) + g_ws_backlog_database->buffer_start = (g_ws_backlog_database->buffer_start + 1) % g_ws_backlog_database->buffer_size; } ws_s_backlog_record* ws_backlog_get_record(uint16_t record_index) { - return &WS_G_BACKLOG_DATABASE->records[record_index]; + return &g_ws_backlog_database->records[record_index]; } ws_s_backlog_record* ws_backlog_get_last_record(uint16_t record_offset) { - return ws_backlog_get_record((WS_G_BACKLOG_DATABASE->buffer_end - record_offset - 1) % WS_G_BACKLOG_DATABASE->buffer_size); + return ws_backlog_get_record((g_ws_backlog_database->buffer_end - record_offset - 1) % g_ws_backlog_database->buffer_size); +} + +static uint16_t mod(uint16_t a, uint16_t b) { + uint16_t m = a % b; + return m < 0 ? (b < 0) ? m - b : m + b : m; +} + +uint16_t ws_backlog_get_record_count() { + // add buffer_size to the result of the modulo operation if it's result is negative + // (only works when buffer_size is less than 2^15) + // this is a consequence of the way in which c handles negative numbers in modulo operations + int16_t mod = (g_ws_backlog_database->buffer_end - g_ws_backlog_database->buffer_start) % g_ws_backlog_database->buffer_size; + return mod < 0 ? mod + g_ws_backlog_database->buffer_size : mod; } diff --git a/stm32f091/backlog.h b/stm32f091/backlog.h index 465b3c0..c8ea019 100644 --- a/stm32f091/backlog.h +++ b/stm32f091/backlog.h @@ -30,7 +30,7 @@ typedef struct { #pragma pack(pop) /** @brief global record backlog database pointer */ -extern ws_s_backlog_database* WS_G_BACKLOG_DATABASE; +extern ws_s_backlog_database* g_ws_backlog_database; /** * @brief add record to database @@ -55,3 +55,5 @@ ws_s_backlog_record* ws_backlog_get_record(uint16_t record_index); /** @brief get pointer to last record with offset `record_offset` from the database */ ws_s_backlog_record* ws_backlog_get_last_record(uint16_t record_offset); +/** @brief return amount of valid records in database */ +uint16_t ws_backlog_get_record_count(); -- cgit v1.2.3 From aab4ed17b94f54813368201d3a0cba3f3d432589 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 19 Oct 2022 20:04:06 +0200 Subject: integrate protocol code into stm32 code --- shared/backlog.c | 47 ---------------------------- shared/backlog.h | 59 ----------------------------------- shared/makefile | 24 --------------- shared/protocol.c | 87 ++++++++++++++++++++++++++-------------------------- shared/protocol.md | 7 +++-- shared/shared.mk | 1 + shared/test.c | 82 ------------------------------------------------- shared/testcmd | 1 - stm32f091/backlog.c | 5 --- stm32f091/esp8266.c | 7 +++-- stm32f091/main.c | 1 - stm32f091/makefile | 8 +++++ stm32f091/protocol.c | 33 ++++++++++++++++++++ stm32f091/sensor.c | 6 ++++ stm32f091/server.c | 2 +- stm32f091/util.h | 3 +- 16 files changed, 103 insertions(+), 270 deletions(-) delete mode 100644 shared/backlog.c delete mode 100644 shared/backlog.h delete mode 100644 shared/makefile create mode 100644 shared/shared.mk delete mode 100644 shared/test.c delete mode 100644 shared/testcmd create mode 100644 stm32f091/protocol.c diff --git a/shared/backlog.c b/shared/backlog.c deleted file mode 100644 index 926ccad..0000000 --- a/shared/backlog.c +++ /dev/null @@ -1,47 +0,0 @@ -#include - -#include "backlog.h" - -ws_s_backlog_database* g_ws_backlog_database = NULL; - -void ws_backlog_alloc(uint16_t record_amt) { - g_ws_backlog_database = malloc(sizeof(ws_s_backlog_database) + sizeof(ws_s_backlog_record) * record_amt); - g_ws_backlog_database->buffer_size = record_amt; - g_ws_backlog_database->buffer_start = 0; - g_ws_backlog_database->buffer_end = 0; -} - -void ws_backlog_add_record(ws_s_backlog_record record) { - static uint16_t id = 0; - - g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].id = id++; - g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_atm_pressure = record.sens_atm_pressure; - g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_humidity = record.sens_humidity; - g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_temperature = record.sens_temperature; - - // shift buffer start/end - g_ws_backlog_database->buffer_end = (g_ws_backlog_database->buffer_end + 1) % g_ws_backlog_database->buffer_size; - if (g_ws_backlog_database->buffer_end == g_ws_backlog_database->buffer_start) - g_ws_backlog_database->buffer_start = (g_ws_backlog_database->buffer_start + 1) % g_ws_backlog_database->buffer_size; -} - -ws_s_backlog_record* ws_backlog_get_record(uint16_t record_index) { - return &g_ws_backlog_database->records[record_index]; -} - -ws_s_backlog_record* ws_backlog_get_last_record(uint16_t record_offset) { - return ws_backlog_get_record((g_ws_backlog_database->buffer_end - record_offset - 1) % g_ws_backlog_database->buffer_size); -} - -static uint16_t mod(uint16_t a, uint16_t b) { - uint16_t m = a % b; - return m < 0 ? (b < 0) ? m - b : m + b : m; -} - -uint16_t ws_backlog_get_record_count() { - // add buffer_size to the result of the modulo operation if it's result is negative - // (only works when buffer_size is less than 2^15) - // this is a consequence of the way in which c handles negative numbers in modulo operations - int16_t mod = (g_ws_backlog_database->buffer_end - g_ws_backlog_database->buffer_start) % g_ws_backlog_database->buffer_size; - return mod < 0 ? mod + g_ws_backlog_database->buffer_size : mod; -} diff --git a/shared/backlog.h b/shared/backlog.h deleted file mode 100644 index c8ea019..0000000 --- a/shared/backlog.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include - -/** - * @brief allocate backlog buffer and set global backlog pointer - * @param record_amt amount of records to keep before overwriting oldest record - */ -void ws_backlog_alloc(uint16_t record_amt); - -// enable struct packing -#pragma pack(push, 1) - -/** @brief backlog record */ -typedef struct { - uint16_t id; /**< unique record identifier, numbered sequentially */ - uint8_t sens_temperature; /**< temperature reading */ - uint8_t sens_humidity; /**< humidity reading */ - uint8_t sens_atm_pressure; /**< atmospheric pressure reading */ -} ws_s_backlog_record; - -typedef struct { - uint16_t buffer_size; /**< buffer size (amount of records) */ - uint16_t buffer_start; /** first record index */ - uint16_t buffer_end; /** last record index */ - ws_s_backlog_record records[]; /** record array */ -} ws_s_backlog_database; - -// disable struct packing -#pragma pack(pop) - -/** @brief global record backlog database pointer */ -extern ws_s_backlog_database* g_ws_backlog_database; - -/** - * @brief add record to database - * - * automatically sets record.id, pushes buffer_end forwards and overwrites the - * last record if the buffer is full - */ -void ws_backlog_add_record(ws_s_backlog_record record); - -/** - * there's intentionally no function to retrieve multiple records as an array, - * as this would either require - * (a) copying the selection which is not possible with the current memory - * constraints, or - * (b) giving a direct pointer, but this would cause undefined behavior at the - * ring buffer seam - */ - -/** @brief get pointer to record with index `record_index` from the database */ -ws_s_backlog_record* ws_backlog_get_record(uint16_t record_index); - -/** @brief get pointer to last record with offset `record_offset` from the database */ -ws_s_backlog_record* ws_backlog_get_last_record(uint16_t record_offset); - -/** @brief return amount of valid records in database */ -uint16_t ws_backlog_get_record_count(); diff --git a/shared/makefile b/shared/makefile deleted file mode 100644 index 2093f00..0000000 --- a/shared/makefile +++ /dev/null @@ -1,24 +0,0 @@ -CC = gcc -LD = gcc -RM = rm -f -CFLAGS = -g -std=c11 -LFLAGS = -TARGET = main - -SRCS := $(wildcard *.c) -OBJS := $(patsubst %.c,%.o, $(SRCS)) - -all: main - -%.o: %.c - $(CC) -c $(CFLAGS) $< -o $@ - -$(TARGET): $(OBJS) - $(LD) $^ $(LFLAGS) -o $@ - -clean: - $(RM) $(TARGET) $(OBJS) - -compile_commands: clean - compiledb make - diff --git a/shared/protocol.c b/shared/protocol.c index 55e6759..c6e5ddd 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -15,30 +15,30 @@ static ws_e_protocol_cmd ws_protocol_get_req_cmd_code(ws_s_protocol_parsed_req_c } void ws_protocol_parse_req_byte(ws_s_protocol_req_parser_state* state, char input) { - switch(input) { - case WS_PROTOCOL_C_EOL: { - break; - } + switch(input) { + case WS_PROTOCOL_C_EOL: { + break; + } - case WS_PROTOCOL_C_SPACE: { - if (!state->valid) return; + case WS_PROTOCOL_C_SPACE: { + if (!state->valid) return; state->arg_len++; - return; - } - - case WS_PROTOCOL_C_NULL: { - state->valid = false; - return; - } - - default: { - if (!state->valid) return; - state->cmd[state->cmd_len++] = input; - state->args_len[state->arg_len] += 1; - if (state->cmd_len == WS_PROTOCOL_CMD_BUFFER_LEN) state->valid = false; - return; - } - } + return; + } + + case WS_PROTOCOL_C_NULL: { + state->valid = false; + return; + } + + default: { + if (!state->valid) return; + state->cmd[state->cmd_len++] = input; + state->args_len[state->arg_len] += 1; + if (state->cmd_len == WS_PROTOCOL_CMD_BUFFER_LEN) state->valid = false; + return; + } + } // arg_len is used as an index while parsing, so add 1 to get length state->arg_len++; @@ -85,22 +85,23 @@ ws_protocol_parse_exit: } void ws_protocol_parse_req_bytes(ws_s_protocol_req_parser_state* state, char* input, unsigned int length) { - for (unsigned int i = 0; i < length; i++) ws_protocol_parse_req_byte(state, input[i]); + for (unsigned int i = 0; i < length; i++) ws_protocol_parse_req_byte(state, input[i]); } ws_s_protocol_req_parser_state* ws_protocol_req_parser_alloc() { - ws_s_protocol_req_parser_state* parser_state = malloc(sizeof(ws_s_protocol_req_parser_state) + sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); - parser_state->cmd = malloc(sizeof(char) * WS_PROTOCOL_CMD_BUFFER_LEN); + ws_s_protocol_req_parser_state* parser_state = malloc(sizeof(ws_s_protocol_req_parser_state) + sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); + parser_state->cmd = malloc(sizeof(char) * WS_PROTOCOL_CMD_BUFFER_LEN); + parser_state->target = NULL; ws_protocol_req_parser_reset(parser_state); - return parser_state; + return parser_state; } void ws_protocol_req_cmd_init(ws_s_protocol_req_parser_state* state) { - state->target = malloc(sizeof(ws_s_protocol_parsed_req_cmd) + sizeof(char*) * state->arg_len); - for (unsigned int i = 0; i < state->arg_len; i++) - state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); + state->target = malloc(sizeof(ws_s_protocol_parsed_req_cmd) + sizeof(char*) * state->arg_len); + for (unsigned int i = 0; i < state->arg_len; i++) + state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); - state->target->argc = state->arg_len; + state->target->argc = state->arg_len; unsigned int head = 0; for (unsigned int i = 0; i < state->arg_len; i++) { @@ -111,26 +112,26 @@ void ws_protocol_req_cmd_init(ws_s_protocol_req_parser_state* state) { } void ws_protocol_req_parser_free(ws_s_protocol_req_parser_state* state) { - if (state == NULL) return; - if (state->target != NULL) ws_protocol_req_cmd_free(state->target); + if (state == NULL) return; + if (state->target != NULL) ws_protocol_req_cmd_free(state->target); state->target = NULL; - free(state->cmd); - free(state); - return; + free(state->cmd); + free(state); + return; } void ws_protocol_req_parser_reset(ws_s_protocol_req_parser_state* state) { if (state->target != NULL) ws_protocol_req_cmd_free(state->target); - state->target = NULL; - state->valid = true; - state->cmd_len = 0; - state->arg_len = 0; + state->target = NULL; + state->valid = true; + state->cmd_len = 0; + state->arg_len = 0; memset(state->args_len, 0, sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); } void ws_protocol_req_cmd_free(ws_s_protocol_parsed_req_cmd* cmd) { - for (unsigned int i = 0; i < cmd->argc; i++) - free(cmd->argv[i]); - free(cmd); - return; + for (int i = 0; i < cmd->argc; i++) + free(cmd->argv[i]); + free(cmd); + return; } diff --git a/shared/protocol.md b/shared/protocol.md index bafec4d..b6e955c 100644 --- a/shared/protocol.md +++ b/shared/protocol.md @@ -29,8 +29,9 @@ conventions. Returns the last `n` records in csv format. The first line has the csv table header, with the fields `id`, `temperature`, `humidity`, and `atmospheric_pressure`. The rest of the response consists of 1 record per line. -When `n` is 0, or no records exist yet, the csv header is still returned, but -without any records. +The amount of records is limited to the amount of valid records in the backlog +buffer. When the amount of returned records is 0, the response consists of the +csv header, but without any following records. ## Example transaction @@ -39,7 +40,7 @@ starting with `<`, and response by lines starting with `>`. ``` < last-records 5<0a> -> ok,115<0a> +> ok,73<0a> > id,temperature,humidity,atmospheric_pressure<0a> > 10dc,2f,c5,7f<0a> > 10dd,30,c6,7f<0a> diff --git a/shared/shared.mk b/shared/shared.mk new file mode 100644 index 0000000..f9586ff --- /dev/null +++ b/shared/shared.mk @@ -0,0 +1 @@ +OBJS += $(patsubst %.c,%-stm.o, $(wildcard ../shared/*.c)) diff --git a/shared/test.c b/shared/test.c deleted file mode 100644 index 287332a..0000000 --- a/shared/test.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "protocol.h" -#include "backlog.h" -#include "util.h" - -void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response, bool send) { - static unsigned int record_amount = 0; - const char* response_header = "id,temperature,humidity,atmospheric_pressure\n"; - const size_t response_line_size = sizeof("xxxx,xx,xx,xx\n"); - - if (!send) { - response->success = WS_PROTOCOL_CMD_RETURN_OK; - if (sscanf(parsed_cmd->argv[1], "%u", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; - record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); - response->csh = true; - response->msg = ws_bin_s_alloc(0); - response->msg->bytes = strlen(response_header) + response_line_size * record_amount; - } else { - // example send routine - ws_protocol_send_data(response_header, strlen(response_header)); - char line[response_line_size + 1]; // +1 for null terminator -> sprintf - for (unsigned int i = 0; i < record_amount; i++) { - ws_s_backlog_record* record = ws_backlog_get_last_record(i); - sprintf(line, "%04x,%02x,%02x,%02x\n", record->id, record->sens_temperature, record->sens_humidity, record->sens_atm_pressure); - ws_protocol_send_data(line, response_line_size); - } - } -} - -void ws_protocol_send_data(const char* data, unsigned int length) { - printf("%.*s", length, data); -} - -int main() { - ws_backlog_alloc(10); - - // disable echo and enable raw mode - fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); - struct termios term; - tcgetattr(STDIN_FILENO, &term); - term.c_lflag &= ~(ECHO | ICANON); - term.c_cc[VTIME] = 0; - term.c_cc[VMIN] = 1; - tcsetattr(STDIN_FILENO, 0, &term); - - ws_s_protocol_req_parser_state* parser1 = ws_protocol_req_parser_alloc(); - - ws_backlog_add_record((ws_s_backlog_record) { - .sens_temperature = 0x29, - .sens_humidity = 0x34, - .sens_atm_pressure = 0x69, - }); - - ws_backlog_add_record((ws_s_backlog_record) { - .sens_temperature = 0x00, - .sens_humidity = 0x00, - .sens_atm_pressure = 0x00, - }); - - ws_backlog_add_record((ws_s_backlog_record) { - .sens_temperature = 0x01, - .sens_humidity = 0x01, - .sens_atm_pressure = 0x01, - }); - - fflush(stdout); - - char byte; - while(read(STDIN_FILENO, &byte, 1) > 0) - ws_protocol_parse_req_byte(parser1, byte); - - ws_protocol_req_parser_free(parser1); - parser1 = NULL; - - return 0; -} diff --git a/shared/testcmd b/shared/testcmd deleted file mode 100644 index 17f8842..0000000 --- a/shared/testcmd +++ /dev/null @@ -1 +0,0 @@ -last-records 5 diff --git a/stm32f091/backlog.c b/stm32f091/backlog.c index 926ccad..662fc75 100644 --- a/stm32f091/backlog.c +++ b/stm32f091/backlog.c @@ -33,11 +33,6 @@ ws_s_backlog_record* ws_backlog_get_last_record(uint16_t record_offset) { return ws_backlog_get_record((g_ws_backlog_database->buffer_end - record_offset - 1) % g_ws_backlog_database->buffer_size); } -static uint16_t mod(uint16_t a, uint16_t b) { - uint16_t m = a % b; - return m < 0 ? (b < 0) ? m - b : m + b : m; -} - uint16_t ws_backlog_get_record_count() { // add buffer_size to the result of the modulo operation if it's result is negative // (only works when buffer_size is less than 2^15) diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 6f12191..4c5d0d2 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -22,7 +22,7 @@ void ws_esp8266_ATsendCommand(uint8_t* data){ } int ws_esp8266_checkOK(uint8_t *receiveData,int length){ char *ret=""; - char *ret1=""; + // char *ret1=""; HAL_UART_Transmit(&huart2, receiveData,length,1000); ret = strstr((char*)receiveData,"OK"); // ret = strstr((char*)receiveData,"change"); @@ -159,8 +159,9 @@ void ws_esp8266_serveraan(){ HAL_Delay(1000); } void ws_esp8266_serveruit(){ - int ret; - uint8_t buffer1[27]={0}; uint8_t Tx_server[]="AT+CIPSERVER=0\r\n"; + //int ret; + //uint8_t buffer1[27]={0}; + uint8_t Tx_server[]="AT+CIPSERVER=0\r\n"; // // while(ret!=1){ diff --git a/stm32f091/main.c b/stm32f091/main.c index 9235f1b..7cb0718 100644 --- a/stm32f091/main.c +++ b/stm32f091/main.c @@ -16,7 +16,6 @@ int main() { }); ws_backlog_alloc(24 * 60); - ws_sensor_read(); xTaskCreate(ws_sensor_read_task, "sensor", 128, NULL, 1, NULL); vTaskStartScheduler(); diff --git a/stm32f091/makefile b/stm32f091/makefile index 5a185de..20424c3 100644 --- a/stm32f091/makefile +++ b/stm32f091/makefile @@ -5,6 +5,8 @@ RM = rm -f TARGET = main +include ../shared/shared.mk + SHARED_FLAGS += -g SHARED_FLAGS += -DSTM32F091xC SHARED_FLAGS += -Wall @@ -74,9 +76,15 @@ $(TARGET).bin: $(TARGET).elf %.o: %.s $(CC) -c $(AFLAGS) $< -o $@ +lib/%.o: lib/%.c + $(CC) -c $(CFLAGS) -w $< -o $@ + %.o: %.c $(CC) -c $(CFLAGS) $< -o $@ +%-stm.o: %.c + $(CC) -c $(CFLAGS) $< -o $@ + $(TARGET).elf: $(OBJS) $(LD) $(LFLAGS) $^ -o $@ diff --git a/stm32f091/protocol.c b/stm32f091/protocol.c new file mode 100644 index 0000000..589ee5d --- /dev/null +++ b/stm32f091/protocol.c @@ -0,0 +1,33 @@ +#include + +#include "../shared/protocol.h" +#include "backlog.h" +#include "util.h" + +void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response, bool send) { + static unsigned int record_amount = 0; + const char* response_header = "id,temperature,humidity,atmospheric_pressure\n"; + const size_t response_line_size = sizeof("xxxx,xx,xx,xx\n"); + + if (!send) { + response->success = WS_PROTOCOL_CMD_RETURN_OK; + if (sscanf(parsed_cmd->argv[1], "%u", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; + record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); + response->csh = true; + response->msg = ws_bin_s_alloc(0); + response->msg->bytes = strlen(response_header) + response_line_size * record_amount; + } else { + ws_protocol_send_data(response_header, strlen(response_header)); + char line[response_line_size + 1]; // +1 for null terminator -> sprintf + for (unsigned int i = 0; i < record_amount; i++) { + ws_s_backlog_record* record = ws_backlog_get_last_record(i); + sprintf(line, "%04x,%02x,%02x,%02x\n", record->id, record->sens_temperature, record->sens_humidity, record->sens_atm_pressure); + ws_protocol_send_data(line, response_line_size); + } + } +} + +void ws_protocol_send_data(const char* data, unsigned int length) { + //TODO: implement on esp data channels + HAL_UART_Transmit(&huart2, (uint8_t*) data, length, HAL_MAX_DELAY); +} diff --git a/stm32f091/sensor.c b/stm32f091/sensor.c index bc3cfd3..1c94e2a 100644 --- a/stm32f091/sensor.c +++ b/stm32f091/sensor.c @@ -58,6 +58,12 @@ void ws_sensor_read() { .sens_humidity = ws_sensor_humidity() }; ws_backlog_add_record(record); + + // < DEBUG PROTOCOL PARSING CODE > + // ws_s_protocol_req_parser_state* parser = ws_protocol_req_parser_alloc(); + // const char* request = "last-records 5\n"; + // ws_protocol_parse_req_bytes(parser, (char*) request, strlen(request)); + // ws_protocol_req_parser_free(parser); } void ws_sensor_read_task() { diff --git a/stm32f091/server.c b/stm32f091/server.c index e289245..4840527 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -28,7 +28,7 @@ void ws_server_demo() { uint8_t receive[24]={0}; uint8_t sendToQTData[]="gelukt"; uint8_t test[]="test"; - int ret; + //int ret; //ATsendCommand(sendToQTData); while (1) { diff --git a/stm32f091/util.h b/stm32f091/util.h index 8e3258f..92f093f 100644 --- a/stm32f091/util.h +++ b/stm32f091/util.h @@ -6,10 +6,11 @@ #include #include "setup.h" +#include "../shared/util.h" #define ws_usb_printf(fmt, ...) { \ char temp[255]; \ - sprintf(temp, fmt, ##__VA_ARGS__); \ + snprintf(temp, 255, fmt, ##__VA_ARGS__); \ HAL_UART_Transmit(&huart2, (uint8_t*) temp, sizeof(char) * strlen(temp), HAL_MAX_DELAY); \ } -- cgit v1.2.3 From ed1c1efa7aee67d36a37212c13998318f02c4350 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 19 Oct 2022 22:12:31 +0200 Subject: moved constants around --- .gitignore | 15 ++++++++++++--- stm32f091/consts.h | 19 +++++++++++++++++++ stm32f091/esp8266.c | 3 ++- stm32f091/readme.md | 7 +++++++ stm32f091/setup.h | 15 +-------------- stm32f091/wifi.def.h | 5 +++++ 6 files changed, 46 insertions(+), 18 deletions(-) create mode 100644 stm32f091/consts.h create mode 100644 stm32f091/readme.md create mode 100644 stm32f091/wifi.def.h diff --git a/.gitignore b/.gitignore index aba4463..18c2616 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,21 @@ -copyright +# blob **/*.o -stm32f091/main.elf -stm32f091/main.bin **/.cache **/compile_commands.json + +# stm32-specific files +stm32f091/main.elf +stm32f091/main.bin +stm32f091/wifi.h + +# client-specific files client/makefile client/client client/moc_* + +# others shared/main .qmake.stash .vscode/.cortex-debug.registers.state.json +copyright + diff --git a/stm32f091/consts.h b/stm32f091/consts.h new file mode 100644 index 0000000..e0d92bb --- /dev/null +++ b/stm32f091/consts.h @@ -0,0 +1,19 @@ +#pragma once + +#include "wifi.h" + +#define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9 +#define WS_PINOUT_I2C_SDA_PORT GPIOB +#define WS_PINOUT_I2C_SCL_PIN GPIO_PIN_8 +#define WS_PINOUT_I2C_SCL_PORT GPIOB + +#define WS_PINOUT_USART1_RX_PIN GPIO_PIN_10 +#define WS_PINOUT_USART1_RX_PORT GPIOA +#define WS_PINOUT_USART1_TX_PIN GPIO_PIN_9 +#define WS_PINOUT_USART1_TX_PORT GPIOA + +#define WS_PINOUT_USART2_RX_PIN GPIO_PIN_3 +#define WS_PINOUT_USART2_RX_PORT GPIOA +#define WS_PINOUT_USART2_TX_PIN GPIO_PIN_2 +#define WS_PINOUT_USART2_TX_PORT GPIOA + diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 4c5d0d2..9fccf70 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -5,6 +5,7 @@ #include "esp8266.h" #include "setup.h" +#include "consts.h" void ws_esp8266_ATsendCommand(uint8_t* data){ char dataChar[20]; @@ -126,7 +127,7 @@ void ws_esp8266_mode(){ HAL_Delay(1000); } void ws_esp8266_connect(){ - uint8_t Tx_network[]="AT+CWJAP=\"Test\",\"12345678\"\r\n"; + uint8_t Tx_network[]="AT+CWJAP=\"" WS_ESP8266_WLAN_SSID "\",\"" WS_ESP8266_WLAN_PASSWD "\"\r\n"; HAL_UART_Transmit(&huart1, Tx_network,strlen((char*)Tx_network),1000); diff --git a/stm32f091/readme.md b/stm32f091/readme.md new file mode 100644 index 0000000..97492d5 --- /dev/null +++ b/stm32f091/readme.md @@ -0,0 +1,7 @@ +# stm32 firmware subdirectory + +- uses make +- make sure to initialize the git submodules +- all warnings from source files in the lib/ subfolder are hidden +- copy wifi.def.h to wifi.h and edit the network credentials + diff --git a/stm32f091/setup.h b/stm32f091/setup.h index 8ca3720..04fa177 100644 --- a/stm32f091/setup.h +++ b/stm32f091/setup.h @@ -4,20 +4,7 @@ #include #include -#define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9 -#define WS_PINOUT_I2C_SDA_PORT GPIOB -#define WS_PINOUT_I2C_SCL_PIN GPIO_PIN_8 -#define WS_PINOUT_I2C_SCL_PORT GPIOB - -#define WS_PINOUT_USART1_RX_PIN GPIO_PIN_10 -#define WS_PINOUT_USART1_RX_PORT GPIOA -#define WS_PINOUT_USART1_TX_PIN GPIO_PIN_9 -#define WS_PINOUT_USART1_TX_PORT GPIOA - -#define WS_PINOUT_USART2_RX_PIN GPIO_PIN_3 -#define WS_PINOUT_USART2_RX_PORT GPIOA -#define WS_PINOUT_USART2_TX_PIN GPIO_PIN_2 -#define WS_PINOUT_USART2_TX_PORT GPIOA +#include "consts.h" extern I2C_HandleTypeDef hi2c1; extern UART_HandleTypeDef huart1; diff --git a/stm32f091/wifi.def.h b/stm32f091/wifi.def.h new file mode 100644 index 0000000..f0748d2 --- /dev/null +++ b/stm32f091/wifi.def.h @@ -0,0 +1,5 @@ +#pragma once + +#define WS_ESP8266_WLAN_SSID "Test" +#define WS_ESP8266_WLAN_PASSWD "12345678" + -- cgit v1.2.3 From 183ed1e4c58f0c788db0b56886aad2dc258e9ddb Mon Sep 17 00:00:00 2001 From: lonkaars Date: Mon, 24 Oct 2022 18:12:11 +0200 Subject: server port in consts.h + function signature for incoming esp data --- stm32f091/consts.h | 2 ++ stm32f091/esp8266.c | 30 +++++++++++++++--------------- stm32f091/server.h | 29 ++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/stm32f091/consts.h b/stm32f091/consts.h index e0d92bb..349ff21 100644 --- a/stm32f091/consts.h +++ b/stm32f091/consts.h @@ -2,6 +2,8 @@ #include "wifi.h" +#define WS_SERVER_PORT "80" + #define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9 #define WS_PINOUT_I2C_SDA_PORT GPIOB #define WS_PINOUT_I2C_SCL_PIN GPIO_PIN_8 diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 9fccf70..4fdf7e6 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -48,6 +48,7 @@ int ws_esp8266_receivingMsg(uint8_t *receiveData,int length){ HAL_UART_Transmit(&huart2, receiveData,length,1000); ret = strstr((char*)receiveData,"+IPD"); // memset(receiveData,0,30); + if((ret[0]='+') && (ret[1]=='I')){ //HAL_UART_Transmit(&huart2, (uint8_t*)ret, sizeof(ret), 100); return 1; @@ -75,13 +76,12 @@ int ws_esp8266_unlink(uint8_t *receiveData,int length){ } void ws_esp8266_StartEsp(){ - uint8_t Tx_AT[]="AT\r\n"; uint8_t Rx_buffer[10]={0}; for(int i=0;i<3;i++){ // HAL_UART_Transmit(&huart2, hier,sizeof(hier),100); - HAL_UART_Transmit_IT(&huart1, Tx_AT,strlen((char*)Tx_AT)); - HAL_UART_Receive_IT(&huart1, Rx_buffer, 10); + HAL_UART_Transmit(&huart1, Tx_AT,strlen((char*)Tx_AT), 100); + HAL_UART_Receive(&huart1, Rx_buffer, 10, 100); HAL_UART_Transmit(&huart2, Rx_buffer,10,100); @@ -95,8 +95,8 @@ void ws_esp8266_disconnect(){ uint8_t Tx_disconnect[]="AT+CWQAP\r\n";uint8_t buffer[17]={0}; while(ret!=1){ - HAL_UART_Transmit_IT(&huart1, Tx_disconnect,strlen((char*)Tx_disconnect)); - HAL_UART_Receive_IT(&huart1, buffer, 17); + HAL_UART_Transmit(&huart1, Tx_disconnect,strlen((char*)Tx_disconnect), 100); + HAL_UART_Receive(&huart1, buffer, 17, 100); HAL_Delay(2000); if(ws_esp8266_checkOK(buffer,17)==1){ @@ -113,8 +113,8 @@ void ws_esp8266_mode(){ while(ret!=1){ - HAL_UART_Transmit_IT(&huart1, Tx_mode,strlen((char*)Tx_mode)); - HAL_UART_Receive_IT(&huart1, buffer1, 20); + HAL_UART_Transmit(&huart1, Tx_mode,strlen((char*)Tx_mode), 100); + HAL_UART_Receive(&huart1, buffer1, 20, 100); HAL_Delay(1000); if(ws_esp8266_checkOK(buffer1,20)==1){ @@ -142,12 +142,12 @@ void ws_esp8266_connect(){ } void ws_esp8266_serveraan(){ int ret; - uint8_t buffer1[30]={0}; uint8_t Tx_server[]="AT+CIPSERVER=1,80\r\n"; + uint8_t buffer1[30]={0}; uint8_t Tx_server[]="AT+CIPSERVER=1," WS_SERVER_PORT "\r\n"; while(ret!=1){ - HAL_UART_Transmit_IT(&huart1, Tx_server,strlen((char*)Tx_server)); - HAL_UART_Receive_IT(&huart1, buffer1, 30); + HAL_UART_Transmit(&huart1, Tx_server,strlen((char*)Tx_server), 100); + HAL_UART_Receive(&huart1, buffer1, 30, 100); HAL_Delay(2000); if(ws_esp8266_checkOK(buffer1,30)==1){ @@ -166,8 +166,8 @@ void ws_esp8266_serveruit(){ // // while(ret!=1){ - HAL_UART_Transmit_IT(&huart1, Tx_server,strlen((char*)Tx_server)); -// HAL_UART_Receive_IT(&huart1, buffer1, 27); + HAL_UART_Transmit(&huart1, Tx_server,strlen((char*)Tx_server), 100); +// HAL_UART_Receive(&huart1, buffer1, 27, 100); HAL_Delay(3000); // if(unlink(buffer1,27)==1){ @@ -185,8 +185,8 @@ void ws_esp8266_mux(){ while(ret!=1){ - HAL_UART_Transmit_IT(&huart1, Tx_mux,strlen((char*)Tx_mux)); - HAL_UART_Receive_IT(&huart1, buffer2, 20); + HAL_UART_Transmit(&huart1, Tx_mux,strlen((char*)Tx_mux), 100); + HAL_UART_Receive(&huart1, buffer2, 20, 100); HAL_Delay(2000); if(ws_esp8266_checkOK(buffer2,20)==1){ @@ -203,7 +203,7 @@ void ws_esp8266_close(){ uint8_t Tx_close[]="AT+CIPCLOSE=0\r\n"; - HAL_UART_Transmit_IT(&huart1, Tx_close,strlen((char*)Tx_close)); + HAL_UART_Transmit(&huart1, Tx_close,strlen((char*)Tx_close), 100); HAL_Delay(3000); diff --git a/stm32f091/server.h b/stm32f091/server.h index 6a3501d..e134079 100644 --- a/stm32f091/server.h +++ b/stm32f091/server.h @@ -1,6 +1,29 @@ #pragma once -void ws_server_demo(); +#include +#include + +// void ws_server_demo(); +// +// /** FreeRTOS task that listens for incoming requests from the esp */ +// void ws_server_listen_task(); + +/** + * @brief +IPD incoming request handler + * + * this function takes chunks of data from the esp8266 and parses +IPD + * commands. when a valid +IPD command is detected, it gets forwarded to + * ws_protocol_parse_req_byte. + * + * @param data pointer to data array + * @param size amount of bytes allowed to be read from `data` + */ +void ws_server_req_incoming(uint8_t* data, size_t size); + +// TODO: server req incoming implementation +// +// example +IPD command: +// +IPD,0,15:last-records 5\n +// +// TODO: protocol req response parser -/** FreeRTOS task that listens for incoming requests from the esp */ -void ws_server_listen_task(); -- cgit v1.2.3 From 931b357fee219f7d69e3b2e1c5c275413de6010b Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-LF2PDOO\\niels" Date: Tue, 25 Oct 2022 17:42:12 +0200 Subject: initial merge of CubeIDE code for dma idle read --- .gitignore | 1 + stm32f091/consts.h | 2 ++ stm32f091/esp8266.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ stm32f091/esp8266.h | 10 ++++++++++ stm32f091/setup.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ stm32f091/setup.h | 2 ++ 6 files changed, 114 insertions(+) diff --git a/.gitignore b/.gitignore index 18c2616..90d7960 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ shared/main .qmake.stash .vscode/.cortex-debug.registers.state.json copyright +temp/ diff --git a/stm32f091/consts.h b/stm32f091/consts.h index 349ff21..1d8648d 100644 --- a/stm32f091/consts.h +++ b/stm32f091/consts.h @@ -4,6 +4,8 @@ #define WS_SERVER_PORT "80" +#define WS_DMA_RX_BUFFER_SIZE 50 + #define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9 #define WS_PINOUT_I2C_SDA_PORT GPIOB #define WS_PINOUT_I2C_SCL_PIN GPIO_PIN_8 diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 4fdf7e6..6a9f254 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -2,11 +2,64 @@ #include #include #include +#include #include "esp8266.h" #include "setup.h" #include "consts.h" +char g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; +char MainBuf[WS_DMA_RX_BUFFER_SIZE]; // TODO: remove +int isOK = 0; // TODO: remove +uint16_t g_ws_esp8266_dma_old_pos = 0; +uint16_t g_ws_esp8266_dma_new_pos = 0; + +// when rx receives data handle the message. this function is in stm32. this name needs to stay the same or else it wont work. +void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){ + if(huart->Instance == USART1) { + g_ws_esp8266_dma_old_pos = g_ws_esp8266_dma_new_pos; // Update the last position before copying new data + + if(g_ws_esp8266_dma_old_pos+Size > WS_DMA_RX_BUFFER_SIZE) { // if the current position + new data is greater than the main buffer + uint16_t dataToCopy = WS_DMA_RX_BUFFER_SIZE-g_ws_esp8266_dma_old_pos; // find remaining space left + memcpy ((uint8_t*)MainBuf+g_ws_esp8266_dma_old_pos,g_ws_esp8266_dma_rx_buffer,dataToCopy); // copy data in the remaining space + + g_ws_esp8266_dma_old_pos = 0; // point to the start of the buffer + memcpy ((uint8_t*)MainBuf,(uint8_t*)g_ws_esp8266_dma_rx_buffer+dataToCopy,(Size-dataToCopy)); // copy the remaing data + g_ws_esp8266_dma_new_pos = (Size-dataToCopy); // update position + } + // if data is less than new data + else { + memcpy ((uint8_t*)MainBuf+g_ws_esp8266_dma_old_pos,g_ws_esp8266_dma_rx_buffer,Size); + g_ws_esp8266_dma_new_pos = Size+g_ws_esp8266_dma_old_pos; + } + // start DMA again + // memset(g_ws_esp8266_dma_rx_buffer,'\0',g_ws_esp8266_dma_rx_buffer_Size); // clear rx_buff + HAL_UARTEx_ReceiveToIdle_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); + __HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT); + } + + // check for OK messagge + for(int i=0;i +extern char g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; + +void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *, uint16_t); +/** @brief This function handles DMA1 channel 2 to 3 and DMA2 channel 1 to 2 interrupts. */ +void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void); +/** @brief This function handles DMA1 channel 1 interrupt. */ +void DMA1_Ch1_IRQHandler(void); + void ws_esp8266_ATsendCommand(uint8_t* data); int ws_esp8266_checkOK(uint8_t *receiveData,int length); int ws_esp8266_receivingMsg(uint8_t *receiveData,int length); diff --git a/stm32f091/setup.c b/stm32f091/setup.c index fec2b7c..318de5a 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -5,6 +5,7 @@ #include #include +#include "esp8266.h" #include "setup.h" I2C_HandleTypeDef hi2c1 = { @@ -45,10 +46,33 @@ UART_HandleTypeDef huart2 = { .AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT, }; +DMA_HandleTypeDef hdma_usart1_rx = { + .Instance = DMA1_Channel1, + .Init.Direction = DMA_PERIPH_TO_MEMORY, + .Init.PeriphInc = DMA_PINC_DISABLE, + .Init.MemInc = DMA_MINC_ENABLE, + .Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE, + .Init.MemDataAlignment = DMA_MDATAALIGN_BYTE, + .Init.Mode = DMA_NORMAL, + .Init.Priority = DMA_PRIORITY_LOW, +}; + +DMA_HandleTypeDef hdma_usart1_tx { + .Instance = DMA1_Channel2, + .Init.Direction = DMA_MEMORY_TO_PERIPH, + .Init.PeriphInc = DMA_PINC_DISABLE, + .Init.MemInc = DMA_MINC_ENABLE, + .Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE, + .Init.MemDataAlignment = DMA_MDATAALIGN_BYTE, + .Init.Mode = DMA_NORMAL, + .Init.Priority = DMA_PRIORITY_LOW, +}; + static void ws_io_clock_setup(); static void ws_io_i2c_setup(); static void ws_io_usart1_setup(); static void ws_io_usart2_setup(); +static void ws_io_dma_setup(); static void ws_setup_error_handler(); void ws_io_setup() { @@ -58,6 +82,7 @@ void ws_io_setup() { ws_io_i2c_setup(); ws_io_usart1_setup(); ws_io_usart2_setup(); + ws_io_dma_setup(); } static void ws_io_clock_setup() { @@ -97,6 +122,9 @@ static void ws_io_i2c_setup() { static void ws_io_usart1_setup() { if (HAL_UART_Init(&huart1) != HAL_OK) return ws_setup_error_handler(); + + HAL_UARTEx_ReceiveToIdle_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); + __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); } static void ws_io_usart2_setup() { @@ -104,6 +132,16 @@ static void ws_io_usart2_setup() { return ws_setup_error_handler(); } +static void ws_io_dma_setup() { + __HAL_RCC_DMA1_CLK_ENABLE(); + + // interrupt priorities + HAL_NVIC_SetPriority(DMA1_Ch1_IRQn, 3, 0); + HAL_NVIC_EnableIRQ(DMA1_Ch1_IRQn); + HAL_NVIC_SetPriority(DMA1_Ch2_3_DMA2_Ch1_2_IRQn, 3, 0); + HAL_NVIC_EnableIRQ(DMA1_Ch2_3_DMA2_Ch1_2_IRQn); +} + void HAL_MspInit() { __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); @@ -136,6 +174,14 @@ void HAL_UART_MspInit(UART_HandleTypeDef *huart) { .Alternate = GPIO_AF1_USART1, }); + // DMA setup + if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) return ws_setup_error_handler(); + __HAL_DMA1_REMAP(HAL_DMA1_CH1_USART1_RX); + __HAL_LINKDMA(huart, hdmarx, hdma_usart1_rx); + if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK) return ws_setup_error_handler(); + __HAL_DMA1_REMAP(HAL_DMA1_CH2_USART1_TX); + __HAL_LINKDMA(huart, hdmatx, hdma_usart1_tx); + // USART1 interrupt Init HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); diff --git a/stm32f091/setup.h b/stm32f091/setup.h index 04fa177..d459635 100644 --- a/stm32f091/setup.h +++ b/stm32f091/setup.h @@ -9,6 +9,8 @@ extern I2C_HandleTypeDef hi2c1; extern UART_HandleTypeDef huart1; extern UART_HandleTypeDef huart2; +extern DMA_HandleTypeDef hdma_usart1_rx; +extern DMA_HandleTypeDef hdma_usart1_tx; void ws_io_setup(); -- cgit v1.2.3 From 7a1316483ff8962f581d686f4e812c7ec5a2b6cc Mon Sep 17 00:00:00 2001 From: lonkaars Date: Tue, 25 Oct 2022 18:08:28 +0200 Subject: finish merge --- stm32f091/esp8266.c | 2 +- stm32f091/main.c | 9 --------- stm32f091/setup.c | 13 +++++++++++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 6a9f254..341f052 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -34,7 +34,7 @@ void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){ } // start DMA again // memset(g_ws_esp8266_dma_rx_buffer,'\0',g_ws_esp8266_dma_rx_buffer_Size); // clear rx_buff - HAL_UARTEx_ReceiveToIdle_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); + HAL_UART_Receive_DMA(&huart1, (uint8_t*) g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); __HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT); } diff --git a/stm32f091/main.c b/stm32f091/main.c index 7cb0718..ed0dacd 100644 --- a/stm32f091/main.c +++ b/stm32f091/main.c @@ -5,18 +5,9 @@ #include "main.h" #include "setup.h" #include "sensor.h" -#include "backlog.h" int main() { ws_io_setup(); - HAL_GPIO_Init(GPIOA, &(GPIO_InitTypeDef) { - .Pin = GPIO_PIN_5, - .Mode = GPIO_MODE_OUTPUT_PP, - .Pull = GPIO_NOPULL - }); - - ws_backlog_alloc(24 * 60); - xTaskCreate(ws_sensor_read_task, "sensor", 128, NULL, 1, NULL); vTaskStartScheduler(); } diff --git a/stm32f091/setup.c b/stm32f091/setup.c index 318de5a..63efd37 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -7,6 +7,7 @@ #include "esp8266.h" #include "setup.h" +#include "backlog.h" I2C_HandleTypeDef hi2c1 = { .Instance = I2C1, @@ -57,7 +58,7 @@ DMA_HandleTypeDef hdma_usart1_rx = { .Init.Priority = DMA_PRIORITY_LOW, }; -DMA_HandleTypeDef hdma_usart1_tx { +DMA_HandleTypeDef hdma_usart1_tx = { .Instance = DMA1_Channel2, .Init.Direction = DMA_MEMORY_TO_PERIPH, .Init.PeriphInc = DMA_PINC_DISABLE, @@ -83,6 +84,14 @@ void ws_io_setup() { ws_io_usart1_setup(); ws_io_usart2_setup(); ws_io_dma_setup(); + + HAL_GPIO_Init(GPIOA, &(GPIO_InitTypeDef) { + .Pin = GPIO_PIN_5, + .Mode = GPIO_MODE_OUTPUT_PP, + .Pull = GPIO_NOPULL + }); + + ws_backlog_alloc(24 * 60); } static void ws_io_clock_setup() { @@ -123,7 +132,7 @@ static void ws_io_usart1_setup() { if (HAL_UART_Init(&huart1) != HAL_OK) return ws_setup_error_handler(); - HAL_UARTEx_ReceiveToIdle_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); + HAL_UART_Receive_DMA(&huart1, (uint8_t*) g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); } -- cgit v1.2.3 From 97800dd398440f50dc48911ad27897c98193c056 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Tue, 25 Oct 2022 18:22:05 +0200 Subject: dummy function in server.h implemented --- stm32f091/server.c | 56 ++++++++---------------------------------------------- stm32f091/server.h | 12 ------------ 2 files changed, 8 insertions(+), 60 deletions(-) diff --git a/stm32f091/server.c b/stm32f091/server.c index 4840527..de6ea50 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -3,55 +3,15 @@ #include #include -#include "setup.h" #include "server.h" -#include "esp8266.h" -void ws_server_demo() { - uint8_t ok[]= "ok\r\n"; - uint8_t hier[]= "hier\r\n"; - //disconnect();//connect();// +void ws_server_req_incoming(uint8_t* data, size_t size) { + // TODO: server req incoming implementation + // + // example +IPD command: + // +IPD,0,15:last-records 5\n + // + // TODO: protocol req response parser -> (ws_esp8622_at_send(data, channel) ?) - ws_esp8266_StartEsp(); - HAL_UART_Transmit(&huart2, hier,sizeof(hier),1000); - ws_esp8266_close(); - HAL_UART_Transmit(&huart2, hier,sizeof(hier),1000); - ws_esp8266_serveruit(); - HAL_UART_Transmit(&huart2, hier,sizeof(hier),1000); - ws_esp8266_mux(); - HAL_UART_Transmit(&huart2, hier,sizeof(hier),1000); - ws_esp8266_mode(); - HAL_UART_Transmit(&huart2, hier,sizeof(hier),1000); - - ws_esp8266_serveraan(); - HAL_UART_Transmit(&huart2, ok,sizeof(ok),1000); - uint8_t receive[24]={0}; - uint8_t sendToQTData[]="gelukt"; - uint8_t test[]="test"; - //int ret; - //ATsendCommand(sendToQTData); - while (1) - { - - if(receive[0]=='\0') - { - HAL_UART_Receive_IT(&huart1, receive, 24); - } - else - { - HAL_UART_Transmit(&huart2, test,strlen((char*)test),1000); - HAL_Delay(5000); - - // if(receivingMsg(receive, 24)==1) - // { - // ret=1; - ws_esp8266_ATsendCommand(sendToQTData); - ws_esp8266_close(); - memset(receive,0,24); - //} - } - - - - } + return; } diff --git a/stm32f091/server.h b/stm32f091/server.h index e134079..6041ef6 100644 --- a/stm32f091/server.h +++ b/stm32f091/server.h @@ -3,11 +3,6 @@ #include #include -// void ws_server_demo(); -// -// /** FreeRTOS task that listens for incoming requests from the esp */ -// void ws_server_listen_task(); - /** * @brief +IPD incoming request handler * @@ -20,10 +15,3 @@ */ void ws_server_req_incoming(uint8_t* data, size_t size); -// TODO: server req incoming implementation -// -// example +IPD command: -// +IPD,0,15:last-records 5\n -// -// TODO: protocol req response parser - -- cgit v1.2.3 From fbd5ed29043c4094f1209ec8935a577f5ce9e7a6 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Tue, 25 Oct 2022 19:59:31 +0200 Subject: fix full path script for other drive letters than C:/ --- scripts/compiledb-full-path-mingw.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/compiledb-full-path-mingw.sh b/scripts/compiledb-full-path-mingw.sh index 8f95756..be45ca7 100755 --- a/scripts/compiledb-full-path-mingw.sh +++ b/scripts/compiledb-full-path-mingw.sh @@ -10,4 +10,4 @@ fixpath () { fixpath arm-none-eabi-gcc fixpath arm-none-eabi-objcopy -sed "s#\"/c/#\"C:/#g" -i "$COMPILEDB_FILE" +sed 's#"/\(.\)/#"\U\1:/#g' -i "$COMPILEDB_FILE" \ No newline at end of file -- cgit v1.2.3 From e2ae9e96ba05baa389ebc49a65a941bada87e3aa Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 26 Oct 2022 15:51:18 +0200 Subject: dma write working --- stm32f091/esp8266.c | 12 +++++------- stm32f091/esp8266.h | 3 ++- stm32f091/main.c | 6 +++++- stm32f091/makefile | 1 + stm32f091/setup.c | 1 - stm32f091/test.c | 25 +++++++++++++++++++++++++ stm32f091/test.h | 4 ++++ 7 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 stm32f091/test.c create mode 100644 stm32f091/test.h diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 341f052..98c4e10 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -14,6 +14,7 @@ int isOK = 0; // TODO: remove uint16_t g_ws_esp8266_dma_old_pos = 0; uint16_t g_ws_esp8266_dma_new_pos = 0; +/* // when rx receives data handle the message. this function is in stm32. this name needs to stay the same or else it wont work. void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){ if(huart->Instance == USART1) { @@ -51,14 +52,11 @@ void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){ } } } +*/ -void DMA1_Ch1_IRQHandler(void) { - HAL_DMA_IRQHandler(&hdma_usart1_rx); -} - -void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void) { - HAL_DMA_IRQHandler(&hdma_usart1_tx); -} +void DMA1_Ch1_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_rx); } +void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_tx); } +void USART1_IRQHandler(void) { HAL_UART_IRQHandler(&huart1); } void ws_esp8266_ATsendCommand(uint8_t* data){ char dataChar[20]; diff --git a/stm32f091/esp8266.h b/stm32f091/esp8266.h index 9df02cb..d18c214 100644 --- a/stm32f091/esp8266.h +++ b/stm32f091/esp8266.h @@ -6,11 +6,12 @@ extern char g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; -void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *, uint16_t); +// void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *, uint16_t); /** @brief This function handles DMA1 channel 2 to 3 and DMA2 channel 1 to 2 interrupts. */ void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void); /** @brief This function handles DMA1 channel 1 interrupt. */ void DMA1_Ch1_IRQHandler(void); +void USART1_IRQHandler(void); void ws_esp8266_ATsendCommand(uint8_t* data); int ws_esp8266_checkOK(uint8_t *receiveData,int length); diff --git a/stm32f091/main.c b/stm32f091/main.c index ed0dacd..f5fe563 100644 --- a/stm32f091/main.c +++ b/stm32f091/main.c @@ -6,8 +6,12 @@ #include "setup.h" #include "sensor.h" +#include "test.h" + int main() { ws_io_setup(); - xTaskCreate(ws_sensor_read_task, "sensor", 128, NULL, 1, NULL); + // xTaskCreate(ws_sensor_read_task, "sensor", 64, NULL, 1, NULL); + xTaskCreate(ws_test_write_task, "testw", 16, NULL, 2, NULL); + xTaskCreate(ws_test_read_task, "testr", 16, NULL, 2, NULL); vTaskStartScheduler(); } diff --git a/stm32f091/makefile b/stm32f091/makefile index 20424c3..bf20f00 100644 --- a/stm32f091/makefile +++ b/stm32f091/makefile @@ -90,6 +90,7 @@ $(TARGET).elf: $(OBJS) flash: $(TARGET).bin st-flash write $(TARGET).bin 0x08000000 + st-flash reset compile_commands: clean compiledb make -n diff --git a/stm32f091/setup.c b/stm32f091/setup.c index 63efd37..39cff07 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -132,7 +132,6 @@ static void ws_io_usart1_setup() { if (HAL_UART_Init(&huart1) != HAL_OK) return ws_setup_error_handler(); - HAL_UART_Receive_DMA(&huart1, (uint8_t*) g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); } diff --git a/stm32f091/test.c b/stm32f091/test.c new file mode 100644 index 0000000..4d1b936 --- /dev/null +++ b/stm32f091/test.c @@ -0,0 +1,25 @@ +#include +#include +#include + +#include "setup.h" + +uint8_t tx_buffer[] = "AT\r\n"; + +void ws_test_read_task() { + uint8_t* buf; // TODO: not working + while (1) { + HAL_UART_Receive_DMA(&huart1, buf, 1); + HAL_UART_Transmit(&huart2, buf, 1, 100); + } +} + +void ws_test_write_task() { + while (1) { + HAL_UART_Transmit_DMA(&huart1, tx_buffer, sizeof(tx_buffer)); + __HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE); + + HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); + vTaskDelay(portTICK_PERIOD_MS * 1000 * 1); + } +} diff --git a/stm32f091/test.h b/stm32f091/test.h new file mode 100644 index 0000000..6c312d9 --- /dev/null +++ b/stm32f091/test.h @@ -0,0 +1,4 @@ +#pragma once + +void ws_test_read_task(); +void ws_test_write_task(); -- cgit v1.2.3 From d945680142d5b16d8809ea200833edd97caec2f8 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 26 Oct 2022 16:20:39 +0200 Subject: esp send with dma in seperate function --- stm32f091/consts.h | 1 + stm32f091/esp8266.c | 57 ++++++++++++----------------------------------------- stm32f091/esp8266.h | 19 ++++++++++++++---- stm32f091/test.c | 8 ++++---- 4 files changed, 33 insertions(+), 52 deletions(-) diff --git a/stm32f091/consts.h b/stm32f091/consts.h index 1d8648d..cf7d34f 100644 --- a/stm32f091/consts.h +++ b/stm32f091/consts.h @@ -5,6 +5,7 @@ #define WS_SERVER_PORT "80" #define WS_DMA_RX_BUFFER_SIZE 50 +#define WS_DMA_TX_BUFFER_SIZE 50 #define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9 #define WS_PINOUT_I2C_SDA_PORT GPIOB diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 98c4e10..24860a1 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -7,57 +7,26 @@ #include "esp8266.h" #include "setup.h" #include "consts.h" +#include "util.h" -char g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; -char MainBuf[WS_DMA_RX_BUFFER_SIZE]; // TODO: remove -int isOK = 0; // TODO: remove -uint16_t g_ws_esp8266_dma_old_pos = 0; -uint16_t g_ws_esp8266_dma_new_pos = 0; - -/* -// when rx receives data handle the message. this function is in stm32. this name needs to stay the same or else it wont work. -void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){ - if(huart->Instance == USART1) { - g_ws_esp8266_dma_old_pos = g_ws_esp8266_dma_new_pos; // Update the last position before copying new data - - if(g_ws_esp8266_dma_old_pos+Size > WS_DMA_RX_BUFFER_SIZE) { // if the current position + new data is greater than the main buffer - uint16_t dataToCopy = WS_DMA_RX_BUFFER_SIZE-g_ws_esp8266_dma_old_pos; // find remaining space left - memcpy ((uint8_t*)MainBuf+g_ws_esp8266_dma_old_pos,g_ws_esp8266_dma_rx_buffer,dataToCopy); // copy data in the remaining space - - g_ws_esp8266_dma_old_pos = 0; // point to the start of the buffer - memcpy ((uint8_t*)MainBuf,(uint8_t*)g_ws_esp8266_dma_rx_buffer+dataToCopy,(Size-dataToCopy)); // copy the remaing data - g_ws_esp8266_dma_new_pos = (Size-dataToCopy); // update position - } - // if data is less than new data - else { - memcpy ((uint8_t*)MainBuf+g_ws_esp8266_dma_old_pos,g_ws_esp8266_dma_rx_buffer,Size); - g_ws_esp8266_dma_new_pos = Size+g_ws_esp8266_dma_old_pos; - } - // start DMA again - // memset(g_ws_esp8266_dma_rx_buffer,'\0',g_ws_esp8266_dma_rx_buffer_Size); // clear rx_buff - HAL_UART_Receive_DMA(&huart1, (uint8_t*) g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); - __HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT); - } +uint8_t g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; +uint8_t g_ws_esp8266_dma_tx_buffer[WS_DMA_TX_BUFFER_SIZE]; - // check for OK messagge - for(int i=0;i #include -extern char g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; +/** @brief null-terminated rx buffer string */ +extern uint8_t g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; +/** @brief null-terminated tx buffer string */ +extern uint8_t g_ws_esp8266_dma_tx_buffer[WS_DMA_TX_BUFFER_SIZE]; -// void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *, uint16_t); -/** @brief This function handles DMA1 channel 2 to 3 and DMA2 channel 1 to 2 interrupts. */ +/** @brief DMA1 channel 2-3 & DMA2 channel 1-2 interrupt handler */ void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void); -/** @brief This function handles DMA1 channel 1 interrupt. */ +/** @brief DMA1 channel 1 interrupt handler */ void DMA1_Ch1_IRQHandler(void); +/** @brief USART1 interrupt handler */ void USART1_IRQHandler(void); +/** @brief send response to incoming request on specific channel */ +void ws_esp8266_res_send(unsigned int channel, uint8_t* data, size_t size); + +/** @brief send data to esp over uart with dma */ +void ws_esp8266_send(uint8_t* data, size_t size); + +// TODO: remove/update/document/refactor these functions void ws_esp8266_ATsendCommand(uint8_t* data); int ws_esp8266_checkOK(uint8_t *receiveData,int length); int ws_esp8266_receivingMsg(uint8_t *receiveData,int length); diff --git a/stm32f091/test.c b/stm32f091/test.c index 4d1b936..0960d0f 100644 --- a/stm32f091/test.c +++ b/stm32f091/test.c @@ -2,9 +2,9 @@ #include #include +#include "esp8266.h" #include "setup.h" - -uint8_t tx_buffer[] = "AT\r\n"; +#include "util.h" void ws_test_read_task() { uint8_t* buf; // TODO: not working @@ -15,9 +15,9 @@ void ws_test_read_task() { } void ws_test_write_task() { + uint8_t data[] = "AT\r\n"; while (1) { - HAL_UART_Transmit_DMA(&huart1, tx_buffer, sizeof(tx_buffer)); - __HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE); + ws_esp8266_send(data, sizeof(data)); HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); vTaskDelay(portTICK_PERIOD_MS * 1000 * 1); -- cgit v1.2.3 From 5c0538a5aef4ee0ea9ec8ed82b1e74768732286f Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 26 Oct 2022 19:17:02 +0200 Subject: flash and build before debugging and don't stop in main --- .vscode/launch.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 9c586dc..b104e0f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -31,9 +31,8 @@ "executable": "${workspaceFolder}/stm32f091/main.elf", "request": "launch", "type": "cortex-debug", - "runToEntryPoint": "main", "servertype": "stlink", - "preLaunchTask": "stm32/build", + "preLaunchTask": "stm32/flash", "linux": { "stlinkPath": "/usr/bin/st-util" }, -- cgit v1.2.3 From a74368cb7eebb99b14060c9198dfa277a18c2234 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 26 Oct 2022 19:17:51 +0200 Subject: optimize makefile --- stm32f091/makefile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/stm32f091/makefile b/stm32f091/makefile index bf20f00..dd03761 100644 --- a/stm32f091/makefile +++ b/stm32f091/makefile @@ -4,6 +4,7 @@ OC = arm-none-eabi-objcopy RM = rm -f TARGET = main +HOST=$(strip $(shell uname -o)) include ../shared/shared.mk @@ -13,7 +14,6 @@ SHARED_FLAGS += -Wall SHARED_FLAGS += -Wextra # SHARED_FLAGS += -Wno-register SHARED_FLAGS += -Wa,--defsym,CALL_ARM_SYSTEM_INIT=1 -# SHARED_FLAGS += -I/usr/arm-none-eabi/include/ SHARED_FLAGS += -I./lib/STM32-base-STM32Cube/HAL/STM32F0xx/inc SHARED_FLAGS += -I./lib/STM32-base-STM32Cube/HAL/STM32F0xx/inc/Legacy SHARED_FLAGS += -I./lib/STM32-base-STM32Cube/CMSIS/ARM/inc @@ -22,7 +22,10 @@ SHARED_FLAGS += -I./lib/STM32-base/startup SHARED_FLAGS += -I./lib/FreeRTOS-Kernel/include SHARED_FLAGS += -I./lib/FreeRTOS-Kernel/portable/GCC/ARM_CM0/ SHARED_FLAGS += -I. -SHARED_FLAGS += -O1 +ifeq ($(HOST),GNU/Linux) +SHARED_FLAGS += -I/usr/arm-none-eabi/include/ +endif +# SHARED_FLAGS += -O1 SHARED_FLAGS += -ffunction-sections SHARED_FLAGS += -fdata-sections SHARED_FLAGS += -Wl,--gc-sections @@ -89,8 +92,7 @@ $(TARGET).elf: $(OBJS) $(LD) $(LFLAGS) $^ -o $@ flash: $(TARGET).bin - st-flash write $(TARGET).bin 0x08000000 - st-flash reset + st-flash --reset write $(TARGET).bin 0x08000000 compile_commands: clean compiledb make -n -- cgit v1.2.3 From d48374c0f38cb01d726958b49bda5c1b6e91ab91 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 26 Oct 2022 19:18:26 +0200 Subject: WIP working dma receive to buffer --- stm32f091/consts.h | 2 +- stm32f091/esp8266.c | 8 ++++++++ stm32f091/esp8266.h | 10 +++++++--- stm32f091/main.c | 3 +-- stm32f091/setup.c | 11 ++++++++--- stm32f091/stm32f0xx_hal_conf.h | 2 ++ stm32f091/test.c | 13 +------------ stm32f091/test.h | 1 - 8 files changed, 28 insertions(+), 22 deletions(-) diff --git a/stm32f091/consts.h b/stm32f091/consts.h index cf7d34f..5f9d7a1 100644 --- a/stm32f091/consts.h +++ b/stm32f091/consts.h @@ -4,7 +4,7 @@ #define WS_SERVER_PORT "80" -#define WS_DMA_RX_BUFFER_SIZE 50 +#define WS_DMA_RX_BUFFER_SIZE 10 #define WS_DMA_TX_BUFFER_SIZE 50 #define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9 diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 24860a1..5d1847b 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -16,6 +16,14 @@ void DMA1_Ch1_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_rx); } void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_tx); } void USART1_IRQHandler(void) { HAL_UART_IRQHandler(&huart1); } +void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart) { + HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); + + HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE, 100); + HAL_UART_Receive_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); + __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); +} + void ws_esp8266_send(uint8_t* data, size_t size) { size_t limited_size = WS_MIN(size, WS_DMA_TX_BUFFER_SIZE - 1); memcpy(g_ws_esp8266_dma_tx_buffer, data, limited_size); diff --git a/stm32f091/esp8266.h b/stm32f091/esp8266.h index 8038679..0832e95 100644 --- a/stm32f091/esp8266.h +++ b/stm32f091/esp8266.h @@ -1,11 +1,12 @@ #pragma once -#include "consts.h" - +#include #include #include -/** @brief null-terminated rx buffer string */ +#include "consts.h" + +/** @brief DMA rx buffer */ extern uint8_t g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; /** @brief null-terminated tx buffer string */ extern uint8_t g_ws_esp8266_dma_tx_buffer[WS_DMA_TX_BUFFER_SIZE]; @@ -17,6 +18,9 @@ void DMA1_Ch1_IRQHandler(void); /** @brief USART1 interrupt handler */ void USART1_IRQHandler(void); +/** @brief receive chunk complete */ +void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart); + /** @brief send response to incoming request on specific channel */ void ws_esp8266_res_send(unsigned int channel, uint8_t* data, size_t size); diff --git a/stm32f091/main.c b/stm32f091/main.c index f5fe563..80eb5a7 100644 --- a/stm32f091/main.c +++ b/stm32f091/main.c @@ -11,7 +11,6 @@ int main() { ws_io_setup(); // xTaskCreate(ws_sensor_read_task, "sensor", 64, NULL, 1, NULL); - xTaskCreate(ws_test_write_task, "testw", 16, NULL, 2, NULL); - xTaskCreate(ws_test_read_task, "testr", 16, NULL, 2, NULL); + xTaskCreate(ws_test_write_task, "test", 16, NULL, 2, NULL); vTaskStartScheduler(); } diff --git a/stm32f091/setup.c b/stm32f091/setup.c index 39cff07..98ef8cd 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -30,8 +30,8 @@ UART_HandleTypeDef huart1 = { .Init.Mode = UART_MODE_TX_RX, .Init.HwFlowCtl = UART_HWCONTROL_NONE, .Init.OverSampling = UART_OVERSAMPLING_16, - .Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE, - .AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT, +// .Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE, +// .AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT, }; UART_HandleTypeDef huart2 = { @@ -81,6 +81,7 @@ void ws_io_setup() { ws_io_clock_setup(); ws_io_i2c_setup(); + ws_io_dma_setup(); ws_io_usart1_setup(); ws_io_usart2_setup(); ws_io_dma_setup(); @@ -132,7 +133,11 @@ static void ws_io_usart1_setup() { if (HAL_UART_Init(&huart1) != HAL_OK) return ws_setup_error_handler(); + // HAL_UARTEx_ReceiveToIdle_DMA(&huart2, RX_DMA_buffer, RX_DMA_BUFFER_SIZE); + HAL_UART_Receive_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); + // __HAL_DMA_ENABLE_IT(&hdma_usart1_rx, DMA_IT_TC); + // __HAL_UART_ENABLE_IT(&huart1, UART_IT_TC); } static void ws_io_usart2_setup() { @@ -191,7 +196,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef *huart) { __HAL_LINKDMA(huart, hdmatx, hdma_usart1_tx); // USART1 interrupt Init - HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); + HAL_NVIC_SetPriority(USART1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); } else if (huart->Instance == USART2) { __HAL_RCC_USART2_CLK_ENABLE(); diff --git a/stm32f091/stm32f0xx_hal_conf.h b/stm32f091/stm32f0xx_hal_conf.h index fc27221..45f9fab 100644 --- a/stm32f091/stm32f0xx_hal_conf.h +++ b/stm32f091/stm32f0xx_hal_conf.h @@ -19,6 +19,8 @@ #define DATA_CACHE_ENABLE 0U #define USE_SPI_CRC 0U +#define USE_HAL_UART_REGISTER_CALLBACKS 1 + #define HAL_RCC_MODULE_ENABLED #define HAL_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED diff --git a/stm32f091/test.c b/stm32f091/test.c index 0960d0f..e25b071 100644 --- a/stm32f091/test.c +++ b/stm32f091/test.c @@ -3,23 +3,12 @@ #include #include "esp8266.h" -#include "setup.h" -#include "util.h" - -void ws_test_read_task() { - uint8_t* buf; // TODO: not working - while (1) { - HAL_UART_Receive_DMA(&huart1, buf, 1); - HAL_UART_Transmit(&huart2, buf, 1, 100); - } -} void ws_test_write_task() { uint8_t data[] = "AT\r\n"; while (1) { ws_esp8266_send(data, sizeof(data)); - HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); - vTaskDelay(portTICK_PERIOD_MS * 1000 * 1); + vTaskDelay(portTICK_PERIOD_MS * 100 * 1); } } diff --git a/stm32f091/test.h b/stm32f091/test.h index 6c312d9..dffa516 100644 --- a/stm32f091/test.h +++ b/stm32f091/test.h @@ -1,4 +1,3 @@ #pragma once -void ws_test_read_task(); void ws_test_write_task(); -- cgit v1.2.3 From 02f7c39773db3daa5e0885035c79a1e10e8af0df Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 26 Oct 2022 19:31:19 +0200 Subject: clean up test code --- stm32f091/setup.c | 23 +++++++++-------------- stm32f091/stm32f0xx_hal_conf.h | 2 -- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/stm32f091/setup.c b/stm32f091/setup.c index 98ef8cd..2110e03 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -22,16 +22,14 @@ I2C_HandleTypeDef hi2c1 = { }; UART_HandleTypeDef huart1 = { - .Instance = USART1, - .Init.BaudRate = 115200, - .Init.WordLength = UART_WORDLENGTH_8B, - .Init.StopBits = UART_STOPBITS_1, - .Init.Parity = UART_PARITY_NONE, - .Init.Mode = UART_MODE_TX_RX, - .Init.HwFlowCtl = UART_HWCONTROL_NONE, - .Init.OverSampling = UART_OVERSAMPLING_16, -// .Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE, -// .AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT, + .Instance = USART1, + .Init.BaudRate = 115200, + .Init.WordLength = UART_WORDLENGTH_8B, + .Init.StopBits = UART_STOPBITS_1, + .Init.Parity = UART_PARITY_NONE, + .Init.Mode = UART_MODE_TX_RX, + .Init.HwFlowCtl = UART_HWCONTROL_NONE, + .Init.OverSampling = UART_OVERSAMPLING_16, }; UART_HandleTypeDef huart2 = { @@ -133,11 +131,8 @@ static void ws_io_usart1_setup() { if (HAL_UART_Init(&huart1) != HAL_OK) return ws_setup_error_handler(); - // HAL_UARTEx_ReceiveToIdle_DMA(&huart2, RX_DMA_buffer, RX_DMA_BUFFER_SIZE); HAL_UART_Receive_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); - // __HAL_DMA_ENABLE_IT(&hdma_usart1_rx, DMA_IT_TC); - // __HAL_UART_ENABLE_IT(&huart1, UART_IT_TC); } static void ws_io_usart2_setup() { @@ -196,7 +191,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef *huart) { __HAL_LINKDMA(huart, hdmatx, hdma_usart1_tx); // USART1 interrupt Init - HAL_NVIC_SetPriority(USART1_IRQn, 5, 0); + HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); } else if (huart->Instance == USART2) { __HAL_RCC_USART2_CLK_ENABLE(); diff --git a/stm32f091/stm32f0xx_hal_conf.h b/stm32f091/stm32f0xx_hal_conf.h index 45f9fab..fc27221 100644 --- a/stm32f091/stm32f0xx_hal_conf.h +++ b/stm32f091/stm32f0xx_hal_conf.h @@ -19,8 +19,6 @@ #define DATA_CACHE_ENABLE 0U #define USE_SPI_CRC 0U -#define USE_HAL_UART_REGISTER_CALLBACKS 1 - #define HAL_RCC_MODULE_ENABLED #define HAL_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED -- cgit v1.2.3 From 754dc7371651bd1b7fa74ee1aab9f297329a0f15 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 26 Oct 2022 19:32:59 +0200 Subject: add disclaimer for broken dma functionality --- stm32f091/readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stm32f091/readme.md b/stm32f091/readme.md index 97492d5..d2758b5 100644 --- a/stm32f091/readme.md +++ b/stm32f091/readme.md @@ -4,4 +4,8 @@ - make sure to initialize the git submodules - all warnings from source files in the lib/ subfolder are hidden - copy wifi.def.h to wifi.h and edit the network credentials +- the initialization code is broken in some way which means that a soft reset + is required for the uart dma to work, either (a) press the reset button on + the development board after plugging in, or (b) run `st-flash reset` after + plugging in. -- cgit v1.2.3 From 4dbb57fe63d3c59893d1a670fecdde7ea20c9a4a Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 26 Oct 2022 19:34:52 +0200 Subject: call server req incoming from transfer complete handler --- stm32f091/esp8266.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 5d1847b..4daba34 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -7,6 +7,7 @@ #include "esp8266.h" #include "setup.h" #include "consts.h" +#include "server.h" #include "util.h" uint8_t g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; @@ -17,9 +18,8 @@ void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_tx void USART1_IRQHandler(void) { HAL_UART_IRQHandler(&huart1); } void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart) { - HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); + ws_server_req_incoming(g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); - HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE, 100); HAL_UART_Receive_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); } -- cgit v1.2.3 From ead710db271795380207141f0add7278ba12ada0 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 27 Oct 2022 10:56:26 +0200 Subject: finish merge and fix sql scripts --- client/ui_dbconnector.h | 163 ++++++++++++++++++++++++++++++++++++++++++++++ client/ui_mainwindow.h | 110 +++++++++++++++++++++++++++++++ scripts/db-init.sql | 20 +++--- scripts/db-privileges.sql | 1 + 4 files changed, 285 insertions(+), 9 deletions(-) create mode 100644 client/ui_dbconnector.h create mode 100644 client/ui_mainwindow.h create mode 100644 scripts/db-privileges.sql diff --git a/client/ui_dbconnector.h b/client/ui_dbconnector.h new file mode 100644 index 0000000..dec4d7b --- /dev/null +++ b/client/ui_dbconnector.h @@ -0,0 +1,163 @@ +/******************************************************************************** +** Form generated from reading UI file 'dbconnector.ui' +** +** Created by: Qt User Interface Compiler version 5.15.6 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_DBCONNECTOR_H +#define UI_DBCONNECTOR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_dbConnector +{ +public: + QWidget *formLayoutWidget; + QFormLayout *formLayout; + QLabel *label_3; + QLineEdit *lineEdit_adress; + QLabel *label_4; + QLineEdit *lineEdit_database; + QFrame *line; + QLabel *label; + QLineEdit *lineEdit_username; + QLabel *label_2; + QLineEdit *lineEdit_password; + QLabel *connectLabel; + QHBoxLayout *horizontalLayout; + QPushButton *pushButton_login; + QPushButton *pushButton_cancel; + + void setupUi(QDialog *dbConnector) + { + if (dbConnector->objectName().isEmpty()) + dbConnector->setObjectName(QString::fromUtf8("dbConnector")); + dbConnector->resize(362, 273); + formLayoutWidget = new QWidget(dbConnector); + formLayoutWidget->setObjectName(QString::fromUtf8("formLayoutWidget")); + formLayoutWidget->setGeometry(QRect(60, 60, 241, 173)); + formLayout = new QFormLayout(formLayoutWidget); + formLayout->setObjectName(QString::fromUtf8("formLayout")); + formLayout->setContentsMargins(0, 0, 0, 0); + label_3 = new QLabel(formLayoutWidget); + label_3->setObjectName(QString::fromUtf8("label_3")); + + formLayout->setWidget(0, QFormLayout::LabelRole, label_3); + + lineEdit_adress = new QLineEdit(formLayoutWidget); + lineEdit_adress->setObjectName(QString::fromUtf8("lineEdit_adress")); + + formLayout->setWidget(0, QFormLayout::FieldRole, lineEdit_adress); + + label_4 = new QLabel(formLayoutWidget); + label_4->setObjectName(QString::fromUtf8("label_4")); + + formLayout->setWidget(1, QFormLayout::LabelRole, label_4); + + lineEdit_database = new QLineEdit(formLayoutWidget); + lineEdit_database->setObjectName(QString::fromUtf8("lineEdit_database")); + + formLayout->setWidget(1, QFormLayout::FieldRole, lineEdit_database); + + line = new QFrame(formLayoutWidget); + line->setObjectName(QString::fromUtf8("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + formLayout->setWidget(2, QFormLayout::SpanningRole, line); + + label = new QLabel(formLayoutWidget); + label->setObjectName(QString::fromUtf8("label")); + + formLayout->setWidget(3, QFormLayout::LabelRole, label); + + lineEdit_username = new QLineEdit(formLayoutWidget); + lineEdit_username->setObjectName(QString::fromUtf8("lineEdit_username")); + lineEdit_username->setEchoMode(QLineEdit::PasswordEchoOnEdit); + + formLayout->setWidget(3, QFormLayout::FieldRole, lineEdit_username); + + label_2 = new QLabel(formLayoutWidget); + label_2->setObjectName(QString::fromUtf8("label_2")); + + formLayout->setWidget(4, QFormLayout::LabelRole, label_2); + + lineEdit_password = new QLineEdit(formLayoutWidget); + lineEdit_password->setObjectName(QString::fromUtf8("lineEdit_password")); + QFont font; + font.setUnderline(false); + font.setStrikeOut(false); + font.setKerning(true); + lineEdit_password->setFont(font); + lineEdit_password->setEchoMode(QLineEdit::Password); + + formLayout->setWidget(4, QFormLayout::FieldRole, lineEdit_password); + + connectLabel = new QLabel(formLayoutWidget); + connectLabel->setObjectName(QString::fromUtf8("connectLabel")); + + formLayout->setWidget(5, QFormLayout::LabelRole, connectLabel); + + horizontalLayout = new QHBoxLayout(); + horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); + pushButton_login = new QPushButton(formLayoutWidget); + pushButton_login->setObjectName(QString::fromUtf8("pushButton_login")); + + horizontalLayout->addWidget(pushButton_login); + + pushButton_cancel = new QPushButton(formLayoutWidget); + pushButton_cancel->setObjectName(QString::fromUtf8("pushButton_cancel")); + + horizontalLayout->addWidget(pushButton_cancel); + + + formLayout->setLayout(5, QFormLayout::FieldRole, horizontalLayout); + + + retranslateUi(dbConnector); + + QMetaObject::connectSlotsByName(dbConnector); + } // setupUi + + void retranslateUi(QDialog *dbConnector) + { + dbConnector->setWindowTitle(QCoreApplication::translate("dbConnector", "Dialog", nullptr)); + label_3->setText(QCoreApplication::translate("dbConnector", "Adress", nullptr)); + lineEdit_adress->setText(QCoreApplication::translate("dbConnector", "localhost", nullptr)); + lineEdit_adress->setPlaceholderText(QCoreApplication::translate("dbConnector", "Hostname/IP-Adress", nullptr)); + label_4->setText(QCoreApplication::translate("dbConnector", "Database", nullptr)); + lineEdit_database->setText(QCoreApplication::translate("dbConnector", "WSdb", nullptr)); + lineEdit_database->setPlaceholderText(QCoreApplication::translate("dbConnector", "Database name", nullptr)); + label->setText(QCoreApplication::translate("dbConnector", "Username", nullptr)); + lineEdit_username->setText(QCoreApplication::translate("dbConnector", "root", nullptr)); + lineEdit_username->setPlaceholderText(QCoreApplication::translate("dbConnector", "Username", nullptr)); + label_2->setText(QCoreApplication::translate("dbConnector", "Password", nullptr)); + lineEdit_password->setText(QCoreApplication::translate("dbConnector", "Ab12345!", nullptr)); + lineEdit_password->setPlaceholderText(QCoreApplication::translate("dbConnector", "Password", nullptr)); + connectLabel->setText(QCoreApplication::translate("dbConnector", "Connect", nullptr)); + pushButton_login->setText(QCoreApplication::translate("dbConnector", "Login", nullptr)); + pushButton_cancel->setText(QCoreApplication::translate("dbConnector", "Cancel", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class dbConnector: public Ui_dbConnector {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_DBCONNECTOR_H diff --git a/client/ui_mainwindow.h b/client/ui_mainwindow.h new file mode 100644 index 0000000..46bb29a --- /dev/null +++ b/client/ui_mainwindow.h @@ -0,0 +1,110 @@ +/******************************************************************************** +** Form generated from reading UI file 'mainwindow.ui' +** +** Created by: Qt User Interface Compiler version 5.15.6 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_MAINWINDOW_H +#define UI_MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_MainWindow +{ +public: + QAction *actionRefresh; + QAction *actionLOAD; + QAction *actionQuerry; + QAction *actionConnection; + QAction *actionDisconnenct; + QWidget *centralwidget; + QLabel *label; + QMenuBar *menubar; + QMenu *menuAbouy; + QMenu *menuDatabase; + QStatusBar *statusbar; + + void setupUi(QMainWindow *MainWindow) + { + if (MainWindow->objectName().isEmpty()) + MainWindow->setObjectName(QString::fromUtf8("MainWindow")); + MainWindow->resize(800, 600); + actionRefresh = new QAction(MainWindow); + actionRefresh->setObjectName(QString::fromUtf8("actionRefresh")); + actionLOAD = new QAction(MainWindow); + actionLOAD->setObjectName(QString::fromUtf8("actionLOAD")); + actionQuerry = new QAction(MainWindow); + actionQuerry->setObjectName(QString::fromUtf8("actionQuerry")); + actionConnection = new QAction(MainWindow); + actionConnection->setObjectName(QString::fromUtf8("actionConnection")); + actionDisconnenct = new QAction(MainWindow); + actionDisconnenct->setObjectName(QString::fromUtf8("actionDisconnenct")); + centralwidget = new QWidget(MainWindow); + centralwidget->setObjectName(QString::fromUtf8("centralwidget")); + label = new QLabel(centralwidget); + label->setObjectName(QString::fromUtf8("label")); + label->setGeometry(QRect(270, 190, 181, 51)); + MainWindow->setCentralWidget(centralwidget); + menubar = new QMenuBar(MainWindow); + menubar->setObjectName(QString::fromUtf8("menubar")); + menubar->setGeometry(QRect(0, 0, 800, 24)); + menuAbouy = new QMenu(menubar); + menuAbouy->setObjectName(QString::fromUtf8("menuAbouy")); + menuDatabase = new QMenu(menubar); + menuDatabase->setObjectName(QString::fromUtf8("menuDatabase")); + MainWindow->setMenuBar(menubar); + statusbar = new QStatusBar(MainWindow); + statusbar->setObjectName(QString::fromUtf8("statusbar")); + MainWindow->setStatusBar(statusbar); + + menubar->addAction(menuAbouy->menuAction()); + menubar->addAction(menuDatabase->menuAction()); + menuAbouy->addAction(actionRefresh); + menuDatabase->addAction(actionConnection); + menuDatabase->addAction(actionDisconnenct); + + retranslateUi(MainWindow); + + QMetaObject::connectSlotsByName(MainWindow); + } // setupUi + + void retranslateUi(QMainWindow *MainWindow) + { + MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr)); + actionRefresh->setText(QCoreApplication::translate("MainWindow", "Refresh", nullptr)); +#if QT_CONFIG(shortcut) + actionRefresh->setShortcut(QCoreApplication::translate("MainWindow", "Ctrl+R", nullptr)); +#endif // QT_CONFIG(shortcut) + actionLOAD->setText(QCoreApplication::translate("MainWindow", "Load", nullptr)); + actionQuerry->setText(QCoreApplication::translate("MainWindow", "Query", nullptr)); + actionConnection->setText(QCoreApplication::translate("MainWindow", "Connect", nullptr)); +#if QT_CONFIG(shortcut) + actionConnection->setShortcut(QCoreApplication::translate("MainWindow", "Ctrl+O", nullptr)); +#endif // QT_CONFIG(shortcut) + actionDisconnenct->setText(QCoreApplication::translate("MainWindow", "Disconnenct", nullptr)); + label->setText(QCoreApplication::translate("MainWindow", "Please load data first", nullptr)); + menuAbouy->setTitle(QCoreApplication::translate("MainWindow", "Home", nullptr)); + menuDatabase->setTitle(QCoreApplication::translate("MainWindow", "Database", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class MainWindow: public Ui_MainWindow {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_MAINWINDOW_H diff --git a/scripts/db-init.sql b/scripts/db-init.sql index 4c4c4d4..2b0581c 100644 --- a/scripts/db-init.sql +++ b/scripts/db-init.sql @@ -1,9 +1,11 @@ -CREATE SCHEMA `WSdb`; -CREATE TABLE `DAB1Pract1`.`tblMain` ( - `ID` INT GENERATED ALWAYS AS (), - `temperature` DECIMAL(5,2) NULL, - `humidity` DECIMAL(5,2) NULL, - `pressure` DECIMAL(5,2) NULL, - `time` DATETIME NULL, - PRIMARY KEY (`ID`), - UNIQUE INDEX `ID_UNIQUE` (`ID` ASC) VISIBLE); +drop schema if exists `WSdb`; +create schema if not exists `WSdb`; +drop table if exists `WSdb`.`tblMain`; +create table if not exists `WSdb`.`tblMain` ( + id int unsigned not null auto_increment, + temperature decimal(5,2) null, + humidity decimal(5,2) null, + pressure decimal(5,2) null, + time datetime null, + primary key (id) +); diff --git a/scripts/db-privileges.sql b/scripts/db-privileges.sql new file mode 100644 index 0000000..75f8fcc --- /dev/null +++ b/scripts/db-privileges.sql @@ -0,0 +1 @@ +grant all privileges on WSdb.* to 'user'@'localhost'; -- cgit v1.2.3 From 94e31069df88c3d5e50b4160705c2b7aa27e152b Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 27 Oct 2022 15:37:35 +0200 Subject: WIP server parser --- stm32f091/consts.h | 6 +++-- stm32f091/esp8266.c | 27 ++++++++++++++++--- stm32f091/esp8266.h | 6 ++--- stm32f091/server.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++----- stm32f091/server.h | 27 +++++++++++++++++++ stm32f091/setup.c | 5 +++- stm32f091/test.c | 15 +++++++---- 7 files changed, 139 insertions(+), 21 deletions(-) diff --git a/stm32f091/consts.h b/stm32f091/consts.h index 5f9d7a1..b3bc2e2 100644 --- a/stm32f091/consts.h +++ b/stm32f091/consts.h @@ -4,8 +4,8 @@ #define WS_SERVER_PORT "80" -#define WS_DMA_RX_BUFFER_SIZE 10 -#define WS_DMA_TX_BUFFER_SIZE 50 +#define WS_DMA_RX_BUFFER_SIZE 100 +#define WS_DMA_TX_BUFFER_SIZE 100 #define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9 #define WS_PINOUT_I2C_SDA_PORT GPIOB @@ -22,3 +22,5 @@ #define WS_PINOUT_USART2_TX_PIN GPIO_PIN_2 #define WS_PINOUT_USART2_TX_PORT GPIOA +// print esp communication over usb serial (green for tx, red for rx) +#define WS_DBG_PRINT_ESP_OVER_USART2 diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 4daba34..c98528e 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -15,13 +15,22 @@ uint8_t g_ws_esp8266_dma_tx_buffer[WS_DMA_TX_BUFFER_SIZE]; void DMA1_Ch1_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_rx); } void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_tx); } -void USART1_IRQHandler(void) { HAL_UART_IRQHandler(&huart1); } +void USART1_IRQHandler(void) { + if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) { + __HAL_UART_CLEAR_IDLEFLAG(&huart1); + HAL_UART_RxCpltCallback(&huart1); + HAL_UART_DMAStop(&huart1); + ws_esp8266_start_receive(); + } + HAL_UART_IRQHandler(&huart1); +} void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart) { - ws_server_req_incoming(g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); + size_t len = strlen((char*) g_ws_esp8266_dma_rx_buffer); + if (len > 0) ws_server_req_incoming(g_ws_esp8266_dma_rx_buffer, len); - HAL_UART_Receive_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); - __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); + memset(g_ws_esp8266_dma_rx_buffer, 0, WS_DMA_RX_BUFFER_SIZE); + ws_esp8266_start_receive(); } void ws_esp8266_send(uint8_t* data, size_t size) { @@ -29,10 +38,20 @@ void ws_esp8266_send(uint8_t* data, size_t size) { memcpy(g_ws_esp8266_dma_tx_buffer, data, limited_size); g_ws_esp8266_dma_tx_buffer[limited_size] = 0x00; +#ifdef WS_DBG_PRINT_ESP_OVER_USART2 + uint8_t green[] = { 0x1b, 0x5b, 0x33, 0x32, 0x6d }; + HAL_UART_Transmit(&huart2, green, sizeof(green), 100); + HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, strlen((char*) g_ws_esp8266_dma_tx_buffer), 100); +#endif + HAL_UART_Transmit_DMA(&huart1, g_ws_esp8266_dma_tx_buffer, strlen((char*) g_ws_esp8266_dma_tx_buffer)); __HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE); } +void ws_esp8266_start_receive() { + HAL_UART_Receive_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); + __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); +} // TODO: refactor code from here to EOF void ws_esp8266_ATsendCommand(uint8_t* data){ diff --git a/stm32f091/esp8266.h b/stm32f091/esp8266.h index 0832e95..64910fd 100644 --- a/stm32f091/esp8266.h +++ b/stm32f091/esp8266.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "consts.h" @@ -21,12 +22,11 @@ void USART1_IRQHandler(void); /** @brief receive chunk complete */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart); -/** @brief send response to incoming request on specific channel */ -void ws_esp8266_res_send(unsigned int channel, uint8_t* data, size_t size); - /** @brief send data to esp over uart with dma */ void ws_esp8266_send(uint8_t* data, size_t size); +void ws_esp8266_start_receive(); + // TODO: remove/update/document/refactor these functions void ws_esp8266_ATsendCommand(uint8_t* data); int ws_esp8266_checkOK(uint8_t *receiveData,int length); diff --git a/stm32f091/server.c b/stm32f091/server.c index de6ea50..aa2ff8b 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -3,15 +3,77 @@ #include #include +#include "esp8266.h" #include "server.h" +#include "setup.h" +#include "consts.h" +static ws_s_server_parser g_ws_server_parser = { + .counter = 0, + .last_response = WS_SERVER_RC_NONE, + .mode = WS_SERVER_LM_IDLE, +}; + +// TODO: next_few_bytes_are assumes that the complete search string is in the +// buffer, so won't work for buffer cutoffs +#define next_few_bytes_are(code) (i + sizeof(code) - 1 < size && strncmp((char*)&data[i], code, sizeof(code) - 1) == 0) void ws_server_req_incoming(uint8_t* data, size_t size) { - // TODO: server req incoming implementation - // - // example +IPD command: - // +IPD,0,15:last-records 5\n - // - // TODO: protocol req response parser -> (ws_esp8622_at_send(data, channel) ?) +#ifdef WS_DBG_PRINT_ESP_OVER_USART2 + uint8_t red[] = { 0x1b, 0x5b, 0x33, 0x31, 0x6d }; + HAL_UART_Transmit(&huart2, red, sizeof(red), 100); + HAL_UART_Transmit(&huart2, data, size, 100); +#endif + + for (unsigned int i = 0; i < size; i++) { + uint8_t byte = data[i]; + + switch (g_ws_server_parser.mode) { + case WS_SERVER_LM_CMD_ECHO: { + if (byte == '\n') g_ws_server_parser.mode = WS_SERVER_LM_STATUS_CODE; + break; + } + case WS_SERVER_LM_STATUS_CODE: { + bool code_got = false; + if (next_few_bytes_are("OK")) { + code_got = true; + g_ws_server_parser.last_response = WS_SERVER_RC_OK; + } else if (next_few_bytes_are("ERROR")) { + code_got = true; + g_ws_server_parser.last_response = WS_SERVER_RC_ERR; + } else if (next_few_bytes_are("busy p...")) { + code_got = true; + g_ws_server_parser.last_response = WS_SERVER_RC_BUSY; + } + if (code_got) g_ws_server_parser.mode = WS_SERVER_LM_IDLE; + break; + } + case WS_SERVER_LM_IDLE: { + if (next_few_bytes_are("+IPD")) { + i += 3; // skip I, P, and D + g_ws_server_parser.mode = WS_SERVER_LM_IPD_LISTENING; + } + break; + } + case WS_SERVER_LM_IPD_LISTENING: { + // +IPD,0,15:last-records 5\n + break; + } + default: {} + } + } return; } + +void ws_server_send(uint8_t* data, size_t size) { + g_ws_server_parser.mode = WS_SERVER_LM_CMD_ECHO; + ws_esp8266_send(data, size); + while (g_ws_server_parser.mode != WS_SERVER_LM_IDLE) {}; +} + +void ws_server_req_respond(unsigned int channel, uint8_t* data, size_t size) { + uint8_t Tx_close[]="AT+CIPCLOSE=0\r\n"; + uint8_t Tx_send[]="AT+CIPSEND=0,LEN:"; + return; +} + diff --git a/stm32f091/server.h b/stm32f091/server.h index 6041ef6..c5698c0 100644 --- a/stm32f091/server.h +++ b/stm32f091/server.h @@ -2,6 +2,27 @@ #include #include +#include + +typedef enum { + WS_SERVER_LM_CMD_ECHO, /** @brief listen for echo of sent command */ + WS_SERVER_LM_STATUS_CODE, /** @brief listen for busy, ERROR or OK */ + WS_SERVER_LM_IDLE, /** @brief listen for incoming +IPD commands */ + WS_SERVER_LM_IPD_LISTENING, /** @brief +IPD received, now reading data */ +} ws_e_server_listen_mode; + +typedef enum { + WS_SERVER_RC_NONE = -1, + WS_SERVER_RC_BUSY, + WS_SERVER_RC_ERR, + WS_SERVER_RC_OK, +} ws_e_server_response_code; + +typedef struct { + int counter; + ws_e_server_listen_mode mode; + ws_e_server_response_code last_response; +} ws_s_server_parser; /** * @brief +IPD incoming request handler @@ -15,3 +36,9 @@ */ void ws_server_req_incoming(uint8_t* data, size_t size); +/** @brief send response to incoming request on specific channel */ +void ws_server_req_respond(unsigned int channel, uint8_t* data, size_t size); + +/** @brief send data to esp, waiting until server returns to idle mode */ +void ws_server_send(uint8_t* data, size_t size); + diff --git a/stm32f091/setup.c b/stm32f091/setup.c index 2110e03..9ed4174 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -133,12 +133,15 @@ static void ws_io_usart1_setup() { HAL_UART_Receive_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); + + __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); // enable receive intterupts + __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // enable idle line detection } static void ws_io_usart2_setup() { if (HAL_UART_Init(&huart2) != HAL_OK) return ws_setup_error_handler(); -} +} static void ws_io_dma_setup() { __HAL_RCC_DMA1_CLK_ENABLE(); diff --git a/stm32f091/test.c b/stm32f091/test.c index e25b071..c5e43da 100644 --- a/stm32f091/test.c +++ b/stm32f091/test.c @@ -2,13 +2,18 @@ #include #include -#include "esp8266.h" +#include "server.h" +#include "setup.h" void ws_test_write_task() { - uint8_t data[] = "AT\r\n"; + // uint8_t data[] = "AT+CIPMUX=1+CWMODE=1+CWJAP=\"" WS_ESP8266_WLAN_SSID "\",\"" WS_ESP8266_WLAN_PASSWD "\"\r\n"; + uint8_t cmd1[] = "AT+CIPMUX=1\r\n"; + uint8_t cmd2[] = "AT+CWMODE=1\r\n"; + uint8_t cmd3[] = "AT+CWJAP=\"" WS_ESP8266_WLAN_SSID "\",\"" WS_ESP8266_WLAN_PASSWD "\"\r\n"; while (1) { - ws_esp8266_send(data, sizeof(data)); - - vTaskDelay(portTICK_PERIOD_MS * 100 * 1); + ws_server_send(cmd1, sizeof(cmd1)); + ws_server_send(cmd2, sizeof(cmd2)); + ws_server_send(cmd3, sizeof(cmd3)); + vTaskDelay(portTICK_PERIOD_MS * 1000 * 1); } } -- cgit v1.2.3 From ea748e6c6e268ec46924ac4e3b9436e094668541 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 27 Oct 2022 16:09:00 +0200 Subject: add dummy server script --- scripts/dummy-server.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100755 scripts/dummy-server.py diff --git a/scripts/dummy-server.py b/scripts/dummy-server.py new file mode 100755 index 0000000..9350cab --- /dev/null +++ b/scripts/dummy-server.py @@ -0,0 +1,48 @@ +#!/bin/python3 + +""" +this is a garbage python script that opens a tcp socket on localhost:33 for +connecting with the qt client +""" + +import socketserver +from random import randint + +def hexpad(n, pad): + return hex(n)[2:].zfill(pad) + +def bs(str): + return bytes(str, 'utf-8') + +def r(max): + return randint(0, max) + +class DummyServer(socketserver.BaseRequestHandler): + def error(self): + self.request.sendall(bs("error\n")) + + def ok(self, rows): + response = "id,temperature,humidity,atmospheric_pressure\n" + line_len = len("xxxx,xx,xx,xx\n") + retstr = f"ok,{hex(len(response) + rows * line_len)[2:]}\n" + retstr += response + for row in range(rows): + retstr += f"{hexpad(row, 4)},{hexpad(r(0xff), 2)},{hexpad(r(0xff), 2)},{hexpad(r(0xff), 2)}\n" + self.request.sendall(bs(retstr)) + + def handle(self): + self.data = self.request.recv(1024).strip() + if len(self.data) > 40: return self.error() + if not self.data.startswith(bs('last-records')): return self.error() + self.data = self.data.replace(bs('last-records'), bs('')) + try: + self.ok(int(self.data)) + except ValueError: + self.error() + +if __name__ == "__main__": + socketserver.TCPServer.allow_reuse_address = True + with socketserver.TCPServer(("localhost", 33), DummyServer) as server: + server.serve_forever() + + -- cgit v1.2.3 From 12704850c9f4cf7410ecf85116da9d23fc2ce6d6 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 27 Oct 2022 16:50:01 +0200 Subject: server to protocol code --- stm32f091/consts.h | 1 + stm32f091/server.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++----- stm32f091/server.h | 34 ++++++++++++++++++++++++- stm32f091/test.c | 1 - 4 files changed, 101 insertions(+), 8 deletions(-) diff --git a/stm32f091/consts.h b/stm32f091/consts.h index b3bc2e2..0a8acec 100644 --- a/stm32f091/consts.h +++ b/stm32f091/consts.h @@ -3,6 +3,7 @@ #include "wifi.h" #define WS_SERVER_PORT "80" +#define WS_SERVER_MAX_CHANNELS 2 #define WS_DMA_RX_BUFFER_SIZE 100 #define WS_DMA_TX_BUFFER_SIZE 100 diff --git a/stm32f091/server.c b/stm32f091/server.c index aa2ff8b..a06727c 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -3,17 +3,46 @@ #include #include +#include "../shared/protocol.h" #include "esp8266.h" #include "server.h" #include "setup.h" #include "consts.h" static ws_s_server_parser g_ws_server_parser = { - .counter = 0, .last_response = WS_SERVER_RC_NONE, .mode = WS_SERVER_LM_IDLE, + + .current_channel = 0, + .channel_data_length = 0, + .channel_data_counter = 0, + .channel_listen_mode = WS_SERVER_CL_DATA_LENGTH, }; +static ws_s_protocol_req_parser_state* g_ws_protocol_parsers[WS_SERVER_MAX_CHANNELS] = {0}; + + +void ws_server_req_parse_byte(unsigned int channel, uint8_t byte, bool ignore) { + if (ignore) return; + if (channel >= WS_SERVER_MAX_CHANNELS) return; + + if (g_ws_protocol_parsers[channel] == NULL) { + g_ws_protocol_parsers[channel] = ws_protocol_req_parser_alloc(); + } + + ws_protocol_parse_req_byte(g_ws_protocol_parsers[channel], byte); +} + +void ws_server_req_finish(unsigned int channel, bool ignore) { + if (ignore) return; + if (channel >= WS_SERVER_MAX_CHANNELS) return; + + if (g_ws_protocol_parsers[channel] != NULL) { + ws_protocol_req_parser_free(g_ws_protocol_parsers[channel]); + g_ws_protocol_parsers[channel] = NULL; + } +} + // TODO: next_few_bytes_are assumes that the complete search string is in the // buffer, so won't work for buffer cutoffs #define next_few_bytes_are(code) (i + sizeof(code) - 1 < size && strncmp((char*)&data[i], code, sizeof(code) - 1) == 0) @@ -37,7 +66,7 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { if (next_few_bytes_are("OK")) { code_got = true; g_ws_server_parser.last_response = WS_SERVER_RC_OK; - } else if (next_few_bytes_are("ERROR")) { + } else if (next_few_bytes_are("ERROR") || next_few_bytes_are("FAIL")) { code_got = true; g_ws_server_parser.last_response = WS_SERVER_RC_ERR; } else if (next_few_bytes_are("busy p...")) { @@ -55,14 +84,46 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { break; } case WS_SERVER_LM_IPD_LISTENING: { - // +IPD,0,15:last-records 5\n + switch (g_ws_server_parser.channel_listen_mode) { + case WS_SERVER_CL_CHANNEL_ID: { + if (byte == ',') { + g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_DATA_LENGTH; + break; + } + g_ws_server_parser.current_channel *= 10; + g_ws_server_parser.current_channel += byte - '0'; // ascii to int + break; + } + case WS_SERVER_CL_DATA_LENGTH: { + if (byte == ':') { + g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_DATA_READ; + if (g_ws_server_parser.channel_data_length > WS_PROTOCOL_CMD_BUFFER_LEN) + g_ws_server_parser.channel_data_ignore = true; + break; + } + g_ws_server_parser.current_channel *= 10; + g_ws_server_parser.current_channel += byte - '0'; // ascii to int + break; + } + case WS_SERVER_CL_DATA_READ: { + ws_server_req_parse_byte(g_ws_server_parser.current_channel, byte, g_ws_server_parser.channel_data_ignore); + g_ws_server_parser.channel_data_counter++; + if (g_ws_server_parser.channel_data_counter == g_ws_server_parser.channel_data_length) { + g_ws_server_parser.current_channel = 0; + g_ws_server_parser.channel_data_counter = 0; + g_ws_server_parser.channel_data_length = 0; + g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_CHANNEL_ID; + ws_server_req_finish(g_ws_server_parser.current_channel, g_ws_server_parser.channel_data_ignore); + } + break; + } + default: {} + } break; } default: {} } } - - return; } void ws_server_send(uint8_t* data, size_t size) { @@ -72,8 +133,8 @@ void ws_server_send(uint8_t* data, size_t size) { } void ws_server_req_respond(unsigned int channel, uint8_t* data, size_t size) { - uint8_t Tx_close[]="AT+CIPCLOSE=0\r\n"; uint8_t Tx_send[]="AT+CIPSEND=0,LEN:"; + uint8_t Tx_close[]="AT+CIPCLOSE=0\r\n"; return; } diff --git a/stm32f091/server.h b/stm32f091/server.h index c5698c0..44882e4 100644 --- a/stm32f091/server.h +++ b/stm32f091/server.h @@ -11,6 +11,12 @@ typedef enum { WS_SERVER_LM_IPD_LISTENING, /** @brief +IPD received, now reading data */ } ws_e_server_listen_mode; +typedef enum { + WS_SERVER_CL_CHANNEL_ID, /** @brief listen channel id */ + WS_SERVER_CL_DATA_LENGTH, /** @brief listen for data byte length */ + WS_SERVER_CL_DATA_READ, /** @brief listen for data and pipe to ws_protocol_parse_req_byte */ +} ws_e_channel_listen_mode; + typedef enum { WS_SERVER_RC_NONE = -1, WS_SERVER_RC_BUSY, @@ -19,9 +25,13 @@ typedef enum { } ws_e_server_response_code; typedef struct { - int counter; ws_e_server_listen_mode mode; ws_e_server_response_code last_response; + unsigned int current_channel; + unsigned int channel_data_length; + unsigned int channel_data_counter; + ws_e_channel_listen_mode channel_listen_mode; + bool channel_data_ignore; } ws_s_server_parser; /** @@ -42,3 +52,25 @@ void ws_server_req_respond(unsigned int channel, uint8_t* data, size_t size); /** @brief send data to esp, waiting until server returns to idle mode */ void ws_server_send(uint8_t* data, size_t size); +/** + * @brief parse byte from channel + * + * automatically creates parser struct and passes data onto protocol parser + * functions + * + * @param channel request channel + * @param byte data byte + * @param ignore ignore mode + */ +void ws_server_req_parse_byte(unsigned int channel, uint8_t byte, bool ignore); + +/** + * @brief close connection + * + * deallocates any parser struct that were automatically created in + * ws_server_req_parse_byte + * + * @param channel request channel + * @param ignore ignore mode + */ +void ws_server_req_finish(unsigned int channel, bool ignore); diff --git a/stm32f091/test.c b/stm32f091/test.c index c5e43da..ae48ef7 100644 --- a/stm32f091/test.c +++ b/stm32f091/test.c @@ -6,7 +6,6 @@ #include "setup.h" void ws_test_write_task() { - // uint8_t data[] = "AT+CIPMUX=1+CWMODE=1+CWJAP=\"" WS_ESP8266_WLAN_SSID "\",\"" WS_ESP8266_WLAN_PASSWD "\"\r\n"; uint8_t cmd1[] = "AT+CIPMUX=1\r\n"; uint8_t cmd2[] = "AT+CWMODE=1\r\n"; uint8_t cmd3[] = "AT+CWJAP=\"" WS_ESP8266_WLAN_SSID "\",\"" WS_ESP8266_WLAN_PASSWD "\"\r\n"; -- cgit v1.2.3 From dd1d0cf34a44f70793dcb52fd9ef90d9274b55d1 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 27 Oct 2022 17:42:54 +0200 Subject: move esp setup to setup.c --- stm32f091/esp8266.c | 205 +++++++-------------------------------------------- stm32f091/esp8266.h | 23 +++--- stm32f091/main.c | 5 +- stm32f091/server.c | 4 +- stm32f091/setup.c | 10 +++ stm32f091/test.c | 18 ----- stm32f091/test.h | 3 - stm32f091/wifi.def.h | 2 + 8 files changed, 54 insertions(+), 216 deletions(-) delete mode 100644 stm32f091/test.c delete mode 100644 stm32f091/test.h diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index c98528e..d45954e 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -10,6 +10,12 @@ #include "server.h" #include "util.h" +// macro for concise sending of multiple commands +#define ws_esp8266_send_seq(cmd) { \ + uint8_t _cmd[] = cmd; \ + ws_server_send(_cmd, sizeof(_cmd)); \ +} + uint8_t g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; uint8_t g_ws_esp8266_dma_tx_buffer[WS_DMA_TX_BUFFER_SIZE]; @@ -53,6 +59,28 @@ void ws_esp8266_start_receive() { __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); } +void ws_esp8266_connect() { + ws_esp8266_send_seq("AT+CWJAP=\"" WS_ESP8266_WLAN_SSID "\",\"" WS_ESP8266_WLAN_PASSWD "\"\r\n"); +} + +void ws_esp8266_ap_client_mode() { + ws_esp8266_send_seq("AT+CWMODE=1\r\n"); +} + +void ws_esp8266_start_tcp_server() { + ws_esp8266_send_seq("AT+CIPSERVER=0\r\n"); + ws_esp8266_send_seq("AT+CIPMUX=1\r\n"); + ws_esp8266_send_seq("AT+CIPSERVER=1," WS_SERVER_PORT "\r\n"); +} + +void ws_esp8266_set_mac() { + ws_esp8266_send_seq("AT+CIPSTAMAC=\"" WS_ESP8266_WLAN_MAC "\"\r\n"); +} + +void ws_esp8266_set_ip() { + ws_esp8266_send_seq("AT+CIPSTA=\"" WS_ESP8266_WLAN_IP "\"\r\n"); +} + // TODO: refactor code from here to EOF void ws_esp8266_ATsendCommand(uint8_t* data){ char dataChar[20]; @@ -68,183 +96,6 @@ void ws_esp8266_ATsendCommand(uint8_t* data){ HAL_UART_Transmit(&huart2, data, strlen((char*)data),1000); HAL_Delay(5000); } -int ws_esp8266_checkOK(uint8_t *receiveData,int length){ - char *ret=""; - // char *ret1=""; - HAL_UART_Transmit(&huart2, receiveData,length,1000); - ret = strstr((char*)receiveData,"OK"); - // ret = strstr((char*)receiveData,"change"); - // memset(receiveData,0,30); - if((ret[0]='O') && (ret[1]=='K')){ - //HAL_UART_Transmit(&huart2, (uint8_t*)ret, sizeof(ret), 100); - return 1; - - } -// else if((ret1[0]='c') && (ret1[1]=='h')){ -// //HAL_UART_Transmit(&huart2, (uint8_t*)ret, sizeof(ret), 100); -// return 1; -// -// } - else{ - return 0; - } - -} -int ws_esp8266_receivingMsg(uint8_t *receiveData,int length){ - char *ret=""; - HAL_UART_Transmit(&huart2, receiveData,length,1000); - ret = strstr((char*)receiveData,"+IPD"); - // memset(receiveData,0,30); - - if((ret[0]='+') && (ret[1]=='I')){ - //HAL_UART_Transmit(&huart2, (uint8_t*)ret, sizeof(ret), 100); - return 1; - - } - else{ - return 0; - } - -} -int ws_esp8266_unlink(uint8_t *receiveData,int length){ - char *ret=""; - HAL_UART_Transmit(&huart2, receiveData,length,1000); - ret = strstr((char*)receiveData,"UNLINK"); - // memset(receiveData,0,30); - if((ret[0]='U') && (ret[1]=='N')){ - //HAL_UART_Transmit(&huart2, (uint8_t*)ret, sizeof(ret), 100); - return 1; - - } - else{ - return 0; - } - -} - -void ws_esp8266_StartEsp(){ - uint8_t Tx_AT[]="AT\r\n"; - uint8_t Rx_buffer[10]={0}; - for(int i=0;i<3;i++){ - // HAL_UART_Transmit(&huart2, hier,sizeof(hier),100); - HAL_UART_Transmit(&huart1, Tx_AT,strlen((char*)Tx_AT), 100); - HAL_UART_Receive(&huart1, Rx_buffer, 10, 100); - - - HAL_UART_Transmit(&huart2, Rx_buffer,10,100); - HAL_Delay(5000); - //memset(Rx_buffer,0,sizeof(Rx_buffer)); - } - -} -void ws_esp8266_disconnect(){ - int ret; - uint8_t Tx_disconnect[]="AT+CWQAP\r\n";uint8_t buffer[17]={0}; - while(ret!=1){ - - HAL_UART_Transmit(&huart1, Tx_disconnect,strlen((char*)Tx_disconnect), 100); - HAL_UART_Receive(&huart1, buffer, 17, 100); - HAL_Delay(2000); - - if(ws_esp8266_checkOK(buffer,17)==1){ - ret=1; - } - - } - - HAL_Delay(5000); -} -void ws_esp8266_mode(){ - int ret; - uint8_t buffer1[20]={0}; uint8_t Tx_mode[]="AT+CWMODE=1\r\n"; - - while(ret!=1){ - - HAL_UART_Transmit(&huart1, Tx_mode,strlen((char*)Tx_mode), 100); - HAL_UART_Receive(&huart1, buffer1, 20, 100); - HAL_Delay(1000); - - if(ws_esp8266_checkOK(buffer1,20)==1){ - ret=1; - - } - - } - - HAL_Delay(1000); -} -void ws_esp8266_connect(){ - uint8_t Tx_network[]="AT+CWJAP=\"" WS_ESP8266_WLAN_SSID "\",\"" WS_ESP8266_WLAN_PASSWD "\"\r\n"; - - - HAL_UART_Transmit(&huart1, Tx_network,strlen((char*)Tx_network),1000); - HAL_Delay(10000); -// HAL_UART_Transmit(&huart1, Tx_network,sizeof(Tx_network),1000); -// HAL_Delay(10000); - - - - - -} -void ws_esp8266_serveraan(){ - int ret; - uint8_t buffer1[30]={0}; uint8_t Tx_server[]="AT+CIPSERVER=1," WS_SERVER_PORT "\r\n"; - - while(ret!=1){ - - HAL_UART_Transmit(&huart1, Tx_server,strlen((char*)Tx_server), 100); - HAL_UART_Receive(&huart1, buffer1, 30, 100); - HAL_Delay(2000); - - if(ws_esp8266_checkOK(buffer1,30)==1){ - ret=1; - - } - - } - - HAL_Delay(1000); -} -void ws_esp8266_serveruit(){ - //int ret; - //uint8_t buffer1[27]={0}; - uint8_t Tx_server[]="AT+CIPSERVER=0\r\n"; -// -// while(ret!=1){ - - HAL_UART_Transmit(&huart1, Tx_server,strlen((char*)Tx_server), 100); -// HAL_UART_Receive(&huart1, buffer1, 27, 100); - HAL_Delay(3000); - -// if(unlink(buffer1,27)==1){ -// ret=1; -// -// } -// -// } - - HAL_Delay(1000); -} -void ws_esp8266_mux(){ - int ret; - uint8_t buffer2[20]={0}; uint8_t Tx_mux[]="AT+CIPMUX=1\r\n"; - - while(ret!=1){ - - HAL_UART_Transmit(&huart1, Tx_mux,strlen((char*)Tx_mux), 100); - HAL_UART_Receive(&huart1, buffer2, 20, 100); - HAL_Delay(2000); - - if(ws_esp8266_checkOK(buffer2,20)==1){ - ret=1; - - } - - } - - HAL_Delay(5000); -} void ws_esp8266_close(){ uint8_t Tx_close[]="AT+CIPCLOSE=0\r\n"; diff --git a/stm32f091/esp8266.h b/stm32f091/esp8266.h index 64910fd..66ccfba 100644 --- a/stm32f091/esp8266.h +++ b/stm32f091/esp8266.h @@ -25,18 +25,17 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart); /** @brief send data to esp over uart with dma */ void ws_esp8266_send(uint8_t* data, size_t size); +/** @brief start dma receive and reset half-transfer interrupt flag */ void ws_esp8266_start_receive(); -// TODO: remove/update/document/refactor these functions -void ws_esp8266_ATsendCommand(uint8_t* data); -int ws_esp8266_checkOK(uint8_t *receiveData,int length); -int ws_esp8266_receivingMsg(uint8_t *receiveData,int length); -int ws_esp8266_unlink(uint8_t *receiveData,int length); -void ws_esp8266_StartEsp(); -void ws_esp8266_disconnect(); -void ws_esp8266_mode(); +/** @brief connect to access point using wifi.h credentials */ void ws_esp8266_connect(); -void ws_esp8266_serveraan(); -void ws_esp8266_serveruit(); -void ws_esp8266_mux(); -void ws_esp8266_close(); +/** @brief set esp to access point client mode (connect to AP, not become one) */ +void ws_esp8266_ap_client_mode(); +/** @brief initialize and configure the tcp server */ +void ws_esp8266_start_tcp_server(); + +/** @brief set mac address of the esp client */ +void ws_esp8266_set_mac(); +/** @brief set static ip address of the esp client */ +void ws_esp8266_set_ip(); diff --git a/stm32f091/main.c b/stm32f091/main.c index 80eb5a7..67c0a8d 100644 --- a/stm32f091/main.c +++ b/stm32f091/main.c @@ -6,11 +6,8 @@ #include "setup.h" #include "sensor.h" -#include "test.h" - int main() { ws_io_setup(); - // xTaskCreate(ws_sensor_read_task, "sensor", 64, NULL, 1, NULL); - xTaskCreate(ws_test_write_task, "test", 16, NULL, 2, NULL); + xTaskCreate(ws_sensor_read_task, "sensor", 64, NULL, 1, NULL); vTaskStartScheduler(); } diff --git a/stm32f091/server.c b/stm32f091/server.c index a06727c..1b677c2 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -77,8 +77,8 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { break; } case WS_SERVER_LM_IDLE: { - if (next_few_bytes_are("+IPD")) { - i += 3; // skip I, P, and D + if (next_few_bytes_are("+IPD,")) { + i += 4; // skip I, P, D, and comma g_ws_server_parser.mode = WS_SERVER_LM_IPD_LISTENING; } break; diff --git a/stm32f091/setup.c b/stm32f091/setup.c index 9ed4174..2175ab3 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -91,6 +91,16 @@ void ws_io_setup() { }); ws_backlog_alloc(24 * 60); + +#ifdef WS_ESP8266_WLAN_MAC + ws_esp8266_set_mac(); +#endif +#ifdef WS_ESP8266_WLAN_IP + ws_esp8266_set_ip(); +#endif + ws_esp8266_ap_client_mode(); + ws_esp8266_connect(); + ws_esp8266_start_tcp_server(); } static void ws_io_clock_setup() { diff --git a/stm32f091/test.c b/stm32f091/test.c deleted file mode 100644 index ae48ef7..0000000 --- a/stm32f091/test.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include - -#include "server.h" -#include "setup.h" - -void ws_test_write_task() { - uint8_t cmd1[] = "AT+CIPMUX=1\r\n"; - uint8_t cmd2[] = "AT+CWMODE=1\r\n"; - uint8_t cmd3[] = "AT+CWJAP=\"" WS_ESP8266_WLAN_SSID "\",\"" WS_ESP8266_WLAN_PASSWD "\"\r\n"; - while (1) { - ws_server_send(cmd1, sizeof(cmd1)); - ws_server_send(cmd2, sizeof(cmd2)); - ws_server_send(cmd3, sizeof(cmd3)); - vTaskDelay(portTICK_PERIOD_MS * 1000 * 1); - } -} diff --git a/stm32f091/test.h b/stm32f091/test.h deleted file mode 100644 index dffa516..0000000 --- a/stm32f091/test.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void ws_test_write_task(); diff --git a/stm32f091/wifi.def.h b/stm32f091/wifi.def.h index f0748d2..61e1706 100644 --- a/stm32f091/wifi.def.h +++ b/stm32f091/wifi.def.h @@ -2,4 +2,6 @@ #define WS_ESP8266_WLAN_SSID "Test" #define WS_ESP8266_WLAN_PASSWD "12345678" +// #define WS_ESP8266_WLAN_MAC "f2:9b:89:47:c4:f3" +// #define WS_ESP8266_WLAN_IP "192.168.2.69" -- cgit v1.2.3 From 89e652af2506f7cf7854ce2e6f5b9b97423d1d40 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 27 Oct 2022 18:33:43 +0200 Subject: fix dumb typo's and added comments to faulty code --- shared/protocol.c | 5 ++++- stm32f091/server.c | 6 +++--- stm32f091/setup.c | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/shared/protocol.c b/shared/protocol.c index c6e5ddd..ca0edc4 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -99,7 +99,10 @@ ws_s_protocol_req_parser_state* ws_protocol_req_parser_alloc() { void ws_protocol_req_cmd_init(ws_s_protocol_req_parser_state* state) { state->target = malloc(sizeof(ws_s_protocol_parsed_req_cmd) + sizeof(char*) * state->arg_len); for (unsigned int i = 0; i < state->arg_len; i++) - state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); + state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); // segfaults on 2nd run? + // state->target->argv stays empty according to debugger + // goes to HardFault_Handler on 2nd iteration + // this might be the stm running out of heap memory though i'm not sure state->target->argc = state->arg_len; diff --git a/stm32f091/server.c b/stm32f091/server.c index 1b677c2..7e44774 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -16,7 +16,7 @@ static ws_s_server_parser g_ws_server_parser = { .current_channel = 0, .channel_data_length = 0, .channel_data_counter = 0, - .channel_listen_mode = WS_SERVER_CL_DATA_LENGTH, + .channel_listen_mode = WS_SERVER_CL_CHANNEL_ID, }; static ws_s_protocol_req_parser_state* g_ws_protocol_parsers[WS_SERVER_MAX_CHANNELS] = {0}; @@ -101,8 +101,8 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { g_ws_server_parser.channel_data_ignore = true; break; } - g_ws_server_parser.current_channel *= 10; - g_ws_server_parser.current_channel += byte - '0'; // ascii to int + g_ws_server_parser.channel_data_length *= 10; + g_ws_server_parser.channel_data_length += byte - '0'; // ascii to int break; } case WS_SERVER_CL_DATA_READ: { diff --git a/stm32f091/setup.c b/stm32f091/setup.c index 2175ab3..5b6c6a4 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -90,7 +90,9 @@ void ws_io_setup() { .Pull = GPIO_NOPULL }); + // TODO: remove debug size ws_backlog_alloc(24 * 60); + // ws_backlog_alloc(10); #ifdef WS_ESP8266_WLAN_MAC ws_esp8266_set_mac(); -- cgit v1.2.3 From 1cac46e7701ef2783aea13d55261582f4d91f2fa Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 28 Oct 2022 09:57:50 +0200 Subject: working janky protocol! --- shared/protocol.c | 14 ++++++++++---- shared/protocol.h | 3 ++- shared/util.c | 7 +++++++ shared/util.h | 2 ++ stm32f091/esp8266.c | 27 -------------------------- stm32f091/protocol.c | 8 ++++++-- stm32f091/server.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++------ stm32f091/server.h | 13 +++++++++++-- stm32f091/setup.c | 3 ++- 9 files changed, 88 insertions(+), 43 deletions(-) create mode 100644 shared/util.c diff --git a/shared/protocol.c b/shared/protocol.c index ca0edc4..fcc84a4 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -3,6 +3,7 @@ #include #include "protocol.h" +#include "util.h" #define WS_CMD_MAP(parsed_cmd, name, code) \ if (strlen(parsed_cmd->argv[0]) == strlen(name) && strncmp(parsed_cmd->argv[0], name, strlen(name)) == 0) return code; @@ -99,10 +100,7 @@ ws_s_protocol_req_parser_state* ws_protocol_req_parser_alloc() { void ws_protocol_req_cmd_init(ws_s_protocol_req_parser_state* state) { state->target = malloc(sizeof(ws_s_protocol_parsed_req_cmd) + sizeof(char*) * state->arg_len); for (unsigned int i = 0; i < state->arg_len; i++) - state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); // segfaults on 2nd run? - // state->target->argv stays empty according to debugger - // goes to HardFault_Handler on 2nd iteration - // this might be the stm running out of heap memory though i'm not sure + state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); state->target->argc = state->arg_len; @@ -138,3 +136,11 @@ void ws_protocol_req_cmd_free(ws_s_protocol_parsed_req_cmd* cmd) { free(cmd); return; } + +unsigned short ws_protocol_get_header_size(ws_s_protocol_res* response) { + unsigned short size = 2; // comma and trailing newline + if (response->success == WS_PROTOCOL_CMD_RETURN_OK) size += 2; // ok + if (response->success == WS_PROTOCOL_CMD_RETURN_ERROR) size += 5; // error + size += ws_log16(response->msg->bytes); // amount of characters for message size (hex) + return size; +} \ No newline at end of file diff --git a/shared/protocol.h b/shared/protocol.h index fbe29d6..5bcb114 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -5,7 +5,7 @@ #include "bin.h" -#define WS_PROTOCOL_CMD_MAX_ARGUMENTS (1) +#define WS_PROTOCOL_CMD_MAX_ARGUMENTS (2) #define WS_PROTOCOL_CMD_BUFFER_LEN (40) #define WS_PROTOCOL_CMD_AMOUNT (1) @@ -148,3 +148,4 @@ static ws_protocol_res_handler_t* g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMO [WS_PROTOCOL_CMD_LAST_RECORDS] = &ws_protocol_res_last_records, }; +unsigned short ws_protocol_get_header_size(ws_s_protocol_res* response); \ No newline at end of file diff --git a/shared/util.c b/shared/util.c new file mode 100644 index 0000000..ea972b0 --- /dev/null +++ b/shared/util.c @@ -0,0 +1,7 @@ +#include "util.h" + +unsigned int ws_log16(unsigned int x) { + unsigned int l = 0; + while (x >>= 4) ++l; // bitshift right by 4 until x == 0 + return l; +} \ No newline at end of file diff --git a/shared/util.h b/shared/util.h index f39ff34..94a3dfe 100644 --- a/shared/util.h +++ b/shared/util.h @@ -2,3 +2,5 @@ #define WS_MIN(a, b) (((a) < (b)) ? (a) : (b)) #define WS_MAX(a, b) (((a) > (b)) ? (a) : (b)) + +unsigned int ws_log16(unsigned int x); diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index d45954e..db134a0 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -80,30 +80,3 @@ void ws_esp8266_set_mac() { void ws_esp8266_set_ip() { ws_esp8266_send_seq("AT+CIPSTA=\"" WS_ESP8266_WLAN_IP "\"\r\n"); } - -// TODO: refactor code from here to EOF -void ws_esp8266_ATsendCommand(uint8_t* data){ - char dataChar[20]; - uint8_t Tx_send[]="AT+CIPSEND=0,"; - - itoa(strlen((char*)data),dataChar,10); - strcat((char*)Tx_send,dataChar); - strcat((char*)Tx_send,"\r\n"); - HAL_UART_Transmit(&huart1, Tx_send, strlen((char*)Tx_send),1000); - HAL_Delay(2000); - HAL_UART_Transmit(&huart1, data, strlen((char*)data),1000); - HAL_Delay(1000); - HAL_UART_Transmit(&huart2, data, strlen((char*)data),1000); - HAL_Delay(5000); -} -void ws_esp8266_close(){ - - uint8_t Tx_close[]="AT+CIPCLOSE=0\r\n"; - - - HAL_UART_Transmit(&huart1, Tx_close,strlen((char*)Tx_close), 100); - - HAL_Delay(3000); - -} - diff --git a/stm32f091/protocol.c b/stm32f091/protocol.c index 589ee5d..3a8d78b 100644 --- a/stm32f091/protocol.c +++ b/stm32f091/protocol.c @@ -3,6 +3,8 @@ #include "../shared/protocol.h" #include "backlog.h" #include "util.h" +#include "server.h" +#include "esp8266.h" void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response, bool send) { static unsigned int record_amount = 0; @@ -16,6 +18,7 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s response->csh = true; response->msg = ws_bin_s_alloc(0); response->msg->bytes = strlen(response_header) + response_line_size * record_amount; + ws_server_req_respond_start(0, response->msg->bytes + ws_protocol_get_header_size(response)); } else { ws_protocol_send_data(response_header, strlen(response_header)); char line[response_line_size + 1]; // +1 for null terminator -> sprintf @@ -24,10 +27,11 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s sprintf(line, "%04x,%02x,%02x,%02x\n", record->id, record->sens_temperature, record->sens_humidity, record->sens_atm_pressure); ws_protocol_send_data(line, response_line_size); } + ws_protocol_send_data("\r\n", 2); // test } } void ws_protocol_send_data(const char* data, unsigned int length) { - //TODO: implement on esp data channels - HAL_UART_Transmit(&huart2, (uint8_t*) data, length, HAL_MAX_DELAY); + ws_server_buffer_send_append((uint8_t*) data, length); + // HAL_UART_Transmit(&huart1, (uint8_t*) data, length, HAL_MAX_DELAY); } diff --git a/stm32f091/server.c b/stm32f091/server.c index 7e44774..d4f7e20 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -9,7 +9,7 @@ #include "setup.h" #include "consts.h" -static ws_s_server_parser g_ws_server_parser = { +ws_s_server_parser g_ws_server_parser = { .last_response = WS_SERVER_RC_NONE, .mode = WS_SERVER_LM_IDLE, @@ -20,7 +20,7 @@ static ws_s_server_parser g_ws_server_parser = { }; static ws_s_protocol_req_parser_state* g_ws_protocol_parsers[WS_SERVER_MAX_CHANNELS] = {0}; - +static unsigned int g_ws_esp8266_dma_tx_buffer_index = 0; void ws_server_req_parse_byte(unsigned int channel, uint8_t byte, bool ignore) { if (ignore) return; @@ -80,6 +80,9 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { if (next_few_bytes_are("+IPD,")) { i += 4; // skip I, P, D, and comma g_ws_server_parser.mode = WS_SERVER_LM_IPD_LISTENING; + } else if (byte == '>') { + g_ws_server_parser.mode = WS_SERVER_LM_CIPSEND_LISTENING; + ws_server_buffer_send_finish(); } break; } @@ -114,6 +117,7 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { g_ws_server_parser.channel_data_length = 0; g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_CHANNEL_ID; ws_server_req_finish(g_ws_server_parser.current_channel, g_ws_server_parser.channel_data_ignore); + g_ws_server_parser.mode = WS_SERVER_LM_IDLE; } break; } @@ -121,6 +125,14 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { } break; } + case WS_SERVER_LM_CIPSEND_LISTENING: { + if (next_few_bytes_are("SEND OK")) { + i += 6; + // g_ws_server_parser.mode = WS_SERVER_LM_IDLE; + ws_server_req_respond_end(0); + } + break; + } default: {} } } @@ -132,9 +144,39 @@ void ws_server_send(uint8_t* data, size_t size) { while (g_ws_server_parser.mode != WS_SERVER_LM_IDLE) {}; } -void ws_server_req_respond(unsigned int channel, uint8_t* data, size_t size) { - uint8_t Tx_send[]="AT+CIPSEND=0,LEN:"; - uint8_t Tx_close[]="AT+CIPCLOSE=0\r\n"; - return; +void ws_server_buffer_send_append(uint8_t* data, size_t size) { + // TODO: buffer overrun protection + // while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); // make sure buffer isn't used + strncpy((char*) &g_ws_esp8266_dma_tx_buffer[g_ws_esp8266_dma_tx_buffer_index], (char*) data, size); // append string + g_ws_esp8266_dma_tx_buffer_index += size; // shift head +} + +void ws_server_buffer_send_finish() { +#ifdef WS_DBG_PRINT_ESP_OVER_USART2 + uint8_t green[] = { 0x1b, 0x5b, 0x33, 0x32, 0x6d }; + HAL_UART_Transmit(&huart2, green, sizeof(green), 100); + HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, strlen((char*) g_ws_esp8266_dma_tx_buffer), 100); +#endif + + HAL_UART_Transmit_DMA(&huart1, g_ws_esp8266_dma_tx_buffer, strlen((char*) g_ws_esp8266_dma_tx_buffer)); + __HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE); + g_ws_esp8266_dma_tx_buffer_index = 0; + while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); +} + +void ws_server_req_respond_start(unsigned int channel, size_t size) { + char* cmd = NULL; + size_t len = asiprintf(&cmd, "AT+CIPSEND=%d,%d\r\n", channel, size); + g_ws_server_parser.mode = WS_SERVER_LM_CMD_ECHO; + ws_esp8266_send((uint8_t*) cmd, len); + while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); +} + +void ws_server_req_respond_end(unsigned int channel) { + char* cmd = NULL; + size_t len = asiprintf(&cmd, "AT+CIPCLOSE=%d\r\n", channel); + g_ws_server_parser.mode = WS_SERVER_LM_CMD_ECHO; + ws_esp8266_send((uint8_t*) cmd, len); + while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); } diff --git a/stm32f091/server.h b/stm32f091/server.h index 44882e4..128b579 100644 --- a/stm32f091/server.h +++ b/stm32f091/server.h @@ -9,6 +9,7 @@ typedef enum { WS_SERVER_LM_STATUS_CODE, /** @brief listen for busy, ERROR or OK */ WS_SERVER_LM_IDLE, /** @brief listen for incoming +IPD commands */ WS_SERVER_LM_IPD_LISTENING, /** @brief +IPD received, now reading data */ + WS_SERVER_LM_CIPSEND_LISTENING, /** @brief AT+CIPSEND sent, now reading data */ } ws_e_server_listen_mode; typedef enum { @@ -34,6 +35,9 @@ typedef struct { bool channel_data_ignore; } ws_s_server_parser; +/** @brief global server parser struct */ +extern ws_s_server_parser g_ws_server_parser; + /** * @brief +IPD incoming request handler * @@ -46,8 +50,10 @@ typedef struct { */ void ws_server_req_incoming(uint8_t* data, size_t size); -/** @brief send response to incoming request on specific channel */ -void ws_server_req_respond(unsigned int channel, uint8_t* data, size_t size); +/** @brief send AT response header for incoming request on specific channel */ +void ws_server_req_respond_start(unsigned int channel, size_t size); +/** @brief send AT tcp close on specific channel */ +void ws_server_req_respond_end(unsigned int channel); /** @brief send data to esp, waiting until server returns to idle mode */ void ws_server_send(uint8_t* data, size_t size); @@ -74,3 +80,6 @@ void ws_server_req_parse_byte(unsigned int channel, uint8_t byte, bool ignore); * @param ignore ignore mode */ void ws_server_req_finish(unsigned int channel, bool ignore); + +void ws_server_buffer_send_append(uint8_t* data, size_t size); +void ws_server_buffer_send_finish(); diff --git a/stm32f091/setup.c b/stm32f091/setup.c index 5b6c6a4..1971809 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -8,6 +8,7 @@ #include "esp8266.h" #include "setup.h" #include "backlog.h" +#include "server.h" I2C_HandleTypeDef hi2c1 = { .Instance = I2C1, @@ -101,7 +102,7 @@ void ws_io_setup() { ws_esp8266_set_ip(); #endif ws_esp8266_ap_client_mode(); - ws_esp8266_connect(); + do ws_esp8266_connect(); while (g_ws_server_parser.last_response == WS_SERVER_RC_ERR); ws_esp8266_start_tcp_server(); } -- cgit v1.2.3 From f37af779bb836faa7571b7d47036f36f71319aca Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 28 Oct 2022 11:29:09 +0200 Subject: use circular dma buffer for rx --- stm32f091/consts.h | 4 ++-- stm32f091/esp8266.c | 36 ++++++++++++++++++++++-------------- stm32f091/esp8266.h | 7 ++----- stm32f091/server.c | 3 +-- stm32f091/setup.c | 2 +- 5 files changed, 28 insertions(+), 24 deletions(-) diff --git a/stm32f091/consts.h b/stm32f091/consts.h index 0a8acec..3d2ef5a 100644 --- a/stm32f091/consts.h +++ b/stm32f091/consts.h @@ -3,10 +3,10 @@ #include "wifi.h" #define WS_SERVER_PORT "80" -#define WS_SERVER_MAX_CHANNELS 2 +#define WS_SERVER_MAX_CHANNELS 4 #define WS_DMA_RX_BUFFER_SIZE 100 -#define WS_DMA_TX_BUFFER_SIZE 100 +#define WS_DMA_TX_BUFFER_SIZE 1024 #define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9 #define WS_PINOUT_I2C_SDA_PORT GPIOB diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index db134a0..754b45b 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -17,6 +17,8 @@ } uint8_t g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; +unsigned int g_ws_esp8266_dma_rx_head = 0; +unsigned int g_ws_esp8266_dma_rx_tail = 0; uint8_t g_ws_esp8266_dma_tx_buffer[WS_DMA_TX_BUFFER_SIZE]; void DMA1_Ch1_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_rx); } @@ -24,19 +26,30 @@ void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_tx void USART1_IRQHandler(void) { if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) { __HAL_UART_CLEAR_IDLEFLAG(&huart1); - HAL_UART_RxCpltCallback(&huart1); - HAL_UART_DMAStop(&huart1); - ws_esp8266_start_receive(); + // https://stackoverflow.com/questions/71039052/hal-uartex-rxeventcallback-circular-dma-what-address-is-the-data + g_ws_esp8266_dma_rx_head = huart1.RxXferSize - huart1.hdmarx->Instance->CNDTR; + + ws_esp8266_incoming_data_chunk(); } HAL_UART_IRQHandler(&huart1); } -void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart) { - size_t len = strlen((char*) g_ws_esp8266_dma_rx_buffer); - if (len > 0) ws_server_req_incoming(g_ws_esp8266_dma_rx_buffer, len); - - memset(g_ws_esp8266_dma_rx_buffer, 0, WS_DMA_RX_BUFFER_SIZE); - ws_esp8266_start_receive(); +void ws_esp8266_incoming_data_chunk() { + if (g_ws_esp8266_dma_rx_head == g_ws_esp8266_dma_rx_tail) return; // no new data + if (g_ws_esp8266_dma_rx_head > g_ws_esp8266_dma_rx_tail) { + // read from tail until head + ws_server_req_incoming(&g_ws_esp8266_dma_rx_buffer[g_ws_esp8266_dma_rx_tail], + g_ws_esp8266_dma_rx_head - g_ws_esp8266_dma_rx_tail); + } else /* if (g_ws_esp8266_dma_rx_head < g_ws_esp8266_dma_rx_tail) */ { + // read from tail until end of buffer + ws_server_req_incoming(&g_ws_esp8266_dma_rx_buffer[g_ws_esp8266_dma_rx_tail], + WS_DMA_RX_BUFFER_SIZE - g_ws_esp8266_dma_rx_tail); + // read from buffer begin until head + ws_server_req_incoming(&g_ws_esp8266_dma_rx_buffer[0], // yes i know this looks dumb + g_ws_esp8266_dma_rx_head); + } + // finish read by shifting tail forward + g_ws_esp8266_dma_rx_tail = g_ws_esp8266_dma_rx_head; } void ws_esp8266_send(uint8_t* data, size_t size) { @@ -54,11 +67,6 @@ void ws_esp8266_send(uint8_t* data, size_t size) { __HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE); } -void ws_esp8266_start_receive() { - HAL_UART_Receive_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); - __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); -} - void ws_esp8266_connect() { ws_esp8266_send_seq("AT+CWJAP=\"" WS_ESP8266_WLAN_SSID "\",\"" WS_ESP8266_WLAN_PASSWD "\"\r\n"); } diff --git a/stm32f091/esp8266.h b/stm32f091/esp8266.h index 66ccfba..94a7356 100644 --- a/stm32f091/esp8266.h +++ b/stm32f091/esp8266.h @@ -19,14 +19,11 @@ void DMA1_Ch1_IRQHandler(void); /** @brief USART1 interrupt handler */ void USART1_IRQHandler(void); -/** @brief receive chunk complete */ -void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart); - /** @brief send data to esp over uart with dma */ void ws_esp8266_send(uint8_t* data, size_t size); -/** @brief start dma receive and reset half-transfer interrupt flag */ -void ws_esp8266_start_receive(); +/** @brief line idle, handle new data on dma buffer */ +void ws_esp8266_incoming_data_chunk(); /** @brief connect to access point using wifi.h credentials */ void ws_esp8266_connect(); diff --git a/stm32f091/server.c b/stm32f091/server.c index d4f7e20..8001380 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -127,9 +127,8 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { } case WS_SERVER_LM_CIPSEND_LISTENING: { if (next_few_bytes_are("SEND OK")) { - i += 6; - // g_ws_server_parser.mode = WS_SERVER_LM_IDLE; ws_server_req_respond_end(0); + // g_ws_server_parser.mode = WS_SERVER_LM_IDLE; } break; } diff --git a/stm32f091/setup.c b/stm32f091/setup.c index 1971809..3bf331f 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -53,7 +53,7 @@ DMA_HandleTypeDef hdma_usart1_rx = { .Init.MemInc = DMA_MINC_ENABLE, .Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE, .Init.MemDataAlignment = DMA_MDATAALIGN_BYTE, - .Init.Mode = DMA_NORMAL, + .Init.Mode = DMA_CIRCULAR, .Init.Priority = DMA_PRIORITY_LOW, }; -- cgit v1.2.3 From 4cd465332087e4ab12709f28fae55df10e1a1154 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 28 Oct 2022 12:14:50 +0200 Subject: add todo.md, fixed segfault in protocol.c, and fix response sending --- shared/protocol.c | 5 +++-- stm32f091/consts.h | 2 +- stm32f091/protocol.c | 13 +++++++------ stm32f091/server.c | 18 ++++++++++-------- stm32f091/todo.md | 10 ++++++++++ 5 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 stm32f091/todo.md diff --git a/shared/protocol.c b/shared/protocol.c index fcc84a4..e17a728 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -99,10 +99,11 @@ ws_s_protocol_req_parser_state* ws_protocol_req_parser_alloc() { void ws_protocol_req_cmd_init(ws_s_protocol_req_parser_state* state) { state->target = malloc(sizeof(ws_s_protocol_parsed_req_cmd) + sizeof(char*) * state->arg_len); - for (unsigned int i = 0; i < state->arg_len; i++) + unsigned int args = WS_MIN(state->arg_len, WS_PROTOCOL_CMD_MAX_ARGUMENTS); + for (unsigned int i = 0; i < args; i++) state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); - state->target->argc = state->arg_len; + state->target->argc = args; unsigned int head = 0; for (unsigned int i = 0; i < state->arg_len; i++) { diff --git a/stm32f091/consts.h b/stm32f091/consts.h index 3d2ef5a..955ceea 100644 --- a/stm32f091/consts.h +++ b/stm32f091/consts.h @@ -6,7 +6,7 @@ #define WS_SERVER_MAX_CHANNELS 4 #define WS_DMA_RX_BUFFER_SIZE 100 -#define WS_DMA_TX_BUFFER_SIZE 1024 +#define WS_DMA_TX_BUFFER_SIZE 100 #define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9 #define WS_PINOUT_I2C_SDA_PORT GPIOB diff --git a/stm32f091/protocol.c b/stm32f091/protocol.c index 3a8d78b..21e6527 100644 --- a/stm32f091/protocol.c +++ b/stm32f091/protocol.c @@ -13,19 +13,21 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s if (!send) { response->success = WS_PROTOCOL_CMD_RETURN_OK; - if (sscanf(parsed_cmd->argv[1], "%u", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; - record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); response->csh = true; response->msg = ws_bin_s_alloc(0); - response->msg->bytes = strlen(response_header) + response_line_size * record_amount; + response->msg->bytes = 0; + record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); + if (sscanf(parsed_cmd->argv[1], "%u", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; + else response->msg->bytes = strlen(response_header) + response_line_size * record_amount; ws_server_req_respond_start(0, response->msg->bytes + ws_protocol_get_header_size(response)); } else { + if (response->success == WS_PROTOCOL_CMD_RETURN_ERROR) return; ws_protocol_send_data(response_header, strlen(response_header)); - char line[response_line_size + 1]; // +1 for null terminator -> sprintf + char line[response_line_size]; for (unsigned int i = 0; i < record_amount; i++) { ws_s_backlog_record* record = ws_backlog_get_last_record(i); sprintf(line, "%04x,%02x,%02x,%02x\n", record->id, record->sens_temperature, record->sens_humidity, record->sens_atm_pressure); - ws_protocol_send_data(line, response_line_size); + ws_protocol_send_data(line, response_line_size - 1); // remove string terminator } ws_protocol_send_data("\r\n", 2); // test } @@ -33,5 +35,4 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s void ws_protocol_send_data(const char* data, unsigned int length) { ws_server_buffer_send_append((uint8_t*) data, length); - // HAL_UART_Transmit(&huart1, (uint8_t*) data, length, HAL_MAX_DELAY); } diff --git a/stm32f091/server.c b/stm32f091/server.c index 8001380..1419da8 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -20,7 +20,7 @@ ws_s_server_parser g_ws_server_parser = { }; static ws_s_protocol_req_parser_state* g_ws_protocol_parsers[WS_SERVER_MAX_CHANNELS] = {0}; -static unsigned int g_ws_esp8266_dma_tx_buffer_index = 0; +static unsigned int g_ws_esp8266_dma_tx_buffer_size = 0; void ws_server_req_parse_byte(unsigned int channel, uint8_t byte, bool ignore) { if (ignore) return; @@ -126,7 +126,7 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { break; } case WS_SERVER_LM_CIPSEND_LISTENING: { - if (next_few_bytes_are("SEND OK")) { + if (next_few_bytes_are("SEND OK") || next_few_bytes_are("ERROR")) { ws_server_req_respond_end(0); // g_ws_server_parser.mode = WS_SERVER_LM_IDLE; } @@ -146,23 +146,25 @@ void ws_server_send(uint8_t* data, size_t size) { void ws_server_buffer_send_append(uint8_t* data, size_t size) { // TODO: buffer overrun protection // while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); // make sure buffer isn't used - strncpy((char*) &g_ws_esp8266_dma_tx_buffer[g_ws_esp8266_dma_tx_buffer_index], (char*) data, size); // append string - g_ws_esp8266_dma_tx_buffer_index += size; // shift head + strncpy((char*) &g_ws_esp8266_dma_tx_buffer[g_ws_esp8266_dma_tx_buffer_size], (char*) data, size); // append string + g_ws_esp8266_dma_tx_buffer_size += size; // shift head } +// TODO: refactor this void ws_server_buffer_send_finish() { #ifdef WS_DBG_PRINT_ESP_OVER_USART2 uint8_t green[] = { 0x1b, 0x5b, 0x33, 0x32, 0x6d }; HAL_UART_Transmit(&huart2, green, sizeof(green), 100); - HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, strlen((char*) g_ws_esp8266_dma_tx_buffer), 100); + HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_size, 100); #endif - HAL_UART_Transmit_DMA(&huart1, g_ws_esp8266_dma_tx_buffer, strlen((char*) g_ws_esp8266_dma_tx_buffer)); + HAL_UART_Transmit_DMA(&huart1, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_size); __HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE); - g_ws_esp8266_dma_tx_buffer_index = 0; + g_ws_esp8266_dma_tx_buffer_size = 0; while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); } +// TODO: refactor this void ws_server_req_respond_start(unsigned int channel, size_t size) { char* cmd = NULL; size_t len = asiprintf(&cmd, "AT+CIPSEND=%d,%d\r\n", channel, size); @@ -171,6 +173,7 @@ void ws_server_req_respond_start(unsigned int channel, size_t size) { while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); } +// TODO: refactor this void ws_server_req_respond_end(unsigned int channel) { char* cmd = NULL; size_t len = asiprintf(&cmd, "AT+CIPCLOSE=%d\r\n", channel); @@ -178,4 +181,3 @@ void ws_server_req_respond_end(unsigned int channel) { ws_esp8266_send((uint8_t*) cmd, len); while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); } - diff --git a/stm32f091/todo.md b/stm32f091/todo.md new file mode 100644 index 0000000..767d745 --- /dev/null +++ b/stm32f091/todo.md @@ -0,0 +1,10 @@ +- handle errors from `AT+CIPSEND`, these look like this: + ``` + > AT0,CONNECT + + > +IPD,0,15:last-records 5<0a> + < AT+CIPSEND=0,125 + > AT+CIPSEND=0,125 + + > ERROR + ``` -- cgit v1.2.3 From babb6dc29a5c4af60292ffad5216317d13e2a685 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 28 Oct 2022 14:31:56 +0200 Subject: fix off-by-one error and create macro for switching serial debug print color --- shared/protocol.c | 2 +- stm32f091/consts.h | 2 +- stm32f091/esp8266.c | 3 +-- stm32f091/protocol.c | 14 ++++++++------ stm32f091/server.c | 8 +++----- stm32f091/setup.c | 7 +++++++ stm32f091/util.h | 4 ++++ 7 files changed, 25 insertions(+), 15 deletions(-) diff --git a/shared/protocol.c b/shared/protocol.c index e17a728..8887070 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -142,6 +142,6 @@ unsigned short ws_protocol_get_header_size(ws_s_protocol_res* response) { unsigned short size = 2; // comma and trailing newline if (response->success == WS_PROTOCOL_CMD_RETURN_OK) size += 2; // ok if (response->success == WS_PROTOCOL_CMD_RETURN_ERROR) size += 5; // error - size += ws_log16(response->msg->bytes); // amount of characters for message size (hex) + size += ws_log16(response->msg->bytes) + 1; // amount of characters for message size (hex) return size; } \ No newline at end of file diff --git a/stm32f091/consts.h b/stm32f091/consts.h index 955ceea..3d2ef5a 100644 --- a/stm32f091/consts.h +++ b/stm32f091/consts.h @@ -6,7 +6,7 @@ #define WS_SERVER_MAX_CHANNELS 4 #define WS_DMA_RX_BUFFER_SIZE 100 -#define WS_DMA_TX_BUFFER_SIZE 100 +#define WS_DMA_TX_BUFFER_SIZE 1024 #define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9 #define WS_PINOUT_I2C_SDA_PORT GPIOB diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 754b45b..b896567 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -58,8 +58,7 @@ void ws_esp8266_send(uint8_t* data, size_t size) { g_ws_esp8266_dma_tx_buffer[limited_size] = 0x00; #ifdef WS_DBG_PRINT_ESP_OVER_USART2 - uint8_t green[] = { 0x1b, 0x5b, 0x33, 0x32, 0x6d }; - HAL_UART_Transmit(&huart2, green, sizeof(green), 100); + ws_dbg_set_usart2_tty_color(2); HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, strlen((char*) g_ws_esp8266_dma_tx_buffer), 100); #endif diff --git a/stm32f091/protocol.c b/stm32f091/protocol.c index 21e6527..4d605fc 100644 --- a/stm32f091/protocol.c +++ b/stm32f091/protocol.c @@ -9,27 +9,29 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response, bool send) { static unsigned int record_amount = 0; const char* response_header = "id,temperature,humidity,atmospheric_pressure\n"; - const size_t response_line_size = sizeof("xxxx,xx,xx,xx\n"); + const unsigned int response_line_len = strlen("xxxx,xx,xx,xx\n"); if (!send) { response->success = WS_PROTOCOL_CMD_RETURN_OK; response->csh = true; response->msg = ws_bin_s_alloc(0); response->msg->bytes = 0; - record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); if (sscanf(parsed_cmd->argv[1], "%u", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; - else response->msg->bytes = strlen(response_header) + response_line_size * record_amount; + else { + record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); + response->msg->bytes = strlen(response_header) + response_line_len * record_amount; + } ws_server_req_respond_start(0, response->msg->bytes + ws_protocol_get_header_size(response)); } else { if (response->success == WS_PROTOCOL_CMD_RETURN_ERROR) return; ws_protocol_send_data(response_header, strlen(response_header)); - char line[response_line_size]; + char line[response_line_len + 1]; // + 1 for string terminator for (unsigned int i = 0; i < record_amount; i++) { ws_s_backlog_record* record = ws_backlog_get_last_record(i); sprintf(line, "%04x,%02x,%02x,%02x\n", record->id, record->sens_temperature, record->sens_humidity, record->sens_atm_pressure); - ws_protocol_send_data(line, response_line_size - 1); // remove string terminator + ws_protocol_send_data(line, response_line_len); // remove string terminator } - ws_protocol_send_data("\r\n", 2); // test + // ws_protocol_send_data("\r\n", 2); // test } } diff --git a/stm32f091/server.c b/stm32f091/server.c index 1419da8..6225eae 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -8,6 +8,7 @@ #include "server.h" #include "setup.h" #include "consts.h" +#include "util.h" ws_s_server_parser g_ws_server_parser = { .last_response = WS_SERVER_RC_NONE, @@ -48,8 +49,7 @@ void ws_server_req_finish(unsigned int channel, bool ignore) { #define next_few_bytes_are(code) (i + sizeof(code) - 1 < size && strncmp((char*)&data[i], code, sizeof(code) - 1) == 0) void ws_server_req_incoming(uint8_t* data, size_t size) { #ifdef WS_DBG_PRINT_ESP_OVER_USART2 - uint8_t red[] = { 0x1b, 0x5b, 0x33, 0x31, 0x6d }; - HAL_UART_Transmit(&huart2, red, sizeof(red), 100); + ws_dbg_set_usart2_tty_color(1); HAL_UART_Transmit(&huart2, data, size, 100); #endif @@ -128,7 +128,6 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { case WS_SERVER_LM_CIPSEND_LISTENING: { if (next_few_bytes_are("SEND OK") || next_few_bytes_are("ERROR")) { ws_server_req_respond_end(0); - // g_ws_server_parser.mode = WS_SERVER_LM_IDLE; } break; } @@ -153,8 +152,7 @@ void ws_server_buffer_send_append(uint8_t* data, size_t size) { // TODO: refactor this void ws_server_buffer_send_finish() { #ifdef WS_DBG_PRINT_ESP_OVER_USART2 - uint8_t green[] = { 0x1b, 0x5b, 0x33, 0x32, 0x6d }; - HAL_UART_Transmit(&huart2, green, sizeof(green), 100); + ws_dbg_set_usart2_tty_color(2); HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_size, 100); #endif diff --git a/stm32f091/setup.c b/stm32f091/setup.c index 3bf331f..1591649 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -9,6 +9,7 @@ #include "setup.h" #include "backlog.h" #include "server.h" +#include "util.h" I2C_HandleTypeDef hi2c1 = { .Instance = I2C1, @@ -95,6 +96,12 @@ void ws_io_setup() { ws_backlog_alloc(24 * 60); // ws_backlog_alloc(10); +#ifdef WS_DBG_PRINT_ESP_OVER_USART2 + ws_dbg_set_usart2_tty_color(7); + const char restart_str[] = "\r\n--- stm restart ---\r\n"; + HAL_UART_Transmit(&huart2, restart_str, strlen(restart_str), 100); +#endif + #ifdef WS_ESP8266_WLAN_MAC ws_esp8266_set_mac(); #endif diff --git a/stm32f091/util.h b/stm32f091/util.h index 92f093f..9f5c1ec 100644 --- a/stm32f091/util.h +++ b/stm32f091/util.h @@ -14,3 +14,7 @@ HAL_UART_Transmit(&huart2, (uint8_t*) temp, sizeof(char) * strlen(temp), HAL_MAX_DELAY); \ } +#define ws_dbg_set_usart2_tty_color(color) { \ + uint8_t sgr[] = { 0x1b, 0x5b, 0x33, 0x30 + color, 0x6d }; \ + HAL_UART_Transmit(&huart2, sgr, sizeof(sgr), 100); \ +} -- cgit v1.2.3 From ee6d749c0fc2b4cd45e3cf8295aae892e0680c6c Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 28 Oct 2022 15:18:26 +0200 Subject: update todo --- stm32f091/todo.md | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/stm32f091/todo.md b/stm32f091/todo.md index 767d745..77c37e6 100644 --- a/stm32f091/todo.md +++ b/stm32f091/todo.md @@ -1,10 +1,28 @@ -- handle errors from `AT+CIPSEND`, these look like this: - ``` - > AT0,CONNECT +# things that have to get fixed before monday - > +IPD,0,15:last-records 5<0a> - < AT+CIPSEND=0,125 - > AT+CIPSEND=0,125 +- [ ] more documentation in header files (for both client and stm code) +- [ ] design/architecture document +- [ ] more tests in the test document +- [ ] handle errors from `AT+CIPSEND`, these look like this: + ``` + > AT0,CONNECT - > ERROR - ``` + > +IPD,0,15:last-records 5<0a> + < AT+CIPSEND=0,125 + > AT+CIPSEND=0,125 + + > ERROR + ``` + +## `// TODO:`'s + +- [ ] `sensor.c:24: return (uint8_t) temp_c; //TODO: convert with range -> util.h` +- [ ] `sensor.c:36: return (uint8_t) humidity; //TODO: convert with range -> util.h` +- [ ] `sensor.c:51: return (uint8_t) val; // TODO: convert with range` +- [ ] `server.c:47:// TODO: next_few_bytes_are assumes that the complete search string is in the` +- [ ] `server.c:146: // TODO: buffer overrun protection` +- [ ] `server.c:152:// TODO: refactor this` +- [ ] `server.c:165:// TODO: refactor this` +- [ ] `server.c:174:// TODO: refactor this` +- [ ] `setup.c:95: // TODO: remove debug size` +- [ ] `setup.c:187: .Pin = GPIO_PIN_8|GPIO_PIN_9, //TODO: use #defines in setup.h` -- cgit v1.2.3 From c429e17061d392ea4b3f73ebcc9101db8e491d8f Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 28 Oct 2022 16:56:23 +0200 Subject: another off-by-one error fixed --- stm32f091/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stm32f091/server.c b/stm32f091/server.c index 6225eae..46d18f0 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -46,7 +46,7 @@ void ws_server_req_finish(unsigned int channel, bool ignore) { // TODO: next_few_bytes_are assumes that the complete search string is in the // buffer, so won't work for buffer cutoffs -#define next_few_bytes_are(code) (i + sizeof(code) - 1 < size && strncmp((char*)&data[i], code, sizeof(code) - 1) == 0) +#define next_few_bytes_are(code) (((i + sizeof(code) - 2) < size) && (strncmp((char*)&data[i], code, sizeof(code) - 1) == 0)) void ws_server_req_incoming(uint8_t* data, size_t size) { #ifdef WS_DBG_PRINT_ESP_OVER_USART2 ws_dbg_set_usart2_tty_color(1); @@ -80,7 +80,7 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { if (next_few_bytes_are("+IPD,")) { i += 4; // skip I, P, D, and comma g_ws_server_parser.mode = WS_SERVER_LM_IPD_LISTENING; - } else if (byte == '>') { + } else if (next_few_bytes_are("> ")) { g_ws_server_parser.mode = WS_SERVER_LM_CIPSEND_LISTENING; ws_server_buffer_send_finish(); } -- cgit v1.2.3 From 7b4dbb553a4d22e88bafc38163d1b2f951c40fde Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sat, 29 Oct 2022 12:26:46 +0200 Subject: add bunch of unneccesary debug stuff, fix some stuff and expect espressif esp firmware --- stm32f091/esp8266.c | 2 +- stm32f091/server.c | 92 ++++++++++++++++++++++++++++++++--------------------- stm32f091/setup.c | 6 ++-- stm32f091/util.h | 31 +++++++++++++++++- 4 files changed, 89 insertions(+), 42 deletions(-) diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index b896567..159b55d 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -58,7 +58,7 @@ void ws_esp8266_send(uint8_t* data, size_t size) { g_ws_esp8266_dma_tx_buffer[limited_size] = 0x00; #ifdef WS_DBG_PRINT_ESP_OVER_USART2 - ws_dbg_set_usart2_tty_color(2); + ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_TX); HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, strlen((char*) g_ws_esp8266_dma_tx_buffer), 100); #endif diff --git a/stm32f091/server.c b/stm32f091/server.c index 46d18f0..e0c97dc 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -49,7 +49,7 @@ void ws_server_req_finish(unsigned int channel, bool ignore) { #define next_few_bytes_are(code) (((i + sizeof(code) - 2) < size) && (strncmp((char*)&data[i], code, sizeof(code) - 1) == 0)) void ws_server_req_incoming(uint8_t* data, size_t size) { #ifdef WS_DBG_PRINT_ESP_OVER_USART2 - ws_dbg_set_usart2_tty_color(1); + ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_RX); HAL_UART_Transmit(&huart2, data, size, 100); #endif @@ -64,12 +64,19 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { case WS_SERVER_LM_STATUS_CODE: { bool code_got = false; if (next_few_bytes_are("OK")) { + i += 1; code_got = true; g_ws_server_parser.last_response = WS_SERVER_RC_OK; - } else if (next_few_bytes_are("ERROR") || next_few_bytes_are("FAIL")) { + } else if (next_few_bytes_are("ERROR")) { + i += 4; + code_got = true; + g_ws_server_parser.last_response = WS_SERVER_RC_ERR; + } else if (next_few_bytes_are("FAIL")) { + i += 3; code_got = true; g_ws_server_parser.last_response = WS_SERVER_RC_ERR; } else if (next_few_bytes_are("busy p...")) { + i += 8; code_got = true; g_ws_server_parser.last_response = WS_SERVER_RC_BUSY; } @@ -80,49 +87,49 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { if (next_few_bytes_are("+IPD,")) { i += 4; // skip I, P, D, and comma g_ws_server_parser.mode = WS_SERVER_LM_IPD_LISTENING; - } else if (next_few_bytes_are("> ")) { + } else if (next_few_bytes_are(">")) { // ">" on official espressif firmware, "> " on ai-thinker firmware g_ws_server_parser.mode = WS_SERVER_LM_CIPSEND_LISTENING; ws_server_buffer_send_finish(); } break; } case WS_SERVER_LM_IPD_LISTENING: { - switch (g_ws_server_parser.channel_listen_mode) { - case WS_SERVER_CL_CHANNEL_ID: { - if (byte == ',') { - g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_DATA_LENGTH; - break; - } - g_ws_server_parser.current_channel *= 10; - g_ws_server_parser.current_channel += byte - '0'; // ascii to int + switch (g_ws_server_parser.channel_listen_mode) { + case WS_SERVER_CL_CHANNEL_ID: { + if (byte == ',') { + g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_DATA_LENGTH; break; } - case WS_SERVER_CL_DATA_LENGTH: { - if (byte == ':') { - g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_DATA_READ; - if (g_ws_server_parser.channel_data_length > WS_PROTOCOL_CMD_BUFFER_LEN) - g_ws_server_parser.channel_data_ignore = true; - break; - } - g_ws_server_parser.channel_data_length *= 10; - g_ws_server_parser.channel_data_length += byte - '0'; // ascii to int + g_ws_server_parser.current_channel *= 10; + g_ws_server_parser.current_channel += byte - '0'; // ascii to int + break; + } + case WS_SERVER_CL_DATA_LENGTH: { + if (byte == ':') { + g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_DATA_READ; + if (g_ws_server_parser.channel_data_length > WS_PROTOCOL_CMD_BUFFER_LEN) + g_ws_server_parser.channel_data_ignore = true; break; } - case WS_SERVER_CL_DATA_READ: { - ws_server_req_parse_byte(g_ws_server_parser.current_channel, byte, g_ws_server_parser.channel_data_ignore); - g_ws_server_parser.channel_data_counter++; - if (g_ws_server_parser.channel_data_counter == g_ws_server_parser.channel_data_length) { - g_ws_server_parser.current_channel = 0; - g_ws_server_parser.channel_data_counter = 0; - g_ws_server_parser.channel_data_length = 0; - g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_CHANNEL_ID; - ws_server_req_finish(g_ws_server_parser.current_channel, g_ws_server_parser.channel_data_ignore); - g_ws_server_parser.mode = WS_SERVER_LM_IDLE; - } - break; + g_ws_server_parser.channel_data_length *= 10; + g_ws_server_parser.channel_data_length += byte - '0'; // ascii to int + break; + } + case WS_SERVER_CL_DATA_READ: { + ws_server_req_parse_byte(g_ws_server_parser.current_channel, byte, g_ws_server_parser.channel_data_ignore); + g_ws_server_parser.channel_data_counter++; + if (g_ws_server_parser.channel_data_counter == g_ws_server_parser.channel_data_length) { + g_ws_server_parser.current_channel = 0; + g_ws_server_parser.channel_data_counter = 0; + g_ws_server_parser.channel_data_length = 0; + g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_CHANNEL_ID; + ws_server_req_finish(g_ws_server_parser.current_channel, g_ws_server_parser.channel_data_ignore); + g_ws_server_parser.mode = WS_SERVER_LM_IDLE; } - default: {} + break; } + default: {} + } break; } case WS_SERVER_LM_CIPSEND_LISTENING: { @@ -151,15 +158,26 @@ void ws_server_buffer_send_append(uint8_t* data, size_t size) { // TODO: refactor this void ws_server_buffer_send_finish() { + /* const int chunk_size = 16; // esp is garbage + + for (unsigned int chunk = 0; chunk <= (g_ws_esp8266_dma_tx_buffer_size / chunk_size); chunk++) { + HAL_UART_Transmit_DMA(&huart1, &g_ws_esp8266_dma_tx_buffer[chunk_size * chunk], WS_MIN(chunk_size, g_ws_esp8266_dma_tx_buffer_size % chunk_size)); + __HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE); + while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); + } */ #ifdef WS_DBG_PRINT_ESP_OVER_USART2 - ws_dbg_set_usart2_tty_color(2); + ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_TX); HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_size, 100); #endif - HAL_UART_Transmit_DMA(&huart1, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_size); - __HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE); + HAL_UART_Transmit(&huart1, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_size, 100); + // for (unsigned j = 0; j < 10000; j++) asm("nop"); // esp garbage + // for (unsigned int i = 0; i < g_ws_esp8266_dma_tx_buffer_size; i++) { + // // send as slow as possible because the esp is garbage + // for (unsigned j = 0; j < 1000; j++) asm("nop"); // did i mention the esp is garbage + // HAL_UART_Transmit(&huart1, &g_ws_esp8266_dma_tx_buffer[i], 1, 100); + // } g_ws_esp8266_dma_tx_buffer_size = 0; - while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); } // TODO: refactor this diff --git a/stm32f091/setup.c b/stm32f091/setup.c index 1591649..ef00a29 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -97,18 +97,18 @@ void ws_io_setup() { // ws_backlog_alloc(10); #ifdef WS_DBG_PRINT_ESP_OVER_USART2 - ws_dbg_set_usart2_tty_color(7); + ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_DBGMSG); const char restart_str[] = "\r\n--- stm restart ---\r\n"; - HAL_UART_Transmit(&huart2, restart_str, strlen(restart_str), 100); + HAL_UART_Transmit(&huart2, (uint8_t*) restart_str, strlen(restart_str), 100); #endif + ws_esp8266_ap_client_mode(); #ifdef WS_ESP8266_WLAN_MAC ws_esp8266_set_mac(); #endif #ifdef WS_ESP8266_WLAN_IP ws_esp8266_set_ip(); #endif - ws_esp8266_ap_client_mode(); do ws_esp8266_connect(); while (g_ws_server_parser.last_response == WS_SERVER_RC_ERR); ws_esp8266_start_tcp_server(); } diff --git a/stm32f091/util.h b/stm32f091/util.h index 9f5c1ec..dde3677 100644 --- a/stm32f091/util.h +++ b/stm32f091/util.h @@ -8,6 +8,35 @@ #include "setup.h" #include "../shared/util.h" +#define WS_DBG_TTY_COLOR_BLK 0x0 +#define WS_DBG_TTY_COLOR_RED 0x1 +#define WS_DBG_TTY_COLOR_GRN 0x2 +#define WS_DBG_TTY_COLOR_YLW 0x3 +#define WS_DBG_TTY_COLOR_BLU 0x4 +#define WS_DBG_TTY_COLOR_VLT 0x5 +#define WS_DBG_TTY_COLOR_CYN 0x6 +#define WS_DBG_TTY_COLOR_WHI 0x7 +#define WS_DBG_TTY_COLOR_BR_BLK 0x8 +#define WS_DBG_TTY_COLOR_BR_RED 0x9 +#define WS_DBG_TTY_COLOR_BR_GRN 0xa +#define WS_DBG_TTY_COLOR_BR_YLW 0xb +#define WS_DBG_TTY_COLOR_BR_BLU 0xc +#define WS_DBG_TTY_COLOR_BR_VLT 0xd +#define WS_DBG_TTY_COLOR_BR_CYN 0xe +#define WS_DBG_TTY_COLOR_BR_WHI 0xf + +// serial debug color scheme +#define WS_DBG_TTY_COLOR_DBGMSG WS_DBG_TTY_COLOR_BR_BLK +#define WS_DBG_TTY_COLOR_TX WS_DBG_TTY_COLOR_GRN +#define WS_DBG_TTY_COLOR_RX WS_DBG_TTY_COLOR_RED + +// unused +// #define WS_DBG_TTY_COLOR_CMD_ECHO WS_DBG_TTY_COLOR_BLK +// #define WS_DBG_TTY_COLOR_STATUS_CODE WS_DBG_TTY_COLOR_YLW +// #define WS_DBG_TTY_COLOR_IDLE WS_DBG_TTY_COLOR_VLT +// #define WS_DBG_TTY_COLOR_IPD_LISTENING WS_DBG_TTY_COLOR_GRN +// #define WS_DBG_TTY_COLOR_CIPSEND_LISTENING WS_DBG_TTY_COLOR_RED + #define ws_usb_printf(fmt, ...) { \ char temp[255]; \ snprintf(temp, 255, fmt, ##__VA_ARGS__); \ @@ -15,6 +44,6 @@ } #define ws_dbg_set_usart2_tty_color(color) { \ - uint8_t sgr[] = { 0x1b, 0x5b, 0x33, 0x30 + color, 0x6d }; \ + uint8_t sgr[] = { 0x1b, 0x5b, 0x33 + (color > 7 ? 6 : 0), 0x30 + (color & 0b111), 0x6d }; \ HAL_UART_Transmit(&huart2, sgr, sizeof(sgr), 100); \ } -- cgit v1.2.3 From f536fb4f92eda7ba5e80230a023b144d373dd86b Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sat, 29 Oct 2022 13:19:24 +0200 Subject: garbage delay - esp still too slow!? --- stm32f091/server.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/stm32f091/server.c b/stm32f091/server.c index e0c97dc..cc47251 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -167,16 +167,18 @@ void ws_server_buffer_send_finish() { } */ #ifdef WS_DBG_PRINT_ESP_OVER_USART2 ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_TX); - HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_size, 100); #endif - HAL_UART_Transmit(&huart1, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_size, 100); - // for (unsigned j = 0; j < 10000; j++) asm("nop"); // esp garbage - // for (unsigned int i = 0; i < g_ws_esp8266_dma_tx_buffer_size; i++) { - // // send as slow as possible because the esp is garbage - // for (unsigned j = 0; j < 1000; j++) asm("nop"); // did i mention the esp is garbage - // HAL_UART_Transmit(&huart1, &g_ws_esp8266_dma_tx_buffer[i], 1, 100); - // } + // HAL_UART_Transmit(&huart1, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_size, 100); + for (unsigned j = 0; j < 1000000; j++) asm("nop"); // esp garbage + for (unsigned int i = 0; i < g_ws_esp8266_dma_tx_buffer_size; i++) { + // send as slow as possible because the esp is garbage + for (unsigned j = 0; j < 10000; j++) asm("nop"); // did i mention the esp is garbage + HAL_UART_Transmit(&huart1, &g_ws_esp8266_dma_tx_buffer[i], 1, 100); +#ifdef WS_DBG_PRINT_ESP_OVER_USART2 + HAL_UART_Transmit(&huart2, &g_ws_esp8266_dma_tx_buffer[i], 1, 100); +#endif + } g_ws_esp8266_dma_tx_buffer_size = 0; } -- cgit v1.2.3 From 9947b4aa803b0430e38be3bd6f7179b45b201213 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sat, 29 Oct 2022 17:15:56 +0200 Subject: send data in chunks for reliability --- stm32f091/esp8266.c | 6 +-- stm32f091/protocol.c | 4 +- stm32f091/server.c | 108 +++++++++++++++++++++++++++++++-------------------- stm32f091/server.h | 24 +++++++++--- stm32f091/todo.md | 2 +- stm32f091/util.h | 2 + 6 files changed, 92 insertions(+), 54 deletions(-) diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 159b55d..74ec347 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -75,9 +75,9 @@ void ws_esp8266_ap_client_mode() { } void ws_esp8266_start_tcp_server() { - ws_esp8266_send_seq("AT+CIPSERVER=0\r\n"); - ws_esp8266_send_seq("AT+CIPMUX=1\r\n"); - ws_esp8266_send_seq("AT+CIPSERVER=1," WS_SERVER_PORT "\r\n"); + ws_esp8266_send_seq("AT+CIPSERVER=0\r\n"); // stop tcp server (if running) + ws_esp8266_send_seq("AT+CIPMUX=1\r\n"); // enable multiplexing (allow multiple connections) + ws_esp8266_send_seq("AT+CIPSERVER=1," WS_SERVER_PORT "\r\n"); // start tcp server } void ws_esp8266_set_mac() { diff --git a/stm32f091/protocol.c b/stm32f091/protocol.c index 4d605fc..ca46b3b 100644 --- a/stm32f091/protocol.c +++ b/stm32f091/protocol.c @@ -21,7 +21,6 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); response->msg->bytes = strlen(response_header) + response_line_len * record_amount; } - ws_server_req_respond_start(0, response->msg->bytes + ws_protocol_get_header_size(response)); } else { if (response->success == WS_PROTOCOL_CMD_RETURN_ERROR) return; ws_protocol_send_data(response_header, strlen(response_header)); @@ -29,9 +28,8 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s for (unsigned int i = 0; i < record_amount; i++) { ws_s_backlog_record* record = ws_backlog_get_last_record(i); sprintf(line, "%04x,%02x,%02x,%02x\n", record->id, record->sens_temperature, record->sens_humidity, record->sens_atm_pressure); - ws_protocol_send_data(line, response_line_len); // remove string terminator + ws_protocol_send_data(line, response_line_len); } - // ws_protocol_send_data("\r\n", 2); // test } } diff --git a/stm32f091/server.c b/stm32f091/server.c index cc47251..0e8cadf 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -18,10 +18,14 @@ ws_s_server_parser g_ws_server_parser = { .channel_data_length = 0, .channel_data_counter = 0, .channel_listen_mode = WS_SERVER_CL_CHANNEL_ID, + + .rc = { 0 }, }; static ws_s_protocol_req_parser_state* g_ws_protocol_parsers[WS_SERVER_MAX_CHANNELS] = {0}; -static unsigned int g_ws_esp8266_dma_tx_buffer_size = 0; +static unsigned int g_ws_esp8266_dma_tx_buffer_head = 0; +static unsigned int g_ws_esp8266_dma_tx_buffer_tail = 0; +static unsigned int g_ws_esp8266_dma_tx_buffer_cs = 0; // chunk size void ws_server_req_parse_byte(unsigned int channel, uint8_t byte, bool ignore) { if (ignore) return; @@ -44,6 +48,13 @@ void ws_server_req_finish(unsigned int channel, bool ignore) { } } +static bool ws_server_is_response(char data, uint8_t* counter, const char* cmd, unsigned short cmd_len) { + if (data == cmd[*counter]) *counter += 1; + else *counter = 0; + if (*counter == cmd_len) return true; + return false; +} + // TODO: next_few_bytes_are assumes that the complete search string is in the // buffer, so won't work for buffer cutoffs #define next_few_bytes_are(code) (((i + sizeof(code) - 2) < size) && (strncmp((char*)&data[i], code, sizeof(code) - 1) == 0)) @@ -63,20 +74,16 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { } case WS_SERVER_LM_STATUS_CODE: { bool code_got = false; - if (next_few_bytes_are("OK")) { - i += 1; + if (ws_server_is_response(byte, &g_ws_server_parser.rc.s_ok, "OK", 2)) { code_got = true; g_ws_server_parser.last_response = WS_SERVER_RC_OK; - } else if (next_few_bytes_are("ERROR")) { - i += 4; + } else if (ws_server_is_response(byte, &g_ws_server_parser.rc.s_error, "ERROR", 5)) { code_got = true; g_ws_server_parser.last_response = WS_SERVER_RC_ERR; - } else if (next_few_bytes_are("FAIL")) { - i += 3; + } else if (ws_server_is_response(byte, &g_ws_server_parser.rc.s_fail, "FAIL", 4)) { code_got = true; g_ws_server_parser.last_response = WS_SERVER_RC_ERR; - } else if (next_few_bytes_are("busy p...")) { - i += 8; + } else if (ws_server_is_response(byte, &g_ws_server_parser.rc.s_busy, "busy p...", 9)) { code_got = true; g_ws_server_parser.last_response = WS_SERVER_RC_BUSY; } @@ -84,12 +91,12 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { break; } case WS_SERVER_LM_IDLE: { - if (next_few_bytes_are("+IPD,")) { - i += 4; // skip I, P, D, and comma + if (ws_server_is_response(byte, &g_ws_server_parser.rc.i_ipd, "+IPD,", 5)) { g_ws_server_parser.mode = WS_SERVER_LM_IPD_LISTENING; - } else if (next_few_bytes_are(">")) { // ">" on official espressif firmware, "> " on ai-thinker firmware + } else if (ws_server_is_response(byte, &g_ws_server_parser.rc.i_prompt, ">", 1)) { + // ^^^ this is ">" on official espressif firmware, "> " on ai-thinker firmware g_ws_server_parser.mode = WS_SERVER_LM_CIPSEND_LISTENING; - ws_server_buffer_send_finish(); + ws_server_buffer_send_chunk(); } break; } @@ -125,6 +132,7 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_CHANNEL_ID; ws_server_req_finish(g_ws_server_parser.current_channel, g_ws_server_parser.channel_data_ignore); g_ws_server_parser.mode = WS_SERVER_LM_IDLE; + ws_server_buffer_request_chunk_send(); } break; } @@ -133,8 +141,8 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { break; } case WS_SERVER_LM_CIPSEND_LISTENING: { - if (next_few_bytes_are("SEND OK") || next_few_bytes_are("ERROR")) { - ws_server_req_respond_end(0); + if (ws_server_is_response(byte, &g_ws_server_parser.rc.l_send_ok, "SEND OK", 7) || ws_server_is_response(byte, &g_ws_server_parser.rc.l_error, "ERROR", 5)) { + ws_server_buffer_request_chunk_send(); } break; } @@ -143,6 +151,13 @@ void ws_server_req_incoming(uint8_t* data, size_t size) { } } +/** @brief get amount of bytes in g_ws_esp8266_dma_tx_buffer until \n */ +static unsigned int ws_server_next_line_length() { + for (unsigned int i = g_ws_esp8266_dma_tx_buffer_tail; i <= g_ws_esp8266_dma_tx_buffer_head; i++) + if (g_ws_esp8266_dma_tx_buffer[i] == '\n') return i - g_ws_esp8266_dma_tx_buffer_tail + 1; + return g_ws_esp8266_dma_tx_buffer_head - g_ws_esp8266_dma_tx_buffer_tail; +} + void ws_server_send(uint8_t* data, size_t size) { g_ws_server_parser.mode = WS_SERVER_LM_CMD_ECHO; ws_esp8266_send(data, size); @@ -152,43 +167,52 @@ void ws_server_send(uint8_t* data, size_t size) { void ws_server_buffer_send_append(uint8_t* data, size_t size) { // TODO: buffer overrun protection // while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); // make sure buffer isn't used - strncpy((char*) &g_ws_esp8266_dma_tx_buffer[g_ws_esp8266_dma_tx_buffer_size], (char*) data, size); // append string - g_ws_esp8266_dma_tx_buffer_size += size; // shift head + strncpy((char*) &g_ws_esp8266_dma_tx_buffer[g_ws_esp8266_dma_tx_buffer_head], (char*) data, size); // append string + g_ws_esp8266_dma_tx_buffer_head += size; // shift head } -// TODO: refactor this -void ws_server_buffer_send_finish() { - /* const int chunk_size = 16; // esp is garbage - - for (unsigned int chunk = 0; chunk <= (g_ws_esp8266_dma_tx_buffer_size / chunk_size); chunk++) { - HAL_UART_Transmit_DMA(&huart1, &g_ws_esp8266_dma_tx_buffer[chunk_size * chunk], WS_MIN(chunk_size, g_ws_esp8266_dma_tx_buffer_size % chunk_size)); - __HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE); - while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); - } */ +void ws_server_buffer_request_chunk_send() { + g_ws_esp8266_dma_tx_buffer_cs = ws_server_next_line_length(); + + char* cmd = NULL; + size_t len; + + if (g_ws_esp8266_dma_tx_buffer_cs > 0) { + len = asiprintf(&cmd, "AT+CIPSEND=%d,%d\r\n", g_ws_server_parser.current_channel, g_ws_esp8266_dma_tx_buffer_cs); + } else { + len = asiprintf(&cmd, "AT+CIPCLOSE=%d\r\n", g_ws_server_parser.current_channel); + } + + g_ws_server_parser.mode = WS_SERVER_LM_CMD_ECHO; + #ifdef WS_DBG_PRINT_ESP_OVER_USART2 ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_TX); + HAL_UART_Transmit(&huart2, (uint8_t*) cmd, len, 100); #endif + HAL_UART_Transmit(&huart1, (uint8_t*) cmd, len, 100); +} - // HAL_UART_Transmit(&huart1, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_size, 100); - for (unsigned j = 0; j < 1000000; j++) asm("nop"); // esp garbage - for (unsigned int i = 0; i < g_ws_esp8266_dma_tx_buffer_size; i++) { - // send as slow as possible because the esp is garbage - for (unsigned j = 0; j < 10000; j++) asm("nop"); // did i mention the esp is garbage - HAL_UART_Transmit(&huart1, &g_ws_esp8266_dma_tx_buffer[i], 1, 100); +void ws_server_buffer_send_chunk() { #ifdef WS_DBG_PRINT_ESP_OVER_USART2 - HAL_UART_Transmit(&huart2, &g_ws_esp8266_dma_tx_buffer[i], 1, 100); + ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_TX); + HAL_UART_Transmit(&huart2, &g_ws_esp8266_dma_tx_buffer[g_ws_esp8266_dma_tx_buffer_tail], g_ws_esp8266_dma_tx_buffer_cs, 100); #endif + HAL_UART_Transmit(&huart1, &g_ws_esp8266_dma_tx_buffer[g_ws_esp8266_dma_tx_buffer_tail], g_ws_esp8266_dma_tx_buffer_cs, 100); + g_ws_esp8266_dma_tx_buffer_tail += g_ws_esp8266_dma_tx_buffer_cs; + + if (g_ws_esp8266_dma_tx_buffer_head == g_ws_esp8266_dma_tx_buffer_tail) { + g_ws_esp8266_dma_tx_buffer_head = g_ws_esp8266_dma_tx_buffer_tail = 0; } - g_ws_esp8266_dma_tx_buffer_size = 0; -} -// TODO: refactor this -void ws_server_req_respond_start(unsigned int channel, size_t size) { - char* cmd = NULL; - size_t len = asiprintf(&cmd, "AT+CIPSEND=%d,%d\r\n", channel, size); - g_ws_server_parser.mode = WS_SERVER_LM_CMD_ECHO; - ws_esp8266_send((uint8_t*) cmd, len); - while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); +// #ifdef WS_DBG_PRINT_ESP_OVER_USART2 +// ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_TX); +// HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_head, 100); +// #endif +// +// HAL_UART_Transmit(&huart1, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_head, 100); +// g_ws_esp8266_dma_tx_buffer_head = 0; +// +// HAL_UART_Transmit(&huart1, (uint8_t*) "+++", 3, 100); } // TODO: refactor this diff --git a/stm32f091/server.h b/stm32f091/server.h index 128b579..07c49d9 100644 --- a/stm32f091/server.h +++ b/stm32f091/server.h @@ -25,6 +25,17 @@ typedef enum { WS_SERVER_RC_OK, } ws_e_server_response_code; +typedef struct { + uint8_t s_ok; /** @brief status code OK */ + uint8_t s_error; /** @brief status code OK */ + uint8_t s_fail; /** @brief status code OK */ + uint8_t s_busy; /** @brief status code OK */ + uint8_t i_ipd; /** @brief idle +IPD, */ + uint8_t i_prompt; /** @brief idle > */ + uint8_t l_send_ok; /** @brief ipd listen SEND OK */ + uint8_t l_error; /** @brief ipd listen ERROR */ +} ws_s_server_parser_response_counter; + typedef struct { ws_e_server_listen_mode mode; ws_e_server_response_code last_response; @@ -33,6 +44,7 @@ typedef struct { unsigned int channel_data_counter; ws_e_channel_listen_mode channel_listen_mode; bool channel_data_ignore; + ws_s_server_parser_response_counter rc; } ws_s_server_parser; /** @brief global server parser struct */ @@ -50,10 +62,10 @@ extern ws_s_server_parser g_ws_server_parser; */ void ws_server_req_incoming(uint8_t* data, size_t size); -/** @brief send AT response header for incoming request on specific channel */ -void ws_server_req_respond_start(unsigned int channel, size_t size); -/** @brief send AT tcp close on specific channel */ -void ws_server_req_respond_end(unsigned int channel); +// /** @brief send AT response header for incoming request on specific channel */ +// void ws_server_req_respond_start(unsigned int channel); +// /** @brief send AT tcp close on specific channel */ +// void ws_server_req_respond_end(unsigned int channel); /** @brief send data to esp, waiting until server returns to idle mode */ void ws_server_send(uint8_t* data, size_t size); @@ -82,4 +94,6 @@ void ws_server_req_parse_byte(unsigned int channel, uint8_t byte, bool ignore); void ws_server_req_finish(unsigned int channel, bool ignore); void ws_server_buffer_send_append(uint8_t* data, size_t size); -void ws_server_buffer_send_finish(); + +void ws_server_buffer_request_chunk_send(); +void ws_server_buffer_send_chunk(); diff --git a/stm32f091/todo.md b/stm32f091/todo.md index 77c37e6..1d42bf8 100644 --- a/stm32f091/todo.md +++ b/stm32f091/todo.md @@ -2,7 +2,7 @@ - [ ] more documentation in header files (for both client and stm code) - [ ] design/architecture document -- [ ] more tests in the test document +- [x] more tests in the test document - [ ] handle errors from `AT+CIPSEND`, these look like this: ``` > AT0,CONNECT diff --git a/stm32f091/util.h b/stm32f091/util.h index dde3677..11bee6f 100644 --- a/stm32f091/util.h +++ b/stm32f091/util.h @@ -30,6 +30,8 @@ #define WS_DBG_TTY_COLOR_TX WS_DBG_TTY_COLOR_GRN #define WS_DBG_TTY_COLOR_RX WS_DBG_TTY_COLOR_RED +#define debugger asm("nop") + // unused // #define WS_DBG_TTY_COLOR_CMD_ECHO WS_DBG_TTY_COLOR_BLK // #define WS_DBG_TTY_COLOR_STATUS_CODE WS_DBG_TTY_COLOR_YLW -- cgit v1.2.3 From aae57dc32a843351fb2e17721afcd841bedec0a6 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sat, 29 Oct 2022 18:01:44 +0200 Subject: fix memory leak --- stm32f091/server.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stm32f091/server.c b/stm32f091/server.c index 0e8cadf..112d23a 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -182,6 +182,7 @@ void ws_server_buffer_request_chunk_send() { } else { len = asiprintf(&cmd, "AT+CIPCLOSE=%d\r\n", g_ws_server_parser.current_channel); } + free(cmd); g_ws_server_parser.mode = WS_SERVER_LM_CMD_ECHO; @@ -222,4 +223,5 @@ void ws_server_req_respond_end(unsigned int channel) { g_ws_server_parser.mode = WS_SERVER_LM_CMD_ECHO; ws_esp8266_send((uint8_t*) cmd, len); while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); + free(cmd); } -- cgit v1.2.3 From 7022c6fbdbdee82339fbe161df169d97235471f0 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sat, 29 Oct 2022 18:26:16 +0200 Subject: update protocol to use hex digits in command arguments and accept offset value in `last-records` --- shared/protocol.h | 4 ++-- shared/protocol.md | 26 ++++++++++++++------------ stm32f091/protocol.c | 11 +++++++---- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/shared/protocol.h b/shared/protocol.h index 5bcb114..96c039a 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -5,7 +5,7 @@ #include "bin.h" -#define WS_PROTOCOL_CMD_MAX_ARGUMENTS (2) +#define WS_PROTOCOL_CMD_MAX_ARGUMENTS (3) #define WS_PROTOCOL_CMD_BUFFER_LEN (40) #define WS_PROTOCOL_CMD_AMOUNT (1) @@ -148,4 +148,4 @@ static ws_protocol_res_handler_t* g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMO [WS_PROTOCOL_CMD_LAST_RECORDS] = &ws_protocol_res_last_records, }; -unsigned short ws_protocol_get_header_size(ws_s_protocol_res* response); \ No newline at end of file +unsigned short ws_protocol_get_header_size(ws_s_protocol_res* response); diff --git a/shared/protocol.md b/shared/protocol.md index b6e955c..1e52e42 100644 --- a/shared/protocol.md +++ b/shared/protocol.md @@ -9,10 +9,10 @@ requirements about the connection itself. The protocol is only used in a request-response fashion, so all commands are assumed to be sent by the qt client, and responded to by the weather station. -Functions for generating commands and parsing incoming data are provided by the -protocol.c and protocol.h files. See [code -implementation](#code-implementation) section for more details about naming -conventions. +~Functions for generating commands and parsing incoming data are provided by +the protocol.c and protocol.h files in this folder.~ A server using these files +should implement every protocol handler function in a seperate c file, along +with a data sending function that is also used internally. - LF for newline instead of CRLF - Commands are single-line @@ -24,22 +24,28 @@ conventions. ## Commands -### `last-records ` +### `last-records ` -Returns the last `n` records in csv format. The first line has the csv table -header, with the fields `id`, `temperature`, `humidity`, and +Returns the last `n` records with offset `` in csv format. The first line +has the csv table header, with the fields `id`, `temperature`, `humidity`, and `atmospheric_pressure`. The rest of the response consists of 1 record per line. The amount of records is limited to the amount of valid records in the backlog buffer. When the amount of returned records is 0, the response consists of the csv header, but without any following records. +Offset `` is a positive integer, representing the starting point for the +most recent record that is returned, this will get subtracted from the id of +the most recent record. E.g. if the last record has id `00f0`, and a request is +sent with parameters `n=3` and `o=5`, the records with id's `00eb`, `00ea`, and +`00e9` will be returned. + ## Example transaction In the following example, newlines are indicated by `<0a>`, request by lines starting with `<`, and response by lines starting with `>`. ``` -< last-records 5<0a> +< last-records 5 0<0a> > ok,73<0a> > id,temperature,humidity,atmospheric_pressure<0a> > 10dc,2f,c5,7f<0a> @@ -49,7 +55,3 @@ starting with `<`, and response by lines starting with `>`. > 10e0,34,c9,7e<0a> ``` -## Code implementation - - - diff --git a/stm32f091/protocol.c b/stm32f091/protocol.c index ca46b3b..f4be08f 100644 --- a/stm32f091/protocol.c +++ b/stm32f091/protocol.c @@ -7,7 +7,8 @@ #include "esp8266.h" void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response, bool send) { - static unsigned int record_amount = 0; + static int record_amount = 0; + static unsigned int record_offset = 0; const char* response_header = "id,temperature,humidity,atmospheric_pressure\n"; const unsigned int response_line_len = strlen("xxxx,xx,xx,xx\n"); @@ -16,9 +17,11 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s response->csh = true; response->msg = ws_bin_s_alloc(0); response->msg->bytes = 0; - if (sscanf(parsed_cmd->argv[1], "%u", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; + if (sscanf(parsed_cmd->argv[1], "%x", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; + if (sscanf(parsed_cmd->argv[2], "%x", &record_offset) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; else { - record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); + record_amount = WS_MIN(record_amount + record_offset, ws_backlog_get_record_count()); + record_amount = WS_MAX(0, record_amount - record_offset); response->msg->bytes = strlen(response_header) + response_line_len * record_amount; } } else { @@ -26,7 +29,7 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s ws_protocol_send_data(response_header, strlen(response_header)); char line[response_line_len + 1]; // + 1 for string terminator for (unsigned int i = 0; i < record_amount; i++) { - ws_s_backlog_record* record = ws_backlog_get_last_record(i); + ws_s_backlog_record* record = ws_backlog_get_last_record(i + record_offset); sprintf(line, "%04x,%02x,%02x,%02x\n", record->id, record->sens_temperature, record->sens_humidity, record->sens_atm_pressure); ws_protocol_send_data(line, response_line_len); } -- cgit v1.2.3 From b5322d74d1839c4af490f5c7297e439a8433ba9b Mon Sep 17 00:00:00 2001 From: NielsCoding Date: Sat, 29 Oct 2022 21:38:47 +0200 Subject: merging TCPcode with main QT code --- client/Client.cpp | 65 ++++++++++++ client/Client.h | 45 ++++++++ client/HandleMessage.cpp | 47 +++++++++ client/HandleMessage.h | 26 +++++ client/client.pro | 12 +-- client/client.pro.user | 260 +++++++++++++++++++++++++++++++++++++++++++++++ client/main.cpp | 5 - client/mainwindow.cpp | 6 ++ client/mainwindow.h | 5 +- client/mainwindow.ui | 6 +- client/mytcpsocket.cpp | 44 -------- client/mytcpsocket.h | 32 ------ client/timetest.cpp | 18 ---- client/timetest.h | 27 ----- client/ui_mainwindow.h | 2 +- 15 files changed, 462 insertions(+), 138 deletions(-) create mode 100644 client/Client.cpp create mode 100644 client/Client.h create mode 100644 client/HandleMessage.cpp create mode 100644 client/HandleMessage.h create mode 100644 client/client.pro.user delete mode 100644 client/mytcpsocket.cpp delete mode 100644 client/mytcpsocket.h delete mode 100644 client/timetest.cpp delete mode 100644 client/timetest.h diff --git a/client/Client.cpp b/client/Client.cpp new file mode 100644 index 0000000..46952b6 --- /dev/null +++ b/client/Client.cpp @@ -0,0 +1,65 @@ +#include "Client.h" + + + +Client::Client(QObject *parent) : QObject(parent) +{ + // initislise timer and socket + socket = new QTcpSocket(this); + timer = new QTimer(this); +} +Client::~Client() +{ + // delete if called again + delete socket; + delete timer; +} + +void Client::ClientEcho() +{ + QTime time1 = QTime::currentTime(); + NextMinute = time1.minute()+1; + + connect(timer, SIGNAL(timeout()),this,SLOT(timeFunction())); // connect timer to time every minute + + // connect to readyread to receive data; + connect(socket,&QTcpSocket::readyRead, [&]() { + QTextStream T(socket); + QString text = T.readAll(); // reads all data + Handlemsg.ParseToSQL(Handlemsg.ParseMessage(text, (totalRecords-'0'))); + + + }); + + timer->start(1000); +} + +void Client::timeFunction() +{ + if(_missingRecords>1){ + totalRecords = _missingRecords; + } + else{ + totalRecords=1; + } + QByteArray msgToSend= (msg.toUtf8() + totalRecords + offsetRecords +'\n'); + + QTime time = QTime::currentTime(); + qint16 currentMinute = time.minute(); + + if(currentMinute==NextMinute){ + socket->connectToHost(networkAddress, tcpPortAddress); + + socket->write(msgToSend); + NextMinute++; + } +} + +void Client::missingRecords() +{ + QSqlQuery queryTimeData; + queryTimeData.exec("SELECT (unix_timestamp(now()) - unix_timestamp(`time`))/60 as delta FROM `WSdb`.`tblMain` limit 1"); + + _missingRecords = queryTimeData.value(0).toInt(); + +} diff --git a/client/Client.h b/client/Client.h new file mode 100644 index 0000000..10af3e1 --- /dev/null +++ b/client/Client.h @@ -0,0 +1,45 @@ +#ifndef CLIENT_H +#define CLIENT_H +#include +#include +#include +#include +#include + +#include "HandleMessage.h" + +// class client for wheather station +class Client : public QObject +{ + Q_OBJECT +public: + Client(QObject *parent = 0); + virtual ~Client(); + +public slots: + void ClientEcho(); // function to ask data from wheather station + void timeFunction(); // function to look every second what time currently is en handle if minute is passed + +private: + void missingRecords(); + + int _missingRecords; + QTcpSocket *socket; // tcpsocket for communicating + QTimer *timer; // timer to read every second what time it curruntly is. + + qint16 NextMinute; // timing for next minute + // qint16 currentMinute; // timing for currentMinute + HandleMessage Handlemsg; // add HandleMessage to Client.h + + int tcpPortAddress = 80; // port of communication via tcp + QString networkAddress = "192.168.137.76"; // network address for commincation via tcp + + QString msg = "last-records "; // part of mesage to send to wheather staion + char totalRecords = '1'; // total records to ask wheather station + char offsetRecords = '0'; // offset from reqeusting records + + + +}; + +#endif // CLIENT_H diff --git a/client/HandleMessage.cpp b/client/HandleMessage.cpp new file mode 100644 index 0000000..f7f14f4 --- /dev/null +++ b/client/HandleMessage.cpp @@ -0,0 +1,47 @@ +#include "HandleMessage.h" + + +HandleMessage::HandleMessage(QObject *parent) : QObject(parent) +{ + +} + +QString HandleMessage::ParseMessage(const QString Msg , int totalRecords ) +{ + QString message= Msg.section('\n',2,(3+totalRecords)); + + return message; + +} + +void HandleMessage::ParseToSQL(QString input) +{ + QSqlQuery queryInsertData; + QString output = "INSERT INTO `WSdb`.`tblMain` () VALUES "; + QVector data; + QVector list = input.split("\n"); + for (int i = 0; i < list.size(); ++i) { + + output += "("; + + data=list[i].split(","); + + for (int j = 1; j < data.size(); ++j) { + bool valid; + output.append(QString::number(data[j].toInt(&valid, 16))); + if (j <= data[j].size()) { + output.append(","); + } + + } + output.append(")"); + + if (i+1 < list.size()){ + output.append(","); + } + } + queryInsertData.exec(output); +} + + + diff --git a/client/HandleMessage.h b/client/HandleMessage.h new file mode 100644 index 0000000..bfc5063 --- /dev/null +++ b/client/HandleMessage.h @@ -0,0 +1,26 @@ +#ifndef HANDLEMESSAGE_H +#define HANDLEMESSAGE_H + +#include +#include +#include +#include +#include + +class HandleMessage : public QObject +{ + Q_OBJECT +public: + HandleMessage(QObject *parent = 0); + + QString ParseMessage(const QString , int); + void ParseToSQL(QString); + + + +private: + +}; + + +#endif // HANDLEMESSAGE_H diff --git a/client/client.pro b/client/client.pro index d680fba..76f2b56 100644 --- a/client/client.pro +++ b/client/client.pro @@ -1,18 +1,18 @@ QT += core gui sql charts network HEADERS += \ + Client.h \ + HandleMessage.h \ dbconnector.h \ main.h \ - mainwindow.h \ - mytcpsocket.h \ - timetest.h + mainwindow.h SOURCES += \ + Client.cpp \ + HandleMessage.cpp \ dbconnector.cpp \ main.cpp \ - mainwindow.cpp \ - mytcpsocket.cpp \ - timetest.cpp + mainwindow.cpp FORMS += \ diff --git a/client/client.pro.user b/client/client.pro.user new file mode 100644 index 0000000..7ccbc7b --- /dev/null +++ b/client/client.pro.user @@ -0,0 +1,260 @@ + + + + + + EnvironmentId + {aa240e53-c124-4cf0-84a8-30bfe8a2cf83} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + false + true + false + 0 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + + 0 + true + + true + true + Builtin.DefaultTidyAndClazy + 4 + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop Qt 6.4.0 MinGW 64-bit + Desktop Qt 6.4.0 MinGW 64-bit + qt.qt6.640.win64_mingw_kit + 0 + 0 + 0 + + 0 + D:\Github2\avans-whether-station\build-client-Desktop_Qt_6_4_0_MinGW_64_bit-Debug + D:/Github2/avans-whether-station/build-client-Desktop_Qt_6_4_0_MinGW_64_bit-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + D:\Github2\avans-whether-station\build-client-Desktop_Qt_6_4_0_MinGW_64_bit-Release + D:/Github2/avans-whether-station/build-client-Desktop_Qt_6_4_0_MinGW_64_bit-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + D:\Github2\avans-whether-station\build-client-Desktop_Qt_6_4_0_MinGW_64_bit-Profile + D:/Github2/avans-whether-station/build-client-Desktop_Qt_6_4_0_MinGW_64_bit-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + true + + 2 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/client/main.cpp b/client/main.cpp index 8561786..157abe6 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -14,17 +14,12 @@ #include "mainwindow.h" #include "main.h" #include "ui_mainwindow.h" -#include "mytcpsocket.h" -#include "timetest.h" QSqlDatabase dbRef = QSqlDatabase(); int main(int argc, char *argv[]) { QApplication a(argc, argv); - TimeTest time; - MyTcpSocket s; - // s.doConnect(); MainWindow w; dbRef = QSqlDatabase::addDatabase("QMYSQL"); diff --git a/client/mainwindow.cpp b/client/mainwindow.cpp index e1736e6..49fcc26 100644 --- a/client/mainwindow.cpp +++ b/client/mainwindow.cpp @@ -11,6 +11,7 @@ MainWindow::MainWindow(QWidget *parent) , ui(new Ui::MainWindow) { ui->setupUi(this); + client.ClientEcho(); } MainWindow::~MainWindow() @@ -19,6 +20,11 @@ MainWindow::~MainWindow() delete ui; } +void MainWindow::timeFunction() +{ + client.timeFunction(); +} + void MainWindow::on_actionConnection_triggered() { _dbConenctor = new dbConnector(this); diff --git a/client/mainwindow.h b/client/mainwindow.h index 25e22ec..6bcc329 100644 --- a/client/mainwindow.h +++ b/client/mainwindow.h @@ -13,6 +13,7 @@ #include #include "main.h" +#include "Client.h" QT_BEGIN_NAMESPACE @@ -33,7 +34,7 @@ private slots: // void on_actionAbout_triggered(); // void on_pushButton_clicked(); - + void timeFunction(); void on_actionConnection_triggered(); void on_actionRefresh_triggered(); @@ -42,7 +43,7 @@ private slots: private: Ui::MainWindow *ui; - + Client client; dbConnector *_dbConenctor; QChart *_pChart; diff --git a/client/mainwindow.ui b/client/mainwindow.ui index a31ffdc..bbcdf9c 100644 --- a/client/mainwindow.ui +++ b/client/mainwindow.ui @@ -17,8 +17,8 @@ - 270 - 190 + 260 + 240 181 51 @@ -34,7 +34,7 @@ 0 0 800 - 24 + 26 diff --git a/client/mytcpsocket.cpp b/client/mytcpsocket.cpp deleted file mode 100644 index 92dd67a..0000000 --- a/client/mytcpsocket.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include - -MyTcpSocket::MyTcpSocket(QObject *parent) : - QObject(parent) -{ -} - -void MyTcpSocket::doConnect() -{ - socket = new QTcpSocket(this); - - connect(socket, SIGNAL(connected()),this, SLOT(connected())); - connect(socket, SIGNAL(disconnected()),this, SLOT(disconnected())); - // connect(socket, SIGNAL(bytesWritten(qint64)),this, SLOT(bytesWritten(qint64))); - connect(socket, SIGNAL(readyRead()),this, SLOT(readyRead())); - qDebug() << "connectig..."; - - socket->connectToHost("192.168.137.141",80); - - if(!socket->waitForConnected(5000)){ - qDebug()<<"Error: "<< socket->errorString(); - } -} - -void MyTcpSocket::connected(){ - qDebug() << "connected..."; - - socket->write("Weerdata: Temp:?\r\n\r\n\r\n\r\n"); - -} -void MyTcpSocket::disconnected(){ - qDebug() << "disconnected..."; - -} - -void MyTcpSocket::bytesWritten(qint64 bytes){ - qDebug() << bytes << "bytes written..."; - -} -void MyTcpSocket::readyRead(){ - qDebug() << "reading..."; - - qDebug() << socket->readAll(); -} diff --git a/client/mytcpsocket.h b/client/mytcpsocket.h deleted file mode 100644 index 4a7e543..0000000 --- a/client/mytcpsocket.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef MYTCPSOCKET_H -#define MYTCPSOCKET_H - -#include -#include -#include -#include - -class MyTcpSocket : public QObject -{ - Q_OBJECT -public: - explicit MyTcpSocket(QObject *parent = 0); - - void doConnect(); -signals: -public slots: - void connected(); - void disconnected(); - void bytesWritten(qint64 bytes); - void readyRead(); -private: - QTcpSocket *socket; - - - - - -}; - - -#endif // MYTCPSOCKET_H diff --git a/client/timetest.cpp b/client/timetest.cpp deleted file mode 100644 index 2e575f2..0000000 --- a/client/timetest.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "timetest.h" - -TimeTest::TimeTest(QObject *parent) : QObject(parent) -{ - timer = new QTimer(this); - connect(timer, SIGNAL(timeout()),this,SLOT(myfunction())); - timer->start(5000); -} - -qint16 TimeTest::myfunction() -{ - QTime time = QTime::currentTime(); - qint16 time_text = time.minute(); - - return time_text; - - -} diff --git a/client/timetest.h b/client/timetest.h deleted file mode 100644 index aa1d8a5..0000000 --- a/client/timetest.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TIMETEST_H -#define TIMETEST_H -#include -#include -#include -#include - -class TimeTest : public QObject -{ - Q_OBJECT -public: - explicit TimeTest(QObject *parent = 0); - -signals: -public slots: - qint16 myfunction(); - -private: - QTimer *timer; - - - - -}; - - -#endif // TIMETEST_H diff --git a/client/ui_mainwindow.h b/client/ui_mainwindow.h index 46bb29a..69c476b 100644 --- a/client/ui_mainwindow.h +++ b/client/ui_mainwindow.h @@ -10,7 +10,7 @@ #define UI_MAINWINDOW_H #include -#include +// #include #include #include #include -- cgit v1.2.3 From c821f53c45b6705e9e5362d331936c1d4280a163 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sun, 30 Oct 2022 09:21:32 +0100 Subject: finish merge --- client/HandleMessage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/HandleMessage.cpp b/client/HandleMessage.cpp index f7f14f4..aa73828 100644 --- a/client/HandleMessage.cpp +++ b/client/HandleMessage.cpp @@ -18,8 +18,8 @@ void HandleMessage::ParseToSQL(QString input) { QSqlQuery queryInsertData; QString output = "INSERT INTO `WSdb`.`tblMain` () VALUES "; - QVector data; - QVector list = input.split("\n"); + QStringList data; + QStringList list = input.split("\n"); for (int i = 0; i < list.size(); ++i) { output += "("; -- cgit v1.2.3 From 19e1b4ae6f64ad2ef1985be1b1005ebec6618bc0 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sun, 30 Oct 2022 09:30:09 +0100 Subject: add a notable detail to the readme --- readme.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 1b42659..8068030 100644 --- a/readme.md +++ b/readme.md @@ -6,8 +6,10 @@ `client/client.pro` should be tracked under version control, not `client/makefile` - the stm32 makefile uses git submodules to pull necessary files for - compilation. make sure to initialize and sync the git submodules, or re-clone - using the `--recursive` flag. + compilation. make sure to initialize and sync the git submodules, or use the + `--recursive` flag when cloning +- the stm32 firmware expects the esp8266 module to have the official espressif + firmware, not the ai-thinker firmware that the module comes pre-flashed with ## support -- cgit v1.2.3 From 60f954dbaa399f8f0bcaeeb307953fc3b37b9dc7 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sun, 30 Oct 2022 09:37:04 +0100 Subject: update todo and move to repo root --- stm32f091/server.c | 3 --- stm32f091/todo.md | 28 ---------------------------- todo.md | 28 ++++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 31 deletions(-) delete mode 100644 stm32f091/todo.md create mode 100644 todo.md diff --git a/stm32f091/server.c b/stm32f091/server.c index 112d23a..d69ef1e 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -55,9 +55,6 @@ static bool ws_server_is_response(char data, uint8_t* counter, const char* cmd, return false; } -// TODO: next_few_bytes_are assumes that the complete search string is in the -// buffer, so won't work for buffer cutoffs -#define next_few_bytes_are(code) (((i + sizeof(code) - 2) < size) && (strncmp((char*)&data[i], code, sizeof(code) - 1) == 0)) void ws_server_req_incoming(uint8_t* data, size_t size) { #ifdef WS_DBG_PRINT_ESP_OVER_USART2 ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_RX); diff --git a/stm32f091/todo.md b/stm32f091/todo.md deleted file mode 100644 index 1d42bf8..0000000 --- a/stm32f091/todo.md +++ /dev/null @@ -1,28 +0,0 @@ -# things that have to get fixed before monday - -- [ ] more documentation in header files (for both client and stm code) -- [ ] design/architecture document -- [x] more tests in the test document -- [ ] handle errors from `AT+CIPSEND`, these look like this: - ``` - > AT0,CONNECT - - > +IPD,0,15:last-records 5<0a> - < AT+CIPSEND=0,125 - > AT+CIPSEND=0,125 - - > ERROR - ``` - -## `// TODO:`'s - -- [ ] `sensor.c:24: return (uint8_t) temp_c; //TODO: convert with range -> util.h` -- [ ] `sensor.c:36: return (uint8_t) humidity; //TODO: convert with range -> util.h` -- [ ] `sensor.c:51: return (uint8_t) val; // TODO: convert with range` -- [ ] `server.c:47:// TODO: next_few_bytes_are assumes that the complete search string is in the` -- [ ] `server.c:146: // TODO: buffer overrun protection` -- [ ] `server.c:152:// TODO: refactor this` -- [ ] `server.c:165:// TODO: refactor this` -- [ ] `server.c:174:// TODO: refactor this` -- [ ] `setup.c:95: // TODO: remove debug size` -- [ ] `setup.c:187: .Pin = GPIO_PIN_8|GPIO_PIN_9, //TODO: use #defines in setup.h` diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..5924b20 --- /dev/null +++ b/todo.md @@ -0,0 +1,28 @@ +# things that have to get fixed before monday + +- [ ] more documentation in header files (for both client and stm code) +- [ ] design/architecture document +- [x] more tests in the test document +- [x] handle errors from `AT+CIPSEND`, these look like this: + ``` + > AT0,CONNECT + + > +IPD,0,15:last-records 5<0a> + < AT+CIPSEND=0,125 + > AT+CIPSEND=0,125 + + > ERROR + ``` + +## `// TODO:`'s + +- [ ] `sensor.c:24: return (uint8_t) temp_c; //TODO: convert with range -> util.h` +- [ ] `sensor.c:36: return (uint8_t) humidity; //TODO: convert with range -> util.h` +- [ ] `sensor.c:51: return (uint8_t) val; // TODO: convert with range` +- [x] `server.c:47:// TODO: next_few_bytes_are assumes that the complete search string is in the` +- [ ] `server.c:146: // TODO: buffer overrun protection` +- [x] `server.c:152:// TODO: refactor this` +- [x] `server.c:165:// TODO: refactor this` +- [x] `server.c:174:// TODO: refactor this` +- [ ] `setup.c:95: // TODO: remove debug size` +- [ ] `setup.c:187: .Pin = GPIO_PIN_8|GPIO_PIN_9, //TODO: use #defines in setup.h` -- cgit v1.2.3