diff --git a/wled00/wled.h b/wled00/wled.h index b665b4386..3dab8f40d 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -113,6 +113,12 @@ #define CLIENT_PASS "" #endif +/*#ifndef SPIFFS_EDITOR_AIRCOOOKIE + #error You are not using the Aircoookie fork of the ESPAsyncWebserver library.\ + Using upstream puts your WiFi password at risk of being served by the filesystem.\ + Comment out this error message to build regardless. +#endif*/ + #if IR_PIN < 0 #ifndef WLED_DISABLE_INFRARED #define WLED_DISABLE_INFRARED diff --git a/wled00/wled_eeprom.cpp b/wled00/wled_eeprom.cpp index 39501d0e3..257769816 100644 --- a/wled00/wled_eeprom.cpp +++ b/wled00/wled_eeprom.cpp @@ -698,6 +698,7 @@ bool applyPreset(byte index) void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj) { + if (index == 0) return; bool docAlloc = fileDoc; JsonObject sObj = saveobj; @@ -721,6 +722,7 @@ void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj) sObj.remove("ib"); sObj.remove("sb"); sObj.remove(F("error")); + sObj.remove(F("time")); writeObjectToFileUsingId("/presets.json", index, fileDoc); if (!docAlloc) delete fileDoc; @@ -870,3 +872,508 @@ void deEEP() { f.close(); DEBUG_PRINTLN(F("deEEP complete!")); } + +//simple macro for ArduinoJSON's or syntax +#define CJSON(a,b) a = b | a + +void getStringFromJson(char* dest, const char* src, size_t len) { + if (src != nullptr) strlcpy(dest, src, len); +} + +void deserializeSettings() { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + + //deserializeJson(doc, json); + + //int rev_major = doc["rev"][0]; // 1 + //int rev_minor = doc["rev"][1]; // 0 + + //long vid = doc["vid"]; // 2010020 + + JsonObject id = doc["id"]; + getStringFromJson(cmDNS, id["mdns"], 33); + getStringFromJson(serverDescription, id["name"], 33); + getStringFromJson(alexaInvocationName, id["inv"], 33); + + JsonObject nw_ins_0 = doc["nw"]["ins"][0]; + getStringFromJson(clientSSID, nw_ins_0["ssid"], 33); + //int nw_ins_0_pskl = nw_ins_0["pskl"]; + //The WiFi PSK is normally not contained in the regular file for security reasons. + //If it is present however, we will use it + getStringFromJson(clientPass, nw_ins_0["psk"], 65); + + JsonArray nw_ins_0_ip = nw_ins_0["ip"]; + JsonArray nw_ins_0_gw = nw_ins_0["gw"]; + JsonArray nw_ins_0_sn = nw_ins_0["sn"]; + + for (int i = 0; i < 4; i++) { + CJSON(staticIP[i], nw_ins_0_ip[i]); + CJSON(staticGateway[i], nw_ins_0_gw[i]); + CJSON(staticSubnet[i], nw_ins_0_sn[i]); + } + + JsonObject ap = doc["ap"]; + getStringFromJson(apSSID, ap["ssid"], 33); + getStringFromJson(apPass, ap["psk"] , 65); //normally not present due to security + //int ap_pskl = ap["pskl"]; + + CJSON(apChannel, ap["chan"]); + if (apChannel > 13 || apChannel < 1) apChannel = 1; + + CJSON(apHide, ap["hide"]); + if (apHide > 1) apHide = 1; + + CJSON(apBehavior, ap["behav"]); + + /* + JsonArray ap_ip = ap["ip"]; + for (int i = 0; i < 4; i++) { + apIP[i] = ap_ip; + }*/ + + noWifiSleep = doc["wifi"]["sleep"] | !noWifiSleep; // inverted + noWifiSleep = !noWifiSleep; + //int wifi_phy = doc["wifi"]["phy"]; //force phy mode n? + + JsonObject hw = doc["hw"]; + + JsonObject hw_led = hw["led"]; + CJSON(ledCount, hw_led["total"]); + if (ledCount > MAX_LEDS) ledCount = MAX_LEDS; + + CJSON(strip.ablMilliampsMax, hw_led["maxpwr"]); + CJSON(strip.milliampsPerLed, hw_led["ledma"]); + CJSON(strip.reverseMode, hw_led["rev"]); + + /*JsonObject hw_led_ins_0 = hw_led["ins"][0]; + bool hw_led_ins_0_en = hw_led_ins_0["en"]; // true + int hw_led_ins_0_start = hw_led_ins_0["start"]; // 0 + int hw_led_ins_0_len = hw_led_ins_0["len"]; // 1200 + + int hw_led_ins_0_pin_0 = hw_led_ins_0["pin"][0]; // 2 + + int hw_led_ins_0_order = hw_led_ins_0["order"]; // 0 + bool hw_led_ins_0_rev = hw_led_ins_0["rev"]; // false + int hw_led_ins_0_skip = hw_led_ins_0["skip"]; // 0 + int hw_led_ins_0_type = hw_led_ins_0["type"]; // 2*/ + + JsonObject hw_btn_ins_0 = hw["btn"]["ins"][0]; + buttonEnabled = hw_btn_ins_0["en"] | buttonEnabled; + + //int hw_btn_ins_0_pin_0 = hw_btn_ins_0["pin"][0]; // 0 + + //bool hw_btn_ins_0_rev = hw_btn_ins_0["rev"]; // false + + JsonArray hw_btn_ins_0_macros = hw_btn_ins_0["macros"]; + CJSON(macroButton, hw_btn_ins_0_macros[0]); + CJSON(macroLongPress,hw_btn_ins_0_macros[1]); + CJSON(macroDoublePress, hw_btn_ins_0_macros[2]); + + //int hw_btn_ins_0_type = hw_btn_ins_0["type"]; // 0 + + //int hw_ir_pin = hw["ir"]["pin"]; // 4 + CJSON(irEnabled, hw["ir"]["type"]); // 0 + + //int hw_relay_pin = hw["relay"]["pin"]; // 12 + //bool hw_relay_rev = hw["relay"]["rev"]; // false + + //int hw_status_pin = hw["status"]["pin"]; // -1 + + JsonObject light = doc["light"]; + CJSON(briMultiplier, light["scale-bri"]); + CJSON(strip.paletteBlend, light["pal-mode"]); + + float light_gc_bri = light["gc"]["bri"]; + float light_gc_col = light["gc"]["col"]; // 2.8 + if (light_gc_bri > 1.5) strip.gammaCorrectBri = true; + else if (light_gc_bri > 0.5) strip.gammaCorrectBri = false; + if (light_gc_col > 1.5) strip.gammaCorrectCol = true; + else if (light_gc_col > 0.5) strip.gammaCorrectCol = false; + + JsonObject light_tr = light["tr"]; + CJSON(fadeTransition, light_tr["mode"]); + CJSON(transitionDelayDefault, light_tr["dur"]); // 700 + CJSON(strip.paletteFade, light_tr["pal"]); + + JsonObject light_nl = light["nl"]; + CJSON(nightlightMode, light_nl["mode"]); + CJSON(nightlightDelayMinsDefault, light_nl["dur"]); + nightlightDelayMins = nightlightDelayMinsDefault; + + CJSON(nightlightTargetBri, light_nl["tbri"]); + CJSON(macroNl, light_nl["macro"]); + + JsonObject def = doc["def"]; + CJSON(bootPreset, def["ps"]); + CJSON(turnOnAtBoot, def["on"]); // true + CJSON(briS, def["bri"]); // 128 + if (briS == 0) briS = 255; + + JsonObject def_cy = def["cy"]; + CJSON(presetCyclingEnabled, def_cy["on"]); + + CJSON(presetCycleMin, def_cy["range"][0]); + CJSON(presetCycleMax, def_cy["range"][1]); + + CJSON(presetCycleTime, def_cy["dur"]); + + JsonObject interfaces = doc["if"]; + + JsonObject if_sync = interfaces["sync"]; + CJSON(udpPort, if_sync["port0"]); // 21324 + CJSON(udpPort2, if_sync["port1"]); // 65506 + + JsonObject if_sync_recv = if_sync["recv"]; + CJSON(receiveNotificationBrightness, if_sync_recv["bri"]); + CJSON(receiveNotificationColor, if_sync_recv["col"]); + CJSON(receiveNotificationEffects, if_sync_recv["fx"]); + receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects); + + JsonObject if_sync_send = if_sync["send"]; + CJSON(notifyDirectDefault, if_sync_send["dir"]); + notifyDirect = notifyDirectDefault; + CJSON(notifyButton, if_sync_send["btn"]); + CJSON(notifyAlexa, if_sync_send["va"]); + CJSON(notifyHue, if_sync_send["hue"]); + CJSON(notifyMacro, if_sync_send["macro"]); + CJSON(notifyTwice, if_sync_send["twice"]); + + JsonObject if_realtime = interfaces["realtime"]; + CJSON(receiveDirect, if_realtime["en"]); + CJSON(e131Port, if_realtime["port"]); // 5568 + CJSON(e131Multicast, if_realtime["mc"]); + + JsonObject if_realtime_dmx = if_realtime["dmx"]; + CJSON(e131Universe, if_realtime_dmx["uni"]); + CJSON(e131SkipOutOfSequence, if_realtime_dmx["seqskip"]); + CJSON(DMXAddress, if_realtime_dmx["addr"]); + CJSON(DMXMode, if_realtime_dmx["mode"]); + + CJSON(realtimeTimeoutMs, if_realtime["timeout"]); + CJSON(arlsForceMaxBri, if_realtime["maxbri"]); + CJSON(arlsDisableGammaCorrection, if_realtime["no-gc"]); // false + CJSON(arlsOffset, if_realtime["offset"]); // 0 + + CJSON(alexaEnabled, interfaces["va"]["alexa"]); // false + + CJSON(macroAlexaOn, interfaces["va"]["macros"][0]); + CJSON(macroAlexaOff, interfaces["va"]["macros"][1]); + + getStringFromJson(blynkApiKey, interfaces["blynk"]["token"], 36); //normally not present due to security + + JsonObject if_mqtt = interfaces["mqtt"]; + CJSON(mqttEnabled, if_mqtt["en"]); + getStringFromJson(mqttServer, if_mqtt["broker"], 33); + CJSON(mqttPort, if_mqtt["port"]); // 1883 + getStringFromJson(mqttUser, if_mqtt["user"], 41); + getStringFromJson(mqttPass, if_mqtt["psk"], 41); //normally not present due to security + getStringFromJson(mqttClientID, if_mqtt["cid"], 41); + + getStringFromJson(mqttDeviceTopic, if_mqtt["topics"]["device"], 33); // "wled/test" + getStringFromJson(mqttGroupTopic, if_mqtt["topics"]["group"], 33); // "" + + JsonObject if_hue = interfaces["hue"]; + CJSON(huePollingEnabled, if_hue["en"]); + CJSON(huePollLightId, if_hue["id"]); + CJSON(huePollIntervalMs, if_hue["iv"]); + + JsonObject if_hue_recv = if_hue["recv"]; + CJSON(hueApplyOnOff, if_hue_recv["on"]); + CJSON(hueApplyBri, if_hue_recv["bri"]); + CJSON(hueApplyColor, if_hue_recv["col"]); + + JsonArray if_hue_ip = if_hue["ip"]; + + for (int i = 0; i < 4; i++) + CJSON(hueIP[i], if_hue_ip[i]); + + JsonObject if_ntp = interfaces["ntp"]; + CJSON(ntpEnabled, if_ntp["en"]); + getStringFromJson(ntpServerName, if_ntp["host"], 33); // "1.wled.pool.ntp.org" + CJSON(currentTimezone, if_ntp["tz"]); + CJSON(utcOffsetSecs, if_ntp["offset"]); + + JsonObject ol = doc["ol"]; + CJSON(overlayDefault ,ol["clock"]); // 0 + overlayCurrent = overlayDefault; + + JsonArray ol_cntdwn = ol["cntdwn"]; //[20,12,31,23,59,59] + CJSON(countdownYear, ol_cntdwn[0]); + CJSON(countdownMonth, ol_cntdwn[1]); + CJSON(countdownDay, ol_cntdwn[2]); + CJSON(countdownHour, ol_cntdwn[3]); + CJSON(countdownMin, ol_cntdwn[4]); + CJSON(countdownSec, ol_cntdwn[5]); + CJSON(macroCountdown, ol["macro"]); + + //timed macro rules + JsonArray timers = doc["timers"]["ins"]; + uint8_t it = 0; + for (JsonObject timer : timers) { + if (it > 7) break; + CJSON(timerHours[it], timer["hour"]); + CJSON(timerMinutes[it], timer["min"]); + CJSON(timerMacro[it], timer["macro"]); + + byte dowPrev = timerWeekday[it]; + bool actPrev = timerWeekday[it] & 0x01; + CJSON(timerWeekday[it], timer["dow"]); + if (timerWeekday[it] != dowPrev) { //present in JSON + timerWeekday[it] <<= 1; //add active bit + bool act = timer["en"] | actPrev; + if (act) timerWeekday[it]++; + } + + it++; + } + + JsonObject ota = doc["ota"]; + const char* pwd = ota["psk"]; //normally not present due to security + + bool pwdCorrect = !otaLock; //always allow access if ota not locked + if (pwd != nullptr && strncmp(otaPass, pwd, 33) == 0) pwdCorrect = true; + + if (pwdCorrect) { //only accept these values from cfg.json if ota is unlocked (else from wsec.json) + CJSON(otaLock, ota["lock"]); + CJSON(wifiLock, ota["lock-wifi"]); + CJSON(aOtaEnabled, ota["aota"]); + getStringFromJson(otaPass, pwd, 33); //normally not present due to security + } +} + +void serializeSettings() { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + + JsonArray rev = doc.createNestedArray("rev"); + rev.add(1); //major settings revision + rev.add(0); //minor settings revision + + doc["vid"] = VERSION; + + JsonObject id = doc.createNestedObject("id"); + id["mdns"] = cmDNS; + id["name"] = serverDescription; + id["inv"] = alexaInvocationName; + + JsonObject nw = doc.createNestedObject("nw"); + + JsonArray nw_ins = nw.createNestedArray("ins"); + + JsonObject nw_ins_0 = nw_ins.createNestedObject(); + nw_ins_0["ssid"] = clientSSID; + nw_ins_0["pskl"] = strlen(clientPass); + + JsonArray nw_ins_0_ip = nw_ins_0.createNestedArray("ip"); + nw_ins_0_ip.add(10); + nw_ins_0_ip.add(10); + nw_ins_0_ip.add(1); + nw_ins_0_ip.add(27); + + JsonArray nw_ins_0_gw = nw_ins_0.createNestedArray("gw"); + nw_ins_0_gw.add(10); + nw_ins_0_gw.add(10); + nw_ins_0_gw.add(1); + nw_ins_0_gw.add(1); + + JsonArray nw_ins_0_sn = nw_ins_0.createNestedArray("sn"); + nw_ins_0_sn.add(255); + nw_ins_0_sn.add(255); + nw_ins_0_sn.add(255); + nw_ins_0_sn.add(0); + + JsonObject ap = doc.createNestedObject("ap"); + ap["ssid"] = "WLED-AP"; + ap["pskl"] = 8; + ap["chan"] = 6; + ap["behav"] = 0; + + JsonArray ap_ip = ap.createNestedArray("ip"); + ap_ip.add(4); + ap_ip.add(3); + ap_ip.add(2); + ap_ip.add(1); + + JsonObject wifi = doc.createNestedObject("wifi"); + wifi["sleep"] = 0; + wifi["phy"] = 0; + + JsonObject hw = doc.createNestedObject("hw"); + + JsonObject hw_led = hw.createNestedObject("led"); + hw_led["total"] = 1200; + hw_led["maxpwr"] = 0; + hw_led["ledma"] = 55; + hw_led["rev"] = false; + + JsonArray hw_led_ins = hw_led.createNestedArray("ins"); + + JsonObject hw_led_ins_0 = hw_led_ins.createNestedObject(); + hw_led_ins_0["en"] = true; + hw_led_ins_0["start"] = 0; + hw_led_ins_0["len"] = 1200; + JsonArray hw_led_ins_0_pin = hw_led_ins_0.createNestedArray("pin"); + hw_led_ins_0_pin.add(2); + hw_led_ins_0["order"] = 0; + hw_led_ins_0["rev"] = false; + hw_led_ins_0["skip"] = 0; + hw_led_ins_0["type"] = 2; + + JsonObject hw_btn = hw.createNestedObject("btn"); + + JsonArray hw_btn_ins = hw_btn.createNestedArray("ins"); + + JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject(); + hw_btn_ins_0["en"] = true; + JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin"); + hw_btn_ins_0_pin.add(0); + hw_btn_ins_0["rev"] = false; + + JsonArray hw_btn_ins_0_macros = hw_btn_ins_0.createNestedArray("macros"); + hw_btn_ins_0_macros.add(0); + hw_btn_ins_0_macros.add(0); + hw_btn_ins_0_macros.add(0); + hw_btn_ins_0["type"] = 0; + + JsonObject hw_ir = hw.createNestedObject("ir"); + hw_ir["pin"] = 4; + hw_ir["type"] = 0; + + JsonObject hw_relay = hw.createNestedObject("relay"); + hw_relay["pin"] = 12; + hw_relay["rev"] = false; + JsonObject hw_status = hw.createNestedObject("status"); + hw_status["pin"] = -1; + + JsonObject light = doc.createNestedObject("light"); + light["scale-bri"] = 100; + light["pal-mode"] = 0; + + JsonObject light_gc = light.createNestedObject("gc"); + light_gc["bri"] = 1; + light_gc["col"] = 2.2; + + JsonObject light_tr = light.createNestedObject("tr"); + light_tr["mode"] = 1; + light_tr["dur"] = 700; + light_tr["pal"] = false; + + JsonObject light_nl = light.createNestedObject("nl"); + light_nl["mode"] = 3; + light_nl["dur"] = 5; + light_nl["tbri"] = 255; + light_nl["macro"] = 0; + + JsonObject def = doc.createNestedObject("def"); + def["ps"] = 1; + def["on"] = true; + def["bri"] = 128; + + JsonObject def_cy = def.createNestedObject("cy"); + def_cy["on"] = false; + + JsonArray def_cy_range = def_cy.createNestedArray("range"); + def_cy_range.add(9); + def_cy_range.add(12); + def_cy["dur"] = 50; + + JsonObject interfaces = doc.createNestedObject("if"); + + JsonObject if_sync = interfaces.createNestedObject("sync"); + if_sync["port0"] = 21324; + if_sync["port1"] = 65506; + + JsonObject if_sync_recv = if_sync.createNestedObject("recv"); + if_sync_recv["bri"] = true; + if_sync_recv["col"] = true; + if_sync_recv["fx"] = true; + + JsonObject if_sync_send = if_sync.createNestedObject("send"); + if_sync_send["dir"] = true; + if_sync_send["btn"] = true; + if_sync_send["va"] = false; + if_sync_send["hue"] = true; + if_sync_send["macro"] = true; + if_sync_send["twice"] = false; + + JsonObject if_realtime = interfaces.createNestedObject("realtime"); + if_realtime["en"] = true; + if_realtime["port"] = 5568; + if_realtime["mc"] = false; + + JsonObject if_realtime_dmx = if_realtime.createNestedObject("dmx"); + if_realtime_dmx["uni"] = 1; + if_realtime_dmx["seqskip"] = false; + if_realtime_dmx["addr"] = 1; + if_realtime_dmx["mode"] = 4; + if_realtime["timeout"] = 250; + if_realtime["maxbri"] = true; + if_realtime["no-gc"] = false; + if_realtime["offset"] = 0; + + JsonObject if_va = interfaces.createNestedObject("va"); + if_va["alexa"] = false; + + JsonArray if_va_macros = if_va.createNestedArray("macros"); + if_va_macros.add(0); + if_va_macros.add(0); + JsonObject if_blynk = interfaces.createNestedObject("blynk"); + if_blynk["token"] = ""; + + JsonObject if_mqtt = interfaces.createNestedObject("mqtt"); + if_mqtt["en"] = false; + if_mqtt["broker"] = ""; + if_mqtt["port"] = 1883; + if_mqtt["user"] = ""; + if_mqtt["pskl"] = 0; + if_mqtt["cid"] = ""; + + JsonObject if_mqtt_topics = if_mqtt.createNestedObject("topics"); + if_mqtt_topics["device"] = "wled/test"; + if_mqtt_topics["group"] = ""; + + JsonObject if_hue = interfaces.createNestedObject("hue"); + if_hue["en"] = true; + if_hue["id"] = 1; + if_hue["iv"] = 250; + + JsonObject if_hue_recv = if_hue.createNestedObject("recv"); + if_hue_recv["on"] = true; + if_hue_recv["bri"] = true; + if_hue_recv["col"] = true; + + JsonArray if_hue_ip = if_hue.createNestedArray("ip"); + if_hue_ip.add(10); + if_hue_ip.add(10); + if_hue_ip.add(1); + if_hue_ip.add(0); + + JsonObject if_ntp = interfaces.createNestedObject("ntp"); + if_ntp["en"] = true; + if_ntp["host"] = "1.wled.pool.ntp.org"; + if_ntp["tz"] = 5; + if_ntp["offset"] = 0; + + JsonObject ol = doc.createNestedObject("ol"); + ol["clock"] = 0; + ol["cntdwn"] = 0; + ol["macro"] = 0; + + JsonObject macros = doc.createNestedObject("macros"); + + JsonArray macros_ins = macros.createNestedArray("ins"); + + JsonObject macros_ins_0 = macros_ins.createNestedObject(); + macros_ins_0["en"] = true; + macros_ins_0["hour"] = 0; + macros_ins_0["min"] = 0; + macros_ins_0["macro"] = 2; + macros_ins_0["dow"] = 0; + + JsonObject ota = doc.createNestedObject("ota"); + ota["lock"] = false; + ota["lock-wifi"] = true; + ota["pskl"] = 0; + ota["aota"] = true; + + serializeJson(doc, Serial); +} \ No newline at end of file diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 733013162..0b72918df 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -246,6 +246,8 @@ void getSettingsJS(byte subPage, char* dest) #ifdef ESP8266 #if LEDPIN == 3 oappend(SET_F("d.Sf.LC.max=500;")); + #else + oappend(SET_F("d.Sf.LC.max=1500;")); #endif #endif sappend('v',SET_F("LC"),ledCount);