mirror of
https://github.com/wled/WLED.git
synced 2025-07-20 09:16:31 +00:00
Merge pull request #4609 from willmmiles/usermod-cfg-live
Use live cfg json instead of file for usermod settings page
This commit is contained in:
commit
e979c58c98
@ -671,7 +671,7 @@ void deserializeConfigFromFS() {
|
|||||||
// call readFromConfig() with an empty object so that usermods can initialize to defaults prior to saving
|
// call readFromConfig() with an empty object so that usermods can initialize to defaults prior to saving
|
||||||
JsonObject empty = JsonObject();
|
JsonObject empty = JsonObject();
|
||||||
UsermodManager::readFromConfig(empty);
|
UsermodManager::readFromConfig(empty);
|
||||||
serializeConfig();
|
serializeConfigToFS();
|
||||||
// init Ethernet (in case default type is set at compile time)
|
// init Ethernet (in case default type is set at compile time)
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||||
initEthernet();
|
initEthernet();
|
||||||
@ -685,10 +685,10 @@ void deserializeConfigFromFS() {
|
|||||||
bool needsSave = deserializeConfig(root, true);
|
bool needsSave = deserializeConfig(root, true);
|
||||||
releaseJSONBufferLock();
|
releaseJSONBufferLock();
|
||||||
|
|
||||||
if (needsSave) serializeConfig(); // usermods required new parameters
|
if (needsSave) serializeConfigToFS(); // usermods required new parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
void serializeConfig() {
|
void serializeConfigToFS() {
|
||||||
serializeConfigSec();
|
serializeConfigSec();
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("Writing settings to /cfg.json..."));
|
DEBUG_PRINTLN(F("Writing settings to /cfg.json..."));
|
||||||
@ -697,6 +697,17 @@ void serializeConfig() {
|
|||||||
|
|
||||||
JsonObject root = pDoc->to<JsonObject>();
|
JsonObject root = pDoc->to<JsonObject>();
|
||||||
|
|
||||||
|
serializeConfig(root);
|
||||||
|
|
||||||
|
File f = WLED_FS.open(FPSTR(s_cfg_json), "w");
|
||||||
|
if (f) serializeJson(root, f);
|
||||||
|
f.close();
|
||||||
|
releaseJSONBufferLock();
|
||||||
|
|
||||||
|
configNeedsWrite = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeConfig(JsonObject root) {
|
||||||
JsonArray rev = root.createNestedArray("rev");
|
JsonArray rev = root.createNestedArray("rev");
|
||||||
rev.add(1); //major settings revision
|
rev.add(1); //major settings revision
|
||||||
rev.add(0); //minor settings revision
|
rev.add(0); //minor settings revision
|
||||||
@ -1111,13 +1122,6 @@ void serializeConfig() {
|
|||||||
|
|
||||||
JsonObject usermods_settings = root.createNestedObject("um");
|
JsonObject usermods_settings = root.createNestedObject("um");
|
||||||
UsermodManager::addToConfig(usermods_settings);
|
UsermodManager::addToConfig(usermods_settings);
|
||||||
|
|
||||||
File f = WLED_FS.open(FPSTR(s_cfg_json), "w");
|
|
||||||
if (f) serializeJson(root, f);
|
|
||||||
f.close();
|
|
||||||
releaseJSONBufferLock();
|
|
||||||
|
|
||||||
doSerializeConfig = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
function S() {
|
function S() {
|
||||||
getLoc();
|
getLoc();
|
||||||
// load settings and insert values into DOM
|
// load settings and insert values into DOM
|
||||||
fetch(getURL('/cfg.json'), {
|
fetch(getURL('/json/cfg'), {
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
@ -22,7 +22,7 @@ void rdmPersonalityChangedCb(dmx_port_t dmxPort, const rdm_header_t *header,
|
|||||||
if (header->cc == RDM_CC_SET_COMMAND_RESPONSE) {
|
if (header->cc == RDM_CC_SET_COMMAND_RESPONSE) {
|
||||||
const uint8_t personality = dmx_get_current_personality(dmx->inputPortNum);
|
const uint8_t personality = dmx_get_current_personality(dmx->inputPortNum);
|
||||||
DMXMode = std::min(DMX_MODE_PRESET, std::max(DMX_MODE_SINGLE_RGB, int(personality)));
|
DMXMode = std::min(DMX_MODE_PRESET, std::max(DMX_MODE_SINGLE_RGB, int(personality)));
|
||||||
doSerializeConfig = true;
|
configNeedsWrite = true;
|
||||||
DEBUG_PRINTF("DMX personality changed to to: %d\n", DMXMode);
|
DEBUG_PRINTF("DMX personality changed to to: %d\n", DMXMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header,
|
|||||||
if (header->cc == RDM_CC_SET_COMMAND_RESPONSE) {
|
if (header->cc == RDM_CC_SET_COMMAND_RESPONSE) {
|
||||||
const uint16_t addr = dmx_get_start_address(dmx->inputPortNum);
|
const uint16_t addr = dmx_get_start_address(dmx->inputPortNum);
|
||||||
DMXAddress = std::min(512, int(addr));
|
DMXAddress = std::min(512, int(addr));
|
||||||
doSerializeConfig = true;
|
configNeedsWrite = true;
|
||||||
DEBUG_PRINTF("DMX start addr changed to: %d\n", DMXAddress);
|
DEBUG_PRINTF("DMX start addr changed to: %d\n", DMXAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,8 @@ void IRAM_ATTR touchButtonISR();
|
|||||||
bool deserializeConfig(JsonObject doc, bool fromFS = false);
|
bool deserializeConfig(JsonObject doc, bool fromFS = false);
|
||||||
void deserializeConfigFromFS();
|
void deserializeConfigFromFS();
|
||||||
bool deserializeConfigSec();
|
bool deserializeConfigSec();
|
||||||
void serializeConfig();
|
void serializeConfig(JsonObject doc);
|
||||||
|
void serializeConfigToFS();
|
||||||
void serializeConfigSec();
|
void serializeConfigSec();
|
||||||
|
|
||||||
template<typename DestType>
|
template<typename DestType>
|
||||||
|
@ -272,5 +272,5 @@ void parseWiFiCommand(char* rpcData) {
|
|||||||
improvActive = 2;
|
improvActive = 2;
|
||||||
|
|
||||||
forceReconnect = true;
|
forceReconnect = true;
|
||||||
serializeConfig();
|
serializeConfigToFS();
|
||||||
}
|
}
|
@ -2,15 +2,6 @@
|
|||||||
|
|
||||||
#include "palettes.h"
|
#include "palettes.h"
|
||||||
|
|
||||||
#define JSON_PATH_STATE 1
|
|
||||||
#define JSON_PATH_INFO 2
|
|
||||||
#define JSON_PATH_STATE_INFO 3
|
|
||||||
#define JSON_PATH_NODES 4
|
|
||||||
#define JSON_PATH_PALETTES 5
|
|
||||||
#define JSON_PATH_FXDATA 6
|
|
||||||
#define JSON_PATH_NETWORKS 7
|
|
||||||
#define JSON_PATH_EFFECTS 8
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JSON API (De)serialization
|
* JSON API (De)serialization
|
||||||
*/
|
*/
|
||||||
@ -1036,16 +1027,21 @@ class LockedJsonResponse: public AsyncJsonResponse {
|
|||||||
|
|
||||||
void serveJson(AsyncWebServerRequest* request)
|
void serveJson(AsyncWebServerRequest* request)
|
||||||
{
|
{
|
||||||
byte subJson = 0;
|
enum class json_target {
|
||||||
|
all, state, info, state_info, nodes, effects, palettes, fxdata, networks, config
|
||||||
|
};
|
||||||
|
json_target subJson = json_target::all;
|
||||||
|
|
||||||
const String& url = request->url();
|
const String& url = request->url();
|
||||||
if (url.indexOf("state") > 0) subJson = JSON_PATH_STATE;
|
if (url.indexOf("state") > 0) subJson = json_target::state;
|
||||||
else if (url.indexOf("info") > 0) subJson = JSON_PATH_INFO;
|
else if (url.indexOf("info") > 0) subJson = json_target::info;
|
||||||
else if (url.indexOf("si") > 0) subJson = JSON_PATH_STATE_INFO;
|
else if (url.indexOf("si") > 0) subJson = json_target::state_info;
|
||||||
else if (url.indexOf(F("nodes")) > 0) subJson = JSON_PATH_NODES;
|
else if (url.indexOf(F("nodes")) > 0) subJson = json_target::nodes;
|
||||||
else if (url.indexOf(F("eff")) > 0) subJson = JSON_PATH_EFFECTS;
|
else if (url.indexOf(F("eff")) > 0) subJson = json_target::effects;
|
||||||
else if (url.indexOf(F("palx")) > 0) subJson = JSON_PATH_PALETTES;
|
else if (url.indexOf(F("palx")) > 0) subJson = json_target::palettes;
|
||||||
else if (url.indexOf(F("fxda")) > 0) subJson = JSON_PATH_FXDATA;
|
else if (url.indexOf(F("fxda")) > 0) subJson = json_target::fxdata;
|
||||||
else if (url.indexOf(F("net")) > 0) subJson = JSON_PATH_NETWORKS;
|
else if (url.indexOf(F("net")) > 0) subJson = json_target::networks;
|
||||||
|
else if (url.indexOf(F("cfg")) > 0) subJson = json_target::config;
|
||||||
#ifdef WLED_ENABLE_JSONLIVE
|
#ifdef WLED_ENABLE_JSONLIVE
|
||||||
else if (url.indexOf("live") > 0) {
|
else if (url.indexOf("live") > 0) {
|
||||||
serveLiveLeds(request);
|
serveLiveLeds(request);
|
||||||
@ -1056,9 +1052,6 @@ void serveJson(AsyncWebServerRequest* request)
|
|||||||
request->send_P(200, FPSTR(CONTENT_TYPE_JSON), JSON_palette_names);
|
request->send_P(200, FPSTR(CONTENT_TYPE_JSON), JSON_palette_names);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (url.indexOf(F("cfg")) > 0 && handleFileRead(request, F("/cfg.json"))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (url.length() > 6) { //not just /json
|
else if (url.length() > 6) { //not just /json
|
||||||
serveJsonError(request, 501, ERR_NOT_IMPL);
|
serveJsonError(request, 501, ERR_NOT_IMPL);
|
||||||
return;
|
return;
|
||||||
@ -1070,32 +1063,35 @@ void serveJson(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
// releaseJSONBufferLock() will be called when "response" is destroyed (from AsyncWebServer)
|
// releaseJSONBufferLock() will be called when "response" is destroyed (from AsyncWebServer)
|
||||||
// make sure you delete "response" if no "request->send(response);" is made
|
// make sure you delete "response" if no "request->send(response);" is made
|
||||||
LockedJsonResponse *response = new LockedJsonResponse(pDoc, subJson==JSON_PATH_FXDATA || subJson==JSON_PATH_EFFECTS); // will clear and convert JsonDocument into JsonArray if necessary
|
LockedJsonResponse *response = new LockedJsonResponse(pDoc, subJson==json_target::fxdata || subJson==json_target::effects); // will clear and convert JsonDocument into JsonArray if necessary
|
||||||
|
|
||||||
JsonVariant lDoc = response->getRoot();
|
JsonVariant lDoc = response->getRoot();
|
||||||
|
|
||||||
switch (subJson)
|
switch (subJson)
|
||||||
{
|
{
|
||||||
case JSON_PATH_STATE:
|
case json_target::state:
|
||||||
serializeState(lDoc); break;
|
serializeState(lDoc); break;
|
||||||
case JSON_PATH_INFO:
|
case json_target::info:
|
||||||
serializeInfo(lDoc); break;
|
serializeInfo(lDoc); break;
|
||||||
case JSON_PATH_NODES:
|
case json_target::nodes:
|
||||||
serializeNodes(lDoc); break;
|
serializeNodes(lDoc); break;
|
||||||
case JSON_PATH_PALETTES:
|
case json_target::palettes:
|
||||||
serializePalettes(lDoc, request->hasParam(F("page")) ? request->getParam(F("page"))->value().toInt() : 0); break;
|
serializePalettes(lDoc, request->hasParam(F("page")) ? request->getParam(F("page"))->value().toInt() : 0); break;
|
||||||
case JSON_PATH_EFFECTS:
|
case json_target::effects:
|
||||||
serializeModeNames(lDoc); break;
|
serializeModeNames(lDoc); break;
|
||||||
case JSON_PATH_FXDATA:
|
case json_target::fxdata:
|
||||||
serializeModeData(lDoc); break;
|
serializeModeData(lDoc); break;
|
||||||
case JSON_PATH_NETWORKS:
|
case json_target::networks:
|
||||||
serializeNetworks(lDoc); break;
|
serializeNetworks(lDoc); break;
|
||||||
default: //all
|
case json_target::config:
|
||||||
|
serializeConfig(lDoc); break;
|
||||||
|
case json_target::state_info:
|
||||||
|
case json_target::all:
|
||||||
JsonObject state = lDoc.createNestedObject("state");
|
JsonObject state = lDoc.createNestedObject("state");
|
||||||
serializeState(state);
|
serializeState(state);
|
||||||
JsonObject info = lDoc.createNestedObject("info");
|
JsonObject info = lDoc.createNestedObject("info");
|
||||||
serializeInfo(info);
|
serializeInfo(info);
|
||||||
if (subJson != JSON_PATH_STATE_INFO)
|
if (subJson == json_target::all)
|
||||||
{
|
{
|
||||||
JsonArray effects = lDoc.createNestedArray(F("effects"));
|
JsonArray effects = lDoc.createNestedArray(F("effects"));
|
||||||
serializeModeNames(effects); // remove WLED-SR extensions from effect names
|
serializeModeNames(effects); // remove WLED-SR extensions from effect names
|
||||||
|
@ -242,7 +242,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
|
|||||||
if (!sObj[FPSTR(bootPS)].isNull()) {
|
if (!sObj[FPSTR(bootPS)].isNull()) {
|
||||||
bootPreset = sObj[FPSTR(bootPS)] | bootPreset;
|
bootPreset = sObj[FPSTR(bootPS)] | bootPreset;
|
||||||
sObj.remove(FPSTR(bootPS));
|
sObj.remove(FPSTR(bootPS));
|
||||||
doSerializeConfig = true;
|
configNeedsWrite = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sObj.size()==0 || sObj["o"].isNull()) { // no "o" means not a playlist or custom API call, saving of state is async (not immediately)
|
if (sObj.size()==0 || sObj["o"].isNull()) { // no "o" means not a playlist or custom API call, saving of state is async (not immediately)
|
||||||
|
@ -805,8 +805,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
|
|
||||||
lastEditTime = millis();
|
lastEditTime = millis();
|
||||||
// do not save if factory reset or LED settings (which are saved after LED re-init)
|
// do not save if factory reset or LED settings (which are saved after LED re-init)
|
||||||
doSerializeConfig = subPage != SUBPAGE_LEDS && !(subPage == SUBPAGE_SEC && doReboot);
|
configNeedsWrite = subPage != SUBPAGE_LEDS && !(subPage == SUBPAGE_SEC && doReboot);
|
||||||
if (subPage == SUBPAGE_UM) doReboot = request->hasArg(F("RBT")); // prevent race condition on dual core system (set reboot here, after doSerializeConfig has been set)
|
if (subPage == SUBPAGE_UM) doReboot = request->hasArg(F("RBT")); // prevent race condition on dual core system (set reboot here, after configNeedsWrite has been set)
|
||||||
#ifndef WLED_DISABLE_ALEXA
|
#ifndef WLED_DISABLE_ALEXA
|
||||||
if (subPage == SUBPAGE_SYNC) alexaInit();
|
if (subPage == SUBPAGE_SYNC) alexaInit();
|
||||||
#endif
|
#endif
|
||||||
|
@ -193,14 +193,14 @@ void WLED::loop()
|
|||||||
if (aligned) strip.makeAutoSegments();
|
if (aligned) strip.makeAutoSegments();
|
||||||
else strip.fixInvalidSegments();
|
else strip.fixInvalidSegments();
|
||||||
BusManager::setBrightness(bri); // fix re-initialised bus' brightness
|
BusManager::setBrightness(bri); // fix re-initialised bus' brightness
|
||||||
doSerializeConfig = true;
|
configNeedsWrite = true;
|
||||||
}
|
}
|
||||||
if (loadLedmap >= 0) {
|
if (loadLedmap >= 0) {
|
||||||
strip.deserializeMap(loadLedmap);
|
strip.deserializeMap(loadLedmap);
|
||||||
loadLedmap = -1;
|
loadLedmap = -1;
|
||||||
}
|
}
|
||||||
yield();
|
yield();
|
||||||
if (doSerializeConfig) serializeConfig();
|
if (configNeedsWrite) serializeConfigToFS();
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
handleWs();
|
handleWs();
|
||||||
@ -223,7 +223,7 @@ void WLED::loop()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (doReboot && (!doInitBusses || !doSerializeConfig)) // if busses have to be inited & saved, wait until next iteration
|
if (doReboot && (!doInitBusses || !configNeedsWrite)) // if busses have to be inited & saved, wait until next iteration
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
// DEBUG serial logging (every 30s)
|
// DEBUG serial logging (every 30s)
|
||||||
|
@ -877,7 +877,7 @@ WLED_GLOBAL byte errorFlag _INIT(0);
|
|||||||
WLED_GLOBAL String messageHead, messageSub;
|
WLED_GLOBAL String messageHead, messageSub;
|
||||||
WLED_GLOBAL byte optionType;
|
WLED_GLOBAL byte optionType;
|
||||||
|
|
||||||
WLED_GLOBAL bool doSerializeConfig _INIT(false); // flag to initiate saving of config
|
WLED_GLOBAL bool configNeedsWrite _INIT(false); // flag to initiate saving of config
|
||||||
WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers
|
WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers
|
||||||
|
|
||||||
WLED_GLOBAL bool psramSafe _INIT(true); // is it safe to use PSRAM (on ESP32 rev.1; compiler fix used "-mfix-esp32-psram-cache-issue")
|
WLED_GLOBAL bool psramSafe _INIT(true); // is it safe to use PSRAM (on ESP32 rev.1; compiler fix used "-mfix-esp32-psram-cache-issue")
|
||||||
|
@ -328,7 +328,7 @@ void initServer()
|
|||||||
interfaceUpdateCallMode = CALL_MODE_WS_SEND; // schedule WS update
|
interfaceUpdateCallMode = CALL_MODE_WS_SEND; // schedule WS update
|
||||||
serveJson(request); return; //if JSON contains "v"
|
serveJson(request); return; //if JSON contains "v"
|
||||||
} else {
|
} else {
|
||||||
doSerializeConfig = true; //serializeConfig(); //Save new settings to FS
|
configNeedsWrite = true; //Save new settings to FS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
request->send(200, CONTENT_TYPE_JSON, F("{\"success\":true}"));
|
request->send(200, CONTENT_TYPE_JSON, F("{\"success\":true}"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user