#include #include "tcp_server.h" #include "sockbuf.h" #include "lwip/sockets.h" #include "station.h" static int strcmp_(const char* s1, const char* s2) { if (!s1) { return !s2; } if (!s2) { return !s1; } return strcmp(s1, s2); } static char* read_token(sockbuf_t* sockbuf, char* into, size_t sz) { int cur = 0; int ch = get_char(sockbuf); while (ch >= 0 && isspace(ch)) { ch = get_char(sockbuf); } while (ch >= 0 && !isspace(ch)) { if (sz > 1) { into[cur++] = (char) ch; sz --; } ch = get_char(sockbuf); } if (ch < 0) { return NULL; } if (sz >= 1) { into[cur] = 0; } return into; } static void handle_int_option( const char* attr, sockbuf_t* sockbuf, int* ptr) { char op_[8]; char buf_[32]; char* op = read_token(sockbuf, op_, sizeof(op_)); char* value = read_token(sockbuf, buf_, sizeof(buf_)); int curval = *ptr; int ivalue = atoi(value); if (!strcmp_(op, "+=")) { curval += ivalue; } else if (!strcmp_(op, "-=")) { curval -= ivalue; } else if (!strcmp_(op, "=")) { curval = ivalue; } else { sockbuf_write(sockbuf, "Unknown operation: '"); sockbuf_write(sockbuf, op); sockbuf_write(sockbuf, "'\n"); return; } snprintf(buf_, sizeof(buf_), "%s = %d\n", attr, curval); *ptr = curval; sockbuf_write(sockbuf, buf_); } static void handle_uint8_option( const char* attr, sockbuf_t* sockbuf, uint8_t* ptr) { int tmp = *ptr; handle_int_option(attr, sockbuf, &tmp); *ptr = tmp; } static void handle_uint32_option( const char* attr, sockbuf_t* sockbuf, uint32_t* ptr) { int tmp = *ptr; handle_int_option(attr, sockbuf, &tmp); *ptr = tmp; } static void handle_bool_option( const char* attr, sockbuf_t* sockbuf, bool* ptr) { char buf_[32]; char* op = read_token(sockbuf, buf_, sizeof(buf_)); bool curval = *ptr; if (!strcmp(op, "on")) { curval = 1; } else if (!strcmp(op, "off")) { curval = 0; } else if (!strcmp(op, "toggle")) { curval = !curval; } else { sockbuf_write(sockbuf, "Invalid value: '"); sockbuf_write(sockbuf, op); sockbuf_write(sockbuf, "'\n"); return; } *ptr = curval; snprintf(buf_, sizeof(buf_), "%s = %s\n", attr, curval ? "on" : "off"); sockbuf_write(sockbuf, buf_); } #define HANDLE_UINT8_OPTION(attr) \ else if (!strcmp_(key, #attr)) { \ handle_uint8_option(#attr, sockbuf, &ws_params->state. attr); \ } #define HANDLE_INT_OPTION(attr) \ else if (!strcmp_(key, #attr)) { \ handle_int_option(#attr, sockbuf, &ws_params->state. attr); \ } #define HANDLE_UINT32_OPTION(attr) \ else if (!strcmp_(key, #attr)) { \ handle_uint32_option(#attr, sockbuf, &ws_params->state. attr); \ } #define HANDLE_BOOL_OPTION(attr) \ else if (!strcmp_(key, #attr)) { \ handle_bool_option(#attr, sockbuf, &ws_params->state. attr); \ } static void handle_set_cmd( sockbuf_t* sockbuf, ws_params_t* ws_params, const char* key) { if (false) {} HANDLE_UINT8_OPTION(brightness) HANDLE_UINT8_OPTION(n_snow) HANDLE_UINT8_OPTION(n_red) HANDLE_INT_OPTION(timetick) HANDLE_UINT32_OPTION(time) HANDLE_BOOL_OPTION(sleep) HANDLE_BOOL_OPTION(power) HANDLE_BOOL_OPTION(cool) else { sockbuf_write(sockbuf, "Unknown attribute: '"); sockbuf_write(sockbuf, key); sockbuf_write(sockbuf, "'\n"); } } #define PRINT_INT(attr) \ snprintf(buf, sizeof(buf), #attr ": %d\n", (int) ws_params->state. attr); \ sockbuf_write(sockbuf, buf) #define PRINT_BOOL(attr) \ snprintf(buf, sizeof(buf), #attr ": %s\n", \ ws_params->state. attr ? "on" : "off"); \ sockbuf_write(sockbuf, buf) static void handle_print_cmd(sockbuf_t* sockbuf, ws_params_t* ws_params) { char buf[128]; PRINT_INT(time); PRINT_INT(timetick); PRINT_INT(brightness); PRINT_INT(off); PRINT_INT(n_snow); PRINT_INT(n_red); PRINT_BOOL(sleep); PRINT_BOOL(power); PRINT_BOOL(cool); } static void run_sockbuf(sockbuf_t* sockbuf, ws_params_t* ws_params) { char buf[128]; while (true) { char* cmd = read_token(sockbuf, buf, sizeof(buf)); if (!cmd) { break; } if (!strcmp_(cmd, "set")) { char* key = read_token(sockbuf, buf, sizeof(buf)); if (key) { handle_set_cmd(sockbuf, ws_params, key); } } else if (!strcmp_(cmd, "print")) { handle_print_cmd(sockbuf, ws_params); } else if (!strcmp_(cmd, "end")) { close(sockbuf->socket); return; } else { sockbuf_write(sockbuf, "Unknown command: '"); sockbuf_write(sockbuf, cmd); sockbuf_write(sockbuf, "'\n"); } } } portTASK_FUNCTION(tcp_server, params) { ws_params_t* ws_params = (ws_params_t*) params; wifi_init_station("Wort", "JoshIsBau5"); int s = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_port = htons(1234); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; int err = bind(s, (struct sockaddr*)&addr, sizeof(addr)); if (err) { printf("Error binding to sockaddr: %d\n", err); return; } printf("Listening ...\n"); listen(s, 1); while (true) { printf("Waiting for connection... \n"); struct sockaddr_in client_addr; socklen_t size; int sock = accept(s, (struct sockaddr*)&client_addr, &size); printf("Accepted connection\n"); sockbuf_t sockbuf; init_sockbuf(&sockbuf, sock); run_sockbuf(&sockbuf, ws_params); ssize_t len; char buf[128]; while ((len = read(sock, buf, sizeof(buf) - 1)) > 0) { buf[len] = 0; printf("Read %s\n", buf); if (!strcmp_(buf, "off\n")) { ws_params->state.power = 0; } if (!strcmp_(buf, "on\n")) { ws_params->state.power = 1; } for (int i = 0; i < len; ++ i) { switch (buf[i]) { case '+': ws_params->state.brightness += 10; break; case '-': ws_params->state.brightness -= 10; break; } } } } }