#include "shared.h" #include "leds.h" #include #include MoveEdgeAction strtoea(const char* str) { if(strcmp(str, "w")) { return LEDS_EDGE_WRAP; } else if(strcmp(str, "r")) { return LEDS_EDGE_REVERSE; } else { return LEDS_EDGE_STOP; } } // 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(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; } sprintf(query_key, "e%d", point); if(httpd_query_key_value(query_string, query_key, query_value, sizeof(query_value)) == ESP_OK) { gradient->points[point].edge_action = strtoea(query_value); } else { gradient->points[point].edge_action = LEDS_EDGE_STOP; } // 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); }