.... actually we undo gamma adjustments, because screens (laptop, pad, etc) will apply their own gamma corrections. Activate in LED settings: "Use Gamma correction for preview" Colors in WLED are sometimes gamma corrected, sometimes not. This change tries to make the best out of the color mess, but its still not working properly in all configurations.
918 lines
32 KiB
C++
918 lines
32 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(!pinManager.isPinOk(pinNr, false)) {
|
|
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(CONFIG_IDF_TARGET_ESP32S2)
|
|
oappendi(46);
|
|
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
|
oappendi(48);
|
|
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
|
oappendi(21);
|
|
#elif defined(ESP32)
|
|
oappendi(39);
|
|
#else //8266
|
|
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);
|
|
}
|
|
|
|
//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
|
|
}
|
|
|
|
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("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_LEDS_PER_BUS,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;
|
|
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
|
|
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);
|
|
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;
|
|
}
|
|
}
|
|
sappend('v',sp,speed);
|
|
}
|
|
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
|
|
}
|
|
|
|
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("DMT"),dmxTransmitPin);
|
|
sappend('v',SET_F("DMR"),dmxReceivePin);
|
|
sappend('v',SET_F("DME"),dmxEnablePin);
|
|
#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.) || (int)(latitude*10.)) {
|
|
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(" (build "));
|
|
oappendi(VERSION);
|
|
oappend(SET_F(")\";"));
|
|
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();
|
|
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();
|
|
}
|
|
|
|
// 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(releaseString);
|
|
oappend(SET_F(".bin<br>("));
|
|
#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(")\";"));
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|