Browse Source

Introducing Wifi-enable/disable

master
Torsten Stauder 5 years ago
parent
commit
4fb74d51c0
  1. 23
      README.md
  2. 1
      html/website.html
  3. 1
      html/website_EN.html
  4. BIN
      pictures/Mgmt-GUI1.jpg
  5. BIN
      pictures/Mgmt-GUI2.jpg
  6. BIN
      pictures/Mgmt-GUI3.jpg
  7. BIN
      pictures/Mgmt-GUI4.jpg
  8. BIN
      pictures/Mgmt-GUI5.jpg
  9. 2
      src/logmessages.h
  10. 2
      src/logmessages_EN.h
  11. 187
      src/main.cpp
  12. 1
      src/websiteMgmt.h
  13. 1
      src/websiteMgmt_EN.h

23
README.md

@ -1,7 +1,7 @@
# Tonuino based on ESP32 with I2S-DAC-support # Tonuino based on ESP32 with I2S-DAC-support
## NEWS ## NEWS
Currently I'm working on a new Tonuino that is completely based on 3.3V and makes use of an (optional) headphone-pcb. As uC-develboard a Lolin32 is used and it's (optionally) battery-powered. So stay tuned...
Currently I'm working on a new Tonuino that is completely based on 3.3V and makes use of an (optional) [headphone-pcb](https://github.com/biologist79/Tonuino-ESP32-I2S/tree/master/PCBs/Headphone%20with%20PCM5102a%20and%20TMD1308). As uC-develboard a Lolin32 is used and it's (optionally) battery-powered. So stay tuned...
## Disclaimer ## Disclaimer
This is a **fork** of the popular [Tonuino-project](https://github.com/xfjx/TonUINO) which means, that it only shares the basic concept of controlling a music-player by RFID-tags and buttons. **Said this I want to rule out, that the code-basis is completely different and developed by myself**. So there might be features, that are supported by my fork whereas others are missing or implemented differently. For sure both share that it's non-profit, DIY and developed on [Arduino](https://www.arduino.cc/). This is a **fork** of the popular [Tonuino-project](https://github.com/xfjx/TonUINO) which means, that it only shares the basic concept of controlling a music-player by RFID-tags and buttons. **Said this I want to rule out, that the code-basis is completely different and developed by myself**. So there might be features, that are supported by my fork whereas others are missing or implemented differently. For sure both share that it's non-profit, DIY and developed on [Arduino](https://www.arduino.cc/).
@ -19,7 +19,7 @@ The basic idea of Tonuino (and my fork, respectively) is to provide a way, to us
The heart of my project is an ESP32 on a [Wemos Lolin32 development-board](https://www.ebay.de/itm/4MB-Flash-WEMOS-Lolin32-V1-0-0-WIFI-Bluetooth-Card-Based-ESP-32-ESP-WROOM-32/162716855489). If ordered in China (Aliexpress, eBay e.g.) it's pretty cheap (around 4€) but even in Europe it's only around 8€. Make sure to install the drivers for the USB/Serial-chip (CP2102 e.g.). If unsure have a look at eBay or Aliexpress for "Lolin 32". The heart of my project is an ESP32 on a [Wemos Lolin32 development-board](https://www.ebay.de/itm/4MB-Flash-WEMOS-Lolin32-V1-0-0-WIFI-Bluetooth-Card-Based-ESP-32-ESP-WROOM-32/162716855489). If ordered in China (Aliexpress, eBay e.g.) it's pretty cheap (around 4€) but even in Europe it's only around 8€. Make sure to install the drivers for the USB/Serial-chip (CP2102 e.g.). If unsure have a look at eBay or Aliexpress for "Lolin 32".
* [MAX98357A (like Adafruit's)](https://www.ebay.de/itm/MAX98357-Amplifier-Breakout-Interface-I2S-Class-D-Module-For-ESP32-Raspberry-Pi/174319322988) * [MAX98357A (like Adafruit's)](https://www.ebay.de/itm/MAX98357-Amplifier-Breakout-Interface-I2S-Class-D-Module-For-ESP32-Raspberry-Pi/174319322988)
* [uSD-card-reader 3.3V + 5V](https://www.amazon.de/AZDelivery-Reader-Speicher-Memory-Arduino/dp/B077MB17JB) * [uSD-card-reader 3.3V + 5V](https://www.amazon.de/AZDelivery-Reader-Speicher-Memory-Arduino/dp/B077MB17JB)
* [uSD-card-reader 3.3V only](https://www.ebay.de/itm/Micro-SD-Karten-SD-Card-Modul-SPI-fur-Breadboard-Arduino-Raspberry-Pi/183106778276)
* [uSD-card-reader 3.3V only](https://www.ebay.de/itm/Micro-SPI-Kartenleser-Card-Reader-2GB-SD-8GB-SDHC-Card-3-3V-ESP8266-Arduino-NEU/333796577968)
* [RFID-reader](https://www.amazon.de/AZDelivery-Reader-Arduino-Raspberry-gratis/dp/B074S8MRQ7) * [RFID-reader](https://www.amazon.de/AZDelivery-Reader-Arduino-Raspberry-gratis/dp/B074S8MRQ7)
* [RFID-tags](https://www.amazon.de/AZDelivery-Keycard-56MHz-Schlüsselkarte-Karte/dp/B07TVJPTM7) * [RFID-tags](https://www.amazon.de/AZDelivery-Keycard-56MHz-Schlüsselkarte-Karte/dp/B07TVJPTM7)
* [Neopixel-ring](https://www.ebay.de/itm/LED-Ring-24-x-5050-RGB-LEDs-WS2812-integrierter-Treiber-NeoPixel-kompatibel/282280571841) * [Neopixel-ring](https://www.ebay.de/itm/LED-Ring-24-x-5050-RGB-LEDs-WS2812-integrierter-Treiber-NeoPixel-kompatibel/282280571841)
@ -36,7 +36,7 @@ In the upper section of main.cpp you can specify the modules that should be comp
Please note: if MQTT is enabled it's still possible to deactivate it via webgui. Please note: if MQTT is enabled it's still possible to deactivate it via webgui.
## Wiring (2 SPI-instances) ## Wiring (2 SPI-instances)
A lot of wiring is necessary to get ESP32-Tonuino working. After my first experiments I soldered the stuff on a board in order to avoid wild-west-cabling. Especially for the interconnect between uC and uSD-card-reader make sure to use short wires (like 10cm or so)! Important: you can easily connect another I2S-DACs but just connecting them in parallel to the I2S-pins (DIN, BCLK, LRC). This is true for example if you plan to integrate a [line/headphone-pcb](https://www.adafruit.com/product/3678). In general, this runs fine. But unfortunately this board lacks of a headphone jack, that takes note if a plug is inserted or not. Best way is to use a [headphone jack](https://www.conrad.de/de/p/cliff-fcr1295-klinken-steckverbinder-3-5-mm-buchse-einbau-horizontal-polzahl-3-stereo-schwarz-1-st-705830.html) that has a pin that is set to GND, if there's no plug and vice versa. Using for example a MOSFET-circuit, this signal can be inverted in a way, that MAX98357.SD is pulled down to GND if there's a plug. Doing that will turn off the speaker immediately if there's a plug and vice versa. Have a look at the PCB-folder in order to view the detailed solution. Here's an example for such a [headphone-pcb)(https://github.com/biologist79/Tonuino-ESP32-I2S/tree/master/PCBs/Headphone%20with%20PCM5102a%20and%20TMD1308) that makes use of GND.
A lot of wiring is necessary to get ESP32-Tonuino working. After my first experiments I soldered the stuff on a board in order to avoid wild-west-cabling. Especially for the interconnect between uC and uSD-card-reader make sure to use short wires (like 10cm or so)! Important: you can easily connect another I2S-DACs but just connecting them in parallel to the I2S-pins (DIN, BCLK, LRC). This is true for example if you plan to integrate a [line/headphone-pcb](https://www.adafruit.com/product/3678). In general, this runs fine. But unfortunately this board lacks of a headphone jack, that takes note if a plug is inserted or not. Best way is to use a [headphone jack](https://www.conrad.de/de/p/cliff-fcr1295-klinken-steckverbinder-3-5-mm-buchse-einbau-horizontal-polzahl-3-stereo-schwarz-1-st-705830.html) that has a pin that is set to GND, if there's no plug and vice versa. Using for example a MOSFET-circuit, this signal can be inverted in a way, that MAX98357.SD is pulled down to GND if there's a plug. Doing that will turn off the speaker immediately if there's a plug and vice versa. Have a look at the PCB-folder in order to view the detailed solution. Here's an example for such a [headphone-pcb](https://github.com/biologist79/Tonuino-ESP32-I2S/tree/master/PCBs/Headphone%20with%20PCM5102a%20and%20TMD1308) that makes use of GND.
| ESP32 (GPIO) | Hardware | Pin | Comment | | ESP32 (GPIO) | Hardware | Pin | Comment |
| ------------- | --------------------- | ------ | ------------------------------------------------------------ | | ------------- | --------------------- | ------ | ------------------------------------------------------------ |
@ -136,11 +136,16 @@ Keep in mind the RFID-lib I used is intended for default-SPI-pins only (SCK, MIS
* compile and upload the sketch * compile and upload the sketch
## Starting Tonuino-ESP32 first time ## Starting Tonuino-ESP32 first time
After plugging in it takes a few seconds until neopixel indicates that Tonuino is ready (by four (slow) rotating white LEDs). If uC was not able to connect to WiFi, an access-point (named Tonuino) is opened and after connecting this WiFi, a [configuration-Interface](http://192.168.4.1) is available via webbrowser. Enter WiFI-credentials + the hostname (Tonuio's name), save them and restart the uC. Then reconnect to your "regular" WiFi. Now you're ready to go: start learning RFID-tags via GUI. To reach the GUI enter the IP stated in the serial console or use the hostname. For example if you're using a Fritzbox as router and entered tonuino as hostname in the previous configuration-step, in your webbrowser tonuino.fritz.box should work. After doing the rfid-learning, place your RFID-tag next to the RFID-reader and the music (or whatever else you choosed) should start to play. While the playlist is generated, fast-rotating LEDs are shown to indicate that Tonuino is busy. The more tracks a playlist/directory contains the longer this step takes. <br >
After plugging in it takes a few seconds until neopixel indicates that Tonuino is ready (by four (slow) rotating LEDs; white if Wifi enabled and blue if disabled). If uC was not able to connect to WiFi, an access-point (named Tonuino) is opened and after connecting this WiFi, a [configuration-Interface](http://192.168.4.1) is available via webbrowser. Enter WiFI-credentials + the hostname (Tonuio's name), save them and restart the uC. Then reconnect to your "regular" WiFi. Now you're ready to go: start learning RFID-tags via GUI. To reach the GUI enter the IP stated in the serial console or use the hostname. For example if you're using a Fritzbox as router and entered tonuino as hostname in the previous configuration-step, in your webbrowser tonuino.fritz.box should work. After doing the rfid-learning, place your RFID-tag next to the RFID-reader and the music (or whatever else you choosed) should start to play. While the playlist is generated, fast-rotating LEDs are shown to indicate that Tonuino is busy. The more tracks a playlist/directory contains the longer this step takes. <br >
Please note: hostname can be used to call webgui or FTP-server. I tested it with a Fritzbox 7490 and worked fine. Make sure you don't use a name that already exists in you local network (LAN). Please note: hostname can be used to call webgui or FTP-server. I tested it with a Fritzbox 7490 and worked fine. Make sure you don't use a name that already exists in you local network (LAN).
## WiFi
WiFi is mandatory for webgui, FTP and MQTT. However, WiFi can be temporarily or permanently disabled. There are two ways to do that:
* Use a special modification-card that can be configured via webgui
* Press previous + next-button in parallel shortly
This toggles the current WiFi-status which means: if it's currently enabled, it will be disabled and vice versa. Please note: change is *not effective until the next reboot* but will remain until you change it again. Having Wifi enabled is indicated in idle-mode (no playlist active) with four white slow rotating LEDs whereas disabled WiFi is represented by those ones colored blue.
## After Tonuino-ESP32 is connected to your WiFi ## After Tonuino-ESP32 is connected to your WiFi
After connecting the Tonuino to your WiFi, the 'regular' Webgui is available at the IP assigned by the router. Using this GUI, you can configure:
After getting Tonuino part of your LAN/WiFi, the 'regular' webgui is available at the IP assigned by your router. Using this GUI, you can configure:
* WiFi * WiFi
* Binding between RFID-tag, file/directory/URL and playMode * Binding between RFID-tag, file/directory/URL and playMode
* Binding between RFID-tag and a modification-type * Binding between RFID-tag and a modification-type
@ -157,6 +162,12 @@ Webgui #2:
Webgui #3: Webgui #3:
<img src="https://raw.githubusercontent.com/biologist79/Tonuino-ESP32-I2S/master/pictures/Mgmt-GUI3.jpg" width="300"> <img src="https://raw.githubusercontent.com/biologist79/Tonuino-ESP32-I2S/master/pictures/Mgmt-GUI3.jpg" width="300">
Webgui #4:
<img src="https://raw.githubusercontent.com/biologist79/Tonuino-ESP32-I2S/master/pictures/Mgmt-GUI4.jpg" width="300">
Webgui #5:
<img src="https://raw.githubusercontent.com/biologist79/Tonuino-ESP32-I2S/master/pictures/Mgmt-GUI5.jpg" width="300">
Webgui: websocket broken: Webgui: websocket broken:
<img src="https://raw.githubusercontent.com/biologist79/Tonuino-ESP32-I2S/master/pictures/Mgmt-GUI_connection_broken.jpg" width="300"> <img src="https://raw.githubusercontent.com/biologist79/Tonuino-ESP32-I2S/master/pictures/Mgmt-GUI_connection_broken.jpg" width="300">
@ -189,6 +200,7 @@ There are special RFID-tags, that don't start music by themself but can modify t
* current track in loop-mode (is "stronger" than playlist-loop but doesn't overwrite it!) * current track in loop-mode (is "stronger" than playlist-loop but doesn't overwrite it!)
* playlist in loop-mode * playlist in loop-mode
* track und playlist loop-mode can both be activated at the same time, but unless track-loop isn't deactivated, playlist-loop won't be effective * track und playlist loop-mode can both be activated at the same time, but unless track-loop isn't deactivated, playlist-loop won't be effective
* Toggle WiFi (enable/disable; effektive after reboot)
### Neopixel-ring (optional) ### Neopixel-ring (optional)
Indicates different things. Don't forget configuration of number of LEDs via #define NUM_LEDS Indicates different things. Don't forget configuration of number of LEDs via #define NUM_LEDS
@ -292,3 +304,4 @@ Feel free to use your own smarthome-environments (instead of openHAB). The MQTT-
| topicRepeatModeState | 0 - 3 | Sends repeat-mode | | topicRepeatModeState | 0 - 3 | Sends repeat-mode |
| topicLedBrightnessCmnd | 0 - 255 | Set brightness of Neopixel | | topicLedBrightnessCmnd | 0 - 255 | Set brightness of Neopixel |
| topicLedBrightnessState | 0 - 255 | Sends brightness of Neopixel | | topicLedBrightnessState | 0 - 255 | Sends brightness of Neopixel |
| topicBatteryVoltage | float | Voltage (e.g. 3.81) |

1
html/website.html

@ -115,6 +115,7 @@
<option value="110">Wiederhole Playlist (endlos)</option> <option value="110">Wiederhole Playlist (endlos)</option>
<option value="111">Wiederhole Titel (endlos)</option> <option value="111">Wiederhole Titel (endlos)</option>
<option value="112">Dimme LEDs (Nachtmodus)</option> <option value="112">Dimme LEDs (Nachtmodus)</option>
<option value="130">Aktiviere/deaktive WLAN</option>
</select> </select>
</div> </div>
<button type="reset" class="btn btn-secondary">Reset</button> <button type="reset" class="btn btn-secondary">Reset</button>

1
html/website_EN.html

@ -115,6 +115,7 @@
<option value="110">Repeat playlist (inf. loop)</option> <option value="110">Repeat playlist (inf. loop)</option>
<option value="111">Repeat track (inf. loop)</option> <option value="111">Repeat track (inf. loop)</option>
<option value="112">Dimm LEDs (nightmode)</option> <option value="112">Dimm LEDs (nightmode)</option>
<option value="130">Toggle WiFi-status</option>
</select> </select>
</div> </div>
<button type="reset" class="btn btn-secondary">Reset</button> <button type="reset" class="btn btn-secondary">Reset</button>

BIN
pictures/Mgmt-GUI1.jpg

Before

Width: 1080  |  Height: 1847  |  Size: 297 KiB

After

Width: 1080  |  Height: 1856  |  Size: 336 KiB

BIN
pictures/Mgmt-GUI2.jpg

Before

Width: 1080  |  Height: 1848  |  Size: 270 KiB

After

Width: 1080  |  Height: 1223  |  Size: 188 KiB

BIN
pictures/Mgmt-GUI3.jpg

Before

Width: 1080  |  Height: 1846  |  Size: 275 KiB

After

Width: 1080  |  Height: 1644  |  Size: 240 KiB

BIN
pictures/Mgmt-GUI4.jpg

After

Width: 1080  |  Height: 1471  |  Size: 245 KiB

BIN
pictures/Mgmt-GUI5.jpg

After

Width: 1080  |  Height: 602  |  Size: 81 KiB

2
src/logmessages.h

@ -143,3 +143,5 @@ static const char restoredHostnameFromNvs[] PROGMEM = "Hostname aus NVS geladen"
static const char currentVoltageMsg[] PROGMEM = "Aktuelle Batteriespannung"; static const char currentVoltageMsg[] PROGMEM = "Aktuelle Batteriespannung";
static const char voltageTooLow[] PROGMEM = "Batteriespannung niedrig"; static const char voltageTooLow[] PROGMEM = "Batteriespannung niedrig";
static const char sdBootFailedDeepsleep[] PROGMEM = "Bootgang wegen SD fehlgeschlagen. Gehe in Deepsleep..."; static const char sdBootFailedDeepsleep[] PROGMEM = "Bootgang wegen SD fehlgeschlagen. Gehe in Deepsleep...";
static const char wifiEnabledAfterRestart[] PROGMEM = "WLAN wird ab dem nächsten Neustart aktiviert.";
static const char wifiDisabledAfterRestart[] PROGMEM = "WLAN wird ab dem nächsten Neustart deaktiviert.";

2
src/logmessages_EN.h

@ -143,3 +143,5 @@ static const char restoredHostnameFromNvs[] PROGMEM = "Restored hostname from NV
static const char currentVoltageMsg[] PROGMEM = "Current battery-voltage"; static const char currentVoltageMsg[] PROGMEM = "Current battery-voltage";
static const char voltageTooLow[] PROGMEM = "Low battery-voltage"; static const char voltageTooLow[] PROGMEM = "Low battery-voltage";
static const char sdBootFailedDeepsleep[] PROGMEM = "Failed to boot due to SD. Will go to deepsleep..."; static const char sdBootFailedDeepsleep[] PROGMEM = "Failed to boot due to SD. Will go to deepsleep...";
static const char wifiEnabledAfterRestart[] PROGMEM = "WiFi will be enabled (effective after next boot).";
static const char wifiDisabledAfterRestart[] PROGMEM = "WiFi will be disabled (effective after next boot).";

187
src/main.cpp

@ -178,6 +178,7 @@ char *logBuf = (char*) calloc(serialLoglength, sizeof(char)); // Buffer for all
#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
@ -203,7 +204,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 {
@ -259,6 +259,8 @@ 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;
// Neopixel // Neopixel
#ifdef NEOPIXEL_ENABLE #ifdef NEOPIXEL_ENABLE
bool showLedError = false; bool showLedError = false;
@ -409,6 +411,7 @@ 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 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);
@ -441,6 +444,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) */
@ -472,39 +476,6 @@ int countChars(const char* string, char ch) {
} }
// 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);
} }
@ -532,7 +503,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();
} }
} }
@ -574,6 +544,26 @@ 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;
Serial.println(wifiManager());
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) {
@ -1629,7 +1619,6 @@ void rfidScanner(void *parameter) {
} }
} }
xQueueSend(rfidCardQueue, &cardIdString, 0); xQueueSend(rfidCardQueue, &cardIdString, 0);
free(cardIdString);
} }
} }
vTaskDelete(NULL); vTaskDelete(NULL);
@ -1855,16 +1844,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::Blue;
leds[NUM_LEDS/4] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[NUM_LEDS/2] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[NUM_LEDS/4*3] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
} 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::Blue;
leds[(ledAddress(i)+NUM_LEDS/4) % NUM_LEDS] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[(ledAddress(i)+NUM_LEDS/2) % NUM_LEDS] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[(ledAddress(i)+NUM_LEDS/4*3) % NUM_LEDS] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
} }
FastLED.show(); FastLED.show();
for (uint8_t i=0; i<=50; i++) { for (uint8_t i=0; i<=50; i++) {
@ -1935,14 +1924,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) {
@ -2583,6 +2573,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);
@ -2607,6 +2610,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);
@ -2693,8 +2697,44 @@ void accessPointStart(const char *SSID, IPAddress ip, IPAddress netmask) {
} }
// 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);
return true;
}
} else {
if (prefsSettings.putUInt("enableWifi", 1)) { // enable
loggerNl((char *) FPSTR(wifiEnabledAfterRestart), LOGLEVEL_NOTICE);
return true;
}
}
}
// Provides management for WiFi // Provides management for WiFi
wl_status_t wifiManager(void) { wl_status_t wifiManager(void) {
// If wifi whould not be activated, return instantly
if (!wifiEnabled) {
return WiFi.status();
}
if (wifiCheckLastTimestamp == 0) { if (wifiCheckLastTimestamp == 0) {
// Get credentials from NVS // Get credentials from NVS
String strSSID = prefsSettings.getString("SSID", "-1"); String strSSID = prefsSettings.getString("SSID", "-1");
@ -2708,28 +2748,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")) {
@ -2816,12 +2834,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");
} }
@ -2900,15 +2912,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"];
@ -3508,6 +3511,7 @@ void setup() {
} }
#endif #endif
wifiEnabled = getWifiEnableStatusFromNVS();
wifiManager(); wifiManager();
lastTimeActiveTimestamp = millis(); // initial set after boot lastTimeActiveTimestamp = millis(); // initial set after boot
@ -3539,13 +3543,6 @@ void setup() {
} }
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());
} }

