aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2022-10-29 17:15:56 +0200
committerlonkaars <loek@pipeframe.xyz>2022-10-29 17:15:56 +0200
commit9947b4aa803b0430e38be3bd6f7179b45b201213 (patch)
tree3a4198da27ea0d200a31c2d28638df590480e792
parentf536fb4f92eda7ba5e80230a023b144d373dd86b (diff)
send data in chunks for reliability
-rw-r--r--stm32f091/esp8266.c6
-rw-r--r--stm32f091/protocol.c4
-rw-r--r--stm32f091/server.c108
-rw-r--r--stm32f091/server.h24
-rw-r--r--stm32f091/todo.md2
-rw-r--r--stm32f091/util.h2
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
@@ -26,6 +26,17 @@ typedef enum {
} 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;
unsigned int current_channel;
@@ -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