2020-04-10 12:30:08 +02:00
# define WLED_DEFINE_GLOBAL_VARS //only in one source file, wled.cpp!
# include "wled.h"
2021-06-20 00:14:09 +02:00
# include "wled_ethernet.h"
2020-04-10 12:30:08 +02:00
# include <Arduino.h>
2021-04-03 17:18:29 +02:00
# if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
# include "soc/soc.h"
# include "soc/rtc_cntl_reg.h"
# endif
2021-08-27 19:48:55 +02:00
/*
* Main WLED class implementation . Mostly initialization and connection logic
*/
WLED : : WLED ( )
{
}
2020-04-10 12:30:08 +02:00
// turns all LEDs off and restarts ESP
void WLED : : reset ( )
{
briT = 0 ;
2020-06-26 17:28:35 +02:00
# ifdef WLED_ENABLE_WEBSOCKETS
ws . closeAll ( 1012 ) ;
# endif
2023-07-12 20:52:34 +02:00
unsigned long dly = millis ( ) ;
2020-06-26 17:28:35 +02:00
while ( millis ( ) - dly < 450 ) {
2020-04-10 12:30:08 +02:00
yield ( ) ; // enough time to send response to client
}
2022-02-20 22:24:11 +01:00
applyBri ( ) ;
2022-03-19 14:21:14 +01:00
DEBUG_PRINTLN ( F ( " WLED RESET " ) ) ;
2020-04-10 12:30:08 +02:00
ESP . restart ( ) ;
}
void WLED : : loop ( )
{
2021-09-11 23:32:36 +02:00
# ifdef WLED_DEBUG
2023-07-06 21:16:29 +02:00
static unsigned long lastRun = 0 ;
2023-07-12 20:52:34 +02:00
unsigned long loopMillis = millis ( ) ;
size_t loopDelay = loopMillis - lastRun ;
2023-07-06 21:16:29 +02:00
if ( lastRun = = 0 ) loopDelay = 0 ; // startup - don't have valid data from last run.
2023-07-12 20:52:34 +02:00
if ( loopDelay > 2 ) DEBUG_PRINTF ( " Loop delayed more than %ums. \n " , loopDelay ) ;
static unsigned long maxLoopMillis = 0 ;
static size_t avgLoopMillis = 0 ;
2021-09-11 23:32:36 +02:00
static unsigned long maxUsermodMillis = 0 ;
2023-07-05 17:16:54 +02:00
static size_t avgUsermodMillis = 0 ;
2021-10-16 15:13:30 +02:00
static unsigned long maxStripMillis = 0 ;
2023-07-05 17:16:54 +02:00
static size_t avgStripMillis = 0 ;
2023-07-12 20:52:34 +02:00
unsigned long stripMillis ;
2021-09-11 23:32:36 +02:00
# endif
2021-05-27 00:09:52 +02:00
handleTime ( ) ;
2023-01-12 20:35:34 +01:00
# ifndef WLED_DISABLE_INFRARED
2020-04-10 12:30:08 +02:00
handleIR ( ) ; // 2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
2023-01-12 20:35:34 +01:00
# endif
2020-04-10 12:30:08 +02:00
handleConnection ( ) ;
2023-07-30 21:42:05 +02:00
# ifndef WLED_DISABLE_ESPNOW
2023-06-22 10:06:19 +02:00
handleRemote ( ) ;
2023-07-30 21:42:05 +02:00
# endif
2020-04-10 12:30:08 +02:00
handleSerial ( ) ;
2023-06-27 01:51:44 +02:00
handleImprovWifiScan ( ) ;
2020-04-10 12:30:08 +02:00
handleNotifications ( ) ;
handleTransitions ( ) ;
# ifdef WLED_ENABLE_DMX
handleDMX ( ) ;
# endif
userLoop ( ) ;
2021-09-11 23:32:36 +02:00
# ifdef WLED_DEBUG
unsigned long usermodMillis = millis ( ) ;
# endif
2020-05-28 02:20:02 +02:00
usermods . loop ( ) ;
2021-09-11 23:32:36 +02:00
# ifdef WLED_DEBUG
usermodMillis = millis ( ) - usermodMillis ;
2021-10-16 15:13:30 +02:00
avgUsermodMillis + = usermodMillis ;
2021-09-11 23:32:36 +02:00
if ( usermodMillis > maxUsermodMillis ) maxUsermodMillis = usermodMillis ;
# endif
2020-04-10 12:30:08 +02:00
yield ( ) ;
handleIO ( ) ;
2023-01-12 20:35:34 +01:00
# ifndef WLED_DISABLE_INFRARED
2020-04-10 12:30:08 +02:00
handleIR ( ) ;
2023-01-12 20:35:34 +01:00
# endif
2022-01-01 12:52:50 +01:00
# ifndef WLED_DISABLE_ALEXA
2020-04-10 12:30:08 +02:00
handleAlexa ( ) ;
2022-01-01 12:52:50 +01:00
# endif
2020-04-10 12:30:08 +02:00
2020-10-13 01:39:34 +02:00
if ( doCloseFile ) {
closeFile ( ) ;
yield ( ) ;
}
2020-04-10 12:30:08 +02:00
2023-07-12 20:52:34 +02:00
# ifdef WLED_DEBUG
stripMillis = millis ( ) ;
# endif
2022-03-25 16:36:05 +01:00
if ( ! realtimeMode | | realtimeOverride | | ( realtimeMode & & useMainSegmentOnly ) ) // block stuff if WARLS/Adalight is enabled
2020-04-10 12:30:08 +02:00
{
2022-01-01 12:52:50 +01:00
if ( apActive ) dnsServer . processNextRequest ( ) ;
# ifndef WLED_DISABLE_OTA
2022-05-01 22:09:40 +02:00
if ( WLED_CONNECTED & & aOtaEnabled & & ! otaLock & & correctPIN ) ArduinoOTA . handle ( ) ;
2022-01-01 12:52:50 +01:00
# endif
2020-04-10 12:30:08 +02:00
handleNightlight ( ) ;
2020-11-11 23:48:14 +01:00
handlePlaylist ( ) ;
2020-04-10 12:30:08 +02:00
yield ( ) ;
2022-01-01 12:52:50 +01:00
# ifndef WLED_DISABLE_HUESYNC
2020-04-10 12:30:08 +02:00
handleHue ( ) ;
2022-01-01 12:52:50 +01:00
yield ( ) ;
# endif
handlePresets ( ) ;
2020-04-10 12:30:08 +02:00
yield ( ) ;
2020-09-20 16:00:24 +02:00
2022-02-04 13:28:00 +01:00
if ( ! offMode | | strip . isOffRefreshRequired ( ) )
2020-04-10 12:30:08 +02:00
strip . service ( ) ;
2022-01-01 12:52:50 +01:00
# ifdef ESP8266
2020-09-20 16:00:24 +02:00
else if ( ! noWifiSleep )
delay ( 1 ) ; //required to make sure ESP enters modem sleep (see #1184)
2022-01-01 12:52:50 +01:00
# endif
2020-04-10 12:30:08 +02:00
}
2023-07-12 20:52:34 +02:00
# ifdef WLED_DEBUG
stripMillis = millis ( ) - stripMillis ;
avgStripMillis + = stripMillis ;
if ( stripMillis > maxStripMillis ) maxStripMillis = stripMillis ;
# endif
2022-07-17 15:58:41 +02:00
2020-04-10 12:30:08 +02:00
yield ( ) ;
# ifdef ESP8266
MDNS . update ( ) ;
# endif
2021-05-30 13:22:42 +02:00
//millis() rolls over every 50 days
if ( lastMqttReconnectAttempt > millis ( ) ) {
rolloverMillis + + ;
lastMqttReconnectAttempt = 0 ;
2023-11-20 15:13:39 +01:00
ntpLastSyncTime = NTP_NEVER ; // force new NTP query
2021-12-20 11:29:03 +01:00
strip . restartRuntime ( ) ;
2021-05-30 13:22:42 +02:00
}
2022-11-20 18:12:01 +01:00
if ( millis ( ) - lastMqttReconnectAttempt > 30000 | | lastMqttReconnectAttempt = = 0 ) { // lastMqttReconnectAttempt==0 forces immediate broadcast
2021-04-14 01:16:32 +02:00
lastMqttReconnectAttempt = millis ( ) ;
2023-01-12 20:35:34 +01:00
# ifndef WLED_DISABLE_MQTT
2020-04-10 12:30:08 +02:00
initMqtt ( ) ;
2023-01-12 20:35:34 +01:00
# endif
2021-05-30 13:22:42 +02:00
yield ( ) ;
// refresh WLED nodes list
2021-01-22 16:17:18 +01:00
refreshNodeList ( ) ;
2021-03-13 22:04:37 +01:00
if ( nodeBroadcastEnabled ) sendSysInfoUDP ( ) ;
2021-03-20 18:43:05 +01:00
yield ( ) ;
2020-04-30 01:52:36 +02:00
}
2021-03-20 18:43:05 +01:00
2022-03-01 23:37:28 +01:00
// 15min PIN time-out
2023-06-14 11:53:39 +02:00
if ( strlen ( settingsPIN ) > 0 & & correctPIN & & millis ( ) - lastEditTime > PIN_TIMEOUT ) {
2022-03-01 23:37:28 +01:00
correctPIN = false ;
2022-04-30 12:45:38 +02:00
createEditHandler ( false ) ;
2022-03-01 23:37:28 +01:00
}
2021-03-20 18:43:05 +01:00
//LED settings have been saved, re-init busses
2023-01-06 09:24:29 +01:00
//This code block causes severe FPS drop on ESP32 with the original "if (busConfigs[0] != nullptr)" conditional. Investigate!
2023-07-06 21:16:29 +02:00
if ( doInitBusses ) {
2021-03-23 03:10:24 +01:00
doInitBusses = false ;
2021-05-30 13:22:42 +02:00
DEBUG_PRINTLN ( F ( " Re-init busses. " ) ) ;
2021-10-11 02:19:33 +02:00
bool aligned = strip . checkSegmentAlignment ( ) ; //see if old segments match old bus(ses)
2021-03-20 18:43:05 +01:00
busses . removeAll ( ) ;
2023-06-27 00:38:30 +02:00
uint32_t mem = 0 , globalBufMem = 0 ;
uint16_t maxlen = 0 ;
2022-12-31 17:06:18 +01:00
for ( uint8_t i = 0 ; i < WLED_MAX_BUSSES + WLED_MIN_VIRTUAL_BUSSES ; i + + ) {
2021-03-20 18:43:05 +01:00
if ( busConfigs [ i ] = = nullptr ) break ;
2021-06-15 23:36:12 +02:00
mem + = BusManager : : memUsage ( * busConfigs [ i ] ) ;
2023-06-30 21:12:59 +02:00
if ( useGlobalLedBuffer & & busConfigs [ i ] - > start + busConfigs [ i ] - > count > maxlen ) {
2023-06-27 00:38:30 +02:00
maxlen = busConfigs [ i ] - > start + busConfigs [ i ] - > count ;
globalBufMem = maxlen * 4 ;
}
if ( mem + globalBufMem < = MAX_LED_MEMORY ) {
2021-10-11 02:19:33 +02:00
busses . add ( * busConfigs [ i ] ) ;
2021-07-09 16:25:23 +02:00
}
2021-03-20 18:43:05 +01:00
delete busConfigs [ i ] ; busConfigs [ i ] = nullptr ;
}
2023-02-11 18:41:30 +01:00
strip . finalizeInit ( ) ; // also loads default ledmap if present
2021-10-11 02:19:33 +02:00
if ( aligned ) strip . makeAutoSegments ( ) ;
else strip . fixInvalidSegments ( ) ;
2023-05-30 19:36:14 +02:00
doSerializeConfig = true ;
2021-03-20 18:43:05 +01:00
}
2021-11-03 14:52:22 +01:00
if ( loadLedmap > = 0 ) {
2023-02-11 18:41:30 +01:00
if ( ! strip . deserializeMap ( loadLedmap ) & & strip . isMatrix & & loadLedmap = = 0 ) strip . setUpMatrix ( ) ;
2021-11-03 14:52:22 +01:00
loadLedmap = - 1 ;
}
2023-05-30 19:36:14 +02:00
yield ( ) ;
if ( doSerializeConfig ) serializeConfig ( ) ;
2021-06-15 23:36:12 +02:00
2020-06-26 17:28:35 +02:00
yield ( ) ;
handleWs ( ) ;
2021-10-27 17:49:35 +02:00
handleStatusLED ( ) ;
2020-05-28 02:20:02 +02:00
2023-07-12 20:52:34 +02:00
toki . resetTick ( ) ;
# if WLED_WATCHDOG_TIMEOUT > 0
// we finished our mainloop, reset the watchdog timer
2023-08-28 17:58:30 +02:00
static unsigned long lastWDTFeed = 0 ;
if ( ! strip . isUpdating ( ) | | millis ( ) - lastWDTFeed > ( WLED_WATCHDOG_TIMEOUT * 500 ) ) {
2023-07-12 20:52:34 +02:00
# ifdef ARDUINO_ARCH_ESP32
esp_task_wdt_reset ( ) ;
# else
ESP . wdtFeed ( ) ;
# endif
2023-08-28 17:58:30 +02:00
lastWDTFeed = millis ( ) ;
}
2023-07-12 20:52:34 +02:00
# endif
if ( doReboot & & ( ! doInitBusses | | ! doSerializeConfig ) ) // if busses have to be inited & saved, wait until next iteration
reset ( ) ;
2021-09-26 12:13:18 +02:00
// DEBUG serial logging (every 30s)
2020-04-10 12:30:08 +02:00
# ifdef WLED_DEBUG
2023-07-12 20:52:34 +02:00
loopMillis = millis ( ) - loopMillis ;
if ( loopMillis > 30 ) {
DEBUG_PRINTF ( " Loop took %lums. \n " , loopMillis ) ;
DEBUG_PRINTF ( " Usermods took %lums. \n " , usermodMillis ) ;
DEBUG_PRINTF ( " Strip took %lums. \n " , stripMillis ) ;
}
avgLoopMillis + = loopMillis ;
if ( loopMillis > maxLoopMillis ) maxLoopMillis = loopMillis ;
2021-09-11 23:32:36 +02:00
if ( millis ( ) - debugTime > 29999 ) {
2021-05-30 13:22:42 +02:00
DEBUG_PRINTLN ( F ( " ---DEBUG INFO--- " ) ) ;
DEBUG_PRINT ( F ( " Runtime: " ) ) ; DEBUG_PRINTLN ( millis ( ) ) ;
DEBUG_PRINT ( F ( " Unix time: " ) ) ; toki . printTime ( toki . getTime ( ) ) ;
DEBUG_PRINT ( F ( " Free heap: " ) ) ; DEBUG_PRINTLN ( ESP . getFreeHeap ( ) ) ;
2023-05-28 22:50:19 +02:00
# if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
2021-05-30 13:22:42 +02:00
if ( psramFound ( ) ) {
DEBUG_PRINT ( F ( " Total PSRAM: " ) ) ; DEBUG_PRINT ( ESP . getPsramSize ( ) / 1024 ) ; DEBUG_PRINTLN ( " kB " ) ;
DEBUG_PRINT ( F ( " Free PSRAM: " ) ) ; DEBUG_PRINT ( ESP . getFreePsram ( ) / 1024 ) ; DEBUG_PRINTLN ( " kB " ) ;
2023-05-28 22:50:19 +02:00
}
2021-05-30 13:22:42 +02:00
# endif
2021-09-11 23:32:36 +02:00
DEBUG_PRINT ( F ( " Wifi state: " ) ) ; DEBUG_PRINTLN ( WiFi . status ( ) ) ;
2020-05-28 02:20:02 +02:00
2020-04-10 12:30:08 +02:00
if ( WiFi . status ( ) ! = lastWifiState ) {
wifiStateChangedTime = millis ( ) ;
}
lastWifiState = WiFi . status ( ) ;
2021-09-11 23:32:36 +02:00
DEBUG_PRINT ( F ( " State time: " ) ) ; DEBUG_PRINTLN ( wifiStateChangedTime ) ;
DEBUG_PRINT ( F ( " NTP last sync: " ) ) ; DEBUG_PRINTLN ( ntpLastSyncTime ) ;
DEBUG_PRINT ( F ( " Client IP: " ) ) ; DEBUG_PRINTLN ( Network . localIP ( ) ) ;
2022-10-04 13:50:01 +02:00
if ( loops > 0 ) { // avoid division by zero
DEBUG_PRINT ( F ( " Loops/sec: " ) ) ; DEBUG_PRINTLN ( loops / 30 ) ;
2023-07-12 20:52:34 +02:00
DEBUG_PRINT ( F ( " Loop time[ms]: " ) ) ; DEBUG_PRINT ( avgLoopMillis / loops ) ; DEBUG_PRINT ( " / " ) ; DEBUG_PRINTLN ( maxLoopMillis ) ;
2022-10-04 13:50:01 +02:00
DEBUG_PRINT ( F ( " UM time[ms]: " ) ) ; DEBUG_PRINT ( avgUsermodMillis / loops ) ; DEBUG_PRINT ( " / " ) ; DEBUG_PRINTLN ( maxUsermodMillis ) ;
DEBUG_PRINT ( F ( " Strip time[ms]: " ) ) ; DEBUG_PRINT ( avgStripMillis / loops ) ; DEBUG_PRINT ( " / " ) ; DEBUG_PRINTLN ( maxStripMillis ) ;
}
2022-08-03 21:36:47 +02:00
strip . printSize ( ) ;
2020-04-10 12:30:08 +02:00
loops = 0 ;
2023-07-12 20:52:34 +02:00
maxLoopMillis = 0 ;
2021-09-11 23:32:36 +02:00
maxUsermodMillis = 0 ;
2021-10-16 15:13:30 +02:00
maxStripMillis = 0 ;
avgUsermodMillis = 0 ;
avgStripMillis = 0 ;
2020-04-10 12:30:08 +02:00
debugTime = millis ( ) ;
}
loops + + ;
2023-07-06 21:16:29 +02:00
lastRun = millis ( ) ;
2020-05-28 02:20:02 +02:00
# endif // WLED_DEBUG
2020-04-10 12:30:08 +02:00
}
2022-05-24 13:45:35 +02:00
void WLED : : enableWatchdog ( ) {
# if WLED_WATCHDOG_TIMEOUT > 0
# ifdef ARDUINO_ARCH_ESP32
esp_err_t watchdog = esp_task_wdt_init ( WLED_WATCHDOG_TIMEOUT , true ) ;
DEBUG_PRINT ( F ( " Watchdog enabled: " ) ) ;
if ( watchdog = = ESP_OK ) {
DEBUG_PRINTLN ( F ( " OK " ) ) ;
} else {
DEBUG_PRINTLN ( watchdog ) ;
return ;
}
esp_task_wdt_add ( NULL ) ;
# else
ESP . wdtEnable ( WLED_WATCHDOG_TIMEOUT * 1000 ) ;
# endif
# endif
}
void WLED : : disableWatchdog ( ) {
# if WLED_WATCHDOG_TIMEOUT > 0
DEBUG_PRINTLN ( F ( " Watchdog: disabled " ) ) ;
# ifdef ARDUINO_ARCH_ESP32
esp_task_wdt_delete ( NULL ) ;
# else
ESP . wdtDisable ( ) ;
# endif
# endif
}
2020-04-10 12:30:08 +02:00
void WLED : : setup ( )
{
2021-04-03 17:18:29 +02:00
# if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
WRITE_PERI_REG ( RTC_CNTL_BROWN_OUT_REG , 0 ) ; //disable brownout detection
# endif
2023-03-16 13:08:34 +01:00
# ifdef ARDUINO_ARCH_ESP32
pinMode ( hardwareRX , INPUT_PULLDOWN ) ; delay ( 1 ) ; // suppress noise in case RX pin is floating (at low noise energy) - see issue #3128
# endif
2020-04-10 12:30:08 +02:00
Serial . begin ( 115200 ) ;
2022-12-21 22:07:15 +01:00
# if !ARDUINO_USB_CDC_ON_BOOT
Serial . setTimeout ( 50 ) ; // this causes troubles on new MCUs that have a "virtual" USB Serial (HWCDC)
# else
# endif
2022-12-08 12:47:34 +01:00
# if defined(WLED_DEBUG) && defined(ARDUINO_ARCH_ESP32) && (defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || ARDUINO_USB_CDC_ON_BOOT)
2022-09-20 21:17:44 +02:00
delay ( 2500 ) ; // allow CDC USB serial to initialise
# endif
2022-12-10 19:16:02 +01:00
# if !defined(WLED_DEBUG) && defined(ARDUINO_ARCH_ESP32) && !defined(WLED_DEBUG_HOST) && ARDUINO_USB_CDC_ON_BOOT
Serial . setDebugOutput ( false ) ; // switch off kernel messages when using USBCDC
# endif
2020-04-10 12:30:08 +02:00
DEBUG_PRINTLN ( ) ;
2021-05-30 13:22:42 +02:00
DEBUG_PRINT ( F ( " ---WLED " ) ) ;
2020-04-10 12:30:08 +02:00
DEBUG_PRINT ( versionString ) ;
DEBUG_PRINT ( " " ) ;
DEBUG_PRINT ( VERSION ) ;
2021-05-30 13:22:42 +02:00
DEBUG_PRINTLN ( F ( " INIT--- " ) ) ;
2020-04-10 12:30:08 +02:00
# ifdef ARDUINO_ARCH_ESP32
2021-05-30 13:22:42 +02:00
DEBUG_PRINT ( F ( " esp32 " ) ) ;
2020-04-10 12:30:08 +02:00
DEBUG_PRINTLN ( ESP . getSdkVersion ( ) ) ;
2022-09-16 16:37:07 +02:00
# if defined(ESP_ARDUINO_VERSION)
//DEBUG_PRINTF(F("arduino-esp32 0x%06x\n"), ESP_ARDUINO_VERSION);
DEBUG_PRINTF ( " arduino-esp32 v%d.%d.%d \n " , int ( ESP_ARDUINO_VERSION_MAJOR ) , int ( ESP_ARDUINO_VERSION_MINOR ) , int ( ESP_ARDUINO_VERSION_PATCH ) ) ; // availeable since v2.0.0
# else
DEBUG_PRINTLN ( F ( " arduino-esp32 v1.0.x \n " ) ) ; // we can't say in more detail.
# endif
2022-09-11 00:16:48 +02:00
DEBUG_PRINT ( F ( " CPU: " ) ) ; DEBUG_PRINT ( ESP . getChipModel ( ) ) ;
2022-09-16 16:37:07 +02:00
DEBUG_PRINT ( F ( " rev. " ) ) ; DEBUG_PRINT ( ESP . getChipRevision ( ) ) ;
2022-09-11 00:16:48 +02:00
DEBUG_PRINT ( F ( " , " ) ) ; DEBUG_PRINT ( ESP . getChipCores ( ) ) ; DEBUG_PRINT ( F ( " core(s) " ) ) ;
DEBUG_PRINT ( F ( " , " ) ) ; DEBUG_PRINT ( ESP . getCpuFreqMHz ( ) ) ; DEBUG_PRINTLN ( F ( " MHz. " ) ) ;
DEBUG_PRINT ( F ( " FLASH: " ) ) ; DEBUG_PRINT ( ( ESP . getFlashChipSize ( ) / 1024 ) / 1024 ) ;
DEBUG_PRINT ( F ( " MB, Mode " ) ) ; DEBUG_PRINT ( ESP . getFlashChipMode ( ) ) ;
# ifdef WLED_DEBUG
switch ( ESP . getFlashChipMode ( ) ) {
// missing: Octal modes
case FM_QIO : DEBUG_PRINT ( F ( " (QIO) " ) ) ; break ;
case FM_QOUT : DEBUG_PRINT ( F ( " (QOUT) " ) ) ; break ;
case FM_DIO : DEBUG_PRINT ( F ( " (DIO) " ) ) ; break ;
case FM_DOUT : DEBUG_PRINT ( F ( " (DOUT) " ) ) ; break ;
default : break ;
}
# endif
DEBUG_PRINT ( F ( " , speed " ) ) ; DEBUG_PRINT ( ESP . getFlashChipSpeed ( ) / 1000000 ) ; DEBUG_PRINTLN ( F ( " MHz. " ) ) ;
2020-04-10 12:30:08 +02:00
# else
2021-05-30 13:22:42 +02:00
DEBUG_PRINT ( F ( " esp8266 " ) ) ;
2020-04-10 12:30:08 +02:00
DEBUG_PRINTLN ( ESP . getCoreVersion ( ) ) ;
# endif
2023-03-10 15:20:50 +01:00
DEBUG_PRINT ( F ( " heap " ) ) ; DEBUG_PRINTLN ( ESP . getFreeHeap ( ) ) ;
2020-04-10 12:30:08 +02:00
2023-05-28 22:50:19 +02:00
# if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
# if defined(CONFIG_IDF_TARGET_ESP32S3)
// S3: reserve GPIO 33-37 for "octal" PSRAM
managed_pin_type pins [ ] = { { 33 , true } , { 34 , true } , { 35 , true } , { 36 , true } , { 37 , true } } ;
pinManager . allocateMultiplePins ( pins , sizeof ( pins ) / sizeof ( managed_pin_type ) , PinOwner : : SPI_RAM ) ;
# elif defined(CONFIG_IDF_TARGET_ESP32S2)
2023-05-30 16:09:51 +02:00
// S2: reserve GPIO 26-32 for PSRAM (may fail due to isPinOk() but that will also prevent other allocation)
2023-05-28 22:50:19 +02:00
managed_pin_type pins [ ] = { { 26 , true } , { 27 , true } , { 28 , true } , { 29 , true } , { 30 , true } , { 31 , true } , { 32 , true } } ;
pinManager . allocateMultiplePins ( pins , sizeof ( pins ) / sizeof ( managed_pin_type ) , PinOwner : : SPI_RAM ) ;
# elif defined(CONFIG_IDF_TARGET_ESP32C3)
2023-05-30 16:09:51 +02:00
// C3: reserve GPIO 12-17 for PSRAM (may fail due to isPinOk() but that will also prevent other allocation)
2023-05-28 22:50:19 +02:00
managed_pin_type pins [ ] = { { 12 , true } , { 13 , true } , { 14 , true } , { 15 , true } , { 16 , true } , { 17 , true } } ;
pinManager . allocateMultiplePins ( pins , sizeof ( pins ) / sizeof ( managed_pin_type ) , PinOwner : : SPI_RAM ) ;
# else
// GPIO16/GPIO17 reserved for SPI RAM
managed_pin_type pins [ ] = { { 16 , true } , { 17 , true } } ;
pinManager . allocateMultiplePins ( pins , sizeof ( pins ) / sizeof ( managed_pin_type ) , PinOwner : : SPI_RAM ) ;
2022-09-11 00:16:48 +02:00
# endif
2023-05-28 22:50:19 +02:00
# if defined(WLED_USE_PSRAM)
if ( psramFound ( ) ) {
DEBUG_PRINT ( F ( " Total PSRAM: " ) ) ; DEBUG_PRINT ( ESP . getPsramSize ( ) / 1024 ) ; DEBUG_PRINTLN ( " kB " ) ;
DEBUG_PRINT ( F ( " Free PSRAM : " ) ) ; DEBUG_PRINT ( ESP . getFreePsram ( ) / 1024 ) ; DEBUG_PRINTLN ( " kB " ) ;
}
# else
DEBUG_PRINTLN ( F ( " PSRAM not used. " ) ) ;
2021-05-30 13:22:42 +02:00
# endif
2023-05-28 22:50:19 +02:00
# endif
2021-05-30 13:22:42 +02:00
2020-11-05 22:54:13 +01:00
//DEBUG_PRINT(F("LEDs inited. heap usage ~"));
//DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
2020-04-10 12:30:08 +02:00
2021-05-30 13:22:42 +02:00
# ifdef WLED_DEBUG
2022-09-11 00:16:48 +02:00
pinManager . allocatePin ( hardwareTX , true , PinOwner : : DebugOut ) ; // TX (GPIO1 on ESP32) reserved for debug output
2021-05-30 13:22:42 +02:00
# endif
2021-11-08 21:51:15 +01:00
# ifdef WLED_ENABLE_DMX //reserve GPIO2 as hardcoded DMX pin
2021-08-23 14:14:48 +02:00
pinManager . allocatePin ( 2 , true , PinOwner : : DMX ) ;
2021-03-13 22:04:37 +01:00
# endif
2021-09-26 12:13:18 +02:00
DEBUG_PRINTLN ( F ( " Registering usermods ... " ) ) ;
registerUsermods ( ) ;
2023-03-10 15:20:50 +01:00
DEBUG_PRINT ( F ( " heap " ) ) ; DEBUG_PRINTLN ( ESP . getFreeHeap ( ) ) ;
2021-07-09 16:25:23 +02:00
for ( uint8_t i = 1 ; i < WLED_MAX_BUTTONS ; i + + ) btnPin [ i ] = - 1 ;
2020-11-05 22:54:13 +01:00
bool fsinit = false ;
DEBUGFS_PRINTLN ( F ( " Mount FS " ) ) ;
# ifdef ARDUINO_ARCH_ESP32
fsinit = WLED_FS . begin ( true ) ;
# else
fsinit = WLED_FS . begin ( ) ;
2020-04-10 12:30:08 +02:00
# endif
2020-11-05 22:54:13 +01:00
if ( ! fsinit ) {
DEBUGFS_PRINTLN ( F ( " FS failed! " ) ) ;
errorFlag = ERR_FS_BEGIN ;
2023-01-06 09:24:29 +01:00
}
2022-07-30 11:04:04 +02:00
# ifdef WLED_ADD_EEPROM_SUPPORT
else deEEP ( ) ;
2022-11-16 20:55:21 +01:00
# else
initPresetsFile ( ) ;
2022-07-30 11:04:04 +02:00
# endif
2020-11-05 22:54:13 +01:00
updateFSInfo ( ) ;
2021-05-30 13:22:42 +02:00
2022-11-20 15:55:38 +01:00
// generate module IDs must be done before AP setup
escapedMac = WiFi . macAddress ( ) ;
escapedMac . replace ( " : " , " " ) ;
escapedMac . toLowerCase ( ) ;
WLED_SET_AP_SSID ( ) ; // otherwise it is empty on first boot until config is saved
2021-05-30 13:22:42 +02:00
DEBUG_PRINTLN ( F ( " Reading config " ) ) ;
2021-05-11 01:11:16 +02:00
deserializeConfigFromFS ( ) ;
2020-04-10 12:30:08 +02:00
2021-11-30 16:28:26 +01:00
# if defined(STATUSLED) && STATUSLED>=0
2021-10-27 17:49:35 +02:00
if ( ! pinManager . isPinAllocated ( STATUSLED ) ) {
// NOTE: Special case: The status LED should *NOT* be allocated.
// See comments in handleStatusLed().
pinMode ( STATUSLED , OUTPUT ) ;
}
# endif
2021-05-30 13:22:42 +02:00
DEBUG_PRINTLN ( F ( " Initializing strip " ) ) ;
2020-04-10 12:30:08 +02:00
beginStrip ( ) ;
2023-03-10 15:20:50 +01:00
DEBUG_PRINT ( F ( " heap " ) ) ; DEBUG_PRINTLN ( ESP . getFreeHeap ( ) ) ;
2021-05-30 13:22:42 +02:00
DEBUG_PRINTLN ( F ( " Usermods setup " ) ) ;
2020-04-10 12:30:08 +02:00
userSetup ( ) ;
2020-05-28 02:20:02 +02:00
usermods . setup ( ) ;
2023-03-10 15:20:50 +01:00
DEBUG_PRINT ( F ( " heap " ) ) ; DEBUG_PRINTLN ( ESP . getFreeHeap ( ) ) ;
2021-09-26 12:13:18 +02:00
2020-04-10 12:30:08 +02:00
if ( strcmp ( clientSSID , DEFAULT_CLIENT_SSID ) = = 0 )
showWelcomePage = true ;
WiFi . persistent ( false ) ;
2021-03-13 22:04:37 +01:00
# ifdef WLED_USE_ETHERNET
2020-11-13 18:25:13 +01:00
WiFi . onEvent ( WiFiEvent ) ;
2021-03-13 22:04:37 +01:00
# endif
2020-04-10 12:30:08 +02:00
2021-05-30 13:22:42 +02:00
# ifdef WLED_ENABLE_ADALIGHT
2022-03-25 16:36:05 +01:00
//Serial RX (Adalight, Improv, Serial JSON) only possible if GPIO3 unused
//Serial TX (Debug, Improv, Serial JSON) only possible if GPIO1 unused
2022-09-11 00:16:48 +02:00
if ( ! pinManager . isPinAllocated ( hardwareRX ) & & ! pinManager . isPinAllocated ( hardwareTX ) ) {
2021-05-30 13:22:42 +02:00
Serial . println ( F ( " Ada " ) ) ;
}
# endif
2020-04-10 12:30:08 +02:00
2022-09-14 22:28:06 +02:00
// fill in unique mdns default
if ( strcmp ( cmDNS , " x " ) = = 0 ) sprintf_P ( cmDNS , PSTR ( " wled-%*s " ) , 6 , escapedMac . c_str ( ) + 6 ) ;
2023-01-12 20:35:34 +01:00
# ifndef WLED_DISABLE_MQTT
2022-09-14 22:28:06 +02:00
if ( mqttDeviceTopic [ 0 ] = = 0 ) sprintf_P ( mqttDeviceTopic , PSTR ( " wled/%*s " ) , 6 , escapedMac . c_str ( ) + 6 ) ;
if ( mqttClientID [ 0 ] = = 0 ) sprintf_P ( mqttClientID , PSTR ( " WLED-%*s " ) , 6 , escapedMac . c_str ( ) + 6 ) ;
2023-01-12 20:35:34 +01:00
# endif
2020-04-10 12:30:08 +02:00
2022-04-17 00:08:27 +02:00
# ifdef WLED_ENABLE_ADALIGHT
2021-11-16 23:20:26 +01:00
if ( Serial . available ( ) > 0 & & Serial . peek ( ) = = ' I ' ) handleImprovPacket ( ) ;
2022-04-17 00:08:27 +02:00
# endif
2021-11-16 23:20:26 +01:00
2020-04-10 12:30:08 +02:00
# ifndef WLED_DISABLE_OTA
if ( aOtaEnabled ) {
ArduinoOTA . onStart ( [ ] ( ) {
# ifdef ESP8266
wifi_set_sleep_type ( NONE_SLEEP_T ) ;
# endif
2022-05-24 13:45:35 +02:00
WLED : : instance ( ) . disableWatchdog ( ) ;
2020-09-20 01:18:31 +02:00
DEBUG_PRINTLN ( F ( " Start ArduinoOTA " ) ) ;
2020-04-10 12:30:08 +02:00
} ) ;
2022-05-24 13:45:35 +02:00
ArduinoOTA . onError ( [ ] ( ota_error_t error ) {
// reenable watchdog on failed update
WLED : : instance ( ) . enableWatchdog ( ) ;
} ) ;
2020-04-10 12:30:08 +02:00
if ( strlen ( cmDNS ) > 0 )
ArduinoOTA . setHostname ( cmDNS ) ;
}
# endif
# ifdef WLED_ENABLE_DMX
initDMX ( ) ;
# endif
2021-11-16 23:20:26 +01:00
2022-04-17 00:08:27 +02:00
# ifdef WLED_ENABLE_ADALIGHT
2021-11-16 23:20:26 +01:00
if ( Serial . available ( ) > 0 & & Serial . peek ( ) = = ' I ' ) handleImprovPacket ( ) ;
2022-04-17 00:08:27 +02:00
# endif
2020-04-10 12:30:08 +02:00
// HTTP server page init
2023-03-10 15:20:50 +01:00
DEBUG_PRINTLN ( F ( " initServer " ) ) ;
2020-04-10 12:30:08 +02:00
initServer ( ) ;
2023-03-10 15:20:50 +01:00
DEBUG_PRINT ( F ( " heap " ) ) ; DEBUG_PRINTLN ( ESP . getFreeHeap ( ) ) ;
2021-05-30 13:22:42 +02:00
2022-08-22 16:47:25 +02:00
enableWatchdog ( ) ;
2021-05-30 13:22:42 +02:00
# if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
WRITE_PERI_REG ( RTC_CNTL_BROWN_OUT_REG , 1 ) ; //enable brownout detector
# endif
2020-04-10 12:30:08 +02:00
}
void WLED : : beginStrip ( )
{
// Initialize NeoPixel Strip and button
2021-06-15 23:36:12 +02:00
strip . finalizeInit ( ) ; // busses created during deserializeConfig()
2021-10-11 02:19:33 +02:00
strip . makeAutoSegments ( ) ;
2020-11-05 22:54:13 +01:00
strip . setBrightness ( 0 ) ;
2020-04-10 12:30:08 +02:00
strip . setShowCallback ( handleOverlayDraw ) ;
2021-06-15 23:36:12 +02:00
if ( turnOnAtBoot ) {
2020-12-20 18:51:46 +01:00
if ( briS > 0 ) bri = briS ;
else if ( bri = = 0 ) bri = 128 ;
2020-11-15 15:45:51 +01:00
} else {
2023-05-30 16:09:51 +02:00
// fix for #3196
2020-11-15 15:45:51 +01:00
briLast = briS ; bri = 0 ;
2023-05-28 22:50:19 +02:00
strip . fill ( BLACK ) ;
strip . show ( ) ;
2020-11-15 15:45:51 +01:00
}
2021-06-15 23:36:12 +02:00
if ( bootPreset > 0 ) {
2021-07-10 17:01:20 +02:00
applyPreset ( bootPreset , CALL_MODE_INIT ) ;
2021-06-15 23:36:12 +02:00
}
2021-07-09 18:54:28 +02:00
colorUpdated ( CALL_MODE_INIT ) ;
2020-04-10 12:30:08 +02:00
2021-01-17 00:20:31 +01:00
// init relay pin
if ( rlyPin > = 0 )
digitalWrite ( rlyPin , ( rlyMde ? bri : ! bri ) ) ;
2020-04-10 12:30:08 +02:00
}
void WLED : : initAP ( bool resetAP )
{
if ( apBehavior = = AP_BEHAVIOR_BUTTON_ONLY & & ! resetAP )
return ;
2022-09-14 22:28:06 +02:00
if ( resetAP ) {
2022-11-20 15:55:38 +01:00
WLED_SET_AP_SSID ( ) ;
strcpy_P ( apPass , PSTR ( WLED_AP_PASS ) ) ;
2022-09-14 22:28:06 +02:00
}
2020-09-20 01:18:31 +02:00
DEBUG_PRINT ( F ( " Opening access point " ) ) ;
2020-04-10 12:30:08 +02:00
DEBUG_PRINTLN ( apSSID ) ;
WiFi . softAPConfig ( IPAddress ( 4 , 3 , 2 , 1 ) , IPAddress ( 4 , 3 , 2 , 1 ) , IPAddress ( 255 , 255 , 255 , 0 ) ) ;
WiFi . softAP ( apSSID , apPass , apChannel , apHide ) ;
2023-07-20 22:09:48 +02:00
# if defined(LOLIN_WIFI_FIX) && (defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32S3))
2023-04-30 17:30:36 +02:00
WiFi . setTxPower ( WIFI_POWER_8_5dBm ) ;
# endif
2020-04-10 12:30:08 +02:00
2020-09-27 11:43:28 +02:00
if ( ! apActive ) // start captive portal if AP active
2020-04-10 12:30:08 +02:00
{
2020-09-20 01:18:31 +02:00
DEBUG_PRINTLN ( F ( " Init AP interfaces " ) ) ;
2020-04-10 12:30:08 +02:00
server . begin ( ) ;
if ( udpPort > 0 & & udpPort ! = ntpLocalPort ) {
udpConnected = notifierUdp . begin ( udpPort ) ;
}
if ( udpRgbPort > 0 & & udpRgbPort ! = ntpLocalPort & & udpRgbPort ! = udpPort ) {
udpRgbConnected = rgbUdp . begin ( udpRgbPort ) ;
}
2020-09-27 11:43:28 +02:00
if ( udpPort2 > 0 & & udpPort2 ! = ntpLocalPort & & udpPort2 ! = udpPort & & udpPort2 ! = udpRgbPort ) {
udp2Connected = notifier2Udp . begin ( udpPort2 ) ;
2020-09-27 11:37:16 +02:00
}
2020-12-10 17:57:38 +01:00
e131 . begin ( false , e131Port , e131Universe , E131_MAX_UNIVERSE_COUNT ) ;
2021-10-01 21:56:54 +02:00
ddp . begin ( false , DDP_DEFAULT_PORT ) ;
2021-01-17 00:20:31 +01:00
2020-04-10 12:30:08 +02:00
dnsServer . setErrorReplyCode ( DNSReplyCode : : NoError ) ;
dnsServer . start ( 53 , " * " , WiFi . softAPIP ( ) ) ;
}
apActive = true ;
}
2021-08-23 14:14:48 +02:00
bool WLED : : initEthernet ( )
2020-04-10 12:30:08 +02:00
{
2020-11-13 18:25:13 +01:00
# if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
2021-07-09 20:06:48 +02:00
2021-08-23 14:14:48 +02:00
static bool successfullyConfiguredEthernet = false ;
if ( successfullyConfiguredEthernet ) {
// DEBUG_PRINTLN(F("initE: ETH already successfully configured, ignoring"));
return false ;
}
if ( ethernetType = = WLED_ETH_NONE ) {
return false ;
}
if ( ethernetType > = WLED_NUM_ETH_TYPES ) {
DEBUG_PRINT ( F ( " initE: Ignoring attempt for invalid ethernetType " ) ) ; DEBUG_PRINTLN ( ethernetType ) ;
return false ;
}
DEBUG_PRINT ( F ( " initE: Attempting ETH config: " ) ) ; DEBUG_PRINTLN ( ethernetType ) ;
// Ethernet initialization should only succeed once -- else reboot required
ethernet_settings es = ethernetBoards [ ethernetType ] ;
managed_pin_type pinsToAllocate [ 10 ] = {
// first six pins are non-configurable
esp32_nonconfigurable_ethernet_pins [ 0 ] ,
esp32_nonconfigurable_ethernet_pins [ 1 ] ,
esp32_nonconfigurable_ethernet_pins [ 2 ] ,
esp32_nonconfigurable_ethernet_pins [ 3 ] ,
esp32_nonconfigurable_ethernet_pins [ 4 ] ,
esp32_nonconfigurable_ethernet_pins [ 5 ] ,
{ ( int8_t ) es . eth_mdc , true } , // [6] = MDC is output and mandatory
{ ( int8_t ) es . eth_mdio , true } , // [7] = MDIO is bidirectional and mandatory
{ ( int8_t ) es . eth_power , true } , // [8] = optional pin, not all boards use
{ ( ( int8_t ) 0xFE ) , false } , // [9] = replaced with eth_clk_mode, mandatory
} ;
// update the clock pin....
if ( es . eth_clk_mode = = ETH_CLOCK_GPIO0_IN ) {
pinsToAllocate [ 9 ] . pin = 0 ;
pinsToAllocate [ 9 ] . isOutput = false ;
} else if ( es . eth_clk_mode = = ETH_CLOCK_GPIO0_OUT ) {
pinsToAllocate [ 9 ] . pin = 0 ;
pinsToAllocate [ 9 ] . isOutput = true ;
} else if ( es . eth_clk_mode = = ETH_CLOCK_GPIO16_OUT ) {
pinsToAllocate [ 9 ] . pin = 16 ;
pinsToAllocate [ 9 ] . isOutput = true ;
} else if ( es . eth_clk_mode = = ETH_CLOCK_GPIO17_OUT ) {
pinsToAllocate [ 9 ] . pin = 17 ;
pinsToAllocate [ 9 ] . isOutput = true ;
} else {
DEBUG_PRINT ( F ( " initE: Failing due to invalid eth_clk_mode ( " ) ) ;
DEBUG_PRINT ( es . eth_clk_mode ) ;
2022-12-26 10:20:45 +01:00
DEBUG_PRINTLN ( " ) " ) ;
2021-08-23 14:14:48 +02:00
return false ;
}
if ( ! pinManager . allocateMultiplePins ( pinsToAllocate , 10 , PinOwner : : Ethernet ) ) {
DEBUG_PRINTLN ( F ( " initE: Failed to allocate ethernet pins " ) ) ;
return false ;
}
2023-05-28 22:50:19 +02:00
/*
2023-04-28 17:15:31 +02:00
For LAN8720 the most correct way is to perform clean reset each time before init
applying LOW to power or nRST pin for at least 100 us ( please refer to datasheet , page 59 )
ESP_IDF > V4 implements it ( 150 us , lan87xx_reset_hw ( esp_eth_phy_t * phy ) function in
/ components / esp_eth / src / esp_eth_phy_lan87xx . c , line 280 )
but ESP_IDF < V4 does not . Lets do it :
[ not always needed , might be relevant in some EMI situations at startup and for hot resets ]
*/
# if ESP_IDF_VERSION_MAJOR==3
if ( es . eth_power > 0 & & es . eth_type = = ETH_PHY_LAN8720 ) {
pinMode ( es . eth_power , OUTPUT ) ;
digitalWrite ( es . eth_power , 0 ) ;
delayMicroseconds ( 150 ) ;
digitalWrite ( es . eth_power , 1 ) ;
delayMicroseconds ( 10 ) ;
}
# endif
2021-08-23 14:14:48 +02:00
if ( ! ETH . begin (
2023-01-06 09:24:29 +01:00
( uint8_t ) es . eth_address ,
( int ) es . eth_power ,
( int ) es . eth_mdc ,
( int ) es . eth_mdio ,
2021-08-23 14:14:48 +02:00
( eth_phy_type_t ) es . eth_type ,
( eth_clock_mode_t ) es . eth_clk_mode
) ) {
DEBUG_PRINTLN ( F ( " initC: ETH.begin() failed " ) ) ;
// de-allocate the allocated pins
for ( managed_pin_type mpt : pinsToAllocate ) {
pinManager . deallocatePin ( mpt . pin , PinOwner : : Ethernet ) ;
2021-07-09 20:06:48 +02:00
}
2021-08-23 14:14:48 +02:00
return false ;
2021-01-15 10:37:45 +01:00
}
2021-08-23 14:14:48 +02:00
successfullyConfiguredEthernet = true ;
DEBUG_PRINTLN ( F ( " initC: *** Ethernet successfully configured! *** " ) ) ;
return true ;
# else
return false ; // Ethernet not enabled for build
2020-11-13 18:25:13 +01:00
# endif
2021-08-23 14:14:48 +02:00
}
void WLED : : initConnection ( )
{
# ifdef WLED_ENABLE_WEBSOCKETS
ws . onEvent ( wsEvent ) ;
# endif
2020-04-30 01:52:36 +02:00
WiFi . disconnect ( true ) ; // close old connections
2020-04-10 12:30:08 +02:00
# ifdef ESP8266
WiFi . setPhyMode ( WIFI_PHY_MODE_11N ) ;
# endif
if ( staticIP [ 0 ] ! = 0 & & staticGateway [ 0 ] ! = 0 ) {
2021-08-23 14:14:48 +02:00
WiFi . config ( staticIP , staticGateway , staticSubnet , IPAddress ( 1 , 1 , 1 , 1 ) ) ;
2020-04-10 12:30:08 +02:00
} else {
2022-01-24 11:34:02 +01:00
WiFi . config ( IPAddress ( ( uint32_t ) 0 ) , IPAddress ( ( uint32_t ) 0 ) , IPAddress ( ( uint32_t ) 0 ) ) ;
2020-04-10 12:30:08 +02:00
}
lastReconnectAttempt = millis ( ) ;
if ( ! WLED_WIFI_CONFIGURED ) {
2021-11-25 06:41:37 +01:00
DEBUG_PRINTLN ( F ( " No connection configured. " ) ) ;
if ( ! apActive ) initAP ( ) ; // instantly go to ap mode
2020-04-10 12:30:08 +02:00
return ;
} else if ( ! apActive ) {
if ( apBehavior = = AP_BEHAVIOR_ALWAYS ) {
2021-11-25 06:41:37 +01:00
DEBUG_PRINTLN ( F ( " Access point ALWAYS enabled. " ) ) ;
2020-04-10 12:30:08 +02:00
initAP ( ) ;
} else {
2021-11-25 06:41:37 +01:00
DEBUG_PRINTLN ( F ( " Access point disabled (init). " ) ) ;
2020-04-10 12:30:08 +02:00
WiFi . softAPdisconnect ( true ) ;
2020-04-30 01:52:36 +02:00
WiFi . mode ( WIFI_STA ) ;
2020-04-10 12:30:08 +02:00
}
}
showWelcomePage = false ;
2020-09-20 01:18:31 +02:00
DEBUG_PRINT ( F ( " Connecting to " ) ) ;
2020-04-10 12:30:08 +02:00
DEBUG_PRINT ( clientSSID ) ;
DEBUG_PRINTLN ( " ... " ) ;
2020-07-19 16:24:26 +02:00
// convert the "serverDescription" into a valid DNS hostname (alphanumeric)
2022-10-10 16:46:23 +02:00
char hostname [ 25 ] ;
2020-11-13 18:25:13 +01:00
prepareHostname ( hostname ) ;
2021-01-17 00:20:31 +01:00
2020-04-10 12:30:08 +02:00
# ifdef ESP8266
2020-07-19 16:24:26 +02:00
WiFi . hostname ( hostname ) ;
2020-04-10 12:30:08 +02:00
# endif
WiFi . begin ( clientSSID , clientPass ) ;
# ifdef ARDUINO_ARCH_ESP32
2023-07-20 22:09:48 +02:00
# if defined(LOLIN_WIFI_FIX) && (defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32S3))
2023-04-30 17:30:36 +02:00
WiFi . setTxPower ( WIFI_POWER_8_5dBm ) ;
# endif
2020-04-10 12:30:08 +02:00
WiFi . setSleep ( ! noWifiSleep ) ;
2020-07-19 16:24:26 +02:00
WiFi . setHostname ( hostname ) ;
2020-04-10 12:30:08 +02:00
# else
wifi_set_sleep_type ( ( noWifiSleep ) ? NONE_SLEEP_T : MODEM_SLEEP_T ) ;
# endif
}
void WLED : : initInterfaces ( )
{
2020-09-20 01:18:31 +02:00
DEBUG_PRINTLN ( F ( " Init STA interfaces " ) ) ;
2020-04-10 12:30:08 +02:00
2021-05-30 13:22:42 +02:00
# ifndef WLED_DISABLE_HUESYNC
2021-09-26 12:13:18 +02:00
IPAddress ipAddress = Network . localIP ( ) ;
2020-04-10 12:30:08 +02:00
if ( hueIP [ 0 ] = = 0 ) {
2021-09-19 19:51:54 +02:00
hueIP [ 0 ] = ipAddress [ 0 ] ;
hueIP [ 1 ] = ipAddress [ 1 ] ;
hueIP [ 2 ] = ipAddress [ 2 ] ;
2020-04-10 12:30:08 +02:00
}
2021-05-30 13:22:42 +02:00
# endif
2020-04-10 12:30:08 +02:00
2023-01-12 20:35:34 +01:00
# ifndef WLED_DISABLE_ALEXA
2020-04-10 12:30:08 +02:00
// init Alexa hue emulation
if ( alexaEnabled )
alexaInit ( ) ;
2023-01-12 20:35:34 +01:00
# endif
2020-04-10 12:30:08 +02:00
# ifndef WLED_DISABLE_OTA
if ( aOtaEnabled )
ArduinoOTA . begin ( ) ;
# endif
// Set up mDNS responder:
if ( strlen ( cmDNS ) > 0 ) {
2021-09-28 23:27:40 +02:00
// "end" must be called before "begin" is called a 2nd time
// see https://github.com/esp8266/Arduino/issues/7213
MDNS . end ( ) ;
2020-09-03 14:04:33 +02:00
MDNS . begin ( cmDNS ) ;
2020-04-10 12:30:08 +02:00
2020-09-20 01:18:31 +02:00
DEBUG_PRINTLN ( F ( " mDNS started " ) ) ;
2020-04-10 12:30:08 +02:00
MDNS . addService ( " http " , " tcp " , 80 ) ;
MDNS . addService ( " wled " , " tcp " , 80 ) ;
MDNS . addServiceTxt ( " wled " , " tcp " , " mac " , escapedMac . c_str ( ) ) ;
}
server . begin ( ) ;
if ( udpPort > 0 & & udpPort ! = ntpLocalPort ) {
udpConnected = notifierUdp . begin ( udpPort ) ;
if ( udpConnected & & udpRgbPort ! = udpPort )
udpRgbConnected = rgbUdp . begin ( udpRgbPort ) ;
2020-09-27 11:43:28 +02:00
if ( udpConnected & & udpPort2 ! = udpPort & & udpPort2 ! = udpRgbPort )
udp2Connected = notifier2Udp . begin ( udpPort2 ) ;
2020-04-10 12:30:08 +02:00
}
if ( ntpEnabled )
ntpConnected = ntpUdp . begin ( ntpLocalPort ) ;
2020-04-13 00:42:27 +02:00
e131 . begin ( e131Multicast , e131Port , e131Universe , E131_MAX_UNIVERSE_COUNT ) ;
2021-10-01 21:56:54 +02:00
ddp . begin ( false , DDP_DEFAULT_PORT ) ;
2020-04-10 12:30:08 +02:00
reconnectHue ( ) ;
2023-01-12 20:35:34 +01:00
# ifndef WLED_DISABLE_MQTT
2020-04-10 12:30:08 +02:00
initMqtt ( ) ;
2023-01-12 20:35:34 +01:00
# endif
2020-04-10 12:30:08 +02:00
interfacesInited = true ;
wasConnected = true ;
}
void WLED : : handleConnection ( )
{
2021-09-26 12:13:18 +02:00
static byte stacO = 0 ;
static uint32_t lastHeap = UINT32_MAX ;
static unsigned long heapTime = 0 ;
2021-09-22 13:20:36 +02:00
unsigned long now = millis ( ) ;
if ( now < 2000 & & ( ! WLED_WIFI_CONFIGURED | | apBehavior = = AP_BEHAVIOR_ALWAYS ) )
2020-04-10 12:30:08 +02:00
return ;
2021-11-25 06:41:37 +01:00
if ( lastReconnectAttempt = = 0 ) {
DEBUG_PRINTLN ( F ( " lastReconnectAttempt == 0 " ) ) ;
2020-04-10 12:30:08 +02:00
initConnection ( ) ;
2021-11-25 06:41:37 +01:00
return ;
}
2020-04-10 12:30:08 +02:00
// reconnect WiFi to clear stale allocations if heap gets too low
2021-09-22 13:20:36 +02:00
if ( now - heapTime > 5000 ) {
2020-04-10 12:30:08 +02:00
uint32_t heap = ESP . getFreeHeap ( ) ;
2021-12-10 12:51:44 +01:00
if ( heap < MIN_HEAP_SIZE & & lastHeap < MIN_HEAP_SIZE ) {
2020-09-20 01:18:31 +02:00
DEBUG_PRINT ( F ( " Heap too low! " ) ) ;
2020-04-10 12:30:08 +02:00
DEBUG_PRINTLN ( heap ) ;
forceReconnect = true ;
2022-08-03 21:36:47 +02:00
strip . purgeSegments ( true ) ; // remove all but one segments from memory
2023-03-10 15:20:50 +01:00
} else if ( heap < MIN_HEAP_SIZE ) {
strip . purgeSegments ( ) ;
2020-04-10 12:30:08 +02:00
}
lastHeap = heap ;
2021-09-22 13:20:36 +02:00
heapTime = now ;
2020-04-10 12:30:08 +02:00
}
byte stac = 0 ;
if ( apActive ) {
# ifdef ESP8266
stac = wifi_softap_get_station_num ( ) ;
# else
wifi_sta_list_t stationList ;
esp_wifi_ap_get_sta_list ( & stationList ) ;
stac = stationList . num ;
# endif
if ( stac ! = stacO ) {
stacO = stac ;
2020-09-20 01:18:31 +02:00
DEBUG_PRINT ( F ( " Connected AP clients: " ) ) ;
2020-04-10 12:30:08 +02:00
DEBUG_PRINTLN ( stac ) ;
if ( ! WLED_CONNECTED & & WLED_WIFI_CONFIGURED ) { // trying to connect, but not connected
if ( stac )
WiFi . disconnect ( ) ; // disable search so that AP can work
else
2021-09-22 13:20:36 +02:00
initConnection ( ) ; // restart search
2020-04-10 12:30:08 +02:00
}
}
}
if ( forceReconnect ) {
2020-09-20 01:18:31 +02:00
DEBUG_PRINTLN ( F ( " Forcing reconnect. " ) ) ;
2020-04-10 12:30:08 +02:00
initConnection ( ) ;
interfacesInited = false ;
forceReconnect = false ;
wasConnected = false ;
return ;
}
2020-11-13 18:25:13 +01:00
if ( ! Network . isConnected ( ) ) {
2020-04-10 12:30:08 +02:00
if ( interfacesInited ) {
2020-09-20 01:18:31 +02:00
DEBUG_PRINTLN ( F ( " Disconnected! " ) ) ;
2020-04-10 12:30:08 +02:00
interfacesInited = false ;
initConnection ( ) ;
}
2021-11-16 23:20:26 +01:00
//send improv failed 6 seconds after second init attempt (24 sec. after provisioning)
if ( improvActive > 2 & & now - lastReconnectAttempt > 6000 ) {
sendImprovStateResponse ( 0x03 , true ) ;
improvActive = 2 ;
}
if ( now - lastReconnectAttempt > ( ( stac ) ? 300000 : 18000 ) & & WLED_WIFI_CONFIGURED ) {
if ( improvActive = = 2 ) improvActive = 3 ;
2021-11-25 06:41:37 +01:00
DEBUG_PRINTLN ( F ( " Last reconnect too old. " ) ) ;
2020-04-10 12:30:08 +02:00
initConnection ( ) ;
2021-11-16 23:20:26 +01:00
}
2021-11-25 06:41:37 +01:00
if ( ! apActive & & now - lastReconnectAttempt > 12000 & & ( ! wasConnected | | apBehavior = = AP_BEHAVIOR_NO_CONN ) ) {
DEBUG_PRINTLN ( F ( " Not connected AP. " ) ) ;
2020-04-10 12:30:08 +02:00
initAP ( ) ;
2021-11-25 06:41:37 +01:00
}
2021-11-16 23:20:26 +01:00
} else if ( ! interfacesInited ) { //newly connected
2020-04-10 12:30:08 +02:00
DEBUG_PRINTLN ( " " ) ;
2020-09-20 01:18:31 +02:00
DEBUG_PRINT ( F ( " Connected! IP address: " ) ) ;
2020-11-13 18:25:13 +01:00
DEBUG_PRINTLN ( Network . localIP ( ) ) ;
2021-11-16 23:20:26 +01:00
if ( improvActive ) {
if ( improvError = = 3 ) sendImprovStateResponse ( 0x00 , true ) ;
sendImprovStateResponse ( 0x04 ) ;
2023-06-27 01:51:44 +02:00
if ( improvActive > 1 ) sendImprovIPRPCResult ( ImprovRPCType : : Command_Wifi ) ;
2021-11-16 23:20:26 +01:00
}
2020-04-10 12:30:08 +02:00
initInterfaces ( ) ;
userConnected ( ) ;
2020-05-28 02:20:02 +02:00
usermods . connected ( ) ;
2022-11-20 18:12:01 +01:00
lastMqttReconnectAttempt = 0 ; // force immediate update
2020-04-10 12:30:08 +02:00
// shut down AP
if ( apBehavior ! = AP_BEHAVIOR_ALWAYS & & apActive ) {
dnsServer . stop ( ) ;
WiFi . softAPdisconnect ( true ) ;
apActive = false ;
2021-11-25 06:41:37 +01:00
DEBUG_PRINTLN ( F ( " Access point disabled (handle). " ) ) ;
2020-04-10 12:30:08 +02:00
}
}
}
2020-10-19 18:08:45 +02:00
2021-08-23 14:14:48 +02:00
// If status LED pin is allocated for other uses, does nothing
// else blink at 1Hz when WLED_CONNECTED is false (no WiFi, ?? no Ethernet ??)
// else blink at 2Hz when MQTT is enabled but not connected
// else turn the status LED off
2020-10-19 18:08:45 +02:00
void WLED : : handleStatusLED ( )
{
2021-11-30 16:28:26 +01:00
# if defined(STATUSLED)
uint32_t c = 0 ;
2021-08-23 14:14:48 +02:00
2021-11-30 16:28:26 +01:00
# if STATUSLED>=0
2021-08-23 14:14:48 +02:00
if ( pinManager . isPinAllocated ( STATUSLED ) ) {
return ; //lower priority if something else uses the same pin
}
2021-11-30 16:28:26 +01:00
# endif
2021-01-17 00:20:31 +01:00
2021-11-30 16:28:26 +01:00
if ( WLED_CONNECTED ) {
c = RGBW32 ( 0 , 255 , 0 , 0 ) ;
ledStatusType = 2 ;
} else if ( WLED_MQTT_CONNECTED ) {
c = RGBW32 ( 0 , 128 , 0 , 0 ) ;
ledStatusType = 4 ;
} else if ( apActive ) {
c = RGBW32 ( 0 , 0 , 255 , 0 ) ;
2022-09-12 22:33:30 +02:00
ledStatusType = 1 ;
2021-08-23 14:14:48 +02:00
}
2020-10-19 18:08:45 +02:00
if ( ledStatusType ) {
if ( millis ( ) - ledStatusLastMillis > = ( 1000 / ledStatusType ) ) {
ledStatusLastMillis = millis ( ) ;
2021-11-30 16:28:26 +01:00
ledStatusState = ! ledStatusState ;
# if STATUSLED>=0
2020-10-19 18:08:45 +02:00
digitalWrite ( STATUSLED , ledStatusState ) ;
2021-11-30 16:28:26 +01:00
# else
busses . setStatusPixel ( ledStatusState ? c : 0 ) ;
# endif
2020-10-19 18:08:45 +02:00
}
} else {
2021-11-30 16:28:26 +01:00
# if STATUSLED>=0
# ifdef STATUSLEDINVERTED
2020-10-19 18:08:45 +02:00
digitalWrite ( STATUSLED , HIGH ) ;
2021-11-30 16:28:26 +01:00
# else
2020-10-19 18:08:45 +02:00
digitalWrite ( STATUSLED , LOW ) ;
2021-11-30 16:28:26 +01:00
# endif
# else
busses . setStatusPixel ( 0 ) ;
2020-10-19 18:08:45 +02:00
# endif
}
# endif
2021-10-11 10:56:25 +02:00
}