#include #include #include #include #include #include "mocs.h" extern "C" { #include "tcp_cmd.h" } #define MAX_TOKENS 10 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; } static void tcp_cmd_parser(struct tcp_pcb* pcb, int argc, char** argv) { char* ext; if (argc == 0) { LOG_WARN(TAG, "No command given"); return; } str_tolower(argv[0]); if (strcmp(argv[0], "help") == 0) { tcp_cmd_print_help(pcb); return; } 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; } tcp_cmd_write(pcb, "Usage: text \"\"\n"); tcp_cmd_write(pcb, "Usage: text \n"); return; } if (strcmp(argv[0], "bgcolor") == 0) { if (argc == 2) { color_bg = (uint32_t)strtol(argv[1], NULL, 16); color_bg |= 0xff000000; return; } if (argc == 4) { color_bg = 0xff000000; color_bg |= (uint32_t)(atoi(argv[1]) && 0xff) << 16; color_bg |= (uint32_t)(atoi(argv[2]) && 0xff) << 8; color_bg |= (uint32_t)(atoi(argv[3]) && 0xff); return; } tcp_cmd_write(pcb, "Usage: bgcolor \n"); tcp_cmd_write(pcb, "Usage: bgcolor r g b\n"); return; } if (strcmp(argv[0], "color") == 0) { if (argc == 2) { color_txt = (uint32_t)strtol(argv[1], NULL, 16); color_txt |= 0xff000000; return; } if (argc == 4) { color_txt = 0xff000000; color_txt |= (uint32_t)(atoi(argv[1]) && 0xff) << 16; color_txt |= (uint32_t)(atoi(argv[2]) && 0xff) << 8; color_txt |= (uint32_t)(atoi(argv[3]) && 0xff); return; } tcp_cmd_write(pcb, "Usage: color 0x\n"); tcp_cmd_write(pcb, "Usage: color \n"); return; } 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; } 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; } } if (argc == 2) { lcd_clear_images(); lcd_draw_img_from_fs(argv[1], 0, 0); return; } if (argc == 4) { lcd_clear_images(); lcd_draw_img_from_fs(argv[1], (uint32_t)atoi(argv[2]), (uint32_t)atoi(argv[3])); return; } tcp_cmd_write(pcb, "Usage: setimage \n"); tcp_cmd_write(pcb, "Usage: setimage \n"); return; } else 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; } } if (argc == 2) { lcd_clear_images(); lcd_draw_gif_from_fs(argv[1], 0, 0); return; } if (argc == 4) { lcd_clear_images(); lcd_draw_gif_from_fs(argv[1], (uint32_t)atoi(argv[2]), (uint32_t)atoi(argv[3])); return; } tcp_cmd_write(pcb, "Usage: setgif \n"); tcp_cmd_write(pcb, "Usage: setgif \n"); return; } if (strcmp(argv[0], "exit") == 0) { tcp_cmd_write(pcb, "Exiting...\n"); lcd_clear_images(); lcd_clear_text(); tcp_close(pcb); return; } 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"); } static err_t tcp_cmd_recv_new(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err) { int argc = 0; char* argv[MAX_TOKENS]; LWIP_UNUSED_ARG(arg); if (err == ERR_OK && p != NULL) { tcp_recved(pcb, p->tot_len); char* next; // Make sure the string is null terminated p->payload = realloc(p->payload, p->len + 1); p->tot_len = p->len + 1; ((char*)(p->payload))[p->len] = '\0'; remove_newline((char*)(p->payload)); // Split string into tokens by delimiter (space) argv[0] = get_next_token((char*)(p->payload), " ", &next); argc = 1; while (argv[argc - 1] != NULL && argc < MAX_TOKENS) { argv[argc] = get_next_token(NULL, " ", &next); if (argv[argc] == NULL) { break; } argc++; } tcp_cmd_parser(pcb, argc, argv); } else { pbuf_free(p); } if (err == ERR_OK && p == NULL) { tcp_cmd_close(pcb); } tcp_cmd_write(pcb, "$> "); 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"); tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK); EXPECT_EQ(0, strcmp("help", (char*)p.payload)); strcpy(cmd, "text \"This is printed on the display\""); tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK); EXPECT_EQ(0, strcmp("text", (char*)p.payload)); strcpy(cmd, "color 0xffffff"); tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK); EXPECT_EQ(0, strcmp("color", (char*)p.payload)); strcpy(cmd, "text \"This is printed on the display\""); tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK); EXPECT_EQ(0, strcmp("text", (char*)p.payload)); strcpy(cmd, "setImage \"test.bmp\""); tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK); EXPECT_EQ(0, strcmp("setimage", (char*)p.payload)); strcpy(cmd, "setImage \"test.gif\""); tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK); EXPECT_EQ(0, strcmp("setimage", (char*)p.payload)); strcpy(cmd, "setGif \"test.gif\""); tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK); EXPECT_EQ(0, strcmp("setgif", (char*)p.payload)); strcpy(cmd, "setGif \"test.bmp\""); tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK); EXPECT_EQ(0, strcmp("setgif", (char*)p.payload)); strcpy(cmd, "exit"); tcp_cmd_recv_new(NULL, NULL, &p, ERR_OK); EXPECT_EQ(0, strcmp("exit", (char*)p.payload)); free(cmd); }