2020-11-04 10:04:40 +00:00
# include "wled.h"
2021-07-07 06:12:03 +00:00
# include "wled_ethernet.h"
2020-11-04 10:04:40 +00:00
/*
* Serializes and parses the cfg . json and wsec . json settings files , stored in internal FS .
* The structure of the JSON is not to be considered an official API and may change without notice .
*/
2025-04-22 20:37:18 +00:00
# ifndef PIXEL_COUNTS
# define PIXEL_COUNTS DEFAULT_LED_COUNT
# endif
# ifndef DATA_PINS
# define DATA_PINS DEFAULT_LED_PIN
# endif
# ifndef LED_TYPES
# define LED_TYPES DEFAULT_LED_TYPE
# endif
# ifndef DEFAULT_LED_COLOR_ORDER
# define DEFAULT_LED_COLOR_ORDER COL_ORDER_GRB //default to GRB
# endif
static constexpr unsigned sumPinsRequired ( const unsigned * current , size_t count ) {
return ( count > 0 ) ? ( Bus : : getNumberOfPins ( * current ) + sumPinsRequired ( current + 1 , count - 1 ) ) : 0 ;
}
static constexpr bool validatePinsAndTypes ( const unsigned * types , unsigned numTypes , unsigned numPins ) {
// Pins provided < pins required -> always invalid
// Pins provided = pins required -> always valid
// Pins provided > pins required -> valid if excess pins are a product of last type pins since it will be repeated
return ( sumPinsRequired ( types , numTypes ) > numPins ) ? false :
( numPins - sumPinsRequired ( types , numTypes ) ) % Bus : : getNumberOfPins ( types [ numTypes - 1 ] ) = = 0 ;
}
2020-11-04 10:04:40 +00:00
//simple macro for ArduinoJSON's or syntax
# define CJSON(a,b) a = b | a
void getStringFromJson ( char * dest , const char * src , size_t len ) {
if ( src ! = nullptr ) strlcpy ( dest , src , len ) ;
}
2021-05-10 23:11:16 +00:00
bool deserializeConfig ( JsonObject doc , bool fromFS ) {
2021-11-03 13:52:22 +00:00
bool needsSave = false ;
2021-03-04 11:10:18 +00:00
//int rev_major = doc["rev"][0]; // 1
//int rev_minor = doc["rev"][1]; // 0
2020-11-04 10:04:40 +00:00
2020-11-07 22:54:56 +00:00
//long vid = doc[F("vid")]; // 2010020
2020-11-04 10:04:40 +00:00
2025-04-22 20:37:18 +00:00
# ifdef WLED_USE_ETHERNET
2021-08-23 12:14:48 +00:00
JsonObject ethernet = doc [ F ( " eth " ) ] ;
CJSON ( ethernetType , ethernet [ " type " ] ) ;
// NOTE: Ethernet configuration takes priority over other use of pins
2024-12-21 18:02:24 +00:00
initEthernet ( ) ;
2024-08-17 13:09:41 +00:00
# endif
2021-08-23 12:14:48 +00:00
2021-03-13 21:04:37 +00:00
JsonObject id = doc [ " id " ] ;
2020-11-07 22:54:56 +00:00
getStringFromJson ( cmDNS , id [ F ( " mdns " ) ] , 33 ) ;
getStringFromJson ( serverDescription , id [ F ( " name " ) ] , 33 ) ;
2024-08-17 13:09:41 +00:00
# ifndef WLED_DISABLE_ALEXA
2020-11-07 22:54:56 +00:00
getStringFromJson ( alexaInvocationName , id [ F ( " inv " ) ] , 33 ) ;
2024-08-17 13:09:41 +00:00
# endif
2021-08-10 15:11:17 +00:00
CJSON ( simplifiedUI , id [ F ( " sui " ) ] ) ;
2020-11-04 10:04:40 +00:00
2023-09-10 16:52:14 +00:00
JsonObject nw = doc [ " nw " ] ;
# ifndef WLED_DISABLE_ESPNOW
CJSON ( enableESPNow , nw [ F ( " espnow " ) ] ) ;
2025-05-19 18:34:27 +00:00
linked_remotes . clear ( ) ;
JsonVariant lrem = nw [ F ( " linked_remote " ) ] ;
if ( ! lrem . isNull ( ) ) {
if ( lrem . is < JsonArray > ( ) ) {
for ( size_t i = 0 ; i < lrem . size ( ) ; i + + ) {
std : : array < char , 13 > entry { } ;
getStringFromJson ( entry . data ( ) , lrem [ i ] , 13 ) ;
entry [ 12 ] = ' \0 ' ;
linked_remotes . emplace_back ( entry ) ;
}
}
else { // legacy support for single MAC address in config
std : : array < char , 13 > entry { } ;
getStringFromJson ( entry . data ( ) , lrem , 13 ) ;
entry [ 12 ] = ' \0 ' ;
linked_remotes . emplace_back ( entry ) ;
}
}
2023-09-10 16:52:14 +00:00
# endif
2024-01-20 23:30:15 +00:00
size_t n = 0 ;
JsonArray nw_ins = nw [ " ins " ] ;
if ( ! nw_ins . isNull ( ) ) {
// as password are stored separately in wsec.json when reading configuration vector resize happens there, but for dynamic config we need to resize if necessary
if ( nw_ins . size ( ) > 1 & & nw_ins . size ( ) > multiWiFi . size ( ) ) multiWiFi . resize ( nw_ins . size ( ) ) ; // resize constructs objects while resizing
for ( JsonObject wifi : nw_ins ) {
JsonArray ip = wifi [ " ip " ] ;
JsonArray gw = wifi [ " gw " ] ;
JsonArray sn = wifi [ " sn " ] ;
char ssid [ 33 ] = " " ;
char pass [ 65 ] = " " ;
2024-12-21 18:02:24 +00:00
char bssid [ 13 ] = " " ;
2024-01-20 23:30:15 +00:00
IPAddress nIP = ( uint32_t ) 0U , nGW = ( uint32_t ) 0U , nSN = ( uint32_t ) 0x00FFFFFF ; // little endian
getStringFromJson ( ssid , wifi [ F ( " ssid " ) ] , 33 ) ;
getStringFromJson ( pass , wifi [ " psk " ] , 65 ) ; // password is not normally present but if it is, use it
2024-12-21 18:02:24 +00:00
getStringFromJson ( bssid , wifi [ F ( " bssid " ) ] , 13 ) ;
2024-01-20 23:30:15 +00:00
for ( size_t i = 0 ; i < 4 ; i + + ) {
CJSON ( nIP [ i ] , ip [ i ] ) ;
CJSON ( nGW [ i ] , gw [ i ] ) ;
CJSON ( nSN [ i ] , sn [ i ] ) ;
}
if ( strlen ( ssid ) > 0 ) strlcpy ( multiWiFi [ n ] . clientSSID , ssid , 33 ) ; // this will keep old SSID intact if not present in JSON
if ( strlen ( pass ) > 0 ) strlcpy ( multiWiFi [ n ] . clientPass , pass , 65 ) ; // this will keep old password intact if not present in JSON
2024-12-21 18:02:24 +00:00
if ( strlen ( bssid ) > 0 ) fillStr2MAC ( multiWiFi [ n ] . bssid , bssid ) ;
2024-01-20 23:30:15 +00:00
multiWiFi [ n ] . staticIP = nIP ;
multiWiFi [ n ] . staticGW = nGW ;
multiWiFi [ n ] . staticSN = nSN ;
if ( + + n > = WLED_MAX_WIFI_COUNT ) break ;
}
}
2020-11-04 10:04:40 +00:00
2024-01-20 23:30:15 +00:00
JsonArray dns = nw [ F ( " dns " ) ] ;
if ( ! dns . isNull ( ) ) {
for ( size_t i = 0 ; i < 4 ; i + + ) {
CJSON ( dnsAddress [ i ] , dns [ i ] ) ;
}
2020-11-04 10:04:40 +00:00
}
2021-03-13 21:04:37 +00:00
JsonObject ap = doc [ " ap " ] ;
2020-11-07 22:54:56 +00:00
getStringFromJson ( apSSID , ap [ F ( " ssid " ) ] , 33 ) ;
2020-11-04 10:04:40 +00:00
getStringFromJson ( apPass , ap [ " psk " ] , 65 ) ; //normally not present due to security
2020-11-07 22:54:56 +00:00
//int ap_pskl = ap[F("pskl")];
CJSON ( apChannel , ap [ F ( " chan " ) ] ) ;
2020-11-04 10:04:40 +00:00
if ( apChannel > 13 | | apChannel < 1 ) apChannel = 1 ;
2020-11-07 22:54:56 +00:00
CJSON ( apHide , ap [ F ( " hide " ) ] ) ;
2020-11-04 10:04:40 +00:00
if ( apHide > 1 ) apHide = 1 ;
2020-11-07 22:54:56 +00:00
CJSON ( apBehavior , ap [ F ( " behav " ) ] ) ;
2020-11-04 10:04:40 +00:00
/*
2021-03-13 21:04:37 +00:00
JsonArray ap_ip = ap [ " ip " ] ;
2024-07-11 19:22:58 +00:00
for ( unsigned i = 0 ; i < 4 ; i + + ) {
2020-11-04 10:04:40 +00:00
apIP [ i ] = ap_ip ;
2021-03-03 21:04:24 +00:00
}
*/
2020-11-04 10:04:40 +00:00
2024-06-23 12:08:18 +00:00
JsonObject wifi = doc [ F ( " wifi " ) ] ;
noWifiSleep = ! ( wifi [ F ( " sleep " ) ] | ! noWifiSleep ) ; // inverted
//noWifiSleep = !noWifiSleep;
CJSON ( force802_3g , wifi [ F ( " phy " ) ] ) ; //force phy mode g?
# ifdef ARDUINO_ARCH_ESP32
CJSON ( txPower , wifi [ F ( " txpwr " ) ] ) ;
txPower = min ( max ( ( int ) txPower , ( int ) WIFI_POWER_2dBm ) , ( int ) WIFI_POWER_19_5dBm ) ;
# endif
2020-11-04 10:04:40 +00:00
2020-11-07 22:54:56 +00:00
JsonObject hw = doc [ F ( " hw " ) ] ;
2020-11-04 10:04:40 +00:00
2021-08-23 12:14:48 +00:00
// initialize LED pins and lengths prior to other HW (except for ethernet)
2022-02-04 09:10:37 +00:00
JsonObject hw_led = hw [ " led " ] ;
2020-11-04 10:04:40 +00:00
2023-11-15 18:37:07 +00:00
uint16_t total = hw_led [ F ( " total " ) ] | strip . getLengthTotal ( ) ;
2023-12-29 22:07:29 +00:00
uint16_t ablMilliampsMax = hw_led [ F ( " maxpwr " ) ] | BusManager : : ablMilliampsMax ( ) ;
BusManager : : setMilliampsMax ( ablMilliampsMax ) ;
2023-12-09 18:03:33 +00:00
Bus : : setGlobalAWMode ( hw_led [ F ( " rgbwm " ) ] | AW_GLOBAL_DISABLED ) ;
2024-08-17 13:09:41 +00:00
CJSON ( strip . correctWB , hw_led [ " cct " ] ) ;
CJSON ( strip . cctFromRgb , hw_led [ F ( " cr " ) ] ) ;
2024-03-28 15:03:06 +00:00
CJSON ( cctICused , hw_led [ F ( " ic " ) ] ) ;
2024-04-08 14:24:27 +00:00
uint8_t cctBlending = hw_led [ F ( " cb " ) ] | Bus : : getCCTBlend ( ) ;
Bus : : setCCTBlend ( cctBlending ) ;
2022-03-08 01:16:33 +00:00
strip . setTargetFps ( hw_led [ " fps " ] ) ; //NOP if 0, default 42 FPS
2025-01-12 14:17:22 +00:00
# if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
CJSON ( useParallelI2S , hw_led [ F ( " prl " ) ] ) ;
# endif
2020-11-04 10:04:40 +00:00
2022-07-10 20:23:25 +00:00
# ifndef WLED_DISABLE_2D
2022-05-08 08:50:48 +00:00
// 2D Matrix Settings
JsonObject matrix = hw_led [ F ( " matrix " ) ] ;
if ( ! matrix . isNull ( ) ) {
strip . isMatrix = true ;
2025-04-22 20:37:18 +00:00
unsigned numPanels = matrix [ F ( " mpc " ) ] | 1 ;
numPanels = constrain ( numPanels , 1 , WLED_MAX_PANELS ) ;
2023-01-02 19:56:00 +00:00
strip . panel . clear ( ) ;
2022-05-08 08:50:48 +00:00
JsonArray panels = matrix [ F ( " panels " ) ] ;
2025-04-22 20:37:18 +00:00
unsigned s = 0 ;
2022-05-08 08:50:48 +00:00
if ( ! panels . isNull ( ) ) {
2025-04-22 20:37:18 +00:00
strip . panel . reserve ( numPanels ) ; // pre-allocate default 8x8 panels
2022-05-08 08:50:48 +00:00
for ( JsonObject pnl : panels ) {
2023-01-02 19:56:00 +00:00
WS2812FX : : Panel p ;
CJSON ( p . bottomStart , pnl [ " b " ] ) ;
CJSON ( p . rightStart , pnl [ " r " ] ) ;
CJSON ( p . vertical , pnl [ " v " ] ) ;
CJSON ( p . serpentine , pnl [ " s " ] ) ;
CJSON ( p . xOffset , pnl [ " x " ] ) ;
CJSON ( p . yOffset , pnl [ " y " ] ) ;
CJSON ( p . height , pnl [ " h " ] ) ;
CJSON ( p . width , pnl [ " w " ] ) ;
strip . panel . push_back ( p ) ;
2025-04-22 20:37:18 +00:00
if ( + + s > = numPanels ) break ; // max panels reached
2022-05-08 08:50:48 +00:00
}
}
2025-04-22 20:37:18 +00:00
strip . panel . shrink_to_fit ( ) ; // release unused memory (just in case)
// cannot call strip.deserializeLedmap()/strip.setUpMatrix() here due to already locked JSON buffer
//if (!fromFS) doInit2D = true; // if called at boot (fromFS==true), WLED::beginStrip() will take care of setting up matrix
2022-05-08 08:50:48 +00:00
}
2022-07-10 20:23:25 +00:00
# endif
2022-05-08 08:50:48 +00:00
2025-04-22 20:37:18 +00:00
DEBUG_PRINTF_P ( PSTR ( " Heap before buses: %d \n " ) , ESP . getFreeHeap ( ) ) ;
2021-01-30 23:38:27 +00:00
JsonArray ins = hw_led [ " ins " ] ;
2025-04-22 20:37:18 +00:00
if ( ! ins . isNull ( ) ) {
2024-05-12 09:12:13 +00:00
int s = 0 ; // bus iterator
2021-05-10 23:11:16 +00:00
for ( JsonObject elm : ins ) {
2025-04-22 20:37:18 +00:00
if ( s > = WLED_MAX_BUSSES ) break ; // only counts physical buses
2021-05-10 23:11:16 +00:00
uint8_t pins [ 5 ] = { 255 , 255 , 255 , 255 , 255 } ;
2021-05-18 13:45:34 +00:00
JsonArray pinArr = elm [ " pin " ] ;
2021-05-10 23:11:16 +00:00
if ( pinArr . size ( ) = = 0 ) continue ;
2024-07-07 12:18:51 +00:00
//pins[0] = pinArr[0];
2024-06-12 16:00:00 +00:00
unsigned i = 0 ;
2021-05-10 23:11:16 +00:00
for ( int p : pinArr ) {
2021-05-18 13:45:34 +00:00
pins [ i + + ] = p ;
2021-05-10 23:11:16 +00:00
if ( i > 4 ) break ;
}
2022-02-04 09:10:37 +00:00
uint16_t length = elm [ " len " ] | 1 ;
2023-12-09 18:03:33 +00:00
uint8_t colorOrder = ( int ) elm [ F ( " order " ) ] ; // contains white channel swap option in upper nibble
2021-05-17 14:23:46 +00:00
uint8_t skipFirst = elm [ F ( " skip " ) ] ;
2021-09-11 23:15:51 +00:00
uint16_t start = elm [ " start " ] | 0 ;
2021-10-11 00:19:33 +00:00
if ( length = = 0 | | start + length > MAX_LEDS ) continue ; // zero length or we reached max. number of LEDs, just stop
2021-05-10 23:11:16 +00:00
uint8_t ledType = elm [ " type " ] | TYPE_WS2812_RGB ;
bool reversed = elm [ " rev " ] ;
2021-10-07 20:57:07 +00:00
bool refresh = elm [ " ref " ] | false ;
2024-03-07 19:21:56 +00:00
uint16_t freqkHz = elm [ F ( " freq " ) ] | 0 ; // will be in kHz for DotStar and Hz for PWM
2023-12-09 18:03:33 +00:00
uint8_t AWmode = elm [ F ( " rgbwm " ) ] | RGBW_MODE_MANUAL_ONLY ;
2024-07-07 12:18:51 +00:00
uint8_t maPerLed = elm [ F ( " ledma " ) ] | LED_MILLIAMPS_DEFAULT ;
2023-12-29 22:07:29 +00:00
uint16_t maMax = elm [ F ( " maxpwr " ) ] | ( ablMilliampsMax * length ) / total ; // rough (incorrect?) per strip ABL calculation when no config exists
2023-11-15 18:37:07 +00:00
// To disable brightness limiter we either set output max current to 0 or single LED current to 0 (we choose output max current)
2024-08-24 09:35:32 +00:00
if ( Bus : : isPWM ( ledType ) | | Bus : : isOnOff ( ledType ) | | Bus : : isVirtual ( ledType ) ) { // analog and virtual
2023-11-15 18:37:07 +00:00
maPerLed = 0 ;
maMax = 0 ;
}
2023-12-02 11:15:57 +00:00
ledType | = refresh < < 7 ; // hack bit 7 to indicate strip requires off refresh
2025-01-22 19:33:56 +00:00
2025-04-22 20:37:18 +00:00
busConfigs . emplace_back ( ledType , pins , start , length , colorOrder , reversed , skipFirst , AWmode , freqkHz , maPerLed , maMax ) ;
2025-01-22 19:33:56 +00:00
doInitBusses = true ; // finalization done in beginStrip()
if ( ! Bus : : isVirtual ( ledType ) ) s + + ; // have as many virtual buses as you want
2021-01-30 23:38:27 +00:00
}
2025-04-22 20:37:18 +00:00
} else if ( fromFS ) {
//if busses failed to load, add default (fresh install, FS issue, ...)
BusManager : : removeAll ( ) ;
busConfigs . clear ( ) ;
DEBUG_PRINTLN ( F ( " No busses, init default " ) ) ;
constexpr unsigned defDataTypes [ ] = { LED_TYPES } ;
constexpr unsigned defDataPins [ ] = { DATA_PINS } ;
constexpr unsigned defCounts [ ] = { PIXEL_COUNTS } ;
constexpr unsigned defNumTypes = ( sizeof ( defDataTypes ) / sizeof ( defDataTypes [ 0 ] ) ) ;
constexpr unsigned defNumPins = ( sizeof ( defDataPins ) / sizeof ( defDataPins [ 0 ] ) ) ;
constexpr unsigned defNumCounts = ( sizeof ( defCounts ) / sizeof ( defCounts [ 0 ] ) ) ;
static_assert ( validatePinsAndTypes ( defDataTypes , defNumTypes , defNumPins ) ,
" The default pin list defined in DATA_PINS does not match the pin requirements for the default buses defined in LED_TYPES " ) ;
unsigned mem = 0 ;
unsigned pinsIndex = 0 ;
unsigned digitalCount = 0 ;
for ( unsigned i = 0 ; i < WLED_MAX_BUSSES ; i + + ) {
uint8_t defPin [ OUTPUT_MAX_PINS ] ;
// if we have less types than requested outputs and they do not align, use last known type to set current type
unsigned dataType = defDataTypes [ ( i < defNumTypes ) ? i : defNumTypes - 1 ] ;
unsigned busPins = Bus : : getNumberOfPins ( dataType ) ;
// if we need more pins than available all outputs have been configured
if ( pinsIndex + busPins > defNumPins ) break ;
// Assign all pins first so we can check for conflicts on this bus
for ( unsigned j = 0 ; j < busPins & & j < OUTPUT_MAX_PINS ; j + + ) defPin [ j ] = defDataPins [ pinsIndex + j ] ;
for ( unsigned j = 0 ; j < busPins & & j < OUTPUT_MAX_PINS ; j + + ) {
bool validPin = true ;
// When booting without config (1st boot) we need to make sure GPIOs defined for LED output don't clash with hardware
// i.e. DEBUG (GPIO1), DMX (2), SPI RAM/FLASH (16&17 on ESP32-WROVER/PICO), read/only pins, etc.
// Pin should not be already allocated, read/only or defined for current bus
while ( PinManager : : isPinAllocated ( defPin [ j ] ) | | ! PinManager : : isPinOk ( defPin [ j ] , true ) ) {
if ( validPin ) {
DEBUG_PRINTLN ( F ( " Some of the provided pins cannot be used to configure this LED output. " ) ) ;
defPin [ j ] = 1 ; // start with GPIO1 and work upwards
validPin = false ;
} else if ( defPin [ j ] < WLED_NUM_PINS ) {
defPin [ j ] + + ;
} else {
DEBUG_PRINTLN ( F ( " No available pins left! Can't configure output. " ) ) ;
break ;
}
// is the newly assigned pin already defined or used previously?
// try next in line until there are no clashes or we run out of pins
bool clash ;
do {
clash = false ;
// check for conflicts on current bus
for ( const auto & pin : defPin ) {
if ( & pin ! = & defPin [ j ] & & pin = = defPin [ j ] ) {
clash = true ;
break ;
}
}
// We already have a clash on current bus, no point checking next buses
if ( ! clash ) {
// check for conflicts in defined pins
for ( const auto & pin : defDataPins ) {
if ( pin = = defPin [ j ] ) {
clash = true ;
break ;
}
}
}
if ( clash ) defPin [ j ] + + ;
if ( defPin [ j ] > = WLED_NUM_PINS ) break ;
} while ( clash ) ;
}
}
pinsIndex + = busPins ;
// if we have less counts than pins and they do not align, use last known count to set current count
unsigned count = defCounts [ ( i < defNumCounts ) ? i : defNumCounts - 1 ] ;
unsigned start = 0 ;
// analog always has length 1
if ( Bus : : isPWM ( dataType ) | | Bus : : isOnOff ( dataType ) ) count = 1 ;
BusConfig defCfg = BusConfig ( dataType , defPin , start , count , DEFAULT_LED_COLOR_ORDER , false , 0 , RGBW_MODE_MANUAL_ONLY , 0 ) ;
mem + = defCfg . memUsage ( Bus : : isDigital ( dataType ) & & ! Bus : : is2Pin ( dataType ) ? digitalCount + + : 0 ) ;
if ( mem > MAX_LED_MEMORY ) {
DEBUG_PRINTF_P ( PSTR ( " Out of LED memory! Bus %d (%d) #%u not created. " ) , ( int ) dataType , ( int ) count , digitalCount ) ;
break ;
}
busConfigs . push_back ( defCfg ) ; // use push_back for simplification as we needed defCfg to calculate memory usage
doInitBusses = true ; // finalization done in beginStrip()
}
DEBUG_PRINTF_P ( PSTR ( " LED buffer size: %uB/%uB \n " ) , mem , BusManager : : memUsage ( ) ) ;
2021-01-30 23:38:27 +00:00
}
2025-01-21 19:14:20 +00:00
if ( hw_led [ " rev " ] & & BusManager : : getNumBusses ( ) ) BusManager : : getBus ( 0 ) - > setReversed ( true ) ; //set 0.11 global reversed setting for first bus
2020-11-04 10:04:40 +00:00
2021-12-31 20:35:27 +00:00
// read color order map configuration
JsonArray hw_com = hw [ F ( " com " ) ] ;
if ( ! hw_com . isNull ( ) ) {
2024-09-11 14:45:39 +00:00
BusManager : : getColorOrderMap ( ) . reserve ( std : : min ( hw_com . size ( ) , ( size_t ) WLED_MAX_COLOR_ORDER_MAPPINGS ) ) ;
2021-12-31 20:35:27 +00:00
for ( JsonObject entry : hw_com ) {
2022-02-04 09:10:37 +00:00
uint16_t start = entry [ " start " ] | 0 ;
uint16_t len = entry [ " len " ] | 0 ;
2021-12-31 20:35:27 +00:00
uint8_t colorOrder = ( int ) entry [ F ( " order " ) ] ;
2024-08-22 15:15:12 +00:00
if ( ! BusManager : : getColorOrderMap ( ) . add ( start , len , colorOrder ) ) break ;
2021-12-31 20:35:27 +00:00
}
}
2021-05-19 16:39:16 +00:00
// read multiple button configuration
2021-07-01 18:51:52 +00:00
JsonObject btn_obj = hw [ " btn " ] ;
2024-02-18 14:52:36 +00:00
CJSON ( touchThreshold , btn_obj [ F ( " tt " ) ] ) ;
2023-01-03 16:36:24 +00:00
bool pull = btn_obj [ F ( " pull " ) ] | ( ! disablePullUp ) ; // if true, pullup is enabled
2023-01-03 16:15:55 +00:00
disablePullUp = ! pull ;
2024-01-20 23:30:15 +00:00
JsonArray hw_btn_ins = btn_obj [ " ins " ] ;
2021-05-19 16:39:16 +00:00
if ( ! hw_btn_ins . isNull ( ) ) {
2024-06-12 16:00:00 +00:00
// deallocate existing button pins
2024-09-19 19:44:11 +00:00
for ( unsigned b = 0 ; b < WLED_MAX_BUTTONS ; b + + ) PinManager : : deallocatePin ( btnPin [ b ] , PinOwner : : Button ) ; // does nothing if trying to deallocate a pin with PinOwner != Button
2024-06-12 16:00:00 +00:00
unsigned s = 0 ;
2021-05-19 16:39:16 +00:00
for ( JsonObject btn : hw_btn_ins ) {
CJSON ( buttonType [ s ] , btn [ " type " ] ) ;
2021-06-30 10:33:51 +00:00
int8_t pin = btn [ " pin " ] [ 0 ] | - 1 ;
2024-09-19 19:44:11 +00:00
if ( pin > - 1 & & PinManager : : allocatePin ( pin , false , PinOwner : : Button ) ) {
2021-05-21 22:13:49 +00:00
btnPin [ s ] = pin ;
2022-12-10 18:16:02 +00:00
# ifdef ARDUINO_ARCH_ESP32
// ESP32 only: check that analog button pin is a valid ADC gpio
2024-07-07 12:18:51 +00:00
if ( ( buttonType [ s ] = = BTN_TYPE_ANALOG ) | | ( buttonType [ s ] = = BTN_TYPE_ANALOG_INVERTED ) ) {
if ( digitalPinToAnalogChannel ( btnPin [ s ] ) < 0 ) {
// not an ADC analog pin
2024-09-10 13:20:34 +00:00
DEBUG_PRINTF_P ( PSTR ( " PIN ALLOC error: GPIO%d for analog button #%d is not an analog pin! \n " ) , btnPin [ s ] , s ) ;
2024-07-07 12:18:51 +00:00
btnPin [ s ] = - 1 ;
2024-09-19 19:44:11 +00:00
PinManager : : deallocatePin ( pin , PinOwner : : Button ) ;
2024-07-07 12:18:51 +00:00
} else {
analogReadResolution ( 12 ) ; // see #4040
}
2023-01-06 08:24:29 +00:00
}
2024-07-07 12:18:51 +00:00
else if ( ( buttonType [ s ] = = BTN_TYPE_TOUCH | | buttonType [ s ] = = BTN_TYPE_TOUCH_SWITCH ) )
2024-04-07 20:15:58 +00:00
{
2024-07-07 12:18:51 +00:00
if ( digitalPinToTouchChannel ( btnPin [ s ] ) < 0 ) {
// not a touch pin
2024-09-10 13:20:34 +00:00
DEBUG_PRINTF_P ( PSTR ( " PIN ALLOC error: GPIO%d for touch button #%d is not a touch pin! \n " ) , btnPin [ s ] , s ) ;
2024-07-07 12:18:51 +00:00
btnPin [ s ] = - 1 ;
2024-09-19 19:44:11 +00:00
PinManager : : deallocatePin ( pin , PinOwner : : Button ) ;
2024-07-07 12:18:51 +00:00
}
//if touch pin, enable the touch interrupt on ESP32 S2 & S3
# ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a function to check touch state but need to attach an interrupt to do so
else
{
2024-08-01 17:49:47 +00:00
touchAttachInterrupt ( btnPin [ s ] , touchButtonISR , touchThreshold < < 4 ) ; // threshold on Touch V2 is much higher (1500 is a value given by Espressif example, I measured changes of over 5000)
2024-07-07 12:18:51 +00:00
}
# endif
2024-04-07 20:15:58 +00:00
}
2023-01-06 08:24:29 +00:00
else
2022-12-10 18:16:02 +00:00
# endif
{
if ( disablePullUp ) {
pinMode ( btnPin [ s ] , INPUT ) ;
} else {
# ifdef ESP32
pinMode ( btnPin [ s ] , buttonType [ s ] = = BTN_TYPE_PUSH_ACT_HIGH ? INPUT_PULLDOWN : INPUT_PULLUP ) ;
# else
pinMode ( btnPin [ s ] , INPUT_PULLUP ) ;
# endif
}
2022-11-26 22:56:55 +00:00
}
2021-05-21 22:13:49 +00:00
} else {
btnPin [ s ] = - 1 ;
2021-05-19 16:39:16 +00:00
}
2021-07-01 18:51:52 +00:00
JsonArray hw_btn_ins_0_macros = btn [ " macros " ] ;
2021-05-19 16:39:16 +00:00
CJSON ( macroButton [ s ] , hw_btn_ins_0_macros [ 0 ] ) ;
CJSON ( macroLongPress [ s ] , hw_btn_ins_0_macros [ 1 ] ) ;
CJSON ( macroDoublePress [ s ] , hw_btn_ins_0_macros [ 2 ] ) ;
if ( + + s > = WLED_MAX_BUTTONS ) break ; // max buttons reached
}
// clear remaining buttons
for ( ; s < WLED_MAX_BUTTONS ; s + + ) {
btnPin [ s ] = - 1 ;
buttonType [ s ] = BTN_TYPE_NONE ;
macroButton [ s ] = 0 ;
macroLongPress [ s ] = 0 ;
macroDoublePress [ s ] = 0 ;
}
2025-04-22 20:37:18 +00:00
} else if ( fromFS ) {
2021-05-20 04:45:02 +00:00
// new install/missing configuration (button 0 has defaults)
2025-04-22 20:37:18 +00:00
// relies upon only being called once with fromFS == true, which is currently true.
for ( size_t s = 0 ; s < WLED_MAX_BUTTONS ; s + + ) {
if ( buttonType [ s ] = = BTN_TYPE_NONE | | btnPin [ s ] < 0 | | ! PinManager : : allocatePin ( btnPin [ s ] , false , PinOwner : : Button ) ) {
btnPin [ s ] = - 1 ;
buttonType [ s ] = BTN_TYPE_NONE ;
}
if ( btnPin [ s ] > = 0 ) {
if ( disablePullUp ) {
pinMode ( btnPin [ s ] , INPUT ) ;
} else {
# ifdef ESP32
pinMode ( btnPin [ s ] , buttonType [ s ] = = BTN_TYPE_PUSH_ACT_HIGH ? INPUT_PULLDOWN : INPUT_PULLUP ) ;
# else
pinMode ( btnPin [ s ] , INPUT_PULLUP ) ;
# endif
2024-03-05 15:27:28 +00:00
}
2021-05-20 04:45:02 +00:00
}
2025-04-22 20:37:18 +00:00
macroButton [ s ] = 0 ;
macroLongPress [ s ] = 0 ;
macroDoublePress [ s ] = 0 ;
2021-07-07 08:18:00 +00:00
}
2021-05-19 16:39:16 +00:00
}
2024-02-18 14:52:36 +00:00
2021-07-01 18:51:52 +00:00
CJSON ( buttonPublishMqtt , btn_obj [ " mqtt " ] ) ;
2020-11-04 10:04:40 +00:00
2024-03-05 15:27:28 +00:00
# ifndef WLED_DISABLE_INFRARED
2021-05-10 23:11:16 +00:00
int hw_ir_pin = hw [ " ir " ] [ " pin " ] | - 2 ; // 4
if ( hw_ir_pin > - 2 ) {
2024-09-19 19:44:11 +00:00
PinManager : : deallocatePin ( irPin , PinOwner : : IR ) ;
if ( PinManager : : allocatePin ( hw_ir_pin , false , PinOwner : : IR ) ) {
2021-05-10 23:11:16 +00:00
irPin = hw_ir_pin ;
} else {
irPin = - 1 ;
}
2021-01-16 23:20:31 +00:00
}
2021-03-13 21:04:37 +00:00
CJSON ( irEnabled , hw [ " ir " ] [ " type " ] ) ;
2024-03-05 15:27:28 +00:00
# endif
2022-02-06 23:40:45 +00:00
CJSON ( irApplyToAllSelected , hw [ " ir " ] [ " sel " ] ) ;
2021-01-16 23:20:31 +00:00
2021-03-04 13:24:25 +00:00
JsonObject relay = hw [ F ( " relay " ) ] ;
2024-04-21 11:37:07 +00:00
2024-04-21 18:02:00 +00:00
rlyOpenDrain = relay [ F ( " odrain " ) ] | rlyOpenDrain ;
2021-05-10 23:11:16 +00:00
int hw_relay_pin = relay [ " pin " ] | - 2 ;
if ( hw_relay_pin > - 2 ) {
2024-09-19 19:44:11 +00:00
PinManager : : deallocatePin ( rlyPin , PinOwner : : Relay ) ;
if ( PinManager : : allocatePin ( hw_relay_pin , true , PinOwner : : Relay ) ) {
2021-05-10 23:11:16 +00:00
rlyPin = hw_relay_pin ;
2024-04-21 11:37:07 +00:00
pinMode ( rlyPin , rlyOpenDrain ? OUTPUT_OPEN_DRAIN : OUTPUT ) ;
2021-05-10 23:11:16 +00:00
} else {
rlyPin = - 1 ;
}
2021-01-16 23:20:31 +00:00
}
2021-03-04 13:24:25 +00:00
if ( relay . containsKey ( " rev " ) ) {
2021-03-04 11:10:18 +00:00
rlyMde = ! relay [ " rev " ] ;
2021-03-04 13:24:25 +00:00
}
2020-11-04 10:04:40 +00:00
2022-02-01 19:02:46 +00:00
CJSON ( serialBaud , hw [ F ( " baud " ) ] ) ;
if ( serialBaud < 96 | | serialBaud > 15000 ) serialBaud = 1152 ;
updateBaudRate ( serialBaud * 100 ) ;
2022-08-07 14:43:29 +00:00
JsonArray hw_if_i2c = hw [ F ( " if " ) ] [ F ( " i2c-pin " ) ] ;
CJSON ( i2c_sda , hw_if_i2c [ 0 ] ) ;
CJSON ( i2c_scl , hw_if_i2c [ 1 ] ) ;
PinManagerPinType i2c [ 2 ] = { { i2c_sda , true } , { i2c_scl , true } } ;
2024-09-19 19:44:11 +00:00
if ( i2c_scl > = 0 & & i2c_sda > = 0 & & PinManager : : allocateMultiplePins ( i2c , 2 , PinOwner : : HW_I2C ) ) {
2022-08-07 14:43:29 +00:00
# ifdef ESP32
2024-02-06 13:47:20 +00:00
if ( ! Wire . setPins ( i2c_sda , i2c_scl ) ) { i2c_scl = i2c_sda = - 1 ; } // this will fail if Wire is initialised (Wire.begin() called prior)
2023-05-30 17:36:14 +00:00
else Wire . begin ( ) ;
# else
Wire . begin ( i2c_sda , i2c_scl ) ;
2022-08-07 14:43:29 +00:00
# endif
} else {
i2c_sda = - 1 ;
i2c_scl = - 1 ;
}
JsonArray hw_if_spi = hw [ F ( " if " ) ] [ F ( " spi-pin " ) ] ;
CJSON ( spi_mosi , hw_if_spi [ 0 ] ) ;
CJSON ( spi_sclk , hw_if_spi [ 1 ] ) ;
2022-08-25 19:57:43 +00:00
CJSON ( spi_miso , hw_if_spi [ 2 ] ) ;
PinManagerPinType spi [ 3 ] = { { spi_mosi , true } , { spi_miso , true } , { spi_sclk , true } } ;
2024-09-19 19:44:11 +00:00
if ( spi_mosi > = 0 & & spi_sclk > = 0 & & PinManager : : allocateMultiplePins ( spi , 3 , PinOwner : : HW_SPI ) ) {
2022-09-09 15:16:52 +00:00
# ifdef ESP32
SPI . begin ( spi_sclk , spi_miso , spi_mosi ) ; // SPI global uses VSPI on ESP32 and FSPI on C3, S3
# else
SPI . begin ( ) ;
# endif
2022-08-07 14:43:29 +00:00
} else {
spi_mosi = - 1 ;
2022-08-25 19:57:43 +00:00
spi_miso = - 1 ;
2022-08-07 14:43:29 +00:00
spi_sclk = - 1 ;
}
2021-03-14 10:41:55 +00:00
//int hw_status_pin = hw[F("status")]["pin"]; // -1
2020-11-04 10:04:40 +00:00
2020-11-07 22:54:56 +00:00
JsonObject light = doc [ F ( " light " ) ] ;
CJSON ( briMultiplier , light [ F ( " scale-bri " ) ] ) ;
2025-04-22 20:37:18 +00:00
CJSON ( paletteBlend , light [ F ( " pal-mode " ) ] ) ;
2024-08-17 13:09:41 +00:00
CJSON ( strip . autoSegments , light [ F ( " aseg " ) ] ) ;
2025-04-22 20:37:18 +00:00
CJSON ( useRainbowWheel , light [ F ( " rw " ) ] ) ;
2020-11-04 10:04:40 +00:00
2025-06-11 06:30:25 +00:00
CJSON ( gammaCorrectVal , light [ " gc " ] [ " val " ] ) ; // default 2.2
2021-07-01 18:51:52 +00:00
float light_gc_bri = light [ " gc " ] [ " bri " ] ;
2023-02-12 12:18:30 +00:00
float light_gc_col = light [ " gc " ] [ " col " ] ;
if ( light_gc_bri > 1.0f ) gammaCorrectBri = true ;
else gammaCorrectBri = false ;
if ( light_gc_col > 1.0f ) gammaCorrectCol = true ;
else gammaCorrectCol = false ;
2024-09-14 12:10:46 +00:00
if ( gammaCorrectVal < = 1.0f | | gammaCorrectVal > 3 ) {
2023-02-12 12:18:30 +00:00
gammaCorrectVal = 1.0f ; // no gamma correction
gammaCorrectBri = false ;
gammaCorrectCol = false ;
}
2025-06-07 11:15:45 +00:00
NeoGammaWLEDMethod : : calcGammaTable ( gammaCorrectVal ) ; // fill look-up tables
2020-11-04 10:04:40 +00:00
2022-02-04 09:10:37 +00:00
JsonObject light_tr = light [ " tr " ] ;
2021-04-12 19:10:47 +00:00
int tdd = light_tr [ " dur " ] | - 1 ;
2022-11-20 18:40:54 +00:00
if ( tdd > = 0 ) transitionDelay = transitionDelayDefault = tdd * 100 ;
2024-04-08 14:24:27 +00:00
strip . setTransition ( transitionDelayDefault ) ;
2023-03-25 20:28:30 +00:00
CJSON ( randomPaletteChangeTime , light_tr [ F ( " rpc " ) ] ) ;
2024-02-06 10:06:23 +00:00
CJSON ( useHarmonicRandomPalette , light_tr [ F ( " hrp " ) ] ) ;
2020-11-04 10:04:40 +00:00
JsonObject light_nl = light [ " nl " ] ;
2022-02-04 09:10:37 +00:00
CJSON ( nightlightMode , light_nl [ " mode " ] ) ;
2021-05-10 23:11:16 +00:00
byte prev = nightlightDelayMinsDefault ;
2022-02-04 09:10:37 +00:00
CJSON ( nightlightDelayMinsDefault , light_nl [ " dur " ] ) ;
2021-05-10 23:11:16 +00:00
if ( nightlightDelayMinsDefault ! = prev ) nightlightDelayMins = nightlightDelayMinsDefault ;
2020-11-04 10:04:40 +00:00
2020-11-07 22:54:56 +00:00
CJSON ( nightlightTargetBri , light_nl [ F ( " tbri " ) ] ) ;
2021-07-01 18:51:52 +00:00
CJSON ( macroNl , light_nl [ " macro " ] ) ;
2020-11-04 10:04:40 +00:00
2022-02-04 09:10:37 +00:00
JsonObject def = doc [ " def " ] ;
2021-11-23 12:17:33 +00:00
CJSON ( bootPreset , def [ " ps " ] ) ;
2020-11-04 10:04:40 +00:00
CJSON ( turnOnAtBoot , def [ " on " ] ) ; // true
CJSON ( briS , def [ " bri " ] ) ; // 128
JsonObject interfaces = doc [ " if " ] ;
2022-02-04 09:10:37 +00:00
JsonObject if_sync = interfaces [ " sync " ] ;
2020-11-07 22:54:56 +00:00
CJSON ( udpPort , if_sync [ F ( " port0 " ) ] ) ; // 21324
CJSON ( udpPort2 , if_sync [ F ( " port1 " ) ] ) ; // 65506
2020-11-04 10:04:40 +00:00
2023-09-10 16:52:14 +00:00
# ifndef WLED_DISABLE_ESPNOW
CJSON ( useESPNowSync , if_sync [ F ( " espnow " ) ] ) ;
# endif
2024-02-09 21:15:29 +00:00
JsonObject if_sync_recv = if_sync [ F ( " recv " ) ] ;
2020-11-04 10:04:40 +00:00
CJSON ( receiveNotificationBrightness , if_sync_recv [ " bri " ] ) ;
2021-03-13 21:04:37 +00:00
CJSON ( receiveNotificationColor , if_sync_recv [ " col " ] ) ;
2021-07-10 14:14:17 +00:00
CJSON ( receiveNotificationEffects , if_sync_recv [ " fx " ] ) ;
2024-09-10 18:02:29 +00:00
CJSON ( receiveNotificationPalette , if_sync_recv [ " pal " ] ) ;
2021-08-21 10:28:22 +00:00
CJSON ( receiveGroups , if_sync_recv [ " grp " ] ) ;
2021-12-17 10:22:20 +00:00
CJSON ( receiveSegmentOptions , if_sync_recv [ " seg " ] ) ;
2022-02-20 21:24:11 +00:00
CJSON ( receiveSegmentBounds , if_sync_recv [ " sb " ] ) ;
2020-11-04 10:04:40 +00:00
2024-02-09 21:15:29 +00:00
JsonObject if_sync_send = if_sync [ F ( " send " ) ] ;
2023-09-10 16:52:14 +00:00
CJSON ( sendNotifications , if_sync_send [ " en " ] ) ;
sendNotificationsRT = sendNotifications ;
CJSON ( notifyDirect , if_sync_send [ F ( " dir " ) ] ) ;
2021-07-01 18:51:52 +00:00
CJSON ( notifyButton , if_sync_send [ " btn " ] ) ;
CJSON ( notifyAlexa , if_sync_send [ " va " ] ) ;
CJSON ( notifyHue , if_sync_send [ " hue " ] ) ;
2021-08-21 10:28:22 +00:00
CJSON ( syncGroups , if_sync_send [ " grp " ] ) ;
2022-10-18 23:31:23 +00:00
if ( if_sync_send [ F ( " twice " ) ] ) udpNumRetries = 1 ; // import setting from 0.13 and earlier
CJSON ( udpNumRetries , if_sync_send [ " ret " ] ) ;
2020-11-07 22:54:56 +00:00
2024-03-05 15:27:28 +00:00
JsonObject if_nodes = interfaces [ " nodes " ] ;
2021-03-13 21:04:37 +00:00
CJSON ( nodeListEnabled , if_nodes [ F ( " list " ) ] ) ;
CJSON ( nodeBroadcastEnabled , if_nodes [ F ( " bcast " ) ] ) ;
JsonObject if_live = interfaces [ " live " ] ;
2023-09-10 16:52:14 +00:00
CJSON ( receiveDirect , if_live [ " en " ] ) ; // UDP/Hyperion realtime
2022-03-25 15:36:05 +00:00
CJSON ( useMainSegmentOnly , if_live [ F ( " mso " ) ] ) ;
2023-11-23 16:13:13 +00:00
CJSON ( realtimeRespectLedMaps , if_live [ F ( " rlm " ) ] ) ;
2021-03-13 21:04:37 +00:00
CJSON ( e131Port , if_live [ " port " ] ) ; // 5568
2021-10-04 17:41:20 +00:00
if ( e131Port = = DDP_DEFAULT_PORT ) e131Port = E131_DEFAULT_PORT ; // prevent double DDP port allocation
2020-11-07 22:54:56 +00:00
CJSON ( e131Multicast , if_live [ F ( " mc " ) ] ) ;
2024-01-20 23:30:15 +00:00
JsonObject if_live_dmx = if_live [ " dmx " ] ;
2020-11-07 22:54:56 +00:00
CJSON ( e131Universe , if_live_dmx [ F ( " uni " ) ] ) ;
CJSON ( e131SkipOutOfSequence , if_live_dmx [ F ( " seqskip " ) ] ) ;
CJSON ( DMXAddress , if_live_dmx [ F ( " addr " ) ] ) ;
2022-09-22 23:02:49 +00:00
if ( ! DMXAddress | | DMXAddress > 510 ) DMXAddress = 1 ;
2022-11-19 13:10:40 +00:00
CJSON ( DMXSegmentSpacing , if_live_dmx [ F ( " dss " ) ] ) ;
if ( DMXSegmentSpacing > 150 ) DMXSegmentSpacing = 0 ;
2023-02-21 16:13:15 +00:00
CJSON ( e131Priority , if_live_dmx [ F ( " e131prio " ) ] ) ;
if ( e131Priority > 200 ) e131Priority = 200 ;
2022-02-04 09:10:37 +00:00
CJSON ( DMXMode , if_live_dmx [ " mode " ] ) ;
2020-11-07 22:54:56 +00:00
tdd = if_live [ F ( " timeout " ) ] | - 1 ;
2020-11-04 10:04:40 +00:00
if ( tdd > = 0 ) realtimeTimeoutMs = tdd * 100 ;
2023-08-14 11:28:34 +00:00
# ifdef WLED_ENABLE_DMX_INPUT
CJSON ( dmxInputTransmitPin , if_live_dmx [ F ( " inputRxPin " ) ] ) ;
CJSON ( dmxInputReceivePin , if_live_dmx [ F ( " inputTxPin " ) ] ) ;
2023-08-17 14:53:02 +00:00
CJSON ( dmxInputEnablePin , if_live_dmx [ F ( " inputEnablePin " ) ] ) ;
2024-03-07 10:44:07 +00:00
CJSON ( dmxInputPort , if_live_dmx [ F ( " dmxInputPort " ) ] ) ;
2023-08-14 11:28:34 +00:00
# endif
2020-11-07 22:54:56 +00:00
CJSON ( arlsForceMaxBri , if_live [ F ( " maxbri " ) ] ) ;
CJSON ( arlsDisableGammaCorrection , if_live [ F ( " no-gc " ) ] ) ; // false
CJSON ( arlsOffset , if_live [ F ( " offset " ) ] ) ; // 0
2020-11-04 10:04:40 +00:00
2024-08-17 13:09:41 +00:00
# ifndef WLED_DISABLE_ALEXA
2021-07-01 18:51:52 +00:00
CJSON ( alexaEnabled , interfaces [ " va " ] [ F ( " alexa " ) ] ) ; // false
CJSON ( macroAlexaOn , interfaces [ " va " ] [ " macros " ] [ 0 ] ) ;
CJSON ( macroAlexaOff , interfaces [ " va " ] [ " macros " ] [ 1 ] ) ;
2022-10-25 21:42:26 +00:00
CJSON ( alexaNumPresets , interfaces [ " va " ] [ " p " ] ) ;
2024-08-17 13:09:41 +00:00
# endif
2022-10-25 21:42:26 +00:00
2024-08-15 14:18:34 +00:00
# ifndef WLED_DISABLE_MQTT
2021-03-13 21:04:37 +00:00
JsonObject if_mqtt = interfaces [ " mqtt " ] ;
CJSON ( mqttEnabled , if_mqtt [ " en " ] ) ;
2023-09-01 23:05:45 +00:00
getStringFromJson ( mqttServer , if_mqtt [ F ( " broker " ) ] , MQTT_MAX_SERVER_LEN + 1 ) ;
2021-03-13 21:04:37 +00:00
CJSON ( mqttPort , if_mqtt [ " port " ] ) ; // 1883
2020-11-07 22:54:56 +00:00
getStringFromJson ( mqttUser , if_mqtt [ F ( " user " ) ] , 41 ) ;
2021-06-29 23:23:35 +00:00
getStringFromJson ( mqttPass , if_mqtt [ " psk " ] , 65 ) ; //normally not present due to security
2020-11-07 22:54:56 +00:00
getStringFromJson ( mqttClientID , if_mqtt [ F ( " cid " ) ] , 41 ) ;
2020-11-04 10:04:40 +00:00
2023-09-01 23:05:45 +00:00
getStringFromJson ( mqttDeviceTopic , if_mqtt [ F ( " topics " ) ] [ F ( " device " ) ] , MQTT_MAX_TOPIC_LEN + 1 ) ; // "wled/test"
getStringFromJson ( mqttGroupTopic , if_mqtt [ F ( " topics " ) ] [ F ( " group " ) ] , MQTT_MAX_TOPIC_LEN + 1 ) ; // ""
2023-05-28 20:50:19 +00:00
CJSON ( retainMqttMsg , if_mqtt [ F ( " rtn " ) ] ) ;
2021-05-07 09:51:48 +00:00
# endif
2020-11-04 10:04:40 +00:00
2021-05-07 09:51:48 +00:00
# ifndef WLED_DISABLE_HUESYNC
2021-07-01 18:51:52 +00:00
JsonObject if_hue = interfaces [ " hue " ] ;
2021-03-13 21:04:37 +00:00
CJSON ( huePollingEnabled , if_hue [ " en " ] ) ;
CJSON ( huePollLightId , if_hue [ " id " ] ) ;
2020-11-07 22:54:56 +00:00
tdd = if_hue [ F ( " iv " ) ] | - 1 ;
2020-11-04 10:04:40 +00:00
if ( tdd > = 2 ) huePollIntervalMs = tdd * 100 ;
2021-03-13 21:04:37 +00:00
JsonObject if_hue_recv = if_hue [ " recv " ] ;
2020-11-04 10:04:40 +00:00
CJSON ( hueApplyOnOff , if_hue_recv [ " on " ] ) ;
CJSON ( hueApplyBri , if_hue_recv [ " bri " ] ) ;
2021-03-13 21:04:37 +00:00
CJSON ( hueApplyColor , if_hue_recv [ " col " ] ) ;
2020-11-04 10:04:40 +00:00
2021-03-13 21:04:37 +00:00
JsonArray if_hue_ip = if_hue [ " ip " ] ;
2020-11-04 10:04:40 +00:00
2024-07-11 19:22:58 +00:00
for ( unsigned i = 0 ; i < 4 ; i + + )
2020-11-04 10:04:40 +00:00
CJSON ( hueIP [ i ] , if_hue_ip [ i ] ) ;
2021-05-07 09:51:48 +00:00
# endif
2020-11-04 10:04:40 +00:00
2020-11-07 22:54:56 +00:00
JsonObject if_ntp = interfaces [ F ( " ntp " ) ] ;
2021-03-13 21:04:37 +00:00
CJSON ( ntpEnabled , if_ntp [ " en " ] ) ;
2020-11-07 22:54:56 +00:00
getStringFromJson ( ntpServerName , if_ntp [ F ( " host " ) ] , 33 ) ; // "1.wled.pool.ntp.org"
CJSON ( currentTimezone , if_ntp [ F ( " tz " ) ] ) ;
CJSON ( utcOffsetSecs , if_ntp [ F ( " offset " ) ] ) ;
CJSON ( useAMPM , if_ntp [ F ( " ampm " ) ] ) ;
2021-03-05 22:05:09 +00:00
CJSON ( longitude , if_ntp [ F ( " ln " ) ] ) ;
CJSON ( latitude , if_ntp [ F ( " lt " ) ] ) ;
2020-11-04 10:04:40 +00:00
2020-11-07 22:54:56 +00:00
JsonObject ol = doc [ F ( " ol " ) ] ;
2022-03-06 23:11:43 +00:00
CJSON ( overlayCurrent , ol [ F ( " clock " ) ] ) ; // 0
2020-11-07 22:54:56 +00:00
CJSON ( countdownMode , ol [ F ( " cntdwn " ) ] ) ;
2020-11-04 10:04:40 +00:00
2021-04-12 19:10:47 +00:00
CJSON ( overlayMin , ol [ " min " ] ) ;
2020-12-10 00:28:42 +00:00
CJSON ( overlayMax , ol [ F ( " max " ) ] ) ;
CJSON ( analogClock12pixel , ol [ F ( " o12pix " ) ] ) ;
CJSON ( analogClock5MinuteMarks , ol [ F ( " o5m " ) ] ) ;
CJSON ( analogClockSecondsTrail , ol [ F ( " osec " ) ] ) ;
2023-10-26 21:36:29 +00:00
CJSON ( analogClockSolidBlack , ol [ F ( " osb " ) ] ) ;
2020-11-04 10:04:40 +00:00
//timed macro rules
2020-11-07 22:54:56 +00:00
JsonObject tm = doc [ F ( " timers " ) ] ;
JsonObject cntdwn = tm [ F ( " cntdwn " ) ] ;
JsonArray cntdwn_goal = cntdwn [ F ( " goal " ) ] ;
2020-11-04 10:04:40 +00:00
CJSON ( countdownYear , cntdwn_goal [ 0 ] ) ;
CJSON ( countdownMonth , cntdwn_goal [ 1 ] ) ;
CJSON ( countdownDay , cntdwn_goal [ 2 ] ) ;
CJSON ( countdownHour , cntdwn_goal [ 3 ] ) ;
CJSON ( countdownMin , cntdwn_goal [ 4 ] ) ;
CJSON ( countdownSec , cntdwn_goal [ 5 ] ) ;
2021-07-01 18:51:52 +00:00
CJSON ( macroCountdown , cntdwn [ " macro " ] ) ;
2020-12-31 19:47:38 +00:00
setCountdown ( ) ;
2020-11-04 10:04:40 +00:00
2021-07-01 14:40:55 +00:00
JsonArray timers = tm [ " ins " ] ;
2020-11-04 10:04:40 +00:00
uint8_t it = 0 ;
for ( JsonObject timer : timers ) {
2021-03-06 23:04:46 +00:00
if ( it > 9 ) break ;
2023-01-06 08:24:29 +00:00
if ( it < 8 & & timer [ F ( " hour " ) ] = = 255 ) it = 8 ; // hour==255 -> sunrise/sunset
2020-11-07 22:54:56 +00:00
CJSON ( timerHours [ it ] , timer [ F ( " hour " ) ] ) ;
2021-04-12 19:10:47 +00:00
CJSON ( timerMinutes [ it ] , timer [ " min " ] ) ;
2021-07-01 18:51:52 +00:00
CJSON ( timerMacro [ it ] , timer [ " macro " ] ) ;
2020-11-04 10:04:40 +00:00
2021-12-31 13:09:48 +00:00
byte dowPrev = timerWeekday [ it ] ;
2020-12-15 23:10:48 +00:00
//note: act is currently only 0 or 1.
//the reason we are not using bool is that the on-disk type in 0.11.0 was already int
int actPrev = timerWeekday [ it ] & 0x01 ;
2020-11-07 22:54:56 +00:00
CJSON ( timerWeekday [ it ] , timer [ F ( " dow " ) ] ) ;
2020-11-04 10:04:40 +00:00
if ( timerWeekday [ it ] ! = dowPrev ) { //present in JSON
timerWeekday [ it ] < < = 1 ; //add active bit
2021-03-13 21:04:37 +00:00
int act = timer [ " en " ] | actPrev ;
2020-11-04 10:04:40 +00:00
if ( act ) timerWeekday [ it ] + + ;
}
2021-12-25 17:46:43 +00:00
if ( it < 8 ) {
2022-01-01 15:36:06 +00:00
JsonObject start = timer [ " start " ] ;
byte startm = start [ " mon " ] ;
if ( startm ) timerMonth [ it ] = ( startm < < 4 ) ;
2021-12-31 13:09:48 +00:00
CJSON ( timerDay [ it ] , start [ " day " ] ) ;
2022-01-01 15:36:06 +00:00
JsonObject end = timer [ " end " ] ;
CJSON ( timerDayEnd [ it ] , end [ " day " ] ) ;
byte endm = end [ " mon " ] ;
if ( startm ) timerMonth [ it ] + = endm & 0x0F ;
if ( ! ( timerMonth [ it ] & 0x0F ) ) timerMonth [ it ] + = 12 ; //default end month to 12
2021-12-25 17:46:43 +00:00
}
2020-11-04 10:04:40 +00:00
it + + ;
}
JsonObject ota = doc [ " ota " ] ;
const char * pwd = ota [ " psk " ] ; //normally not present due to security
bool pwdCorrect = ! otaLock ; //always allow access if ota not locked
if ( pwd ! = nullptr & & strncmp ( otaPass , pwd , 33 ) = = 0 ) pwdCorrect = true ;
if ( pwdCorrect ) { //only accept these values from cfg.json if ota is unlocked (else from wsec.json)
2020-11-07 22:54:56 +00:00
CJSON ( otaLock , ota [ F ( " lock " ) ] ) ;
CJSON ( wifiLock , ota [ F ( " lock-wifi " ) ] ) ;
2025-04-20 09:44:26 +00:00
# ifndef WLED_DISABLE_OTA
2020-11-07 22:54:56 +00:00
CJSON ( aOtaEnabled , ota [ F ( " aota " ) ] ) ;
2025-04-20 09:44:26 +00:00
# endif
2020-11-04 10:04:40 +00:00
getStringFromJson ( otaPass , pwd , 33 ) ; //normally not present due to security
2025-05-26 16:00:45 +00:00
CJSON ( otaSameSubnet , ota [ F ( " same-subnet " ) ] ) ;
2020-11-04 10:04:40 +00:00
}
2020-11-04 16:17:54 +00:00
2020-11-09 10:09:47 +00:00
# ifdef WLED_ENABLE_DMX
JsonObject dmx = doc [ " dmx " ] ;
CJSON ( DMXChannels , dmx [ F ( " chan " ) ] ) ;
CJSON ( DMXGap , dmx [ F ( " gap " ) ] ) ;
2021-09-11 23:15:51 +00:00
CJSON ( DMXStart , dmx [ " start " ] ) ;
2020-11-09 10:09:47 +00:00
CJSON ( DMXStartLED , dmx [ F ( " start-led " ) ] ) ;
2020-12-21 20:04:21 +00:00
JsonArray dmx_fixmap = dmx [ F ( " fixmap " ) ] ;
2021-11-09 23:29:04 +00:00
for ( int i = 0 ; i < dmx_fixmap . size ( ) ; i + + ) {
if ( i > 14 ) break ;
2020-12-21 20:04:21 +00:00
CJSON ( DMXFixtureMap [ i ] , dmx_fixmap [ i ] ) ;
2020-11-09 10:09:47 +00:00
}
2021-11-30 22:10:23 +00:00
CJSON ( e131ProxyUniverse , dmx [ F ( " e131proxy " ) ] ) ;
2020-11-09 10:09:47 +00:00
# endif
2020-11-11 14:50:15 +00:00
2021-04-29 15:44:31 +00:00
DEBUG_PRINTLN ( F ( " Starting usermod config. " ) ) ;
2020-11-11 14:50:15 +00:00
JsonObject usermods_settings = doc [ " um " ] ;
2021-06-24 23:26:15 +00:00
if ( ! usermods_settings . isNull ( ) ) {
2024-09-19 19:44:11 +00:00
needsSave = ! UsermodManager : : readFromConfig ( usermods_settings ) ;
2021-06-24 23:26:15 +00:00
}
2021-05-10 23:11:16 +00:00
2021-11-03 13:52:22 +00:00
if ( fromFS ) return needsSave ;
2022-03-19 13:21:14 +00:00
// if from /json/cfg
2021-05-10 23:11:16 +00:00
doReboot = doc [ F ( " rb " ) ] | doReboot ;
2022-03-19 13:21:14 +00:00
if ( doInitBusses ) return false ; // no save needed, will do after bus init in wled.cpp loop
2021-11-12 22:33:10 +00:00
return ( doc [ " sv " ] | true ) ;
2021-05-10 23:11:16 +00:00
}
2024-03-07 19:21:56 +00:00
static const char s_cfg_json [ ] PROGMEM = " /cfg.json " ;
2021-05-10 23:11:16 +00:00
void deserializeConfigFromFS ( ) {
2025-04-22 20:37:18 +00:00
[[maybe_unused]] bool success = deserializeConfigSec ( ) ;
2024-03-22 19:49:13 +00:00
# ifdef WLED_ADD_EEPROM_SUPPORT
2021-05-10 23:11:16 +00:00
if ( ! success ) { //if file does not exist, try reading from EEPROM
deEEPSettings ( ) ;
}
2024-03-22 19:49:13 +00:00
# endif
2021-05-10 23:11:16 +00:00
2021-11-14 15:56:34 +00:00
if ( ! requestJSONBufferLock ( 1 ) ) return ;
2021-05-10 23:11:16 +00:00
DEBUG_PRINTLN ( F ( " Reading settings from /cfg.json... " ) ) ;
2024-03-07 19:21:56 +00:00
success = readObjectFromFile ( s_cfg_json , nullptr , pDoc ) ;
2021-05-10 23:11:16 +00:00
2021-08-23 12:14:48 +00:00
// NOTE: This routine deserializes *and* applies the configuration
// Therefore, must also initialize ethernet from this function
2023-12-21 20:30:17 +00:00
JsonObject root = pDoc - > as < JsonObject > ( ) ;
bool needsSave = deserializeConfig ( root , true ) ;
2021-11-12 22:33:10 +00:00
releaseJSONBufferLock ( ) ;
2021-11-03 13:52:22 +00:00
2025-03-23 19:15:52 +00:00
if ( needsSave ) serializeConfigToFS ( ) ; // usermods required new parameters
2020-11-04 10:04:40 +00:00
}
2025-03-23 19:15:52 +00:00
void serializeConfigToFS ( ) {
2020-11-07 22:54:56 +00:00
serializeConfigSec ( ) ;
2020-11-06 21:12:48 +00:00
DEBUG_PRINTLN ( F ( " Writing settings to /cfg.json... " ) ) ;
2021-11-14 15:56:34 +00:00
if ( ! requestJSONBufferLock ( 2 ) ) return ;
2020-11-04 10:04:40 +00:00
2023-12-23 21:56:07 +00:00
JsonObject root = pDoc - > to < JsonObject > ( ) ;
2023-12-21 20:30:17 +00:00
2025-03-23 19:15:52 +00:00
serializeConfig ( root ) ;
File f = WLED_FS . open ( FPSTR ( s_cfg_json ) , " w " ) ;
if ( f ) serializeJson ( root , f ) ;
f . close ( ) ;
releaseJSONBufferLock ( ) ;
2025-03-23 19:16:52 +00:00
configNeedsWrite = false ;
2025-03-23 19:15:52 +00:00
}
void serializeConfig ( JsonObject root ) {
2023-12-21 20:30:17 +00:00
JsonArray rev = root . createNestedArray ( " rev " ) ;
2020-11-04 10:04:40 +00:00
rev . add ( 1 ) ; //major settings revision
rev . add ( 0 ) ; //minor settings revision
2023-12-21 20:30:17 +00:00
root [ F ( " vid " ) ] = VERSION ;
2020-11-04 10:04:40 +00:00
2023-12-21 20:30:17 +00:00
JsonObject id = root . createNestedObject ( " id " ) ;
2020-11-07 22:54:56 +00:00
id [ F ( " mdns " ) ] = cmDNS ;
id [ F ( " name " ) ] = serverDescription ;
2024-08-17 13:09:41 +00:00
# ifndef WLED_DISABLE_ALEXA
2020-11-07 22:54:56 +00:00
id [ F ( " inv " ) ] = alexaInvocationName ;
2024-08-17 13:09:41 +00:00
# endif
2021-08-10 15:11:17 +00:00
id [ F ( " sui " ) ] = simplifiedUI ;
2020-11-04 10:04:40 +00:00
2023-12-21 20:30:17 +00:00
JsonObject nw = root . createNestedObject ( " nw " ) ;
2023-09-10 16:52:14 +00:00
# ifndef WLED_DISABLE_ESPNOW
nw [ F ( " espnow " ) ] = enableESPNow ;
2025-05-19 18:34:27 +00:00
JsonArray lrem = nw . createNestedArray ( F ( " linked_remote " ) ) ;
for ( size_t i = 0 ; i < linked_remotes . size ( ) ; i + + ) {
lrem . add ( linked_remotes [ i ] . data ( ) ) ;
}
2023-09-10 16:52:14 +00:00
# endif
2020-11-04 10:04:40 +00:00
JsonArray nw_ins = nw . createNestedArray ( " ins " ) ;
2024-01-20 23:30:15 +00:00
for ( size_t n = 0 ; n < multiWiFi . size ( ) ; n + + ) {
JsonObject wifi = nw_ins . createNestedObject ( ) ;
wifi [ F ( " ssid " ) ] = multiWiFi [ n ] . clientSSID ;
wifi [ F ( " pskl " ) ] = strlen ( multiWiFi [ n ] . clientPass ) ;
2024-12-21 18:02:24 +00:00
char bssid [ 13 ] ;
fillMAC2Str ( bssid , multiWiFi [ n ] . bssid ) ;
wifi [ F ( " bssid " ) ] = bssid ;
2024-01-20 23:30:15 +00:00
JsonArray wifi_ip = wifi . createNestedArray ( " ip " ) ;
JsonArray wifi_gw = wifi . createNestedArray ( " gw " ) ;
JsonArray wifi_sn = wifi . createNestedArray ( " sn " ) ;
for ( size_t i = 0 ; i < 4 ; i + + ) {
wifi_ip . add ( multiWiFi [ n ] . staticIP [ i ] ) ;
wifi_gw . add ( multiWiFi [ n ] . staticGW [ i ] ) ;
wifi_sn . add ( multiWiFi [ n ] . staticSN [ i ] ) ;
}
}
2020-11-04 10:04:40 +00:00
2024-01-20 23:30:15 +00:00
JsonArray dns = nw . createNestedArray ( F ( " dns " ) ) ;
for ( size_t i = 0 ; i < 4 ; i + + ) {
dns . add ( dnsAddress [ i ] ) ;
2020-11-04 10:04:40 +00:00
}
2023-12-21 20:30:17 +00:00
JsonObject ap = root . createNestedObject ( " ap " ) ;
2020-11-07 22:54:56 +00:00
ap [ F ( " ssid " ) ] = apSSID ;
ap [ F ( " pskl " ) ] = strlen ( apPass ) ;
ap [ F ( " chan " ) ] = apChannel ;
2020-12-19 16:09:39 +00:00
ap [ F ( " hide " ) ] = apHide ;
2020-11-07 22:54:56 +00:00
ap [ F ( " behav " ) ] = apBehavior ;
2020-11-04 10:04:40 +00:00
JsonArray ap_ip = ap . createNestedArray ( " ip " ) ;
ap_ip . add ( 4 ) ;
ap_ip . add ( 3 ) ;
ap_ip . add ( 2 ) ;
ap_ip . add ( 1 ) ;
2024-01-20 23:30:15 +00:00
JsonObject wifi = root . createNestedObject ( F ( " wifi " ) ) ;
2020-11-07 22:54:56 +00:00
wifi [ F ( " sleep " ) ] = ! noWifiSleep ;
2024-01-10 18:40:59 +00:00
wifi [ F ( " phy " ) ] = force802_3g ;
2024-06-23 12:08:18 +00:00
# ifdef ARDUINO_ARCH_ESP32
wifi [ F ( " txpwr " ) ] = txPower ;
# endif
2020-11-04 10:04:40 +00:00
2024-12-21 18:02:24 +00:00
# if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
2023-12-21 20:30:17 +00:00
JsonObject ethernet = root . createNestedObject ( " eth " ) ;
2021-03-13 21:04:37 +00:00
ethernet [ " type " ] = ethernetType ;
2021-07-07 06:12:03 +00:00
if ( ethernetType ! = WLED_ETH_NONE & & ethernetType < WLED_NUM_ETH_TYPES ) {
JsonArray pins = ethernet . createNestedArray ( " pin " ) ;
2024-07-11 19:22:58 +00:00
for ( unsigned p = 0 ; p < WLED_ETH_RSVD_PINS_COUNT ; p + + ) pins . add ( esp32_nonconfigurable_ethernet_pins [ p ] . pin ) ;
2021-08-27 17:48:55 +00:00
if ( ethernetBoards [ ethernetType ] . eth_power > = 0 ) pins . add ( ethernetBoards [ ethernetType ] . eth_power ) ;
if ( ethernetBoards [ ethernetType ] . eth_mdc > = 0 ) pins . add ( ethernetBoards [ ethernetType ] . eth_mdc ) ;
if ( ethernetBoards [ ethernetType ] . eth_mdio > = 0 ) pins . add ( ethernetBoards [ ethernetType ] . eth_mdio ) ;
2021-07-07 06:12:03 +00:00
switch ( ethernetBoards [ ethernetType ] . eth_clk_mode ) {
case ETH_CLOCK_GPIO0_IN :
case ETH_CLOCK_GPIO0_OUT :
pins . add ( 0 ) ;
break ;
case ETH_CLOCK_GPIO16_OUT :
pins . add ( 16 ) ;
break ;
case ETH_CLOCK_GPIO17_OUT :
pins . add ( 17 ) ;
break ;
}
}
2024-06-23 12:08:18 +00:00
# endif
2021-01-15 09:37:45 +00:00
2024-01-20 23:30:15 +00:00
JsonObject hw = root . createNestedObject ( F ( " hw " ) ) ;
2020-11-04 10:04:40 +00:00
JsonObject hw_led = hw . createNestedObject ( " led " ) ;
2023-11-15 18:37:07 +00:00
hw_led [ F ( " total " ) ] = strip . getLengthTotal ( ) ; //provided for compatibility on downgrade and per-output ABL
2023-12-29 22:07:29 +00:00
hw_led [ F ( " maxpwr " ) ] = BusManager : : ablMilliampsMax ( ) ;
2025-04-22 20:37:18 +00:00
// hw_led[F("ledma")] = 0; // no longer used
2024-08-17 13:09:41 +00:00
hw_led [ " cct " ] = strip . correctWB ;
hw_led [ F ( " cr " ) ] = strip . cctFromRgb ;
2024-03-28 15:03:06 +00:00
hw_led [ F ( " ic " ) ] = cctICused ;
2024-04-08 14:24:27 +00:00
hw_led [ F ( " cb " ) ] = Bus : : getCCTBlend ( ) ;
2022-03-08 01:16:33 +00:00
hw_led [ " fps " ] = strip . getTargetFps ( ) ;
2023-02-14 00:33:06 +00:00
hw_led [ F ( " rgbwm " ) ] = Bus : : getGlobalAWMode ( ) ; // global auto white mode override
2025-01-12 14:17:22 +00:00
# if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
hw_led [ F ( " prl " ) ] = BusManager : : hasParallelOutput ( ) ;
# endif
2020-11-04 10:04:40 +00:00
2022-07-10 20:23:25 +00:00
# ifndef WLED_DISABLE_2D
2022-05-08 08:50:48 +00:00
// 2D Matrix Settings
if ( strip . isMatrix ) {
JsonObject matrix = hw_led . createNestedObject ( F ( " matrix " ) ) ;
2025-04-22 20:37:18 +00:00
matrix [ F ( " mpc " ) ] = strip . panel . size ( ) ;
2022-05-08 08:50:48 +00:00
JsonArray panels = matrix . createNestedArray ( F ( " panels " ) ) ;
2024-05-15 13:35:14 +00:00
for ( size_t i = 0 ; i < strip . panel . size ( ) ; i + + ) {
2022-05-08 08:50:48 +00:00
JsonObject pnl = panels . createNestedObject ( ) ;
pnl [ " b " ] = strip . panel [ i ] . bottomStart ;
pnl [ " r " ] = strip . panel [ i ] . rightStart ;
pnl [ " v " ] = strip . panel [ i ] . vertical ;
pnl [ " s " ] = strip . panel [ i ] . serpentine ;
2023-01-02 19:56:00 +00:00
pnl [ " x " ] = strip . panel [ i ] . xOffset ;
pnl [ " y " ] = strip . panel [ i ] . yOffset ;
pnl [ " h " ] = strip . panel [ i ] . height ;
pnl [ " w " ] = strip . panel [ i ] . width ;
2022-05-08 08:50:48 +00:00
}
}
2022-07-10 20:23:25 +00:00
# endif
2022-05-08 08:50:48 +00:00
2020-11-04 10:04:40 +00:00
JsonArray hw_led_ins = hw_led . createNestedArray ( " ins " ) ;
2024-05-15 13:35:14 +00:00
for ( size_t s = 0 ; s < BusManager : : getNumBusses ( ) ; s + + ) {
2025-01-21 19:14:20 +00:00
DEBUG_PRINTF_P ( PSTR ( " Cfg: Saving bus #%u \n " ) , s ) ;
const Bus * bus = BusManager : : getBus ( s ) ;
if ( ! bus | | ! bus - > isOk ( ) ) break ;
DEBUG_PRINTF_P ( PSTR ( " (%d-%d, type:%d, CO:%d, rev:%d, skip:%d, AW:%d kHz:%d, mA:%d/%d) \n " ) ,
( int ) bus - > getStart ( ) , ( int ) ( bus - > getStart ( ) + bus - > getLength ( ) ) ,
( int ) ( bus - > getType ( ) & 0x7F ) ,
( int ) bus - > getColorOrder ( ) ,
( int ) bus - > isReversed ( ) ,
( int ) bus - > skippedLeds ( ) ,
( int ) bus - > getAutoWhiteMode ( ) ,
( int ) bus - > getFrequency ( ) ,
( int ) bus - > getLEDCurrent ( ) , ( int ) bus - > getMaxCurrent ( )
) ;
2021-01-21 00:21:16 +00:00
JsonObject ins = hw_led_ins . createNestedObject ( ) ;
2021-09-11 23:15:51 +00:00
ins [ " start " ] = bus - > getStart ( ) ;
2025-01-21 19:14:20 +00:00
ins [ " len " ] = bus - > getLength ( ) ;
2021-01-21 00:21:16 +00:00
JsonArray ins_pin = ins . createNestedArray ( " pin " ) ;
uint8_t pins [ 5 ] ;
uint8_t nPins = bus - > getPins ( pins ) ;
2024-05-12 09:12:13 +00:00
for ( int i = 0 ; i < nPins ; i + + ) ins_pin . add ( pins [ i ] ) ;
2025-01-21 19:14:20 +00:00
ins [ F ( " order " ) ] = bus - > getColorOrder ( ) ;
ins [ " rev " ] = bus - > isReversed ( ) ;
ins [ F ( " skip " ) ] = bus - > skippedLeds ( ) ;
ins [ " type " ] = bus - > getType ( ) & 0x7F ;
ins [ " ref " ] = bus - > isOffRefreshRequired ( ) ;
ins [ F ( " rgbwm " ) ] = bus - > getAutoWhiteMode ( ) ;
ins [ F ( " freq " ) ] = bus - > getFrequency ( ) ;
2023-11-15 18:37:07 +00:00
ins [ F ( " maxpwr " ) ] = bus - > getMaxCurrent ( ) ;
2025-01-21 19:14:20 +00:00
ins [ F ( " ledma " ) ] = bus - > getLEDCurrent ( ) ;
2021-01-16 23:20:31 +00:00
}
2020-11-04 10:04:40 +00:00
2021-12-31 20:35:27 +00:00
JsonArray hw_com = hw . createNestedArray ( F ( " com " ) ) ;
2023-12-29 22:07:29 +00:00
const ColorOrderMap & com = BusManager : : getColorOrderMap ( ) ;
2024-05-15 13:35:14 +00:00
for ( size_t s = 0 ; s < com . count ( ) ; s + + ) {
2021-12-31 20:35:27 +00:00
const ColorOrderMapEntry * entry = com . get ( s ) ;
2025-01-21 16:50:36 +00:00
if ( ! entry | | ! entry - > len ) break ;
2021-12-31 20:35:27 +00:00
JsonObject co = hw_com . createNestedObject ( ) ;
2022-02-04 09:10:37 +00:00
co [ " start " ] = entry - > start ;
co [ " len " ] = entry - > len ;
2021-12-31 20:35:27 +00:00
co [ F ( " order " ) ] = entry - > colorOrder ;
}
2021-05-19 16:39:16 +00:00
// button(s)
2020-11-04 10:04:40 +00:00
JsonObject hw_btn = hw . createNestedObject ( " btn " ) ;
2021-05-20 04:45:02 +00:00
hw_btn [ " max " ] = WLED_MAX_BUTTONS ; // just information about max number of buttons (not actually used)
2022-11-26 22:56:55 +00:00
hw_btn [ F ( " pull " ) ] = ! disablePullUp ;
2020-11-04 10:04:40 +00:00
JsonArray hw_btn_ins = hw_btn . createNestedArray ( " ins " ) ;
2021-07-09 14:25:23 +00:00
// configuration for all buttons
2024-05-12 09:12:13 +00:00
for ( int i = 0 ; i < WLED_MAX_BUTTONS ; i + + ) {
2021-07-09 14:25:23 +00:00
JsonObject hw_btn_ins_0 = hw_btn_ins . createNestedObject ( ) ;
2021-05-19 16:39:16 +00:00
hw_btn_ins_0 [ " type " ] = buttonType [ i ] ;
2021-07-09 14:25:23 +00:00
JsonArray hw_btn_ins_0_pin = hw_btn_ins_0 . createNestedArray ( " pin " ) ;
2021-05-19 16:39:16 +00:00
hw_btn_ins_0_pin . add ( btnPin [ i ] ) ;
2021-07-09 14:25:23 +00:00
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0 . createNestedArray ( " macros " ) ;
2021-05-19 16:39:16 +00:00
hw_btn_ins_0_macros . add ( macroButton [ i ] ) ;
hw_btn_ins_0_macros . add ( macroLongPress [ i ] ) ;
hw_btn_ins_0_macros . add ( macroDoublePress [ i ] ) ;
}
2021-07-09 14:25:23 +00:00
2021-05-19 20:32:50 +00:00
hw_btn [ F ( " tt " ) ] = touchThreshold ;
2021-07-01 18:51:52 +00:00
hw_btn [ " mqtt " ] = buttonPublishMqtt ;
2020-11-04 10:04:40 +00:00
2021-03-20 22:59:17 +00:00
JsonObject hw_ir = hw . createNestedObject ( " ir " ) ;
2024-03-05 15:27:28 +00:00
# ifndef WLED_DISABLE_INFRARED
2021-03-20 22:59:17 +00:00
hw_ir [ " pin " ] = irPin ;
hw_ir [ " type " ] = irEnabled ; // the byte 'irEnabled' does contain the IR-Remote Type ( 0=disabled )
2024-03-05 15:27:28 +00:00
# endif
2022-02-06 23:40:45 +00:00
hw_ir [ " sel " ] = irApplyToAllSelected ;
2020-11-04 10:04:40 +00:00
2021-03-13 21:04:37 +00:00
JsonObject hw_relay = hw . createNestedObject ( F ( " relay " ) ) ;
hw_relay [ " pin " ] = rlyPin ;
2021-03-04 11:10:18 +00:00
hw_relay [ " rev " ] = ! rlyMde ;
2024-04-21 18:02:00 +00:00
hw_relay [ F ( " odrain " ) ] = rlyOpenDrain ;
2021-01-16 23:20:31 +00:00
2022-02-01 19:02:46 +00:00
hw [ F ( " baud " ) ] = serialBaud ;
2022-08-07 14:43:29 +00:00
JsonObject hw_if = hw . createNestedObject ( F ( " if " ) ) ;
JsonArray hw_if_i2c = hw_if . createNestedArray ( " i2c-pin " ) ;
hw_if_i2c . add ( i2c_sda ) ;
hw_if_i2c . add ( i2c_scl ) ;
JsonArray hw_if_spi = hw_if . createNestedArray ( " spi-pin " ) ;
hw_if_spi . add ( spi_mosi ) ;
hw_if_spi . add ( spi_sclk ) ;
2022-08-25 19:57:43 +00:00
hw_if_spi . add ( spi_miso ) ;
2022-08-07 14:43:29 +00:00
2021-01-16 23:20:31 +00:00
//JsonObject hw_status = hw.createNestedObject("status");
2021-03-13 21:04:37 +00:00
//hw_status["pin"] = -1;
2021-01-16 23:20:31 +00:00
2023-12-21 20:30:17 +00:00
JsonObject light = root . createNestedObject ( F ( " light " ) ) ;
2020-11-07 22:54:56 +00:00
light [ F ( " scale-bri " ) ] = briMultiplier ;
2025-04-22 20:37:18 +00:00
light [ F ( " pal-mode " ) ] = paletteBlend ;
2024-08-17 13:09:41 +00:00
light [ F ( " aseg " ) ] = strip . autoSegments ;
2025-04-22 20:37:18 +00:00
light [ F ( " rw " ) ] = useRainbowWheel ;
2020-11-04 10:04:40 +00:00
JsonObject light_gc = light . createNestedObject ( " gc " ) ;
2023-02-17 19:36:35 +00:00
light_gc [ " bri " ] = ( gammaCorrectBri ) ? gammaCorrectVal : 1.0f ; // keep compatibility
light_gc [ " col " ] = ( gammaCorrectCol ) ? gammaCorrectVal : 1.0f ; // keep compatibility
2023-02-12 12:18:30 +00:00
light_gc [ " val " ] = gammaCorrectVal ;
2020-11-04 10:04:40 +00:00
JsonObject light_tr = light . createNestedObject ( " tr " ) ;
2021-04-12 19:10:47 +00:00
light_tr [ " dur " ] = transitionDelayDefault / 100 ;
2023-03-25 20:28:30 +00:00
light_tr [ F ( " rpc " ) ] = randomPaletteChangeTime ;
2024-02-06 10:06:23 +00:00
light_tr [ F ( " hrp " ) ] = useHarmonicRandomPalette ;
2020-11-04 10:04:40 +00:00
JsonObject light_nl = light . createNestedObject ( " nl " ) ;
2022-02-04 09:10:37 +00:00
light_nl [ " mode " ] = nightlightMode ;
2021-04-12 19:10:47 +00:00
light_nl [ " dur " ] = nightlightDelayMinsDefault ;
2020-11-07 22:54:56 +00:00
light_nl [ F ( " tbri " ) ] = nightlightTargetBri ;
2021-07-01 18:51:52 +00:00
light_nl [ " macro " ] = macroNl ;
2020-11-04 10:04:40 +00:00
2023-12-21 20:30:17 +00:00
JsonObject def = root . createNestedObject ( " def " ) ;
2021-11-23 12:17:33 +00:00
def [ " ps " ] = bootPreset ;
2020-11-04 10:04:40 +00:00
def [ " on " ] = turnOnAtBoot ;
def [ " bri " ] = briS ;
2023-12-21 20:30:17 +00:00
JsonObject interfaces = root . createNestedObject ( " if " ) ;
2020-11-04 10:04:40 +00:00
JsonObject if_sync = interfaces . createNestedObject ( " sync " ) ;
2020-11-07 22:54:56 +00:00
if_sync [ F ( " port0 " ) ] = udpPort ;
if_sync [ F ( " port1 " ) ] = udpPort2 ;
2020-11-04 10:04:40 +00:00
2023-09-10 16:52:14 +00:00
# ifndef WLED_DISABLE_ESPNOW
if_sync [ F ( " espnow " ) ] = useESPNowSync ;
# endif
2024-02-09 21:15:29 +00:00
JsonObject if_sync_recv = if_sync . createNestedObject ( F ( " recv " ) ) ;
2020-11-04 10:04:40 +00:00
if_sync_recv [ " bri " ] = receiveNotificationBrightness ;
2021-03-13 21:04:37 +00:00
if_sync_recv [ " col " ] = receiveNotificationColor ;
2022-02-20 21:24:11 +00:00
if_sync_recv [ " fx " ] = receiveNotificationEffects ;
2024-09-10 18:02:29 +00:00
if_sync_recv [ " pal " ] = receiveNotificationPalette ;
2021-08-21 10:28:22 +00:00
if_sync_recv [ " grp " ] = receiveGroups ;
2021-12-17 10:22:20 +00:00
if_sync_recv [ " seg " ] = receiveSegmentOptions ;
2022-02-20 21:24:11 +00:00
if_sync_recv [ " sb " ] = receiveSegmentBounds ;
2020-11-04 10:04:40 +00:00
2024-02-09 21:15:29 +00:00
JsonObject if_sync_send = if_sync . createNestedObject ( F ( " send " ) ) ;
2023-09-10 16:52:14 +00:00
if_sync_send [ " en " ] = sendNotifications ;
2020-11-07 22:54:56 +00:00
if_sync_send [ F ( " dir " ) ] = notifyDirect ;
2021-07-01 18:51:52 +00:00
if_sync_send [ " btn " ] = notifyButton ;
if_sync_send [ " va " ] = notifyAlexa ;
if_sync_send [ " hue " ] = notifyHue ;
2021-08-21 10:28:22 +00:00
if_sync_send [ " grp " ] = syncGroups ;
2022-10-18 23:31:23 +00:00
if_sync_send [ " ret " ] = udpNumRetries ;
2020-11-07 22:54:56 +00:00
2024-03-05 15:27:28 +00:00
JsonObject if_nodes = interfaces . createNestedObject ( " nodes " ) ;
2021-03-13 21:04:37 +00:00
if_nodes [ F ( " list " ) ] = nodeListEnabled ;
if_nodes [ F ( " bcast " ) ] = nodeBroadcastEnabled ;
2020-11-07 22:54:56 +00:00
JsonObject if_live = interfaces . createNestedObject ( " live " ) ;
2023-09-10 16:52:14 +00:00
if_live [ " en " ] = receiveDirect ; // UDP/Hyperion realtime
2022-03-25 15:36:05 +00:00
if_live [ F ( " mso " ) ] = useMainSegmentOnly ;
2023-11-23 16:13:13 +00:00
if_live [ F ( " rlm " ) ] = realtimeRespectLedMaps ;
2021-03-13 21:04:37 +00:00
if_live [ " port " ] = e131Port ;
2020-11-07 22:54:56 +00:00
if_live [ F ( " mc " ) ] = e131Multicast ;
JsonObject if_live_dmx = if_live . createNestedObject ( " dmx " ) ;
if_live_dmx [ F ( " uni " ) ] = e131Universe ;
if_live_dmx [ F ( " seqskip " ) ] = e131SkipOutOfSequence ;
2023-02-21 16:13:15 +00:00
if_live_dmx [ F ( " e131prio " ) ] = e131Priority ;
2020-11-07 22:54:56 +00:00
if_live_dmx [ F ( " addr " ) ] = DMXAddress ;
2022-11-19 13:10:40 +00:00
if_live_dmx [ F ( " dss " ) ] = DMXSegmentSpacing ;
2022-02-04 09:10:37 +00:00
if_live_dmx [ " mode " ] = DMXMode ;
2023-08-14 11:28:34 +00:00
# ifdef WLED_ENABLE_DMX_INPUT
2023-08-17 14:53:02 +00:00
if_live_dmx [ F ( " inputRxPin " ) ] = dmxInputTransmitPin ;
if_live_dmx [ F ( " inputTxPin " ) ] = dmxInputReceivePin ;
if_live_dmx [ F ( " inputEnablePin " ) ] = dmxInputEnablePin ;
2024-03-07 10:44:07 +00:00
if_live_dmx [ F ( " dmxInputPort " ) ] = dmxInputPort ;
2023-08-14 11:28:34 +00:00
# endif
2021-08-19 16:24:41 +00:00
2020-11-07 22:54:56 +00:00
if_live [ F ( " timeout " ) ] = realtimeTimeoutMs / 100 ;
if_live [ F ( " maxbri " ) ] = arlsForceMaxBri ;
if_live [ F ( " no-gc " ) ] = arlsDisableGammaCorrection ;
if_live [ F ( " offset " ) ] = arlsOffset ;
2020-11-04 10:04:40 +00:00
2023-09-10 16:52:14 +00:00
# ifndef WLED_DISABLE_ALEXA
2020-11-04 10:04:40 +00:00
JsonObject if_va = interfaces . createNestedObject ( " va " ) ;
2020-11-07 22:54:56 +00:00
if_va [ F ( " alexa " ) ] = alexaEnabled ;
2020-11-04 10:04:40 +00:00
JsonArray if_va_macros = if_va . createNestedArray ( " macros " ) ;
if_va_macros . add ( macroAlexaOn ) ;
if_va_macros . add ( macroAlexaOff ) ;
2021-05-07 09:51:48 +00:00
2022-10-25 21:42:26 +00:00
if_va [ " p " ] = alexaNumPresets ;
2023-09-10 16:52:14 +00:00
# endif
2022-10-25 21:42:26 +00:00
2024-08-15 14:18:34 +00:00
# ifndef WLED_DISABLE_MQTT
2020-11-04 10:04:40 +00:00
JsonObject if_mqtt = interfaces . createNestedObject ( " mqtt " ) ;
2021-03-13 21:04:37 +00:00
if_mqtt [ " en " ] = mqttEnabled ;
2020-11-07 22:54:56 +00:00
if_mqtt [ F ( " broker " ) ] = mqttServer ;
2021-03-13 21:04:37 +00:00
if_mqtt [ " port " ] = mqttPort ;
2020-11-07 22:54:56 +00:00
if_mqtt [ F ( " user " ) ] = mqttUser ;
if_mqtt [ F ( " pskl " ) ] = strlen ( mqttPass ) ;
if_mqtt [ F ( " cid " ) ] = mqttClientID ;
2023-05-28 20:50:19 +00:00
if_mqtt [ F ( " rtn " ) ] = retainMqttMsg ;
2020-11-04 10:04:40 +00:00
2021-03-13 21:04:37 +00:00
JsonObject if_mqtt_topics = if_mqtt . createNestedObject ( F ( " topics " ) ) ;
2020-11-07 22:54:56 +00:00
if_mqtt_topics [ F ( " device " ) ] = mqttDeviceTopic ;
if_mqtt_topics [ F ( " group " ) ] = mqttGroupTopic ;
2021-05-07 09:51:48 +00:00
# endif
2020-11-04 10:04:40 +00:00
2021-05-07 09:51:48 +00:00
# ifndef WLED_DISABLE_HUESYNC
2020-11-04 10:04:40 +00:00
JsonObject if_hue = interfaces . createNestedObject ( " hue " ) ;
2021-03-13 21:04:37 +00:00
if_hue [ " en " ] = huePollingEnabled ;
if_hue [ " id " ] = huePollLightId ;
2020-11-07 22:54:56 +00:00
if_hue [ F ( " iv " ) ] = huePollIntervalMs / 100 ;
2020-11-04 10:04:40 +00:00
2024-02-09 21:15:29 +00:00
JsonObject if_hue_recv = if_hue . createNestedObject ( F ( " recv " ) ) ;
2020-11-04 10:04:40 +00:00
if_hue_recv [ " on " ] = hueApplyOnOff ;
if_hue_recv [ " bri " ] = hueApplyBri ;
2021-03-13 21:04:37 +00:00
if_hue_recv [ " col " ] = hueApplyColor ;
2020-11-04 10:04:40 +00:00
JsonArray if_hue_ip = if_hue . createNestedArray ( " ip " ) ;
2024-07-11 19:22:58 +00:00
for ( unsigned i = 0 ; i < 4 ; i + + ) {
2020-11-04 10:04:40 +00:00
if_hue_ip . add ( hueIP [ i ] ) ;
}
2021-05-07 09:51:48 +00:00
# endif
2020-11-04 10:04:40 +00:00
JsonObject if_ntp = interfaces . createNestedObject ( " ntp " ) ;
2021-03-13 21:04:37 +00:00
if_ntp [ " en " ] = ntpEnabled ;
2020-11-07 22:54:56 +00:00
if_ntp [ F ( " host " ) ] = ntpServerName ;
if_ntp [ F ( " tz " ) ] = currentTimezone ;
if_ntp [ F ( " offset " ) ] = utcOffsetSecs ;
if_ntp [ F ( " ampm " ) ] = useAMPM ;
2021-03-05 22:05:09 +00:00
if_ntp [ F ( " ln " ) ] = longitude ;
if_ntp [ F ( " lt " ) ] = latitude ;
2020-11-04 10:04:40 +00:00
2023-12-21 20:30:17 +00:00
JsonObject ol = root . createNestedObject ( " ol " ) ;
2022-03-06 23:11:43 +00:00
ol [ F ( " clock " ) ] = overlayCurrent ;
2020-11-07 22:54:56 +00:00
ol [ F ( " cntdwn " ) ] = countdownMode ;
2020-11-04 10:04:40 +00:00
2021-04-12 19:10:47 +00:00
ol [ " min " ] = overlayMin ;
2020-12-10 00:28:42 +00:00
ol [ F ( " max " ) ] = overlayMax ;
ol [ F ( " o12pix " ) ] = analogClock12pixel ;
ol [ F ( " o5m " ) ] = analogClock5MinuteMarks ;
ol [ F ( " osec " ) ] = analogClockSecondsTrail ;
2023-10-26 21:36:29 +00:00
ol [ F ( " osb " ) ] = analogClockSolidBlack ;
2020-12-10 00:28:42 +00:00
2023-12-21 20:30:17 +00:00
JsonObject timers = root . createNestedObject ( F ( " timers " ) ) ;
2020-11-04 10:04:40 +00:00
2021-03-13 21:04:37 +00:00
JsonObject cntdwn = timers . createNestedObject ( F ( " cntdwn " ) ) ;
JsonArray goal = cntdwn . createNestedArray ( F ( " goal " ) ) ;
2020-11-04 10:04:40 +00:00
goal . add ( countdownYear ) ; goal . add ( countdownMonth ) ; goal . add ( countdownDay ) ;
goal . add ( countdownHour ) ; goal . add ( countdownMin ) ; goal . add ( countdownSec ) ;
2021-07-01 18:51:52 +00:00
cntdwn [ " macro " ] = macroCountdown ;
2020-11-04 10:04:40 +00:00
JsonArray timers_ins = timers . createNestedArray ( " ins " ) ;
2024-07-11 19:22:58 +00:00
for ( unsigned i = 0 ; i < 10 ; i + + ) {
2021-03-09 12:24:20 +00:00
if ( timerMacro [ i ] = = 0 & & timerHours [ i ] = = 0 & & timerMinutes [ i ] = = 0 ) continue ; // sunrise/sunset get saved always (timerHours=255)
2020-11-04 10:04:40 +00:00
JsonObject timers_ins0 = timers_ins . createNestedObject ( ) ;
2021-03-13 21:04:37 +00:00
timers_ins0 [ " en " ] = ( timerWeekday [ i ] & 0x01 ) ;
2020-11-07 22:54:56 +00:00
timers_ins0 [ F ( " hour " ) ] = timerHours [ i ] ;
2021-04-12 19:10:47 +00:00
timers_ins0 [ " min " ] = timerMinutes [ i ] ;
2021-07-01 18:51:52 +00:00
timers_ins0 [ " macro " ] = timerMacro [ i ] ;
2020-11-07 22:54:56 +00:00
timers_ins0 [ F ( " dow " ) ] = timerWeekday [ i ] > > 1 ;
2021-12-25 17:46:43 +00:00
if ( i < 8 ) {
2022-01-01 15:36:06 +00:00
JsonObject start = timers_ins0 . createNestedObject ( " start " ) ;
2021-12-31 13:09:48 +00:00
start [ " mon " ] = ( timerMonth [ i ] > > 4 ) & 0xF ;
start [ " day " ] = timerDay [ i ] ;
2022-01-01 15:36:06 +00:00
JsonObject end = timers_ins0 . createNestedObject ( " end " ) ;
end [ " mon " ] = timerMonth [ i ] & 0xF ;
2021-12-31 13:09:48 +00:00
end [ " day " ] = timerDayEnd [ i ] ;
2021-12-25 17:46:43 +00:00
}
2020-11-04 10:04:40 +00:00
}
2023-12-21 20:30:17 +00:00
JsonObject ota = root . createNestedObject ( " ota " ) ;
2020-11-07 22:54:56 +00:00
ota [ F ( " lock " ) ] = otaLock ;
ota [ F ( " lock-wifi " ) ] = wifiLock ;
ota [ F ( " pskl " ) ] = strlen ( otaPass ) ;
2025-04-20 09:44:26 +00:00
# ifndef WLED_DISABLE_OTA
2020-11-07 22:54:56 +00:00
ota [ F ( " aota " ) ] = aOtaEnabled ;
2025-04-20 09:44:26 +00:00
# endif
2025-05-26 16:00:45 +00:00
ota [ F ( " same-subnet " ) ] = otaSameSubnet ;
2020-11-08 22:44:10 +00:00
# ifdef WLED_ENABLE_DMX
2023-12-21 20:30:17 +00:00
JsonObject dmx = root . createNestedObject ( " dmx " ) ;
2020-11-08 22:44:10 +00:00
dmx [ F ( " chan " ) ] = DMXChannels ;
dmx [ F ( " gap " ) ] = DMXGap ;
2021-09-11 23:15:51 +00:00
dmx [ " start " ] = DMXStart ;
2020-11-08 22:44:10 +00:00
dmx [ F ( " start-led " ) ] = DMXStartLED ;
2021-03-13 21:04:37 +00:00
JsonArray dmx_fixmap = dmx . createNestedArray ( F ( " fixmap " ) ) ;
2024-07-11 19:22:58 +00:00
for ( unsigned i = 0 ; i < 15 ; i + + ) {
2020-11-08 22:44:10 +00:00
dmx_fixmap . add ( DMXFixtureMap [ i ] ) ;
2021-11-30 22:10:23 +00:00
}
dmx [ F ( " e131proxy " ) ] = e131ProxyUniverse ;
2020-11-08 22:44:10 +00:00
# endif
2020-11-04 10:04:40 +00:00
2023-12-21 20:30:17 +00:00
JsonObject usermods_settings = root . createNestedObject ( " um " ) ;
2024-09-19 19:44:11 +00:00
UsermodManager : : addToConfig ( usermods_settings ) ;
2020-11-04 16:17:54 +00:00
}
2024-03-07 19:21:56 +00:00
static const char s_wsec_json [ ] PROGMEM = " /wsec.json " ;
2020-11-04 16:17:54 +00:00
//settings in /wsec.json, not accessible via webserver, for passwords and tokens
2020-11-05 21:54:13 +00:00
bool deserializeConfigSec ( ) {
2020-11-06 21:12:48 +00:00
DEBUG_PRINTLN ( F ( " Reading settings from /wsec.json... " ) ) ;
2021-11-14 15:56:34 +00:00
if ( ! requestJSONBufferLock ( 3 ) ) return false ;
2020-11-04 16:17:54 +00:00
2024-03-07 19:21:56 +00:00
bool success = readObjectFromFile ( s_wsec_json , nullptr , pDoc ) ;
2021-11-03 13:52:22 +00:00
if ( ! success ) {
2021-11-12 22:33:10 +00:00
releaseJSONBufferLock ( ) ;
2021-11-03 13:52:22 +00:00
return false ;
}
2020-11-06 21:12:48 +00:00
2023-12-21 20:30:17 +00:00
JsonObject root = pDoc - > as < JsonObject > ( ) ;
2024-01-20 23:30:15 +00:00
size_t n = 0 ;
JsonArray nw_ins = root [ " nw " ] [ " ins " ] ;
if ( ! nw_ins . isNull ( ) ) {
if ( nw_ins . size ( ) > 1 & & nw_ins . size ( ) > multiWiFi . size ( ) ) multiWiFi . resize ( nw_ins . size ( ) ) ; // resize constructs objects while resizing
for ( JsonObject wifi : nw_ins ) {
char pw [ 65 ] = " " ;
getStringFromJson ( pw , wifi [ " psk " ] , 65 ) ;
strlcpy ( multiWiFi [ n ] . clientPass , pw , 65 ) ;
if ( + + n > = WLED_MAX_WIFI_COUNT ) break ;
}
}
2020-11-04 16:17:54 +00:00
2023-12-21 20:30:17 +00:00
JsonObject ap = root [ " ap " ] ;
2020-11-04 16:17:54 +00:00
getStringFromJson ( apPass , ap [ " psk " ] , 65 ) ;
2023-12-21 20:30:17 +00:00
[[maybe_unused]] JsonObject interfaces = root [ " if " ] ;
2020-11-04 16:17:54 +00:00
2024-08-15 14:18:34 +00:00
# ifndef WLED_DISABLE_MQTT
2021-03-13 21:04:37 +00:00
JsonObject if_mqtt = interfaces [ " mqtt " ] ;
2021-06-29 23:23:35 +00:00
getStringFromJson ( mqttPass , if_mqtt [ " psk " ] , 65 ) ;
2021-05-07 09:51:48 +00:00
# endif
2020-11-04 16:17:54 +00:00
2021-05-07 09:51:48 +00:00
# ifndef WLED_DISABLE_HUESYNC
2021-07-01 18:51:52 +00:00
getStringFromJson ( hueApiKey , interfaces [ " hue " ] [ F ( " key " ) ] , 47 ) ;
2021-05-07 09:51:48 +00:00
# endif
2020-11-05 21:54:13 +00:00
2023-12-21 20:30:17 +00:00
getStringFromJson ( settingsPIN , root [ " pin " ] , 5 ) ;
2022-03-01 22:37:28 +00:00
correctPIN = ! strlen ( settingsPIN ) ;
2023-12-21 20:30:17 +00:00
JsonObject ota = root [ " ota " ] ;
2020-11-07 22:54:56 +00:00
getStringFromJson ( otaPass , ota [ F ( " pwd " ) ] , 33 ) ;
CJSON ( otaLock , ota [ F ( " lock " ) ] ) ;
CJSON ( wifiLock , ota [ F ( " lock-wifi " ) ] ) ;
2025-04-20 09:44:26 +00:00
# ifndef WLED_DISABLE_OTA
2020-11-07 22:54:56 +00:00
CJSON ( aOtaEnabled , ota [ F ( " aota " ) ] ) ;
2025-04-20 09:44:26 +00:00
# endif
2020-11-06 21:12:48 +00:00
2021-11-12 22:33:10 +00:00
releaseJSONBufferLock ( ) ;
2020-11-06 21:12:48 +00:00
return true ;
2020-11-04 16:17:54 +00:00
}
2020-11-05 21:54:13 +00:00
void serializeConfigSec ( ) {
2020-11-06 21:12:48 +00:00
DEBUG_PRINTLN ( F ( " Writing settings to /wsec.json... " ) ) ;
2021-11-14 15:56:34 +00:00
if ( ! requestJSONBufferLock ( 4 ) ) return ;
2020-11-06 21:12:48 +00:00
2023-12-23 21:56:07 +00:00
JsonObject root = pDoc - > to < JsonObject > ( ) ;
2023-12-21 20:30:17 +00:00
JsonObject nw = root . createNestedObject ( " nw " ) ;
2020-11-06 21:12:48 +00:00
JsonArray nw_ins = nw . createNestedArray ( " ins " ) ;
2024-01-20 23:30:15 +00:00
for ( size_t i = 0 ; i < multiWiFi . size ( ) ; i + + ) {
JsonObject wifi = nw_ins . createNestedObject ( ) ;
wifi [ F ( " psk " ) ] = multiWiFi [ i ] . clientPass ;
}
2020-11-06 21:12:48 +00:00
2023-12-21 20:30:17 +00:00
JsonObject ap = root . createNestedObject ( " ap " ) ;
2020-11-06 21:12:48 +00:00
ap [ " psk " ] = apPass ;
2023-12-21 20:30:17 +00:00
[[maybe_unused]] JsonObject interfaces = root . createNestedObject ( " if " ) ;
2024-08-15 14:18:34 +00:00
# ifndef WLED_DISABLE_MQTT
2020-11-06 21:12:48 +00:00
JsonObject if_mqtt = interfaces . createNestedObject ( " mqtt " ) ;
if_mqtt [ " psk " ] = mqttPass ;
2021-05-07 09:51:48 +00:00
# endif
# ifndef WLED_DISABLE_HUESYNC
2020-11-06 21:12:48 +00:00
JsonObject if_hue = interfaces . createNestedObject ( " hue " ) ;
2020-11-07 22:54:56 +00:00
if_hue [ F ( " key " ) ] = hueApiKey ;
2021-05-07 09:51:48 +00:00
# endif
2020-11-06 21:12:48 +00:00
2023-12-21 20:30:17 +00:00
root [ " pin " ] = settingsPIN ;
2022-03-01 22:37:28 +00:00
2023-12-21 20:30:17 +00:00
JsonObject ota = root . createNestedObject ( " ota " ) ;
2020-11-07 22:54:56 +00:00
ota [ F ( " pwd " ) ] = otaPass ;
ota [ F ( " lock " ) ] = otaLock ;
ota [ F ( " lock-wifi " ) ] = wifiLock ;
2025-04-20 09:44:26 +00:00
# ifndef WLED_DISABLE_OTA
2020-11-07 22:54:56 +00:00
ota [ F ( " aota " ) ] = aOtaEnabled ;
2025-04-20 09:44:26 +00:00
# endif
2020-11-04 16:17:54 +00:00
2024-03-07 19:21:56 +00:00
File f = WLED_FS . open ( FPSTR ( s_wsec_json ) , " w " ) ;
2023-12-23 21:56:07 +00:00
if ( f ) serializeJson ( root , f ) ;
2020-11-06 21:12:48 +00:00
f . close ( ) ;
2021-11-12 22:33:10 +00:00
releaseJSONBufferLock ( ) ;
Adding Particle System with many new FX (#4506)
* cleanup
* added collision handling back in
update from another commit that got lost
* reformat
* added latest version of functions
this somehow also got lost from an earlier commit
* Update platformio.ini
* updated particle box and firework effects
particle box now is more random in random mode (still a work in progress)
firework is now more configurable by sliders
* added preliminary functions and FX
* added particle attractor, added two new FX but still buggy
particle attractor animation does not work, somthing wrong with pointer allocation, it worked with static variables
* bugfixes, attracot now works
still unknown, why more than 256 particles are needed in memory allocation to not make it crash, but it works for now
* added angle emitter, added fireworks effect using it
* Added saturation to be set for each particle individually
at the expense of more ram usage, animations now have more options for color control (already used in fireworks now)
* bugfixes in impact animation
* added option to use fast color add, may improve performance a little
also fixed a bug in fire animation
* collision detection is now a function plus some improvements & fixes
* improved collision efficiency
improved efficiency for stackup (pushback), added code to correctly determine direction if particles meed (probably overkill but now its there)
* added fix for piling oscillations
untested, need to verify it works
* Improved collision handling (faster, less oscillations), changed variables to 32bit for faster calculation
32bit variables are faster on ESP32, so use them whenever a variable is used a lot, it saves one instruction per access.
* removed option for fastcolor add
it made very little difference in performance, but for ESP8266 it may matter so it is set permanently there. graphically the difference is also very small (sometimes a particle gets brighter or less saturated)
* Fixed some bugs in particle system, runs much smoother now
also tweaked some of the FX
* Bugfix in particle push, now piling is working again
particle pile-up did not work correctly, now fixed
* changed particle pile demo into waterfall plus some tweaks
* lots of bugfixes
* updated particle attractor animation parameters and added more user options to perlin noise
* removed TODOs
* added particle WrapUpdate function, added spray FX, some bugfixes
* fixed touch buttons for ESP32 S2 and S3
touch is implemented differently on S2 and S3, these changes make touch buttons work on S2 and S3
* some tuning for touch buttons on S2/S3
now better fits the default threshold value of 32
* updated rotating particle spray with more user options
* chaned rotating spray default parameters
* add todo
* Revert "some tuning for touch buttons on S2/S3"
This reverts commit d21ad8e7d1651a96f879d43ef1146a72a6ed8271.
* Revert "fixed touch buttons for ESP32 S2 and S3"
This reverts commit 09041551862361cd8c7444ca25403f5f96a9077b.
* removed comments, added comments
* cleanup
-removed wrap_update function, now integrated into move_update
-added more 'out of bounds' checking in fire functions, may speed it up a little
* cleanup session
-removed particle box 'rocking boat' (buggy) and replaced with random sloshing.
-removed comments
-changed some variables into 32bit for speed boost on ESP32
-added link to KB at the top of FX.cpp
* cleanup
removed / added comments
* added particle GEQ effect (untested)
* Particle GEQ fixes, it now actually works
* GEQ FX parameter tuning
* added rotating GEQ, work in progress
-animation works but sliders are too sensitive. need to adjust the ranges
* FX update
- changed firework exhaust to low saturation
- updated rotating particle spray animation
* Cleanup & Bugfixes plus major improvements for ESP8266
-added particle reductions for ESP8266 for all FX
-Removed collisions from Particle Perlin Noise FX, slows things down and does not contribute to a better effect experience
-lots of optimizations for ESP8266, all FX now work (at least on 160MHz but still slow)
-Some bugfixes
-removed unused variables to make compiler happy
* Particle FX Rename, default parameter tuning, bugfix
-Now shorter names, 'PS' in front to filter the list
-Tuned default parameters to make them look better by default
-Bugfix in particle system (removed duplicate application of velocity)
-reduced PS fire RAM usage (less particles, less base flames, no noticeable difference)
-some variable renaming
* slight speed improvements in fire, like 1-2FPS
* Big update: lots of little fixes and big speed boost on fire animation
-fixed fire burning more on the left side
-fixed crash in particle attractor
-added many improvements for ESP8266
-improved particle rendering efficiency
-efficiency improvements in general
-changed the way fire is rendered, now more than 2x faster
-re-tuned fire to new rendering, also seperately tuned it for ESP8266
-changed all random8() to random16() as it runs faster on ESPs
-some reformating
-some renaming of effect stuff
-fine tuning on falling particle effect
-improvements to collision handling (faster and better)
-added a (temporary) function for speed tests, will be removed again
* bugfix
* updated PS Fireworks with many changes and fine-tuning of parameters
-removed spiral explosions
-added more versatility to circular explosions
-removed user selectable amount of rockets
-tuned explosion size of circular explosions to match random explosions (more or less, may need improvement)
-changed order of sliders in volcano animation
* put particle system in a class. work in progress.
another huge update to the particle system.
went through the whole code, rewrote many of the functions. many improvements over the previous code. fixed many bugs (and even an ancient one in rendering function). spent many hours optimizing the code for speed and usability.
still a work in progress, debugging is ongoing. more updates to come.
* many (many!) bugfixes, added fire FX back in (and improved it a lot) added local renderbuffer for huge speed boost
-lots of bugfixes in Particle system
-added local rendering buffer (renders to buffer in heap)
-added fast and accurate color-add function
-bugfixes in render function
-added improved 'sticky' particles in collision (unfinished business)
-added ballpit animation back
-lots of tweaks to fire FX and fire rendering functions, looks even better now (still unfinished)
-added palette render option to fire
still many debug print outputs around, needs cleanup at one point
* More Bugfixes, more converted FX
* more bugfixes, some animation tuning, added volcano back in
- fixed animation transitions with proper pointer setting in each FX call
- added color by age setting to particle system
- maybe fixed collision having a tendency to go to the left
- fixed bugs in fireworks FX
- added fire spread width as a slider
- changed max number of particles and sprays based on some ram calculations
- some other random fixes
* updated fire, added some functions to PS, ported attractor FX
- added turbulance to fire (after hours of fine-tuning) it now looks even more awesome
- added attractor animation back in and improved it with more functionality
- fixed the attractor function in the PS
- renamed FX: 'candy' is now called 'vortex'
- added new force function to apply a force immediately (and handle the timing in the FX)
- added update function to PS for size update to handle dynamic segment size change
- made waterfall width dynamic on segment width
- removed some debug stuff
- added #defines for maximum number of particles/sprays
- updated fire parameter to make it look better on ESP8266
- some little bugfixes
* another huge update, many improvements, fine-tune collision, fire and some other FX
-removed classic fire render as palette now looks much better
-tweaked fire parameters to more awesome
-added (optional) turbulence to fire using perlin-noise
-ported spray FX to use PS-class
-now definitely fixed asymmetrical collision issue: do not use bitshifts on negative numbers!
-changed piling behaviour of particles, full rework. looks way more natural now and works much better
-changed bouncing behavour: they now bounce at full diameter, making them stay fully in frame when laying on the floor
-replaced all relevant bitshifts with divisions for higher accuracy throughout the PS
-added new modes to particle box FX
-changed a lot of FX parameters (finetuning)
-changed all config strings to proper settings (matrix only)
-fixed newly introduced bugs
-added speedup/slowdown to vortex FX (aka candy, aka rotating sprays)
-some renaming
-fixed bugs… lots of bugs
-merged rendering functions, removed obsolete stuff
* Fixed Speed limit
limiting speed was incorrect, leading to overflows. fixed this.
also fixed bugs in GEQ, removed some debug stuff, added FPS limit to fire (just en experiment)
* work in progress, added motion blur and line attracto (non working)
* work in progress, added test function to increase particle size, also added wobbling test
* added more tests, non compiling at the moment
* in the middle of fixing FX to use new PS functions
* debugging going on
* bugfix in wrap function and firwork FX
* added local render blurring, boosting FPS, work in progress
- changed fast-add function to use pointers
- added fast-scaling function
- added simple (but fast) 2D blurring function
test shows that local blurring of full frame is almost double the speed (40FPS now is 80FPS).
lots of comments still there
* Bugfixes, improvements and added wall roughness setting
- fixed bug in PS fuzzy noise which made it asymmetric for some reason, seems to work better now
- added particle size option to attractor but had to remove speed setting (now fixed emit speed)
- some parameter tuning of FX
- improvements to code size in render function
- added smear option to blurring (not tested much, may be buggy without smear)
- speed improvement to caldForce_dv, added zero checking.
* removed zero inits
- removed zero initialisations in FX, segment.data is set to zero by alloc function
* added individual size particle rendering plus some fixes
- advanced particles can now be rendered to individual sizes. It is computationally intensive but it works well for up to 15 very large particles and more smaller ones
- added collision handling for individual sizes (walls and collisions)
- fixed bugs in particlebox
- fixed fire not transitioning properly (flickering) when frame skip is active
- removed 'wraparound' function as it can easily be done by casting to an unsigned and then modulo
- fixed ballpit particles wandering left and right very fast if wrapX is set
* Fixed some nasty memory bugs, fixed some FX parameters
- fixed memory alignment bug in PS pointer assignment by making sure only multiples of 4 are allowed for particles and sources
- added saturation back to particle struct, as it was aligned to 10 bytes anyway.
- fixed a bug where a null pointer could be accessed
- fixed rendering out of frame particles if buffer allocation failed
- improvements on ESP8266
* Replaced Ghost Rider FX with PS version
- new FX is kept close to original animation but added more user settings
* added walls to ghostride, fixed some bugs
* added 'perpetual' flag to particles
* Fixed another memory / pointer bug, but there is still one left...
-also some minor fixes
* Found and fixed crashes, it was wrongly assigned pointers
* Added advanced particle size control and new Blob FX
- advanced size control allows for growing, shrinking, wobbling
- render function updated to support asymmetric rendering
- various code improvements and bugfixes
- some FX parameter tuning
- bugfix: removed sli() sei() calls in render function that caused random flickering on S3/C3 (may add that back in but only for ESP8266 to reduce fragmentation)
- removed some debug / test stuff
* code cleanup, removed some unused stuff
* bugfix, sprayEmit() would not return and get stuck
- forgot default return value...
* remove esp_random() as it is not supported on ESP8266
* small bugfix for ESP32, cleanup / reformatting
* added WLED_DISABLE_PARTICLESYSTEM option, fixed volcano movement
use '-D WLED_DISABLE_PARTICLESYSTEM' to disable compiling
* a line got lost in the last commit
* - added WLED_DISABLE_PARTICLESYSTEM option & cleanup & bugfixes
- cleanup / reformatting
- fixed volcano movement
- small bugfix for ESP32 (random() does not work, using random16() )
* Added PS source option to emit more than one particle, addes AR to Blobs and Spray
* added center GEQ back in, changed AR behaviour of spray a little
center GEQ is a mix between the PS equalizer and vortex, tuned for AR. some more tuning may be needed, it can probably be extended and improved a little.
* Bugfix and minor improvements
- fixed bug in center GEQ
- added '2D washing machine' mode for particle box
- improved color-change rate in ghostrider
- added AR to attractor (experimental, may remove again)
* hacked in a 1D port of the 2D PS, untested code
* fixed first bugs in 1D system, added test FX
* fixed bug in wrapping (also was wrong for 2D system)
* fixed collisions, added bouncing ball replacement (work in progress)
* replaced more FX, some tweaks to 1D PS
- changed virtual particle size from 64 to 32, making them able to move faster
- added 'rolling balls' option to bouncing balls (i.e. no gravity plus some tweaks)
- added dancing shadows with PS (work in progress)
- temporarily removed native FX: bouncing balls, rolling balls, popcorn, dancing shadows
-and of course some bugfixes
* updated dancing shadows to more closely mimic original
* added drip FX, added #ifdefs, removed some common functions
#ifdefs to individually disable 1D and 2D system.
* fixed compile issue, removed replaced FX (again)
* added Fireworks1D replacement (unfinished)
also fixed a bug in `applyForce()` using uninitialized variable.
* added sparkler and hourglass (both work in progress) tried fixing 1D collisions
* many improvements in 1D collisions (fine tuned), hour glass FX is almost done
spent A LOT of time in fine-tuning collisions for best stacking without collipsing, ringing, oscillations or particle flips. still not perfect but probably as good as it can be with the limited time-resolution
* many bugfixes in PS and FX
* minor FX adjustments
* Improved 1D collisions, added 2 new 1D FX (work in progress)
* bugfixes
* added 'color by position' as a PS setting
-made settings struct for 1D and 2D version to be different
-added setting 'color by position' as that is used by multiple FX now
* added large size rendering to 1D PS, work in progress
* bugfix (forgot to free memory)
also: made random size a permanent option in 1D fireworks as it looks kind of cool
* Added PS based Chase, fixed some bugs
* minor update
* two new FX: Starburst and 1D GEQ
* Added more advanced (and proper) size handling in collisions, work in progress
- copied and adapted some stuff from 2D system (out of bounds size rendering, dynamic collision detection distance, dynamic wall bounce distance)
* fixed some parameters in 1D FX
* added #ifndef to disable FX replaced by PS
- define DISABLE_1D_PS_REPLACEMENTS or DISABLE_2D_PS_REPLACEMENTS
* bugfixes
* default parameter change
* explicit cast to fix compile error
* Bugfixes
* added color-waves to PS chase, some parameter tuning plus bugfixes
* FX update and bugfixes
- fixed wall collisions on larger particle sizes
- update to bouncing balls:
- added size setting
- added proper updating on parameter change
- bugfixes
added support for 'colorwaves' and 'pride' to PS Chase to save on code size. currently broken...
* minor update to rolling balls, fixed stuff in Chase, pride option still not working
* update on 'pride' now working again but needs finetuning
* SEGMENT -> SEGENV on data, aux0, aux1, step
also removed debug outputs
* added pride and colorwaves to 1D replacement list
* removed unused variables
* added variable to set number of particles if not all are required (saves ram) also fixed a nasty render bug
* added preliminary 1D fire function, unfinished
* added fractal FX test, fixed bugs in emit function
* tweaked 1D fire a little, still work in progress
* minor tuning on 1D fire to avoid 'oscillation' at start
* improved 1D particle fire, much more natural now.
* updated 2D fire, fixed init bug
- source init was wrong making fire init weirdly
- changed parameters on 2D fire making it look better and improving flame height for larger setups
* fixed 'nervours' fire
* slight improvements and some cleanup
* removed douplicate code for fire emit (tradeoff for some speed), removed unfinished fractal FX
- with the duplicate code removed, the fire particle emits are a bit slower but it saves on code. it is not really noticeable, its slower by about 1FPS
* Re-license from MIT to EUPL
* Started cleanup, speed improvement to rendering, renamed class
- removed 'smar' parameter in blur functions as smear is always used
- improved particle rendering (passing by reference, passing wrap parameters for faster access)
- renamed class to ParticleSystem2D
- removed some whitespaces
- some reformating, removed some comments
- minor tweaks
- removed non-working line-attractor function
* Optimization and bugfixes
- added out of bounds checking function
- fixed rendering at boundaries
- various small changes and cleanup
- bugfixes with comparing ints of different signeness
- fixed bounce radius
* Cleanup, bugfixes, speed improvements, refactoring
- lots of code refactoring / reformating
- fixed bug in fire particle update and improved speed a bit
- refactoring of pixel rendering
- removed 2D buffers, replaced with 1D buffer for faster access
- bugfix in blur2D
- many small improvements to 2D system
* Refactoring and cleanup of 1D PS, removed debug printouts
- code reformating for consistency and readability
- replaced "'?" operator with min / max (produces the same code, more readable)
- minor changes for speed (random16 used, can later be replaced with hardware random function)
- renamed PS Equalizer to PS 2D GEQ
* Cleanup and some refactoring of particle FX
- moved 2D / length check to PS initi
- code reformating
- removed some comments
* missed a spot
* minor tweaks to fast_color_add()
* Work in progress: update to fireworks, needs more testing & finetuning
also bugs fixed and some minor cleanup
* Work in Progress: added particle memory manager for transitions
- uses only one, persistant buffer to render all present particle systems
- Buffer for particles is shared for one segment (may allow interacitng systems in the future)
- updated some of the FX to handle the new transfer, 1D FX still not done
- updated parameters for particle impact FX
* work in progress: lots of changes & fixes, transitions now work correctly in 2D
- still fragile code with lots of cleanup to do
* added transitions for big-size rendering
- transitions now work with FX that use global large size rendering. this is done by handling the buffer correctly. to avoid creating a second buffer, it is transferred back and forth to the segment. this is a bit slow but a compromise solution.
- multiple segment handling is still untested
* speed improvement to fast_color_add, added preliminary buffer transfer function
* merge fixes
* bugfix in setCurrentPalette, corrected order of 2D memory allocation, increased max particles/sources
- fixed timing for vortex
* fixed particle buffer handover, added 2D blur option, increased particle limits, various fixes
- fixed bug in memory watchdog, now works and also works when freezing segments
- fixed PS Box to work again with particle handover
- added smear blurring to waterfall
- added smear blurring to vortex, fixed color distribution, removed random color distribution option
- replaced all random() calls with hw_random()
- transitions now work but only if FX transitions are enabled and not when chaning segment size
* implemented correct 1D<->2D buffer handover+bugfixes
work in progress
* added smear to fuzzy noise, some cleanup
* added blurring option to PS 2D fireworks, work in progress in finding that nasty bug that crashes all
* BUGFIX: finally found and squased the memory bug, no more random crashes
also: removed debug outputs and minor cleanup
* minor cleanup and fixed a bug
1D system had a lot of crashes, some out of bounds memory issue. fixed it but I have no idea which change did that, maybe the order in 1D initialization
* BUGFIX: out of bounds checking was wrong, leading to crashes
* better handling of used particles in transitions
for FX that do not use all particles, transitions were constantly shifting the pointer, resulting in newly generated particles and weird particle flickering, this is not fixed by keeping the pointer constant once the number of used particles is reached.
* improved particle transition for low-count FX, updated 1D FX
now most 1D FX work again, still needs some fine-tuning
* Rework on Fireworks 1D, some minor fixes
- fireworks 1D now matches as closely as possible to the old FX
still not identical but as good as it gets.
* bugfix in PS Chase, increased brightness of 1D fireworks
* replaced sin16/cos16 with new versions
* bugfixes
* fixed hourglass init, rearranged PS FX init
* speed optimization
- moved out of bounds calculation to proper spot
- removed repeated allocation attempts if initial buffer alloc fails
* Added Sonic Stream FX, some cleanup, bugfix in emitter
* changed TTL to brightness calculation, added collision binning
- brightness is now doubled as some FX were really dim due to low TTL
- added binning in x-direction giving a huge speed advantage on larger matrix sizes
* collision binning bugfix, made particles less sticky, update to waterfall
- updated waterfall intensity and blurring
* WIP: fixed 1D system for over 1000 pixels, added collision binning for 1D
- making x coordinate 32bit allows for larger strips but uses a lot of ram due to struct memory alignment (12bytes instead of 8 bytes), this needs some more work to properly fix.
- adding collision binning significantly speeds things up, about a factor of 2 on most FX using collision
- there are still some bugs in FX or 1D memory handling (or both) on large setups
* moved particle flags to seperate array to save on RAM, refactoring
- moving the flags optimizes ram alignment, saving memory for each particle
- changed lots of parameters to `const`
- moved fire intensity to a variable instead of passing it to every render() call
- changed passing pointers to passing reference where possible
- saves a total of 340 bytes of flash
* removed todos after some checks, minor improvements
* inverted y axis in 2D render, 1D collision improvements, cleanup and fixes
- inverting the y-axis in the buffer instead of in buffer transfer fixes the FX flipping when transitiononing 1D<->2D
- improved particle binning for collisions
- added hard-pushing also when not using gravity so piles close to an edge dont collapse
- some improvments to "balance" FX
- renaming and cleanup
* FX fixes and minor tweaks
* increased min rockets
* fixed #ifdefs
* another fix
* revert unnecessary changes to base code
* merge fix
* minor tweak
* tweaked sparkler FX, some cleanup
* Fix in volcano FX, changed blurring of volcano and waterfall
* added ifdefs
* minor tweaks, increased 1D minsurfacehardness
* improved sparkler FX, made overlay possible (1D not yet), cleanup
* cleanup, now using new hsv2rgb/rgb2hsv, add overlay rendering to 1D
- new hsv2rgb is a tiny bit faster
- removed redundant code (using transferBuffer instead)
- tweked parameters in vortex, removed unneeded slider defaults
* fix for non or partially overlapping segments
- can not use overlay rendering if no segment clears the buffer, it will all add up to white eventually
- now additive transfer i.e. overlay mode is only activated if the segment is fully overlapping an underlying segment
* change got lost...
* increased sparkler intensity, some cleanup
* replaced #ifdefs, removed 1D replacements that have 2D version, removed notes
* cleanup, improvements to PS bouncing ball, replaced multicomet
- bouncing balls is now named pinball and has settings/parameters updated to be a replacement for multicomet
* cleanup, improvements, bugfixes
- large size rendering now works without framebuffer
- background adding is now done on buffer (if avilable) instead of segment
- fixed overflow bug in 2D large particle rendering (it worked only for powers of 2 size)
* potential bugfix, compiler warning fix
* removed colorwaves and pride option from chase (not worthy replacements)
* updated #defines, removed PS from 1M and 2M builds
* Adding Particle System and PS FX
Adding all 187 commits from particle system dev branch
* reverted some accidental changes
* reverted some accidental changes
* merge fixes
* changed replacement: multicomet instead of comet (lighthouse)
* changed replacement: multicomet instead of comet (lighthouse)
* disable 2D PS for ESP8266, some cleanup, improved pinball FX parameters, bugfixes
* Improved collision binning for large particles, improved pinball FX
* improved speed handling in pinball FX - rolling
* disable 2D PS for ESP8266, some cleanup, improved pinball FX parameters, bugfixes
* improved hourglass: millis instead of frame timing, better stacking. and cleanup.
* revert whitespaces
* simplified 1D collisions, improved binning for larger particles
- ran a lot of experiments with collisions in 1D, the new much simpler approach seems to be a good compromise with regards to stacking and normal collisions.
* Improved collision binning for large particles, improved pinball FX
* improved speed handling in pinball FX - rolling
* improved hourglass: millis instead of frame timing, better stacking. and cleanup.
* revert whitespaces
* prohibit use of 1D and 2D system simultaneously on ESP8266
* prohibit use of 1D and 2D system simultaneously on ESP8266
* update to handle blending styles
* fixed bugs, improved new transition handling
* updated 1D system to work with new transitions, replaced NULL with nullptr
* merge fixes
* added single pixel particle rendering for 2D system, adjusted FX to work with it
* improved collisions in 1D and 2D, some bugfixes in radius calculation, minor tweaks
- collisions are now also velocity based in 1D, there was a bug that prevented that from working well (wrong collision distance calculation)
- improvement and bugfix in 2D collision distance calculation
- added distance based pushing in 2D (instead of only using the dotproduct)
the combination of improved distance calculation and proper pushing make collisions a lot better in all tested FX
* minor fix
* fixed overlay detection, checking for partial overlay
if a PS FX is partially overlapping, it will render in overlay mode
* better blur range in PS Firworks
* minor code consolidation
* updated 1D collisions (yet again), improved 2D collision speed
- slight improvement to 2D collision code efficiency
- added faster "division" to C3/ESP8266 by using a right shift trick (biasing towards 0 also for negative numbers by applying proper rounding)
* minor tweak in PS balance
2025-02-17 17:32:12 +00:00
}