2020-04-10 12:30:08 +02:00
# include "wled.h"
2016-12-31 00:38:51 +01:00
/*
* Receives client input
*/
2018-09-17 11:15:08 +02:00
//called upon POST settings form submit
2019-02-16 00:21:22 +01:00
void handleSettingsSet ( AsyncWebServerRequest * request , byte subPage )
2016-11-19 19:39:17 +01:00
{
2023-06-15 23:58:22 +02:00
if ( subPage = = SUBPAGE_PINREQ )
2022-03-01 23:37:28 +01:00
{
2023-06-14 11:53:39 +02:00
checkSettingsPIN ( request - > arg ( F ( " PIN " ) ) . c_str ( ) ) ;
2022-03-01 23:37:28 +01:00
return ;
}
2020-02-23 22:24:51 +01:00
2022-05-08 10:50:48 +02:00
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX 8: usermods 9: N/A 10: 2D
2023-06-15 23:58:22 +02:00
if ( subPage < 1 | | subPage > 10 | | ! correctPIN ) return ;
2022-03-01 23:37:28 +01:00
2018-02-20 22:29:48 +01:00
//WIFI SETTINGS
2023-06-15 23:58:22 +02:00
if ( subPage = = SUBPAGE_WIFI )
2016-11-19 19:39:17 +01:00
{
2020-09-20 01:18:31 +02:00
strlcpy ( clientSSID , request - > arg ( F ( " CS " ) ) . c_str ( ) , 33 ) ;
2019-12-11 00:59:15 +01:00
2020-09-20 01:18:31 +02:00
if ( ! isAsterisksOnly ( request - > arg ( F ( " CP " ) ) . c_str ( ) , 65 ) ) strlcpy ( clientPass , request - > arg ( F ( " CP " ) ) . c_str ( ) , 65 ) ;
2018-09-17 11:15:08 +02:00
2020-09-20 01:18:31 +02:00
strlcpy ( cmDNS , request - > arg ( F ( " CM " ) ) . c_str ( ) , 33 ) ;
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
apBehavior = request - > arg ( F ( " AB " ) ) . toInt ( ) ;
strlcpy ( apSSID , request - > arg ( F ( " AS " ) ) . c_str ( ) , 33 ) ;
apHide = request - > hasArg ( F ( " AH " ) ) ;
int passlen = request - > arg ( F ( " AP " ) ) . length ( ) ;
if ( passlen = = 0 | | ( passlen > 7 & & ! isAsterisksOnly ( request - > arg ( F ( " AP " ) ) . c_str ( ) , 65 ) ) ) strlcpy ( apPass , request - > arg ( F ( " AP " ) ) . c_str ( ) , 65 ) ;
int t = request - > arg ( F ( " AC " ) ) . toInt ( ) ; if ( t > 0 & & t < 14 ) apChannel = t ;
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
noWifiSleep = request - > hasArg ( F ( " WS " ) ) ;
2020-02-20 17:08:56 +01:00
2023-06-22 10:06:19 +02:00
# ifndef WLED_DISABLE_ESPNOW
enable_espnow_remote = request - > hasArg ( F ( " RE " ) ) ;
strlcpy ( linked_remote , request - > arg ( F ( " RMAC " ) ) . c_str ( ) , 13 ) ;
//Normalize MAC format to lowercase
strlcpy ( linked_remote , strlwr ( linked_remote ) , 13 ) ;
# endif
2021-01-15 10:37:45 +01:00
# ifdef WLED_USE_ETHERNET
ethernetType = request - > arg ( F ( " ETH " ) ) . toInt ( ) ;
2021-08-23 14:14:48 +02:00
WLED : : instance ( ) . initEthernet ( ) ;
2021-01-15 10:37:45 +01:00
# endif
2018-09-17 11:15:08 +02:00
char k [ 3 ] ; k [ 2 ] = 0 ;
2018-07-21 23:21:07 +02:00
for ( int i = 0 ; i < 4 ; i + + )
2018-01-27 23:28:20 +01:00
{
2018-09-17 11:15:08 +02:00
k [ 1 ] = i + 48 ; //ascii 0,1,2,3
2019-08-17 12:27:06 +02:00
2018-07-21 23:21:07 +02:00
k [ 0 ] = ' I ' ; //static IP
2019-02-16 00:21:22 +01:00
staticIP [ i ] = request - > arg ( k ) . toInt ( ) ;
2019-08-17 12:27:06 +02:00
2018-07-21 23:21:07 +02:00
k [ 0 ] = ' G ' ; //gateway
2019-02-16 00:21:22 +01:00
staticGateway [ i ] = request - > arg ( k ) . toInt ( ) ;
2019-08-17 12:27:06 +02:00
2018-07-21 23:21:07 +02:00
k [ 0 ] = ' S ' ; //subnet
2019-02-16 00:21:22 +01:00
staticSubnet [ i ] = request - > arg ( k ) . toInt ( ) ;
2016-11-27 16:45:54 +01:00
}
2016-11-19 19:39:17 +01:00
}
2018-02-20 22:29:48 +01:00
//LED SETTINGS
2023-06-15 23:58:22 +02:00
if ( subPage = = SUBPAGE_LEDS )
2016-12-11 20:11:14 +01:00
{
2021-01-21 01:21:16 +01:00
int t = 0 ;
2021-08-23 14:14:48 +02:00
if ( rlyPin > = 0 & & pinManager . isPinAllocated ( rlyPin , PinOwner : : Relay ) ) {
pinManager . deallocatePin ( rlyPin , PinOwner : : Relay ) ;
}
if ( irPin > = 0 & & pinManager . isPinAllocated ( irPin , PinOwner : : IR ) ) {
pinManager . deallocatePin ( irPin , PinOwner : : IR ) ;
}
for ( uint8_t s = 0 ; s < WLED_MAX_BUTTONS ; s + + ) {
if ( btnPin [ s ] > = 0 & & pinManager . isPinAllocated ( btnPin [ s ] , PinOwner : : Button ) ) {
pinManager . deallocatePin ( btnPin [ s ] , PinOwner : : Button ) ;
}
}
2021-01-17 00:20:31 +01:00
2022-04-30 12:45:38 +02:00
uint8_t colorOrder , type , skip , awmode , channelSwap ;
2021-01-26 00:19:41 +01:00
uint16_t length , start ;
2021-02-24 20:23:32 +01:00
uint8_t pins [ 5 ] = { 255 , 255 , 255 , 255 , 255 } ;
2021-01-21 01:21:16 +01:00
2021-09-11 01:17:42 +02:00
autoSegments = request - > hasArg ( F ( " MS " ) ) ;
2021-11-24 11:02:25 +01:00
correctWB = request - > hasArg ( F ( " CCT " ) ) ;
2021-11-26 20:18:38 +01:00
cctFromRgb = request - > hasArg ( F ( " CR " ) ) ;
2022-03-08 02:16:33 +01:00
strip . cctBlending = request - > arg ( F ( " CB " ) ) . toInt ( ) ;
Bus : : setCCTBlend ( strip . cctBlending ) ;
2023-02-14 01:33:06 +01:00
Bus : : setGlobalAWMode ( request - > arg ( F ( " AW " ) ) . toInt ( ) ) ;
2022-03-08 02:16:33 +01:00
strip . setTargetFps ( request - > arg ( F ( " FR " ) ) . toInt ( ) ) ;
2023-06-30 21:12:59 +02:00
useGlobalLedBuffer = request - > hasArg ( F ( " LD " ) ) ;
2021-09-11 01:17:42 +02:00
2022-07-01 14:10:32 +02:00
bool busesChanged = false ;
2022-12-31 17:06:18 +01:00
for ( uint8_t s = 0 ; s < WLED_MAX_BUSSES + WLED_MIN_VIRTUAL_BUSSES ; s + + ) {
2021-01-30 20:51:36 +01:00
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
2022-03-16 01:45:07 +01:00
char sl [ 4 ] = " SL " ; sl [ 2 ] = 48 + s ; sl [ 3 ] = 0 ; //skip first N LEDs
2021-10-07 22:57:07 +02:00
char rf [ 4 ] = " RF " ; rf [ 2 ] = 48 + s ; rf [ 3 ] = 0 ; //refresh required
2022-03-09 13:39:51 +01:00
char aw [ 4 ] = " AW " ; aw [ 2 ] = 48 + s ; aw [ 3 ] = 0 ; //auto white mode
2022-04-30 12:45:38 +02:00
char wo [ 4 ] = " WO " ; wo [ 2 ] = 48 + s ; wo [ 3 ] = 0 ; //channel swap
2023-04-28 00:27:19 +02:00
char sp [ 4 ] = " SP " ; sp [ 2 ] = 48 + s ; sp [ 3 ] = 0 ; //bus clock speed (DotStar & PWM)
2021-01-30 20:51:36 +01:00
if ( ! request - > hasArg ( lp ) ) {
2022-07-01 14:10:32 +02:00
DEBUG_PRINT ( F ( " No data for " ) ) ;
DEBUG_PRINTLN ( s ) ;
break ;
2021-01-17 00:20:31 +01:00
}
2021-02-24 14:49:39 +01:00
for ( uint8_t i = 0 ; i < 5 ; i + + ) {
lp [ 1 ] = 48 + i ;
if ( ! request - > hasArg ( lp ) ) break ;
pins [ i ] = ( request - > arg ( lp ) . length ( ) > 0 ) ? request - > arg ( lp ) . toInt ( ) : 255 ;
2021-01-30 20:51:36 +01:00
}
type = request - > arg ( lt ) . toInt ( ) ;
2021-10-07 22:57:07 +02:00
type | = request - > hasArg ( rf ) < < 7 ; // off refresh override
2022-03-16 01:45:07 +01:00
skip = request - > arg ( sl ) . toInt ( ) ;
2021-02-25 09:54:10 +01:00
colorOrder = request - > arg ( co ) . toInt ( ) ;
start = ( request - > hasArg ( ls ) ) ? request - > arg ( ls ) . toInt ( ) : t ;
2021-01-30 20:51:36 +01:00
if ( request - > hasArg ( lc ) & & request - > arg ( lc ) . toInt ( ) > 0 ) {
2021-02-25 09:54:10 +01:00
t + = length = request - > arg ( lc ) . toInt ( ) ;
2021-01-30 20:51:36 +01:00
} else {
break ; // no parameter
}
2022-03-09 13:39:51 +01:00
awmode = request - > arg ( aw ) . toInt ( ) ;
2023-04-28 00:27:19 +02:00
uint16_t freqHz = request - > arg ( sp ) . toInt ( ) ;
if ( type > TYPE_ONOFF & & type < 49 ) {
switch ( freqHz ) {
case 0 : freqHz = WLED_PWM_FREQ / 3 ; break ;
case 1 : freqHz = WLED_PWM_FREQ / 2 ; break ;
default :
case 2 : freqHz = WLED_PWM_FREQ ; break ;
case 3 : freqHz = WLED_PWM_FREQ * 2 ; break ;
case 4 : freqHz = WLED_PWM_FREQ * 3 ; break ;
}
} else if ( type > 48 & & type < 64 ) {
switch ( freqHz ) {
default :
case 0 : freqHz = 1000 ; break ;
case 1 : freqHz = 2000 ; break ;
case 2 : freqHz = 5000 ; break ;
case 3 : freqHz = 10000 ; break ;
case 4 : freqHz = 20000 ; break ;
}
} else {
freqHz = 0 ;
}
2022-04-30 12:45:38 +02:00
channelSwap = ( type = = TYPE_SK6812_RGBW | | type = = TYPE_TM1814 ) ? request - > arg ( wo ) . toInt ( ) : 0 ;
2021-03-03 22:04:24 +01:00
// actual finalization is done in WLED::loop() (removing old busses and adding new)
2022-07-01 14:10:32 +02:00
// this may happen even before this loop is finished so we do "doInitBusses" after the loop
2021-01-30 20:51:36 +01:00
if ( busConfigs [ s ] ! = nullptr ) delete busConfigs [ s ] ;
2023-07-05 23:57:46 +02:00
busConfigs [ s ] = new BusConfig ( type , pins , start , length , colorOrder | ( channelSwap < < 4 ) , request - > hasArg ( cv ) , skip , awmode , freqHz , useGlobalLedBuffer ) ;
2022-07-01 14:10:32 +02:00
busesChanged = true ;
2021-01-17 00:20:31 +01:00
}
2022-07-01 14:10:32 +02:00
//doInitBusses = busesChanged; // we will do that below to ensure all input data is processed
2021-01-17 00:20:31 +01:00
2021-12-31 21:35:27 +01:00
ColorOrderMap com = { } ;
for ( uint8_t s = 0 ; s < WLED_MAX_COLOR_ORDER_MAPPINGS ; s + + ) {
char xs [ 4 ] = " XS " ; xs [ 2 ] = 48 + s ; xs [ 3 ] = 0 ; //start LED
char xc [ 4 ] = " XC " ; xc [ 2 ] = 48 + s ; xc [ 3 ] = 0 ; //strip length
char xo [ 4 ] = " XO " ; xo [ 2 ] = 48 + s ; xo [ 3 ] = 0 ; //color order
2022-01-13 16:06:01 +01:00
if ( request - > hasArg ( xs ) ) {
start = request - > arg ( xs ) . toInt ( ) ;
length = request - > arg ( xc ) . toInt ( ) ;
colorOrder = request - > arg ( xo ) . toInt ( ) ;
com . add ( start , length , colorOrder ) ;
}
2021-12-31 21:35:27 +01:00
}
busses . updateColorOrderMap ( com ) ;
2021-01-17 00:20:31 +01:00
// upate other pins
int hw_ir_pin = request - > arg ( F ( " IR " ) ) . toInt ( ) ;
2021-08-23 14:14:48 +02:00
if ( pinManager . allocatePin ( hw_ir_pin , false , PinOwner : : IR ) ) {
2021-01-17 00:20:31 +01:00
irPin = hw_ir_pin ;
} else {
irPin = - 1 ;
}
2021-05-19 18:39:16 +02:00
irEnabled = request - > arg ( F ( " IT " ) ) . toInt ( ) ;
2022-02-07 00:40:45 +01:00
irApplyToAllSelected = ! request - > hasArg ( F ( " MSO " ) ) ;
2021-01-17 00:20:31 +01:00
int hw_rly_pin = request - > arg ( F ( " RL " ) ) . toInt ( ) ;
2021-08-23 14:14:48 +02:00
if ( pinManager . allocatePin ( hw_rly_pin , true , PinOwner : : Relay ) ) {
2021-01-17 00:20:31 +01:00
rlyPin = hw_rly_pin ;
} else {
rlyPin = - 1 ;
}
rlyMde = ( bool ) request - > hasArg ( F ( " RM " ) ) ;
2022-11-26 23:56:55 +01:00
disablePullUp = ( bool ) request - > hasArg ( F ( " IP " ) ) ;
2021-05-19 18:39:16 +02:00
for ( uint8_t i = 0 ; i < WLED_MAX_BUTTONS ; i + + ) {
2021-11-28 11:24:58 +01:00
char bt [ 4 ] = " BT " ; bt [ 2 ] = ( i < 10 ? 48 : 55 ) + i ; bt [ 3 ] = 0 ; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10)
char be [ 4 ] = " BE " ; be [ 2 ] = ( i < 10 ? 48 : 55 ) + i ; be [ 3 ] = 0 ; // button type (use A,B,C,... if WLED_MAX_BUTTONS>10)
2021-05-20 06:45:02 +02:00
int hw_btn_pin = request - > arg ( bt ) . toInt ( ) ;
2021-08-23 14:14:48 +02:00
if ( pinManager . allocatePin ( hw_btn_pin , false , PinOwner : : Button ) ) {
2021-05-20 06:45:02 +02:00
btnPin [ i ] = hw_btn_pin ;
buttonType [ i ] = request - > arg ( be ) . toInt ( ) ;
2022-12-10 19:16:02 +01:00
# ifdef ARDUINO_ARCH_ESP32
// ESP32 only: check that analog button pin is a valid ADC gpio
2023-01-06 09:24:29 +01:00
if ( ( ( buttonType [ i ] = = BTN_TYPE_ANALOG ) | | ( buttonType [ i ] = = BTN_TYPE_ANALOG_INVERTED ) ) & & ( digitalPinToAnalogChannel ( btnPin [ i ] ) < 0 ) )
2022-12-10 19:16:02 +01:00
{
// not an ADC analog pin
2022-12-10 21:03:58 +01:00
if ( btnPin [ i ] > = 0 ) DEBUG_PRINTF ( " PIN ALLOC error: GPIO%d for analog button #%d is not an analog pin! \n " , btnPin [ i ] , i ) ;
2022-12-10 19:16:02 +01:00
btnPin [ i ] = - 1 ;
pinManager . deallocatePin ( hw_btn_pin , PinOwner : : Button ) ;
2023-01-06 09:24:29 +01:00
}
else
2022-12-10 19:16:02 +01:00
# endif
{
if ( disablePullUp ) {
pinMode ( btnPin [ i ] , INPUT ) ;
} else {
# ifdef ESP32
pinMode ( btnPin [ i ] , buttonType [ i ] = = BTN_TYPE_PUSH_ACT_HIGH ? INPUT_PULLDOWN : INPUT_PULLUP ) ;
# else
pinMode ( btnPin [ i ] , INPUT_PULLUP ) ;
# endif
}
2022-11-26 23:56:55 +01:00
}
2021-05-20 06:45:02 +02:00
} else {
btnPin [ i ] = - 1 ;
buttonType [ i ] = BTN_TYPE_NONE ;
}
2021-01-17 00:20:31 +01:00
}
2021-05-19 20:23:35 +02:00
touchThreshold = request - > arg ( F ( " TT " ) ) . toInt ( ) ;
2021-01-17 00:20:31 +01:00
2020-09-20 01:18:31 +02:00
strip . ablMilliampsMax = request - > arg ( F ( " MA " ) ) . toInt ( ) ;
strip . milliampsPerLed = request - > arg ( F ( " LA " ) ) . toInt ( ) ;
2023-01-06 09:24:29 +01:00
2020-09-20 01:18:31 +02:00
briS = request - > arg ( F ( " CA " ) ) . toInt ( ) ;
2019-12-04 02:01:47 +01:00
2020-09-20 01:18:31 +02:00
turnOnAtBoot = request - > hasArg ( F ( " BO " ) ) ;
t = request - > arg ( F ( " BP " ) ) . toInt ( ) ;
2021-01-13 11:24:27 +01:00
if ( t < = 250 ) bootPreset = t ;
2022-09-04 20:17:05 +02:00
gammaCorrectBri = request - > hasArg ( F ( " GB " ) ) ;
gammaCorrectCol = request - > hasArg ( F ( " GC " ) ) ;
2023-02-12 13:18:30 +01:00
gammaCorrectVal = request - > arg ( F ( " GV " ) ) . toFloat ( ) ;
if ( gammaCorrectVal > 1.0f & & gammaCorrectVal < = 3 )
2023-06-10 20:43:27 +02:00
NeoGammaWLEDMethod : : calcGammaTable ( gammaCorrectVal ) ;
2023-02-12 13:18:30 +01:00
else {
gammaCorrectVal = 1.0f ; // no gamma correction
gammaCorrectBri = false ;
gammaCorrectCol = false ;
}
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
fadeTransition = request - > hasArg ( F ( " TF " ) ) ;
t = request - > arg ( F ( " TD " ) ) . toInt ( ) ;
2022-07-29 12:15:56 +02:00
if ( t > = 0 ) transitionDelayDefault = t ;
2020-09-20 01:18:31 +02:00
strip . paletteFade = request - > hasArg ( F ( " PF " ) ) ;
2023-03-25 21:28:30 +01:00
t = request - > arg ( F ( " TP " ) ) . toInt ( ) ;
randomPaletteChangeTime = MIN ( 255 , MAX ( 1 , t ) ) ;
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
nightlightTargetBri = request - > arg ( F ( " TB " ) ) . toInt ( ) ;
t = request - > arg ( F ( " TL " ) ) . toInt ( ) ;
2018-11-22 00:09:30 +01:00
if ( t > 0 ) nightlightDelayMinsDefault = t ;
2019-09-19 21:15:20 +02:00
nightlightDelayMins = nightlightDelayMinsDefault ;
2020-09-20 01:18:31 +02:00
nightlightMode = request - > arg ( F ( " TW " ) ) . toInt ( ) ;
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " PB " ) ) . toInt ( ) ;
2018-09-17 11:15:08 +02:00
if ( t > = 0 & & t < 4 ) strip . paletteBlend = t ;
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " BF " ) ) . toInt ( ) ;
2018-09-17 11:15:08 +02:00
if ( t > 0 ) briMultiplier = t ;
2022-07-01 14:10:32 +02:00
doInitBusses = busesChanged ;
2016-12-11 20:11:14 +01:00
}
2018-02-20 22:29:48 +01:00
//UI
2023-06-15 23:58:22 +02:00
if ( subPage = = SUBPAGE_UI )
2016-11-19 19:39:17 +01:00
{
2020-09-20 01:18:31 +02:00
strlcpy ( serverDescription , request - > arg ( F ( " DS " ) ) . c_str ( ) , 33 ) ;
syncToggleReceive = request - > hasArg ( F ( " ST " ) ) ;
2022-03-31 21:44:11 +02:00
# ifdef WLED_ENABLE_SIMPLE_UI
2021-08-10 21:52:07 +02:00
if ( simplifiedUI ^ request - > hasArg ( F ( " SU " ) ) ) {
// UI selection changed, invalidate browser cache
cacheInvalidate + + ;
}
2021-08-10 17:11:17 +02:00
simplifiedUI = request - > hasArg ( F ( " SU " ) ) ;
# endif
2023-02-12 13:18:30 +01:00
DEBUG_PRINTLN ( F ( " Enumerating ledmaps " ) ) ;
enumerateLedmaps ( ) ;
DEBUG_PRINTLN ( F ( " Loading custom palettes " ) ) ;
strip . loadCustomPalettes ( ) ; // (re)load all custom palettes
2016-11-19 19:39:17 +01:00
}
2018-02-20 22:29:48 +01:00
//SYNC
2023-06-15 23:58:22 +02:00
if ( subPage = = SUBPAGE_SYNC )
2017-02-24 23:21:48 +01:00
{
2020-09-20 01:18:31 +02:00
int t = request - > arg ( F ( " UP " ) ) . toInt ( ) ;
2018-09-17 11:15:08 +02:00
if ( t > 0 ) udpPort = t ;
2020-09-27 11:43:28 +02:00
t = request - > arg ( F ( " U2 " ) ) . toInt ( ) ;
if ( t > 0 ) udpPort2 = t ;
2021-08-21 12:22:26 +02:00
2021-08-25 00:36:31 +02:00
syncGroups = request - > arg ( F ( " GS " ) ) . toInt ( ) ;
receiveGroups = request - > arg ( F ( " GR " ) ) . toInt ( ) ;
2021-08-21 12:22:26 +02:00
2020-09-20 01:18:31 +02:00
receiveNotificationBrightness = request - > hasArg ( F ( " RB " ) ) ;
receiveNotificationColor = request - > hasArg ( F ( " RC " ) ) ;
receiveNotificationEffects = request - > hasArg ( F ( " RX " ) ) ;
2021-12-17 11:22:20 +01:00
receiveSegmentOptions = request - > hasArg ( F ( " SO " ) ) ;
2022-02-20 22:24:11 +01:00
receiveSegmentBounds = request - > hasArg ( F ( " SG " ) ) ;
2021-12-17 11:22:20 +01:00
receiveNotifications = ( receiveNotificationBrightness | | receiveNotificationColor | | receiveNotificationEffects | | receiveSegmentOptions ) ;
2020-09-20 01:18:31 +02:00
notifyDirectDefault = request - > hasArg ( F ( " SD " ) ) ;
2018-02-20 22:29:48 +01:00
notifyDirect = notifyDirectDefault ;
2020-09-20 01:18:31 +02:00
notifyButton = request - > hasArg ( F ( " SB " ) ) ;
notifyAlexa = request - > hasArg ( F ( " SA " ) ) ;
notifyHue = request - > hasArg ( F ( " SH " ) ) ;
notifyMacro = request - > hasArg ( F ( " SM " ) ) ;
2022-10-19 01:31:23 +02:00
t = request - > arg ( F ( " UR " ) ) . toInt ( ) ;
if ( ( t > = 0 ) & & ( t < 30 ) ) udpNumRetries = t ;
2020-09-20 01:18:31 +02:00
2021-03-13 22:04:37 +01:00
nodeListEnabled = request - > hasArg ( F ( " NL " ) ) ;
if ( ! nodeListEnabled ) Nodes . clear ( ) ;
nodeBroadcastEnabled = request - > hasArg ( F ( " NB " ) ) ;
2020-09-20 01:18:31 +02:00
receiveDirect = request - > hasArg ( F ( " RD " ) ) ;
2022-03-25 16:36:05 +01:00
useMainSegmentOnly = request - > hasArg ( F ( " MO " ) ) ;
2020-09-20 01:18:31 +02:00
e131SkipOutOfSequence = request - > hasArg ( F ( " ES " ) ) ;
e131Multicast = request - > hasArg ( F ( " EM " ) ) ;
t = request - > arg ( F ( " EP " ) ) . toInt ( ) ;
2020-04-13 00:42:27 +02:00
if ( t > 0 ) e131Port = t ;
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " EU " ) ) . toInt ( ) ;
2020-04-13 00:42:27 +02:00
if ( t > = 0 & & t < = 63999 ) e131Universe = t ;
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " DA " ) ) . toInt ( ) ;
2020-04-13 00:42:27 +02:00
if ( t > = 0 & & t < = 510 ) DMXAddress = t ;
2022-11-19 14:10:40 +01:00
t = request - > arg ( F ( " XX " ) ) . toInt ( ) ;
if ( t > = 0 & & t < = 150 ) DMXSegmentSpacing = t ;
2023-02-21 17:13:15 +01:00
t = request - > arg ( F ( " PY " ) ) . toInt ( ) ;
if ( t > = 0 & & t < = 200 ) e131Priority = t ;
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " DM " ) ) . toInt ( ) ;
2022-11-19 14:10:40 +01:00
if ( t > = DMX_MODE_DISABLED & & t < = DMX_MODE_PRESET ) DMXMode = t ;
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " ET " ) ) . toInt ( ) ;
2018-09-17 11:15:08 +02:00
if ( t > 99 & & t < = 65000 ) realtimeTimeoutMs = t ;
2020-09-20 01:18:31 +02:00
arlsForceMaxBri = request - > hasArg ( F ( " FB " ) ) ;
arlsDisableGammaCorrection = request - > hasArg ( F ( " RG " ) ) ;
t = request - > arg ( F ( " WO " ) ) . toInt ( ) ;
2018-09-17 11:15:08 +02:00
if ( t > = - 255 & & t < = 255 ) arlsOffset = t ;
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
alexaEnabled = request - > hasArg ( F ( " AL " ) ) ;
strlcpy ( alexaInvocationName , request - > arg ( F ( " AI " ) ) . c_str ( ) , 33 ) ;
2022-10-25 23:42:26 +02:00
t = request - > arg ( F ( " AP " ) ) . toInt ( ) ;
if ( t > = 0 & & t < = 9 ) alexaNumPresets = t ;
2019-08-17 12:27:06 +02:00
2019-12-11 00:59:15 +01:00
# ifdef WLED_ENABLE_MQTT
2020-09-20 01:18:31 +02:00
mqttEnabled = request - > hasArg ( F ( " MQ " ) ) ;
2023-09-02 01:05:45 +02:00
strlcpy ( mqttServer , request - > arg ( F ( " MS " ) ) . c_str ( ) , MQTT_MAX_SERVER_LEN + 1 ) ;
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " MQPORT " ) ) . toInt ( ) ;
2019-08-18 18:14:17 +02:00
if ( t > 0 ) mqttPort = t ;
2020-09-20 01:18:31 +02:00
strlcpy ( mqttUser , request - > arg ( F ( " MQUSER " ) ) . c_str ( ) , 41 ) ;
2021-06-30 01:23:35 +02:00
if ( ! isAsterisksOnly ( request - > arg ( F ( " MQPASS " ) ) . c_str ( ) , 41 ) ) strlcpy ( mqttPass , request - > arg ( F ( " MQPASS " ) ) . c_str ( ) , 65 ) ;
2020-09-20 01:18:31 +02:00
strlcpy ( mqttClientID , request - > arg ( F ( " MQCID " ) ) . c_str ( ) , 41 ) ;
2023-09-02 01:05:45 +02:00
strlcpy ( mqttDeviceTopic , request - > arg ( F ( " MD " ) ) . c_str ( ) , MQTT_MAX_TOPIC_LEN + 1 ) ;
2023-09-05 17:15:12 +02:00
strlcpy ( mqttGroupTopic , request - > arg ( F ( " MG " ) ) . c_str ( ) , MQTT_MAX_TOPIC_LEN + 1 ) ;
2021-07-01 20:51:52 +02:00
buttonPublishMqtt = request - > hasArg ( F ( " BM " ) ) ;
2023-05-28 22:50:19 +02:00
retainMqttMsg = request - > hasArg ( F ( " RT " ) ) ;
2019-12-11 00:59:15 +01:00
# endif
2019-08-17 12:27:06 +02:00
2019-12-11 00:59:15 +01:00
# ifndef WLED_DISABLE_HUESYNC
2018-02-28 00:27:10 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
2018-03-14 19:05:51 +01:00
String a = " H " + String ( i ) ;
2019-02-16 00:21:22 +01:00
hueIP [ i ] = request - > arg ( a ) . toInt ( ) ;
2018-02-28 00:27:10 +01:00
}
2018-09-17 11:15:08 +02:00
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " HL " ) ) . toInt ( ) ;
2018-09-17 11:15:08 +02:00
if ( t > 0 ) huePollLightId = t ;
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " HI " ) ) . toInt ( ) ;
2018-09-17 11:15:08 +02:00
if ( t > 50 ) huePollIntervalMs = t ;
2020-09-20 01:18:31 +02:00
hueApplyOnOff = request - > hasArg ( F ( " HO " ) ) ;
hueApplyBri = request - > hasArg ( F ( " HB " ) ) ;
hueApplyColor = request - > hasArg ( F ( " HC " ) ) ;
huePollingEnabled = request - > hasArg ( F ( " HP " ) ) ;
2019-02-18 22:34:21 +01:00
hueStoreAllowed = true ;
reconnectHue ( ) ;
2019-12-11 00:59:15 +01:00
# endif
2022-02-01 20:02:46 +01:00
t = request - > arg ( F ( " BD " ) ) . toInt ( ) ;
if ( t > = 96 & & t < = 15000 ) serialBaud = t ;
updateBaudRate ( serialBaud * 100 ) ;
2017-02-24 23:21:48 +01:00
}
2018-02-20 22:29:48 +01:00
//TIME
2023-06-15 23:58:22 +02:00
if ( subPage = = SUBPAGE_TIME )
2017-02-24 23:21:48 +01:00
{
2020-09-20 01:18:31 +02:00
ntpEnabled = request - > hasArg ( F ( " NT " ) ) ;
strlcpy ( ntpServerName , request - > arg ( F ( " NS " ) ) . c_str ( ) , 33 ) ;
useAMPM = ! request - > hasArg ( F ( " CF " ) ) ;
currentTimezone = request - > arg ( F ( " TZ " ) ) . toInt ( ) ;
utcOffsetSecs = request - > arg ( F ( " UO " ) ) . toInt ( ) ;
2018-11-09 17:00:36 +01:00
//start ntp if not already connected
2019-10-18 13:26:39 +02:00
if ( ntpEnabled & & WLED_CONNECTED & & ! ntpConnected ) ntpConnected = ntpUdp . begin ( ntpLocalPort ) ;
2021-12-29 17:03:03 +01:00
ntpLastSyncTime = 0 ; // force new NTP query
2021-03-09 13:24:20 +01:00
2021-03-05 23:05:09 +01:00
longitude = request - > arg ( F ( " LN " ) ) . toFloat ( ) ;
latitude = request - > arg ( F ( " LT " ) ) . toFloat ( ) ;
2021-03-08 19:52:43 +01:00
// force a sunrise/sunset re-calculation
2023-01-06 09:24:29 +01:00
calculateSunriseAndSunset ( ) ;
2019-08-17 12:27:06 +02:00
2022-03-07 00:11:43 +01:00
overlayCurrent = request - > hasArg ( F ( " OL " ) ) ? 1 : 0 ;
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
overlayMin = request - > arg ( F ( " O1 " ) ) . toInt ( ) ;
overlayMax = request - > arg ( F ( " O2 " ) ) . toInt ( ) ;
analogClock12pixel = request - > arg ( F ( " OM " ) ) . toInt ( ) ;
analogClock5MinuteMarks = request - > hasArg ( F ( " O5 " ) ) ;
analogClockSecondsTrail = request - > hasArg ( F ( " OS " ) ) ;
2023-10-26 23:36:29 +02:00
analogClockSolidBlack = request - > hasArg ( F ( " OB " ) ) ;
2020-09-20 01:18:31 +02:00
countdownMode = request - > hasArg ( F ( " CE " ) ) ;
countdownYear = request - > arg ( F ( " CY " ) ) . toInt ( ) ;
countdownMonth = request - > arg ( F ( " CI " ) ) . toInt ( ) ;
countdownDay = request - > arg ( F ( " CD " ) ) . toInt ( ) ;
countdownHour = request - > arg ( F ( " CH " ) ) . toInt ( ) ;
countdownMin = request - > arg ( F ( " CM " ) ) . toInt ( ) ;
countdownSec = request - > arg ( F ( " CS " ) ) . toInt ( ) ;
2020-12-31 20:47:38 +01:00
setCountdown ( ) ;
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
macroAlexaOn = request - > arg ( F ( " A0 " ) ) . toInt ( ) ;
macroAlexaOff = request - > arg ( F ( " A1 " ) ) . toInt ( ) ;
macroCountdown = request - > arg ( F ( " MC " ) ) . toInt ( ) ;
macroNl = request - > arg ( F ( " MN " ) ) . toInt ( ) ;
2021-05-19 18:39:16 +02:00
for ( uint8_t i = 0 ; i < WLED_MAX_BUTTONS ; i + + ) {
2021-12-08 22:05:51 +01:00
char mp [ 4 ] = " MP " ; mp [ 2 ] = ( i < 10 ? 48 : 55 ) + i ; mp [ 3 ] = 0 ; // short
char ml [ 4 ] = " ML " ; ml [ 2 ] = ( i < 10 ? 48 : 55 ) + i ; ml [ 3 ] = 0 ; // long
char md [ 4 ] = " MD " ; md [ 2 ] = ( i < 10 ? 48 : 55 ) + i ; md [ 3 ] = 0 ; // double
2021-05-20 06:45:02 +02:00
//if (!request->hasArg(mp)) break;
macroButton [ i ] = request - > arg ( mp ) . toInt ( ) ; // these will default to 0 if not present
2021-05-19 18:39:16 +02:00
macroLongPress [ i ] = request - > arg ( ml ) . toInt ( ) ;
macroDoublePress [ i ] = request - > arg ( md ) . toInt ( ) ;
}
2018-09-22 22:49:24 +02:00
char k [ 3 ] ; k [ 2 ] = 0 ;
2021-12-25 18:46:43 +01:00
for ( int i = 0 ; i < 10 ; i + + ) {
2021-12-31 14:09:48 +01:00
k [ 1 ] = i + 48 ; //ascii 0,1,2,3,...
2018-09-22 22:49:24 +02:00
k [ 0 ] = ' H ' ; //timer hours
2019-02-16 00:21:22 +01:00
timerHours [ i ] = request - > arg ( k ) . toInt ( ) ;
2018-09-22 22:49:24 +02:00
k [ 0 ] = ' N ' ; //minutes
2019-02-16 00:21:22 +01:00
timerMinutes [ i ] = request - > arg ( k ) . toInt ( ) ;
2018-09-22 22:49:24 +02:00
k [ 0 ] = ' T ' ; //macros
2019-02-16 00:21:22 +01:00
timerMacro [ i ] = request - > arg ( k ) . toInt ( ) ;
2019-01-31 00:09:44 +01:00
k [ 0 ] = ' W ' ; //weekdays
2019-02-16 00:21:22 +01:00
timerWeekday [ i ] = request - > arg ( k ) . toInt ( ) ;
2021-12-25 18:46:43 +01:00
if ( i < 8 ) {
2023-02-14 14:28:10 +01:00
k [ 0 ] = ' M ' ; //start month
timerMonth [ i ] = request - > arg ( k ) . toInt ( ) & 0x0F ;
timerMonth [ i ] < < = 4 ;
k [ 0 ] = ' P ' ; //end month
timerMonth [ i ] + = ( request - > arg ( k ) . toInt ( ) & 0x0F ) ;
k [ 0 ] = ' D ' ; //start day
timerDay [ i ] = request - > arg ( k ) . toInt ( ) ;
k [ 0 ] = ' E ' ; //end day
timerDayEnd [ i ] = request - > arg ( k ) . toInt ( ) ;
2021-12-25 18:46:43 +01:00
}
2018-09-22 22:49:24 +02:00
}
2017-02-24 23:21:48 +01:00
}
2018-02-20 22:29:48 +01:00
//SECURITY
2023-06-15 23:58:22 +02:00
if ( subPage = = SUBPAGE_SEC )
2016-11-20 01:47:15 +01:00
{
2020-09-20 01:18:31 +02:00
if ( request - > hasArg ( F ( " RS " ) ) ) //complete factory reset
2016-11-20 01:47:15 +01:00
{
2020-11-06 22:12:48 +01:00
WLED_FS . format ( ) ;
2022-07-30 11:04:04 +02:00
# ifdef WLED_ADD_EEPROM_SUPPORT
2020-12-10 16:27:23 +01:00
clearEEPROM ( ) ;
2022-07-30 11:04:04 +02:00
# endif
2020-09-20 01:18:31 +02:00
serveMessage ( request , 200 , F ( " All Settings erased. " ) , F ( " Connect to WLED-AP to setup again " ) , 255 ) ;
2023-05-30 19:36:14 +02:00
doReboot = true ; // may reboot immediately on dual-core system (race condition) which is desireable in this case
2018-02-20 22:29:48 +01:00
}
2018-02-23 01:33:32 +01:00
2022-03-01 23:37:28 +01:00
if ( request - > hasArg ( F ( " PIN " ) ) ) {
const char * pin = request - > arg ( F ( " PIN " ) ) . c_str ( ) ;
2022-04-30 12:45:38 +02:00
uint8_t pinLen = strlen ( pin ) ;
if ( pinLen = = 4 | | pinLen = = 0 ) {
uint8_t numZeros = 0 ;
for ( uint8_t i = 0 ; i < pinLen ; i + + ) numZeros + = ( pin [ i ] = = ' 0 ' ) ;
if ( numZeros < pinLen | | pinLen = = 0 ) { // ignore 0000 input (placeholder)
strlcpy ( settingsPIN , pin , 5 ) ;
}
2022-03-01 23:37:28 +01:00
settingsPIN [ 4 ] = 0 ;
}
}
2018-02-23 01:33:32 +01:00
bool pwdCorrect = ! otaLock ; //always allow access if ota not locked
2020-09-20 01:18:31 +02:00
if ( request - > hasArg ( F ( " OP " ) ) )
2016-11-20 01:47:15 +01:00
{
2020-09-20 01:18:31 +02:00
if ( otaLock & & strcmp ( otaPass , request - > arg ( F ( " OP " ) ) . c_str ( ) ) = = 0 )
2018-02-20 22:29:48 +01:00
{
2022-04-30 12:45:38 +02:00
// brute force protection: do not unlock even if correct if last save was less than 3 seconds ago
2023-06-14 11:53:39 +02:00
if ( millis ( ) - lastEditTime > PIN_RETRY_COOLDOWN ) pwdCorrect = true ;
2018-02-23 01:33:32 +01:00
}
2020-09-20 01:18:31 +02:00
if ( ! otaLock & & request - > arg ( F ( " OP " ) ) . length ( ) > 0 )
2016-11-20 01:47:15 +01:00
{
2022-04-30 12:45:38 +02:00
strlcpy ( otaPass , request - > arg ( F ( " OP " ) ) . c_str ( ) , 33 ) ; // set new OTA password
2016-11-20 01:47:15 +01:00
}
}
2019-08-17 12:27:06 +02:00
2018-02-23 01:33:32 +01:00
if ( pwdCorrect ) //allow changes if correct pwd or no ota active
2018-02-20 22:29:48 +01:00
{
2020-09-20 01:18:31 +02:00
otaLock = request - > hasArg ( F ( " NO " ) ) ;
wifiLock = request - > hasArg ( F ( " OW " ) ) ;
aOtaEnabled = request - > hasArg ( F ( " AO " ) ) ;
2022-04-30 12:45:38 +02:00
//createEditHandler(correctPIN && !otaLock);
2018-02-20 22:29:48 +01:00
}
2016-11-20 01:47:15 +01:00
}
2022-03-01 23:37:28 +01:00
2020-02-23 22:24:51 +01:00
# ifdef WLED_ENABLE_DMX // include only if DMX is enabled
2023-06-15 23:58:22 +02:00
if ( subPage = = SUBPAGE_DMX )
2020-02-23 22:24:51 +01:00
{
2020-09-20 01:18:31 +02:00
int t = request - > arg ( F ( " PU " ) ) . toInt ( ) ;
2020-05-11 11:51:11 +02:00
if ( t > = 0 & & t < = 63999 ) e131ProxyUniverse = t ;
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " CN " ) ) . toInt ( ) ;
2020-02-23 22:24:51 +01:00
if ( t > 0 & & t < 16 ) {
DMXChannels = t ;
}
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " CS " ) ) . toInt ( ) ;
2020-02-23 22:24:51 +01:00
if ( t > 0 & & t < 513 ) {
DMXStart = t ;
}
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " CG " ) ) . toInt ( ) ;
2020-02-23 22:24:51 +01:00
if ( t > 0 & & t < 513 ) {
DMXGap = t ;
}
2020-09-20 01:18:31 +02:00
t = request - > arg ( F ( " SL " ) ) . toInt ( ) ;
2020-04-10 12:30:08 +02:00
if ( t > = 0 & & t < MAX_LEDS ) {
DMXStartLED = t ;
}
2020-02-23 22:24:51 +01:00
for ( int i = 0 ; i < 15 ; i + + ) {
String argname = " CH " + String ( ( i + 1 ) ) ;
t = request - > arg ( argname ) . toInt ( ) ;
DMXFixtureMap [ i ] = t ;
}
}
# endif
2021-01-17 00:20:31 +01:00
2021-04-10 00:17:15 +02:00
//USERMODS
2023-06-15 23:58:22 +02:00
if ( subPage = = SUBPAGE_UM )
2021-04-10 00:17:15 +02:00
{
2021-12-04 01:05:01 +01:00
if ( ! requestJSONBufferLock ( 5 ) ) return ;
2021-11-03 14:52:22 +01:00
2022-08-07 16:43:29 +02:00
// global I2C & SPI pins
2022-09-13 20:26:45 +02:00
int8_t hw_sda_pin = ! request - > arg ( F ( " SDA " ) ) . length ( ) ? - 1 : ( int ) request - > arg ( F ( " SDA " ) ) . toInt ( ) ;
int8_t hw_scl_pin = ! request - > arg ( F ( " SCL " ) ) . length ( ) ? - 1 : ( int ) request - > arg ( F ( " SCL " ) ) . toInt ( ) ;
2023-05-30 19:36:14 +02:00
if ( i2c_sda ! = hw_sda_pin | | i2c_scl ! = hw_scl_pin ) {
// only if pins changed
uint8_t old_i2c [ 2 ] = { static_cast < uint8_t > ( i2c_scl ) , static_cast < uint8_t > ( i2c_sda ) } ;
pinManager . deallocateMultiplePins ( old_i2c , 2 , PinOwner : : HW_I2C ) ; // just in case deallocation of old pins
PinManagerPinType i2c [ 2 ] = { { hw_sda_pin , true } , { hw_scl_pin , true } } ;
if ( hw_sda_pin > = 0 & & hw_scl_pin > = 0 & & pinManager . allocateMultiplePins ( i2c , 2 , PinOwner : : HW_I2C ) ) {
i2c_sda = hw_sda_pin ;
i2c_scl = hw_scl_pin ;
// no bus re-initialisation as usermods do not get any notification
//Wire.begin(i2c_sda, i2c_scl);
} else {
// there is no Wire.end()
DEBUG_PRINTLN ( F ( " Could not allocate I2C pins. " ) ) ;
i2c_sda = - 1 ;
i2c_scl = - 1 ;
}
2022-08-07 16:43:29 +02:00
}
2022-09-13 20:26:45 +02:00
int8_t hw_mosi_pin = ! request - > arg ( F ( " MOSI " ) ) . length ( ) ? - 1 : ( int ) request - > arg ( F ( " MOSI " ) ) . toInt ( ) ;
int8_t hw_miso_pin = ! request - > arg ( F ( " MISO " ) ) . length ( ) ? - 1 : ( int ) request - > arg ( F ( " MISO " ) ) . toInt ( ) ;
int8_t hw_sclk_pin = ! request - > arg ( F ( " SCLK " ) ) . length ( ) ? - 1 : ( int ) request - > arg ( F ( " SCLK " ) ) . toInt ( ) ;
2022-08-07 16:43:29 +02:00
# ifdef ESP8266
// cannot change pins on ESP8266
2022-08-15 20:23:47 +02:00
if ( hw_mosi_pin > = 0 & & hw_mosi_pin ! = HW_PIN_DATASPI ) hw_mosi_pin = HW_PIN_DATASPI ;
2022-08-27 18:25:54 +02:00
if ( hw_miso_pin > = 0 & & hw_miso_pin ! = HW_PIN_MISOSPI ) hw_mosi_pin = HW_PIN_MISOSPI ;
2022-08-15 20:23:47 +02:00
if ( hw_sclk_pin > = 0 & & hw_sclk_pin ! = HW_PIN_CLOCKSPI ) hw_sclk_pin = HW_PIN_CLOCKSPI ;
2022-08-07 16:43:29 +02:00
# endif
2023-05-30 19:36:14 +02:00
if ( spi_mosi ! = hw_mosi_pin | | spi_miso ! = hw_miso_pin | | spi_sclk ! = hw_sclk_pin ) {
// only if pins changed
uint8_t old_spi [ 3 ] = { static_cast < uint8_t > ( spi_mosi ) , static_cast < uint8_t > ( spi_miso ) , static_cast < uint8_t > ( spi_sclk ) } ;
pinManager . deallocateMultiplePins ( old_spi , 3 , PinOwner : : HW_SPI ) ; // just in case deallocation of old pins
PinManagerPinType spi [ 3 ] = { { hw_mosi_pin , true } , { hw_miso_pin , true } , { hw_sclk_pin , true } } ;
if ( hw_mosi_pin > = 0 & & hw_sclk_pin > = 0 & & pinManager . allocateMultiplePins ( spi , 3 , PinOwner : : HW_SPI ) ) {
spi_mosi = hw_mosi_pin ;
spi_miso = hw_miso_pin ;
spi_sclk = hw_sclk_pin ;
// no bus re-initialisation as usermods do not get any notification
//SPI.end();
# ifdef ESP32
//SPI.begin(spi_sclk, spi_miso, spi_mosi);
# else
//SPI.begin();
# endif
} else {
//SPI.end();
DEBUG_PRINTLN ( F ( " Could not allocate SPI pins. " ) ) ;
spi_mosi = - 1 ;
spi_miso = - 1 ;
spi_sclk = - 1 ;
}
2022-08-07 16:43:29 +02:00
}
2021-04-25 21:15:57 +02:00
JsonObject um = doc . createNestedObject ( " um " ) ;
2021-04-10 00:17:15 +02:00
size_t args = request - > args ( ) ;
2022-02-20 22:24:11 +01:00
uint16_t j = 0 ;
2021-04-10 00:17:15 +02:00
for ( size_t i = 0 ; i < args ; i + + ) {
String name = request - > argName ( i ) ;
String value = request - > arg ( i ) ;
2021-04-17 17:04:36 +02:00
// POST request parameters are combined as <usermodname>_<usermodparameter>
2021-06-27 12:15:35 +02:00
int umNameEnd = name . indexOf ( " : " ) ;
2022-08-15 20:23:47 +02:00
if ( umNameEnd < 1 ) continue ; // parameter does not contain ":" or on 1st place -> wrong
2021-04-17 17:04:36 +02:00
JsonObject mod = um [ name . substring ( 0 , umNameEnd ) ] ; // get a usermod JSON object
if ( mod . isNull ( ) ) {
mod = um . createNestedObject ( name . substring ( 0 , umNameEnd ) ) ; // if it does not exist create it
}
DEBUG_PRINT ( name . substring ( 0 , umNameEnd ) ) ;
DEBUG_PRINT ( " : " ) ;
name = name . substring ( umNameEnd + 1 ) ; // remove mod name from string
2021-06-27 12:15:35 +02:00
// if the resulting name still contains ":" this means nested object
2021-06-25 23:20:01 +02:00
JsonObject subObj ;
2021-06-27 12:15:35 +02:00
int umSubObj = name . indexOf ( " : " ) ;
DEBUG_PRINTF ( " (%d): " , umSubObj ) ;
2021-06-25 23:20:01 +02:00
if ( umSubObj > 0 ) {
2021-06-27 12:15:35 +02:00
subObj = mod [ name . substring ( 0 , umSubObj ) ] ;
2021-06-25 23:20:01 +02:00
if ( subObj . isNull ( ) )
2021-06-27 12:15:35 +02:00
subObj = mod . createNestedObject ( name . substring ( 0 , umSubObj ) ) ;
2021-06-25 23:20:01 +02:00
name = name . substring ( umSubObj + 1 ) ; // remove nested object name from string
} else {
subObj = mod ;
}
2021-06-27 12:15:35 +02:00
DEBUG_PRINT ( name ) ;
2021-06-25 23:20:01 +02:00
2021-04-17 17:04:36 +02:00
// check if parameters represent array
2021-04-11 00:38:13 +02:00
if ( name . endsWith ( " [] " ) ) {
name . replace ( " [] " , " " ) ;
2022-02-12 23:14:00 +01:00
value . replace ( " , " , " . " ) ; // just in case conversion
2021-06-25 23:20:01 +02:00
if ( ! subObj [ name ] . is < JsonArray > ( ) ) {
JsonArray ar = subObj . createNestedArray ( name ) ;
2022-02-12 23:14:00 +01:00
if ( value . indexOf ( " . " ) > = 0 ) ar . add ( value . toFloat ( ) ) ; // we do have a float
else ar . add ( value . toInt ( ) ) ; // we may have an int
2021-04-11 00:38:13 +02:00
j = 0 ;
} else {
2022-02-12 23:14:00 +01:00
if ( value . indexOf ( " . " ) > = 0 ) subObj [ name ] . add ( value . toFloat ( ) ) ; // we do have a float
else subObj [ name ] . add ( value . toInt ( ) ) ; // we may have an int
2021-04-11 00:38:13 +02:00
j + + ;
}
DEBUG_PRINT ( " [ " ) ;
DEBUG_PRINT ( j ) ;
DEBUG_PRINT ( " ] = " ) ;
DEBUG_PRINTLN ( value ) ;
} else {
2021-06-25 23:20:01 +02:00
// we are using a hidden field with the same name as our parameter (!before the actual parameter!)
// to describe the type of parameter (text,float,int), for boolean patameters the first field contains "off"
2021-06-27 12:15:35 +02:00
// so checkboxes have one or two fields (first is always "false", existence of second depends on checkmark and may be "true")
2021-06-25 23:20:01 +02:00
if ( subObj [ name ] . isNull ( ) ) {
// the first occurence of the field describes the parameter type (used in next loop)
2021-06-27 12:15:35 +02:00
if ( value = = " false " ) subObj [ name ] = false ; // checkboxes may have only one field
else subObj [ name ] = value ;
2021-06-25 23:20:01 +02:00
} else {
String type = subObj [ name ] . as < String > ( ) ; // get previously stored value as a type
2021-06-29 18:18:28 +02:00
if ( subObj [ name ] . is < bool > ( ) ) subObj [ name ] = true ; // checkbox/boolean
else if ( type = = " number " ) {
value . replace ( " , " , " . " ) ; // just in case conversion
if ( value . indexOf ( " . " ) > = 0 ) subObj [ name ] = value . toFloat ( ) ; // we do have a float
else subObj [ name ] = value . toInt ( ) ; // we may have an int
} else if ( type = = " int " ) subObj [ name ] = value . toInt ( ) ;
else subObj [ name ] = value ; // text fields
2021-06-25 23:20:01 +02:00
}
2021-04-11 00:38:13 +02:00
DEBUG_PRINT ( " = " ) ;
DEBUG_PRINTLN ( value ) ;
}
2021-04-10 00:17:15 +02:00
}
2021-04-17 17:04:36 +02:00
usermods . readFromConfig ( um ) ; // force change of usermod parameters
2022-09-14 22:28:06 +02:00
DEBUG_PRINTLN ( F ( " Done re-init usermods. " ) ) ;
2021-12-10 13:29:42 +01:00
releaseJSONBufferLock ( ) ;
}
2022-03-01 23:37:28 +01:00
2022-07-10 22:23:25 +02:00
# ifndef WLED_DISABLE_2D
2022-05-08 10:50:48 +02:00
//2D panels
2023-06-15 23:58:22 +02:00
if ( subPage = = SUBPAGE_2D )
2022-05-08 10:50:48 +02:00
{
strip . isMatrix = request - > arg ( F ( " SOMP " ) ) . toInt ( ) ;
2023-01-02 20:56:00 +01:00
strip . panel . clear ( ) ; // release memory if allocated
if ( strip . isMatrix ) {
strip . panels = MAX ( 1 , MIN ( WLED_MAX_PANELS , request - > arg ( F ( " MPC " ) ) . toInt ( ) ) ) ;
strip . panel . reserve ( strip . panels ) ; // pre-allocate memory
for ( uint8_t i = 0 ; i < strip . panels ; i + + ) {
WS2812FX : : Panel p ;
2023-01-03 14:17:42 +01:00
char pO [ 8 ] = { ' \0 ' } ;
2023-01-03 15:16:45 +01:00
snprintf_P ( pO , 7 , PSTR ( " P%d " ) , i ) ; // MAX_PANELS is 64 so pO will always only be 4 characters or less
2023-01-03 14:17:42 +01:00
pO [ 7 ] = ' \0 ' ;
uint8_t l = strlen ( pO ) ;
2023-01-03 15:16:45 +01:00
// create P0B, P1B, ..., P63B, etc for other PxxX
pO [ l ] = ' B ' ; if ( ! request - > hasArg ( pO ) ) break ;
2023-01-02 20:56:00 +01:00
pO [ l ] = ' B ' ; p . bottomStart = request - > arg ( pO ) . toInt ( ) ;
pO [ l ] = ' R ' ; p . rightStart = request - > arg ( pO ) . toInt ( ) ;
pO [ l ] = ' V ' ; p . vertical = request - > arg ( pO ) . toInt ( ) ;
pO [ l ] = ' S ' ; p . serpentine = request - > hasArg ( pO ) ;
pO [ l ] = ' X ' ; p . xOffset = request - > arg ( pO ) . toInt ( ) ;
pO [ l ] = ' Y ' ; p . yOffset = request - > arg ( pO ) . toInt ( ) ;
pO [ l ] = ' W ' ; p . width = request - > arg ( pO ) . toInt ( ) ;
pO [ l ] = ' H ' ; p . height = request - > arg ( pO ) . toInt ( ) ;
strip . panel . push_back ( p ) ;
}
2023-02-09 20:15:55 +01:00
strip . setUpMatrix ( ) ; // will check limits
2023-02-11 18:41:30 +01:00
strip . makeAutoSegments ( true ) ;
2023-02-12 13:18:30 +01:00
strip . deserializeMap ( ) ;
2023-01-02 20:56:00 +01:00
} else {
Segment : : maxWidth = strip . getLengthTotal ( ) ;
Segment : : maxHeight = 1 ;
2022-05-08 10:50:48 +02:00
}
}
2022-07-10 22:23:25 +02:00
# endif
2022-05-08 10:50:48 +02:00
2022-04-30 12:45:38 +02:00
lastEditTime = millis ( ) ;
2023-05-30 19:36:14 +02:00
// do not save if factory reset or LED settings (which are saved after LED re-init)
2023-06-15 23:58:22 +02:00
doSerializeConfig = subPage ! = SUBPAGE_LEDS & & ! ( subPage = = SUBPAGE_SEC & & doReboot ) ;
if ( subPage = = SUBPAGE_UM ) doReboot = request - > hasArg ( F ( " RBT " ) ) ; // prevent race condition on dual core system (set reboot here, after doSerializeConfig has been set)
2023-01-12 20:35:34 +01:00
# ifndef WLED_DISABLE_ALEXA
2023-06-15 23:58:22 +02:00
if ( subPage = = SUBPAGE_SYNC ) alexaInit ( ) ;
2023-01-12 20:35:34 +01:00
# endif
2016-11-19 19:39:17 +01:00
}
2018-11-25 00:00:02 +01:00
//HTTP API request parser
2020-10-03 00:29:36 +02:00
bool handleSet ( AsyncWebServerRequest * request , const String & req , bool apply )
2016-11-19 19:39:17 +01:00
{
2018-11-09 17:00:36 +01:00
if ( ! ( req . indexOf ( " win " ) > = 0 ) ) return false ;
2018-09-17 11:15:08 +02:00
2018-11-09 17:00:36 +01:00
int pos = 0 ;
2020-09-20 01:18:31 +02:00
DEBUG_PRINT ( F ( " API req: " ) ) ;
2018-11-09 17:00:36 +01:00
DEBUG_PRINTLN ( req ) ;
2019-08-17 12:27:06 +02:00
2019-12-01 01:42:52 +01:00
//segment select (sets main segment)
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " SM= " ) ) ;
2022-04-07 21:54:55 +02:00
if ( pos > 0 & & ! realtimeMode ) {
2022-02-20 22:24:11 +01:00
strip . setMainSegmentId ( getNumVal ( & req , pos ) ) ;
2019-12-01 01:42:52 +01:00
}
2022-02-23 19:20:07 +01:00
byte selectedSeg = strip . getFirstSelectedSegId ( ) ;
2019-12-04 02:01:47 +01:00
2022-02-20 22:24:11 +01:00
bool singleSegment = false ;
2022-01-14 14:27:11 +01:00
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " SS= " ) ) ;
2019-12-04 02:01:47 +01:00
if ( pos > 0 ) {
byte t = getNumVal ( & req , pos ) ;
2022-07-19 16:16:43 +02:00
if ( t < strip . getSegmentsNum ( ) ) {
2022-01-14 14:27:11 +01:00
selectedSeg = t ;
2022-02-20 22:24:11 +01:00
singleSegment = true ;
2022-01-14 14:27:11 +01:00
}
2019-12-04 02:01:47 +01:00
}
2022-07-06 13:13:54 +02:00
Segment & selseg = strip . getSegment ( selectedSeg ) ;
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " SV= " ) ) ; //segment selected
2020-06-26 23:30:13 +02:00
if ( pos > 0 ) {
byte t = getNumVal ( & req , pos ) ;
2022-08-19 21:14:49 +02:00
if ( t = = 2 ) for ( uint8_t i = 0 ; i < strip . getSegmentsNum ( ) ; i + + ) strip . getSegment ( i ) . selected = false ; // unselect other segments
selseg . selected = t ;
2020-06-26 23:30:13 +02:00
}
2019-12-01 01:42:52 +01:00
2022-02-23 19:20:07 +01:00
// temporary values, write directly to segments, globals are updated by setValuesFromFirstSelectedSeg()
2022-02-21 18:31:19 +01:00
uint32_t col0 = selseg . colors [ 0 ] ;
uint32_t col1 = selseg . colors [ 1 ] ;
byte colIn [ 4 ] = { R ( col0 ) , G ( col0 ) , B ( col0 ) , W ( col0 ) } ;
byte colInSec [ 4 ] = { R ( col1 ) , G ( col1 ) , B ( col1 ) , W ( col1 ) } ;
byte effectIn = selseg . mode ;
byte speedIn = selseg . speed ;
byte intensityIn = selseg . intensity ;
byte paletteIn = selseg . palette ;
2022-11-13 12:13:49 +01:00
byte custom1In = selseg . custom1 ;
byte custom2In = selseg . custom2 ;
byte custom3In = selseg . custom3 ;
byte check1In = selseg . check1 ;
byte check2In = selseg . check2 ;
byte check3In = selseg . check3 ;
uint16_t startI = selseg . start ;
uint16_t stopI = selseg . stop ;
uint16_t startY = selseg . startY ;
uint16_t stopY = selseg . stopY ;
uint8_t grpI = selseg . grouping ;
uint16_t spcI = selseg . spacing ;
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " &S= " ) ) ; //segment start
2019-12-01 01:42:52 +01:00
if ( pos > 0 ) {
startI = getNumVal ( & req , pos ) ;
}
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " S2= " ) ) ; //segment stop
2019-12-01 01:42:52 +01:00
if ( pos > 0 ) {
stopI = getNumVal ( & req , pos ) ;
}
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " GP= " ) ) ; //segment grouping
2020-01-19 01:07:38 +01:00
if ( pos > 0 ) {
grpI = getNumVal ( & req , pos ) ;
if ( grpI = = 0 ) grpI = 1 ;
}
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " SP= " ) ) ; //segment spacing
2020-01-19 01:07:38 +01:00
if ( pos > 0 ) {
spcI = getNumVal ( & req , pos ) ;
}
2023-07-13 13:08:36 +02:00
strip . setSegment ( selectedSeg , startI , stopI , grpI , spcI , UINT16_MAX , startY , stopY ) ;
2019-12-01 01:42:52 +01:00
2021-09-20 22:24:58 +02:00
pos = req . indexOf ( F ( " RV= " ) ) ; //Segment reverse
2022-08-19 21:14:49 +02:00
if ( pos > 0 ) selseg . reverse = req . charAt ( pos + 3 ) ! = ' 0 ' ;
2021-09-20 22:24:58 +02:00
pos = req . indexOf ( F ( " MI= " ) ) ; //Segment mirror
2022-08-19 21:14:49 +02:00
if ( pos > 0 ) selseg . mirror = req . charAt ( pos + 3 ) ! = ' 0 ' ;
2021-09-20 22:24:58 +02:00
pos = req . indexOf ( F ( " SB= " ) ) ; //Segment brightness/opacity
if ( pos > 0 ) {
byte segbri = getNumVal ( & req , pos ) ;
2022-08-23 15:57:05 +02:00
selseg . setOption ( SEG_OPTION_ON , segbri ) ; // use transition
2021-09-20 22:24:58 +02:00
if ( segbri ) {
2022-07-10 22:23:25 +02:00
selseg . setOpacity ( segbri ) ;
2021-09-20 22:24:58 +02:00
}
}
pos = req . indexOf ( F ( " SW= " ) ) ; //segment power
if ( pos > 0 ) {
switch ( getNumVal ( & req , pos ) ) {
2022-08-23 15:57:05 +02:00
case 0 : selseg . setOption ( SEG_OPTION_ON , false ) ; break ; // use transition
case 1 : selseg . setOption ( SEG_OPTION_ON , true ) ; break ; // use transition
default : selseg . setOption ( SEG_OPTION_ON , ! selseg . on ) ; break ; // use transition
2021-09-20 22:24:58 +02:00
}
}
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " PS= " ) ) ; //saves current in preset
2020-10-08 00:52:15 +02:00
if ( pos > 0 ) savePreset ( getNumVal ( & req , pos ) ) ;
2020-02-09 16:11:38 +01:00
2021-07-04 13:23:45 +02:00
pos = req . indexOf ( F ( " P1= " ) ) ; //sets first preset for cycle
2021-11-22 21:41:04 +01:00
if ( pos > 0 ) presetCycMin = getNumVal ( & req , pos ) ;
2021-07-04 13:23:45 +02:00
pos = req . indexOf ( F ( " P2= " ) ) ; //sets last preset for cycle
2021-11-22 21:41:04 +01:00
if ( pos > 0 ) presetCycMax = getNumVal ( & req , pos ) ;
2021-07-04 13:23:45 +02:00
2020-02-09 16:11:38 +01:00
//apply preset
2022-06-03 22:22:18 +02:00
if ( updateVal ( req . c_str ( ) , " PL= " , & presetCycCurr , presetCycMin , presetCycMax ) ) {
2023-02-14 14:28:10 +01:00
unloadPlaylist ( ) ;
2021-07-04 13:23:45 +02:00
applyPreset ( presetCycCurr ) ;
}
2020-02-09 16:11:38 +01:00
2019-02-22 22:53:33 +01:00
//set brightness
2022-06-03 22:22:18 +02:00
updateVal ( req . c_str ( ) , " &A= " , & bri ) ;
2019-02-22 22:53:33 +01:00
2022-02-16 21:12:33 +01:00
bool col0Changed = false , col1Changed = false ;
2019-02-22 22:53:33 +01:00
//set colors
2022-06-03 22:22:18 +02:00
col0Changed | = updateVal ( req . c_str ( ) , " &R= " , & colIn [ 0 ] ) ;
col0Changed | = updateVal ( req . c_str ( ) , " &G= " , & colIn [ 1 ] ) ;
col0Changed | = updateVal ( req . c_str ( ) , " &B= " , & colIn [ 2 ] ) ;
col0Changed | = updateVal ( req . c_str ( ) , " &W= " , & colIn [ 3 ] ) ;
2022-02-16 21:12:33 +01:00
2022-06-03 22:22:18 +02:00
col1Changed | = updateVal ( req . c_str ( ) , " R2= " , & colInSec [ 0 ] ) ;
col1Changed | = updateVal ( req . c_str ( ) , " G2= " , & colInSec [ 1 ] ) ;
col1Changed | = updateVal ( req . c_str ( ) , " B2= " , & colInSec [ 2 ] ) ;
col1Changed | = updateVal ( req . c_str ( ) , " W2= " , & colInSec [ 3 ] ) ;
2018-02-28 00:27:10 +01:00
2020-09-27 11:43:28 +02:00
# ifdef WLED_ENABLE_LOXONE
2020-09-27 11:37:16 +02:00
//lox parser
pos = req . indexOf ( F ( " LX= " ) ) ; // Lox primary color
if ( pos > 0 ) {
int lxValue = getNumVal ( & req , pos ) ;
2022-02-20 22:24:11 +01:00
if ( parseLx ( lxValue , colIn ) ) {
2020-09-27 11:37:16 +02:00
bri = 255 ;
nightlightActive = false ; //always disable nightlight when toggling
2022-02-21 20:48:11 +01:00
col0Changed = true ;
2020-09-27 11:37:16 +02:00
}
}
2020-09-27 11:43:28 +02:00
pos = req . indexOf ( F ( " LY= " ) ) ; // Lox secondary color
2020-09-27 11:37:16 +02:00
if ( pos > 0 ) {
int lxValue = getNumVal ( & req , pos ) ;
2022-02-20 22:24:11 +01:00
if ( parseLx ( lxValue , colInSec ) ) {
2020-09-27 11:37:16 +02:00
bri = 255 ;
nightlightActive = false ; //always disable nightlight when toggling
2022-02-21 20:48:11 +01:00
col1Changed = true ;
2020-09-27 11:37:16 +02:00
}
}
2020-09-27 11:43:28 +02:00
# endif
2018-11-09 17:00:36 +01:00
//set hue
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " HU= " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2018-11-25 00:00:02 +01:00
uint16_t temphue = getNumVal ( & req , pos ) ;
2018-11-09 17:00:36 +01:00
byte tempsat = 255 ;
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " SA= " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2018-11-25 00:00:02 +01:00
tempsat = getNumVal ( & req , pos ) ;
2018-11-09 17:00:36 +01:00
}
2022-01-15 21:15:37 +01:00
byte sec = req . indexOf ( F ( " H2 " ) ) ;
2022-02-20 22:24:11 +01:00
colorHStoRGB ( temphue , tempsat , ( sec > 0 ) ? colInSec : colIn ) ;
2022-02-21 20:48:11 +01:00
col0Changed | = ( ! sec ) ; col1Changed | = sec ;
2018-11-09 17:00:36 +01:00
}
2019-08-17 12:27:06 +02:00
2020-09-27 11:43:28 +02:00
//set white spectrum (kelvin)
pos = req . indexOf ( F ( " &K= " ) ) ;
if ( pos > 0 ) {
2022-01-15 21:15:37 +01:00
byte sec = req . indexOf ( F ( " K2 " ) ) ;
2022-02-20 22:24:11 +01:00
colorKtoRGB ( getNumVal ( & req , pos ) , ( sec > 0 ) ? colInSec : colIn ) ;
2022-02-21 20:48:11 +01:00
col0Changed | = ( ! sec ) ; col1Changed | = sec ;
2020-09-27 11:43:28 +02:00
}
2018-11-09 17:00:36 +01:00
//set color from HEX or 32bit DEC
2022-01-15 21:15:37 +01:00
byte tmpCol [ 4 ] ;
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " CL= " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2022-02-20 22:24:11 +01:00
colorFromDecOrHexString ( colIn , ( char * ) req . substring ( pos + 3 ) . c_str ( ) ) ;
2022-02-21 20:48:11 +01:00
col0Changed = true ;
2018-11-09 17:00:36 +01:00
}
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " C2= " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2022-02-20 22:24:11 +01:00
colorFromDecOrHexString ( colInSec , ( char * ) req . substring ( pos + 3 ) . c_str ( ) ) ;
2022-02-21 20:48:11 +01:00
col1Changed = true ;
2018-11-09 17:00:36 +01:00
}
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " C3= " ) ) ;
2020-04-23 23:52:33 +02:00
if ( pos > 0 ) {
2022-01-15 21:15:37 +01:00
colorFromDecOrHexString ( tmpCol , ( char * ) req . substring ( pos + 3 ) . c_str ( ) ) ;
2022-02-16 21:12:33 +01:00
uint32_t col2 = RGBW32 ( tmpCol [ 0 ] , tmpCol [ 1 ] , tmpCol [ 2 ] , tmpCol [ 3 ] ) ;
2022-07-10 22:23:25 +02:00
selseg . setColor ( 2 , col2 ) ; // defined above (SS= or main)
2022-02-22 10:42:00 +01:00
if ( ! singleSegment ) strip . setColor ( 2 , col2 ) ; // will set color to all active & selected segments
2020-04-23 23:52:33 +02:00
}
2019-08-17 12:27:06 +02:00
2018-11-09 17:00:36 +01:00
//set to random hue SR=0->1st SR=1->2nd
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " SR " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2022-01-15 21:15:37 +01:00
byte sec = getNumVal ( & req , pos ) ;
2022-02-20 22:24:11 +01:00
setRandomColor ( sec ? colInSec : colIn ) ;
2022-02-21 20:48:11 +01:00
col0Changed | = ( ! sec ) ; col1Changed | = sec ;
2018-11-09 17:00:36 +01:00
}
2019-08-17 12:27:06 +02:00
2018-11-09 17:00:36 +01:00
//swap 2nd & 1st
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " SC " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2019-02-05 21:53:39 +01:00
byte temp ;
2022-01-15 21:15:37 +01:00
for ( uint8_t i = 0 ; i < 4 ; i + + ) {
2022-02-20 22:24:11 +01:00
temp = colIn [ i ] ;
colIn [ i ] = colInSec [ i ] ;
colInSec [ i ] = temp ;
2018-11-09 17:00:36 +01:00
}
2022-02-21 20:48:11 +01:00
col0Changed = col1Changed = true ;
2022-02-16 21:12:33 +01:00
}
2022-02-21 20:48:11 +01:00
// apply colors to selected segment, and all selected segments if applicable
if ( col0Changed ) {
uint32_t colIn0 = RGBW32 ( colIn [ 0 ] , colIn [ 1 ] , colIn [ 2 ] , colIn [ 3 ] ) ;
2022-07-10 22:23:25 +02:00
selseg . setColor ( 0 , colIn0 ) ;
2022-02-22 10:42:00 +01:00
if ( ! singleSegment ) strip . setColor ( 0 , colIn0 ) ; // will set color to all active & selected segments
2022-02-16 21:12:33 +01:00
}
2022-02-21 20:48:11 +01:00
if ( col1Changed ) {
uint32_t colIn1 = RGBW32 ( colInSec [ 0 ] , colInSec [ 1 ] , colInSec [ 2 ] , colInSec [ 3 ] ) ;
2022-07-10 22:23:25 +02:00
selseg . setColor ( 1 , colIn1 ) ;
2022-02-22 10:42:00 +01:00
if ( ! singleSegment ) strip . setColor ( 1 , colIn1 ) ; // will set color to all active & selected segments
2018-11-09 17:00:36 +01:00
}
2019-08-17 12:27:06 +02:00
2022-02-21 20:48:11 +01:00
bool fxModeChanged = false , speedChanged = false , intensityChanged = false , paletteChanged = false ;
2022-11-13 12:13:49 +01:00
bool custom1Changed = false , custom2Changed = false , custom3Changed = false , check1Changed = false , check2Changed = false , check3Changed = false ;
2022-02-21 20:48:11 +01:00
// set effect parameters
2022-06-03 22:22:18 +02:00
if ( updateVal ( req . c_str ( ) , " FX= " , & effectIn , 0 , strip . getModeCount ( ) - 1 ) ) {
2022-02-21 20:48:11 +01:00
if ( request ! = nullptr ) unloadPlaylist ( ) ; // unload playlist if changing FX using web request
fxModeChanged = true ;
}
2022-06-03 22:22:18 +02:00
speedChanged = updateVal ( req . c_str ( ) , " SX= " , & speedIn ) ;
intensityChanged = updateVal ( req . c_str ( ) , " IX= " , & intensityIn ) ;
paletteChanged = updateVal ( req . c_str ( ) , " FP= " , & paletteIn , 0 , strip . getPaletteCount ( ) - 1 ) ;
2022-11-13 12:13:49 +01:00
custom1Changed = updateVal ( req . c_str ( ) , " X1= " , & custom1In ) ;
custom2Changed = updateVal ( req . c_str ( ) , " X2= " , & custom2In ) ;
custom3Changed = updateVal ( req . c_str ( ) , " X3= " , & custom3In ) ;
check1Changed = updateVal ( req . c_str ( ) , " M1= " , & check1In ) ;
check2Changed = updateVal ( req . c_str ( ) , " M2= " , & check2In ) ;
check3Changed = updateVal ( req . c_str ( ) , " M3= " , & check3In ) ;
stateChanged | = ( fxModeChanged | | speedChanged | | intensityChanged | | paletteChanged | | custom1Changed | | custom2Changed | | custom3Changed | | check1Changed | | check2Changed | | check3Changed ) ;
2022-02-21 20:48:11 +01:00
2022-02-26 01:37:09 +01:00
// apply to main and all selected segments to prevent #1618.
2022-07-19 16:16:43 +02:00
for ( uint8_t i = 0 ; i < strip . getSegmentsNum ( ) ; i + + ) {
2022-07-06 13:13:54 +02:00
Segment & seg = strip . getSegment ( i ) ;
2022-02-22 10:42:00 +01:00
if ( i ! = selectedSeg & & ( singleSegment | | ! seg . isActive ( ) | | ! seg . isSelected ( ) ) ) continue ; // skip non main segments if not applying to all
2022-09-29 12:49:12 +02:00
if ( fxModeChanged ) seg . setMode ( effectIn , req . indexOf ( F ( " FXD= " ) ) > 0 ) ; // apply defaults if FXD= is specified
2022-02-22 10:42:00 +01:00
if ( speedChanged ) seg . speed = speedIn ;
2022-02-21 20:48:11 +01:00
if ( intensityChanged ) seg . intensity = intensityIn ;
2022-09-29 12:49:12 +02:00
if ( paletteChanged ) seg . setPalette ( paletteIn ) ;
2022-11-13 12:13:49 +01:00
if ( custom1Changed ) seg . custom1 = custom1In ;
if ( custom2Changed ) seg . custom2 = custom2In ;
if ( custom3Changed ) seg . custom3 = custom3In ;
if ( check1Changed ) seg . check1 = ( bool ) check1In ;
if ( check2Changed ) seg . check2 = ( bool ) check2In ;
if ( check3Changed ) seg . check3 = ( bool ) check3In ;
2022-02-20 22:24:11 +01:00
}
2018-11-09 17:00:36 +01:00
//set advanced overlay
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " OL= " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2018-11-25 00:00:02 +01:00
overlayCurrent = getNumVal ( & req , pos ) ;
2018-11-09 17:00:36 +01:00
}
2018-09-04 15:51:38 +02:00
2020-11-06 22:12:48 +01:00
//apply macro (deprecated, added for compatibility with pre-0.11 automations)
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " &M= " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2020-11-06 22:12:48 +01:00
applyPreset ( getNumVal ( & req , pos ) + 16 ) ;
2018-11-09 17:00:36 +01:00
}
2019-08-17 12:27:06 +02:00
2018-11-09 17:00:36 +01:00
//toggle send UDP direct notifications
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " SN= " ) ) ;
2019-02-22 22:53:33 +01:00
if ( pos > 0 ) notifyDirect = ( req . charAt ( pos + 3 ) ! = ' 0 ' ) ;
2019-08-17 12:27:06 +02:00
2018-11-09 17:00:36 +01:00
//toggle receive UDP direct notifications
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " RN= " ) ) ;
2019-02-22 22:53:33 +01:00
if ( pos > 0 ) receiveNotifications = ( req . charAt ( pos + 3 ) ! = ' 0 ' ) ;
2019-03-09 14:48:13 +01:00
//receive live data via UDP/Hyperion
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " RD= " ) ) ;
2019-03-09 14:48:13 +01:00
if ( pos > 0 ) receiveDirect = ( req . charAt ( pos + 3 ) ! = ' 0 ' ) ;
2019-08-17 12:27:06 +02:00
2020-10-02 12:30:17 +02:00
//main toggle on/off (parse before nightlight, #1214)
pos = req . indexOf ( F ( " &T= " ) ) ;
if ( pos > 0 ) {
nightlightActive = false ; //always disable nightlight when toggling
switch ( getNumVal ( & req , pos ) )
{
case 0 : if ( bri ! = 0 ) { briLast = bri ; bri = 0 ; } break ; //off, only if it was previously on
case 1 : if ( bri = = 0 ) bri = briLast ; break ; //on, only if it was previously off
default : toggleOnOff ( ) ; //toggle
}
}
2018-11-09 17:00:36 +01:00
//toggle nightlight mode
bool aNlDef = false ;
2020-09-20 01:18:31 +02:00
if ( req . indexOf ( F ( " &ND " ) ) > 0 ) aNlDef = true ;
pos = req . indexOf ( F ( " NL= " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 )
{
2019-02-22 22:53:33 +01:00
if ( req . charAt ( pos + 3 ) = = ' 0 ' )
2018-11-09 17:00:36 +01:00
{
nightlightActive = false ;
} else {
2018-04-15 15:27:54 +02:00
nightlightActive = true ;
2018-11-25 00:00:02 +01:00
if ( ! aNlDef ) nightlightDelayMins = getNumVal ( & req , pos ) ;
2022-11-04 08:33:55 +01:00
else nightlightDelayMins = nightlightDelayMinsDefault ;
2018-04-15 15:27:54 +02:00
nightlightStartTime = millis ( ) ;
2018-11-09 17:00:36 +01:00
}
} else if ( aNlDef )
{
nightlightActive = true ;
2022-11-04 08:33:55 +01:00
nightlightDelayMins = nightlightDelayMinsDefault ;
2018-11-09 17:00:36 +01:00
nightlightStartTime = millis ( ) ;
}
2019-08-17 12:27:06 +02:00
2018-11-09 17:00:36 +01:00
//set nightlight target brightness
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " NT= " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2018-11-25 00:00:02 +01:00
nightlightTargetBri = getNumVal ( & req , pos ) ;
2018-11-09 17:00:36 +01:00
nightlightActiveOld = false ; //re-init
}
2019-08-17 12:27:06 +02:00
2018-11-09 17:00:36 +01:00
//toggle nightlight fade
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " NF= " ) ) ;
2019-02-22 22:53:33 +01:00
if ( pos > 0 )
2018-11-09 17:00:36 +01:00
{
2020-06-22 12:30:31 +02:00
nightlightMode = getNumVal ( & req , pos ) ;
2018-11-09 17:00:36 +01:00
nightlightActiveOld = false ; //re-init
}
2020-06-22 12:30:31 +02:00
if ( nightlightMode > NL_MODE_SUN ) nightlightMode = NL_MODE_SUN ;
2019-02-25 19:14:13 +01:00
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " TT= " ) ) ;
2019-02-22 22:53:33 +01:00
if ( pos > 0 ) transitionDelay = getNumVal ( & req , pos ) ;
2018-11-09 17:00:36 +01:00
//set time (unix timestamp)
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " ST= " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2021-05-27 02:02:02 +02:00
setTimeFromAPI ( getNumVal ( & req , pos ) ) ;
2018-11-09 17:00:36 +01:00
}
2019-08-17 12:27:06 +02:00
2018-11-09 17:00:36 +01:00
//set countdown goal (unix timestamp)
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " CT= " ) ) ;
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2018-11-25 00:00:02 +01:00
countdownTime = getNumVal ( & req , pos ) ;
2021-05-25 09:59:19 +02:00
if ( countdownTime - toki . second ( ) > 0 ) countdownOverTriggered = false ;
2018-11-09 17:00:36 +01:00
}
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " LO= " ) ) ;
2020-06-22 12:30:31 +02:00
if ( pos > 0 ) {
realtimeOverride = getNumVal ( & req , pos ) ;
if ( realtimeOverride > 2 ) realtimeOverride = REALTIME_OVERRIDE_ALWAYS ;
2022-04-01 00:59:19 +02:00
if ( realtimeMode & & useMainSegmentOnly ) {
2022-08-19 21:14:49 +02:00
strip . getMainSegment ( ) . freeze = ! realtimeOverride ;
2022-04-01 00:59:19 +02:00
}
2020-06-22 12:30:31 +02:00
}
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " RB " ) ) ;
2020-04-30 01:52:36 +02:00
if ( pos > 0 ) doReboot = true ;
2022-03-06 23:47:36 +01:00
// clock mode, 0: normal, 1: countdown
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " NM= " ) ) ;
2020-01-01 01:04:54 +01:00
if ( pos > 0 ) countdownMode = ( req . charAt ( pos + 3 ) ! = ' 0 ' ) ;
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " U0= " ) ) ; //user var 0
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2018-11-25 00:00:02 +01:00
userVar0 = getNumVal ( & req , pos ) ;
2018-11-09 17:00:36 +01:00
}
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " U1= " ) ) ; //user var 1
2018-11-09 17:00:36 +01:00
if ( pos > 0 ) {
2018-11-25 00:00:02 +01:00
userVar1 = getNumVal ( & req , pos ) ;
2018-11-09 17:00:36 +01:00
}
2022-02-21 20:48:11 +01:00
// you can add more if you need
2019-08-17 12:27:06 +02:00
2022-02-21 20:48:11 +01:00
// global col[], effectCurrent, ... are updated in stateChanged()
if ( ! apply ) return true ; // when called by JSON API, do not call colorUpdated() here
2019-08-17 12:27:06 +02:00
2020-09-20 01:18:31 +02:00
pos = req . indexOf ( F ( " &NN " ) ) ; //do not send UDP notifications this time
2022-02-21 16:19:11 +01:00
stateUpdated ( ( pos > 0 ) ? CALL_MODE_NO_NOTIFY : CALL_MODE_DIRECT_CHANGE ) ;
2019-08-17 12:27:06 +02:00
2022-02-23 19:20:07 +01:00
// internal call, does not send XML response
pos = req . indexOf ( F ( " IN " ) ) ;
if ( pos < 1 ) XML_response ( request ) ;
2018-11-09 17:00:36 +01:00
return true ;
2016-11-19 19:39:17 +01:00
}