aboutsummaryrefslogtreecommitdiff
path: root/main/param
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2025-12-07 13:04:02 -0700
committerJosh Rahm <joshuarahm@gmail.com>2025-12-07 13:04:02 -0700
commit42f4c42676d42619d530db27e7a2a0b76fbf9253 (patch)
tree01ebd66f55aeb9a7c2113ebde3508a2cb1f01f5a /main/param
parent3f8b6e6f34275bdba501e3b1cddab43331b6f569 (diff)
downloadesp32-ws2812b-42f4c42676d42619d530db27e7a2a0b76fbf9253.tar.gz
esp32-ws2812b-42f4c42676d42619d530db27e7a2a0b76fbf9253.tar.bz2
esp32-ws2812b-42f4c42676d42619d530db27e7a2a0b76fbf9253.zip
Clean up how parameters work.
Formalize a poor-man's Parameter "typeclass" and create "instances". This makes things way less ad-hoc.
Diffstat (limited to 'main/param')
-rw-r--r--main/param/CMakeLists.txt2
-rw-r--r--main/param/bool.c81
-rw-r--r--main/param/color_int.c96
-rw-r--r--main/param/int.c99
-rw-r--r--main/param/uint32_t.c43
-rw-r--r--main/param/uint8_t.c42
6 files changed, 363 insertions, 0 deletions
diff --git a/main/param/CMakeLists.txt b/main/param/CMakeLists.txt
new file mode 100644
index 0000000..614a7e3
--- /dev/null
+++ b/main/param/CMakeLists.txt
@@ -0,0 +1,2 @@
+file(GLOB PARAM_SRCS "${CMAKE_CURRENT_LIST_DIR}/*.c")
+set(PARAM_SRCS ${PARAM_SRCS} PARENT_SCOPE)
diff --git a/main/param/bool.c b/main/param/bool.c
new file mode 100644
index 0000000..46b6ebb
--- /dev/null
+++ b/main/param/bool.c
@@ -0,0 +1,81 @@
+#include "param.h"
+#include "http_server.h"
+
+void cmd_handle(bool)(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_);
+}
+
+size_t serialize_to_json(bool)(
+ char** out, size_t len, const char* attr, const char* dn, bool value)
+{
+ size_t newlen = snprintf(
+ *out,
+ len,
+ "\"%s\":{\"type\":\"bool\",\"value\":\"%s\",\"disp\":\"%s\"}",
+ attr,
+ value ? "on" : "off",
+ dn);
+ *out += newlen;
+ return len - newlen;
+}
+
+#define TAG "serialize"
+void http_handle(bool)(httpd_req_t* req, bool* val)
+{
+ char buf[128];
+ int buf_len = httpd_req_get_url_query_len(req) + 1;
+
+ if (buf_len > 1) {
+ if (buf_len > sizeof(buf)) {
+ ESP_LOGI(TAG, "Invalid request. Query string too long.");
+ httpd_resp_set_status(req, HTTPD_400);
+ return;
+ }
+
+ if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
+ char param[32];
+ if (httpd_query_key_value(buf, "set", param, sizeof(param)) == ESP_OK) {
+ if (!strcmp(param, "on")) {
+ *val = true;
+ } else if (!strcmp(param, "off")) {
+ *val = false;
+ } else if (!strcmp(param, "toggle")) {
+ *val = !*val;
+ } else {
+ ESP_LOGI(TAG, "Invalid request. Invalid param value.");
+ httpd_resp_set_status(req, HTTPD_400);
+ return;
+ }
+ }
+ }
+ }
+
+ httpd_resp_set_status(req, HTTPD_204);
+}
+
+void print(bool)(sockbuf_t* sockbuf, const char* attr, bool val)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%s: %s :: bool\n", attr, val ? "on" : "off");
+ sockbuf_write(sockbuf, buf);
+}
diff --git a/main/param/color_int.c b/main/param/color_int.c
new file mode 100644
index 0000000..0b8b002
--- /dev/null
+++ b/main/param/color_int.c
@@ -0,0 +1,96 @@
+#include "param.h"
+#include "http_server.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+void cmd_handle(color_int_t)(
+ const char* attr, sockbuf_t* sockbuf, color_int_t* ptr)
+{
+ char buf_[32];
+ char* value = read_token(sockbuf, buf_, sizeof(buf_));
+
+ if (!value) {
+ sockbuf_write(sockbuf, "Missing color value\n");
+ return;
+ }
+
+ char* p = value;
+ if (*p == '#') {
+ p++;
+ } else if (!strncasecmp(p, "0x", 2)) {
+ p += 2;
+ }
+
+ char* end = NULL;
+ unsigned long parsed = strtoul(p, &end, 16);
+ if (end == p || *end != '\0' || parsed > 0xFFFFFFUL) {
+ sockbuf_write(sockbuf, "Invalid color; expected hex like RRGGBB\n");
+ return;
+ }
+
+ *ptr = (color_int_t)parsed;
+ snprintf(buf_, sizeof(buf_), "%s = 0x%06lx\n", attr, parsed);
+ sockbuf_write(sockbuf, buf_);
+}
+
+size_t serialize_to_json(color_int_t)(
+ char** out, size_t len, const char* attr, const char* dn, color_int_t value)
+{
+ size_t newlen = snprintf(
+ *out,
+ len,
+ "\"%s\":{\"type\":\"color\",\"value\":\"#%06lx\",\"disp\":\"%s\"}",
+ attr,
+ (unsigned long)(value & 0xFFFFFF),
+ dn);
+ *out += newlen;
+ return len - newlen;
+}
+
+#define TAG "param_color"
+void http_handle(color_int_t)(httpd_req_t* req, color_int_t* val)
+{
+ char buf[128];
+ int buf_len = httpd_req_get_url_query_len(req) + 1;
+
+ if (buf_len > 1) {
+ if (buf_len > sizeof(buf)) {
+ ESP_LOGI(TAG, "Invalid request. Query string too long.");
+ httpd_resp_set_status(req, HTTPD_400);
+ return;
+ }
+
+ if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
+ char param[32];
+ if (httpd_query_key_value(buf, "set", param, sizeof(param)) == ESP_OK) {
+ char* p = param;
+ if (*p == '#') {
+ p++;
+ } else if (!strncasecmp(p, "0x", 2)) {
+ p += 2;
+ }
+ char* end = NULL;
+ unsigned long parsed = strtoul(p, &end, 16);
+ if (end == p || *end != '\0' || parsed > 0xFFFFFFUL) {
+ ESP_LOGI(TAG, "Invalid request. Invalid color value.");
+ httpd_resp_set_status(req, HTTPD_400);
+ return;
+ }
+ *val = (color_int_t)parsed;
+ }
+ }
+ }
+
+ httpd_resp_set_status(req, HTTPD_204);
+}
+
+void print(color_int_t)(
+ sockbuf_t* sockbuf, const char* attr, color_int_t val)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%s: 0x%06lx :: color\n", attr, (unsigned long)val);
+ sockbuf_write(sockbuf, buf);
+}
diff --git a/main/param/int.c b/main/param/int.c
new file mode 100644
index 0000000..758180a
--- /dev/null
+++ b/main/param/int.c
@@ -0,0 +1,99 @@
+#include "param.h"
+#include "http_server.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void cmd_handle(int)(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 = value ? atoi(value) : 0;
+ 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_);
+}
+
+size_t serialize_to_json(int)(
+ char** out, size_t len, const char* attr, const char* dn, int value)
+{
+ size_t newlen = snprintf(
+ *out,
+ len,
+ "\"%s\":{\"type\":\"int\",\"value\":\"%d\",\"disp\":\"%s\"}",
+ attr,
+ value,
+ dn);
+ *out += newlen;
+ return len - newlen;
+}
+
+#define TAG "param_int"
+void http_handle(int)(httpd_req_t* req, int* val)
+{
+ char buf[128];
+ int buf_len = httpd_req_get_url_query_len(req) + 1;
+ esp_err_t err;
+
+ if (buf_len > 1) {
+ if (buf_len > sizeof(buf)) {
+ ESP_LOGI(TAG, "Invalid request. Query string too long.");
+ httpd_resp_set_status(req, HTTPD_400);
+ return;
+ }
+
+ if ((err = httpd_req_get_url_query_str(req, buf, buf_len)) == ESP_OK) {
+ char param[32];
+ if (httpd_query_key_value(buf, "add", param, sizeof(param)) == ESP_OK) {
+ *val += atoi(param);
+ } else if (
+ httpd_query_key_value(buf, "set", param, sizeof(param)) == ESP_OK) {
+ *val = atoi(param);
+ } else if (
+ httpd_query_key_value(buf, "sub", param, sizeof(param)) == ESP_OK) {
+ *val -= atoi(param);
+ } else {
+ ESP_LOGI(TAG, "No valid parameters.");
+ httpd_resp_set_status(req, HTTPD_400);
+ return;
+ }
+ } else {
+ ESP_LOGI(TAG, "Unable to get URL query string. [%d]", err);
+ httpd_resp_set_status(req, HTTPD_500);
+ return;
+ }
+ } else {
+ ESP_LOGI(TAG, "No query string provided?");
+ httpd_resp_set_status(req, HTTPD_400);
+ return;
+ }
+
+ ESP_LOGI(TAG, "Now equals %d", *val);
+ httpd_resp_set_status(req, HTTPD_204);
+}
+
+void print(int)(sockbuf_t* sockbuf, const char* attr, int val)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%s: %d :: int\n", attr, val);
+ sockbuf_write(sockbuf, buf);
+}
diff --git a/main/param/uint32_t.c b/main/param/uint32_t.c
new file mode 100644
index 0000000..2c256c1
--- /dev/null
+++ b/main/param/uint32_t.c
@@ -0,0 +1,43 @@
+#include "param.h"
+#include "http_server.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void cmd_handle(uint32_t)(
+ const char* attr, sockbuf_t* sockbuf, uint32_t* ptr)
+{
+ int tmp = (int)(*ptr);
+ cmd_handle(int)(attr, sockbuf, &tmp);
+ *ptr = (uint32_t)tmp;
+}
+
+size_t serialize_to_json(uint32_t)(
+ char** out, size_t len, const char* attr, const char* dn, uint32_t value)
+{
+ size_t newlen = snprintf(
+ *out,
+ len,
+ "\"%s\":{\"type\":\"uint32_t\",\"value\":\"%u\",\"disp\":\"%s\"}",
+ attr,
+ (unsigned int)value,
+ dn);
+ *out += newlen;
+ return len - newlen;
+}
+
+#define TAG "param_u32"
+void http_handle(uint32_t)(httpd_req_t* req, uint32_t* val)
+{
+ int tmp = (int)(*val);
+ http_handle(int)(req, &tmp);
+ *val = (uint32_t)tmp;
+}
+
+void print(uint32_t)(sockbuf_t* sockbuf, const char* attr, uint32_t val)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%s: %lu :: uint32_t\n", attr, (unsigned long)val);
+ sockbuf_write(sockbuf, buf);
+}
diff --git a/main/param/uint8_t.c b/main/param/uint8_t.c
new file mode 100644
index 0000000..6d8e01a
--- /dev/null
+++ b/main/param/uint8_t.c
@@ -0,0 +1,42 @@
+#include "param.h"
+#include "http_server.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void cmd_handle(uint8_t)(const char* attr, sockbuf_t* sockbuf, uint8_t* ptr)
+{
+ int tmp = (int)(*ptr);
+ cmd_handle(int)(attr, sockbuf, &tmp);
+ *ptr = (uint8_t)tmp;
+}
+
+size_t serialize_to_json(uint8_t)(
+ char** out, size_t len, const char* attr, const char* dn, uint8_t value)
+{
+ size_t newlen = snprintf(
+ *out,
+ len,
+ "\"%s\":{\"type\":\"uint8_t\",\"value\":\"%u\",\"disp\":\"%s\"}",
+ attr,
+ (unsigned int)value,
+ dn);
+ *out += newlen;
+ return len - newlen;
+}
+
+#define TAG "param_u8"
+void http_handle(uint8_t)(httpd_req_t* req, uint8_t* val)
+{
+ int tmp = (int)(*val);
+ http_handle(int)(req, &tmp);
+ *val = (uint8_t)tmp;
+}
+
+void print(uint8_t)(sockbuf_t* sockbuf, const char* attr, uint8_t val)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%s: %u :: uint8_t\n", attr, (unsigned int)val);
+ sockbuf_write(sockbuf, buf);
+}