aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/http_server.h11
-rw-r--r--include/state_params.i21
-rw-r--r--include/ws2812b_writer.h4
-rw-r--r--main/CMakeLists.txt1
-rw-r--r--main/drv/CMakeLists.txt1
-rw-r--r--main/http_server.c222
-rw-r--r--main/main.c10
-rw-r--r--main/tcp_server.c8
-rw-r--r--main/ws2812b_writer.c54
9 files changed, 299 insertions, 33 deletions
diff --git a/include/http_server.h b/include/http_server.h
new file mode 100644
index 0000000..578b561
--- /dev/null
+++ b/include/http_server.h
@@ -0,0 +1,11 @@
+#pragma once
+#ifndef HTTP_SERVER_H_
+#define HTTP_SERVER_H_
+
+#include <esp_log.h>
+#include <esp_http_server.h>
+#include "ws2812b_writer.h"
+
+httpd_handle_t start_webserver(ws_params_t* params);
+
+#endif /* HTTP_SERVER_H_ */
diff --git a/include/state_params.i b/include/state_params.i
index 447b72b..15a5b43 100644
--- a/include/state_params.i
+++ b/include/state_params.i
@@ -1,9 +1,12 @@
-STATE_PARAM(uint32_t, time)
-STATE_PARAM(int, timetick)
-STATE_PARAM(uint8_t, brightness)
-STATE_PARAM(uint8_t, off)
-STATE_PARAM(uint8_t, n_snow)
-STATE_PARAM(uint8_t, n_red)
-STATE_PARAM(bool, sleep)
-STATE_PARAM(bool, power)
-STATE_PARAM(bool, cool)
+// List of parameters.
+// type name display name, default value
+
+STATE_PARAM(uint32_t, time, "Current Time", 0)
+STATE_PARAM(int, timetick, "Speed", 100)
+STATE_PARAM(uint8_t, brightness, "Brightness", 50)
+STATE_PARAM(uint8_t, n_snow, "Snow Effect", 10)
+STATE_PARAM(uint8_t, n_red, "Desaturation", 32)
+STATE_PARAM(int, x_scale, "X Scale", 255)
+STATE_PARAM(bool, power, "Power", true)
+STATE_PARAM(bool, cool, "Cool", false)
+STATE_PARAM(bool, invert, "Invert", false)
diff --git a/include/ws2812b_writer.h b/include/ws2812b_writer.h
index 89b4f7a..e8fa84f 100644
--- a/include/ws2812b_writer.h
+++ b/include/ws2812b_writer.h
@@ -6,11 +6,13 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
+extern const int NUMBER_PARAMS;
+
typedef struct {
ws2812b_t* drv;
struct {
-#define STATE_PARAM(t, n) t n;
+#define STATE_PARAM(t, n, ...) t n;
#include "state_params.i"
#undef STATE_PARAM
} state;
diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt
index 9ecb402..5bc9356 100644
--- a/main/CMakeLists.txt
+++ b/main/CMakeLists.txt
@@ -4,4 +4,5 @@ idf_component_register(SRCS
"ws2812b_writer.c"
"tcp_server.c"
"sockbuf.c"
+ "http_server.c"
INCLUDE_DIRS "../include")
diff --git a/main/drv/CMakeLists.txt b/main/drv/CMakeLists.txt
index b56f1b0..3d9018f 100644
--- a/main/drv/CMakeLists.txt
+++ b/main/drv/CMakeLists.txt
@@ -1,2 +1,3 @@
idf_component_register(SRCS "ws2812b.c"
+ REQUIRES driver
INCLUDE_DIRS "../../include")
diff --git a/main/http_server.c b/main/http_server.c
new file mode 100644
index 0000000..e4c426c
--- /dev/null
+++ b/main/http_server.c
@@ -0,0 +1,222 @@
+#include "http_server.h"
+
+#define TAG "httpd"
+
+static void handle_set_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);
+}
+
+static void handle_set_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);
+}
+
+static void handle_set_uint8_t(httpd_req_t* req, uint8_t* val)
+{
+ int tmp = *val;
+ handle_set_int(req, &tmp);
+ *val = tmp;
+}
+
+static void handle_set_uint32_t(httpd_req_t* req, uint32_t* val)
+{
+ int tmp = *val;
+ handle_set_int(req, &tmp);
+ *val = tmp;
+}
+
+#define STATE_PARAM(typ, attr, ...) \
+ static esp_err_t handle_set_ ## attr (httpd_req_t *req) { \
+ ESP_LOGI(TAG, "Handling [%s] (%s)", #attr, req->uri); \
+ ws_params_t* params = (ws_params_t*) req->user_ctx; \
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); \
+ handle_set_ ## typ (req, &params->state. attr); \
+ httpd_resp_send(req, NULL, 0); \
+ return ESP_OK; \
+ } \
+ static httpd_uri_t http_ ## attr ## _handler = { \
+ .uri = "/" #attr, \
+ .method = HTTP_POST, \
+ .handler = handle_set_ ## attr, \
+ .user_ctx = NULL \
+ };
+#include "state_params.i"
+#undef STATE_PARAM
+
+static size_t write_uint32_t_value(
+ 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;
+}
+
+static size_t write_uint8_t_value(
+ 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;
+}
+
+static size_t write_int_value(
+ 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;
+}
+
+static size_t write_bool_value(
+ 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;
+}
+
+static esp_err_t handle_get_params(httpd_req_t* req)
+{
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); \
+ size_t len = NUMBER_PARAMS * 128;
+ char out_buffer[len + 1];
+ out_buffer[len] = 0;
+
+ char* out_ptr = out_buffer;
+
+ ws_params_t* ws_params = (ws_params_t*) req->user_ctx;
+ bool write_comma = false;
+ httpd_resp_set_type(req, "application/json");
+ if (len > 1) {
+ *out_ptr = '{';
+ out_ptr ++;
+ len --;
+ }
+#define STATE_PARAM(typ, attr, display, ...) \
+ if (write_comma && len > 1) { \
+ *(out_ptr++) = ','; \
+ len --; \
+ } \
+ len = write_ ## typ ## _value( \
+ &out_ptr, len, #attr, display, ws_params->state. attr); \
+ write_comma = true;
+#include "state_params.i"
+#undef STATE_PARAM
+ if (len > 3) {
+ *(out_ptr++) = '}'; len --;
+ *(out_ptr++) = '\r'; len --;
+ *(out_ptr++) = '\n'; len --;
+ }
+ if (len > 1) {
+ *(out_ptr++) = 0;
+ len --;
+ }
+
+ httpd_resp_set_status(req, HTTPD_200);
+ httpd_resp_send(req, out_buffer, strlen(out_buffer));
+
+ return ESP_OK;
+}
+
+static httpd_uri_t http_params_get_handler = {
+ .uri = "/params",
+ .method = HTTP_GET,
+ .handler = handle_get_params,
+ .user_ctx = NULL
+};
+
+httpd_handle_t start_webserver(ws_params_t* params)
+{
+ httpd_handle_t server = NULL;
+ httpd_config_t config = HTTPD_DEFAULT_CONFIG();
+ config.lru_purge_enable = true;
+ config.max_uri_handlers = NUMBER_PARAMS + 1;
+
+ ESP_LOGI(TAG, "Starting httpd server on port: '%d'", config.server_port);
+ if (httpd_start(&server, &config) == ESP_OK) {
+
+ http_params_get_handler.user_ctx = params;
+ httpd_register_uri_handler(server, &http_params_get_handler);
+
+#define STATE_PARAM(typ, attr, ...) \
+ ESP_LOGI(TAG, "Registering URI handler [%s]", #attr); \
+ http_ ## attr ## _handler.user_ctx = params; \
+ httpd_register_uri_handler(server, & http_ ## attr ## _handler);
+#include "state_params.i"
+#undef STATE_PARAM
+
+ return server;
+ }
+
+ ESP_LOGI(TAG, "Error starting server!");
+ return NULL;
+}
diff --git a/main/main.c b/main/main.c
index 9cd4f0f..82fff1e 100644
--- a/main/main.c
+++ b/main/main.c
@@ -6,6 +6,8 @@
#include "freertos/task.h"
#include "sdkconfig.h"
+#include "station.h"
+#include "http_server.h"
#include "ws2812b_writer.h"
#include "tcp_server.h"
@@ -91,7 +93,7 @@ void app_main(void)
printf("miso: %d\n", PIN_NUM_MISO);
printf("mosi: %d\n", PIN_NUM_MOSI);
printf("sclk: %d\n", PIN_NUM_CLK);
- printf("Tick period ms: %d\n", portTICK_PERIOD_MS);
+ printf("Tick period ms: %d\n", (int) portTICK_PERIOD_MS);
error = spi_bus_initialize(HSPI_HOST, &cfg, SPI_DMA_CH_AUTO);
printf("Bus Init\n");
@@ -105,7 +107,13 @@ void app_main(void)
printf("Configuration complete!!\n");
+ ESP_LOGI("main", "Connection to AP");
+ wifi_init_station("Wort", "JoshIsBau5");
+ ESP_LOGI("main", "Complete!");
+
xTaskCreate(time_keeper, "time_keeper", 1024, &ws_params, 1, NULL);
xTaskCreate(ws2812b_write_task, "ws2812b_writer", 4096, &ws_params, 1, NULL);
xTaskCreate(tcp_server, "tcp_server", 4096, &ws_params, 2, NULL);
+
+ start_webserver(&ws_params);
}
diff --git a/main/tcp_server.c b/main/tcp_server.c
index 434f014..2ee7e51 100644
--- a/main/tcp_server.c
+++ b/main/tcp_server.c
@@ -130,7 +130,7 @@ static void handle_set_cmd(
{
if (false) {}
-#define STATE_PARAM(ty, attr) \
+#define STATE_PARAM(ty, attr, ...) \
else if (!strcmp_(key, #attr)) { \
handle_ ## ty ## _option(#attr, sockbuf, &ws_params->state. attr); \
}
@@ -147,7 +147,7 @@ static void handle_set_cmd(
static void print_uint32_t(sockbuf_t* sockbuf, const char* attr, uint32_t val)
{
char buf[128];
- snprintf(buf, sizeof(buf), "%s: %d :: uint32_t\n", attr, val);
+ snprintf(buf, sizeof(buf), "%s: %ld :: uint32_t\n", attr, val);
sockbuf_write(sockbuf, buf);
}
@@ -174,7 +174,7 @@ static void print_int(sockbuf_t* sockbuf, const char* attr, int val)
static void handle_print_cmd(sockbuf_t* sockbuf, ws_params_t* ws_params)
{
-#define STATE_PARAM(ty, attr) \
+#define STATE_PARAM(ty, attr, ...) \
print_ ## ty ( sockbuf, #attr, ws_params->state. attr );
#include "state_params.i"
#undef STATE_PARAM
@@ -215,8 +215,6 @@ 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));
diff --git a/main/ws2812b_writer.c b/main/ws2812b_writer.c
index f7176f1..36fa666 100644
--- a/main/ws2812b_writer.c
+++ b/main/ws2812b_writer.c
@@ -3,6 +3,12 @@
#include <stdlib.h>
#include <string.h>
+const int NUMBER_PARAMS =
+#define STATE_PARAM(...) +1
+#include "state_params.i"
+#undef STATE_PARAM
+;
+
#define SIZE 300
/* Returns round(sin(2πn / 256) * 127.5 + 127.5). */
@@ -21,11 +27,11 @@ uint8_t amp(uint8_t in, uint8_t n);
void reset_parameters(ws_params_t* params)
{
memset(&params->state, 0, sizeof(params->state));
- params->state.brightness = 32;
- params->state.off = 8;
- params->state.timetick = 100;
- params->state.power = 1;
- params->state.n_snow = 2;
+
+#define STATE_PARAM(type, attr, displ, def, ...) \
+ params->state. attr = def;
+#include "state_params.i"
+#undef STATE_PARAM
}
void calculate_colors(
@@ -33,14 +39,18 @@ void calculate_colors(
ws2812b_buffer_t* buffer)
{
uint32_t red = 0, green = 0, blue = 0;
+ int time;
for (int i = 0; i < SIZE; ++i) {
+ int x = i * 255 / ws_params->state.x_scale;
+ time = ws_params->state.time;
+
if (!ws_params->state.power) {
ws2812b_buffer_set_rgb(buffer, i, 0, 0, 0);
continue;
}
- red = byte_scale(byte_sin(ws_params->state.time / 1000 + i * 4), 255 - ws_params->state.n_red) +
+ red = byte_scale(byte_sin(time / 1000 + x * 4), 255 - ws_params->state.n_red) +
ws_params->state.n_red;
green = 255 - red;
@@ -56,11 +66,11 @@ void calculate_colors(
if (ws_params->state.n_snow) {
uint32_t white[] = {
/* Parallax "snow" */
- ws_params->state.time / 179 + i * 8,
- ws_params->state.time / 193 + i * 12,
- ws_params->state.time / 211 + i * 16,
- (ws_params->state.time) / 233 + i * 8,
- // (ws_params->state.time + 128) / 233 + i * 8,
+ time / 179 + x * 8,
+ time / 193 + x * 12,
+ time / 211 + x * 16,
+ time / 233 + x * 8,
+ // (ws_params->state.time + 128) / 233 + x * 8,
};
for (int i = 0; i < sizeof(white) / sizeof(uint32_t); ++i) {
@@ -73,12 +83,22 @@ void calculate_colors(
}
}
- ws2812b_buffer_set_rgb(
- buffer,
- i,
- byte_scale(min(red + whitesum, 255), ws_params->state.brightness),
- byte_scale(min(green + whitesum, 255), ws_params->state.brightness),
- byte_scale(min(blue + whitesum, 255), ws_params->state.brightness));
+ uint8_t brightness = ws_params->state.brightness;
+ red = min(red + whitesum, 255);
+ green = min(green + whitesum, 255);
+ blue = min(blue + whitesum, 255);
+
+ if (ws_params->state.invert) {
+ red = 255 - red;
+ green = 255 - green;
+ blue = 255 - blue;
+ }
+
+ red = byte_scale(red, brightness);
+ green = byte_scale(green, brightness);
+ blue = byte_scale(blue, brightness);
+
+ ws2812b_buffer_set_rgb(buffer, i, red, green, blue);
}
}