move functions from test file to project
This commit is contained in:
2023-11-30 21:26:16 +01:00
parent 5bc3250c15
commit b7a924719e
3 changed files with 249 additions and 397 deletions

View File

@@ -9,310 +9,60 @@ extern "C" {
#include "tcp_cmd.h"
}
#define MAX_TOKENS 10
#define MAX_CMD_LEN 50
static uint32_t color_txt = 0;
static uint32_t color_bg = 0;
static const char* TAG = "tcp_cmd";
static void tcp_cmd_close(struct tcp_pcb* pcb) {
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
tcp_close(pcb);
}
void remove_newline(char* str) {
int i = 0;
while (str[i] != '\0') {
if (str[i] == '\n' || str[i] == '\r') {
str[i] = '\0';
}
i++;
}
}
void str_tolower(char* str) {
int i = 0;
while (str[i] != '\0') {
str[i] = (char)tolower((int)str[i]);
i++;
}
}
char* get_filename_ext(char* filename) {
char* dot = strrchr(filename, '.');
if (!dot || dot == filename)
return NULL;
return dot + 1;
}
// Function to find the next token in the input string
// If the token is between quotes, return the whole string between quotes
char* get_next_token(char* input, const char* delimiters, char** next) {
if (input == NULL) {
input = *next;
}
// Skip leading delimiters
input += strspn(input, delimiters);
if (*input == '\0') {
return NULL;
}
// If the token is between quotes, return the whole string between quotes
if (*input == '"') {
char* end = strchr(++input, '"');
if (end == NULL) {
return NULL;
}
*end = '\0';
*next = end + 1;
return input;
}
// Find the end of the token
char* end = input + strcspn(input, delimiters);
if (*end == '\0') {
*next = end;
} else {
*end = '\0';
*next = end + 1;
}
return input;
}
/**
* @brief This function parses the command and calls the appropriate function
*
* @param pcb Pointer to the tcp_pcb struct to write to
* @param argc Count of arguments
* @param argv Array of arguments
* @return true Connection should be closed
* @return false Connection should be kept open
*/
static bool tcp_cmd_parser(struct tcp_pcb* pcb, int argc, char** argv) {
char* ext;
if (argc == 0) {
LOG_WARN(TAG, "No command given");
return false;
}
str_tolower(argv[0]);
if (strcmp(argv[0], "help") == 0) {
tcp_cmd_print_help(pcb);
return false;
} if (strcmp(argv[0], "text") == 0) {
if (argc == 2) {
lcd_clear_text();
lcd_display_text((uint8_t*)argv[1], 10, 10, color_txt, color_bg, LCD_FONT24);
return false;
}
tcp_cmd_write(pcb, "Usage: text \"<text>\"\n");
tcp_cmd_write(pcb, "Usage: text <word>\n");
return false;
} if (strcmp(argv[0], "bgcolor") == 0) {
if (argc == 2) {
color_bg = (uint32_t)strtol(argv[1], NULL, 16);
color_bg |= 0xff000000;
return false;
} if (argc == 4) {
color_bg = 0xff000000;
color_bg |= (uint32_t)strtol(argv[1], NULL, 10) << 16;
color_bg |= (uint32_t)strtol(argv[2], NULL, 10) << 8;
color_bg |= (uint32_t)strtol(argv[3], NULL, 10);
return false;
}
tcp_cmd_write(pcb, "Usage: bgcolor <background color>\n");
tcp_cmd_write(pcb, "Usage: bgcolor r g b\n");
return false;
} if (strcmp(argv[0], "color") == 0) {
if (argc == 2) {
color_txt = (uint32_t)strtol(argv[1], NULL, 16);
color_txt |= 0xff000000;
return false;
} if (argc == 4) {
color_txt = 0xff000000;
color_txt |= (uint32_t)strtol(argv[1], NULL, 10) << 16;
color_txt |= (uint32_t)strtol(argv[2], NULL, 10) << 8;
color_txt |= (uint32_t)strtol(argv[3], NULL, 10);
return false;
}
tcp_cmd_write(pcb, "Usage: color 0x<txt color>\n");
tcp_cmd_write(pcb, "Usage: color <r> <g> <b>\n");
return false;
} if (strcmp(argv[0], "listimages") == 0) {
void* mem = NULL; // Pointer for internal use by the llfs library
llfs_file_t* file;
while ((file = llfs_next_file(&mem, NULL)) != NULL) {
tcp_cmd_write(pcb, file->name);
tcp_cmd_write(pcb, "\r\n");
}
return false;
} if (strcmp(argv[0], "setimage") == 0) {
if (argc >= 2) {
ext = get_filename_ext(argv[1]);
if (strcmp(ext, "bmp") != 0) {
tcp_cmd_write(pcb, "File is not a bmp\n");
return false;
}
} if (argc == 2) {
lcd_clear_images();
lcd_draw_img_from_fs(argv[1], 0, 0);
return false;
} if (argc == 4) {
lcd_clear_images();
lcd_draw_img_from_fs(argv[1], (uint32_t)atoi(argv[2]), (uint32_t)atoi(argv[3]));
return false;
}
tcp_cmd_write(pcb, "Usage: setimage <filename>\n");
tcp_cmd_write(pcb, "Usage: setimage <filename> <x> <y>\n");
return false;
} if (strcmp(argv[0], "setgif") == 0) {
if (argc >= 2) {
char* ext = get_filename_ext(argv[1]);
if (strcmp(ext, "gif") != 0) {
tcp_cmd_write(pcb, "File is not a gif\n");
return false;
}
} if (argc == 2) {
lcd_clear_images();
lcd_draw_gif_from_fs(argv[1], 0, 0);
return false;
} if (argc == 4) {
lcd_clear_images();
lcd_draw_gif_from_fs(argv[1], (uint32_t)atoi(argv[2]), (uint32_t)atoi(argv[3]));
return false;
}
tcp_cmd_write(pcb, "Usage: setgif <filename>\n");
tcp_cmd_write(pcb, "Usage: setgif <filename> <x> <y>\n");
return false;
} if (strcmp(argv[0], "exit") == 0) {
tcp_cmd_write(pcb, "Exiting...\n");
lcd_clear_images();
lcd_clear_text();
tcp_close(pcb);
return true;
}
tcp_cmd_write(pcb, "Unknown command: ");
tcp_cmd_write(pcb, argv[0]);
tcp_cmd_write(pcb, "\n");
tcp_cmd_write(pcb, "Type help for list of commands\r\n");
return false;
}
static err_t tcp_cmd_recv_new(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err) {
int argc = 0;
char cmd[MAX_CMD_LEN];
char* argv[MAX_TOKENS];
bool close_conn = false;
char* next;
LWIP_UNUSED_ARG(arg);
LOG_DEBUG(TAG, "TCP data received");
// Connection closed?
if (p == NULL && err == ERR_OK) {
LOG_INFO(TAG, "Remote closed connection");
return tcp_close(pcb);
}
if (err != ERR_OK) {
LOG_WARN(TAG, "TCP data received with error(%d): %s", err, lwip_strerr(err));
return ERR_OK;
}
// Make sure the string is null terminated
if (p->len >= MAX_CMD_LEN) {
LOG_WARN(TAG, "Command too long");
}
uint16_t len = p->tot_len >= MAX_CMD_LEN ? MAX_CMD_LEN : p->tot_len;
pbuf_copy_partial(p, cmd, len, 0);
cmd[len] = '\0';
// Tell the tcp stack that we have taken the data
tcp_recved(pcb, p->tot_len);
remove_newline(cmd);
// Split string into tokens by delimiter (space)
argv[0] = get_next_token(cmd, " ", &next);
argc = 1;
while (argv[argc - 1] != NULL && argc < MAX_TOKENS) {
argv[argc] = get_next_token(NULL, " ", &next);
if (argv[argc] == NULL) {
break;
}
argc++;
}
close_conn = tcp_cmd_parser(pcb, argc, argv);
if (close_conn) {
tcp_cmd_close(pcb);
} else {
tcp_cmd_write(pcb, "$> ");
}
defer:
pbuf_free(p);
return ERR_OK;
}
TEST(TCP_CMD, tcp_data_cb) {
char* cmd = (char*)calloc(50, 1);
pbuf p = {.next = NULL, .payload = (void*)cmd, .tot_len = 4, .len = 0, .type_internal = 0, .flags = 0, .if_idx = 0};
strcpy(cmd, "help");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "text \"This is printed on the display\"");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "color 0x555555");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "bgcolor 0xAAAAAA");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "text \"This is printed on the display\"");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "color 255 255 255");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "bgcolor 255 255 255");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "text \"This is printed on the display\"");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "setImage \"test.bmp\"");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "setImage \"test.gif\"");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "setGif \"test.gif\"");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "setGif \"test.bmp\"");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
strcpy(cmd, "exit");
p.tot_len = (uint16_t)strlen(cmd);
tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK);
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
free(cmd);
}