124 lines
3.7 KiB
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();
|
||
|
}
|