diff --git a/lib/DFMiniMp3-1.0.7-noChecksums/.github/FUNDING.yml b/lib/DFMiniMp3-1.0.7-noChecksums/.github/FUNDING.yml deleted file mode 100644 index 9bcf96a..0000000 --- a/lib/DFMiniMp3-1.0.7-noChecksums/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: [makuna] -custom: ["https://paypal.me/MakunaGithub"] diff --git a/lib/DFMiniMp3-1.0.7-noChecksums/examples/PlayAdvertisements/PlayAdvertisements.ino b/lib/DFMiniMp3-1.0.7-noChecksums/examples/PlayAdvertisements/PlayAdvertisements.ino deleted file mode 100644 index fa34f12..0000000 --- a/lib/DFMiniMp3-1.0.7-noChecksums/examples/PlayAdvertisements/PlayAdvertisements.ino +++ /dev/null @@ -1,105 +0,0 @@ -// this example will play a track and then every 60 seconds -// it will play an advertisement -// -// it expects the sd card to contain the following mp3 files -// but doesn't care whats in them -// -// sd:/01/001.mp3 - the song to play, the longer the better -// sd:/advert/0001.mp3 - the advertisement to interrupt the song, keep it short - -#include -#include - -// implement a notification class, -// its member methods will get called -// -class Mp3Notify -{ -public: - static void PrintlnSourceAction(DfMp3_PlaySources source, const char* action) - { - if (source & DfMp3_PlaySources_Sd) - { - Serial.print("SD Card, "); - } - if (source & DfMp3_PlaySources_Usb) - { - Serial.print("USB Disk, "); - } - if (source & DfMp3_PlaySources_Flash) - { - Serial.print("Flash, "); - } - Serial.println(action); - } - static void OnError(uint16_t errorCode) - { - // see DfMp3_Error for code meaning - Serial.println(); - Serial.print("Com Error "); - Serial.println(errorCode); - } - static void OnPlayFinished(DfMp3_PlaySources source, uint16_t track) - { - Serial.print("Play finished for #"); - Serial.println(track); - } - static void OnPlaySourceOnline(DfMp3_PlaySources source) - { - PrintlnSourceAction(source, "online"); - } - static void OnPlaySourceInserted(DfMp3_PlaySources source) - { - PrintlnSourceAction(source, "inserted"); - } - static void OnPlaySourceRemoved(DfMp3_PlaySources source) - { - PrintlnSourceAction(source, "removed"); - } -}; - -// instance a DFMiniMp3 object, -// defined with the above notification class and the hardware serial class -// -DFMiniMp3 mp3(Serial1); - -// Some arduino boards only have one hardware serial port, so a software serial port is needed instead. -// comment out the above definition and uncomment these lines -//SoftwareSerial secondarySerial(10, 11); // RX, TX -//DFMiniMp3 mp3(secondarySerial); - -uint32_t lastAdvert; // track time for last advertisement - -void setup() -{ - Serial.begin(115200); - - Serial.println("initializing..."); - - mp3.begin(); - uint16_t volume = mp3.getVolume(); - Serial.print("volume was "); - Serial.println(volume); - mp3.setVolume(24); - volume = mp3.getVolume(); - Serial.print(" and changed to "); - Serial.println(volume); - - Serial.println("track 1 from folder 1"); - mp3.playFolderTrack(1, 1); // sd:/01/001.mp3 - - lastAdvert = millis(); -} - -void loop() -{ - uint32_t now = millis(); - if ((now - lastAdvert) > 60000) - { - // interrupt the song and play the advertisement, it will - // return to the song when its done playing automatically - mp3.playAdvertisement(1); // sd:/advert/0001.mp3 - lastAdvert = now; - } - mp3.loop(); -} diff --git a/lib/DFMiniMp3-1.0.7-noChecksums/examples/PlayMp3/PlayMp3.ino b/lib/DFMiniMp3-1.0.7-noChecksums/examples/PlayMp3/PlayMp3.ino deleted file mode 100644 index c5e9b0a..0000000 --- a/lib/DFMiniMp3-1.0.7-noChecksums/examples/PlayMp3/PlayMp3.ino +++ /dev/null @@ -1,121 +0,0 @@ -// this example will play a track and then -// every five seconds play another track -// -// it expects the sd card to contain these three mp3 files -// but doesn't care whats in them -// -// sd:/mp3/0001.mp3 -// sd:/mp3/0002.mp3 -// sd:/mp3/0003.mp3 - -#include -#include - -// implement a notification class, -// its member methods will get called -// -class Mp3Notify -{ -public: - static void PrintlnSourceAction(DfMp3_PlaySources source, const char* action) - { - if (source & DfMp3_PlaySources_Sd) - { - Serial.print("SD Card, "); - } - if (source & DfMp3_PlaySources_Usb) - { - Serial.print("USB Disk, "); - } - if (source & DfMp3_PlaySources_Flash) - { - Serial.print("Flash, "); - } - Serial.println(action); - } - static void OnError(uint16_t errorCode) - { - // see DfMp3_Error for code meaning - Serial.println(); - Serial.print("Com Error "); - Serial.println(errorCode); - } - static void OnPlayFinished(DfMp3_PlaySources source, uint16_t track) - { - Serial.print("Play finished for #"); - Serial.println(track); - } - static void OnPlaySourceOnline(DfMp3_PlaySources source) - { - PrintlnSourceAction(source, "online"); - } - static void OnPlaySourceInserted(DfMp3_PlaySources source) - { - PrintlnSourceAction(source, "inserted"); - } - static void OnPlaySourceRemoved(DfMp3_PlaySources source) - { - PrintlnSourceAction(source, "removed"); - } -}; - -// instance a DFMiniMp3 object, -// defined with the above notification class and the hardware serial class -// -DFMiniMp3 mp3(Serial1); - -// Some arduino boards only have one hardware serial port, so a software serial port is needed instead. -// comment out the above definition and uncomment these lines -//SoftwareSerial secondarySerial(10, 11); // RX, TX -//DFMiniMp3 mp3(secondarySerial); - -void setup() -{ - Serial.begin(115200); - - Serial.println("initializing..."); - - mp3.begin(); - - uint16_t volume = mp3.getVolume(); - Serial.print("volume "); - Serial.println(volume); - mp3.setVolume(24); - - uint16_t count = mp3.getTotalTrackCount(DfMp3_PlaySource_Sd); - Serial.print("files "); - Serial.println(count); - - Serial.println("starting..."); -} - -void waitMilliseconds(uint16_t msWait) -{ - uint32_t start = millis(); - - while ((millis() - start) < msWait) - { - // calling mp3.loop() periodically allows for notifications - // to be handled without interrupts - mp3.loop(); - delay(1); - } -} - -void loop() -{ - Serial.println("track 1"); - mp3.playMp3FolderTrack(1); // sd:/mp3/0001.mp3 - - waitMilliseconds(5000); - - Serial.println("track 2"); - mp3.playMp3FolderTrack(2); // sd:/mp3/0002.mp3 - - waitMilliseconds(5000); - - Serial.println("track 3"); - mp3.playMp3FolderTrack(3); // sd:/mp3/0002.mp3 - - waitMilliseconds(5000); -} diff --git a/lib/DFMiniMp3-1.0.7-noChecksums/examples/PlayRandom/PlayRandom.ino b/lib/DFMiniMp3-1.0.7-noChecksums/examples/PlayRandom/PlayRandom.ino deleted file mode 100644 index 9714099..0000000 --- a/lib/DFMiniMp3-1.0.7-noChecksums/examples/PlayRandom/PlayRandom.ino +++ /dev/null @@ -1,100 +0,0 @@ -// this example will play a random track from all on the sd -// -// it expects the sd card to contain some mp3 files - -#include -#include - -// implement a notification class, -// its member methods will get called -// -class Mp3Notify -{ -public: - static void PrintlnSourceAction(DfMp3_PlaySources source, const char* action) - { - if (source & DfMp3_PlaySources_Sd) - { - Serial.print("SD Card, "); - } - if (source & DfMp3_PlaySources_Usb) - { - Serial.print("USB Disk, "); - } - if (source & DfMp3_PlaySources_Flash) - { - Serial.print("Flash, "); - } - Serial.println(action); - } - static void OnError(uint16_t errorCode) - { - // see DfMp3_Error for code meaning - Serial.println(); - Serial.print("Com Error "); - Serial.println(errorCode); - } - static void OnPlayFinished(DfMp3_PlaySources source, uint16_t track) - { - Serial.print("Play finished for #"); - Serial.println(track); - } - static void OnPlaySourceOnline(DfMp3_PlaySources source) - { - PrintlnSourceAction(source, "online"); - } - static void OnPlaySourceInserted(DfMp3_PlaySources source) - { - PrintlnSourceAction(source, "inserted"); - } - static void OnPlaySourceRemoved(DfMp3_PlaySources source) - { - PrintlnSourceAction(source, "removed"); - } -}; - -// instance a DFMiniMp3 object, -// defined with the above notification class and the hardware serial class -// -DFMiniMp3 mp3(Serial1); - -// Some arduino boards only have one hardware serial port, so a software serial port is needed instead. -// comment out the above definition and uncomment these lines -//SoftwareSerial secondarySerial(10, 11); // RX, TX -//DFMiniMp3 mp3(secondarySerial); - -void setup() -{ - - Serial.begin(115200); - - Serial.println("initializing..."); - - mp3.begin(); - mp3.reset(); - - // show some properties and set the volume - uint16_t volume = mp3.getVolume(); - Serial.print("volume "); - Serial.println(volume); - mp3.setVolume(24); - - uint16_t count = mp3.getTotalTrackCount(DfMp3_PlaySource_Sd); - Serial.print("files "); - Serial.println(count); - - uint16_t mode = mp3.getPlaybackMode(); - Serial.print("playback mode "); - Serial.println(mode); - - Serial.println("starting..."); - - mp3.playRandomTrackFromAll(); // random of all folders on sd -} - -void loop() -{ - // calling mp3.loop() periodically allows for notifications - // to be handled without interrupts - mp3.loop(); -} diff --git a/lib/MatrixUI/MatrixDisplayUi.h b/lib/MatrixUI/MatrixDisplayUi.h index 485060f..4f817fc 100644 --- a/lib/MatrixUI/MatrixDisplayUi.h +++ b/lib/MatrixUI/MatrixDisplayUi.h @@ -102,7 +102,6 @@ private: uint8_t updateInterval = 33; uint8_t getnextAppNumber(); - void drawIndicator(); void drawApp(); void drawOverlays(); void tick(); @@ -110,7 +109,6 @@ private: public: MatrixDisplayUi(FastLED_NeoMatrix *matrix); - uint8_t AppCount = 0; /** * Initialise the display diff --git a/lib/webserver/src/esp-fs-webserver.cpp b/lib/webserver/src/esp-fs-webserver.cpp index 00cd534..79031a6 100644 --- a/lib/webserver/src/esp-fs-webserver.cpp +++ b/lib/webserver/src/esp-fs-webserver.cpp @@ -24,16 +24,17 @@ void FSWebServer::addHandler(const Uri &uri, HTTPMethod method, WebServerClass:: webserver->on(uri, method, fn); } + +void FSWebServer::onNotFound(WebServerClass::THandlerFunction fn) +{ + webserver->onNotFound(fn); +} + void FSWebServer::addHandler(const Uri &uri, WebServerClass::THandlerFunction handler) { webserver->on(uri, HTTP_ANY, handler); } -void FSWebServer::onNotFound(WebServerClass::THandlerFunction handler) -{ - webserver->onNotFound(handler); -} - // List all files saved in the selected filesystem bool FSWebServer::checkDir(char *dirname, uint8_t levels) { @@ -85,7 +86,7 @@ bool FSWebServer::begin(const char *path) webserver->on("/edit", HTTP_PUT, std::bind(&FSWebServer::handleFileCreate, this)); webserver->on("/edit", HTTP_DELETE, std::bind(&FSWebServer::handleFileDelete, this)); #endif - //webserver->onNotFound(std::bind(&FSWebServer::handleRequest, this)); + webserver->onNotFound(std::bind(&FSWebServer::handleRequest, this)); webserver->on("/favicon.ico", HTTP_GET, std::bind(&FSWebServer::replyOK, this)); webserver->on("/", HTTP_GET, std::bind(&FSWebServer::handleIndex, this)); #ifdef INCLUDE_SETUP_HTM @@ -158,6 +159,7 @@ IPAddress FSWebServer::startWiFi(uint32_t timeout, const char *apSSID, const cha #elif defined(ESP32) wifi_config_t conf; esp_wifi_get_config(WIFI_IF_STA, &conf); + _ssid = reinterpret_cast(conf.sta.ssid); _pass = reinterpret_cast(conf.sta.password); #endif @@ -167,6 +169,7 @@ IPAddress FSWebServer::startWiFi(uint32_t timeout, const char *apSSID, const cha WiFi.begin(_ssid, _pass); Serial.print(F("Connecting to ")); Serial.println(_ssid); + uint32_t startTime = millis(); while (WiFi.status() != WL_CONNECTED) { @@ -174,6 +177,8 @@ IPAddress FSWebServer::startWiFi(uint32_t timeout, const char *apSSID, const cha Serial.print("."); if (WiFi.status() == WL_CONNECTED) { + WiFi.setAutoReconnect(true); + WiFi.persistent(true); ip = WiFi.localIP(); return ip; } @@ -921,4 +926,4 @@ void FSWebServer::handleStatus() webserver->send(200, "application/json", json); } -#endif // INCLUDE_EDIT_HTM +#endif // INCLUDE_EDIT_HTM \ No newline at end of file diff --git a/lib/webserver/src/esp-fs-webserver.h b/lib/webserver/src/esp-fs-webserver.h index 88aab4f..9701dbe 100644 --- a/lib/webserver/src/esp-fs-webserver.h +++ b/lib/webserver/src/esp-fs-webserver.h @@ -5,7 +5,7 @@ #include #include #include -//#include +// #include #include #define INCLUDE_EDIT_HTM @@ -82,11 +82,11 @@ public: bool begin(const char *path = nullptr); void run(); - + void onNotFound(WebServerClass::THandlerFunction fn); + void addHandler(const Uri &uri, HTTPMethod method, WebServerClass::THandlerFunction fn); void addHandler(const Uri &uri, WebServerClass::THandlerFunction handler); - void onNotFound(WebServerClass::THandlerFunction handler); void setCaptiveWebage(const char *url); @@ -256,13 +256,12 @@ public: return true; } - template bool saveOptionValue(const char *label, T val) { // Öffne die Datei im Lesemodus, um den Inhalt des Dokuments beizubehalten File file = m_filesystem->open("/config.json", "r"); - DynamicJsonDocument doc(file.size()* 1.33); + DynamicJsonDocument doc(file.size() * 1.33); if (file) { diff --git a/platformio.ini b/platformio.ini index bd2766f..a73cba3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -22,6 +22,7 @@ lib_deps = fastled/FastLED@^3.5.0 marcmerlin/FastLED NeoMatrix@^1.2 knolleary/PubSubClient@^2.8 + plerup/EspSoftwareSerial@^8.0.1 [env:awtrix_upgrade] platform = https://github.com/platformio/platform-espressif32.git @@ -36,4 +37,5 @@ lib_deps = evert-arias/EasyButton@^2.0.1 fastled/FastLED@^3.5.0 marcmerlin/FastLED NeoMatrix@^1.2 - knolleary/PubSubClient@^2.8 \ No newline at end of file + knolleary/PubSubClient@^2.8 + plerup/EspSoftwareSerial@^8.0.1 diff --git a/src/Apps.h b/src/Apps.h index aef6c56..ca747eb 100644 --- a/src/Apps.h +++ b/src/Apps.h @@ -36,6 +36,7 @@ struct CustomApp bool isGif; bool rainbow; bool soundPlayed; + uint16_t duration = 0; String sound; int16_t repeat = 0; int16_t currentRepeat = 0; @@ -61,7 +62,7 @@ struct Notification bool isGif; bool flag = false; unsigned long startime = 0; - unsigned long duration = 0; + uint16_t duration = 0; int16_t repeat = -1; bool hold = false; byte pushIcon = 0; @@ -104,7 +105,7 @@ int findAppIndexByName(const String &name) return -1; } -void TimeApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void TimeApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { if (notify.flag) return; @@ -152,7 +153,7 @@ void TimeApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, } } -void DateApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void DateApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { if (notify.flag) return; @@ -180,7 +181,7 @@ void DateApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, } } -void TempApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void TempApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { if (notify.flag) return; @@ -201,7 +202,7 @@ void TempApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, } } -void HumApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void HumApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { if (notify.flag) return; @@ -215,7 +216,7 @@ void HumApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, i } #ifdef ULANZI -void BatApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void BatApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { if (notify.flag) return; @@ -275,7 +276,7 @@ void TimerApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state) } } -void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { // Abort if notify.flag is set if (notify.flag) @@ -292,8 +293,8 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState return; } - // reset custom App properties if last App - if (lastApp) + // reset custom App properties if last frame + if (lastFrame) { ca->iconWasPushed = false; ca->scrollposition = 9; @@ -301,6 +302,14 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState ca->scrollDelay = 0; } + if (!DisplayManager.appIsSwitching) + { + if (ca->duration > 0) + { + DisplayManager.setAppTime(ca->duration); + } + } + CURRENT_APP = ca->name; currentCustomApp = name; @@ -622,127 +631,126 @@ void NotifyApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state) DisplayManager.getInstance().resetTextColor(); } +// Unattractive to have a function for every customapp wich does the same, but currently still no other option found TODO -//Unattractive to have a function for every customapp wich does the same, but currently still no other option found TODO - -void CApp1(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp1(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp1); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp2(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp2(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp2); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp3(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp3(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp3); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp4(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp4(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp4); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp5(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp5(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp5); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp6(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp6(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp6); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp7(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp7(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp7); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp8(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp8(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp8); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp9(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp9(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp9); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp10(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp10(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp10); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp11(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp11(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp11); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp12(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp12(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp12); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp13(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp13(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp13); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp14(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp14(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp14); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp15(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp15(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp15); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp16(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp16(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp16); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp17(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp17(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp17); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp18(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp18(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp18); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp19(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp19(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp19); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } -void CApp20(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void CApp20(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { String name = getAppNameByFunction(CApp20); - ShowCustomApp(name, matrix, state, x, y, firstApp, lastApp); + ShowCustomApp(name, matrix, state, x, y, firstFrame, lastFrame); } const uint16_t *getWeatherIcon(int code) @@ -759,7 +767,7 @@ const uint16_t *getWeatherIcon(int code) } } -void WeatherApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstApp, bool lastApp) +void WeatherApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame) { if (notify.flag) return; diff --git a/src/DisplayManager.cpp b/src/DisplayManager.cpp index 7091d99..958d9a7 100644 --- a/src/DisplayManager.cpp +++ b/src/DisplayManager.cpp @@ -27,8 +27,6 @@ Ticker TimerTicker; #define MATRIX_WIDTH 32 #define MATRIX_HEIGHT 8 -bool appIsSwitching; - GifPlayer gif; CRGB leds[MATRIX_WIDTH * MATRIX_HEIGHT]; @@ -240,17 +238,15 @@ void removeCustomApp(const String &name) auto it = std::find_if(Apps.begin(), Apps.end(), [&name](const std::pair &appPair) { return appPair.first == name; }); - if (it != Apps.end()) - { - Apps.erase(it); - ui.setApps(Apps); - } + Apps.erase(it); + ui.setApps(Apps); } void DisplayManager_::generateCustomPage(String name, const char *json) { - if (json == "" && customApps.count(name)) + if (strcmp(json, "") == 0 && customApps.count(name)) { + Serial.println("delete"); customApps.erase(customApps.find(name)); removeCustomApp(name); return; @@ -297,6 +293,7 @@ void DisplayManager_::generateCustomPage(String name, const char *json) customApp.barSize = 0; } + customApp.duration = doc.containsKey("duration") ? doc["duration"].as() * 1000 : -1; int pos = doc.containsKey("pos") ? doc["pos"].as() : -1; customApp.rainbow = doc.containsKey("rainbow") ? doc["rainbow"] : false; customApp.pushIcon = doc.containsKey("pushIcon") ? doc["pushIcon"] : 0; @@ -534,17 +531,17 @@ void DisplayManager_::tick() } else { - ui.update(); if (ui.getUiState()->appState == IN_TRANSITION && !appIsSwitching) { appIsSwitching = true; - MQTTManager.setCurrentApp(CURRENT_APP); } else if (ui.getUiState()->appState == FIXED && appIsSwitching) { appIsSwitching = false; MQTTManager.setCurrentApp(CURRENT_APP); + setAppTime(TIME_PER_APP); } + ui.update(); } } @@ -910,3 +907,7 @@ String DisplayManager_::getStat() return jsonString; } +void DisplayManager_::setAppTime(uint16_t duration) +{ + ui.setTimePerApp(duration); +} \ No newline at end of file diff --git a/src/DisplayManager.h b/src/DisplayManager.h index b6b79a4..c81253f 100644 --- a/src/DisplayManager.h +++ b/src/DisplayManager.h @@ -26,6 +26,7 @@ private: public: static DisplayManager_ &getInstance(); + bool appIsSwitching; void setup(); void tick(); void clear(); @@ -48,7 +49,7 @@ public: void setFPS(uint8_t); void MatrixState(bool); void generateNotification(const char *json); - void generateCustomPage(String, const char *json); + void generateCustomPage(String name, const char *json); void printText(int16_t x, int16_t y, const char *text, bool centered, bool ignoreUppercase); bool setAutoTransition(bool active); void switchToApp(const char *json); @@ -60,6 +61,8 @@ public: void drawBMP(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h); void drawBarChart(int16_t x, int16_t y, const int data[], byte dataSize, bool withIcon, uint16_t color); void updateAppVector(const char *json); + void setMatrixLayout(int layout); + void setAppTime(uint16_t duration); String getStat(); }; diff --git a/src/Globals.cpp b/src/Globals.cpp index aa530d0..549de3d 100644 --- a/src/Globals.cpp +++ b/src/Globals.cpp @@ -73,6 +73,7 @@ void loadSettings() SHOW_DATE = Settings.getBool("DAT", true); SHOW_TEMP = Settings.getBool("TEMP", true); SHOW_HUM = Settings.getBool("HUM", true); + MATRIX_LAYOUT = Settings.getUInt("MAT", 0); #ifdef ULANZI SHOW_BAT = Settings.getBool("BAT", true); #endif @@ -101,6 +102,7 @@ void saveSettings() Settings.putBool("DAT", SHOW_DATE); Settings.putBool("TEMP", SHOW_TEMP); Settings.putBool("HUM", SHOW_HUM); + Settings.putUInt("MAT", MATRIX_LAYOUT); #ifdef ULANZI Settings.putBool("BAT", SHOW_BAT); #endif @@ -177,4 +179,7 @@ bool TIMER_ACTIVE; bool ALARM_ACTIVE; uint16_t TEXTCOLOR_565 = 0xFFFF; bool SOUND_ACTIVE; -String BOOT_SOUND = ""; \ No newline at end of file +String BOOT_SOUND = ""; +uint8_t VOLUME; +uint8_t VOLUME_PERCENT; +int MATRIX_LAYOUT; \ No newline at end of file diff --git a/src/Globals.h b/src/Globals.h index a5242e6..6cb3e06 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -68,6 +68,9 @@ extern bool START_ON_MONDAY; extern bool IS_CELSIUS; extern bool SOUND_ACTIVE; extern String BOOT_SOUND; +extern uint8_t VOLUME; +extern uint8_t VOLUME_PERCENT; +extern int MATRIX_LAYOUT; void loadSettings(); void saveSettings(); #endif // Globals_H \ No newline at end of file diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index f4f0127..55f8b4e 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,8 @@ enum MenuState WeekdayMenu, TempMenu, Appmenu, - SoundMenu + SoundMenu, + VolumeMenu }; const char *menuItems[] PROGMEM = { @@ -42,10 +44,11 @@ const char *menuItems[] PROGMEM = { "TEMP", "APPS", "SOUND", + "VOLUME", "UPDATE"}; int8_t menuIndex = 0; -uint8_t menuItemCount = 13; +uint8_t menuItemCount = 14; const char *timeFormat[] PROGMEM = { "%H:%M:%S", @@ -77,10 +80,10 @@ const char *appsItems[][2] PROGMEM = { {"13", "time"}, {"1158", "date"}, {"234", "temp"}, -#ifdef ULANZI +#ifdef ULANZI {"2075", "hum"}, {"1486", "bat"}}; -#else +#else {"2075", "hum"}}; #endif @@ -247,6 +250,10 @@ void MenuManager_::rightButton() case TempMenu: IS_CELSIUS = !IS_CELSIUS; break; + case VolumeMenu: + VOLUME_PERCENT = (VOLUME_PERCENT % 100) + 1; + VOLUME = map(VOLUME_PERCENT, 0, 100, 0, 30); + PeripheryManager.setVolume(VOLUME); default: break; } @@ -307,6 +314,10 @@ void MenuManager_::leftButton() case SoundMenu: SOUND_ACTIVE = !SOUND_ACTIVE; break; + case VolumeMenu: + VOLUME_PERCENT = (VOLUME_PERCENT % 100) + 1; + VOLUME = map(VOLUME_PERCENT, 0, 100, 0, 30); + PeripheryManager.setVolume(VOLUME); default: break; } @@ -361,6 +372,11 @@ void MenuManager_::selectButton() currentState = SoundMenu; break; case 12: +#ifdef AWTRIX_UPGRADE + currentState = VolumeMenu; +#endif + break; + case 13: if (FirmwareVersionCheck()) { updateFirmware(); @@ -437,6 +453,12 @@ void MenuManager_::selectButtonLong() DisplayManager.applyAllSettings(); saveSettings(); break; + case VolumeMenu: +#ifdef AWTRIX_UPGRADE + VOLUME = map(VOLUME_PERCENT, 0, 100, 0, 30); + saveSettings(); +#endif + break; case TimeFormatMenu: TIME_FORMAT = timeFormat[timeFormatIndex]; saveSettings(); diff --git a/src/PeripheryManager.cpp b/src/PeripheryManager.cpp index ba5ea0c..2232ea5 100644 --- a/src/PeripheryManager.cpp +++ b/src/PeripheryManager.cpp @@ -29,8 +29,16 @@ #ifdef ULANZI Adafruit_SHT31 sht31; #else + +class Mp3Notify +{ +}; Adafruit_BME280 bme280; +SoftwareSerial mySoftwareSerial(D7, D5); // RX, TX +typedef DFMiniMp3 DfMp3; +DfMp3 dfmp3(mySoftwareSerial); #endif + EasyButton button_left(BUTTON_UP_PIN); EasyButton button_right(BUTTON_DOWN_PIN); EasyButton button_select(BUTTON_SELECT_PIN); @@ -59,6 +67,11 @@ float sampleSum = 0.0; float sampleAverage = 0.0; float brightnessPercent = 0.0; +#ifdef awrtrix_upgrade +class Mp3Notify; +SoftwareSerial mySoftwareSerial(D7, D5); // RX, TX +#endif + // The getter for the instantiated singleton instance PeripheryManager_ &PeripheryManager_::getInstance() { @@ -71,14 +84,36 @@ PeripheryManager_ &PeripheryManager = PeripheryManager.getInstance(); void left_button_pressed() { - DisplayManager.leftButton(); - MenuManager.leftButton(); + if (AP_MODE) + { + --MATRIX_LAYOUT; + if (MATRIX_LAYOUT < 0) + MATRIX_LAYOUT = 2; + saveSettings(); + ESP.restart(); + } + else + { + DisplayManager.leftButton(); + MenuManager.leftButton(); + } } void right_button_pressed() { - DisplayManager.rightButton(); - MenuManager.rightButton(); + if (AP_MODE) + { + ++MATRIX_LAYOUT; + if (MATRIX_LAYOUT > 2) + MATRIX_LAYOUT = 0; + saveSettings(); + ESP.restart(); + } + else + { + DisplayManager.rightButton(); + MenuManager.rightButton(); + } } void select_button_pressed() @@ -111,35 +146,61 @@ void PeripheryManager_::playBootSound() return; if (BOOT_SOUND == "") { +#ifdef ULANZI const int nNotes = 6; String notes[nNotes] = {"E5", "C5", "G4", "E4", "G4", "C5"}; const int timeUnit = 150; Melody melody = MelodyFactory.load("Bootsound", timeUnit, notes, nNotes); player.playAsync(melody); +#else +// no standardsound +#endif } else - { +#ifdef ULANZI playFromFile("/MELODIES/" + BOOT_SOUND + ".txt"); +#else + dfmp3.playMp3FolderTrack(BOOT_SOUND.toInt()); +#endif } } void PeripheryManager_::stopSound() { +#ifdef ULANZI player.stop(); +#else + dfmp3.stop(); +#endif +} + +void PeripheryManager_::setVolume(uint8_t vol) +{ +#ifdef AWTRIX_UPGRADE + dfmp3.setVolume(vol); +#endif } void PeripheryManager_::playFromFile(String file) { if (!SOUND_ACTIVE) return; +#ifdef ULANZI Melody melody = MelodyFactory.loadRtttlFile(file); player.playAsync(melody); +#else + dfmp3.playMp3FolderTrack(file.toInt()); +#endif } bool PeripheryManager_::isPlaying() { +#ifdef ULANZI return player.isPlaying(); +#else + return false; +#endif } void fistStart() @@ -152,7 +213,7 @@ void fistStart() CURRENT_TEMP -= 9.0; #else CURRENT_TEMP = bme280.readTemperature(); - CURRENT_HUM = 0; + CURRENT_HUM = bme280.readHumidity(); #endif uint16_t LDRVALUE = analogRead(LDR_PIN); @@ -180,6 +241,7 @@ void PeripheryManager_::setup() sht31.begin(0x44); #else bme280.begin(); + dfmp3.begin(); #endif photocell.setPhotocellPositionOnGround(false); fistStart(); @@ -300,7 +362,6 @@ void PeripheryManager_::checkAlarms() } } - const char *PeripheryManager_::readUptime() { static char uptime[25]; // Make the array static to keep it from being destroyed when the function returns diff --git a/src/PeripheryManager.h b/src/PeripheryManager.h index 838a3ac..c2111bd 100644 --- a/src/PeripheryManager.h +++ b/src/PeripheryManager.h @@ -4,9 +4,11 @@ #include #include #ifdef ULANZI -#include "Adafruit_SHT31.h" + #include "Adafruit_SHT31.h" #else -#include "Adafruit_BME280.h" + #include "Adafruit_BME280.h" + #include "SoftwareSerial.h" + #include #endif class PeripheryManager_ @@ -35,6 +37,7 @@ public: void playFromFile(String file); bool isPlaying(); void stopSound(); + void setVolume(uint8_t); const char *readUptime(); }; diff --git a/src/ServerManager.cpp b/src/ServerManager.cpp index 3f24a54..3fde180 100644 --- a/src/ServerManager.cpp +++ b/src/ServerManager.cpp @@ -37,7 +37,7 @@ void saveHandler() webRequest->send(200); } -void handlePostRequest() +void handleAPIRequest() { WebServerClass *webRequest = mws.getRequest(); String url = webRequest->uri(); @@ -129,7 +129,7 @@ void ServerManager_::setup() if (isConnected) { - mws.onNotFound(handlePostRequest); + mws.addOptionBox("Network"); mws.addOption("Static IP", NET_STATIC); mws.addOption("Local IP", NET_IP); @@ -154,9 +154,30 @@ void ServerManager_::setup() mws.addJavascript(custom_script); mws.addOptionBox("General"); mws.addOption("Uppercase letters", UPPERCASE_LETTERS); - mws.addHandler("/save", HTTP_GET, saveHandler); + mws.addHandler("/save", HTTP_POST, saveHandler); + mws.addHandler("/api/notify", HTTP_POST, []() + {DisplayManager.generateNotification(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/nextapp", HTTP_POST, []() + {DisplayManager.nextApp(); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/previousapp", HTTP_POST, []() + {DisplayManager.previousApp(); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/timer", HTTP_POST, []() + { DisplayManager.gererateTimer(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/notify/dismiss", HTTP_POST, []() + { DisplayManager.dismissNotify(); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/apps", HTTP_POST, []() + { DisplayManager.updateAppVector(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/switch", HTTP_POST, []() + { DisplayManager.switchToApp(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/settings", HTTP_POST, []() + { DisplayManager.setNewSettings(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/custom", HTTP_POST, []() + { DisplayManager.generateCustomPage(mws.webserver->arg("name"),mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); + mws.addHandler("/api/stats", HTTP_GET, []() + { mws.webserver->sendContent(DisplayManager.getStat()); }); + Serial.println("Webserver loaded"); } - + mws.addHandler("/version", HTTP_GET, versionHandler); mws.begin(); if (!MDNS.begin(uniqueID)) diff --git a/src/main.cpp b/src/main.cpp index 3e78a3a..18a0b5f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -61,10 +61,15 @@ void setup() delay(500); Serial.begin(9600); loadSettings(); + Serial.println("1"); ServerManager.loadSettings(); + Serial.println("2"); DisplayManager.setup(); + Serial.println("3"); DisplayManager.HSVtext(9, 6, VERSION, true); + Serial.println("4"); delay(500); + Serial.println("5"); PeripheryManager.playBootSound(); xTaskCreatePinnedToCore(BootAnimation, "Task", 10000, NULL, 1, &taskHandle, 1); ServerManager.setup(); @@ -88,9 +93,10 @@ void loop() { ServerManager.tick(); DisplayManager.tick(); + PeripheryManager.tick(); if (ServerManager.isConnected) { - PeripheryManager.tick(); + MQTTManager.tick(); } }