Added experimental /json/cfg
endpoint for changing settings from JSON
This commit is contained in:
parent
119826cb9b
commit
d94d3d4bc5
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
### Builds after release 0.12.0
|
### Builds after release 0.12.0
|
||||||
|
|
||||||
|
#### Build 2105110
|
||||||
|
|
||||||
|
- Added Usermod settings page and configurable usermods (PR #1951)
|
||||||
|
- Added experimental `/json/cfg` endpoint for changing settings from JSON (see #1944, not part of official API)
|
||||||
|
|
||||||
#### Build 2105070
|
#### Build 2105070
|
||||||
|
|
||||||
- Fixed not turning on after pressing "Off" on IR remote twice (#1950)
|
- Fixed not turning on after pressing "Off" on IR remote twice (#1950)
|
||||||
|
@ -12,24 +12,7 @@ void getStringFromJson(char* dest, const char* src, size_t len) {
|
|||||||
if (src != nullptr) strlcpy(dest, src, len);
|
if (src != nullptr) strlcpy(dest, src, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deserializeConfig() {
|
bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||||
bool fromeep = false;
|
|
||||||
bool success = deserializeConfigSec();
|
|
||||||
if (!success) { //if file does not exist, try reading from EEPROM
|
|
||||||
deEEPSettings();
|
|
||||||
fromeep = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("Reading settings from /cfg.json..."));
|
|
||||||
|
|
||||||
success = readObjectFromFile("/cfg.json", nullptr, &doc);
|
|
||||||
if (!success) { //if file does not exist, try reading from EEPROM
|
|
||||||
if (!fromeep) deEEPSettings();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//int rev_major = doc["rev"][0]; // 1
|
//int rev_major = doc["rev"][0]; // 1
|
||||||
//int rev_minor = doc["rev"][1]; // 0
|
//int rev_minor = doc["rev"][1]; // 0
|
||||||
|
|
||||||
@ -98,6 +81,7 @@ void deserializeConfig() {
|
|||||||
CJSON(strip.rgbwMode, hw_led[F("rgbwm")]);
|
CJSON(strip.rgbwMode, hw_led[F("rgbwm")]);
|
||||||
|
|
||||||
JsonArray ins = hw_led["ins"];
|
JsonArray ins = hw_led["ins"];
|
||||||
|
if (fromFS || !ins.isNull()) {
|
||||||
uint8_t s = 0; //bus iterator
|
uint8_t s = 0; //bus iterator
|
||||||
strip.isRgbw = false;
|
strip.isRgbw = false;
|
||||||
busses.removeAll();
|
busses.removeAll();
|
||||||
@ -134,44 +118,48 @@ void deserializeConfig() {
|
|||||||
if (mem <= MAX_LED_MEMORY) busses.add(bc);
|
if (mem <= MAX_LED_MEMORY) busses.add(bc);
|
||||||
}
|
}
|
||||||
strip.finalizeInit(ledCount, skipFirstLed);
|
strip.finalizeInit(ledCount, skipFirstLed);
|
||||||
|
}
|
||||||
if (hw_led["rev"]) busses.getBus(0)->reversed = true; //set 0.11 global reversed setting for first bus
|
if (hw_led["rev"]) busses.getBus(0)->reversed = true; //set 0.11 global reversed setting for first bus
|
||||||
|
|
||||||
JsonObject hw_btn_ins_0 = hw[F("btn")][F("ins")][0];
|
JsonObject hw_btn_ins_0 = hw[F("btn")][F("ins")][0];
|
||||||
CJSON(buttonType, hw_btn_ins_0["type"]);
|
CJSON(buttonType, hw_btn_ins_0["type"]);
|
||||||
int hw_btn_pin = hw_btn_ins_0[F("pin")][0];
|
int hw_btn_pin = hw_btn_ins_0[F("pin")][0] | -2; //-2 = not present in doc, keep current. -1 = disable
|
||||||
|
if (hw_btn_pin > -2) {
|
||||||
if (pinManager.allocatePin(hw_btn_pin,false)) {
|
if (pinManager.allocatePin(hw_btn_pin,false)) {
|
||||||
btnPin = hw_btn_pin;
|
btnPin = hw_btn_pin;
|
||||||
pinMode(btnPin, INPUT_PULLUP);
|
pinMode(btnPin, INPUT_PULLUP);
|
||||||
} else {
|
} else {
|
||||||
btnPin = -1;
|
btnPin = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0[F("macros")];
|
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0[F("macros")];
|
||||||
CJSON(macroButton, hw_btn_ins_0_macros[0]);
|
CJSON(macroButton, hw_btn_ins_0_macros[0]);
|
||||||
CJSON(macroLongPress,hw_btn_ins_0_macros[1]);
|
CJSON(macroLongPress,hw_btn_ins_0_macros[1]);
|
||||||
CJSON(macroDoublePress, hw_btn_ins_0_macros[2]);
|
CJSON(macroDoublePress, hw_btn_ins_0_macros[2]);
|
||||||
|
|
||||||
//int hw_btn_ins_0_type = hw_btn_ins_0["type"]; // 0
|
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_INFRARED
|
#ifndef WLED_DISABLE_INFRARED
|
||||||
int hw_ir_pin = hw["ir"]["pin"] | -1; // 4
|
int hw_ir_pin = hw["ir"]["pin"] | -2; // 4
|
||||||
|
if (hw_ir_pin > -2) {
|
||||||
if (pinManager.allocatePin(hw_ir_pin,false)) {
|
if (pinManager.allocatePin(hw_ir_pin,false)) {
|
||||||
irPin = hw_ir_pin;
|
irPin = hw_ir_pin;
|
||||||
} else {
|
} else {
|
||||||
irPin = -1;
|
irPin = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
CJSON(irEnabled, hw["ir"]["type"]);
|
CJSON(irEnabled, hw["ir"]["type"]);
|
||||||
|
|
||||||
JsonObject relay = hw[F("relay")];
|
JsonObject relay = hw[F("relay")];
|
||||||
|
int hw_relay_pin = relay["pin"] | -2;
|
||||||
int hw_relay_pin = relay["pin"];
|
if (hw_relay_pin > -2) {
|
||||||
if (pinManager.allocatePin(hw_relay_pin,true)) {
|
if (pinManager.allocatePin(hw_relay_pin,true)) {
|
||||||
rlyPin = hw_relay_pin;
|
rlyPin = hw_relay_pin;
|
||||||
pinMode(rlyPin, OUTPUT);
|
pinMode(rlyPin, OUTPUT);
|
||||||
} else {
|
} else {
|
||||||
rlyPin = -1;
|
rlyPin = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (relay.containsKey("rev")) {
|
if (relay.containsKey("rev")) {
|
||||||
rlyMde = !relay["rev"];
|
rlyMde = !relay["rev"];
|
||||||
}
|
}
|
||||||
@ -193,12 +181,13 @@ void deserializeConfig() {
|
|||||||
CJSON(fadeTransition, light_tr[F("mode")]);
|
CJSON(fadeTransition, light_tr[F("mode")]);
|
||||||
int tdd = light_tr[F("dur")] | -1;
|
int tdd = light_tr[F("dur")] | -1;
|
||||||
if (tdd >= 0) transitionDelayDefault = tdd * 100;
|
if (tdd >= 0) transitionDelayDefault = tdd * 100;
|
||||||
CJSON(strip.paletteFade, light_tr[F("pal")]);
|
CJSON(strip.paletteFade, light_tr["pal"]);
|
||||||
|
|
||||||
JsonObject light_nl = light["nl"];
|
JsonObject light_nl = light["nl"];
|
||||||
CJSON(nightlightMode, light_nl[F("mode")]);
|
CJSON(nightlightMode, light_nl[F("mode")]);
|
||||||
|
byte prev = nightlightDelayMinsDefault;
|
||||||
CJSON(nightlightDelayMinsDefault, light_nl[F("dur")]);
|
CJSON(nightlightDelayMinsDefault, light_nl[F("dur")]);
|
||||||
nightlightDelayMins = nightlightDelayMinsDefault;
|
if (nightlightDelayMinsDefault != prev) nightlightDelayMins = nightlightDelayMinsDefault;
|
||||||
|
|
||||||
CJSON(nightlightTargetBri, light_nl[F("tbri")]);
|
CJSON(nightlightTargetBri, light_nl[F("tbri")]);
|
||||||
CJSON(macroNl, light_nl[F("macro")]);
|
CJSON(macroNl, light_nl[F("macro")]);
|
||||||
@ -227,11 +216,13 @@ void deserializeConfig() {
|
|||||||
CJSON(receiveNotificationBrightness, if_sync_recv["bri"]);
|
CJSON(receiveNotificationBrightness, if_sync_recv["bri"]);
|
||||||
CJSON(receiveNotificationColor, if_sync_recv["col"]);
|
CJSON(receiveNotificationColor, if_sync_recv["col"]);
|
||||||
CJSON(receiveNotificationEffects, if_sync_recv[F("fx")]);
|
CJSON(receiveNotificationEffects, if_sync_recv[F("fx")]);
|
||||||
|
//! following line might be a problem if called after boot
|
||||||
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
||||||
|
|
||||||
JsonObject if_sync_send = if_sync["send"];
|
JsonObject if_sync_send = if_sync["send"];
|
||||||
|
prev = notifyDirectDefault;
|
||||||
CJSON(notifyDirectDefault, if_sync_send[F("dir")]);
|
CJSON(notifyDirectDefault, if_sync_send[F("dir")]);
|
||||||
notifyDirect = notifyDirectDefault;
|
if (notifyDirectDefault != prev) notifyDirect = notifyDirectDefault;
|
||||||
CJSON(notifyButton, if_sync_send[F("btn")]);
|
CJSON(notifyButton, if_sync_send[F("btn")]);
|
||||||
CJSON(notifyAlexa, if_sync_send[F("va")]);
|
CJSON(notifyAlexa, if_sync_send[F("va")]);
|
||||||
CJSON(notifyHue, if_sync_send[F("hue")]);
|
CJSON(notifyHue, if_sync_send[F("hue")]);
|
||||||
@ -310,9 +301,10 @@ void deserializeConfig() {
|
|||||||
CJSON(latitude, if_ntp[F("lt")]);
|
CJSON(latitude, if_ntp[F("lt")]);
|
||||||
|
|
||||||
JsonObject ol = doc[F("ol")];
|
JsonObject ol = doc[F("ol")];
|
||||||
|
prev = overlayDefault;
|
||||||
CJSON(overlayDefault ,ol[F("clock")]); // 0
|
CJSON(overlayDefault ,ol[F("clock")]); // 0
|
||||||
CJSON(countdownMode, ol[F("cntdwn")]);
|
CJSON(countdownMode, ol[F("cntdwn")]);
|
||||||
overlayCurrent = overlayDefault;
|
if (prev != overlayDefault) overlayCurrent = overlayDefault;
|
||||||
|
|
||||||
CJSON(overlayMin, ol[F("min")]);
|
CJSON(overlayMin, ol[F("min")]);
|
||||||
CJSON(overlayMax, ol[F("max")]);
|
CJSON(overlayMax, ol[F("max")]);
|
||||||
@ -386,7 +378,32 @@ void deserializeConfig() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
JsonObject usermods_settings = doc["um"];
|
JsonObject usermods_settings = doc["um"];
|
||||||
usermods.readFromConfig(usermods_settings);
|
if (!usermods_settings.isNull()) usermods.readFromConfig(usermods_settings);
|
||||||
|
|
||||||
|
if (fromFS) return false;
|
||||||
|
doReboot = doc[F("rb")] | doReboot;
|
||||||
|
return (doc["sv"] | true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializeConfigFromFS() {
|
||||||
|
bool fromeep = false;
|
||||||
|
bool success = deserializeConfigSec();
|
||||||
|
if (!success) { //if file does not exist, try reading from EEPROM
|
||||||
|
deEEPSettings();
|
||||||
|
fromeep = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
||||||
|
|
||||||
|
DEBUG_PRINTLN(F("Reading settings from /cfg.json..."));
|
||||||
|
|
||||||
|
success = readObjectFromFile("/cfg.json", nullptr, &doc);
|
||||||
|
if (!success) { //if file does not exist, try reading from EEPROM
|
||||||
|
if (!fromeep) deEEPSettings();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializeConfig(doc.as<JsonObject>(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serializeConfig() {
|
void serializeConfig() {
|
||||||
@ -513,7 +530,7 @@ void serializeConfig() {
|
|||||||
JsonObject light_tr = light.createNestedObject("tr");
|
JsonObject light_tr = light.createNestedObject("tr");
|
||||||
light_tr[F("mode")] = fadeTransition;
|
light_tr[F("mode")] = fadeTransition;
|
||||||
light_tr[F("dur")] = transitionDelayDefault / 100;
|
light_tr[F("dur")] = transitionDelayDefault / 100;
|
||||||
light_tr[F("pal")] = strip.paletteFade;
|
light_tr["pal"] = strip.paletteFade;
|
||||||
|
|
||||||
JsonObject light_nl = light.createNestedObject("nl");
|
JsonObject light_nl = light.createNestedObject("nl");
|
||||||
light_nl[F("mode")] = nightlightMode;
|
light_nl[F("mode")] = nightlightMode;
|
||||||
|
@ -26,7 +26,8 @@ void handleButton();
|
|||||||
void handleIO();
|
void handleIO();
|
||||||
|
|
||||||
//cfg.cpp
|
//cfg.cpp
|
||||||
void deserializeConfig();
|
bool deserializeConfig(JsonObject doc, bool fromFS = false);
|
||||||
|
void deserializeConfigFromFS();
|
||||||
bool deserializeConfigSec();
|
bool deserializeConfigSec();
|
||||||
void serializeConfig();
|
void serializeConfig();
|
||||||
void serializeConfigSec();
|
void serializeConfigSec();
|
||||||
|
@ -98,13 +98,13 @@ void deserializeSegment(JsonObject elem, byte it)
|
|||||||
effectCurrent = elem[F("fx")] | effectCurrent;
|
effectCurrent = elem[F("fx")] | effectCurrent;
|
||||||
effectSpeed = elem[F("sx")] | effectSpeed;
|
effectSpeed = elem[F("sx")] | effectSpeed;
|
||||||
effectIntensity = elem[F("ix")] | effectIntensity;
|
effectIntensity = elem[F("ix")] | effectIntensity;
|
||||||
effectPalette = elem[F("pal")] | effectPalette;
|
effectPalette = elem["pal"] | effectPalette;
|
||||||
} else { //permanent
|
} else { //permanent
|
||||||
byte fx = elem[F("fx")] | seg.mode;
|
byte fx = elem[F("fx")] | seg.mode;
|
||||||
if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(id, fx);
|
if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(id, fx);
|
||||||
seg.speed = elem[F("sx")] | seg.speed;
|
seg.speed = elem[F("sx")] | seg.speed;
|
||||||
seg.intensity = elem[F("ix")] | seg.intensity;
|
seg.intensity = elem[F("ix")] | seg.intensity;
|
||||||
seg.palette = elem[F("pal")] | seg.palette;
|
seg.palette = elem["pal"] | seg.palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArray iarr = elem[F("i")]; //set individual LEDs
|
JsonArray iarr = elem[F("i")]; //set individual LEDs
|
||||||
@ -339,7 +339,7 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
|
|||||||
root[F("fx")] = seg.mode;
|
root[F("fx")] = seg.mode;
|
||||||
root[F("sx")] = seg.speed;
|
root[F("sx")] = seg.speed;
|
||||||
root[F("ix")] = seg.intensity;
|
root[F("ix")] = seg.intensity;
|
||||||
root[F("pal")] = seg.palette;
|
root["pal"] = seg.palette;
|
||||||
root[F("sel")] = seg.isSelected();
|
root[F("sel")] = seg.isSelected();
|
||||||
root["rev"] = seg.getOption(SEG_OPTION_REVERSED);
|
root["rev"] = seg.getOption(SEG_OPTION_REVERSED);
|
||||||
root[F("mi")] = seg.getOption(SEG_OPTION_MIRROR);
|
root[F("mi")] = seg.getOption(SEG_OPTION_MIRROR);
|
||||||
@ -740,10 +740,13 @@ void serveJson(AsyncWebServerRequest* request)
|
|||||||
request->send_P(200, "application/json", JSON_mode_names);
|
request->send_P(200, "application/json", JSON_mode_names);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (url.indexOf(F("pal")) > 0) {
|
else if (url.indexOf("pal") > 0) {
|
||||||
request->send_P(200, "application/json", JSON_palette_names);
|
request->send_P(200, "application/json", JSON_palette_names);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (url.indexOf("cfg") > 0 && handleFileRead(request, "/cfg.json")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if (url.length() > 6) { //not just /json
|
else if (url.length() > 6) { //not just /json
|
||||||
request->send( 501, "application/json", F("{\"error\":\"Not implemented\"}"));
|
request->send( 501, "application/json", F("{\"error\":\"Not implemented\"}"));
|
||||||
return;
|
return;
|
||||||
|
@ -333,7 +333,7 @@ void WLED::setup()
|
|||||||
errorFlag = ERR_FS_BEGIN;
|
errorFlag = ERR_FS_BEGIN;
|
||||||
} else deEEP();
|
} else deEEP();
|
||||||
updateFSInfo();
|
updateFSInfo();
|
||||||
deserializeConfig();
|
deserializeConfigFromFS();
|
||||||
|
|
||||||
#if STATUSLED
|
#if STATUSLED
|
||||||
bool lStatusLed = false;
|
bool lStatusLed = false;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2105070
|
#define VERSION 2105110
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
|
@ -84,6 +84,7 @@ void initServer()
|
|||||||
|
|
||||||
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request) {
|
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request) {
|
||||||
bool verboseResponse = false;
|
bool verboseResponse = false;
|
||||||
|
bool isConfig = false;
|
||||||
{ //scope JsonDocument so it releases its buffer
|
{ //scope JsonDocument so it releases its buffer
|
||||||
DynamicJsonDocument jsonBuffer(JSON_BUFFER_SIZE);
|
DynamicJsonDocument jsonBuffer(JSON_BUFFER_SIZE);
|
||||||
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject));
|
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject));
|
||||||
@ -91,12 +92,22 @@ void initServer()
|
|||||||
if (error || root.isNull()) {
|
if (error || root.isNull()) {
|
||||||
request->send(400, "application/json", F("{\"error\":9}")); return;
|
request->send(400, "application/json", F("{\"error\":9}")); return;
|
||||||
}
|
}
|
||||||
|
const String& url = request->url();
|
||||||
|
isConfig = url.indexOf("cfg") > -1;
|
||||||
|
if (!isConfig) {
|
||||||
fileDoc = &jsonBuffer;
|
fileDoc = &jsonBuffer;
|
||||||
verboseResponse = deserializeState(root);
|
verboseResponse = deserializeState(root);
|
||||||
fileDoc = nullptr;
|
fileDoc = nullptr;
|
||||||
|
} else {
|
||||||
|
verboseResponse = deserializeConfig(root); //use verboseResponse to determine whether cfg change should be saved immediately
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (verboseResponse) {
|
||||||
|
if (!isConfig) {
|
||||||
|
serveJson(request); return; //if JSON contains "v"
|
||||||
|
} else {
|
||||||
|
serializeConfig(); //Save new settings to FS
|
||||||
}
|
}
|
||||||
if (verboseResponse) { //if JSON contains "v"
|
|
||||||
serveJson(request); return;
|
|
||||||
}
|
}
|
||||||
request->send(200, "application/json", F("{\"success\":true}"));
|
request->send(200, "application/json", F("{\"success\":true}"));
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user