8386b9a0b4
Temporary presets in RAM (ESP32) Async loading of presets (stability). Other minor fixes. Bumped version to 0.13.1-bl6
127 lines
3.8 KiB
C++
127 lines
3.8 KiB
C++
#include "wled.h"
|
|
|
|
/*
|
|
* Methods to handle saving and loading presets to/from the filesystem
|
|
*/
|
|
|
|
#ifdef ARDUINO_ARCH_ESP32
|
|
static char *tmpRAMbuffer = nullptr;
|
|
#endif
|
|
|
|
static volatile byte presetToApply = 0;
|
|
static volatile byte callModeToApply = 0;
|
|
|
|
bool applyPreset(byte index, byte callMode)
|
|
{
|
|
presetToApply = index;
|
|
callModeToApply = callMode;
|
|
return true;
|
|
}
|
|
|
|
void handlePresets()
|
|
{
|
|
if (presetToApply == 0 || fileDoc) return; //JSON buffer allocated (apply preset in next cycle) or no preset waiting
|
|
|
|
JsonObject fdo;
|
|
const char *filename = presetToApply < 255 ? "/presets.json" : "/tmp.json";
|
|
|
|
// allocate buffer
|
|
DEBUG_PRINTLN(F("Apply preset JSON buffer requested."));
|
|
if (!requestJSONBufferLock(9)) return; // will also assign fileDoc
|
|
|
|
#ifdef ARDUINO_ARCH_ESP32
|
|
if (presetToApply==255 && tmpRAMbuffer!=nullptr) {
|
|
deserializeJson(*fileDoc,tmpRAMbuffer);
|
|
errorFlag = ERR_NONE;
|
|
} else
|
|
#endif
|
|
{
|
|
errorFlag = readObjectFromFileUsingId(filename, presetToApply, fileDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
|
}
|
|
fdo = fileDoc->as<JsonObject>();
|
|
fdo.remove("ps"); //remove load request for presets to prevent recursive crash
|
|
|
|
deserializeState(fdo, callModeToApply, presetToApply);
|
|
|
|
#if defined(ARDUINO_ARCH_ESP32)
|
|
//Aircoookie recommended not to delete buffer
|
|
if (presetToApply==255 && tmpRAMbuffer!=nullptr) {
|
|
free(tmpRAMbuffer);
|
|
tmpRAMbuffer = nullptr;
|
|
}
|
|
#endif
|
|
|
|
releaseJSONBufferLock(); // will also clear fileDoc
|
|
|
|
if (!errorFlag && presetToApply < 255) currentPreset = presetToApply;
|
|
if (callModeToApply == CALL_MODE_BUTTON_PRESET) errorFlag = ERR_NONE; //ignore error on button press
|
|
presetToApply = 0; //clear request for preset
|
|
callModeToApply = 0;
|
|
}
|
|
|
|
//called from handleSet(PS=) [network callback (fileDoc==nullptr), IR (irrational), deserializeState, UDP] and deserializeState() [network callback (filedoc!=nullptr)]
|
|
void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj)
|
|
{
|
|
if (index == 0 || (index > 250 && persist) || (index<255 && !persist)) return;
|
|
|
|
JsonObject sObj = saveobj;
|
|
bool bufferAllocated = false;
|
|
|
|
const char *filename = persist ? "/presets.json" : "/tmp.json";
|
|
|
|
if (!fileDoc) {
|
|
// called from handleSet() HTTP API
|
|
DEBUG_PRINTLN(F("Save preset JSON buffer requested."));
|
|
if (!requestJSONBufferLock(10)) return;
|
|
sObj = fileDoc->to<JsonObject>();
|
|
bufferAllocated = true;
|
|
}
|
|
if (pname) sObj["n"] = pname;
|
|
|
|
sObj.remove(F("psave"));
|
|
sObj.remove(F("v"));
|
|
|
|
if (!sObj["o"]) {
|
|
DEBUGFS_PRINTLN(F("Serialize current state"));
|
|
if (sObj["ib"].isNull() && sObj["sb"].isNull()) serializeState(sObj, true);
|
|
else serializeState(sObj, true, sObj["ib"], sObj["sb"]);
|
|
if (persist) currentPreset = index;
|
|
}
|
|
sObj.remove("o");
|
|
sObj.remove("ib");
|
|
sObj.remove("sb");
|
|
sObj.remove(F("error"));
|
|
sObj.remove(F("time"));
|
|
|
|
#if defined(ARDUINO_ARCH_ESP32)
|
|
if (index==255) {
|
|
if (tmpRAMbuffer!=nullptr) free(tmpRAMbuffer);
|
|
size_t len = measureJson(*fileDoc) + 1;
|
|
DEBUG_PRINTLN(len);
|
|
// if possible use SPI RAM on ESP32
|
|
#ifdef WLED_USE_PSRAM
|
|
if (psramFound())
|
|
tmpRAMbuffer = (char*) ps_malloc(len);
|
|
else
|
|
#endif
|
|
tmpRAMbuffer = (char*) malloc(len);
|
|
if (tmpRAMbuffer!=nullptr) {
|
|
serializeJson(*fileDoc, tmpRAMbuffer, len);
|
|
} else {
|
|
writeObjectToFileUsingId(filename, index, fileDoc);
|
|
}
|
|
} else
|
|
#endif
|
|
writeObjectToFileUsingId(filename, index, fileDoc);
|
|
|
|
if (persist) presetsModifiedTime = toki.second(); //unix time
|
|
if (bufferAllocated) releaseJSONBufferLock();
|
|
updateFSInfo();
|
|
}
|
|
|
|
void deletePreset(byte index) {
|
|
StaticJsonDocument<24> empty;
|
|
writeObjectToFileUsingId("/presets.json", index, &empty);
|
|
presetsModifiedTime = toki.second(); //unix time
|
|
updateFSInfo();
|
|
} |