diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp old mode 100755 new mode 100644 index 771ada25b..449182fe7 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -1052,7 +1052,7 @@ void serializeConfig() { JsonObject usermods_settings = root.createNestedObject("um"); usermods.addToConfig(usermods_settings); - File f = WLED_FS.open("/cfg.json", "w"); + File f = WLED_FS.open(SET_F("/cfg.json"), "w"); if (f) serializeJson(root, f); f.close(); releaseJSONBufferLock(); @@ -1066,7 +1066,7 @@ bool deserializeConfigSec() { if (!requestJSONBufferLock(3)) return false; - bool success = readObjectFromFile("/wsec.json", nullptr, pDoc); + bool success = readObjectFromFile(PSTR("/wsec.json"), nullptr, pDoc); if (!success) { releaseJSONBufferLock(); return false; diff --git a/wled00/file.cpp b/wled00/file.cpp index bf90d1f47..57541dff6 100644 --- a/wled00/file.cpp +++ b/wled00/file.cpp @@ -272,8 +272,8 @@ bool writeObjectToFile(const char* file, const char* key, JsonDocument* content) #endif size_t pos = 0; - f = WLED_FS.open(file, "r+"); - if (!f && !WLED_FS.exists(file)) f = WLED_FS.open(file, "w+"); + char fileName[129]; strncpy_P(fileName, file, 128); fileName[128] = 0; //use PROGMEM safe copy as FS.open() does not + f = WLED_FS.open(fileName, WLED_FS.exists(fileName) ? "r+" : "w+"); if (!f) { DEBUGFS_PRINTLN(F("Failed to open!")); return false; @@ -340,7 +340,8 @@ bool readObjectFromFile(const char* file, const char* key, JsonDocument* dest) DEBUGFS_PRINTF("Read from %s with key %s >>>\n", file, (key==nullptr)?"nullptr":key); uint32_t s = millis(); #endif - f = WLED_FS.open(file, "r"); + char fileName[129]; strncpy_P(fileName, file, 128); fileName[128] = 0; //use PROGMEM safe copy as FS.open() does not + f = WLED_FS.open(fileName, "r"); if (!f) return false; if (key != nullptr && !bufferedFind(key)) //key does not exist in file diff --git a/wled00/ir.cpp b/wled00/ir.cpp index 3da4d68be..ba34aa526 100644 --- a/wled00/ir.cpp +++ b/wled00/ir.cpp @@ -631,6 +631,7 @@ Sample: void decodeIRJson(uint32_t code) { char objKey[10]; + char fileName[16]; String cmdStr; JsonObject fdo; JsonObject jsonCmdObj; @@ -638,17 +639,18 @@ void decodeIRJson(uint32_t code) if (!requestJSONBufferLock(13)) return; sprintf_P(objKey, PSTR("\"0x%lX\":"), (unsigned long)code); + strcpy_P(fileName, PSTR("/ir.json")); // for FS.exists() // attempt to read command from ir.json // this may fail for two reasons: ir.json does not exist or IR code not found // if the IR code is not found readObjectFromFile() will clean() doc JSON document // so we can differentiate between the two - readObjectFromFile("/ir.json", objKey, pDoc); + readObjectFromFile(fileName, objKey, pDoc); fdo = pDoc->as(); lastValidCode = 0; if (fdo.isNull()) { //the received code does not exist - if (!WLED_FS.exists("/ir.json")) errorFlag = ERR_FS_IRLOAD; //warn if IR file itself doesn't exist + if (!WLED_FS.exists(fileName)) errorFlag = ERR_FS_IRLOAD; //warn if IR file itself doesn't exist releaseJSONBufferLock(); return; } diff --git a/wled00/presets.cpp b/wled00/presets.cpp index 4897251e7..72833a97c 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -12,8 +12,8 @@ static volatile byte presetToApply = 0; static volatile byte callModeToApply = 0; static volatile byte presetToSave = 0; static volatile int8_t saveLedmap = -1; -static char quickLoad[9]; -static char saveName[33]; +static char *quickLoad = nullptr; +static char *saveName = nullptr; static bool includeBri = true, segBounds = true, selectedOnly = false, playlistSave = false;; static const char presets_json[] PROGMEM = "/presets.json"; @@ -39,8 +39,9 @@ static void doSaveState() { } else { serializeState(sObj, true, includeBri, segBounds, selectedOnly); } - sObj["n"] = saveName; - if (quickLoad[0]) sObj[F("ql")] = quickLoad; + if (saveName) sObj["n"] = saveName; + else sObj["n"] = F("Unkonwn preset"); // should not happen, but just in case... + if (quickLoad && quickLoad[0]) sObj[F("ql")] = quickLoad; if (saveLedmap >= 0) sObj[F("ledmap")] = saveLedmap; /* #ifdef WLED_DEBUG @@ -64,11 +65,11 @@ static void doSaveState() { if (tmpRAMbuffer!=nullptr) { serializeJson(*fileDoc, tmpRAMbuffer, len); } else { - writeObjectToFileUsingId(FPSTR(getPresetsFileName(persist)), presetToSave, fileDoc); + writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, fileDoc); } } else #endif - writeObjectToFileUsingId(FPSTR(getPresetsFileName(persist)), presetToSave, fileDoc); + writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, fileDoc); if (persist) presetsModifiedTime = toki.second(); //unix time releaseJSONBufferLock(); @@ -77,8 +78,10 @@ static void doSaveState() { // clean up saveLedmap = -1; presetToSave = 0; - saveName[0] = '\0'; - quickLoad[0] = '\0'; + delete[] saveName; + delete[] quickLoad; + saveName = nullptr; + quickLoad = nullptr; playlistSave = false; } @@ -86,7 +89,7 @@ bool getPresetName(byte index, String& name) { if (!requestJSONBufferLock(19)) return false; bool presetExists = false; - if (readObjectFromFileUsingId(FPSTR(getPresetsFileName()), index, pDoc)) { + if (readObjectFromFileUsingId(getPresetsFileName(), index, pDoc)) { JsonObject fdo = pDoc->as(); if (fdo["n"]) { name = (const char*)(fdo["n"]); @@ -99,12 +102,13 @@ bool getPresetName(byte index, String& name) void initPresetsFile() { - if (WLED_FS.exists(FPSTR(getPresetsFileName()))) return; + char fileName[33]; strncpy_P(fileName, getPresetsFileName(), 32); fileName[32] = 0; //use PROGMEM safe copy as FS.open() does not + if (WLED_FS.exists(fileName)) return; StaticJsonDocument<64> doc; JsonObject sObj = doc.to(); sObj.createNestedObject("0"); - File f = WLED_FS.open(FPSTR(getPresetsFileName()), "w"); + File f = WLED_FS.open(fileName, "w"); if (!f) { errorFlag = ERR_FS_GENERAL; return; @@ -164,7 +168,7 @@ void handlePresets() } else #endif { - errorFlag = readObjectFromFileUsingId(FPSTR(getPresetsFileName(tmpPreset < 255)), tmpPreset, fileDoc) ? ERR_NONE : ERR_FS_PLOAD; + errorFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, fileDoc) ? ERR_NONE : ERR_FS_PLOAD; } fdo = fileDoc->as(); @@ -202,6 +206,10 @@ void handlePresets() //called from handleSet(PS=) [network callback (fileDoc==nullptr), IR (irrational), deserializeState, UDP] and deserializeState() [network callback (filedoc!=nullptr)] void savePreset(byte index, const char* pname, JsonObject sObj) { + if (!saveName) saveName = new char[33]; + if (!quickLoad) quickLoad = new char[9]; + if (!saveName || !quickLoad) return; + if (index == 0 || (index > 250 && index < 255)) return; if (pname) strlcpy(saveName, pname, 33); else { @@ -214,6 +222,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj) presetToSave = index; playlistSave = false; if (sObj[F("ql")].is()) strlcpy(quickLoad, sObj[F("ql")].as(), 9); // client limits QL to 2 chars, buffer for 8 bytes to allow unicode + else quickLoad[0] = 0; if (sObj.size()==0 || sObj["o"].isNull()) { // no "o" means not a playlist or custom API call, saving of state is async (not immediately) includeBri = sObj["ib"].as() || sObj.size()==0 || index==255; // temporary preset needs brightness @@ -225,17 +234,22 @@ void savePreset(byte index, const char* pname, JsonObject sObj) if (sObj[F("playlist")].isNull()) { // we will save API call immediately (often causes presets.json corruption) presetToSave = 0; - if (index > 250 || !fileDoc) return; // cannot save API calls to temporary preset (255) - sObj.remove("o"); - sObj.remove("v"); - sObj.remove("time"); - sObj.remove(F("error")); - sObj.remove(F("psave")); - if (sObj["n"].isNull()) sObj["n"] = saveName; - initPresetsFile(); // just in case if someone deleted presets.json using /edit - writeObjectToFileUsingId(FPSTR(getPresetsFileName()), index, fileDoc); - presetsModifiedTime = toki.second(); //unix time - updateFSInfo(); + if (index <= 250 && fileDoc) { // cannot save API calls to temporary preset (255) + sObj.remove("o"); + sObj.remove("v"); + sObj.remove("time"); + sObj.remove(F("error")); + sObj.remove(F("psave")); + if (sObj["n"].isNull()) sObj["n"] = saveName; + initPresetsFile(); // just in case if someone deleted presets.json using /edit + writeObjectToFileUsingId(getPresetsFileName(), index, fileDoc); + presetsModifiedTime = toki.second(); //unix time + updateFSInfo(); + } + delete[] saveName; + delete[] quickLoad; + saveName = nullptr; + quickLoad = nullptr; } else { // store playlist // WARNING: playlist will be loaded in json.cpp after this call and will have repeat counter increased by 1 @@ -247,7 +261,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj) void deletePreset(byte index) { StaticJsonDocument<24> empty; - writeObjectToFileUsingId(FPSTR(getPresetsFileName()), index, &empty); + writeObjectToFileUsingId(getPresetsFileName(), index, &empty); presetsModifiedTime = toki.second(); //unix time updateFSInfo(); } \ No newline at end of file diff --git a/wled00/remote.cpp b/wled00/remote.cpp index 022b7f452..8f6650746 100644 --- a/wled00/remote.cpp +++ b/wled00/remote.cpp @@ -123,7 +123,7 @@ static bool remoteJson(int button) sprintf_P(objKey, PSTR("\"%d\":"), button); // attempt to read command from remote.json - readObjectFromFile("/remote.json", objKey, pDoc); + readObjectFromFile(PSTR("/remote.json"), objKey, pDoc); JsonObject fdo = pDoc->as(); if (fdo.isNull()) { // the received button does not exist diff --git a/wled00/wled.h b/wled00/wled.h index 2c619a9fd..8d113d6e1 100755 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2402250 +#define VERSION 2402290 //uncomment this if you have a "my_config.h" file you'd like to use //#define WLED_USE_MY_CONFIG @@ -567,7 +567,7 @@ WLED_GLOBAL byte bri _INIT(briS); // global brightness WLED_GLOBAL byte briOld _INIT(0); // global brightness while in transition loop (previous iteration) WLED_GLOBAL byte briT _INIT(0); // global brightness during transition WLED_GLOBAL byte briLast _INIT(128); // brightness before turned off. Used for toggle function -WLED_GLOBAL byte whiteLast _INIT(128); // white channel before turned off. Used for toggle function +WLED_GLOBAL byte whiteLast _INIT(128); // white channel before turned off. Used for toggle function in ir.cpp // button WLED_GLOBAL bool buttonPublishMqtt _INIT(false);