1
src/websiteMgmt.h

@ -115,6 +115,7 @@ static const char mgtWebsite[] PROGMEM = "<!DOCTYPE html>\
<option value=\"110\">Wiederhole Playlist (endlos)</option>\ <option value=\"110\">Wiederhole Playlist (endlos)</option>\
<option value=\"111\">Wiederhole Titel (endlos)</option>\ <option value=\"111\">Wiederhole Titel (endlos)</option>\
<option value=\"112\">Dimme LEDs (Nachtmodus)</option>\ <option value=\"112\">Dimme LEDs (Nachtmodus)</option>\
<option value=\"130\">Aktiviere/deaktive WLAN</option>\
</select>\ </select>\
</div>\ </div>\
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ <button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\

1
src/websiteMgmt_EN.h

@ -115,6 +115,7 @@ static const char mgtWebsite[] PROGMEM = "<!DOCTYPE html>\
<option value=\"110\">Repeat playlist (inf. loop)</option>\ <option value=\"110\">Repeat playlist (inf. loop)</option>\
<option value=\"111\">Repeat track (inf. loop)</option>\ <option value=\"111\">Repeat track (inf. loop)</option>\
<option value=\"112\">Dimm LEDs (nightmode)</option>\ <option value=\"112\">Dimm LEDs (nightmode)</option>\
<option value=\"130\">Toggle WiFi-status</option>\
</select>\ </select>\
</div>\ </div>\
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ <button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\

Loading…
Cancel
Save