aboutsummaryrefslogtreecommitdiff
path: root/main/http_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/http_server.c')
-rw-r--r--main/http_server.c222
1 files changed, 222 insertions, 0 deletions
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;
+}