2023-09-28 12:31:14 +00:00
|
|
|
#include "shared.h"
|
|
|
|
#include "leds.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <esp_http_server.h>
|
|
|
|
|
|
|
|
// parse a URL query as described in api-doc.txt into a valid Gradient struct.
|
|
|
|
// If the gradient is invalid, the is_ok flag on the return value will be set, and error will be set to a message describing the problem.
|
2023-09-28 12:43:07 +00:00
|
|
|
Result parse_leds_query(char* query_string, size_t query_size) {
|
2023-09-28 12:31:14 +00:00
|
|
|
char query_value[16];
|
|
|
|
char query_key[3];
|
2023-09-28 12:43:07 +00:00
|
|
|
Gradient* gradient = malloc(sizeof(Gradient));
|
2023-09-28 12:31:14 +00:00
|
|
|
|
|
|
|
// Fetch the &l length parameter.
|
|
|
|
// Interpret as a positive integer number of points on the gradient.
|
|
|
|
if(httpd_query_key_value(query_string, "l", query_value, sizeof(query_value)) == ESP_OK) {
|
|
|
|
gradient->points_len = max(0, atoi(query_value));
|
|
|
|
} else {
|
|
|
|
free(gradient);
|
|
|
|
return PARSE_ERR("ERROR: Failed to find length parameter &l");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the &d 'duration' parameter from the query.
|
|
|
|
// Interpreted as a floating point number of seconds before returning to default state.
|
|
|
|
if(httpd_query_key_value(query_string, "d", query_value, sizeof(query_value)) == ESP_OK) {
|
|
|
|
gradient->duration = atof(query_string);
|
|
|
|
} else {
|
|
|
|
gradient->duration = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOGLN("Reading %zu points of gradient query:", gradient->points_len);
|
|
|
|
LOGLN("duration: %f", gradient->duration);
|
|
|
|
|
|
|
|
// Get the gradient point components for every point that was promised by the &l parameter
|
|
|
|
for(int point = 0; point < gradient->points_len; ++point) {
|
|
|
|
// Get the r, g, and b components as 8 bit integers
|
|
|
|
sprintf(query_key, "r%d", point);
|
|
|
|
if(httpd_query_key_value(query_string, query_key, query_value, sizeof(query_size)) == ESP_OK) {
|
|
|
|
gradient->points[point].led.components.red = atoi(query_value);
|
|
|
|
} else {
|
|
|
|
free(gradient);
|
|
|
|
return PARSE_ERR("ERROR: Point missing red component &r.");
|
|
|
|
}
|
|
|
|
sprintf(query_key, "g%d", point);
|
|
|
|
if(httpd_query_key_value(query_string, query_key, query_value, sizeof(query_size)) == ESP_OK) {
|
|
|
|
gradient->points[point].led.components.green = atoi(query_value);
|
|
|
|
} else {
|
|
|
|
free(gradient);
|
|
|
|
return PARSE_ERR("ERROR: Point missing green component &g.");
|
|
|
|
}
|
|
|
|
sprintf(query_key, "b%d", point);
|
|
|
|
if(httpd_query_key_value(query_string, query_key, query_value, sizeof(query_value)) == ESP_OK) {
|
|
|
|
gradient->points[point].led.components.blue = atoi(query_value);
|
|
|
|
} else {
|
|
|
|
free(gradient);
|
|
|
|
return PARSE_ERR("ERROR: Point missing blue component &b.");
|
|
|
|
}
|
|
|
|
// Get the global variable, passed as alpha. Limited to 0-32 (a 5bit unsigned int)
|
|
|
|
// Make sure the most significant 3 bits are all ones
|
|
|
|
sprintf(query_key, "a%d", point);
|
|
|
|
if(httpd_query_key_value(query_string, query_key, query_value, sizeof(query_value)) == ESP_OK) {
|
|
|
|
gradient->points[point].led.components.global = GLOBAL((uint8_t)atoi(query_value));
|
|
|
|
} else {
|
|
|
|
free(gradient);
|
|
|
|
return PARSE_ERR("ERROR: Point missing alpha component &a.");
|
|
|
|
}
|
|
|
|
// Get the time of the gradient as a number ranging from 0 - 120.
|
|
|
|
// Interpreted as an integer offset from the first led to the last
|
|
|
|
sprintf(query_key, "t%d", point);
|
|
|
|
if(httpd_query_key_value(query_string, query_key, query_value, sizeof(query_value)) == ESP_OK) {
|
|
|
|
gradient->points[point].offset = clamp(0, 120, atoi(query_value));
|
|
|
|
} else {
|
|
|
|
free(gradient);
|
|
|
|
return PARSE_ERR("ERROR: Point missing time component &t.");
|
|
|
|
}
|
|
|
|
// Get the movement variable &m.
|
|
|
|
// Interpreted as an integer number from -1 to +1
|
|
|
|
sprintf(query_key, "m%d", point);
|
|
|
|
if(gradient->duration > 0 && httpd_query_key_value(query_string, query_key, query_value, sizeof(query_value)) == ESP_OK) {
|
|
|
|
gradient->points[point].movement = clamp(-1, +1, atoi(query_value));
|
|
|
|
} else {
|
|
|
|
gradient->points[point].movement = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Log fetched fields
|
|
|
|
LOGLN("led[%d]:", point);
|
|
|
|
LOGLN(" r %d", gradient->points[point].led.components.red);
|
|
|
|
LOGLN(" g %d", gradient->points[point].led.components.green);
|
|
|
|
LOGLN(" b %d", gradient->points[point].led.components.blue);
|
|
|
|
LOGLN(" global %d", gradient->points[point].led.components.global >> 3);
|
|
|
|
// may show up as a compile error on modern computers,
|
|
|
|
// x86_64 size_t is usually an unsigned long int, on the ESP8266 it is an unsigned int
|
|
|
|
LOGLN(" t %u", gradient->points[point].offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return PARSE_OK(gradient);
|
|
|
|
}
|