diff --git a/tools/all_xml.sh b/tools/all_xml.sh
new file mode 100644
index 0000000000..68ed07bbda
--- /dev/null
+++ b/tools/all_xml.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Pull all settings pages for comparison
+HOST=$1
+TGT_PATH=$2
+CURL_ARGS="--compressed"
+
+# Replicate one target many times
+function replicate() {
+ for i in {0..10}
+ do
+ echo -n " http://${HOST}/settings.js?p=$i -o ${TGT_PATH}/$i.xml"
+ done
+}
+read -a TARGETS <<< $(replicate)
+
+mkdir -p ${TGT_PATH}
+curl ${CURL_ARGS} ${TARGETS[@]}
diff --git a/usermods/Animated_Staircase/Animated_Staircase.h b/usermods/Animated_Staircase/Animated_Staircase.h
index 8953756d35..f1404c73ac 100644
--- a/usermods/Animated_Staircase/Animated_Staircase.h
+++ b/usermods/Animated_Staircase/Animated_Staircase.h
@@ -424,11 +424,11 @@ class Animated_Staircase : public Usermod {
}
}
- void appendConfigData() {
- //oappend(SET_F("dd=addDropdown('staircase','selectfield');"));
- //oappend(SET_F("addOption(dd,'1st value',0);"));
- //oappend(SET_F("addOption(dd,'2nd value',1);"));
- //oappend(SET_F("addInfo('staircase:selectfield',1,'additional info');")); // 0 is field type, 1 is actual field
+ void appendConfigData(Print& dest) {
+ //dest.print(F("dd=addDropdown('staircase','selectfield');"));
+ //dest.print(F("addOption(dd,'1st value',0);"));
+ //dest.print(F("addOption(dd,'2nd value',1);"));
+ //dest.print(F("addInfo('staircase:selectfield',1,'additional info');")); // 0 is field type, 1 is actual field
}
diff --git a/usermods/BME68X_v2/usermod_bme68x.h b/usermods/BME68X_v2/usermod_bme68x.h
index 8e360515a2..6001ddb46b 100644
--- a/usermods/BME68X_v2/usermod_bme68x.h
+++ b/usermods/BME68X_v2/usermod_bme68x.h
@@ -52,7 +52,7 @@ class UsermodBME68X : public Usermod {
void loop(); // Loop of the user module called by wled main in loop
void setup(); // Setup of the user module called by wled main
void addToConfig(JsonObject& root); // Extends the settings/user module settings page to include the user module requirements. The settings are written from the wled core to the configuration file.
- void appendConfigData(); // Adds extra info to the config page of weld
+ void appendConfigData(Print& dest); // Adds extra info to the config page of weld
bool readFromConfig(JsonObject& root); // Reads config values
void addToJsonInfo(JsonObject& root); // Adds user module info to the weld info page
@@ -756,33 +756,33 @@ void UsermodBME68X::addToConfig(JsonObject& root) {
/**
* @brief Called by WLED: Add dropdown and additional infos / structure
- * @see Usermod::appendConfigData()
- * @see UsermodManager::appendConfigData()
+ * @see Usermod::appendConfigData(Print& dest)
+ * @see UsermodManager::appendConfigData(Print& dest)
*/
-void UsermodBME68X::appendConfigData() {
- // snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'read interval [seconds]');"), UMOD_NAME, _nameInterval); oappend(charbuffer);
- // snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'only if value changes');"), UMOD_NAME, _namePublishChange); oappend(charbuffer);
- // snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'maximum age of a message in seconds');"), UMOD_NAME, _nameMaxAge); oappend(charbuffer);
- // snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'Gas related values are only published after the gas sensor has been calibrated');"), UMOD_NAME, _namePubAfterCalib); oappend(charbuffer);
- // snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'*) Set to minus to deactivate (all sensors)');"), UMOD_NAME, _nameTemp); oappend(charbuffer);
+void UsermodBME68X::appendConfigData(Print& dest) {
+ // snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'read interval [seconds]');"), UMOD_NAME, _nameInterval); dest.print(charbuffer);
+ // snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'only if value changes');"), UMOD_NAME, _namePublishChange); dest.print(charbuffer);
+ // snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'maximum age of a message in seconds');"), UMOD_NAME, _nameMaxAge); dest.print(charbuffer);
+ // snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'Gas related values are only published after the gas sensor has been calibrated');"), UMOD_NAME, _namePubAfterCalib); dest.print(charbuffer);
+ // snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'*) Set to minus to deactivate (all sensors)');"), UMOD_NAME, _nameTemp); dest.print(charbuffer);
/* Dropdown for Celsius/Fahrenheit*/
- oappend(SET_F("dd=addDropdown('"));
- oappend(UMOD_NAME);
- oappend(SET_F("','"));
- oappend(_nameTempScale);
- oappend(SET_F("');"));
- oappend(SET_F("addOption(dd,'Celsius',0);"));
- oappend(SET_F("addOption(dd,'Fahrenheit',1);"));
+ dest.print(F("dd=addDropdown('"));
+ dest.print(UMOD_NAME);
+ dest.print(F("','"));
+ dest.print(_nameTempScale);
+ dest.print(F("');"));
+ dest.print(F("addOption(dd,'Celsius',0);"));
+ dest.print(F("addOption(dd,'Fahrenheit',1);"));
/* i²C Address*/
- oappend(SET_F("dd=addDropdown('"));
- oappend(UMOD_NAME);
- oappend(SET_F("','"));
- oappend(_nameI2CAdr);
- oappend(SET_F("');"));
- oappend(SET_F("addOption(dd,'0x76',0x76);"));
- oappend(SET_F("addOption(dd,'0x77',0x77);"));
+ dest.print(F("dd=addDropdown('"));
+ dest.print(UMOD_NAME);
+ dest.print(F("','"));
+ dest.print(_nameI2CAdr);
+ dest.print(F("');"));
+ dest.print(F("addOption(dd,'0x76',0x76);"));
+ dest.print(F("addOption(dd,'0x77',0x77);"));
}
/**
diff --git a/usermods/Battery/usermod_v2_Battery.h b/usermods/Battery/usermod_v2_Battery.h
index 136d3a71a4..7bed741c85 100644
--- a/usermods/Battery/usermod_v2_Battery.h
+++ b/usermods/Battery/usermod_v2_Battery.h
@@ -475,32 +475,32 @@ class UsermodBattery : public Usermod
DEBUG_PRINTLN(F("Battery config saved."));
}
- void appendConfigData()
+ void appendConfigData(Print& dest)
{
// Total: 462 Bytes
- oappend(SET_F("td=addDropdown('Battery','type');")); // 34 Bytes
- oappend(SET_F("addOption(td,'Unkown','0');")); // 28 Bytes
- oappend(SET_F("addOption(td,'LiPo','1');")); // 26 Bytes
- oappend(SET_F("addOption(td,'LiOn','2');")); // 26 Bytes
- oappend(SET_F("addInfo('Battery:type',1,'requires reboot');")); // 81 Bytes
- oappend(SET_F("addInfo('Battery:min-voltage',1,'v');")); // 38 Bytes
- oappend(SET_F("addInfo('Battery:max-voltage',1,'v');")); // 38 Bytes
- oappend(SET_F("addInfo('Battery:interval',1,'ms');")); // 36 Bytes
- oappend(SET_F("addInfo('Battery:HA-discovery',1,'');")); // 38 Bytes
- oappend(SET_F("addInfo('Battery:auto-off:threshold',1,'%');")); // 45 Bytes
- oappend(SET_F("addInfo('Battery:indicator:threshold',1,'%');")); // 46 Bytes
- oappend(SET_F("addInfo('Battery:indicator:duration',1,'s');")); // 45 Bytes
+ dest.print(F("td=addDropdown('Battery','type');")); // 34 Bytes
+ dest.print(F("addOption(td,'Unkown','0');")); // 28 Bytes
+ dest.print(F("addOption(td,'LiPo','1');")); // 26 Bytes
+ dest.print(F("addOption(td,'LiOn','2');")); // 26 Bytes
+ dest.print(F("addInfo('Battery:type',1,'requires reboot');")); // 81 Bytes
+ dest.print(F("addInfo('Battery:min-voltage',1,'v');")); // 38 Bytes
+ dest.print(F("addInfo('Battery:max-voltage',1,'v');")); // 38 Bytes
+ dest.print(F("addInfo('Battery:interval',1,'ms');")); // 36 Bytes
+ dest.print(F("addInfo('Battery:HA-discovery',1,'');")); // 38 Bytes
+ dest.print(F("addInfo('Battery:auto-off:threshold',1,'%');")); // 45 Bytes
+ dest.print(F("addInfo('Battery:indicator:threshold',1,'%');")); // 46 Bytes
+ dest.print(F("addInfo('Battery:indicator:duration',1,'s');")); // 45 Bytes
- // this option list would exeed the oappend() buffer
+ // this option list would exeed the dest.print() buffer
// a list of all presets to select one from
- // oappend(SET_F("bd=addDropdown('Battery:low-power-indicator', 'preset');"));
- // the loop generates: oappend(SET_F("addOption(bd, 'preset name', preset id);"));
+ // dest.print(F("bd=addDropdown('Battery:low-power-indicator', 'preset');"));
+ // the loop generates: dest.print(F("addOption(bd, 'preset name', preset id);"));
// for(int8_t i=1; i < 42; i++) {
- // oappend(SET_F("addOption(bd, 'Preset#"));
- // oappendi(i);
- // oappend(SET_F("',"));
- // oappendi(i);
- // oappend(SET_F(");"));
+ // dest.print(F("addOption(bd, 'Preset#"));
+ // dest.print(i);
+ // dest.print(F("',"));
+ // dest.print(i);
+ // dest.print(F(");"));
// }
}
diff --git a/usermods/EXAMPLE_v2/usermod_v2_example.h b/usermods/EXAMPLE_v2/usermod_v2_example.h
index 32374fde2a..5c944e97e2 100644
--- a/usermods/EXAMPLE_v2/usermod_v2_example.h
+++ b/usermods/EXAMPLE_v2/usermod_v2_example.h
@@ -281,17 +281,17 @@ class MyExampleUsermod : public Usermod {
/*
- * appendConfigData() is called when user enters usermod settings page
+ * appendConfigData(Print& dest) is called when user enters usermod settings page
* it may add additional metadata for certain entry fields (adding drop down is possible)
- * be careful not to add too much as oappend() buffer is limited to 3k
+ * be careful not to add too much as dest.print() buffer is limited to 3k
*/
- void appendConfigData() override
+ void appendConfigData(Print& dest) override
{
- oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":great")); oappend(SET_F("',1,'(this is a great config value)');"));
- oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":testString")); oappend(SET_F("',1,'enter any string you want');"));
- oappend(SET_F("dd=addDropdown('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F("','testInt');"));
- oappend(SET_F("addOption(dd,'Nothing',0);"));
- oappend(SET_F("addOption(dd,'Everything',42);"));
+ dest.print(F("addInfo('")); dest.print(String(FPSTR(_name)).c_str()); dest.print(F(":great")); dest.print(F("',1,'(this is a great config value)');"));
+ dest.print(F("addInfo('")); dest.print(String(FPSTR(_name)).c_str()); dest.print(F(":testString")); dest.print(F("',1,'enter any string you want');"));
+ dest.print(F("dd=addDropdown('")); dest.print(String(FPSTR(_name)).c_str()); dest.print(F("','testInt');"));
+ dest.print(F("addOption(dd,'Nothing',0);"));
+ dest.print(F("addOption(dd,'Everything',42);"));
}
diff --git a/usermods/Internal_Temperature_v2/usermod_internal_temperature.h b/usermods/Internal_Temperature_v2/usermod_internal_temperature.h
index 2236bfeaba..085e3da1c8 100644
--- a/usermods/Internal_Temperature_v2/usermod_internal_temperature.h
+++ b/usermods/Internal_Temperature_v2/usermod_internal_temperature.h
@@ -146,14 +146,14 @@ class InternalTemperatureUsermod : public Usermod
}
// Append useful info to the usermod settings gui
- void appendConfigData()
+ void appendConfigData(Print& dest)
{
// Display 'ms' next to the 'Loop Interval' setting
- oappend(SET_F("addInfo('Internal Temperature:Loop Interval', 1, 'ms');"));
+ dest.print(F("addInfo('Internal Temperature:Loop Interval', 1, 'ms');"));
// Display '°C' next to the 'Activation Threshold' setting
- oappend(SET_F("addInfo('Internal Temperature:Activation Threshold', 1, '°C');"));
+ dest.print(F("addInfo('Internal Temperature:Activation Threshold', 1, '°C');"));
// Display '0 = Disabled' next to the 'Preset To Activate' setting
- oappend(SET_F("addInfo('Internal Temperature:Preset To Activate', 1, '0 = unused');"));
+ dest.print(F("addInfo('Internal Temperature:Preset To Activate', 1, '0 = unused');"));
}
bool readFromConfig(JsonObject &root)
diff --git a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
index 7a67dd7497..9d4c37fba3 100644
--- a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
+++ b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
@@ -174,7 +174,7 @@ class PIRsensorSwitch : public Usermod
/**
* provide UI information and allow extending UI options
*/
- void appendConfigData() override;
+ void appendConfigData(Print& dest) override;
/**
* restore the changeable values
@@ -509,14 +509,14 @@ void PIRsensorSwitch::addToConfig(JsonObject &root)
DEBUG_PRINTLN(F("PIR config saved."));
}
-void PIRsensorSwitch::appendConfigData()
+void PIRsensorSwitch::appendConfigData(Print& dest)
{
- oappend(SET_F("addInfo('PIRsensorSwitch:HA-discovery',1,'HA=Home Assistant');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('PIRsensorSwitch:override',1,'Cancel timer on change');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('PIRsensorSwitch:HA-discovery',1,'HA=Home Assistant');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('PIRsensorSwitch:override',1,'Cancel timer on change');")); // 0 is field type, 1 is actual field
for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++) {
char str[128];
sprintf_P(str, PSTR("addInfo('PIRsensorSwitch:pin[]',%d,'','#%d');"), i, i);
- oappend(str);
+ dest.print(str);
}
}
diff --git a/usermods/ST7789_display/ST7789_display.h b/usermods/ST7789_display/ST7789_display.h
index 59f6d9271d..29104de178 100644
--- a/usermods/ST7789_display/ST7789_display.h
+++ b/usermods/ST7789_display/ST7789_display.h
@@ -376,11 +376,11 @@ class St7789DisplayUsermod : public Usermod {
}
- void appendConfigData() override {
- oappend(SET_F("addInfo('ST7789:pin[]',0,'','SPI CS');"));
- oappend(SET_F("addInfo('ST7789:pin[]',1,'','SPI DC');"));
- oappend(SET_F("addInfo('ST7789:pin[]',2,'','SPI RST');"));
- oappend(SET_F("addInfo('ST7789:pin[]',3,'','SPI BL');"));
+ void appendConfigData(Print& dest) override {
+ dest.print(F("addInfo('ST7789:pin[]',0,'','SPI CS');"));
+ dest.print(F("addInfo('ST7789:pin[]',1,'','SPI DC');"));
+ dest.print(F("addInfo('ST7789:pin[]',2,'','SPI RST');"));
+ dest.print(F("addInfo('ST7789:pin[]',3,'','SPI BL');"));
}
/*
diff --git a/usermods/Temperature/usermod_temperature.h b/usermods/Temperature/usermod_temperature.h
index d7a9d82a47..7f0ee5ca9a 100644
--- a/usermods/Temperature/usermod_temperature.h
+++ b/usermods/Temperature/usermod_temperature.h
@@ -106,7 +106,7 @@ class UsermodTemperature : public Usermod {
void addToConfig(JsonObject &root) override;
bool readFromConfig(JsonObject &root) override;
- void appendConfigData() override;
+ void appendConfigData(Print& dest) override;
};
//Dallas sensor quick (& dirty) reading. Credit to - Author: Peter Scargill, August 17th, 2013
@@ -434,11 +434,11 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
return !top[FPSTR(_domoticzIDX)].isNull();
}
-void UsermodTemperature::appendConfigData() {
- oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":")); oappend(String(FPSTR(_parasite)).c_str());
- oappend(SET_F("',1,'(if no Vcc connected)');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":")); oappend(String(FPSTR(_parasitePin)).c_str());
- oappend(SET_F("',1,'(for external MOSFET)');")); // 0 is field type, 1 is actual field
+void UsermodTemperature::appendConfigData(Print& dest) {
+ dest.print(F("addInfo('")); dest.print(String(FPSTR(_name)).c_str()); dest.print(F(":")); dest.print(String(FPSTR(_parasite)).c_str());
+ dest.print(F("',1,'(if no Vcc connected)');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('")); dest.print(String(FPSTR(_name)).c_str()); dest.print(F(":")); dest.print(String(FPSTR(_parasitePin)).c_str());
+ dest.print(F("',1,'(for external MOSFET)');")); // 0 is field type, 1 is actual field
}
float UsermodTemperature::getTemperature() {
diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h
index fde7afded0..50a7783222 100644
--- a/usermods/audioreactive/audio_reactive.h
+++ b/usermods/audioreactive/audio_reactive.h
@@ -1879,57 +1879,57 @@ class AudioReactive : public Usermod {
}
- void appendConfigData() override
+ void appendConfigData(Print& dest) override
{
#ifdef ARDUINO_ARCH_ESP32
- oappend(SET_F("dd=addDropdown('AudioReactive','digitalmic:type');"));
+ dest.print(F("dd=addDropdown('AudioReactive','digitalmic:type');"));
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
- oappend(SET_F("addOption(dd,'Generic Analog',0);"));
+ dest.print(F("addOption(dd,'Generic Analog',0);"));
#endif
- oappend(SET_F("addOption(dd,'Generic I2S',1);"));
- oappend(SET_F("addOption(dd,'ES7243',2);"));
- oappend(SET_F("addOption(dd,'SPH0654',3);"));
- oappend(SET_F("addOption(dd,'Generic I2S with Mclk',4);"));
+ dest.print(F("addOption(dd,'Generic I2S',1);"));
+ dest.print(F("addOption(dd,'ES7243',2);"));
+ dest.print(F("addOption(dd,'SPH0654',3);"));
+ dest.print(F("addOption(dd,'Generic I2S with Mclk',4);"));
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
- oappend(SET_F("addOption(dd,'Generic I2S PDM',5);"));
+ dest.print(F("addOption(dd,'Generic I2S PDM',5);"));
#endif
- oappend(SET_F("addOption(dd,'ES8388',6);"));
+ dest.print(F("addOption(dd,'ES8388',6);"));
- oappend(SET_F("dd=addDropdown('AudioReactive','config:AGC');"));
- oappend(SET_F("addOption(dd,'Off',0);"));
- oappend(SET_F("addOption(dd,'Normal',1);"));
- oappend(SET_F("addOption(dd,'Vivid',2);"));
- oappend(SET_F("addOption(dd,'Lazy',3);"));
-
- oappend(SET_F("dd=addDropdown('AudioReactive','dynamics:limiter');"));
- oappend(SET_F("addOption(dd,'Off',0);"));
- oappend(SET_F("addOption(dd,'On',1);"));
- oappend(SET_F("addInfo('AudioReactive:dynamics:limiter',0,' On ');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('AudioReactive:dynamics:rise',1,'ms (♪ effects only)');"));
- oappend(SET_F("addInfo('AudioReactive:dynamics:fall',1,'ms (♪ effects only)');"));
-
- oappend(SET_F("dd=addDropdown('AudioReactive','frequency:scale');"));
- oappend(SET_F("addOption(dd,'None',0);"));
- oappend(SET_F("addOption(dd,'Linear (Amplitude)',2);"));
- oappend(SET_F("addOption(dd,'Square Root (Energy)',3);"));
- oappend(SET_F("addOption(dd,'Logarithmic (Loudness)',1);"));
+ dest.print(F("dd=addDropdown('AudioReactive','config:AGC');"));
+ dest.print(F("addOption(dd,'Off',0);"));
+ dest.print(F("addOption(dd,'Normal',1);"));
+ dest.print(F("addOption(dd,'Vivid',2);"));
+ dest.print(F("addOption(dd,'Lazy',3);"));
+
+ dest.print(F("dd=addDropdown('AudioReactive','dynamics:limiter');"));
+ dest.print(F("addOption(dd,'Off',0);"));
+ dest.print(F("addOption(dd,'On',1);"));
+ dest.print(F("addInfo('AudioReactive:dynamics:limiter',0,' On ');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('AudioReactive:dynamics:rise',1,'ms (♪ effects only)');"));
+ dest.print(F("addInfo('AudioReactive:dynamics:fall',1,'ms (♪ effects only)');"));
+
+ dest.print(F("dd=addDropdown('AudioReactive','frequency:scale');"));
+ dest.print(F("addOption(dd,'None',0);"));
+ dest.print(F("addOption(dd,'Linear (Amplitude)',2);"));
+ dest.print(F("addOption(dd,'Square Root (Energy)',3);"));
+ dest.print(F("addOption(dd,'Logarithmic (Loudness)',1);"));
#endif
- oappend(SET_F("dd=addDropdown('AudioReactive','sync:mode');"));
- oappend(SET_F("addOption(dd,'Off',0);"));
+ dest.print(F("dd=addDropdown('AudioReactive','sync:mode');"));
+ dest.print(F("addOption(dd,'Off',0);"));
#ifdef ARDUINO_ARCH_ESP32
- oappend(SET_F("addOption(dd,'Send',1);"));
+ dest.print(F("addOption(dd,'Send',1);"));
#endif
- oappend(SET_F("addOption(dd,'Receive',2);"));
+ dest.print(F("addOption(dd,'Receive',2);"));
#ifdef ARDUINO_ARCH_ESP32
- oappend(SET_F("addInfo('AudioReactive:digitalmic:type',1,'requires reboot!');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',0,'sd/data/dout','I2S SD');"));
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',1,'ws/clk/lrck','I2S WS');"));
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',2,'sck/bclk','I2S SCK');"));
+ dest.print(F("addInfo('AudioReactive:digitalmic:type',1,'requires reboot!');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('AudioReactive:digitalmic:pin[]',0,'sd/data/dout','I2S SD');"));
+ dest.print(F("addInfo('AudioReactive:digitalmic:pin[]',1,'ws/clk/lrck','I2S WS');"));
+ dest.print(F("addInfo('AudioReactive:digitalmic:pin[]',2,'sck/bclk','I2S SCK');"));
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'only use -1, 0, 1 or 3','I2S MCLK');"));
+ dest.print(F("addInfo('AudioReactive:digitalmic:pin[]',3,'only use -1, 0, 1 or 3','I2S MCLK');"));
#else
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'master clock','I2S MCLK');"));
+ dest.print(F("addInfo('AudioReactive:digitalmic:pin[]',3,'master clock','I2S MCLK');"));
#endif
#endif
}
diff --git a/usermods/boblight/boblight.h b/usermods/boblight/boblight.h
index 916f7da988..ec470ed1a3 100644
--- a/usermods/boblight/boblight.h
+++ b/usermods/boblight/boblight.h
@@ -304,15 +304,15 @@ class BobLightUsermod : public Usermod {
}
}
- void appendConfigData() override {
- //oappend(SET_F("dd=addDropdown('usermod','selectfield');"));
- //oappend(SET_F("addOption(dd,'1st value',0);"));
- //oappend(SET_F("addOption(dd,'2nd value',1);"));
- oappend(SET_F("addInfo('BobLight:top',1,'LEDs');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('BobLight:bottom',1,'LEDs');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('BobLight:left',1,'LEDs');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('BobLight:right',1,'LEDs');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('BobLight:pct',1,'Depth of scan [%]');")); // 0 is field type, 1 is actual field
+ void appendConfigData(Print& dest) override {
+ //dest.print(F("dd=addDropdown('usermod','selectfield');"));
+ //dest.print(F("addOption(dd,'1st value',0);"));
+ //dest.print(F("addOption(dd,'2nd value',1);"));
+ dest.print(F("addInfo('BobLight:top',1,'LEDs');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('BobLight:bottom',1,'LEDs');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('BobLight:left',1,'LEDs');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('BobLight:right',1,'LEDs');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('BobLight:pct',1,'Depth of scan [%]');")); // 0 is field type, 1 is actual field
}
void addToConfig(JsonObject& root) override {
diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/usermod_multi_relay.h
index efb3c8ae19..16a2a01d69 100644
--- a/usermods/multi_relay/usermod_multi_relay.h
+++ b/usermods/multi_relay/usermod_multi_relay.h
@@ -211,7 +211,7 @@ class MultiRelay : public Usermod {
*/
void addToConfig(JsonObject &root) override;
- void appendConfigData() override;
+ void appendConfigData(Print& dest) override;
/**
* restore the changeable values
@@ -764,11 +764,11 @@ void MultiRelay::addToConfig(JsonObject &root) {
DEBUG_PRINTLN(F("MultiRelay config saved."));
}
-void MultiRelay::appendConfigData() {
- oappend(SET_F("addInfo('MultiRelay:PCF8574-address',1,'(not hex!)');"));
- oappend(SET_F("addInfo('MultiRelay:broadcast-sec',1,'(MQTT message)');"));
- //oappend(SET_F("addInfo('MultiRelay:relay-0:pin',1,'(use -1 for PCF8574)');"));
- oappend(SET_F("d.extra.push({'MultiRelay':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
+void MultiRelay::appendConfigData(Print& dest) {
+ dest.print(F("addInfo('MultiRelay:PCF8574-address',1,'(not hex!)');"));
+ dest.print(F("addInfo('MultiRelay:broadcast-sec',1,'(MQTT message)');"));
+ //dest.print(F("addInfo('MultiRelay:relay-0:pin',1,'(use -1 for PCF8574)');"));
+ dest.print(F("d.extra.push({'MultiRelay':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
}
/**
diff --git a/usermods/pixels_dice_tray/pixels_dice_tray.h b/usermods/pixels_dice_tray/pixels_dice_tray.h
index 238af314ea..1f21869aea 100644
--- a/usermods/pixels_dice_tray/pixels_dice_tray.h
+++ b/usermods/pixels_dice_tray/pixels_dice_tray.h
@@ -374,7 +374,7 @@ class PixelsDiceTrayUsermod : public Usermod {
#endif
}
- void appendConfigData() override {
+ void appendConfigData(Print& dest) override {
// Slightly annoying that you can't put text before an element.
// The an item on the usermod config page has the following HTML:
// ```html
@@ -387,23 +387,23 @@ class PixelsDiceTrayUsermod : public Usermod {
// To work around this, add info text to the end of the preceding item.
//
// See addInfo in wled00/data/settings_um.htm for details on what this function does.
- oappend(SET_F(
+ dest.print(F(
"addInfo('DiceTray:ble_scan_duration',1,'
Set to \"*\" to "
"connect to any die.
Leave Blank to disable.
Saving will replace \"*\" with die names.','');"));
#if USING_TFT_DISPLAY
- oappend(SET_F("ddr=addDropdown('DiceTray','rotation');"));
- oappend(SET_F("addOption(ddr,'0 deg',0);"));
- oappend(SET_F("addOption(ddr,'90 deg',1);"));
- oappend(SET_F("addOption(ddr,'180 deg',2);"));
- oappend(SET_F("addOption(ddr,'270 deg',3);"));
- oappend(SET_F(
+ dest.print(F("ddr=addDropdown('DiceTray','rotation');"));
+ dest.print(F("addOption(ddr,'0 deg',0);"));
+ dest.print(F("addOption(ddr,'90 deg',1);"));
+ dest.print(F("addOption(ddr,'180 deg',2);"));
+ dest.print(F("addOption(ddr,'270 deg',3);"));
+ dest.print(F(
"addInfo('DiceTray:rotation',1,'
DO NOT CHANGE "
"SPI PINS.
CHANGES ARE IGNORED.','');"));
- oappend(SET_F("addInfo('TFT:pin[]',0,'','SPI CS');"));
- oappend(SET_F("addInfo('TFT:pin[]',1,'','SPI DC');"));
- oappend(SET_F("addInfo('TFT:pin[]',2,'','SPI RST');"));
- oappend(SET_F("addInfo('TFT:pin[]',3,'','SPI BL');"));
+ dest.print(F("addInfo('TFT:pin[]',0,'','SPI CS');"));
+ dest.print(F("addInfo('TFT:pin[]',1,'','SPI DC');"));
+ dest.print(F("addInfo('TFT:pin[]',2,'','SPI RST');"));
+ dest.print(F("addInfo('TFT:pin[]',3,'','SPI BL');"));
#endif
}
diff --git a/usermods/sht/usermod_sht.h b/usermods/sht/usermod_sht.h
index c6e17221be..0fc0cc439f 100644
--- a/usermods/sht/usermod_sht.h
+++ b/usermods/sht/usermod_sht.h
@@ -53,7 +53,7 @@ class ShtUsermod : public Usermod
void setup();
void loop();
void onMqttConnect(bool sessionPresent);
- void appendConfigData();
+ void appendConfigData(Print& dest);
void addToConfig(JsonObject &root);
bool readFromConfig(JsonObject &root);
void addToJsonInfo(JsonObject& root);
@@ -304,28 +304,28 @@ void ShtUsermod::onMqttConnect(bool sessionPresent) {
/**
* Add dropdown for sensor type and unit to UM config page.
*
- * @see Usermod::appendConfigData()
- * @see UsermodManager::appendConfigData()
+ * @see Usermod::appendConfigData(Print& dest)
+ * @see UsermodManager::appendConfigData(Print& dest)
*
* @return void
*/
-void ShtUsermod::appendConfigData() {
- oappend(SET_F("dd=addDropdown('"));
- oappend(_name);
- oappend(SET_F("','"));
- oappend(_shtType);
- oappend(SET_F("');"));
- oappend(SET_F("addOption(dd,'SHT30',0);"));
- oappend(SET_F("addOption(dd,'SHT31',1);"));
- oappend(SET_F("addOption(dd,'SHT35',2);"));
- oappend(SET_F("addOption(dd,'SHT85',3);"));
- oappend(SET_F("dd=addDropdown('"));
- oappend(_name);
- oappend(SET_F("','"));
- oappend(_unitOfTemp);
- oappend(SET_F("');"));
- oappend(SET_F("addOption(dd,'Celsius',0);"));
- oappend(SET_F("addOption(dd,'Fahrenheit',1);"));
+void ShtUsermod::appendConfigData(Print& dest) {
+ dest.print(F("dd=addDropdown('"));
+ dest.print(_name);
+ dest.print(F("','"));
+ dest.print(_shtType);
+ dest.print(F("');"));
+ dest.print(F("addOption(dd,'SHT30',0);"));
+ dest.print(F("addOption(dd,'SHT31',1);"));
+ dest.print(F("addOption(dd,'SHT35',2);"));
+ dest.print(F("addOption(dd,'SHT85',3);"));
+ dest.print(F("dd=addDropdown('"));
+ dest.print(_name);
+ dest.print(F("','"));
+ dest.print(_unitOfTemp);
+ dest.print(F("');"));
+ dest.print(F("addOption(dd,'Celsius',0);"));
+ dest.print(F("addOption(dd,'Fahrenheit',1);"));
}
/**
diff --git a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
index 008647fa7b..36ec2f2065 100644
--- a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
+++ b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
@@ -309,7 +309,7 @@ class FourLineDisplayUsermod : public Usermod {
*/
//void readFromJsonState(JsonObject& root) override;
- void appendConfigData() override;
+ void appendConfigData(Print& dest) override;
/*
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
@@ -1201,22 +1201,22 @@ void FourLineDisplayUsermod::onUpdateBegin(bool init) {
// if (!initDone) return; // prevent crash on boot applyPreset()
//}
-void FourLineDisplayUsermod::appendConfigData() {
- oappend(SET_F("dd=addDropdown('4LineDisplay','type');"));
- oappend(SET_F("addOption(dd,'None',0);"));
- oappend(SET_F("addOption(dd,'SSD1306',1);"));
- oappend(SET_F("addOption(dd,'SH1106',2);"));
- oappend(SET_F("addOption(dd,'SSD1306 128x64',3);"));
- oappend(SET_F("addOption(dd,'SSD1305',4);"));
- oappend(SET_F("addOption(dd,'SSD1305 128x64',5);"));
- oappend(SET_F("addOption(dd,'SSD1309 128x64',9);"));
- oappend(SET_F("addOption(dd,'SSD1306 SPI',6);"));
- oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);"));
- oappend(SET_F("addOption(dd,'SSD1309 SPI 128x64',8);"));
- oappend(SET_F("addInfo('4LineDisplay:type',1,'
Change may require reboot','');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',0,'','SPI CS');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',1,'','SPI DC');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',2,'','SPI RST');"));
+void FourLineDisplayUsermod::appendConfigData(Print& dest) {
+ dest.print(F("dd=addDropdown('4LineDisplay','type');"));
+ dest.print(F("addOption(dd,'None',0);"));
+ dest.print(F("addOption(dd,'SSD1306',1);"));
+ dest.print(F("addOption(dd,'SH1106',2);"));
+ dest.print(F("addOption(dd,'SSD1306 128x64',3);"));
+ dest.print(F("addOption(dd,'SSD1305',4);"));
+ dest.print(F("addOption(dd,'SSD1305 128x64',5);"));
+ dest.print(F("addOption(dd,'SSD1309 128x64',9);"));
+ dest.print(F("addOption(dd,'SSD1306 SPI',6);"));
+ dest.print(F("addOption(dd,'SSD1306 SPI 128x64',7);"));
+ dest.print(F("addOption(dd,'SSD1309 SPI 128x64',8);"));
+ dest.print(F("addInfo('4LineDisplay:type',1,'
Change may require reboot','');"));
+ dest.print(F("addInfo('4LineDisplay:pin[]',0,'','SPI CS');"));
+ dest.print(F("addInfo('4LineDisplay:pin[]',1,'','SPI DC');"));
+ dest.print(F("addInfo('4LineDisplay:pin[]',2,'','SPI RST');"));
}
/*
diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
index 5756fbb695..9802c1829e 100644
--- a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
+++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
@@ -347,7 +347,7 @@ class RotaryEncoderUIUsermod : public Usermod {
*/
void addToConfig(JsonObject &root) override;
- void appendConfigData() override;
+ void appendConfigData(Print& dest) override;
/**
* restore the changeable values
@@ -1089,9 +1089,9 @@ void RotaryEncoderUIUsermod::addToConfig(JsonObject &root) {
DEBUG_PRINTLN(F("Rotary Encoder config saved."));
}
-void RotaryEncoderUIUsermod::appendConfigData() {
- oappend(SET_F("addInfo('Rotary-Encoder:PCF8574-address',1,'(not hex!)');"));
- oappend(SET_F("d.extra.push({'Rotary-Encoder':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
+void RotaryEncoderUIUsermod::appendConfigData(Print& dest) {
+ dest.print(F("addInfo('Rotary-Encoder:PCF8574-address',1,'(not hex!)');"));
+ dest.print(F("d.extra.push({'Rotary-Encoder':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
}
/**
diff --git a/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h b/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h
index b66be290a5..1d541a1741 100644
--- a/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h
+++ b/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h
@@ -431,10 +431,10 @@ class WordClockUsermod : public Usermod
top[F("Norddeutsch")] = nord;
}
- void appendConfigData()
+ void appendConfigData(Print& dest)
{
- oappend(SET_F("addInfo('WordClockUsermod:ledOffset', 1, 'Number of LEDs before the letters');"));
- oappend(SET_F("addInfo('WordClockUsermod:Norddeutsch', 1, 'Viertel vor instead of Dreiviertel');"));
+ dest.print(F("addInfo('WordClockUsermod:ledOffset', 1, 'Number of LEDs before the letters');"));
+ dest.print(F("addInfo('WordClockUsermod:Norddeutsch', 1, 'Viertel vor instead of Dreiviertel');"));
}
/*
diff --git a/usermods/wireguard/wireguard.h b/usermods/wireguard/wireguard.h
index 8c88d00018..573adfb00e 100644
--- a/usermods/wireguard/wireguard.h
+++ b/usermods/wireguard/wireguard.h
@@ -53,14 +53,14 @@ class WireguardUsermod : public Usermod {
if (is_enabled) infoArr.add(uiDomString);
}
- void appendConfigData() {
- oappend(SET_F("addInfo('WireGuard:host',1,'Server Hostname');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:port',1,'Server Port');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:ip',1,'Device IP');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:psk',1,'Pre Shared Key (optional)');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:pem',1,'Private Key');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:pub',1,'Public Key');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:tz',1,'POSIX timezone string');")); // 0 is field type, 1 is actual field
+ void appendConfigData(Print& dest) {
+ dest.print(F("addInfo('WireGuard:host',1,'Server Hostname');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('WireGuard:port',1,'Server Port');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('WireGuard:ip',1,'Device IP');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('WireGuard:psk',1,'Pre Shared Key (optional)');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('WireGuard:pem',1,'Private Key');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('WireGuard:pub',1,'Public Key');")); // 0 is field type, 1 is actual field
+ dest.print(F("addInfo('WireGuard:tz',1,'POSIX timezone string');")); // 0 is field type, 1 is actual field
}
void addToConfig(JsonObject& root) {
diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h
index a95064a2a6..29db8ea765 100644
--- a/wled00/fcn_declare.h
+++ b/wled00/fcn_declare.h
@@ -302,7 +302,7 @@ class Usermod {
virtual bool handleButton(uint8_t b) { return false; } // button overrides are possible here
virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; }; // usermod data exchange [see examples for audio effects]
virtual void connected() {} // called when WiFi is (re)connected
- virtual void appendConfigData() {} // helper function called from usermod settings page to add metadata for entry fields
+ virtual void appendConfigData(Print&); // helper function called from usermod settings page to add metadata for entry fields
virtual void addToJsonState(JsonObject& obj) {} // add JSON objects for WLED state
virtual void addToJsonInfo(JsonObject& obj) {} // add JSON objects for UI Info page
virtual void readFromJsonState(JsonObject& obj) {} // process JSON messages received from web server
@@ -314,6 +314,16 @@ class Usermod {
virtual void onUpdateBegin(bool) {} // fired prior to and after unsuccessful firmware update
virtual void onStateChange(uint8_t mode) {} // fired upon WLED state change
virtual uint16_t getId() {return USERMOD_ID_UNSPECIFIED;}
+
+ // API shims
+ private:
+ static Print* oappend_shim;
+ // old form of appendConfigData; called by default appendConfigData(Print&) with oappend_shim set up
+ // private so it is not accidentally invoked except via Usermod::appendConfigData(Print&)
+ virtual void appendConfigData() {}
+ protected:
+ // Shim for oappend(), which used to exist in utils.cpp
+ template static inline void oappend(const T& t) { oappend_shim->print(t); };
};
class UsermodManager {
@@ -328,7 +338,7 @@ class UsermodManager {
bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods
void setup();
void connected();
- void appendConfigData();
+ void appendConfigData(Print&);
void addToJsonState(JsonObject& obj);
void addToJsonInfo(JsonObject& obj);
void readFromJsonState(JsonObject& obj);
@@ -362,10 +372,11 @@ void parseNumber(const char* str, byte* val, byte minv=0, byte maxv=255);
bool getVal(JsonVariant elem, byte* val, byte minv=0, byte maxv=255);
bool getBoolVal(JsonVariant elem, bool dflt);
bool updateVal(const char* req, const char* key, byte* val, byte minv=0, byte maxv=255);
-bool oappend(const char* txt); // append new c string to temp buffer efficiently
-bool oappendi(int i); // append new number to temp buffer efficiently
-void sappend(char stype, const char* key, int val);
-void sappends(char stype, const char* key, char* val);
+size_t printSetFormCheckbox(Print& dest, const char* key, int val);
+size_t printSetFormValue(Print& dest, const char* key, int val);
+size_t printSetFormValue(Print& dest, const char* key, const char* val);
+size_t printSetFormIndex(Print& dest, const char* key, int index);
+size_t printSetClassElementHTML(Print& dest, const char* key, const int index, const char* val);
void prepareHostname(char* hostname);
bool isAsterisksOnly(const char* str, byte maxLen);
bool requestJSONBufferLock(uint8_t module=255);
@@ -444,7 +455,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
void sendDataWs(AsyncWebSocketClient * client = nullptr);
//xml.cpp
-void XML_response(AsyncWebServerRequest *request, char* dest = nullptr);
-void getSettingsJS(byte subPage, char* dest);
+void XML_response(Print& dest);
+void getSettingsJS(byte subPage, Print& dest);
#endif
diff --git a/wled00/file.cpp b/wled00/file.cpp
index 69e1e692cd..bc34672023 100644
--- a/wled00/file.cpp
+++ b/wled00/file.cpp
@@ -433,7 +433,7 @@ bool handleFileRead(AsyncWebServerRequest* request, String path){
}
#endif
if(WLED_FS.exists(path) || WLED_FS.exists(path + ".gz")) {
- request->send(WLED_FS, path, String(), request->hasArg(F("download")));
+ request->send(request->beginResponse(WLED_FS, path, {}, request->hasArg(F("download")), {}));
return true;
}
return false;
diff --git a/wled00/mqtt.cpp b/wled00/mqtt.cpp
index 833e6eb7d4..6694be07dc 100644
--- a/wled00/mqtt.cpp
+++ b/wled00/mqtt.cpp
@@ -124,6 +124,32 @@ static void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProp
payloadStr = nullptr;
}
+// Print adapter for flat buffers
+namespace {
+class bufferPrint : public Print {
+ char* _buf;
+ size_t _size, _offset;
+ public:
+
+ bufferPrint(char* buf, size_t size) : _buf(buf), _size(size), _offset(0) {};
+
+ size_t write(const uint8_t *buffer, size_t size) {
+ size = std::min(size, _size - _offset);
+ memcpy(_buf + _offset, buffer, size);
+ _offset += size;
+ return size;
+ }
+
+ size_t write(uint8_t c) {
+ return this->write(&c, 1);
+ }
+
+ char* data() const { return _buf; }
+ size_t size() const { return _offset; }
+ size_t capacity() const { return _size; }
+};
+}; // anonymous namespace
+
void publishMqtt()
{
@@ -148,11 +174,13 @@ void publishMqtt()
strcat_P(subuf, PSTR("/status"));
mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT
- char apires[1024]; // allocating 1024 bytes from stack can be risky
- XML_response(nullptr, apires);
+ // TODO: use a DynamicBufferList. Requires a list-read-capable MQTT client API.
+ DynamicBuffer buf(1024);
+ bufferPrint pbuf(buf.data(), buf.size());
+ XML_response(pbuf);
strlcpy(subuf, mqttDeviceTopic, 33);
strcat_P(subuf, PSTR("/v"));
- mqtt->publish(subuf, 0, retainMqttMsg, apires); // optionally retain message (#2263)
+ mqtt->publish(subuf, 0, retainMqttMsg, buf.data(), pbuf.size()); // optionally retain message (#2263)
#endif
}
diff --git a/wled00/set.cpp b/wled00/set.cpp
index 812bcc52f3..05b5b31811 100644
--- a/wled00/set.cpp
+++ b/wled00/set.cpp
@@ -1191,7 +1191,11 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
// internal call, does not send XML response
pos = req.indexOf(F("IN"));
- if (pos < 1) XML_response(request);
+ if (pos < 1) {
+ auto response = request->beginResponseStream("text/xml");
+ XML_response(*response);
+ request->send(response);
+ }
return true;
}
diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp
index 2db29c3cda..5307d26f6b 100644
--- a/wled00/um_manager.cpp
+++ b/wled00/um_manager.cpp
@@ -8,7 +8,7 @@ void UsermodManager::setup() { for (unsigned i = 0; i < numMods; i++
void UsermodManager::connected() { for (unsigned i = 0; i < numMods; i++) ums[i]->connected(); }
void UsermodManager::loop() { for (unsigned i = 0; i < numMods; i++) ums[i]->loop(); }
void UsermodManager::handleOverlayDraw() { for (unsigned i = 0; i < numMods; i++) ums[i]->handleOverlayDraw(); }
-void UsermodManager::appendConfigData() { for (unsigned i = 0; i < numMods; i++) ums[i]->appendConfigData(); }
+void UsermodManager::appendConfigData(Print& dest) { for (unsigned i = 0; i < numMods; i++) ums[i]->appendConfigData(dest); }
bool UsermodManager::handleButton(uint8_t b) {
bool overrideIO = false;
for (unsigned i = 0; i < numMods; i++) {
@@ -68,3 +68,14 @@ bool UsermodManager::add(Usermod* um)
ums[numMods++] = um;
return true;
}
+
+
+/* Usermod v2 interface shim for oappend */
+Print* Usermod::oappend_shim = nullptr;
+
+void Usermod::appendConfigData(Print& p) {
+ assert(!oappend_shim);
+ oappend_shim = &p;
+ this->appendConfigData();
+ oappend_shim = nullptr;
+}
diff --git a/wled00/util.cpp b/wled00/util.cpp
index 99a75bdd30..07190e37cc 100644
--- a/wled00/util.cpp
+++ b/wled00/util.cpp
@@ -87,90 +87,30 @@ bool updateVal(const char* req, const char* key, byte* val, byte minv, byte maxv
return true;
}
-
-//append a numeric setting to string buffer
-void sappend(char stype, const char* key, int val)
-{
- char ds[] = "d.Sf.";
-
- switch(stype)
- {
- case 'c': //checkbox
- oappend(ds);
- oappend(key);
- oappend(".checked=");
- oappendi(val);
- oappend(";");
- break;
- case 'v': //numeric
- oappend(ds);
- oappend(key);
- oappend(".value=");
- oappendi(val);
- oappend(";");
- break;
- case 'i': //selectedIndex
- oappend(ds);
- oappend(key);
- oappend(SET_F(".selectedIndex="));
- oappendi(val);
- oappend(";");
- break;
- }
+static size_t printSetFormInput(Print& dest, const char* key, const char* selector, int value) {
+ return dest.printf_P(PSTR("d.Sf.%s.%s=%d;"), key, selector, value);
}
-
-//append a string setting to buffer
-void sappends(char stype, const char* key, char* val)
-{
- switch(stype)
- {
- case 's': {//string (we can interpret val as char*)
- String buf = val;
- //convert "%" to "%%" to make EspAsyncWebServer happy
- //buf.replace("%","%%");
- oappend("d.Sf.");
- oappend(key);
- oappend(".value=\"");
- oappend(buf.c_str());
- oappend("\";");
- break;}
- case 'm': //message
- oappend(SET_F("d.getElementsByClassName"));
- oappend(key);
- oappend(SET_F(".innerHTML=\""));
- oappend(val);
- oappend("\";");
- break;
- }
+size_t printSetFormCheckbox(Print& dest, const char* key, int val) {
+ return printSetFormInput(dest, key, PSTR("checked"), val);
}
-
-
-bool oappendi(int i)
-{
- char s[12]; // 32bit signed number can have 10 digits plus - sign
- sprintf(s, "%d", i);
- return oappend(s);
+size_t printSetFormValue(Print& dest, const char* key, int val) {
+ return printSetFormInput(dest, key, PSTR("value"), val);
+}
+size_t printSetFormIndex(Print& dest, const char* key, int index) {
+ return printSetFormInput(dest, key, PSTR("selectedIndex"), index);
}
+size_t printSetFormValue(Print& dest, const char* key, const char* val) {
+ return dest.printf_P(PSTR("d.Sf.%s.value=\"%s\";"),key,val);
+}
-bool oappend(const char* txt)
-{
- unsigned len = strlen(txt);
- if ((obuf == nullptr) || (olen + len >= SETTINGS_STACK_BUF_SIZE)) { // sanity checks
-#ifdef WLED_DEBUG
- DEBUG_PRINT(F("oappend() buffer overflow. Cannot append "));
- DEBUG_PRINT(len); DEBUG_PRINT(F(" bytes \t\""));
- DEBUG_PRINT(txt); DEBUG_PRINTLN(F("\""));
-#endif
- return false; // buffer full
- }
- strcpy(obuf + olen, txt);
- olen += len;
- return true;
+size_t printSetClassElementHTML(Print& dest, const char* key, const int index, const char* val) {
+ return dest.printf_P(PSTR("d.getElementsByClassName(\"%s\")[%d].innerHTML=\"%s\";"), key, index, val);
}
+
void prepareHostname(char* hostname)
{
sprintf_P(hostname, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6);
diff --git a/wled00/wled.h b/wled00/wled.h
index 31a6128580..052f29b29f 100644
--- a/wled00/wled.h
+++ b/wled00/wled.h
@@ -839,10 +839,6 @@ WLED_GLOBAL time_t sunrise _INIT(0);
WLED_GLOBAL time_t sunset _INIT(0);
WLED_GLOBAL Toki toki _INIT(Toki());
-// Temp buffer
-WLED_GLOBAL char* obuf;
-WLED_GLOBAL uint16_t olen _INIT(0);
-
// General filesystem
WLED_GLOBAL size_t fsBytesUsed _INIT(0);
WLED_GLOBAL size_t fsBytesTotal _INIT(0);
diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp
index 9d4e4c85b9..c0e6c0c4a5 100644
--- a/wled00/wled_server.cpp
+++ b/wled00/wled_server.cpp
@@ -520,27 +520,24 @@ void serveSettingsJS(AsyncWebServerRequest* request)
handleStaticContent(request, FPSTR(_common_js), 200, FPSTR(CONTENT_TYPE_JAVASCRIPT), JS_common, JS_common_length);
return;
}
- char buf[SETTINGS_STACK_BUF_SIZE+37];
- buf[0] = 0;
+
byte subPage = request->arg(F("p")).toInt();
if (subPage > 10) {
- strcpy_P(buf, PSTR("alert('Settings for this request are not implemented.');"));
- request->send(501, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
+ request->send_P(501, FPSTR(CONTENT_TYPE_JAVASCRIPT), PSTR("alert('Settings for this request are not implemented.');"));
return;
}
if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) {
- strcpy_P(buf, PSTR("alert('PIN incorrect.');"));
- request->send(401, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
+ request->send_P(401, FPSTR(CONTENT_TYPE_JAVASCRIPT), PSTR("alert('PIN incorrect.');"));
return;
}
- strcat_P(buf,PSTR("function GetV(){var d=document;"));
- getSettingsJS(subPage, buf+strlen(buf)); // this may overflow by 35bytes!!!
- strcat_P(buf,PSTR("}"));
- AsyncWebServerResponse *response;
- response = request->beginResponse(200, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
+ AsyncResponseStream *response = request->beginResponseStream(FPSTR(CONTENT_TYPE_JAVASCRIPT));
response->addHeader(F("Cache-Control"), F("no-store"));
response->addHeader(F("Expires"), F("0"));
+
+ response->print(F("function GetV(){var d=document;"));
+ getSettingsJS(subPage, *response);
+ response->print(F("}"));
request->send(response);
}
diff --git a/wled00/xml.cpp b/wled00/xml.cpp
index 71d66d0022..8e6a35f17c 100644
--- a/wled00/xml.cpp
+++ b/wled00/xml.cpp
@@ -6,85 +6,39 @@
*/
//build XML response to HTTP /win API request
-void XML_response(AsyncWebServerRequest *request, char* dest)
+void XML_response(Print& dest)
{
- char sbuf[(dest == nullptr)?1024:1]; //allocate local buffer if none passed
- obuf = (dest == nullptr)? sbuf:dest;
-
- olen = 0;
- oappend(SET_F(""));
- oappendi((nightlightActive && nightlightMode > NL_MODE_SET) ? briT : bri);
- oappend(SET_F(""));
-
+ dest.printf_P(PSTR("%d"), (nightlightActive && nightlightMode > NL_MODE_SET) ? briT : bri);
for (int i = 0; i < 3; i++)
{
- oappend("");
- oappendi(col[i]);
- oappend("");
+ dest.printf_P(PSTR("%d"), col[i]);
}
for (int i = 0; i < 3; i++)
{
- oappend("");
- oappendi(colSec[i]);
- oappend("");
- }
- oappend(SET_F(""));
- oappendi(notifyDirect);
- oappend(SET_F(""));
- oappendi(receiveGroups!=0);
- oappend(SET_F(""));
- oappendi(nightlightActive);
- oappend(SET_F(""));
- oappendi(nightlightMode > NL_MODE_SET);
- oappend(SET_F(""));
- oappendi(nightlightDelayMins);
- oappend(SET_F(""));
- oappendi(nightlightTargetBri);
- oappend(SET_F(""));
- oappendi(effectCurrent);
- oappend(SET_F(""));
- oappendi(effectSpeed);
- oappend(SET_F(""));
- oappendi(effectIntensity);
- oappend(SET_F(""));
- oappendi(effectPalette);
- oappend(SET_F(""));
- if (strip.hasWhiteChannel()) {
- oappendi(col[3]);
- } else {
- oappend("-1");
- }
- oappend(SET_F(""));
- oappendi(colSec[3]);
- oappend(SET_F(""));
- oappendi(currentPreset);
- oappend(SET_F(""));
- oappendi(currentPlaylist >= 0);
- oappend(SET_F(""));
- oappend(serverDescription);
- if (realtimeMode)
- {
- oappend(SET_F(" (live)"));
+ dest.printf_P(PSTR("%d"), colSec[i]);
}
- oappend(SET_F(""));
- oappendi(strip.getFirstSelectedSegId());
- oappend(SET_F(""));
- if (request != nullptr) request->send(200, "text/xml", obuf);
+ dest.printf_P(PSTR("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%s%s%d"),
+ notifyDirect, receiveGroups!=0, nightlightActive, nightlightMode > NL_MODE_SET, nightlightDelayMins,
+ nightlightTargetBri, effectCurrent, effectSpeed, effectIntensity, effectPalette,
+ strip.hasWhiteChannel() ? col[3] : -1, colSec[3], currentPreset, currentPlaylist >= 0,
+ serverDescription, realtimeMode ? PSTR(" (live)") : "",
+ strip.getFirstSelectedSegId()
+ );
}
-void extractPin(JsonObject &obj, const char *key) {
+static void extractPin(Print& dest, JsonObject &obj, const char *key) {
if (obj[key].is()) {
JsonArray pins = obj[key].as();
for (JsonVariant pv : pins) {
- if (pv.as() > -1) { oappend(","); oappendi(pv.as()); }
+ if (pv.as() > -1) { dest.print(","); dest.print(pv.as()); }
}
} else {
- if (obj[key].as() > -1) { oappend(","); oappendi(obj[key].as()); }
+ if (obj[key].as() > -1) { dest.print(","); dest.print(obj[key].as()); }
}
}
-// oappend used pins by scanning JsonObject (1 level deep)
-void fillUMPins(JsonObject &mods)
+// dest.print used pins by scanning JsonObject (1 level deep)
+void fillUMPins(Print& dest, JsonObject &mods)
{
for (JsonPair kv : mods) {
// kv.key() is usermod name or subobject key
@@ -93,7 +47,7 @@ void fillUMPins(JsonObject &mods)
if (!obj.isNull()) {
// element is an JsonObject
if (!obj["pin"].isNull()) {
- extractPin(obj, "pin");
+ extractPin(dest, obj, "pin");
} else {
// scan keys (just one level deep as is possible with usermods)
for (JsonPair so : obj) {
@@ -102,7 +56,7 @@ void fillUMPins(JsonObject &mods)
// we found a key containing "pin" substring
if (strlen(strstr(key, "pin")) == 3) {
// and it is at the end, we found another pin
- extractPin(obj, key);
+ extractPin(dest, obj, key);
continue;
}
}
@@ -110,7 +64,7 @@ void fillUMPins(JsonObject &mods)
JsonObject subObj = obj[so.key()];
if (!subObj["pin"].isNull()) {
// get pins from subobject
- extractPin(subObj, "pin");
+ extractPin(dest, subObj, "pin");
}
}
}
@@ -118,167 +72,151 @@ void fillUMPins(JsonObject &mods)
}
}
-void appendGPIOinfo() {
- char nS[8];
-
+void appendGPIOinfo(Print& dest) {
// add usermod pins as d.um_p array
- oappend(SET_F("d.um_p=[-1")); // has to have 1 element
+ dest.print(F("d.um_p=[-1")); // has to have 1 element
if (i2c_sda > -1 && i2c_scl > -1) {
- oappend(","); oappend(itoa(i2c_sda,nS,10));
- oappend(","); oappend(itoa(i2c_scl,nS,10));
+ dest.printf_P(PSTR(",%d,%d"), i2c_sda, i2c_scl);
}
if (spi_mosi > -1 && spi_sclk > -1) {
- oappend(","); oappend(itoa(spi_mosi,nS,10));
- oappend(","); oappend(itoa(spi_sclk,nS,10));
+ dest.printf_P(PSTR(",%d,%d"), spi_mosi, spi_sclk);
}
// usermod pin reservations will become unnecessary when settings pages will read cfg.json directly
if (requestJSONBufferLock(6)) {
// if we can't allocate JSON buffer ignore usermod pins
JsonObject mods = pDoc->createNestedObject(F("um"));
usermods.addToConfig(mods);
- if (!mods.isNull()) fillUMPins(mods);
+ if (!mods.isNull()) fillUMPins(dest, mods);
releaseJSONBufferLock();
}
- oappend(SET_F("];"));
+ dest.print(F("];"));
// add reserved (unusable) pins
- oappend(SET_F("d.rsvd=["));
+ dest.print(F("d.rsvd=["));
for (unsigned i = 0; i < WLED_NUM_PINS; i++) {
if (!pinManager.isPinOk(i, false)) { // include readonly pins
- oappendi(i); oappend(",");
+ dest.printf_P(PSTR("%d,"),i);
}
}
#ifdef WLED_ENABLE_DMX
- oappend(SET_F("2,")); // DMX hardcoded pin
+ dest.print(F("2,")); // DMX hardcoded pin
#endif
#if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST)
- oappend(itoa(hardwareTX,nS,10)); oappend(","); // debug output (TX) pin
+ dest.printf_P(PSTR("%d,"),hardwareTX); // debug output (TX) pin
#endif
//Note: Using pin 3 (RX) disables Adalight / Serial JSON
#ifdef WLED_USE_ETHERNET
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
- for (unsigned p=0; p=0) { oappend(itoa(ethernetBoards[ethernetType].eth_power,nS,10)); oappend(","); }
- if (ethernetBoards[ethernetType].eth_mdc>=0) { oappend(itoa(ethernetBoards[ethernetType].eth_mdc,nS,10)); oappend(","); }
- if (ethernetBoards[ethernetType].eth_mdio>=0) { oappend(itoa(ethernetBoards[ethernetType].eth_mdio,nS,10)); oappend(","); }
- switch (ethernetBoards[ethernetType].eth_clk_mode) {
+ for (unsigned p=0; p=0) { dest.printf("%d,", ethernetBoards[ethernetType].eth_power); }
+ if (ethernetBoards[ethernetType].eth_mdc>=0) { dest.printf("%d,", ethernetBoards[ethernetType].eth_mdc); }
+ if (ethernetBoards[ethernetType].eth_mdio>=0) { dest.printf("%d,", ethernetBoards[ethernetType].eth_mdio); }
+ switch (ethernetBoards[ethernetType].eth_clk_mode) {
case ETH_CLOCK_GPIO0_IN:
case ETH_CLOCK_GPIO0_OUT:
- oappend(SET_F("0"));
+ dest.print(F("0"));
break;
case ETH_CLOCK_GPIO16_OUT:
- oappend(SET_F("16"));
+ dest.print(F("16"));
break;
case ETH_CLOCK_GPIO17_OUT:
- oappend(SET_F("17"));
+ dest.print(F("17"));
break;
}
}
#endif
- oappend(SET_F("];")); // rsvd
+ dest.print(F("];")); // rsvd
// add info for read-only GPIO
- oappend(SET_F("d.ro_gpio=["));
+ dest.print(F("d.ro_gpio=["));
bool firstPin = true;
for (unsigned i = 0; i < WLED_NUM_PINS; i++) {
if (pinManager.isReadOnlyPin(i)) {
// No comma before the first pin
- if (!firstPin) oappend(SET_F(","));
- oappendi(i);
+ if (!firstPin) dest.print(',');
+ dest.print(i);
firstPin = false;
}
}
- oappend(SET_F("];"));
+ dest.print(F("];"));
// add info about max. # of pins
- oappend(SET_F("d.max_gpio="));
- oappendi(WLED_NUM_PINS);
- oappend(SET_F(";"));
+ dest.printf_P(PSTR("d.max_gpio=%d;"),WLED_NUM_PINS);
}
//get values for settings form in javascript
-void getSettingsJS(byte subPage, char* dest)
+void getSettingsJS(byte subPage, Print& dest)
{
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec
DEBUG_PRINTF_P(PSTR("settings resp %u\n"), (unsigned)subPage);
- obuf = dest;
- olen = 0;
if (subPage <0 || subPage >10) return;
if (subPage == SUBPAGE_MENU)
{
#ifdef WLED_DISABLE_2D // include only if 2D is not compiled in
- oappend(PSTR("gId('2dbtn').style.display='none';"));
+ dest.print(F("gId('2dbtn').style.display='none';"));
#endif
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
- oappend(PSTR("gId('dmxbtn').style.display='';"));
+ dest.print(F("gId('dmxbtn').style.display='';"));
#endif
}
if (subPage == SUBPAGE_WIFI)
{
- char nS[10];
size_t l;
- oappend(SET_F("resetWiFi("));
- oappend(itoa(WLED_MAX_WIFI_COUNT,nS,10));
- oappend(SET_F(");"));
+ dest.printf_P(PSTR("resetWiFi(%d);"), WLED_MAX_WIFI_COUNT);
for (size_t n = 0; n < multiWiFi.size(); n++) {
l = strlen(multiWiFi[n].clientPass);
char fpass[l+1]; //fill password field with ***
fpass[l] = 0;
memset(fpass,'*',l);
- oappend(SET_F("addWiFi(\""));
- oappend(multiWiFi[n].clientSSID);
- oappend(SET_F("\",\""));
- oappend(fpass);
- oappend(SET_F("\",0x"));
- oappend(itoa(multiWiFi[n].staticIP,nS,16));
- oappend(SET_F(",0x"));
- oappend(itoa(multiWiFi[n].staticGW,nS,16));
- oappend(SET_F(",0x"));
- oappend(itoa(multiWiFi[n].staticSN,nS,16));
- oappend(SET_F(");"));
+ dest.printf_P(PSTR("addWiFi(\"%s\",\",%s\",0x%X,0x%X,0x%X);"),
+ multiWiFi[n].clientSSID,
+ fpass,
+ (uint32_t) multiWiFi[n].staticIP, // explicit cast required as this is a struct
+ (uint32_t) multiWiFi[n].staticGW,
+ (uint32_t) multiWiFi[n].staticSN);
}
- sappend('v',SET_F("D0"),dnsAddress[0]);
- sappend('v',SET_F("D1"),dnsAddress[1]);
- sappend('v',SET_F("D2"),dnsAddress[2]);
- sappend('v',SET_F("D3"),dnsAddress[3]);
+ printSetFormValue(dest,PSTR("D0"),dnsAddress[0]);
+ printSetFormValue(dest,PSTR("D1"),dnsAddress[1]);
+ printSetFormValue(dest,PSTR("D2"),dnsAddress[2]);
+ printSetFormValue(dest,PSTR("D3"),dnsAddress[3]);
- sappends('s',SET_F("CM"),cmDNS);
- sappend('i',SET_F("AB"),apBehavior);
- sappends('s',SET_F("AS"),apSSID);
- sappend('c',SET_F("AH"),apHide);
+ printSetFormValue(dest,PSTR("CM"),cmDNS);
+ printSetFormIndex(dest,PSTR("AB"),apBehavior);
+ printSetFormValue(dest,PSTR("AS"),apSSID);
+ printSetFormCheckbox(dest,PSTR("AH"),apHide);
l = strlen(apPass);
char fapass[l+1]; //fill password field with ***
fapass[l] = 0;
memset(fapass,'*',l);
- sappends('s',SET_F("AP"),fapass);
+ printSetFormValue(dest,PSTR("AP"),fapass);
- sappend('v',SET_F("AC"),apChannel);
+ printSetFormValue(dest,PSTR("AC"),apChannel);
#ifdef ARDUINO_ARCH_ESP32
- sappend('v',SET_F("TX"),txPower);
+ printSetFormValue(dest,PSTR("TX"),txPower);
#else
- oappend(SET_F("gId('tx').style.display='none';"));
+ dest.print(F("gId('tx').style.display='none';"));
#endif
- sappend('c',SET_F("FG"),force802_3g);
- sappend('c',SET_F("WS"),noWifiSleep);
+ printSetFormCheckbox(dest,PSTR("FG"),force802_3g);
+ printSetFormCheckbox(dest,PSTR("WS"),noWifiSleep);
#ifndef WLED_DISABLE_ESPNOW
- sappend('c',SET_F("RE"),enableESPNow);
- sappends('s',SET_F("RMAC"),linked_remote);
+ printSetFormCheckbox(dest,PSTR("RE"),enableESPNow);
+ printSetFormValue(dest,PSTR("RMAC"),linked_remote);
#else
//hide remote settings if not compiled
- oappend(SET_F("toggle('ESPNOW');")); // hide ESP-NOW setting
+ dest.print(F("toggle('ESPNOW');")); // hide ESP-NOW setting
#endif
#ifdef WLED_USE_ETHERNET
- sappend('v',SET_F("ETH"),ethernetType);
+ printSetFormValue(dest,PSTR("ETH"),ethernetType);
#else
//hide ethernet setting if not compiled in
- oappend(SET_F("gId('ethd').style.display='none';"));
+ dest.print(F("gId('ethd').style.display='none';"));
#endif
if (Network.isConnected()) //is connected
@@ -290,10 +228,10 @@ void getSettingsJS(byte subPage, char* dest)
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
if (Network.isEthernet()) strcat_P(s ,SET_F(" (Ethernet)"));
#endif
- sappends('m',SET_F("(\"sip\")[0]"),s);
+ printSetClassElementHTML(dest,PSTR("sip"),0,s);
} else
{
- sappends('m',SET_F("(\"sip\")[0]"),(char*)F("Not connected"));
+ printSetClassElementHTML(dest,PSTR("sip"),0,(char*)F("Not connected"));
}
if (WiFi.softAPIP()[0] != 0) //is active
@@ -301,19 +239,19 @@ void getSettingsJS(byte subPage, char* dest)
char s[16];
IPAddress apIP = WiFi.softAPIP();
sprintf(s, "%d.%d.%d.%d", apIP[0], apIP[1], apIP[2], apIP[3]);
- sappends('m',SET_F("(\"sip\")[1]"),s);
+ printSetClassElementHTML(dest,PSTR("sip"),1,s);
} else
{
- sappends('m',SET_F("(\"sip\")[1]"),(char*)F("Not active"));
+ printSetClassElementHTML(dest,PSTR("sip"),1,(char*)F("Not active"));
}
#ifndef WLED_DISABLE_ESPNOW
if (strlen(last_signal_src) > 0) { //Have seen an ESP-NOW Remote
- sappends('m',SET_F("(\"rlid\")[0]"),last_signal_src);
+ printSetClassElementHTML(dest,PSTR("rlid"),0,last_signal_src);
} else if (!enableESPNow) {
- sappends('m',SET_F("(\"rlid\")[0]"),(char*)F("(Enable ESP-NOW to listen)"));
+ printSetClassElementHTML(dest,PSTR("rlid"),0,(char*)F("(Enable ESP-NOW to listen)"));
} else {
- sappends('m',SET_F("(\"rlid\")[0]"),(char*)F("None"));
+ printSetClassElementHTML(dest,PSTR("rlid"),0,(char*)F("None"));
}
#endif
}
@@ -322,30 +260,30 @@ void getSettingsJS(byte subPage, char* dest)
{
char nS[32];
- appendGPIOinfo();
+ appendGPIOinfo(dest);
- oappend(SET_F("d.ledTypes=")); oappend(BusManager::getLEDTypesJSONString().c_str()); oappend(";");
+ dest.printf_P(PSTR("d.ledTypes=%s;"), BusManager::getLEDTypesJSONString().c_str());
// set limits
- oappend(SET_F("bLimits("));
- oappend(itoa(WLED_MAX_BUSSES,nS,10)); oappend(",");
- oappend(itoa(WLED_MIN_VIRTUAL_BUSSES,nS,10)); oappend(",");
- oappend(itoa(MAX_LEDS_PER_BUS,nS,10)); oappend(",");
- oappend(itoa(MAX_LED_MEMORY,nS,10)); oappend(",");
- oappend(itoa(MAX_LEDS,nS,10)); oappend(",");
- oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10)); oappend(",");
- oappend(itoa(WLED_MAX_DIGITAL_CHANNELS,nS,10)); oappend(",");
- oappend(itoa(WLED_MAX_ANALOG_CHANNELS,nS,10));
- oappend(SET_F(");"));
-
- sappend('c',SET_F("MS"),strip.autoSegments);
- sappend('c',SET_F("CCT"),strip.correctWB);
- sappend('c',SET_F("IC"),cctICused);
- sappend('c',SET_F("CR"),strip.cctFromRgb);
- sappend('v',SET_F("CB"),strip.cctBlending);
- sappend('v',SET_F("FR"),strip.getTargetFps());
- sappend('v',SET_F("AW"),Bus::getGlobalAWMode());
- sappend('c',SET_F("LD"),useGlobalLedBuffer);
+ dest.printf_P(PSTR("bLimits(%d,%d,%d,%d,%d,%d,%d,%d);"),
+ WLED_MAX_BUSSES,
+ WLED_MIN_VIRTUAL_BUSSES,
+ MAX_LEDS_PER_BUS,
+ MAX_LED_MEMORY,
+ MAX_LEDS,
+ WLED_MAX_COLOR_ORDER_MAPPINGS,
+ WLED_MAX_DIGITAL_CHANNELS,
+ WLED_MAX_ANALOG_CHANNELS
+ );
+
+ printSetFormCheckbox(dest,PSTR("MS"),strip.autoSegments);
+ printSetFormCheckbox(dest,PSTR("CCT"),strip.correctWB);
+ printSetFormCheckbox(dest,PSTR("IC"),cctICused);
+ printSetFormCheckbox(dest,PSTR("CR"),strip.cctFromRgb);
+ printSetFormValue(dest,PSTR("CB"),strip.cctBlending);
+ printSetFormValue(dest,PSTR("FR"),strip.getTargetFps());
+ printSetFormValue(dest,PSTR("AW"),Bus::getGlobalAWMode());
+ printSetFormCheckbox(dest,PSTR("LD"),useGlobalLedBuffer);
unsigned sumMa = 0;
for (int s = 0; s < BusManager::getNumBusses(); s++) {
@@ -365,22 +303,22 @@ void getSettingsJS(byte subPage, char* dest)
char sp[4] = "SP"; sp[2] = offset+s; sp[3] = 0; //bus clock speed
char la[4] = "LA"; la[2] = offset+s; la[3] = 0; //LED current
char ma[4] = "MA"; ma[2] = offset+s; ma[3] = 0; //max per-port PSU current
- oappend(SET_F("addLEDs(1);"));
+ dest.print(F("addLEDs(1);"));
uint8_t pins[5];
int nPins = bus->getPins(pins);
for (int i = 0; i < nPins; i++) {
lp[1] = offset+i;
- if (pinManager.isPinOk(pins[i]) || bus->isVirtual()) sappend('v',lp,pins[i]);
+ if (pinManager.isPinOk(pins[i]) || bus->isVirtual()) printSetFormValue(dest,lp,pins[i]);
}
- sappend('v',lc,bus->getLength());
- sappend('v',lt,bus->getType());
- sappend('v',co,bus->getColorOrder() & 0x0F);
- sappend('v',ls,bus->getStart());
- sappend('c',cv,bus->isReversed());
- sappend('v',sl,bus->skippedLeds());
- sappend('c',rf,bus->isOffRefreshRequired());
- sappend('v',aw,bus->getAutoWhiteMode());
- sappend('v',wo,bus->getColorOrder() >> 4);
+ printSetFormValue(dest,lc,bus->getLength());
+ printSetFormValue(dest,lt,bus->getType());
+ printSetFormValue(dest,co,bus->getColorOrder() & 0x0F);
+ printSetFormValue(dest,ls,bus->getStart());
+ printSetFormCheckbox(dest,cv,bus->isReversed());
+ printSetFormValue(dest,sl,bus->skippedLeds());
+ printSetFormCheckbox(dest,rf,bus->isOffRefreshRequired());
+ printSetFormValue(dest,aw,bus->getAutoWhiteMode());
+ printSetFormValue(dest,wo,bus->getColorOrder() >> 4);
unsigned speed = bus->getFrequency();
if (bus->isPWM()) {
switch (speed) {
@@ -401,158 +339,148 @@ void getSettingsJS(byte subPage, char* dest)
case 20000 : speed = 4; break;
}
}
- sappend('v',sp,speed);
- sappend('v',la,bus->getLEDCurrent());
- sappend('v',ma,bus->getMaxCurrent());
+ printSetFormValue(dest,sp,speed);
+ printSetFormValue(dest,la,bus->getLEDCurrent());
+ printSetFormValue(dest,ma,bus->getMaxCurrent());
sumMa += bus->getMaxCurrent();
}
- sappend('v',SET_F("MA"),BusManager::ablMilliampsMax() ? BusManager::ablMilliampsMax() : sumMa);
- sappend('c',SET_F("ABL"),BusManager::ablMilliampsMax() || sumMa > 0);
- sappend('c',SET_F("PPL"),!BusManager::ablMilliampsMax() && sumMa > 0);
+ printSetFormValue(dest,PSTR("MA"),BusManager::ablMilliampsMax() ? BusManager::ablMilliampsMax() : sumMa);
+ printSetFormCheckbox(dest,PSTR("ABL"),BusManager::ablMilliampsMax() || sumMa > 0);
+ printSetFormCheckbox(dest,PSTR("PPL"),!BusManager::ablMilliampsMax() && sumMa > 0);
- oappend(SET_F("resetCOM("));
- oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10));
- oappend(SET_F(");"));
+ dest.printf_P(PSTR("resetCOM(%d);"), WLED_MAX_COLOR_ORDER_MAPPINGS);
const ColorOrderMap& com = BusManager::getColorOrderMap();
for (int s = 0; s < com.count(); s++) {
const ColorOrderMapEntry* entry = com.get(s);
if (entry == nullptr) break;
- oappend(SET_F("addCOM("));
- oappend(itoa(entry->start,nS,10)); oappend(",");
- oappend(itoa(entry->len,nS,10)); oappend(",");
- oappend(itoa(entry->colorOrder,nS,10)); oappend(");");
+ dest.printf_P(PSTR("addCOM(%d,%d,%d);"), entry->start, entry->len, entry->colorOrder);
}
- sappend('v',SET_F("CA"),briS);
-
- sappend('c',SET_F("BO"),turnOnAtBoot);
- sappend('v',SET_F("BP"),bootPreset);
-
- sappend('c',SET_F("GB"),gammaCorrectBri);
- sappend('c',SET_F("GC"),gammaCorrectCol);
- dtostrf(gammaCorrectVal,3,1,nS); sappends('s',SET_F("GV"),nS);
- sappend('c',SET_F("TF"),fadeTransition);
- sappend('c',SET_F("EB"),modeBlending);
- sappend('v',SET_F("TD"),transitionDelayDefault);
- sappend('c',SET_F("PF"),strip.paletteFade);
- sappend('v',SET_F("TP"),randomPaletteChangeTime);
- sappend('c',SET_F("TH"),useHarmonicRandomPalette);
- sappend('v',SET_F("BF"),briMultiplier);
- sappend('v',SET_F("TB"),nightlightTargetBri);
- sappend('v',SET_F("TL"),nightlightDelayMinsDefault);
- sappend('v',SET_F("TW"),nightlightMode);
- sappend('i',SET_F("PB"),strip.paletteBlend);
- sappend('v',SET_F("RL"),rlyPin);
- sappend('c',SET_F("RM"),rlyMde);
- sappend('c',SET_F("RO"),rlyOpenDrain);
+ printSetFormValue(dest,PSTR("CA"),briS);
+
+ printSetFormCheckbox(dest,PSTR("BO"),turnOnAtBoot);
+ printSetFormValue(dest,PSTR("BP"),bootPreset);
+
+ printSetFormCheckbox(dest,PSTR("GB"),gammaCorrectBri);
+ printSetFormCheckbox(dest,PSTR("GC"),gammaCorrectCol);
+ dtostrf(gammaCorrectVal,3,1,nS); printSetFormValue(dest,PSTR("GV"),nS);
+ printSetFormCheckbox(dest,PSTR("TF"),fadeTransition);
+ printSetFormCheckbox(dest,PSTR("EB"),modeBlending);
+ printSetFormValue(dest,PSTR("TD"),transitionDelayDefault);
+ printSetFormCheckbox(dest,PSTR("PF"),strip.paletteFade);
+ printSetFormValue(dest,PSTR("TP"),randomPaletteChangeTime);
+ printSetFormCheckbox(dest,PSTR("TH"),useHarmonicRandomPalette);
+ printSetFormValue(dest,PSTR("BF"),briMultiplier);
+ printSetFormValue(dest,PSTR("TB"),nightlightTargetBri);
+ printSetFormValue(dest,PSTR("TL"),nightlightDelayMinsDefault);
+ printSetFormValue(dest,PSTR("TW"),nightlightMode);
+ printSetFormIndex(dest,PSTR("PB"),strip.paletteBlend);
+ printSetFormValue(dest,PSTR("RL"),rlyPin);
+ printSetFormCheckbox(dest,PSTR("RM"),rlyMde);
+ printSetFormCheckbox(dest,PSTR("RO"),rlyOpenDrain);
for (int i = 0; i < WLED_MAX_BUTTONS; i++) {
- oappend(SET_F("addBtn("));
- oappend(itoa(i,nS,10)); oappend(",");
- oappend(itoa(btnPin[i],nS,10)); oappend(",");
- oappend(itoa(buttonType[i],nS,10));
- oappend(SET_F(");"));
+ dest.printf_P(PSTR("addBtn(%d,%d,%d);"), i, btnPin[i], buttonType[i]);
}
- sappend('c',SET_F("IP"),disablePullUp);
- sappend('v',SET_F("TT"),touchThreshold);
+ printSetFormCheckbox(dest,PSTR("IP"),disablePullUp);
+ printSetFormValue(dest,PSTR("TT"),touchThreshold);
#ifndef WLED_DISABLE_INFRARED
- sappend('v',SET_F("IR"),irPin);
- sappend('v',SET_F("IT"),irEnabled);
+ printSetFormValue(dest,PSTR("IR"),irPin);
+ printSetFormValue(dest,PSTR("IT"),irEnabled);
#endif
- sappend('c',SET_F("MSO"),!irApplyToAllSelected);
+ printSetFormCheckbox(dest,PSTR("MSO"),!irApplyToAllSelected);
}
if (subPage == SUBPAGE_UI)
{
- sappends('s',SET_F("DS"),serverDescription);
- sappend('c',SET_F("SU"),simplifiedUI);
+ printSetFormValue(dest,PSTR("DS"),serverDescription);
+ printSetFormCheckbox(dest,PSTR("SU"),simplifiedUI);
}
if (subPage == SUBPAGE_SYNC)
{
[[maybe_unused]] char nS[32];
- sappend('v',SET_F("UP"),udpPort);
- sappend('v',SET_F("U2"),udpPort2);
+ printSetFormValue(dest,PSTR("UP"),udpPort);
+ printSetFormValue(dest,PSTR("U2"),udpPort2);
#ifndef WLED_DISABLE_ESPNOW
- if (enableESPNow) sappend('c',SET_F("EN"),useESPNowSync);
- else oappend(SET_F("toggle('ESPNOW');")); // hide ESP-NOW setting
+ if (enableESPNow) printSetFormCheckbox(dest,PSTR("EN"),useESPNowSync);
+ else dest.print(F("toggle('ESPNOW');")); // hide ESP-NOW setting
#else
- oappend(SET_F("toggle('ESPNOW');")); // hide ESP-NOW setting
+ dest.print(F("toggle('ESPNOW');")); // hide ESP-NOW setting
#endif
- sappend('v',SET_F("GS"),syncGroups);
- sappend('v',SET_F("GR"),receiveGroups);
-
- sappend('c',SET_F("RB"),receiveNotificationBrightness);
- sappend('c',SET_F("RC"),receiveNotificationColor);
- sappend('c',SET_F("RX"),receiveNotificationEffects);
- sappend('c',SET_F("RP"),receiveNotificationPalette);
- sappend('c',SET_F("SO"),receiveSegmentOptions);
- sappend('c',SET_F("SG"),receiveSegmentBounds);
- sappend('c',SET_F("SS"),sendNotifications);
- sappend('c',SET_F("SD"),notifyDirect);
- sappend('c',SET_F("SB"),notifyButton);
- sappend('c',SET_F("SH"),notifyHue);
- sappend('v',SET_F("UR"),udpNumRetries);
-
- sappend('c',SET_F("NL"),nodeListEnabled);
- sappend('c',SET_F("NB"),nodeBroadcastEnabled);
-
- sappend('c',SET_F("RD"),receiveDirect);
- sappend('c',SET_F("MO"),useMainSegmentOnly);
- sappend('c',SET_F("RLM"),realtimeRespectLedMaps);
- sappend('v',SET_F("EP"),e131Port);
- sappend('c',SET_F("ES"),e131SkipOutOfSequence);
- sappend('c',SET_F("EM"),e131Multicast);
- sappend('v',SET_F("EU"),e131Universe);
- sappend('v',SET_F("DA"),DMXAddress);
- sappend('v',SET_F("XX"),DMXSegmentSpacing);
- sappend('v',SET_F("PY"),e131Priority);
- sappend('v',SET_F("DM"),DMXMode);
- sappend('v',SET_F("ET"),realtimeTimeoutMs);
- sappend('c',SET_F("FB"),arlsForceMaxBri);
- sappend('c',SET_F("RG"),arlsDisableGammaCorrection);
- sappend('v',SET_F("WO"),arlsOffset);
+ printSetFormValue(dest,PSTR("GS"),syncGroups);
+ printSetFormValue(dest,PSTR("GR"),receiveGroups);
+
+ printSetFormCheckbox(dest,PSTR("RB"),receiveNotificationBrightness);
+ printSetFormCheckbox(dest,PSTR("RC"),receiveNotificationColor);
+ printSetFormCheckbox(dest,PSTR("RX"),receiveNotificationEffects);
+ printSetFormCheckbox(dest,PSTR("RP"),receiveNotificationPalette);
+ printSetFormCheckbox(dest,PSTR("SO"),receiveSegmentOptions);
+ printSetFormCheckbox(dest,PSTR("SG"),receiveSegmentBounds);
+ printSetFormCheckbox(dest,PSTR("SS"),sendNotifications);
+ printSetFormCheckbox(dest,PSTR("SD"),notifyDirect);
+ printSetFormCheckbox(dest,PSTR("SB"),notifyButton);
+ printSetFormCheckbox(dest,PSTR("SH"),notifyHue);
+ printSetFormValue(dest,PSTR("UR"),udpNumRetries);
+
+ printSetFormCheckbox(dest,PSTR("NL"),nodeListEnabled);
+ printSetFormCheckbox(dest,PSTR("NB"),nodeBroadcastEnabled);
+
+ printSetFormCheckbox(dest,PSTR("RD"),receiveDirect);
+ printSetFormCheckbox(dest,PSTR("MO"),useMainSegmentOnly);
+ printSetFormCheckbox(dest,PSTR("RLM"),realtimeRespectLedMaps);
+ printSetFormValue(dest,PSTR("EP"),e131Port);
+ printSetFormCheckbox(dest,PSTR("ES"),e131SkipOutOfSequence);
+ printSetFormCheckbox(dest,PSTR("EM"),e131Multicast);
+ printSetFormValue(dest,PSTR("EU"),e131Universe);
+ printSetFormValue(dest,PSTR("DA"),DMXAddress);
+ printSetFormValue(dest,PSTR("XX"),DMXSegmentSpacing);
+ printSetFormValue(dest,PSTR("PY"),e131Priority);
+ printSetFormValue(dest,PSTR("DM"),DMXMode);
+ printSetFormValue(dest,PSTR("ET"),realtimeTimeoutMs);
+ printSetFormCheckbox(dest,PSTR("FB"),arlsForceMaxBri);
+ printSetFormCheckbox(dest,PSTR("RG"),arlsDisableGammaCorrection);
+ printSetFormValue(dest,PSTR("WO"),arlsOffset);
#ifndef WLED_DISABLE_ALEXA
- sappend('c',SET_F("AL"),alexaEnabled);
- sappends('s',SET_F("AI"),alexaInvocationName);
- sappend('c',SET_F("SA"),notifyAlexa);
- sappend('v',SET_F("AP"),alexaNumPresets);
+ printSetFormCheckbox(dest,PSTR("AL"),alexaEnabled);
+ printSetFormValue(dest,PSTR("AI"),alexaInvocationName);
+ printSetFormCheckbox(dest,PSTR("SA"),notifyAlexa);
+ printSetFormValue(dest,PSTR("AP"),alexaNumPresets);
#else
- oappend(SET_F("toggle('Alexa');")); // hide Alexa settings
+ dest.print(F("toggle('Alexa');")); // hide Alexa settings
#endif
#ifndef WLED_DISABLE_MQTT
- sappend('c',SET_F("MQ"),mqttEnabled);
- sappends('s',SET_F("MS"),mqttServer);
- sappend('v',SET_F("MQPORT"),mqttPort);
- sappends('s',SET_F("MQUSER"),mqttUser);
+ printSetFormCheckbox(dest,PSTR("MQ"),mqttEnabled);
+ printSetFormValue(dest,PSTR("MS"),mqttServer);
+ printSetFormValue(dest,PSTR("MQPORT"),mqttPort);
+ printSetFormValue(dest,PSTR("MQUSER"),mqttUser);
byte l = strlen(mqttPass);
char fpass[l+1]; //fill password field with ***
fpass[l] = 0;
memset(fpass,'*',l);
- sappends('s',SET_F("MQPASS"),fpass);
- sappends('s',SET_F("MQCID"),mqttClientID);
- sappends('s',"MD",mqttDeviceTopic);
- sappends('s',SET_F("MG"),mqttGroupTopic);
- sappend('c',SET_F("BM"),buttonPublishMqtt);
- sappend('c',SET_F("RT"),retainMqttMsg);
- oappend(SET_F("d.Sf.MD.maxlength=")); oappend(itoa(MQTT_MAX_TOPIC_LEN,nS,10)); oappend(SET_F(";"));
- oappend(SET_F("d.Sf.MG.maxlength=")); oappend(itoa(MQTT_MAX_TOPIC_LEN,nS,10)); oappend(SET_F(";"));
- oappend(SET_F("d.Sf.MS.maxlength=")); oappend(itoa(MQTT_MAX_SERVER_LEN,nS,10)); oappend(SET_F(";"));
+ printSetFormValue(dest,PSTR("MQPASS"),fpass);
+ printSetFormValue(dest,PSTR("MQCID"),mqttClientID);
+ printSetFormValue(dest,PSTR("MD"),mqttDeviceTopic);
+ printSetFormValue(dest,PSTR("MG"),mqttGroupTopic);
+ printSetFormCheckbox(dest,PSTR("BM"),buttonPublishMqtt);
+ printSetFormCheckbox(dest,PSTR("RT"),retainMqttMsg);
+ dest.printf_P(PSTR("d.Sf.MD.maxlength=%d;d.Sf.MG.maxlength=%d;d.Sf.MS.maxlength=%d;"),
+ MQTT_MAX_TOPIC_LEN, MQTT_MAX_TOPIC_LEN, MQTT_MAX_SERVER_LEN);
#else
- oappend(SET_F("toggle('MQTT');")); // hide MQTT settings
+ dest.print(F("toggle('MQTT');")); // hide MQTT settings
#endif
#ifndef WLED_DISABLE_HUESYNC
- sappend('v',SET_F("H0"),hueIP[0]);
- sappend('v',SET_F("H1"),hueIP[1]);
- sappend('v',SET_F("H2"),hueIP[2]);
- sappend('v',SET_F("H3"),hueIP[3]);
- sappend('v',SET_F("HL"),huePollLightId);
- sappend('v',SET_F("HI"),huePollIntervalMs);
- sappend('c',SET_F("HP"),huePollingEnabled);
- sappend('c',SET_F("HO"),hueApplyOnOff);
- sappend('c',SET_F("HB"),hueApplyBri);
- sappend('c',SET_F("HC"),hueApplyColor);
+ printSetFormValue(dest,PSTR("H0"),hueIP[0]);
+ printSetFormValue(dest,PSTR("H1"),hueIP[1]);
+ printSetFormValue(dest,PSTR("H2"),hueIP[2]);
+ printSetFormValue(dest,PSTR("H3"),hueIP[3]);
+ printSetFormValue(dest,PSTR("HL"),huePollLightId);
+ printSetFormValue(dest,PSTR("HI"),huePollIntervalMs);
+ printSetFormCheckbox(dest,PSTR("HP"),huePollingEnabled);
+ printSetFormCheckbox(dest,PSTR("HO"),hueApplyOnOff);
+ printSetFormCheckbox(dest,PSTR("HB"),hueApplyBri);
+ printSetFormCheckbox(dest,PSTR("HC"),hueApplyColor);
char hueErrorString[25];
switch (hueError)
{
@@ -566,61 +494,56 @@ void getSettingsJS(byte subPage, char* dest)
default: sprintf_P(hueErrorString,PSTR("Bridge Error %i"),hueError);
}
- sappends('m',SET_F("(\"sip\")[0]"),hueErrorString);
+ printSetClassElementHTML(dest,PSTR("sip"),0,hueErrorString);
#else
- oappend(SET_F("toggle('Hue');")); // hide Hue Sync settings
+ dest.print(F("toggle('Hue');")); // hide Hue Sync settings
#endif
- sappend('v',SET_F("BD"),serialBaud);
+ printSetFormValue(dest,PSTR("BD"),serialBaud);
#ifndef WLED_ENABLE_ADALIGHT
- oappend(SET_F("toggle('Serial);"));
+ dest.print(F("toggle('Serial);"));
#endif
}
if (subPage == SUBPAGE_TIME)
{
- sappend('c',SET_F("NT"),ntpEnabled);
- sappends('s',SET_F("NS"),ntpServerName);
- sappend('c',SET_F("CF"),!useAMPM);
- sappend('i',SET_F("TZ"),currentTimezone);
- sappend('v',SET_F("UO"),utcOffsetSecs);
+ printSetFormCheckbox(dest,PSTR("NT"),ntpEnabled);
+ printSetFormValue(dest,PSTR("NS"),ntpServerName);
+ printSetFormCheckbox(dest,PSTR("CF"),!useAMPM);
+ printSetFormIndex(dest,PSTR("TZ"),currentTimezone);
+ printSetFormValue(dest,PSTR("UO"),utcOffsetSecs);
char tm[32];
dtostrf(longitude,4,2,tm);
- sappends('s',SET_F("LN"),tm);
+ printSetFormValue(dest,PSTR("LN"),tm);
dtostrf(latitude,4,2,tm);
- sappends('s',SET_F("LT"),tm);
+ printSetFormValue(dest,PSTR("LT"),tm);
getTimeString(tm);
- sappends('m',SET_F("(\"times\")[0]"),tm);
+ printSetClassElementHTML(dest,PSTR("times"),0,tm);
if ((int)(longitude*10.0f) || (int)(latitude*10.0f)) {
sprintf_P(tm, PSTR("Sunrise: %02d:%02d Sunset: %02d:%02d"), hour(sunrise), minute(sunrise), hour(sunset), minute(sunset));
- sappends('m',SET_F("(\"times\")[1]"),tm);
+ printSetClassElementHTML(dest,PSTR("times"),1,tm);
}
- sappend('c',SET_F("OL"),overlayCurrent);
- sappend('v',SET_F("O1"),overlayMin);
- sappend('v',SET_F("O2"),overlayMax);
- sappend('v',SET_F("OM"),analogClock12pixel);
- sappend('c',SET_F("OS"),analogClockSecondsTrail);
- sappend('c',SET_F("O5"),analogClock5MinuteMarks);
- sappend('c',SET_F("OB"),analogClockSolidBlack);
-
- sappend('c',SET_F("CE"),countdownMode);
- sappend('v',SET_F("CY"),countdownYear);
- sappend('v',SET_F("CI"),countdownMonth);
- sappend('v',SET_F("CD"),countdownDay);
- sappend('v',SET_F("CH"),countdownHour);
- sappend('v',SET_F("CM"),countdownMin);
- sappend('v',SET_F("CS"),countdownSec);
-
- sappend('v',SET_F("A0"),macroAlexaOn);
- sappend('v',SET_F("A1"),macroAlexaOff);
- sappend('v',SET_F("MC"),macroCountdown);
- sappend('v',SET_F("MN"),macroNl);
+ printSetFormCheckbox(dest,PSTR("OL"),overlayCurrent);
+ printSetFormValue(dest,PSTR("O1"),overlayMin);
+ printSetFormValue(dest,PSTR("O2"),overlayMax);
+ printSetFormValue(dest,PSTR("OM"),analogClock12pixel);
+ printSetFormCheckbox(dest,PSTR("OS"),analogClockSecondsTrail);
+ printSetFormCheckbox(dest,PSTR("O5"),analogClock5MinuteMarks);
+ printSetFormCheckbox(dest,PSTR("OB"),analogClockSolidBlack);
+
+ printSetFormCheckbox(dest,PSTR("CE"),countdownMode);
+ printSetFormValue(dest,PSTR("CY"),countdownYear);
+ printSetFormValue(dest,PSTR("CI"),countdownMonth);
+ printSetFormValue(dest,PSTR("CD"),countdownDay);
+ printSetFormValue(dest,PSTR("CH"),countdownHour);
+ printSetFormValue(dest,PSTR("CM"),countdownMin);
+ printSetFormValue(dest,PSTR("CS"),countdownSec);
+
+ printSetFormValue(dest,PSTR("A0"),macroAlexaOn);
+ printSetFormValue(dest,PSTR("A1"),macroAlexaOff);
+ printSetFormValue(dest,PSTR("MC"),macroCountdown);
+ printSetFormValue(dest,PSTR("MN"),macroNl);
for (unsigned i=0; i> 4) & 0x0F);
- k[0] = 'P'; sappend('v',k,timerMonth[i] & 0x0F);
- k[0] = 'D'; sappend('v',k,timerDay[i]);
- k[0] = 'E'; sappend('v',k,timerDayEnd[i]);
+ k[0] = 'M'; printSetFormValue(dest,k,(timerMonth[i] >> 4) & 0x0F);
+ k[0] = 'P'; printSetFormValue(dest,k,timerMonth[i] & 0x0F);
+ k[0] = 'D'; printSetFormValue(dest,k,timerDay[i]);
+ k[0] = 'E'; printSetFormValue(dest,k,timerDayEnd[i]);
}
}
}
@@ -647,121 +570,115 @@ void getSettingsJS(byte subPage, char* dest)
char fpass[l+1]; //fill PIN field with 0000
fpass[l] = 0;
memset(fpass,'0',l);
- sappends('s',SET_F("PIN"),fpass);
- sappend('c',SET_F("NO"),otaLock);
- sappend('c',SET_F("OW"),wifiLock);
- sappend('c',SET_F("AO"),aOtaEnabled);
- sappends('m',SET_F("(\"sip\")[0]"),(char*)F("WLED "));
- olen -= 2; //delete ";
- oappend(versionString);
- oappend(SET_F(" (build "));
- oappendi(VERSION);
- oappend(SET_F(")\";"));
- oappend(SET_F("sd=\""));
- oappend(serverDescription);
- oappend(SET_F("\";"));
+ printSetFormValue(dest,PSTR("PIN"),fpass);
+ printSetFormCheckbox(dest,PSTR("NO"),otaLock);
+ printSetFormCheckbox(dest,PSTR("OW"),wifiLock);
+ printSetFormCheckbox(dest,PSTR("AO"),aOtaEnabled);
+ char msg_buf[256];
+ snprintf_P(msg_buf,sizeof(msg_buf), PSTR("WLED %s (build %d)"), versionString, VERSION);
+ printSetClassElementHTML(dest,PSTR("sip"),0,msg_buf);
+ dest.printf_P(PSTR("sd=\"%s\";"), serverDescription);
}
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
if (subPage == SUBPAGE_DMX)
{
- sappend('v',SET_F("PU"),e131ProxyUniverse);
-
- sappend('v',SET_F("CN"),DMXChannels);
- sappend('v',SET_F("CG"),DMXGap);
- sappend('v',SET_F("CS"),DMXStart);
- sappend('v',SET_F("SL"),DMXStartLED);
-
- sappend('i',SET_F("CH1"),DMXFixtureMap[0]);
- sappend('i',SET_F("CH2"),DMXFixtureMap[1]);
- sappend('i',SET_F("CH3"),DMXFixtureMap[2]);
- sappend('i',SET_F("CH4"),DMXFixtureMap[3]);
- sappend('i',SET_F("CH5"),DMXFixtureMap[4]);
- sappend('i',SET_F("CH6"),DMXFixtureMap[5]);
- sappend('i',SET_F("CH7"),DMXFixtureMap[6]);
- sappend('i',SET_F("CH8"),DMXFixtureMap[7]);
- sappend('i',SET_F("CH9"),DMXFixtureMap[8]);
- sappend('i',SET_F("CH10"),DMXFixtureMap[9]);
- sappend('i',SET_F("CH11"),DMXFixtureMap[10]);
- sappend('i',SET_F("CH12"),DMXFixtureMap[11]);
- sappend('i',SET_F("CH13"),DMXFixtureMap[12]);
- sappend('i',SET_F("CH14"),DMXFixtureMap[13]);
- sappend('i',SET_F("CH15"),DMXFixtureMap[14]);
+ printSetFormValue(dest,PSTR("PU"),e131ProxyUniverse);
+
+ printSetFormValue(dest,PSTR("CN"),DMXChannels);
+ printSetFormValue(dest,PSTR("CG"),DMXGap);
+ printSetFormValue(dest,PSTR("CS"),DMXStart);
+ printSetFormValue(dest,PSTR("SL"),DMXStartLED);
+
+ printSetFormIndex(dest,PSTR("CH1"),DMXFixtureMap[0]);
+ printSetFormIndex(dest,PSTR("CH2"),DMXFixtureMap[1]);
+ printSetFormIndex(dest,PSTR("CH3"),DMXFixtureMap[2]);
+ printSetFormIndex(dest,PSTR("CH4"),DMXFixtureMap[3]);
+ printSetFormIndex(dest,PSTR("CH5"),DMXFixtureMap[4]);
+ printSetFormIndex(dest,PSTR("CH6"),DMXFixtureMap[5]);
+ printSetFormIndex(dest,PSTR("CH7"),DMXFixtureMap[6]);
+ printSetFormIndex(dest,PSTR("CH8"),DMXFixtureMap[7]);
+ printSetFormIndex(dest,PSTR("CH9"),DMXFixtureMap[8]);
+ printSetFormIndex(dest,PSTR("CH10"),DMXFixtureMap[9]);
+ printSetFormIndex(dest,PSTR("CH11"),DMXFixtureMap[10]);
+ printSetFormIndex(dest,PSTR("CH12"),DMXFixtureMap[11]);
+ printSetFormIndex(dest,PSTR("CH13"),DMXFixtureMap[12]);
+ printSetFormIndex(dest,PSTR("CH14"),DMXFixtureMap[13]);
+ printSetFormIndex(dest,PSTR("CH15"),DMXFixtureMap[14]);
}
#endif
if (subPage == SUBPAGE_UM) //usermods
{
- appendGPIOinfo();
- oappend(SET_F("numM="));
- oappendi(usermods.getModCount());
- oappend(";");
- sappend('v',SET_F("SDA"),i2c_sda);
- sappend('v',SET_F("SCL"),i2c_scl);
- sappend('v',SET_F("MOSI"),spi_mosi);
- sappend('v',SET_F("MISO"),spi_miso);
- sappend('v',SET_F("SCLK"),spi_sclk);
- oappend(SET_F("addInfo('SDA','")); oappendi(HW_PIN_SDA); oappend(SET_F("');"));
- oappend(SET_F("addInfo('SCL','")); oappendi(HW_PIN_SCL); oappend(SET_F("');"));
- oappend(SET_F("addInfo('MOSI','")); oappendi(HW_PIN_DATASPI); oappend(SET_F("');"));
- oappend(SET_F("addInfo('MISO','")); oappendi(HW_PIN_MISOSPI); oappend(SET_F("');"));
- oappend(SET_F("addInfo('SCLK','")); oappendi(HW_PIN_CLOCKSPI); oappend(SET_F("');"));
- usermods.appendConfigData();
+ appendGPIOinfo(dest);
+ dest.printf_P(PSTR("numM=%d;"), usermods.getModCount());
+ printSetFormValue(dest,PSTR("SDA"),i2c_sda);
+ printSetFormValue(dest,PSTR("SCL"),i2c_scl);
+ printSetFormValue(dest,PSTR("MOSI"),spi_mosi);
+ printSetFormValue(dest,PSTR("MISO"),spi_miso);
+ printSetFormValue(dest,PSTR("SCLK"),spi_sclk);
+ dest.printf_P(PSTR("addInfo('SDA','%d');"
+ "addInfo('SCL','%d');"
+ "addInfo('MOSI','%d');"
+ "addInfo('MISO','%d');"
+ "addInfo('SCLK','%d');"),
+ HW_PIN_SDA, HW_PIN_SCL, HW_PIN_DATASPI, HW_PIN_MISOSPI, HW_PIN_CLOCKSPI
+ );
+ usermods.appendConfigData(dest);
}
if (subPage == SUBPAGE_UPDATE) // update
{
- sappends('m',SET_F("(\"sip\")[0]"),(char*)F("WLED "));
- olen -= 2; //delete ";
- oappend(versionString);
- oappend(SET_F("
"));
- oappend(releaseString);
- oappend(SET_F("
("));
- #if defined(ARDUINO_ARCH_ESP32)
- oappend(ESP.getChipModel());
- #else
- oappend("esp8266");
- #endif
- oappend(SET_F(" build "));
- oappendi(VERSION);
- oappend(SET_F(")\";"));
+ char msg[256];
+ snprintf_P(msg, sizeof(msg), PSTR("WLED %s
%s
(%s build %d)"),
+ versionString,
+ releaseString,
+#if defined(ARDUINO_ARCH_ESP32)
+ ESP.getChipModel(),
+#else
+ F("esp8266"),
+ #endif
+ VERSION
+ );
+
+ printSetClassElementHTML(dest,PSTR("sip"),0,msg);
}
if (subPage == SUBPAGE_2D) // 2D matrices
{
- sappend('v',SET_F("SOMP"),strip.isMatrix);
+ printSetFormValue(dest,PSTR("SOMP"),strip.isMatrix);
#ifndef WLED_DISABLE_2D
- oappend(SET_F("maxPanels=")); oappendi(WLED_MAX_PANELS); oappend(SET_F(";"));
- oappend(SET_F("resetPanels();"));
+ dest.printf_P(PSTR("maxPanels=%d;"),WLED_MAX_PANELS);
+ dest.print(F("resetPanels();"));
if (strip.isMatrix) {
if(strip.panels>0){
- sappend('v',SET_F("PW"),strip.panel[0].width); //Set generator Width and Height to first panel size for convenience
- sappend('v',SET_F("PH"),strip.panel[0].height);
+ printSetFormValue(dest,PSTR("PW"),strip.panel[0].width); //Set generator Width and Height to first panel size for convenience
+ printSetFormValue(dest,PSTR("PH"),strip.panel[0].height);
}
- sappend('v',SET_F("MPC"),strip.panels);
+ printSetFormValue(dest,PSTR("MPC"),strip.panels);
// panels
for (unsigned i=0; i