diff --git a/wled00/WS2812FX.cpp b/wled00/WS2812FX.cpp index f3ea3e463..23f93c086 100644 --- a/wled00/WS2812FX.cpp +++ b/wled00/WS2812FX.cpp @@ -35,7 +35,7 @@ */ uint16_t WS2812FX::mode_static(void) { fill(SEGMENT.colors[0]); - return ((SEGMENT.options >> 7) & 0x01) ? 20 : 500; //update faster if in transition + return (SEGMENT.getOption(7)) ? 20 : 500; //update faster if in transition } diff --git a/wled00/WS2812FX.h b/wled00/WS2812FX.h index a7e5bcf0e..ce65547c5 100644 --- a/wled00/WS2812FX.h +++ b/wled00/WS2812FX.h @@ -42,7 +42,7 @@ /* each segment uses 37 bytes of SRAM memory, so if you're application fails because of insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ -#define MAX_NUM_SEGMENTS 10 +#define MAX_NUM_SEGMENTS 1 #define NUM_COLORS 3 /* number of colors per segment */ #define SEGMENT _segments[_segment_index] #define SEGMENT_RUNTIME _segment_runtimes[_segment_index] @@ -174,8 +174,26 @@ class WS2812FX { uint8_t intensity; uint8_t palette; uint8_t mode; - uint8_t options; //bit pattern: msb first: cloning3 cloning2 cloning1 cloning0 tbd tbd reverse selected + uint8_t options; //bit pattern: msb first: transitional tbd tbd tbd tbd paused reverse selected uint32_t colors[NUM_COLORS]; + //member functions + uint32_t color(uint8_t n) + { + return colors[n]; + } + void setOption(uint8_t n, bool val) + { + if (val) { + options |= 0x01 << n; + } else + { + options &= ~(0x01 << n); + } + } + bool getOption(uint8_t n) + { + return ((options >> n) & 0x01); + } } segment; // segment runtime parameters @@ -185,6 +203,7 @@ class WS2812FX { uint32_t counter_mode_call; uint16_t aux_param; uint16_t aux_param2; + void reset(){next_time = 0; counter_mode_step = 0; counter_mode_call = 0; aux_param = 0; aux_param2 = 0;}; } segment_runtime; WS2812FX() { @@ -318,10 +337,7 @@ class WS2812FX { unlockAll(void), setTransitionMode(bool t), trigger(void), - setNumSegments(uint8_t n), - setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint8_t speed, uint8_t intensity, bool reverse), - setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, bool reverse), - setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, uint8_t options), + setSegment(uint8_t n, uint16_t start, uint16_t stop), resetSegments(), setPixelColor(uint16_t n, uint32_t c), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), @@ -340,6 +356,7 @@ class WS2812FX { getNumSegments(void), getModeCount(void), getPaletteCount(void), + getMaxSegments(void), get_random_wheel_index(uint8_t); uint32_t @@ -349,8 +366,8 @@ class WS2812FX { getPixelColor(uint16_t), getColor(void); - WS2812FX::Segment - getSegment(void); + WS2812FX::Segment& + getSegment(uint8_t n); WS2812FX::Segment_runtime getSegmentRuntime(void); @@ -495,144 +512,31 @@ class WS2812FX { uint8_t _num_segments = 1; segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 21 bytes per element // start, stop, speed, intensity, palette, mode, options, color[] - { 0, 7, DEFAULT_SPEED, 128, 0, FX_MODE_STATIC, NO_OPTIONS, {DEFAULT_COLOR}} + { 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, {DEFAULT_COLOR}} }; segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 16 bytes per element }; -const char JSON_mode_names[] PROGMEM = R"=====({"effects":[ -"Solid", -"Blink", -"Breathe", -"Wipe", -"Wipe Random", -"Random Colors", -"Sweep", -"Dynamic", -"Colorloop", -"Rainbow", -"Scan", -"Dual Scan", -"Fade", -"Chase", -"Chase Rainbow", -"Running", -"Saw", -"Twinkle", -"Dissolve", -"Dissolve Rnd", -"Sparkle", -"Dark Sparkle", -"Sparkle+", -"Strobe", -"Strobe Rainbow", -"Mega Strobe", -"Blink Rainbow", -"Android", -"Chase", -"Chase Random", -"Chase Rainbow", -"Chase Flash", -"Chase Flash Rnd", -"Rainbow Runner", -"Colorful", -"Traffic Light", -"Sweep Random", -"Running 2", -"Red & Blue", -"Stream", -"Scanner", -"Lighthouse", -"Fireworks", -"Rain", -"Merry Christmas", -"Fire Flicker", -"Gradient", -"Loading", -"In Out", -"In In", -"Out Out", -"Out In", -"Circus", -"Halloween", -"Tri Chase", -"Tri Wipe", -"Tri Fade", -"Lightning", -"ICU", -"Multi Comet", -"Dual Scanner", -"Stream 2", -"Oscillate", -"Pride 2015", -"Juggle", -"Palette", -"Fire 2012", -"Colorwaves", -"BPM", -"Fill Noise", -"Noise 1", -"Noise 2", -"Noise 3", -"Noise 4", -"Colortwinkle", -"Lake", -"Meteor", -"Smooth Meteor", -"Railway", -"Ripple" -]})====="; +//10 names per line +const char JSON_mode_names[] PROGMEM = R"=====([ +"Solid","Blink","Breathe","Wipe","Wipe Random","Random Colors","Sweep","Dynamic","Colorloop","Rainbow", +"Scan","Dual Scan","Fade","Chase","Chase Rainbow","Running","Saw","Twinkle","Dissolve","Dissolve Rnd", +"Sparkle","Dark Sparkle","Sparkle+","Strobe","Strobe Rainbow","Mega Strobe","Blink Rainbow","Android","Chase","Chase Random", +"Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Red & Blue","Stream", +"Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","In Out","In In", +"Out Out","Out In","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", +"Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","BPM","Fill Noise","Noise 1", +"Noise 2","Noise 3","Noise 4","Colortwinkle","Lake","Meteor","Smooth Meteor","Railway","Ripple" +])====="; -const char JSON_palette_names[] PROGMEM = R"=====({"palettes":[ -"Default", -"Random Cycle", -"Primary Color", -"Based on Primary", -"Set Colors", -"Based on Set", -"Party", -"Cloud", -"Lava", -"Ocean", -"Forest", -"Rainbow", -"Rainbow Bands", -"Sunset", -"Rivendell", -"Breeze", -"Red & Blue", -"Yellowout", -"Analogous", -"Splash", -"Pastel", -"Sunset 2", -"Beech", -"Vintage", -"Departure", -"Landscape", -"Beach", -"Sherbet", -"Hult", -"Hult 64", -"Drywet", -"Jul", -"Grintage", -"Rewhi", -"Tertiary", -"Fire", -"Icefire", -"Cyane", -"Light Pink", -"Autumn", -"Magenta", -"Magred", -"Yelmag", -"Yelblu", -"Orange & Teal", -"Tiamat", -"April Night" -]})====="; +const char JSON_palette_names[] PROGMEM = R"=====([ +"Default","Random Cycle","Primary Color","Based on Primary","Set Colors","Based on Set","Party","Cloud","Lava","Ocean", +"Forest","Rainbow","Rainbow Bands","Sunset","Rivendell","Breeze","Red & Blue","Yellowout","Analogous","Splash", +"Pastel","Sunset 2","Beech","Vintage","Departure","Landscape","Beach","Sherbet","Hult","Hult 64", +"Drywet","Jul","Grintage","Rewhi","Tertiary","Fire","Icefire","Cyane","Light Pink","Autumn", +"Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night" +])====="; #endif diff --git a/wled00/WS2812FX_fcn.cpp b/wled00/WS2812FX_fcn.cpp index bb6b88351..77d9ff177 100644 --- a/wled00/WS2812FX_fcn.cpp +++ b/wled00/WS2812FX_fcn.cpp @@ -336,8 +336,8 @@ uint8_t WS2812FX::getNumSegments(void) { return _num_segments; } -void WS2812FX::setNumSegments(uint8_t n) { - _num_segments = n; +uint8_t WS2812FX::getMaxSegments(void) { + return MAX_NUM_SEGMENTS; } uint32_t WS2812FX::getColor(void) { @@ -379,8 +379,9 @@ uint32_t WS2812FX::getPixelColor(uint16_t i) return ( (lColor.W << 24) | (r << 16) | (g << 8) | (b) ); } -WS2812FX::Segment WS2812FX::getSegment(void) { - return _segments[0]; +WS2812FX::Segment& WS2812FX::getSegment(uint8_t id) { + if (id >= MAX_NUM_SEGMENTS) return _segments[0]; + return _segments[id]; } WS2812FX::Segment_runtime WS2812FX::getSegmentRuntime(void) { @@ -391,29 +392,14 @@ WS2812FX::Segment* WS2812FX::getSegments(void) { return _segments; } -void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint8_t speed, uint8_t intensity, bool reverse) { - uint32_t colors[] = {color, 0, 0}; - setSegment(n, start, stop, mode, colors, speed, intensity, reverse); -} - -void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, bool reverse) { - setSegment(n, start, stop, mode, colors, speed, intensity, (uint8_t)(reverse ? REVERSE : NO_OPTIONS)); -} - -void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, uint8_t options) { - if(n < (sizeof(_segments) / sizeof(_segments[0]))) { - if(n + 1 > _num_segments) _num_segments = n + 1; - _segments[n].start = start; - _segments[n].stop = stop; - _segments[n].mode = mode; - _segments[n].speed = speed; - _segments[n].intensity = intensity; - _segments[n].options = options; - - for(uint8_t i=0; i= MAX_NUM_SEGMENTS) return; + Segment& seg = _segments[n]; + if (seg.start == i1 && seg.stop == i2) return; + if (i1 < _length) seg.start = i1; + seg.stop = i2; + if (i2 > _length) seg.stop = _length; + _segment_runtimes[n].reset(); } void WS2812FX::resetSegments() { @@ -421,7 +407,11 @@ void WS2812FX::resetSegments() { memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); _segment_index = 0; _num_segments = 1; - setSegment(0, 0, 7, FX_MODE_STATIC, (const uint32_t[]){DEFAULT_COLOR, 0, 0}, DEFAULT_SPEED, 128, NO_OPTIONS); + _segments[0].mode = DEFAULT_MODE; + _segments[0].colors[0] = DEFAULT_COLOR; + _segments[0].start = 0; + _segments[0].speed = DEFAULT_SPEED; + _segments[0].stop = _length; } void WS2812FX::setIndividual(uint16_t i, uint32_t col) @@ -483,13 +473,8 @@ void WS2812FX::unlockAll() void WS2812FX::setTransitionMode(bool t) { - if (t) { - SEGMENT.options |= 0x01 << 7; - } else - { - SEGMENT.options &= ~(0x01 << 7); - return; - } + SEGMENT.setOption(7,t); + if (!t) return; unsigned long waitMax = millis() + 20; //refresh after 20 ms if transition enabled if (SEGMENT.mode == FX_MODE_STATIC && SEGMENT_RUNTIME.next_time > waitMax) SEGMENT_RUNTIME.next_time = waitMax; } diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 5ce1c3808..51a4d86c1 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -89,7 +89,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1903051 +#define VERSION 1903055 char versionString[] = "0.8.4-dev"; @@ -467,7 +467,6 @@ const byte gamma8[] = { //function prototypes void serveMessage(AsyncWebServerRequest*,uint16_t,String,String,byte); - //turns all LEDs off and restarts ESP void reset() { diff --git a/wled00/wled18_server.ino b/wled00/wled18_server.ino index 2c60773cb..dd04a401a 100644 --- a/wled00/wled18_server.ino +++ b/wled00/wled18_server.ino @@ -64,25 +64,17 @@ void initServer() doReboot = true; }); - server.on("/json/state", HTTP_GET, [](AsyncWebServerRequest *request){ - serveJsonState(request); - }); + server.on("/json", HTTP_GET, [](AsyncWebServerRequest *request){ + serveJson(request); + }); - server.on("/json/effects", HTTP_GET, [](AsyncWebServerRequest *request){ - request->send_P(200, "application/json", JSON_mode_names); - }); - - server.on("/json/palettes", HTTP_GET, [](AsyncWebServerRequest *request){ - request->send_P(200, "application/json", JSON_palette_names); - }); - - server.on("/json/info", HTTP_GET, [](AsyncWebServerRequest *request){ - serveJsonInfo(request); - }); - - server.on("/json", HTTP_ANY, [](AsyncWebServerRequest *request){ - request->send(500, "application/json", "{\"error\":\"Not implemented\"}"); - }); + AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request, JsonVariant &json) { + JsonObject& root = json.as(); + if (!root.success()){request->send(500, "application/json", "{\"error\":\"Parsing failed\"}"); return;} + deserializeState(root); + request->send(200, "application/json", "{\"success\":true}"); + }); + server.addHandler(handler); //*******DEPRECATED******* server.on("/version", HTTP_GET, [](AsyncWebServerRequest *request){ @@ -96,10 +88,6 @@ void initServer() server.on("/freeheap", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(200, "text/plain", (String)ESP.getFreeHeap()); }); - - server.on("/build", HTTP_GET, [](AsyncWebServerRequest *request){ - serveJsonInfo(request); - }); server.on("/power", HTTP_GET, [](AsyncWebServerRequest *request){ String val = ""; @@ -312,7 +300,7 @@ String settingsProcessor(const String& var) void serveSettings(AsyncWebServerRequest* request) { byte subPage = 0; - String url = request->url(); + const String& url = request->url(); if (url.indexOf("sett") >= 0) { if (url.indexOf("wifi") > 0) subPage = 1; diff --git a/wled00/wled19_json.ino b/wled00/wled19_json.ino index c77278dfd..279c26a49 100644 --- a/wled00/wled19_json.ino +++ b/wled00/wled19_json.ino @@ -2,36 +2,114 @@ * JSON API (De)serialization */ -void serveJsonState(AsyncWebServerRequest* request) +void deserializeState(JsonObject& root) { - AsyncJsonResponse * response = new AsyncJsonResponse(); - JsonObject& doc = response->getRoot(); - - doc["on"] = (bri > 0); - doc["bri"] = briLast; - doc["transition"] = transitionDelay/100; //in 100ms + bool on = root["on"] | (bri > 0); + if (!on != !bri) toggleOnOff(); - JsonObject& nl = doc.createNestedObject("nl"); + briLast = root["bri"] | briLast; + if (bri > 0) bri = briLast; + + if (root.containsKey("transition")) + { + transitionDelay = root["transition"]; + transitionDelay *= 100; + } + + JsonObject& nl = root["nl"]; + nightlightActive = nl["on"] | nightlightActive; + nightlightDelayMins = nl["dur"] | nightlightDelayMins; + nightlightFade = nl["fade"] | nightlightFade; + nightlightTargetBri = nl["tbri"] | nightlightTargetBri; + + JsonObject& udpn = root["udpn"]; + notifyDirect = udpn["send"] | notifyDirect; + receiveNotifications = udpn["recv"] | receiveNotifications; + bool noNotification = udpn["nn"]; //send no notification just for this request + + int it = 0; + JsonArray& segs = root["seg"]; + for (JsonObject& elem : segs) + { + byte id = elem["id"] | it; + if (id < strip.getMaxSegments()) + { + WS2812FX::Segment& seg = strip.getSegment(id); + uint16_t start = elem["start"] | seg.start; + int stop = elem["stop"] | -1; + + if (stop < 0) { + uint16_t len = elem["len"]; + stop = (len > 0) ? start + len : seg.stop; + } + strip.setSegment(id, start, stop); + + JsonArray& colarr = elem["col"]; + if (colarr.success()) + { + for (uint8_t i = 0; i < 3; i++) + { + JsonArray& colX = colarr[i]; + if (!colX.success()) break; + byte sz = colX.size(); + if (sz > 0 && sz < 5) + { + int rgbw[] = {0,0,0,0}; + memset(rgbw, 0, 4); + byte cp = colX.copyTo(rgbw); + seg.colors[i] = ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF))); + if (cp == 1 && rgbw[0] == 0) seg.colors[i] = 0; + //temporary + if (i == 0) {col[0] = rgbw[0]; col[1] = rgbw[1]; col[2] = rgbw[2]; col[3] = rgbw[3];} + if (i == 1) {colSec[0] = rgbw[0]; colSec[1] = rgbw[1]; colSec[2] = rgbw[2]; colSec[3] = rgbw[3];} + } + } + } + + byte fx = elem["fx"] | seg.mode; + if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(fx); + seg.speed = elem["sx"] | seg.speed; + seg.intensity = elem["ix"] | seg.intensity; + byte pal = elem["pal"] | seg.palette; + if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal); + seg.setOption(0, elem["sel"] | seg.getOption(0)); + seg.setOption(1, elem["rev"] | seg.getOption(1)); + //int cln = seg_0["cln"]; + //temporary + effectCurrent = seg.mode; + effectSpeed = seg.speed; + effectIntensity = seg.intensity; + effectPalette = seg.palette; + } + it++; + } + colorUpdated(noNotification ? 5:1); +} + +void serializeState(JsonObject& root) +{ + root["on"] = (bri > 0); + root["bri"] = briLast; + root["transition"] = transitionDelay/100; //in 100ms + + JsonObject& nl = root.createNestedObject("nl"); nl["on"] = nightlightActive; nl["dur"] = nightlightDelayMins; nl["fade"] = nightlightFade; nl["tbri"] = nightlightTargetBri; - JsonObject& udpn = doc.createNestedObject("udpn"); + JsonObject& udpn = root.createNestedObject("udpn"); udpn["send"] = notifyDirect; udpn["recv"] = receiveNotifications; - JsonArray& seg = doc.createNestedArray("seg"); + JsonArray& seg = root.createNestedArray("seg"); JsonObject& seg0 = seg.createNestedObject(); serializeSegment(seg0); - - response->setLength(); - request->send(response); } -JsonObject& serializeSegment(JsonObject& root) +void serializeSegment(JsonObject& root) { - WS2812FX::Segment seg = strip.getSegment(); + WS2812FX::Segment seg = strip.getSegment(0); //root["i"] = i; root["start"] = seg.start; @@ -54,21 +132,17 @@ JsonObject& serializeSegment(JsonObject& root) root["sx"] = seg.speed; root["ix"] = seg.intensity; root["pal"] = seg.palette; - root["sel"] = ((seg.options & 0x01) == 0x01); - root["rev"] = ((seg.options & 0x02) == 0x02); + root["sel"] = seg.getOption(0); + root["rev"] = seg.getOption(1); root["cln"] = -1; } -//fill string buffer with build info -void serveJsonInfo(AsyncWebServerRequest* request) +void serializeInfo(JsonObject& root) { - AsyncJsonResponse* response = new AsyncJsonResponse(); - JsonObject& doc = response->getRoot(); + root["ver"] = versionString; + root["vid"] = VERSION; - doc["ver"] = versionString; - doc["vid"] = VERSION; - - JsonObject& leds = doc.createNestedObject("leds"); + JsonObject& leds = root.createNestedObject("leds"); leds["count"] = ledCount; leds["rgbw"] = useRGBW; JsonArray& leds_pin = leds.createNestedArray("pin"); @@ -76,55 +150,95 @@ void serveJsonInfo(AsyncWebServerRequest* request) leds["pwr"] = strip.currentMilliamps; leds["maxpwr"] = strip.ablMilliampsMax; - leds["maxseg"] = 1; - doc["name"] = serverDescription; - doc["udpport"] = udpPort; - doc["live"] = realtimeActive; - doc["fxcount"] = strip.getModeCount(); - doc["palcount"] = strip.getPaletteCount(); - #ifdef ARDUINO_ARCH_ESP32 - doc["arch"] = "esp32"; - doc["core"] = ESP.getSdkVersion(); - //doc["maxalloc"] = ESP.getMaxAllocHeap(); - #else - doc["arch"] = "esp8266"; - doc["core"] = ESP.getCoreVersion(); - //doc["maxalloc"] = ESP.getMaxFreeBlockSize(); - #endif - doc["freeheap"] = ESP.getFreeHeap(); - doc["uptime"] = millis()/1000; + leds["maxseg"] = strip.getMaxSegments(); - JsonArray& opt = doc.createNestedArray("opt"); + root["name"] = serverDescription; + root["udpport"] = udpPort; + root["live"] = realtimeActive; + root["fxcount"] = strip.getModeCount(); + root["palcount"] = strip.getPaletteCount(); + #ifdef ARDUINO_ARCH_ESP32 + root["arch"] = "esp32"; + root["core"] = ESP.getSdkVersion(); + //root["maxalloc"] = ESP.getMaxAllocHeap(); + #else + root["arch"] = "esp8266"; + root["core"] = ESP.getCoreVersion(); + //root["maxalloc"] = ESP.getMaxFreeBlockSize(); + #endif + root["freeheap"] = ESP.getFreeHeap(); + root["uptime"] = millis()/1000; + + byte os = 0; + #ifdef WLED_DEBUG + os = 0x80; + #endif #ifndef WLED_DISABLE_ALEXA - opt.add("alexa"); + os += 0x40; #endif #ifndef WLED_DISABLE_BLYNK - opt.add("blynk"); + os += 0x20; #endif #ifndef WLED_DISABLE_CRONIXIE - opt.add("cronixie"); - #endif - #ifdef WLED_DEBUG - opt.add("debug"); + os += 0x10; #endif #ifdef USEFS - opt.add("fs"); + os += 0x08; #endif #ifndef WLED_DISABLE_HUESYNC - opt.add("huesync"); + os += 0x04; #endif #ifndef WLED_DISABLE_MOBILE_UI - opt.add("mobile-ui"); + os += 0x02; #endif #ifndef WLED_DISABLE_OTA - opt.add("ota"); + os += 0x01; #endif + root["opt"] = os; - doc["brand"] = "wled"; - doc["product"] = "DIY light"; - doc["btype"] = "dev"; - doc["mac"] = escapedMac; + root["brand"] = "WLED"; + root["product"] = "DIY light"; + root["btype"] = "dev"; + root["mac"] = escapedMac; +} +void serveJson(AsyncWebServerRequest* request) +{ + byte subJson = 0; + const String& url = request->url(); + if (url.indexOf("state") > 0) subJson = 1; + else if (url.indexOf("info") > 0) subJson = 2; + else if (url.indexOf("eff") > 0) { + request->send_P(200, "application/json", JSON_mode_names); + return; + } + else if (url.indexOf("pal") > 0) { + request->send_P(200, "application/json", JSON_palette_names); + return; + } + else if (url.length() > 6) { //not just /json + request->send( 500, "application/json", "{\"error\":\"Not implemented\"}"); + return; + } + + AsyncJsonResponse* response = new AsyncJsonResponse(); + JsonObject& doc = response->getRoot(); + + switch (subJson) + { + case 1: //state + serializeState(doc); break; + case 2: //info + serializeInfo(doc); break; + default: //all + JsonObject& state = doc.createNestedObject("state"); + serializeState(state); + JsonObject& info = doc.createNestedObject("info"); + serializeInfo(info); + doc["effects"] = RawJson(JSON_mode_names); + doc["palettes"] = RawJson(JSON_palette_names); + } + response->setLength(); request->send(response); }