aboutsummaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/CMakeLists.txt7
-rw-r--r--main/sockbuf.c43
-rw-r--r--main/tcp_server.c230
3 files changed, 279 insertions, 1 deletions
diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt
index 60434ca..9ecb402 100644
--- a/main/CMakeLists.txt
+++ b/main/CMakeLists.txt
@@ -1,2 +1,7 @@
-idf_component_register(SRCS "main.c" "station.c" "ws2812b_writer.c" "tcp_server.c"
+idf_component_register(SRCS
+ "main.c"
+ "station.c"
+ "ws2812b_writer.c"
+ "tcp_server.c"
+ "sockbuf.c"
INCLUDE_DIRS "../include")
diff --git a/main/sockbuf.c b/main/sockbuf.c
new file mode 100644
index 0000000..0fede63
--- /dev/null
+++ b/main/sockbuf.c
@@ -0,0 +1,43 @@
+#include "sockbuf.h"
+
+#include <unistd.h>
+#include <string.h>
+
+void sockbuf_write(sockbuf_t* sockbuf, const char* value)
+{
+ write(sockbuf->socket, value, strlen(value));
+}
+
+sockbuf_t* init_sockbuf(sockbuf_t* sockbuf, int socket)
+{
+ memset(sockbuf, 0, sizeof(sockbuf_t));
+ sockbuf->socket = socket;
+
+ return sockbuf;
+}
+
+int peek_char(sockbuf_t* sockbuf)
+{
+ if (sockbuf->next == sockbuf->last) {
+ sockbuf->next = 0;
+ int size = read(sockbuf->socket, sockbuf->buf, sizeof(sockbuf->buf));
+ sockbuf->last = (uint8_t) size;
+
+ if (size <= 0) {
+ return size - 1;
+ }
+ }
+
+ return sockbuf->buf[sockbuf->next];
+}
+
+int get_char(sockbuf_t* sockbuf)
+{
+ int ret = peek_char(sockbuf);
+
+ if (ret >= 0) {
+ sockbuf->next ++;
+ }
+
+ return ret;
+}
diff --git a/main/tcp_server.c b/main/tcp_server.c
index f50dc21..7bfaa61 100644
--- a/main/tcp_server.c
+++ b/main/tcp_server.c
@@ -1,8 +1,226 @@
+#include <ctype.h>
+
#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;
@@ -32,6 +250,10 @@ portTASK_FUNCTION(tcp_server, params)
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];
@@ -40,6 +262,14 @@ portTASK_FUNCTION(tcp_server, params)
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 '+':