Files
WLED_MM_Infinity/wled00/xml.cpp
Frank fd079d6105 add HUB75 and DMX pins to usermods pin dropdown
these pins were wrongly shown as "available", because the are not stored in the cfg.json part related to LEDs settings.
2026-02-04 22:19:42 +01:00

987 lines
36 KiB
C++

#include "wled.h"
#include "wled_ethernet.h"
/*
* Sending XML status files to client
*/
//build XML response to HTTP /win API request
void XML_response(AsyncWebServerRequest *request, char* dest)
{
char sbuf[(dest == nullptr)?1024:1]; //allocate local buffer if none passed
obuf = (dest == nullptr)? sbuf:dest;
olen = 0;
oappend(SET_F("<?xml version=\"1.0\" ?><vs><ac>"));
oappendi((nightlightActive && nightlightMode > NL_MODE_SET) ? briT : bri);
oappend(SET_F("</ac>"));
for (int i = 0; i < 3; i++)
{
oappend("<cl>");
oappendi(col[i]);
oappend("</cl>");
}
for (int i = 0; i < 3; i++)
{
oappend("<cs>");
oappendi(colSec[i]);
oappend("</cs>");
}
oappend(SET_F("<ns>"));
oappendi(notifyDirect);
oappend(SET_F("</ns><nr>"));
oappendi(receiveNotifications);
oappend(SET_F("</nr><nl>"));
oappendi(nightlightActive);
oappend(SET_F("</nl><nf>"));
oappendi(nightlightMode > NL_MODE_SET);
oappend(SET_F("</nf><nd>"));
oappendi(nightlightDelayMins);
oappend(SET_F("</nd><nt>"));
oappendi(nightlightTargetBri);
oappend(SET_F("</nt><fx>"));
oappendi(effectCurrent);
oappend(SET_F("</fx><sx>"));
oappendi(effectSpeed);
oappend(SET_F("</sx><ix>"));
oappendi(effectIntensity);
oappend(SET_F("</ix><fp>"));
oappendi(effectPalette);
oappend(SET_F("</fp><wv>"));
if (strip.hasWhiteChannel()) {
oappendi(col[3]);
} else {
oappend("-1");
}
oappend(SET_F("</wv><ws>"));
oappendi(colSec[3]);
oappend(SET_F("</ws><ps>"));
oappendi(currentPreset);
oappend(SET_F("</ps><cy>"));
oappendi(currentPlaylist >= 0);
oappend(SET_F("</cy><ds>"));
oappend(serverDescription);
if (realtimeMode)
{
oappend(SET_F(" (live)"));
}
oappend(SET_F("</ds><ss>"));
oappendi(strip.getFirstSelectedSegId());
oappend(SET_F("</ss></vs>"));
if (request != nullptr) request->send(200, "text/xml", obuf);
}
//Deprecated, use of /json/state and presets recommended instead
void URL_response(AsyncWebServerRequest *request)
{
char sbuf[256];
char s2buf[100];
obuf = s2buf;
olen = 0;
char s[16];
oappend(SET_F("http://"));
IPAddress localIP = Network.localIP();
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
oappend(s);
oappend(SET_F("/win&A="));
oappendi(bri);
oappend(SET_F("&CL=h"));
for (int i = 0; i < 3; i++)
{
sprintf(s,"%02X", col[i]);
oappend(s);
}
oappend(SET_F("&C2=h"));
for (int i = 0; i < 3; i++)
{
sprintf(s,"%02X", colSec[i]);
oappend(s);
}
oappend(SET_F("&FX="));
oappendi(effectCurrent);
oappend(SET_F("&SX="));
oappendi(effectSpeed);
oappend(SET_F("&IX="));
oappendi(effectIntensity);
oappend(SET_F("&FP="));
oappendi(effectPalette);
obuf = sbuf;
olen = 0;
oappend(SET_F("<html><body><a href=\""));
oappend(s2buf);
oappend(SET_F("\" target=\"_blank\">"));
oappend(s2buf);
oappend(SET_F("</a></body></html>"));
if (request != nullptr) request->send(200, "text/html", obuf);
}
void extractPin(JsonObject &obj, const char *key) {
if (obj[key].is<JsonArray>()) {
JsonArray pins = obj[key].as<JsonArray>();
for (JsonVariant pv : pins) {
if (pv.as<int>() > -1) { oappend(","); oappendi(pv.as<int>()); }
}
} else {
if (obj[key].as<int>() > -1) { oappend(","); oappendi(obj[key].as<int>()); }
}
}
// oappend used pins by scanning JsonObject (1 level deep)
void fillUMPins(JsonObject &mods)
{
for (JsonPair kv : mods) {
// kv.key() is usermod name or subobject key
// kv.value() is object itself
JsonObject obj = kv.value();
if (!obj.isNull()) {
// element is an JsonObject
if (!obj["pin"].isNull()) {
extractPin(obj, "pin");
} else {
// scan keys (just one level deep as is possible with usermods)
for (JsonPair so : obj) {
const char *key = so.key().c_str();
if (strstr(key, "pin")) {
// 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);
continue;
}
}
if (!obj[so.key()].is<JsonObject>()) continue;
JsonObject subObj = obj[so.key()];
if (!subObj["pin"].isNull()) {
// get pins from subobject
extractPin(subObj, "pin");
}
}
}
}
}
}
void appendGPIOinfo() {
char nS[8];
oappend(SET_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));
}
if (spi_mosi > -1 && spi_sclk > -1) {
oappend(","); oappend(itoa(spi_mosi,nS,10));
oappend(","); oappend(itoa(spi_sclk,nS,10));
}
// 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 = doc.createNestedObject(F("um"));
usermods.addToConfig(mods);
if (!mods.isNull()) fillUMPins(mods);
releaseJSONBufferLock();
}
oappend(SET_F("];"));
//WLEDMM: use isPinOK instead of hardcoded pins
char rsvd[140] = "d.rsvd=[";
size_t rsLen = strlen(rsvd);
char ro_gpio[140] = "d.ro_gpio=[";
size_t roLen = strlen(ro_gpio);
char pinString[10];
for(int pinNr = 0; pinNr < WLED_NUM_PINS; pinNr++) { // 49 = highest PIN on ESP32-S3
#if defined(ARDUINO_ARCH_ESP32) && !defined(BOARD_HAS_PSRAM)
if ((!pinManager.isPinOk(pinNr, false)) || (pinManager.getPinOwner(pinNr) == PinOwner::SPI_RAM)) { // WLEDMM add SPIRAM pins as "reserved" (pico boards)
#else
if (!pinManager.isPinOk(pinNr, false)) {
#endif
sprintf(pinString, "%s%d", strlen(rsvd)==rsLen?"":",", pinNr);
strcat(rsvd, pinString);
}
else {
//if ((!pinManager.isPinAllocated(pinNr)) && (pinManager.getPinSpecialText(pinNr).length() == 0)) continue; // un-comment to hide no-name,unused GPIO pins
bool is_inOut = pinManager.isPinOk(pinNr, true);
if (!is_inOut) {
sprintf(pinString, "%s%d", strlen(ro_gpio)==roLen?"":",", pinNr);
strcat(ro_gpio, pinString);
}
}
}
// add reserved and usermod pins as d.um_p array
oappend(rsvd);
#ifdef WLED_ENABLE_DMX
oappend(SET_F(",2")); // DMX hardcoded pin
#endif
#ifdef WLED_DEBUG
#if defined(WLED_DEBUG_HOST)
if (!netDebugEnabled) oappend(SET_F(",")); oappend(itoa(hardwareTX,nS,10));// debug output (TX) pin
#else
oappend(SET_F(",")); oappend(itoa(hardwareTX,nS,10));// debug output (TX) pin
#endif
#endif
//Note: Using pin 3 (RX) disables Adalight / Serial JSON
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C3)
if (psramFound()) oappend(SET_F(",16,17")); // GPIO16 & GPIO17 reserved for SPI RAM on ESP32 (not on S2, S3 or C3)
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
if (psramFound()) oappend(SET_F(",33,34,35,36,37")); // in use for "octal" PSRAM or "octal" FLASH -seems that octal PSRAM is very common on S3.
#endif
#endif
#ifdef WLED_USE_ETHERNET
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
for (uint8_t p=0; p<WLED_ETH_RSVD_PINS_COUNT; p++) { oappend(","); oappend(itoa(esp32_nonconfigurable_ethernet_pins[p].pin,nS,10)); }
if (ethernetBoards[ethernetType].eth_power>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_power,nS,10)); }
if (ethernetBoards[ethernetType].eth_mdc>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdc,nS,10)); }
if (ethernetBoards[ethernetType].eth_mdio>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdio,nS,10)); }
switch (ethernetBoards[ethernetType].eth_clk_mode) {
case ETH_CLOCK_GPIO0_IN:
case ETH_CLOCK_GPIO0_OUT:
oappend(SET_F(",0"));
break;
case ETH_CLOCK_GPIO16_OUT:
oappend(SET_F(",16"));
break;
case ETH_CLOCK_GPIO17_OUT:
oappend(SET_F(",17"));
break;
}
}
#endif
oappend(SET_F("];"));
// add info for read-only GPIO
//WLEDMM: use isPinOK instead of hardcoded pins
oappend(ro_gpio);
oappend(SET_F("];"));
// add info about max. # of pins
oappend(SET_F("d.max_gpio="));
#if defined(ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S3)
oappendi(NUM_DIGITAL_PINS - 1);
#else //8266 (max=17), or esp32-S3 (max=48)
oappendi(NUM_DIGITAL_PINS); //WLEDMM include pin 17 for Analog
#endif
oappend(SET_F(";"));
char dt_pins[64] = { '\0' }; // fix warning: output 45 bytes into a destination of size 30
#if defined(ESP8266) && !defined(ARDUINO_ESP8266_ESP01)
snprintf(dt_pins, 64, "d.dt_pins=[%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d];", D0, D1, D2, D3, D4, D5, D6, D7, D8, hardwareRX, hardwareTX);
#else
snprintf(dt_pins, 64, "d.dt_pins=[%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d];", PM_NO_PIN, PM_NO_PIN, PM_NO_PIN, PM_NO_PIN, PM_NO_PIN, PM_NO_PIN, PM_NO_PIN, PM_NO_PIN, PM_NO_PIN, hardwareRX, hardwareTX);
#endif
oappend(dt_pins);
char a_pins[64] = { '\0' }; // fix warning: output 45 bytes into a destination of size 30
snprintf(a_pins, 64, "d.a_pins=[%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d];", pinManager.getADCPin(PM_ADC1, 0), pinManager.getADCPin(PM_ADC1, 1), pinManager.getADCPin(PM_ADC1, 2), pinManager.getADCPin(PM_ADC1, 3), pinManager.getADCPin(PM_ADC1, 4), pinManager.getADCPin(PM_ADC1, 5), pinManager.getADCPin(PM_ADC1, 6), pinManager.getADCPin(PM_ADC1, 7), pinManager.getADCPin(PM_ADC1, 8), pinManager.getADCPin(PM_ADC1, 9), pinManager.getADCPin(PM_ADC1, 10));
oappend(a_pins);
// WLEDMM add HUB75 pins, as they are not stored directly in cfg.json
strcpy(ro_gpio, "d.h_pins=["); // WLEDMM we re-use this array, instead of creating an addition one; 140 bytes is more than enough for 14 pins.
bool isFirstHub = true;
for(int pinNr = 0; pinNr < WLED_NUM_PINS; pinNr++) {
if ((pinManager.isPinOk(pinNr)) && (pinManager.getPinOwner(pinNr) == PinOwner::HUB75)) {
sprintf(pinString, "%s%d", isFirstHub?"":",", pinNr);
strcat(ro_gpio, pinString); isFirstHub = false;
}
}
oappend(ro_gpio);
oappend(SET_F("];"));
// WLEDMM same procedure for DMX pins
strcpy(ro_gpio, "d.x_pins=["); // WLEDMM we re-use this array, instead of creating an addition one; 140 bytes is more than enough for max 4 pins.
isFirstHub = true;
for(int pinNr = 0; pinNr < WLED_NUM_PINS; pinNr++) {
if ((pinManager.isPinOk(pinNr)) && (pinManager.getPinOwner(pinNr) == PinOwner::DMX || pinManager.getPinOwner(pinNr) == PinOwner::DMX_INPUT)) {
sprintf(pinString, "%s%d", isFirstHub?"":",", pinNr);
strcat(ro_gpio, pinString); isFirstHub = false;
}
}
oappend(ro_gpio);
oappend(SET_F("];"));
}
//get values for settings form in javascript
void getSettingsJS(AsyncWebServerRequest* request, byte subPage, char* dest) //WLEDMM add request
{
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec
DEBUG_PRINT(F("settings resp"));
DEBUG_PRINTLN(subPage);
obuf = dest;
olen = 0;
if (subPage <0 || subPage >10) return;
if (subPage == 0)
{
#ifndef WLED_DISABLE_2D // include only if 2D is compiled in
oappend(PSTR("gId('2dbtn').style.display='';"));
#endif
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
oappend(PSTR("gId('dmxbtn').style.display='';"));
#endif
#ifdef WLED_ENABLE_PIXART // include only if PixelArt tool is enabled
oappend(PSTR("gId('pixbtn').style.display='';"));
#endif
#if defined(WLED_ENABLE_PXMAGIC) && !defined(WLED_ENABLE_PIXART) // include only if PixelMagic tool is enabled - only when PixelArt is not enabled
oappend(PSTR("gId('pxmbtn').style.display='';"));
#endif
#if defined(WLED_ENABLE_PIXELFORGE) && !defined(WLED_DISABLE_PIXELFORGE) // include only if PixelForge is enabled
oappend(PSTR("gId('forgebtn').style.display='';"));
#endif
}
if (subPage == 1)
{
sappends('s',SET_F("CS"),clientSSID);
byte l = strlen(clientPass);
char fpass[l+1]; //fill password field with ***
fpass[l] = 0;
memset(fpass,'*',l);
sappends('s',SET_F("CP"),fpass);
char k[3]; k[2] = 0; //IP addresses
for (int i = 0; i<4; i++)
{
k[1] = 48+i; //ascii 0,1,2,3
k[0] = 'I'; sappend('v',k,staticIP[i]);
k[0] = 'G'; sappend('v',k,staticGateway[i]);
k[0] = 'S'; sappend('v',k,staticSubnet[i]);
}
sappends('s',SET_F("CM"),cmDNS);
sappend('i',SET_F("AB"),apBehavior);
sappends('s',SET_F("AS"),apSSID);
sappend('c',SET_F("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);
sappend('v',SET_F("AC"),apChannel);
sappend('c',SET_F("FG"),force802_3g);
sappend('c',SET_F("WS"),noWifiSleep);
#ifndef WLED_DISABLE_ESPNOW
sappend('c',SET_F("RE"),enable_espnow_remote);
sappends('s',SET_F("RMAC"),linked_remote);
#else
//hide remote settings if not compiled
oappend(SET_F("document.getElementById('remd').style.display='none';"));
#endif
#ifdef WLED_USE_ETHERNET
sappend('v',SET_F("ETH"),ethernetType);
#else
//hide ethernet setting if not compiled in
oappend(SET_F("document.getElementById('ethd').style.display='none';"));
#endif
if (Network.isConnected()) //is connected
{
char s[32];
IPAddress localIP = Network.localIP();
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
#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);
} else
{
sappends('m',SET_F("(\"sip\")[0]"),(char*)F("Not connected"));
}
if (WiFi.softAPIP()[0] != 0) //is active
{
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);
} else
{
sappends('m',SET_F("(\"sip\")[1]"),(char*)F("Not active"));
}
#ifndef WLED_DISABLE_ESPNOW
if (last_signal_src[0] != 0) //Have seen an ESP-NOW Remote
{
sappends('m',SET_F("(\"rlid\")[0]"),last_signal_src);
} else if (!enable_espnow_remote)
{
sappends('m',SET_F("(\"rlid\")[0]"),(char*)F("(Enable remote to listen)"));
} else
{
sappends('m',SET_F("(\"rlid\")[0]"),(char*)F("None"));
}
#endif
}
if (subPage == 2)
{
char nS[32];
appendGPIOinfo();
// 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_LED_MEMORY,nS,10)); oappend(",");
oappend(itoa(MAX_LEDS,nS,10));
oappend(SET_F(");"));
sappend('c',SET_F("MS"),autoSegments);
sappend('c',SET_F("CCT"),correctWB);
sappend('c',SET_F("CR"),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"),strip.useLedsArray);
for (uint8_t s=0; s < busses.getNumBusses(); s++) {
Bus* bus = busses.getBus(s);
if (bus == nullptr) continue;
// "48+s" means the ASCII character "0", so 48+1 = ASCII for "1", etc - and "[3]=0" means null-terminate the string.
char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin
char lc[4] = "LC"; lc[2] = 48+s; lc[3] = 0; //strip length
char co[4] = "CO"; co[2] = 48+s; co[3] = 0; //strip color order
char lt[4] = "LT"; lt[2] = 48+s; lt[3] = 0; //strip type
char ls[4] = "LS"; ls[2] = 48+s; ls[3] = 0; //strip start LED
char cv[4] = "CV"; cv[2] = 48+s; cv[3] = 0; //strip reverse
char sl[4] = "SL"; sl[2] = 48+s; sl[3] = 0; //skip 1st LED
char rf[4] = "RF"; rf[2] = 48+s; rf[3] = 0; //off refresh
char aw[4] = "AW"; aw[2] = 48+s; aw[3] = 0; //auto white mode
char wo[4] = "WO"; wo[2] = 48+s; wo[3] = 0; //swap channels
char sp[4] = "SP"; sp[2] = 48+s; sp[3] = 0; //bus clock speed
char ao[4] = "AO"; ao[2] = 48+s; ao[3] = 0; //Art-Net outputs
char al[4] = "AL"; al[2] = 48+s; al[3] = 0; //Art-Net LEDs per output
char af[4] = "AF"; af[2] = 48+s; af[3] = 0; //Art-Net FPS limit
oappend(SET_F("addLEDs(1);"));
uint8_t pins[5];
uint8_t nPins = bus->getPins(pins);
for (uint8_t i = 0; i < nPins; i++) {
lp[1] = 48+i;
if (pinManager.isPinOk(pins[i]) || bus->getType()>=TYPE_NET_DDP_RGB) sappend('v',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->reversed);
sappend('v',sl,bus->skippedLeds());
sappend('c',rf,bus->isOffRefreshRequired());
sappend('v',aw,bus->getAutoWhiteMode());
sappend('v',wo,bus->getColorOrder() >> 4);
sappend('v',ao,bus->get_artnet_outputs());
sappend('v',al,bus->get_artnet_leds_per_output());
sappend('v',af,bus->get_artnet_fps_limit());
uint16_t speed = bus->getFrequency();
if (bus->getType() > TYPE_ONOFF && bus->getType() < 48) {
switch (speed) {
case WLED_PWM_FREQ/3 : speed = 0; break;
case WLED_PWM_FREQ/2 : speed = 1; break;
default:
case WLED_PWM_FREQ : speed = 2; break;
case WLED_PWM_FREQ*2 : speed = 3; break;
case WLED_PWM_FREQ*3 : speed = 4; break;
}
} else {
switch (speed) {
case 1000 : speed = 0; break;
case 2000 : speed = 1; break;
default:
case 5000 : speed = 2; break;
case 10000 : speed = 3; break;
case 20000 : speed = 4; break;
case 40000 : speed = 5; break; // WLEDMM max speed 40Mhz - requires carefull wiring
case 60000 : speed = 6; break; // WLEDMM overspeed 60Mhz - may or may not work
}
}
sappend('v',sp,speed);
oappend(SET_F("setPixelLimit("));
oappendi(s); oappend(SET_F(","));
oappendi(bus->getMaxPixels()); oappend(SET_F(");"));
}
oappend(SET_F("d.e131Universe="));
oappendi(e131Universe); // Art-Net start universe
oappend(SET_F(";"));
sappend('v',SET_F("MA"),strip.ablMilliampsMax);
sappend('v',SET_F("LA"),strip.milliampsPerLed);
if (strip.currentMilliamps)
{
sappends('m',SET_F("(\"pow\")[0]"),(char*)"");
olen -= 2; //delete ";
oappendi(strip.currentMilliamps);
oappend(SET_F("mA\";"));
}
oappend(SET_F("resetCOM("));
oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10));
oappend(SET_F(");"));
const ColorOrderMap& com = busses.getColorOrderMap();
for (uint8_t 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(");");
}
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);
sappend('c',SET_F("GCP"),gammaCorrectPreview); // WLEDMM
dtostrf(gammaCorrectVal,3,1,nS); sappends('s',SET_F("GV"),nS);
sappend('c',SET_F("TF"),fadeTransition);
sappend('v',SET_F("TD"),transitionDelayDefault);
sappend('c',SET_F("PF"),strip.paletteFade);
sappend('v',SET_F("TP"),randomPaletteChangeTime);
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);
for (uint8_t 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(");"));
}
sappend('c',SET_F("IP"),disablePullUp);
sappend('v',SET_F("TT"),touchThreshold);
sappend('v',SET_F("IR"),irPin);
sappend('v',SET_F("IT"),irEnabled);
sappend('c',SET_F("MSO"),!irApplyToAllSelected);
#if !defined(WLED_DISABLE_INFRARED)
oappend(SET_F("hideNoIR();")); // WLEDMM hide "not compiled in" message
#endif
#ifndef WLED_ENABLE_HUB75MATRIX
oappend(SET_F("hideHub75();")); // WLEDMM hide HUB75 LED types
#endif
}
if (subPage == 3)
{
sappends('s',SET_F("DS"),serverDescription);
sappend('c',SET_F("ST"),syncToggleReceive);
#ifdef WLED_ENABLE_SIMPLE_UI
sappend('c',SET_F("SU"),simplifiedUI);
#else
oappend(SET_F("toggle('Simple');")); // hide Simplified UI settings
#endif
}
if (subPage == 4)
{
sappend('v',SET_F("UP"),udpPort);
sappend('v',SET_F("U2"),udpPort2);
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("SO"),receiveSegmentOptions);
sappend('c',SET_F("SG"),receiveSegmentBounds);
sappend('c',SET_F("SD"),notifyDirectDefault);
sappend('c',SET_F("SB"),notifyButton);
sappend('c',SET_F("SH"),notifyHue);
sappend('c',SET_F("SM"),notifyMacro);
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('v',SET_F("EP"),e131Port);
sappend('c',SET_F("ES"),e131SkipOutOfSequence);
sappend('c',SET_F("EM"),e131Multicast);
sappend('v',SET_F("EU"),e131Universe);
#ifdef WLED_ENABLE_DMX
oappend(SET_F("hideNoDMX();")); // WLEDMM hide "not compiled in" message
#endif
#ifndef WLED_ENABLE_DMX_INPUT
oappend(SET_F("hideDMXInput();")); // WLEDMM hide "dmx input" settings
#else
oappend(SET_F("hideNoDMXInput();")); // WLEDMM hide "not compiled in" message
sappend('v',SET_F("IDMT"),dmxInputTransmitPin);
sappend('v',SET_F("IDMR"),dmxInputReceivePin);
sappend('v',SET_F("IDME"),dmxInputEnablePin);
sappend('v',SET_F("IDMP"),dmxInputPort);
#endif
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);
sappend('c',SET_F("AL"),alexaEnabled);
sappends('s',SET_F("AI"),alexaInvocationName);
sappend('c',SET_F("SA"),notifyAlexa);
sappend('v',SET_F("AP"),alexaNumPresets);
#ifdef WLED_DISABLE_ALEXA
oappend(SET_F("toggle('Alexa');")); // hide Alexa settings
#endif
#ifdef WLED_ENABLE_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);
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);
#else
oappend(SET_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);
char hueErrorString[25];
switch (hueError)
{
case HUE_ERROR_INACTIVE : strcpy_P(hueErrorString,PSTR("Inactive")); break;
case HUE_ERROR_ACTIVE : strcpy_P(hueErrorString,PSTR("Active")); break;
case HUE_ERROR_UNAUTHORIZED : strcpy_P(hueErrorString,PSTR("Unauthorized")); break;
case HUE_ERROR_LIGHTID : strcpy_P(hueErrorString,PSTR("Invalid light ID")); break;
case HUE_ERROR_PUSHLINK : strcpy_P(hueErrorString,PSTR("Link button not pressed")); break;
case HUE_ERROR_JSON_PARSING : strcpy_P(hueErrorString,PSTR("JSON parsing error")); break;
case HUE_ERROR_TIMEOUT : strcpy_P(hueErrorString,PSTR("Timeout")); break;
default: sprintf_P(hueErrorString,PSTR("Bridge Error %i"),hueError);
}
sappends('m',SET_F("(\"sip\")[0]"),hueErrorString);
#else
oappend(SET_F("toggle('Hue');")); // hide Hue Sync settings
#endif
//WLEDMM: add netdebug variables
#ifdef WLED_DEBUG_HOST
sappend('v',SET_F("N0"),netDebugPrintIP[0]);
sappend('v',SET_F("N1"),netDebugPrintIP[1]);
sappend('v',SET_F("N2"),netDebugPrintIP[2]);
sappend('v',SET_F("N3"),netDebugPrintIP[3]);
sappend('v',SET_F("NP"),netDebugPrintPort);
#endif
sappend('v',SET_F("BD"),serialBaud);
#ifdef WLED_ENABLE_LOXONE
oappend(SET_F("hideNoLOX();")); // WLEDMM hide "not compiled in" message
#endif
#ifdef WLED_ENABLE_ADALIGHT
oappend(SET_F("hideNoADA();")); // WLEDMM hide "not compiled in" message
#endif
}
if (subPage == 5)
{
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);
char tm[48];
dtostrf(longitude,4,2,tm);
sappends('s',SET_F("LN"),tm);
dtostrf(latitude,4,2,tm);
sappends('s',SET_F("LT"),tm);
getTimeString(tm);
sappends('m',SET_F("(\"times\")[0]"),tm);
if ((int)(longitude*10.0f) || (int)(latitude*10.0f)) {
snprintf_P(tm, sizeof(tm), PSTR("Sunrise: %02d:%02d Sunset: %02d:%02d"), hour(sunrise), minute(sunrise), hour(sunset), minute(sunset));
sappends('m',SET_F("(\"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("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);
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
oappend(SET_F("addRow("));
oappend(itoa(i,tm,10)); oappend(",");
oappend(itoa(macroButton[i],tm,10)); oappend(",");
oappend(itoa(macroLongPress[i],tm,10)); oappend(",");
oappend(itoa(macroDoublePress[i],tm,10));
oappend(SET_F(");"));
}
char k[4];
k[2] = 0; //Time macros
for (int i = 0; i<10; i++)
{
k[1] = 48+i; //ascii 0,1,2,3
if (i<8) { k[0] = 'H'; sappend('v',k,timerHours[i]); }
k[0] = 'N'; sappend('v',k,timerMinutes[i]);
k[0] = 'T'; sappend('v',k,timerMacro[i]);
k[0] = 'W'; sappend('v',k,timerWeekday[i]);
if (i<8) {
k[0] = 'M'; sappend('v',k,(timerMonth[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]);
}
}
}
if (subPage == 6)
{
byte l = strlen(settingsPIN);
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("WLEDMM ")); //WLEDMM server message
olen -= 2; //delete ";
oappend(versionString);
oappend(SET_F(" ("));
oappendi(VERSION);
oappend(SET_F(")<br><small>\\\""));
oappend(releaseString);
oappend(SET_F(".bin\\\"<br>(Processor: "));
oappend(
#if defined(ARDUINO_ARCH_ESP32)
ESP.getChipModel()
#else
"ESP8266"
#endif
);
oappend(SET_F(")</small>\";"));
oappend(SET_F("sd=\""));
oappend(serverDescription);
oappend(SET_F("\";"));
}
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
if (subPage == 7)
{
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]);
}
#endif
if (subPage == 8) //usermods
{
appendGPIOinfo();
oappendUseDeflate(true); // allow replacing long functions with shorter equivalents - only works for usermods
if (!request->hasParam("um") ) {
// oappend(SET_F("numM="));
// oappendi(usermods.getModCount());
// oappend(";");
oappend(SET_F("d.getElementsByName(\"if:SDA:pin\")[1].value=")); oappendi(i2c_sda); oappend(";");
oappend(SET_F("d.getElementsByName(\"if:SCL:pin\")[1].value=")); oappendi(i2c_scl); oappend(";");
oappend(SET_F("d.getElementsByName(\"if:MOSI:pin\")[1].value=")); oappendi(spi_mosi); oappend(";");
oappend(SET_F("d.getElementsByName(\"if:MISO:pin\")[1].value=")); oappendi(spi_miso); oappend(";");
oappend(SET_F("d.getElementsByName(\"if:SCLK:pin\")[1].value=")); oappendi(spi_sclk); oappend(";");
//WLEDMM: add help info showing defaults
oappend(SET_F("addInfo('if:SDA:pin',0,'', 'SDA');"));
oappend(SET_F("xOpt('if:SDA:pin',1,' ⍼',")); oappendi(SDA); oappend(");");
#ifdef HW_PIN_SDA
oappend(SET_F("xOpt('if:SDA:pin',1,' ⎌',")); oappendi(HW_PIN_SDA); oappend(");");
#endif
oappend(SET_F("addInfo('if:SCL:pin',0,'', 'SCL');"));
oappend(SET_F("xOpt('if:SCL:pin',1,' ⍼',")); oappendi(SCL); oappend(");");
oappend(SET_F("dRO('if:SCL:pin',1);")); // disable read only pins
#ifdef HW_PIN_SCL
oappend(SET_F("xOpt('if:SCL:pin',1,' ⎌',")); oappendi(HW_PIN_SCL); oappend(");");
#endif
oappend(SET_F("addInfo('if:MOSI:pin',0,'', 'MOSI');"));
oappend(SET_F("xOpt('if:MOSI:pin',1,' ⍼',")); oappendi(MOSI); oappend(");");
#ifdef HW_PIN_MOSISPI //WLEDMM renamed from HW_PIN_DATASPI
oappend(SET_F("xOpt('if:MOSI:pin',1,' ⎌',")); oappendi(HW_PIN_MOSISPI); oappend(");");
#endif
oappend(SET_F("addInfo('if:MISO:pin',0,'', 'MISO');"));
oappend(SET_F("xOpt('if:MISO:pin',1,' ⍼',")); oappendi(MISO); oappend(");");
#ifdef HW_PIN_MISOSPI
oappend(SET_F("xOpt('if:MISO:pin',1,' ⎌',")); oappendi(HW_PIN_MISOSPI); oappend(");");
#endif
oappend(SET_F("addInfo('if:SCLK:pin',0,'', 'SCLK');"));
oappend(SET_F("xOpt('if:SCLK:pin',1,' ⍼',")); oappendi(SCK); oappend(");");
oappend(SET_F("dRO('if:SCLK:pin',1);")); // disable read only pins
#ifdef HW_PIN_CLOCKSPI
oappend(SET_F("xOpt('if:SCLK:pin',1,' ⎌',")); oappendi(HW_PIN_CLOCKSPI); oappend(");");
#endif
}
else {
Usermod *usermod = usermods.lookupName(request->getParam("um")->value().c_str());
if (usermod) usermod->appendConfigData();
}
oappendUseDeflate(false);
// oappend(SET_F("console.log('getSettingsJS fix ro pins', d.max_gpio, d.ro_gpio);"));
oappend(SET_F("pinPost();"));
}
if (subPage == 9) // update
{
//WLEDMM: show bin name
sappends('m',SET_F("(\"sip\")[0]"),(char*)F("WLEDMM_"));
olen -= 2; //delete ";
oappend(versionString);
oappend(SET_F(" "));
oappend((char*)FPSTR(releaseString));
oappend(SET_F(".bin<br><small>("));
#if defined(CONFIG_IDF_TARGET_ESP32C3)
oappend(SET_F("ESP32-C3"));
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
oappend(SET_F("ESP32-S3"));
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
oappend(SET_F("ESP32-S2"));
#elif defined(ARDUINO_ARCH_ESP32)
oappend(ESP.getChipModel());
#else
oappend("esp8266");
#endif
oappend(SET_F(" build "));
oappendi(VERSION);
oappend(SET_F(")</small>\";"));
}
if (subPage == 10) // 2D matrices
{
sappend('v',SET_F("SOMP"),strip.isMatrix);
#ifndef WLED_DISABLE_2D
oappend(SET_F("maxPanels=")); oappendi(WLED_MAX_PANELS); oappend(SET_F(";"));
oappend(SET_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);
}
sappend('v',SET_F("MPC"),strip.panels);
//WLEDMM: keep storing basic 2d setup
sappend('v',SET_F("BA"),strip.bOrA); //WLEDMM basic or advanced
sappend('v',SET_F("MPH"),strip.panelsH);
sappend('v',SET_F("MPV"),strip.panelsV);
sappend('v',SET_F("PB"),strip.matrix.bottomStart);
sappend('v',SET_F("PR"),strip.matrix.rightStart);
sappend('v',SET_F("PV"),strip.matrix.vertical);
sappend('c',SET_F("PS"),strip.matrix.serpentine);
sappend('v',SET_F("PBL"),strip.panelO.bottomStart);
sappend('v',SET_F("PRL"),strip.panelO.rightStart);
sappend('v',SET_F("PVL"),strip.panelO.vertical);
sappend('c',SET_F("PSL"),strip.panelO.serpentine);
//WLEDMM: add Total LEDs
uint16_t ledCount = 0;
for (int8_t b = 0; b < busses.getNumBusses(); b++) {
ledCount+=busses.getBus(b)->getLength();
}
sappend('v',SET_F("LC"),ledCount); //WLEDMM
// panels
for (uint8_t i=0; i<strip.panels; i++) {
char n[5];
oappend(SET_F("addPanel("));
oappend(itoa(i,n,10));
oappend(SET_F(");"));
char pO[8] = { '\0' };
snprintf_P(pO, 7, PSTR("P%d"), i); // MAX_PANELS is 64 so pO will always only be 4 characters or less
pO[7] = '\0';
uint8_t l = strlen(pO);
// create P0B, P1B, ..., P63B, etc for other PxxX
pO[l] = 'B'; sappend('v',pO,strip.panel[i].bottomStart);
pO[l] = 'R'; sappend('v',pO,strip.panel[i].rightStart);
pO[l] = 'V'; sappend('v',pO,strip.panel[i].vertical);
pO[l] = 'S'; sappend('c',pO,strip.panel[i].serpentine);
pO[l] = 'X'; sappend('v',pO,strip.panel[i].xOffset);
pO[l] = 'Y'; sappend('v',pO,strip.panel[i].yOffset);
pO[l] = 'W'; sappend('v',pO,strip.panel[i].width);
pO[l] = 'H'; sappend('v',pO,strip.panel[i].height);
}
}
#else
oappend(SET_F("gId(\"somp\").remove(1);")); // remove 2D option from dropdown
#endif
}
}