potion_party_leds/main/parse.c

96 lines
4.6 KiB
C

#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.
Result parse_leds_query(char* query_string, size_t query_size) {
char query_value[16];
char query_key[3];
Gradient* gradient = malloc(sizeof(Gradient));
// 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);
}