potion_party_leds/main/server.c

124 lines
3.7 KiB
C

#include "server.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "shared.h"
#include "leds.h"
#include "parse.h"
#include <esp_http_server.h>
#include <esp_system.h>
#include <esp_netif.h>
#include <sys_arch.h>
const char* http_response_ok = "OK!";
static httpd_handle_t g_http_server = NULL;
// convert a (valid) request as described in api-doc.txt to a gradient.
static
struct result_t request_to_gradient(httpd_req_t* request) {
// buffer for query string
char* query_buffer;
size_t query_length = httpd_req_get_url_query_len(request) + 1;
struct result_t result = { .error = NULL };
if(query_length > 1) {
query_buffer = malloc(query_length * sizeof(char));
if(httpd_req_get_url_query_str(request, query_buffer, query_length) == ESP_OK) {
LOGLN("Received query.");
result = parse_leds_query(query_buffer, query_length);
}
free(query_buffer);
}
return result;
}
// receives HTTP GET requests on root
static
esp_err_t on_http_get_root(httpd_req_t* request) {
const char* response_msg = http_response_ok;
LOGLN("GET received on '/next'.");
// convert the request url to a gradient
struct result_t result = request_to_gradient(request);
// an error was returned, pass it on to the API caller
if(!result.is_ok) {
httpd_resp_set_status(request, "400 Bad Request");
response_msg = result.error;
} else {
// grab a lock on the leds data
xSemaphoreTake(g_led_mutex, portMAX_DELAY);
// modify leds data
leds_set_current_gradient(result.ok, 0);
// release lock
xSemaphoreGive(g_led_mutex);
// request to gradient allocates the gradient on the heap,
// we can free that after use
free(result.ok);
}
// respond to http caller
httpd_resp_send(request, response_msg, strlen(response_msg));
return ESP_OK;
}
httpd_uri_t get_root_uri = {
.uri="/",
.method=HTTP_GET,
.handler=&on_http_get_root,
.user_ctx = NULL
};
static
esp_err_t on_http_get_default(httpd_req_t* request) {
const char* response_msg = http_response_ok;
LOGLN("GET received on '/default'.");
// convert the request to a gradient object
struct result_t result = request_to_gradient(request);
// handle invalid query
if(!result.is_ok) {
httpd_resp_set_status(request, "400 Bad Request");
response_msg = result.error;
} else {
// set default gradient
// take lock on leds data
xSemaphoreTake(g_led_mutex, portMAX_DELAY);
leds_set_default_gradient(result.ok);
// release lock on leds data
xSemaphoreGive(g_led_mutex);
// we allocated a gradient_t struct with request_to_gradient,
// we no longer need it so we'll free it asap
free(result.ok);
}
// send http response
httpd_resp_send(request, response_msg, strlen(response_msg));
return ESP_OK;
}
httpd_uri_t get_default_uri = {
.uri="/default",
.method=HTTP_GET,
.handler=&on_http_get_default,
.user_ctx=NULL
};
// Configure server and enable the http handler.
static
httpd_handle_t start_webserver(void) {
httpd_handle_t server = NULL;
httpd_config_t server_config = HTTPD_DEFAULT_CONFIG();
LOGLN("Starting HTTPd server ':%d'.", server_config.server_port);
if(httpd_start(&server, &server_config) == ESP_OK) {
httpd_register_uri_handler(server, &get_root_uri);
httpd_register_uri_handler(server, &get_default_uri);
return server;
}
LOGLN("Failed to start HTTPd server.");
return NULL;
}
// Start an http server and store it's handle in g_http_server.
void server_init(void) {
g_http_server = start_webserver();
}