@ -1,22 +1,18 @@
// Define modules to compile:
// Define modules to compile:
# define MQTT_ENABLE // Make sure to configure mqtt-server and (optionally) username+pwd
//#define MQTT_ENABLE // Make sure to configure mqtt-server and (optionally) username+pwd
//#define FTP_ENABLE // Enables FTP-server
//#define FTP_ENABLE // Enables FTP-server
//#define NEOPIXEL_ENABLE // Don't forget configuration of NUM_LEDS if enabled
//#define NEOPIXEL_ENABLE // Don't forget configuration of NUM_LEDS if enabled
//#define NEOPIXEL_REVERSE_ROTATION // Some Neopixels are adressed/soldered counter-clockwise. This can be configured here.
//#define NEOPIXEL_REVERSE_ROTATION // Some Neopixels are adressed/soldered counter-clockwise. This can be configured here.
# define LANGUAGE 1 // 1 = deutsch; 2 = english
# define LANGUAGE 1 // 1 = deutsch; 2 = english
< < < < < < < HEAD
// #define HAL 1 // HAL 1 = LoLin32, 2 = AI AudioKit - no need to define when using platformIO
// #define HAL 2 // HAL 1 = LoLin32, 2 = AI AudioKit - no need to define when using platformIO
# define MFRC522_BUS 2 // If MFRC522 should be connected to I2C-Port(2) or SPI(1)
# define MFRC522_BUS 2 // If MFRC522 should be connected to I2C-Port(2) or SPI(1)
# define DISPLAY_I2C // If external Display via I2C connected - tested with SH1106_128X64_NONAME
//#define SD_NOT_MANDATORY_ENABLE // Only for debugging-purposes: Tonuino will also start without mounted SD-card anyway (will only try once to mount it)
= = = = = = =
# define HEADPHONE_ADJUST_ENABLE // Used to adjust (lower) volume for optional headphone-pcb (refer maxVolumeSpeaker / maxVolumeHeadphone)
//#define DISPLAY_I2C // If external Display via I2C connected - tested with SH1106_128X64_NONAME
// #define HEADPHONE_ADJUST_ENABLE // Used to adjust (lower) volume for optional headphone-pcb (refer maxVolumeSpeaker / maxVolumeHeadphone)
// #define SINGLE_SPI_ENABLE // If only one SPI-instance should be used instead of two (not yet working!)
// #define SINGLE_SPI_ENABLE // If only one SPI-instance should be used instead of two (not yet working!)
# define SHUTDOWN_IF_SD_BOOT_FAILS // Will put ESP to deepsleep if boot fails due to SD. Really recommend this if there's in battery-mode no other way to restart ESP! Interval adjustable via deepsleepTimeAfterBootFails.
// #define SHUTDOWN_IF_SD_BOOT_FAILS // Will put ESP to deepsleep if boot fails due to SD. Really recommend this if there's in battery-mode no other way to restart ESP! Interval adjustable via deepsleepTimeAfterBootFails.
//#define MEASURE_BATTERY_VOLTAGE // Enables battery-measurement via GPIO (ADC) and voltage-divider
//#define MEASURE_BATTERY_VOLTAGE // Enables battery-measurement via GPIO (ADC) and voltage-divider
//#define SD_NOT_MANDATORY_ENABLE // Only for debugging-purposes: Tonuino will also start without mounted SD-card anyway (will only try once to mount it). Will overwrite SHUTDOWN_IF_SD_BOOT_FAILS!
//#define SD_NOT_MANDATORY_ENABLE // Only for debugging-purposes: Tonuino will also start without mounted SD-card anyway (will only try once to mount it). Will overwrite SHUTDOWN_IF_SD_BOOT_FAILS!
> > > > > > > upstream / master
//#define BLUETOOTH_ENABLE // Doesn't work currently (so don't enable) as there's not enough DRAM available
//#define BLUETOOTH_ENABLE // Doesn't work currently (so don't enable) as there's not enough DRAM available
# include <ESP32Encoder.h>
# include <ESP32Encoder.h>
@ -87,9 +83,11 @@ char *logBuf = (char*) calloc(serialLoglength, sizeof(char)); // Buffer for all
// GPIOs (uSD card-reader)
// GPIOs (uSD card-reader)
# define SPISD_CS 15
# define SPISD_CS 15
# ifndef SINGLE_SPI_ENABLE
# define SPISD_MOSI 13
# define SPISD_MOSI 13
# define SPISD_MISO 16 // 12 doesn't work with some devel-boards
# define SPISD_MISO 16 // 12 doesn't work with some devel-boards
# define SPISD_SCK 14
# define SPISD_SCK 14
# endif
// GPIOs (RFID-readercurrentRfidTagId)
// GPIOs (RFID-readercurrentRfidTagId)
# define RST_PIN 99 // Not necessary but has to be set anyway; so let's use a dummy-number
# define RST_PIN 99 // Not necessary but has to be set anyway; so let's use a dummy-number
@ -103,20 +101,6 @@ char *logBuf = (char*) calloc(serialLoglength, sizeof(char)); // Buffer for all
# define I2S_BCLK 27
# define I2S_BCLK 27
# define I2S_LRC 26
# define I2S_LRC 26
// GPIO to detect if headphone was plugged in (pulled to GND)
# ifdef HEADPHONE_ADJUST_ENABLE
# define HP_DETECT 22 // Detects if there's a plug in the headphone jack or not
uint16_t headphoneLastDetectionDebounce = 1000 ; // Debounce-interval in ms when plugging in headphone
// Internal values
bool headphoneLastDetectionState ;
uint32_t headphoneLastDetectionTimestamp = 0 ;
# endif
# ifdef BLUETOOTH_ENABLE
BluetoothA2DPSink a2dp_sink ;
# endif
// GPIO used to trigger transistor-circuit / RFID-reader
// GPIO used to trigger transistor-circuit / RFID-reader
# define POWER 17
# define POWER 17
@ -172,17 +156,12 @@ MFRC522_SPI mfrcDevice = MFRC522_SPI(MFRC522_CS_PIN, MFRC522_RST_PIN);
# elif (MFRC522_BUS == 2)
# elif (MFRC522_BUS == 2)
# include <Wire.h>
# include <Wire.h>
# include <MFRC522_I2C.h>
# include <MFRC522_I2C.h>
# define MFRC522_RST_PIN POWER // needed for i2c-comm
# define MFRC522_RST_PIN 12 // needed for i2c-comm
// second I2C GPIOs
// second I2C GPIOs
# define ext_IIC_CLK 23 // 14-pin-header
# define ext_IIC_CLK 23 // 14-pin-header
# define ext_IIC_DATA 18 // 14-pin-header
# define ext_IIC_DATA 18 // 14-pin-header
# endif
# endif
# ifdef DISPLAY_I2C
// OLED Display - https://github.com/olikraus/u8g2/wiki/u8g2setupcpp#sh1106-128x64_noname-1
U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2 ( U8G2_R0 , /* reset=*/ U8X8_PIN_NONE , /* clock=*/ ext_IIC_CLK , /* data=*/ ext_IIC_DATA ) ;
# endif
// DAC (internal)
// DAC (internal)
# define I2S_DSIN 25 // internal
# define I2S_DSIN 25 // internal
# define I2S_BCLK 27 // internal
# define I2S_BCLK 27 // internal
@ -197,9 +176,6 @@ U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* c
// Amp enable
// Amp enable
# define GPIO_PA_EN 21 // internal
# define GPIO_PA_EN 21 // internal
// Headphone?
# define HEADPHONE_PLUGGED_IN 39 // internal
// GPIOs (Rotary encoder)
// GPIOs (Rotary encoder)
# define DREHENCODER_CLK 5
# define DREHENCODER_CLK 5
# define DREHENCODER_DT 18
# define DREHENCODER_DT 18
@ -207,9 +183,8 @@ U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* c
// GPIOs (Control-buttons) // Currently deactivated; please read README.md
// GPIOs (Control-buttons) // Currently deactivated; please read README.md
# define PAUSEPLAY_BUTTON 36
# define PAUSEPLAY_BUTTON 36
/*#define NEXT_BUTTON 4
# define PREVIOUS_BUTTON 33* /
# define NEXT_BUTTON 199
# define PREVIOUS_BUTTON 198
// GPIOs (LEDs)
// GPIOs (LEDs)
# define LED_PIN 23
# define LED_PIN 23
@ -217,6 +192,19 @@ U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* c
// END HAL 2
// END HAL 2
# endif
# endif
// GPIO to detect if headphone was plugged in (pulled to GND)
# ifdef HEADPHONE_ADJUST_ENABLE
// HAL 2
# define HEADPHONE_PLUGGED_IN 39 // internal
// HAL 1
# define HP_DETECT 22 // Detects if there's a plug in the headphone jack or not
uint16_t headphoneLastDetectionDebounce = 1000 ; // Debounce-interval in ms when plugging in headphone
// Internal values
bool headphoneLastDetectionState ;
uint32_t headphoneLastDetectionTimestamp = 0 ;
# endif
# ifdef BLUETOOTH_ENABLE
# ifdef BLUETOOTH_ENABLE
BluetoothA2DPSink a2dp_sink ;
BluetoothA2DPSink a2dp_sink ;
# endif
# endif
@ -262,6 +250,7 @@ U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* c
# define REPEAT_PLAYLIST 110 // Changes active playmode to endless-loop (for a playlist)
# define REPEAT_PLAYLIST 110 // Changes active playmode to endless-loop (for a playlist)
# define REPEAT_TRACK 111 // Changes active playmode to endless-loop (for a single track)
# define REPEAT_TRACK 111 // Changes active playmode to endless-loop (for a single track)
# define DIMM_LEDS_NIGHTMODE 120 // Changes LED-brightness
# define DIMM_LEDS_NIGHTMODE 120 // Changes LED-brightness
# define TOGGLE_WIFI_STATUS 130 // Toggles WiFi-status; effective after next reboot
// Repeat-Modes
// Repeat-Modes
# define NO_REPEAT 0 // No repeat
# define NO_REPEAT 0 // No repeat
@ -287,7 +276,6 @@ typedef struct { // Bit field
bool playlistFinished : 1 ; // If whole playlist is finished
bool playlistFinished : 1 ; // If whole playlist is finished
uint8_t playUntilTrackNumber : 6 ; // Number of tracks to play after which uC goes to sleep
uint8_t playUntilTrackNumber : 6 ; // Number of tracks to play after which uC goes to sleep
} playProps ;
} playProps ;
//playProps *playProperties = (playProps*) malloc(sizeof(playProps));
playProps playProperties ;
playProps playProperties ;
typedef struct {
typedef struct {
@ -343,6 +331,10 @@ static const char backupFile[] PROGMEM = "/backup.txt"; // File is written every
// HELPER //
// HELPER //
// WiFi
// WiFi
unsigned long wifiCheckLastTimestamp = 0 ;
unsigned long wifiCheckLastTimestamp = 0 ;
bool wifiEnabled ; // Current status if wifi is enabled
uint32_t wifiStatusToggledTimestamp = 0 ;
bool webserverStarted = false ;
bool wifiNeedsRestart = false ;
// Neopixel
// Neopixel
# ifdef NEOPIXEL_ENABLE
# ifdef NEOPIXEL_ENABLE
bool showLedError = false ;
bool showLedError = false ;
@ -493,6 +485,8 @@ bool endsWith (const char *str, const char *suf);
bool fileValid ( const char * _fileItem ) ;
bool fileValid ( const char * _fileItem ) ;
void freeMultiCharArray ( char * * arr , const uint32_t cnt ) ;
void freeMultiCharArray ( char * * arr , const uint32_t cnt ) ;
uint8_t getRepeatMode ( void ) ;
uint8_t getRepeatMode ( void ) ;
bool getWifiEnableStatusFromNVS ( void ) ;
void handleUpload ( AsyncWebServerRequest * request , String filename , size_t index , uint8_t * data , size_t len , bool final ) ;
void headphoneVolumeManager ( void ) ;
void headphoneVolumeManager ( void ) ;
bool isNumber ( const char * str ) ;
bool isNumber ( const char * str ) ;
void loggerNl ( const char * str , const uint8_t logLevel ) ;
void loggerNl ( const char * str , const uint8_t logLevel ) ;
@ -525,7 +519,7 @@ void trackQueueDispatcher(const char *_sdFile, const uint32_t _lastPlayPos, cons
void volumeHandler ( const int32_t _minVolume , const int32_t _maxVolume ) ;
void volumeHandler ( const int32_t _minVolume , const int32_t _maxVolume ) ;
void volumeToQueueSender ( const int32_t _newVolume ) ;
void volumeToQueueSender ( const int32_t _newVolume ) ;
wl_status_t wifiManager ( void ) ;
wl_status_t wifiManager ( void ) ;
bool writeWifiStatusToNVS ( bool wifiStatus ) ;
/* Wrapper-Funktion for Serial-logging (with newline) */
/* Wrapper-Funktion for Serial-logging (with newline) */
void loggerNl ( const char * str , const uint8_t logLevel ) {
void loggerNl ( const char * str , const uint8_t logLevel ) {
@ -555,40 +549,6 @@ int countChars(const char* string, char ch) {
return count ;
return count ;
}
}
// Used to print content of sd-card (currently not used, maybe later :-))
/*void printSdContent(File dir, uint16_t allocSize, uint8_t allocCount, char *sdContent, uint8_t depth) {
while ( true ) {
File entry = dir . openNextFile ( ) ;
if ( ! entry ) {
dir . rewindDirectory ( ) ;
break ;
}
if ( countChars ( entry . name ( ) , ' / ' ) > depth + 1 ) {
continue ;
}
Serial . println ( entry . name ( ) ) ;
if ( ( strlen ( sdContent ) + strlen ( entry . name ( ) ) + 2 ) > = allocCount * allocSize ) {
sdContent = ( char * ) realloc ( sdContent , + + allocCount * allocSize ) ;
Serial . printf ( " Free heap: %u " , ESP . getFreeHeap ( ) ) ;
Serial . printf ( " realloc! -%d- \n " , allocCount ) ;
if ( sdContent = = NULL ) {
return ;
}
}
strcat ( sdContent , stringDelimiter ) ;
strcat ( sdContent , entry . name ( ) ) ;
if ( entry . isDirectory ( ) ) {
printSdContent ( entry , allocSize , allocCount , sdContent , depth ) ;
}
entry . close ( ) ;
}
} */
void IRAM_ATTR onTimer ( ) {
void IRAM_ATTR onTimer ( ) {
xSemaphoreGiveFromISR ( timerSemaphore , NULL ) ;
xSemaphoreGiveFromISR ( timerSemaphore , NULL ) ;
}
}
@ -616,7 +576,6 @@ void IRAM_ATTR onTimer() {
# endif
# endif
snprintf ( logBuf , serialLoglength , " %s: %.2f V " , ( char * ) FPSTR ( currentVoltageMsg ) , voltage ) ;
snprintf ( logBuf , serialLoglength , " %s: %.2f V " , ( char * ) FPSTR ( currentVoltageMsg ) , voltage ) ;
loggerNl ( logBuf , LOGLEVEL_INFO ) ;
loggerNl ( logBuf , LOGLEVEL_INFO ) ;
//Serial.printf("Spannung: %f\n", voltage);
lastVoltageCheckTimestamp = millis ( ) ;
lastVoltageCheckTimestamp = millis ( ) ;
}
}
}
}
@ -630,10 +589,8 @@ void buttonHandler() {
return ;
return ;
}
}
unsigned long currentTimestamp = millis ( ) ;
unsigned long currentTimestamp = millis ( ) ;
# if (HAL == 1)
buttons [ 0 ] . currentState = digitalRead ( NEXT_BUTTON ) ;
buttons [ 0 ] . currentState = digitalRead ( NEXT_BUTTON ) ;
buttons [ 1 ] . currentState = digitalRead ( PREVIOUS_BUTTON ) ;
buttons [ 1 ] . currentState = digitalRead ( PREVIOUS_BUTTON ) ;
# endif
buttons [ 2 ] . currentState = digitalRead ( PAUSEPLAY_BUTTON ) ;
buttons [ 2 ] . currentState = digitalRead ( PAUSEPLAY_BUTTON ) ;
buttons [ 3 ] . currentState = digitalRead ( DREHENCODER_BUTTON ) ;
buttons [ 3 ] . currentState = digitalRead ( DREHENCODER_BUTTON ) ;
@ -660,6 +617,25 @@ void doButtonActions(void) {
return ; // Avoid button-handling if buttons are locked
return ; // Avoid button-handling if buttons are locked
}
}
// WiFi-toggle
if ( buttons [ 0 ] . isPressed & & buttons [ 1 ] . isPressed ) {
if ( ! wifiStatusToggledTimestamp | | ( millis ( ) - wifiStatusToggledTimestamp > = 2000 ) ) {
wifiStatusToggledTimestamp = millis ( ) ;
buttons [ 0 ] . isPressed = false ;
buttons [ 1 ] . isPressed = false ;
if ( writeWifiStatusToNVS ( ! getWifiEnableStatusFromNVS ( ) ) ) {
# ifdef NEOPIXEL_ENABLE
showLedOk = true ; // Tell user action was accepted
# endif
} else {
# ifdef NEOPIXEL_ENABLE
showLedError = true ; // Tell user action failed
# endif
}
}
return ;
}
for ( uint8_t i = 0 ; i < sizeof ( buttons ) / sizeof ( buttons [ 0 ] ) ; i + + ) {
for ( uint8_t i = 0 ; i < sizeof ( buttons ) / sizeof ( buttons [ 0 ] ) ; i + + ) {
if ( buttons [ i ] . isPressed ) {
if ( buttons [ i ] . isPressed ) {
if ( buttons [ i ] . lastReleasedTimestamp > buttons [ i ] . lastPressedTimestamp ) {
if ( buttons [ i ] . lastReleasedTimestamp > buttons [ i ] . lastPressedTimestamp ) {
@ -1314,9 +1290,25 @@ size_t nvsRfidWriteWrapper (const char *_rfidCardId, const char *_track, const u
// Function to play music as task
// Function to play music as task
void playAudio ( void * parameter ) {
void playAudio ( void * parameter ) {
static Audio audio ;
static Audio audio ;
# if (HAL == 2)
static AC101 ac ;
static bool currentHeadphoneState = digitalRead ( HEADPHONE_PLUGGED_IN ) ;
static bool lastHeadphoneState = currentHeadphoneState ;
static uint32_t lastHeadphoneStateTimestamp = 0 ;
while ( ! ac . begin ( IIC_DATA , IIC_CLK ) ) {
Serial . printf ( " Failed! \n " ) ;
delay ( 1000 ) ;
}
pinMode ( GPIO_PA_EN , OUTPUT ) ;
digitalWrite ( GPIO_PA_EN , HIGH ) ;
# endif
audio . setPinout ( I2S_BCLK , I2S_LRC , I2S_DOUT ) ;
audio . setPinout ( I2S_BCLK , I2S_LRC , I2S_DOUT ) ;
audio . setVolume ( initVolume ) ;
audio . setVolume ( initVolume ) ;
uint8_t currentVolume ;
uint8_t currentVolume ;
static BaseType_t trackQStatus ;
static BaseType_t trackQStatus ;
static uint8_t trackCommand = 0 ;
static uint8_t trackCommand = 0 ;
@ -1394,6 +1386,8 @@ void playAudio(void *parameter) {
trackCommand = 0 ;
trackCommand = 0 ;
loggerNl ( ( char * ) FPSTR ( cmndStop ) , LOGLEVEL_INFO ) ;
loggerNl ( ( char * ) FPSTR ( cmndStop ) , LOGLEVEL_INFO ) ;
playProperties . pausePlay = true ;
playProperties . pausePlay = true ;
playProperties . playlistFinished = true ;
playProperties . playMode = NO_PLAYLIST ;
continue ;
continue ;
case PAUSEPLAY :
case PAUSEPLAY :
@ -1659,8 +1653,15 @@ void playAudio(void *parameter) {
// Instructs RFID-scanner to scan for new RFID-tags
// Instructs RFID-scanner to scan for new RFID-tags
void rfidScanner ( void * parameter ) {
void rfidScanner ( void * parameter ) {
# if (MFRC522_BUS == 1)
static MFRC522 mfrc522 ( RFID_CS , RST_PIN ) ;
# elif (MFRC522_BUS == 2)
TwoWire i2cBus = TwoWire ( 1 ) ;
i2cBus . begin ( ext_IIC_DATA , ext_IIC_CLK , 40000 ) ;
static MFRC522 mfrc522 ( MFRC522_RST_PIN , 0x28 , i2cBus ) ;
# endif
mfrc522 . PCD_Init ( ) ;
mfrc522 . PCD_Init ( ) ;
delay ( 50 ) ;
mfrc522 . PCD_DumpVersionToSerial ( ) ; // Show details of PCD - MFRC522 Card Reader detail
mfrc522 . PCD_DumpVersionToSerial ( ) ; // Show details of PCD - MFRC522 Card Reader detail
delay ( 4 ) ;
delay ( 4 ) ;
loggerNl ( ( char * ) FPSTR ( rfidScannerReady ) , LOGLEVEL_DEBUG ) ;
loggerNl ( ( char * ) FPSTR ( rfidScannerReady ) , LOGLEVEL_DEBUG ) ;
@ -1712,13 +1713,12 @@ void rfidScanner(void *parameter) {
}
}
}
}
xQueueSend ( rfidCardQueue , & cardIdString , 0 ) ;
xQueueSend ( rfidCardQueue , & cardIdString , 0 ) ;
free ( cardIdString ) ;
// free(cardIdString);
}
}
}
}
vTaskDelete ( NULL ) ;
vTaskDelete ( NULL ) ;
}
}
// This task handles everything for Neopixel-visualisation
// This task handles everything for Neopixel-visualisation
# ifdef NEOPIXEL_ENABLE
# ifdef NEOPIXEL_ENABLE
@ -1938,16 +1938,16 @@ void showLed(void *parameter) {
if ( hlastVolume = = currentVolume & & lastLedBrightness = = ledBrightness ) {
if ( hlastVolume = = currentVolume & & lastLedBrightness = = ledBrightness ) {
for ( uint8_t i = 0 ; i < NUM_LEDS ; i + + ) {
for ( uint8_t i = 0 ; i < NUM_LEDS ; i + + ) {
FastLED . clear ( ) ;
FastLED . clear ( ) ;
if ( ledAddress ( i ) = = 0 ) {
leds [ 0 ] = CRGB : : White ;
leds [ NUM_LEDS / 4 ] = CRGB : : White ;
leds [ NUM_LEDS / 2 ] = CRGB : : White ;
leds [ NUM_LEDS / 4 * 3 ] = CRGB : : White ;
if ( ledAddress ( i ) = = 0 ) { // White if Wifi is enabled and blue if not
leds [ 0 ] = ( wifiManager ( ) = = WL_CONNECTED ) ? CRGB : : White : CRGB : : Blu e ;
leds [ NUM_LEDS / 4 ] = ( wifiManager ( ) = = WL_CONNECTED ) ? CRGB : : White : CRGB : : Blu e ;
leds [ NUM_LEDS / 2 ] = ( wifiManager ( ) = = WL_CONNECTED ) ? CRGB : : White : CRGB : : Blu e ;
leds [ NUM_LEDS / 4 * 3 ] = ( wifiManager ( ) = = WL_CONNECTED ) ? CRGB : : White : CRGB : : Blu e ;
} else {
} else {
leds [ ledAddress ( i ) % NUM_LEDS ] = CRGB : : White ;
leds [ ( ledAddress ( i ) + NUM_LEDS / 4 ) % NUM_LEDS ] = CRGB : : White ;
leds [ ( ledAddress ( i ) + NUM_LEDS / 2 ) % NUM_LEDS ] = CRGB : : White ;
leds [ ( ledAddress ( i ) + NUM_LEDS / 4 * 3 ) % NUM_LEDS ] = CRGB : : White ;
leds [ ledAddress ( i ) % NUM_LEDS ] = ( wifiManager ( ) = = WL_CONNECTED ) ? CRGB : : White : CRGB : : Blu e ;
leds [ ( ledAddress ( i ) + NUM_LEDS / 4 ) % NUM_LEDS ] = ( wifiManager ( ) = = WL_CONNECTED ) ? CRGB : : White : CRGB : : Blu e ;
leds [ ( ledAddress ( i ) + NUM_LEDS / 2 ) % NUM_LEDS ] = ( wifiManager ( ) = = WL_CONNECTED ) ? CRGB : : White : CRGB : : Blu e ;
leds [ ( ledAddress ( i ) + NUM_LEDS / 4 * 3 ) % NUM_LEDS ] = ( wifiManager ( ) = = WL_CONNECTED ) ? CRGB : : White : CRGB : : Blu e ;
}
}
FastLED . show ( ) ;
FastLED . show ( ) ;
for ( uint8_t i = 0 ; i < = 50 ; i + + ) {
for ( uint8_t i = 0 ; i < = 50 ; i + + ) {
@ -2018,14 +2018,15 @@ void showLed(void *parameter) {
leds [ ledAddress ( led ) ] = CRGB : : Red ;
leds [ ledAddress ( led ) ] = CRGB : : Red ;
} else if ( ! playProperties . pausePlay ) { // Hue-rainbow
} else if ( ! playProperties . pausePlay ) { // Hue-rainbow
leds [ ledAddress ( led ) ] . setHue ( ( uint8_t ) ( 85 - ( ( double ) 95 / NUM_LEDS ) * led ) ) ;
leds [ ledAddress ( led ) ] . setHue ( ( uint8_t ) ( 85 - ( ( double ) 95 / NUM_LEDS ) * led ) ) ;
} else if ( playProperties . pausePlay ) {
leds [ ledAddress ( led ) % NUM_LEDS ] = CRGB : : Orange ;
leds [ ( ledAddress ( led ) + NUM_LEDS / 4 ) % NUM_LEDS ] = CRGB : : Orange ;
leds [ ( ledAddress ( led ) + NUM_LEDS / 2 ) % NUM_LEDS ] = CRGB : : Orange ;
leds [ ( ledAddress ( led ) + NUM_LEDS / 4 * 3 ) % NUM_LEDS ] = CRGB : : Orange ;
break ;
}
}
}
}
if ( playProperties . pausePlay ) {
leds [ ledAddress ( 0 ) ] = CRGB : : Orange ;
leds [ ( ledAddress ( NUM_LEDS / 4 ) ) % NUM_LEDS ] = CRGB : : Orange ;
leds [ ( ledAddress ( NUM_LEDS / 2 ) ) % NUM_LEDS ] = CRGB : : Orange ;
leds [ ( ledAddress ( NUM_LEDS / 4 * 3 ) ) % NUM_LEDS ] = CRGB : : Orange ;
break ;
}
}
}
} else { // ... but do things a little bit different for Webstream as there's no progress available
} else { // ... but do things a little bit different for Webstream as there's no progress available
if ( lastSwitchTimestamp = = 0 | | ( millis ( ) - lastSwitchTimestamp > = ledSwitchInterval * 1000 ) | | redrawProgress ) {
if ( lastSwitchTimestamp = = 0 | | ( millis ( ) - lastSwitchTimestamp > = ledSwitchInterval * 1000 ) | | redrawProgress ) {
@ -2666,6 +2667,19 @@ void doRfidCardModifications(const uint32_t mod) {
# endif
# endif
break ;
break ;
case TOGGLE_WIFI_STATUS :
if ( writeWifiStatusToNVS ( ! getWifiEnableStatusFromNVS ( ) ) ) {
# ifdef NEOPIXEL_ENABLE
showLedOk = true ;
# endif
} else {
# ifdef NEOPIXEL_ENABLE
showLedError = true ;
# endif
}
break ;
default :
default :
snprintf ( logBuf , serialLoglength , " %s %d ! " , ( char * ) FPSTR ( modificatorDoesNotExist ) , mod ) ;
snprintf ( logBuf , serialLoglength , " %s %d ! " , ( char * ) FPSTR ( modificatorDoesNotExist ) , mod ) ;
loggerNl ( logBuf , LOGLEVEL_ERROR ) ;
loggerNl ( logBuf , LOGLEVEL_ERROR ) ;
@ -2690,6 +2704,7 @@ void rfidPreferenceLookupHandler (void) {
lastTimeActiveTimestamp = millis ( ) ;
lastTimeActiveTimestamp = millis ( ) ;
free ( currentRfidTagId ) ;
free ( currentRfidTagId ) ;
currentRfidTagId = strdup ( rfidTagId ) ;
currentRfidTagId = strdup ( rfidTagId ) ;
free ( rfidTagId ) ;
snprintf ( logBuf , serialLoglength , " %s: %s " , ( char * ) FPSTR ( rfidTagReceived ) , currentRfidTagId ) ;
snprintf ( logBuf , serialLoglength , " %s: %s " , ( char * ) FPSTR ( rfidTagReceived ) , currentRfidTagId ) ;
sendWebsocketData ( 0 , 10 ) ; // Push new rfidTagId to all websocket-clients
sendWebsocketData ( 0 , 10 ) ; // Push new rfidTagId to all websocket-clients
loggerNl ( logBuf , LOGLEVEL_INFO ) ;
loggerNl ( logBuf , LOGLEVEL_INFO ) ;
@ -2775,10 +2790,53 @@ void accessPointStart(const char *SSID, IPAddress ip, IPAddress netmask) {
accessPointStarted = true ;
accessPointStarted = true ;
}
}
// Reads stored WiFi-status from NVS
bool getWifiEnableStatusFromNVS ( void ) {
uint32_t wifiStatus = prefsSettings . getUInt ( " enableWifi " , 99 ) ;
// if not set so far, preseed with 1 (enable)
if ( wifiStatus = = 99 ) {
prefsSettings . putUInt ( " enableWifi " , 1 ) ;
wifiStatus = 1 ;
}
return wifiStatus ;
}
// Writes to NVS whether WiFi should be activated (not effective until next reboot!)
bool writeWifiStatusToNVS ( bool wifiStatus ) {
if ( ! wifiStatus ) {
if ( prefsSettings . putUInt ( " enableWifi " , 0 ) ) { // disable
loggerNl ( ( char * ) FPSTR ( wifiDisabledAfterRestart ) , LOGLEVEL_NOTICE ) ;
if ( playProperties . playMode = = WEBSTREAM ) {
trackControlToQueueSender ( STOP ) ;
}
delay ( 300 ) ;
WiFi . mode ( WIFI_OFF ) ;
wifiEnabled = false ;
return true ;
}
} else {
if ( prefsSettings . putUInt ( " enableWifi " , 1 ) ) { // enable
loggerNl ( ( char * ) FPSTR ( wifiEnabledAfterRestart ) , LOGLEVEL_NOTICE ) ;
wifiNeedsRestart = true ;
wifiEnabled = true ;
return true ;
}
}
}
// Provides management for WiFi
// Provides management for WiFi
wl_status_t wifiManager ( void ) {
wl_status_t wifiManager ( void ) {
if ( wifiCheckLastTimestamp = = 0 ) {
// If wifi whould not be activated, return instantly
if ( ! wifiEnabled ) {
return WiFi . status ( ) ;
}
if ( ! wifiCheckLastTimestamp | | wifiNeedsRestart ) {
// Get credentials from NVS
// Get credentials from NVS
String strSSID = prefsSettings . getString ( " SSID " , " -1 " ) ;
String strSSID = prefsSettings . getString ( " SSID " , " -1 " ) ;
if ( ! strSSID . compareTo ( " -1 " ) ) {
if ( ! strSSID . compareTo ( " -1 " ) ) {
@ -2791,28 +2849,6 @@ wl_status_t wifiManager(void) {
const char * _ssid = strSSID . c_str ( ) ;
const char * _ssid = strSSID . c_str ( ) ;
const char * _pwd = strPassword . c_str ( ) ;
const char * _pwd = strPassword . c_str ( ) ;
/*
// Get (optional) static-IP-configration from NVS
String strStaticIp = prefsSettings . getString ( " staticIP " , " -1 " ) ;
String strStaticIpGw = prefsSettings . getString ( " staticIPGw " , " -1 " ) ;
String strStaticIpNetmask = prefsSettings . getString ( " staticIPNetmask " , " -1 " ) ;
if ( ! strStaticIp . compareTo ( " -1 " ) | | ! strStaticIpGw . compareTo ( " -1 " ) | | ! strStaticIpNetmask . compareTo ( " -1 " ) ) {
loggerNl ( ( char * ) FPSTR ( wifiStaticIpConfigNotFoundInNvs ) , LOGLEVEL_INFO ) ;
} else {
IPAddress staticWifiIp ;
IPAddress staticWifiIpGw ;
IPAddress staticWifiIpNetmask ;
if ( strStaticIp . length ( ) > = 7 & & strStaticIpGw . length ( ) > = 7 & & strStaticIpNetmask . length ( ) > = 7 ) {
staticWifiIp . fromString ( strStaticIp . c_str ( ) ) ;
staticWifiIpGw . fromString ( strStaticIpGw . c_str ( ) ) ;
staticWifiIpNetmask . fromString ( strStaticIpNetmask . c_str ( ) ) ;
WiFi . config ( staticWifiIp , staticWifiIpGw , staticWifiIpNetmask ) ;
} else {
Serial . println ( " IP-config nicht gueltig! " ) ;
}
} */
// Get (optional) hostname-configration from NVS
// Get (optional) hostname-configration from NVS
String hostname = prefsSettings . getString ( " Hostname " , " -1 " ) ;
String hostname = prefsSettings . getString ( " Hostname " , " -1 " ) ;
if ( hostname . compareTo ( " -1 " ) ) {
if ( hostname . compareTo ( " -1 " ) ) {
@ -2847,6 +2883,7 @@ wl_status_t wifiManager(void) {
} else { // Starts AP if WiFi-connect wasn't successful
} else { // Starts AP if WiFi-connect wasn't successful
accessPointStart ( ( char * ) FPSTR ( accessPointNetworkSSID ) , apIP , apNetmask ) ;
accessPointStart ( ( char * ) FPSTR ( accessPointNetworkSSID ) , apIP , apNetmask ) ;
}
}
wifiNeedsRestart = false ;
}
}
return WiFi . status ( ) ;
return WiFi . status ( ) ;
@ -2899,12 +2936,6 @@ String templateProcessor(const String& templ) {
return String ( logBuf ) ;
return String ( logBuf ) ;
} else if ( templ = = " RFID_TAG_ID " ) {
} else if ( templ = = " RFID_TAG_ID " ) {
return String ( currentRfidTagId ) ;
return String ( currentRfidTagId ) ;
/*} else if (templ == "STATIC_IP") {
return prefsSettings . getString ( " staticIP " , " -1 " ) ;
} else if ( templ = = " STATIC_IP_GW " ) {
return prefsSettings . getString ( " staticIPGw " , " -1 " ) ;
} else if ( templ = = " STATIC_IP_NETMASK " ) {
return prefsSettings . getString ( " staticIPNetmask " , " -1 " ) ; */
} else if ( templ = = " HOSTNAME " ) {
} else if ( templ = = " HOSTNAME " ) {
return prefsSettings . getString ( " Hostname " , " -1 " ) ;
return prefsSettings . getString ( " Hostname " , " -1 " ) ;
}
}
@ -2944,7 +2975,7 @@ bool processJsonRequest(char *_serialJson) {
// Check if settings were written successfully
// Check if settings were written successfully
if ( prefsSettings . getUInt ( " initVolume " , 0 ) ! = iVol | |
if ( prefsSettings . getUInt ( " initVolume " , 0 ) ! = iVol | |
prefsSettings . getUInt ( " maxVolumeSp " , 0 ) ! = mVolSpeaker | |
prefsSettings . getUInt ( " maxVolumeSp " , 0 ) ! = mVolSpeaker | |
prefsSettings . getUInt ( " maxVolumeHp " , 0 ) ! = mVolHeadphone |
prefsSettings . getUInt ( " maxVolumeHp " , 0 ) ! = mVolHeadphone | |
prefsSettings . getUChar ( " iLedBrightness " , 0 ) ! = iBright | |
prefsSettings . getUChar ( " iLedBrightness " , 0 ) ! = iBright | |
prefsSettings . getUChar ( " nLedBrightness " , 0 ) ! = nBright | |
prefsSettings . getUChar ( " nLedBrightness " , 0 ) ! = nBright | |
prefsSettings . getUInt ( " mInactiviyT " , 0 ) ! = iTime ) {
prefsSettings . getUInt ( " mInactiviyT " , 0 ) ! = iTime ) {
@ -2983,15 +3014,6 @@ bool processJsonRequest(char *_serialJson) {
return false ;
return false ;
}
}
/*} else if (doc.containsKey("staticIP")) {
const char * _staticIp = object [ " ip " ] [ " staticIP " ] ;
const char * _staticIpGW = doc [ " ip " ] [ " staticIPGW " ] ;
const char * _staticIpNM = doc [ " ip " ] [ " staticIPNM " ] ;
prefsSettings . putString ( " staticIP " , ( String ) _staticIp ) ;
prefsSettings . putString ( " staticIPGw " , ( String ) _staticIpGW ) ;
prefsSettings . putString ( " staticIPNetmask " , ( String ) _staticIpNM ) ; */
} else if ( doc . containsKey ( " rfidMod " ) ) {
} else if ( doc . containsKey ( " rfidMod " ) ) {
const char * _rfidIdModId = object [ " rfidMod " ] [ " rfidIdMod " ] ;
const char * _rfidIdModId = object [ " rfidMod " ] [ " rfidIdMod " ] ;
uint8_t _modId = object [ " rfidMod " ] [ " modId " ] ;
uint8_t _modId = object [ " rfidMod " ] [ " modId " ] ;
@ -3080,7 +3102,7 @@ void onWebsocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsE
client - > ping ( ) ;
client - > ping ( ) ;
} else if ( type = = WS_EVT_DISCONNECT ) {
} else if ( type = = WS_EVT_DISCONNECT ) {
//client disconnected
//client disconnected
Serial . printf ( " ws[%s][%u] disconnect: %u \n " , server - > url ( ) , client - > id ( ) ) ;
Serial . printf ( " ws[%s][%u] disconnect \n " , server - > url ( ) , client - > id ( ) ) ;
} else if ( type = = WS_EVT_ERROR ) {
} else if ( type = = WS_EVT_ERROR ) {
//error was received from the other end
//error was received from the other end
Serial . printf ( " ws[%s][%u] error(%u): %s \n " , server - > url ( ) , client - > id ( ) , * ( ( uint16_t * ) arg ) , ( char * ) data ) ;
Serial . printf ( " ws[%s][%u] error(%u): %s \n " , server - > url ( ) , client - > id ( ) , * ( ( uint16_t * ) arg ) , ( char * ) data ) ;
@ -3100,6 +3122,7 @@ void onWebsocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsE
} else {
} else {
returnCode = 0 ;
returnCode = 0 ;
}
}
sendWebsocketData ( client - > id ( ) , 1 ) ;
sendWebsocketData ( client - > id ( ) , 1 ) ;
if ( info - > opcode = = WS_TEXT ) {
if ( info - > opcode = = WS_TEXT ) {
@ -3173,6 +3196,34 @@ bool isNumber(const char *str) {
}
}
void webserverStart ( void ) {
if ( wifiManager ( ) = = WL_CONNECTED & & ! webserverStarted ) {
// attach AsyncWebSocket for Mgmt-Interface
ws . onEvent ( onWebsocketEvent ) ;
wServer . addHandler ( & ws ) ;
// attach AsyncEventSource
wServer . addHandler ( & events ) ;
wServer . on ( " / " , HTTP_GET , [ ] ( AsyncWebServerRequest * request ) {
request - > send_P ( 200 , " text/html " , mgtWebsite , templateProcessor ) ;
} ) ;
wServer . on ( " /upload " , HTTP_POST , [ ] ( AsyncWebServerRequest * request ) {
request - > send_P ( 200 , " text/html " , backupRecoveryWebsite ) ;
} , handleUpload ) ;
wServer . on ( " /restart " , HTTP_GET , [ ] ( AsyncWebServerRequest * request ) {
request - > send_P ( 200 , " text/html " , restartWebsite ) ;
Serial . flush ( ) ;
ESP . restart ( ) ;
} ) ;
wServer . onNotFound ( notFound ) ;
wServer . begin ( ) ;
webserverStarted = true ;
}
}
// Dumps all RFID-entries from NVS into a file on SD-card
// Dumps all RFID-entries from NVS into a file on SD-card
bool dumpNvsToSd ( char * _namespace , char * _destFile ) {
bool dumpNvsToSd ( char * _namespace , char * _destFile ) {
@ -3282,7 +3333,7 @@ void setup() {
esp_sleep_enable_ext0_wakeup ( ( gpio_num_t ) DREHENCODER_BUTTON , 0 ) ;
esp_sleep_enable_ext0_wakeup ( ( gpio_num_t ) DREHENCODER_BUTTON , 0 ) ;
srand ( esp_random ( ) ) ;
srand ( esp_random ( ) ) ;
pinMode ( POWER , OUTPUT ) ;
pinMode ( POWER , OUTPUT ) ;
// digitalWrite(POWER, HIGH);
digitalWrite ( POWER , HIGH ) ;
prefsRfid . begin ( ( char * ) FPSTR ( prefsRfidNamespace ) ) ;
prefsRfid . begin ( ( char * ) FPSTR ( prefsRfidNamespace ) ) ;
prefsSettings . begin ( ( char * ) FPSTR ( prefsSettingsNamespace ) ) ;
prefsSettings . begin ( ( char * ) FPSTR ( prefsSettingsNamespace ) ) ;
@ -3310,25 +3361,6 @@ void setup() {
prefsRfid . putString ( " 228064156042 " , " #0#0#110#0 " ) ; // modification-card (repeat playlist)
prefsRfid . putString ( " 228064156042 " , " #0#0#110#0 " ) ; // modification-card (repeat playlist)
prefsRfid . putString ( " 212130160042 " , " #/mp3/Hoerspiele/Yakari/Sammlung2#0#3#0 " ) ; */
prefsRfid . putString ( " 212130160042 " , " #/mp3/Hoerspiele/Yakari/Sammlung2#0#3#0 " ) ; */
# if (MFRC522_BUS == 1)
# ifndef SINGLE_SPI_ENABLE
SPI . begin ( ) ;
# endif
# elif (MFRC522_BUS == 2)
TwoWire i2cBus = TwoWire ( 1 ) ;
i2cBus . begin ( ext_IIC_DATA , ext_IIC_CLK , 40000 ) ;
MFRC522 mfrcdevice ( MFRC522_RST_PIN , 0x28 , i2cBus ) ;
// END MFRC522_BUS
i2cBus . beginTransmission ( 40 ) ;
if ( i2cBus . endTransmission ( ) = = 0 ) {
String s ;
s + = " I2C device found at 0x " ;
s + = String ( 40 , HEX ) ;
s + = " \n " ;
Serial . println ( s ) ;
}
# endif
# ifdef NEOPIXEL_ENABLE
# ifdef NEOPIXEL_ENABLE
xTaskCreatePinnedToCore (
xTaskCreatePinnedToCore (
showLed , /* Function to implement the task */
showLed , /* Function to implement the task */
@ -3341,6 +3373,12 @@ if (i2cBus.endTransmission() == 0) {
) ;
) ;
# endif
# endif
# if (MFRC522_BUS == 1)
# ifndef SINGLE_SPI_ENABLE
SPI . begin ( ) ;
# endif
# endif
// Init uSD-SPI
// Init uSD-SPI
pinMode ( SPISD_CS , OUTPUT ) ;
pinMode ( SPISD_CS , OUTPUT ) ;
digitalWrite ( SPISD_CS , HIGH ) ;
digitalWrite ( SPISD_CS , HIGH ) ;
@ -3389,6 +3427,20 @@ if (i2cBus.endTransmission() == 0) {
a2dp_sink . start ( " Tonuino " ) ;
a2dp_sink . start ( " Tonuino " ) ;
# endif
# endif
# ifdef DISPLAY_I2C
// OLED Display - https://github.com/olikraus/u8g2/wiki/u8g2setupcpp#sh1106-128x64_noname-1
U8G2_SH1106_128X64_NONAME_1_2ND_HW_I2C u8g2 ( U8G2_R0 , U8X8_PIN_NONE ) ;
u8g2 . begin ( ) ;
u8g2 . firstPage ( ) ;
do {
u8g2 . setFont ( u8g2_font_ncenB08_tr ) ;
u8g2 . drawStr ( 0 , 8 , " Tonuino gestartet " ) ;
u8g2 . drawStr ( 0 , 16 , " Papas Projekt " ) ;
u8g2 . drawStr ( 0 , 24 , " Dritte Statuszeile passt " ) ;
u8g2 . drawStr ( 0 , 16 , " und noch eine vierte Zeile " ) ;
} while ( u8g2 . nextPage ( ) ) ;
# endif
// Create queues
// Create queues
volumeQueue = xQueueCreate ( 1 , sizeof ( int ) ) ;
volumeQueue = xQueueCreate ( 1 , sizeof ( int ) ) ;
if ( volumeQueue = = NULL ) {
if ( volumeQueue = = NULL ) {
@ -3594,10 +3646,8 @@ if (i2cBus.endTransmission() == 0) {
// Activate internal pullups for all buttons
// Activate internal pullups for all buttons
pinMode ( DREHENCODER_BUTTON , INPUT_PULLUP ) ;
pinMode ( DREHENCODER_BUTTON , INPUT_PULLUP ) ;
pinMode ( PAUSEPLAY_BUTTON , INPUT_PULLUP ) ;
pinMode ( PAUSEPLAY_BUTTON , INPUT_PULLUP ) ;
# if (HAL == 1)
pinMode ( NEXT_BUTTON , INPUT_PULLUP ) ;
pinMode ( NEXT_BUTTON , INPUT_PULLUP ) ;
pinMode ( PREVIOUS_BUTTON , INPUT_PULLUP ) ;
pinMode ( PREVIOUS_BUTTON , INPUT_PULLUP ) ;
# endif
// Init rotary encoder
// Init rotary encoder
encoder . attachHalfQuad ( DREHENCODER_CLK , DREHENCODER_DT ) ;
encoder . attachHalfQuad ( DREHENCODER_CLK , DREHENCODER_DT ) ;
@ -3612,11 +3662,12 @@ if (i2cBus.endTransmission() == 0) {
}
}
# endif
# endif
wifiEnabled = getWifiEnableStatusFromNVS ( ) ;
wifiManager ( ) ;
wifiManager ( ) ;
lastTimeActiveTimestamp = millis ( ) ; // initial set after boot
lastTimeActiveTimestamp = millis ( ) ; // initial set after boot
if ( wifiManager ( ) = = WL_CONNECTED ) {
/*if (wifiManager() == WL_CONNECTED) {
// attach AsyncWebSocket for Mgmt-Interface
// attach AsyncWebSocket for Mgmt-Interface
ws . onEvent ( onWebsocketEvent ) ;
ws . onEvent ( onWebsocketEvent ) ;
wServer . addHandler ( & ws ) ;
wServer . addHandler ( & ws ) ;
@ -3640,35 +3691,17 @@ if (i2cBus.endTransmission() == 0) {
wServer . onNotFound ( notFound ) ;
wServer . onNotFound ( notFound ) ;
wServer . begin ( ) ;
wServer . begin ( ) ;
}
# ifdef DISPLAY_I2C
u8g2 . begin ( ) ;
u8g2 . firstPage ( ) ;
do {
u8g2 . setFont ( u8g2_font_ncenB08_tr ) ;
u8g2 . drawStr ( 0 , 15 , " Tonuino gestartet " ) ;
u8g2 . drawStr ( 15 , 30 , " Papas Projekt " ) ;
} while ( u8g2 . nextPage ( ) ) ;
# endif
} */
bootComplete = true ;
bootComplete = true ;
/*char *sdC = (char *) calloc(16384, sizeof(char));
printSdContent ( SD . open ( " / " , FILE_READ ) , 16384 , 1 , sdC , 2 ) ;
printSdContent ( SD . open ( " / " , FILE_READ ) , 16384 , 1 , sdC , 2 ) ;
Serial . println ( sdC ) ;
Serial . println ( strlen ( sdC ) ) ;
Serial . println ( ESP . getFreeHeap ( ) ) ;
free ( sdC ) ;
Serial . print ( F ( " Free heap: " ) ) ;
Serial . print ( F ( " Free heap: " ) ) ;
Serial . println ( ESP . getFreeHeap ( ) ) ; */
Serial . println ( ESP . getFreeHeap ( ) ) ;
}
}
void loop ( ) {
void loop ( ) {
webserverStart ( ) ;
# ifdef HEADPHONE_ADJUST_ENABLE
# ifdef HEADPHONE_ADJUST_ENABLE
headphoneVolumeManager ( ) ;
headphoneVolumeManager ( ) ;
# endif
# endif
@ -3698,7 +3731,6 @@ void loop() {
lastTimeActiveTimestamp = millis ( ) ; // Re-adjust timer while client is connected to avoid ESP falling asleep
lastTimeActiveTimestamp = millis ( ) ; // Re-adjust timer while client is connected to avoid ESP falling asleep
}
}
# endif
# endif
}
}