From 34e5ca63044c4972a6f5caac517237b2da6708ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20M=C3=BChl?= <31169771+Blueforcer@users.noreply.github.com> Date: Tue, 16 May 2023 23:19:06 +0200 Subject: [PATCH] v0.64 allows to stack notifications --- src/Apps.h | 176 +++++++++++++++++++---------------------- src/DisplayManager.cpp | 116 ++++++++++++++------------- src/Globals.cpp | 2 +- 3 files changed, 147 insertions(+), 147 deletions(-) diff --git a/src/Apps.h b/src/Apps.h index 80c13191..a5df1d48 100644 --- a/src/Apps.h +++ b/src/Apps.h @@ -74,7 +74,6 @@ struct Notification File icon; bool rainbow; bool isGif; - bool flag = false; unsigned long startime = 0; uint16_t duration = 0; int16_t repeat = -1; @@ -95,9 +94,8 @@ struct Notification uint16_t background = 0; uint16_t pbColor; }; - -Notification notify; - +std::vector notifications; +bool notifyFlag = false; std::vector> Apps; CustomApp *getCustomAppByName(String name) @@ -131,7 +129,7 @@ int findAppIndexByName(const String &name) void TimeApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame, GifPlayer *gifPlayer) { - if (notify.flag) + if (notifyFlag) return; CURRENT_APP = "Time"; @@ -188,7 +186,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 firstFrame, bool lastFrame, GifPlayer *gifPlayer) { - if (notify.flag) + if (notifyFlag) return; CURRENT_APP = "Date"; if (DATE_COLOR > 0) @@ -223,7 +221,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 firstFrame, bool lastFrame, GifPlayer *gifPlayer) { - if (notify.flag) + if (notifyFlag) return; CURRENT_APP = "Temperature"; if (TEMP_COLOR > 0) @@ -256,7 +254,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 firstFrame, bool lastFrame, GifPlayer *gifPlayer) { - if (notify.flag) + if (notifyFlag) return; CURRENT_APP = "Humidity"; if (HUM_COLOR > 0) @@ -277,7 +275,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 firstFrame, bool lastFrame, GifPlayer *gifPlayer) { - if (notify.flag) + if (notifyFlag) return; CURRENT_APP = "Battery"; if (BAT_COLOR > 0) @@ -356,8 +354,8 @@ void TimerApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame, GifPlayer *gifPlayer) { - // Abort if notify.flag is set - if (notify.flag) + // Abort if notifyFlag is set + if (notifyFlag) { return; } @@ -461,7 +459,7 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState { if (ca->iconWasPushed && ca->pushIcon == 1) { - ca->scrollposition = 0 + notify.textOffset; + ca->scrollposition = 0 + notifications[0].textOffset; } else { @@ -470,7 +468,7 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState } else { - ca->scrollposition = 0 + notify.textOffset; + ca->scrollposition = 0 + notifications[0].textOffset; } } } @@ -663,117 +661,109 @@ void EyesApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, void NotifyApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer *gifPlayer) { // Check if notification flag is set - if (!notify.flag) + if (notifications.empty()) { + notifyFlag = false; return; // Exit function if flag is not set } + else + { + notifyFlag = true; + } // Set current app name CURRENT_APP = "Notification"; - // Get current time - unsigned long currentTime = millis(); // Check if notification duration has expired or if repeat count is 0 and hold is not enabled - if ((((currentTime - notify.startime >= notify.duration) && notify.repeat == -1) || notify.repeat == 0) && !notify.hold) + if ((((millis() - notifications[0].startime >= notifications[0].duration) && notifications[0].repeat == -1) || notifications[0].repeat == 0) && !notifications[0].hold) { // Reset notification flags and exit function - notify.flag = false; - notify.duration = 0; - notify.startime = 0; - notify.scrollposition = 34; - notify.iconWasPushed = false; - notify.iconPosition = 0; - notify.scrollDelay = 0; - notify.background = 0; - notify.repeat = -1; - notify.hold = false; - notify.textCase = 0; - notify.pushIcon = 0; - notify.barSize = 0; - notify.lineSize = 0; - notify.textOffset = 0; - notify.progress = -1; - notify.drawInstructions.clear(); + DEBUG_PRINTLN("Notification deleted"); + if (notifications.size() >= 2) + { + notifications[1].startime = millis(); + } + notifications.erase(notifications.begin()); return; } // Check if notification has an icon - bool hasIcon = notify.icon; + bool hasIcon = notifications[0].icon; // Clear the matrix display - matrix->fillRect(0, 0, 32, 8, notify.background); + matrix->fillRect(0, 0, 32, 8, notifications[0].background); // Calculate text and available width uint16_t textWidth = 0; - if (!notify.fragments.empty()) + if (!notifications[0].fragments.empty()) { - for (const auto &fragment : notify.fragments) + for (const auto &fragment : notifications[0].fragments) { - textWidth += getTextWidth(fragment.c_str(), notify.textCase); + textWidth += getTextWidth(fragment.c_str(), notifications[0].textCase); } } else { - textWidth = getTextWidth(notify.text.c_str(), notify.textCase); + textWidth = getTextWidth(notifications[0].text.c_str(), notifications[0].textCase); } uint16_t availableWidth = hasIcon ? 24 : 32; // Check if text is scrolling bool noScrolling = textWidth <= availableWidth; - if (notify.barSize > 0) + if (notifications[0].barSize > 0) { - DisplayManager.drawBarChart(0, 0, notify.barData, notify.barSize, hasIcon, notify.color); + DisplayManager.drawBarChart(0, 0, notifications[0].barData, notifications[0].barSize, hasIcon, notifications[0].color); } - else if (notify.lineSize > 0) + else if (notifications[0].lineSize > 0) { - DisplayManager.drawLineChart(0, 0, notify.lineData, notify.lineSize, hasIcon, notify.color); + DisplayManager.drawLineChart(0, 0, notifications[0].lineData, notifications[0].lineSize, hasIcon, notifications[0].color); } else { // Check if text needs to be scrolled - if (textWidth > availableWidth && notify.scrollposition <= -textWidth) + if (textWidth > availableWidth && notifications[0].scrollposition <= -textWidth) { // Reset scroll position and icon position if needed - notify.scrollDelay = 0; - notify.scrollposition = 9 + notify.textOffset; + notifications[0].scrollDelay = 0; + notifications[0].scrollposition = 9 + notifications[0].textOffset; - if (notify.pushIcon == 2) + if (notifications[0].pushIcon == 2) { - notify.iconWasPushed = false; + notifications[0].iconWasPushed = false; } - if (notify.repeat > 0) + if (notifications[0].repeat > 0) { - --notify.repeat; - if (notify.repeat == 0) + --notifications[0].repeat; + if (notifications[0].repeat == 0) return; } } if (!noScrolling) { - if ((notify.scrollDelay > MATRIX_FPS * 1.2) || ((hasIcon ? notify.textOffset + 9 : notify.textOffset) > 31)) + if ((notifications[0].scrollDelay > MATRIX_FPS * 1.2) || ((hasIcon ? notifications[0].textOffset + 9 : notifications[0].textOffset) > 31)) { - --notify.scrollposition; + --notifications[0].scrollposition; } else { - ++notify.scrollDelay; + ++notifications[0].scrollDelay; if (hasIcon) { - if (notify.iconWasPushed && notify.pushIcon == 1) + if (notifications[0].iconWasPushed && notifications[0].pushIcon == 1) { - notify.scrollposition = 0 + notify.textOffset; + notifications[0].scrollposition = 0 + notifications[0].textOffset; } else { - notify.scrollposition = 9 + notify.textOffset; + notifications[0].scrollposition = 9 + notifications[0].textOffset; } } else { - notify.scrollposition = 0 + notify.textOffset; + notifications[0].scrollposition = 0 + notifications[0].textOffset; } } } @@ -782,58 +772,58 @@ void NotifyApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer int16_t textX = hasIcon ? ((24 - textWidth) / 2) + 9 : ((32 - textWidth) / 2); // Set text color - matrix->setTextColor(notify.color); + matrix->setTextColor(notifications[0].color); if (noScrolling) { // Disable repeat if text is not scrolling - notify.repeat = -1; + notifications[0].repeat = -1; - if (!notify.fragments.empty()) + if (!notifications[0].fragments.empty()) { int16_t fragmentX = textX; - for (size_t i = 0; i < notify.fragments.size(); ++i) + for (size_t i = 0; i < notifications[0].fragments.size(); ++i) { - matrix->setTextColor(notify.colors[i]); - DisplayManager.printText(fragmentX, 6, notify.fragments[i].c_str(), false, notify.textCase); - fragmentX += getTextWidth(notify.fragments[i].c_str(), notify.textCase); + matrix->setTextColor(notifications[0].colors[i]); + DisplayManager.printText(fragmentX, 6, notifications[0].fragments[i].c_str(), false, notifications[0].textCase); + fragmentX += getTextWidth(notifications[0].fragments[i].c_str(), notifications[0].textCase); } } else { - if (notify.rainbow) + if (notifications[0].rainbow) { - DisplayManager.HSVtext(textX, 6, notify.text.c_str(), false, notify.textCase); + DisplayManager.HSVtext(textX, 6, notifications[0].text.c_str(), false, notifications[0].textCase); } else { - DisplayManager.printText(textX, 6, notify.text.c_str(), false, notify.textCase); + DisplayManager.printText(textX, 6, notifications[0].text.c_str(), false, notifications[0].textCase); } } } else { - if (!notify.fragments.empty()) + if (!notifications[0].fragments.empty()) { - int16_t fragmentX = notify.scrollposition; - for (size_t i = 0; i < notify.fragments.size(); ++i) + int16_t fragmentX = notifications[0].scrollposition; + for (size_t i = 0; i < notifications[0].fragments.size(); ++i) { - matrix->setTextColor(notify.colors[i]); - DisplayManager.printText(fragmentX, 6, notify.fragments[i].c_str(), false, notify.textCase); - fragmentX += getTextWidth(notify.fragments[i].c_str(), notify.textCase); + matrix->setTextColor(notifications[0].colors[i]); + DisplayManager.printText(fragmentX, 6, notifications[0].fragments[i].c_str(), false, notifications[0].textCase); + fragmentX += getTextWidth(notifications[0].fragments[i].c_str(), notifications[0].textCase); } } else { - if (notify.rainbow) + if (notifications[0].rainbow) { // Display scrolling text in rainbow color if enabled - DisplayManager.HSVtext(notify.scrollposition, 6, notify.text.c_str(), false, notify.textCase); + DisplayManager.HSVtext(notifications[0].scrollposition, 6, notifications[0].text.c_str(), false, notifications[0].textCase); } else { // Display scrolling text in solid color - DisplayManager.printText(notify.scrollposition, 6, notify.text.c_str(), false, notify.textCase); + DisplayManager.printText(notifications[0].scrollposition, 6, notifications[0].text.c_str(), false, notifications[0].textCase); } } } @@ -843,52 +833,52 @@ void NotifyApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer if (hasIcon) { // Push icon if enabled and text is scrolling - if (notify.pushIcon > 0 && !noScrolling && notify.barSize == 0) + if (notifications[0].pushIcon > 0 && !noScrolling && notifications[0].barSize == 0) { - if (notify.iconPosition < 0 && notify.iconWasPushed == false && notify.scrollposition > 8) + if (notifications[0].iconPosition < 0 && notifications[0].iconWasPushed == false && notifications[0].scrollposition > 8) { - ++notify.iconPosition; + ++notifications[0].iconPosition; } - if (notify.scrollposition < 9 && !notify.iconWasPushed) + if (notifications[0].scrollposition < 9 && !notifications[0].iconWasPushed) { - notify.iconPosition = notify.scrollposition - 9; + notifications[0].iconPosition = notifications[0].scrollposition - 9; - if (notify.iconPosition <= -9) + if (notifications[0].iconPosition <= -9) { - notify.iconWasPushed = true; + notifications[0].iconWasPushed = true; } } } // Display animated GIF if - if (notify.isGif) + if (notifications[0].isGif) { // Display GIF if present - gifPlayer->playGif(notify.iconPosition, 0, ¬ify.icon); + gifPlayer->playGif(notifications[0].iconPosition, 0, ¬ifications[0].icon); } else { // Display JPG image if present - DisplayManager.drawJPG(notify.iconPosition, 0, notify.icon); + DisplayManager.drawJPG(notifications[0].iconPosition, 0, notifications[0].icon); } // Display icon divider line if text is scrolling if (!noScrolling) { - matrix->drawLine(8 + notify.iconPosition, 0, 8 + notify.iconPosition, 7, 0); + matrix->drawLine(8 + notifications[0].iconPosition, 0, 8 + notifications[0].iconPosition, 7, 0); } } - if (notify.progress > -1) + if (notifications[0].progress > -1) { - DisplayManager.drawProgressBar((hasIcon ? 9 : 0), 7, notify.progress, notify.pColor, notify.pbColor); + DisplayManager.drawProgressBar((hasIcon ? 9 : 0), 7, notifications[0].progress, notifications[0].pColor, notifications[0].pbColor); } - if (notify.drawInstructions.length() > 0) + if (notifications[0].drawInstructions.length() > 0) { - DisplayManager.processDrawInstructions(0, 0, notify.drawInstructions); + DisplayManager.processDrawInstructions(0, 0, notifications[0].drawInstructions); } // Reset text color after displaying notification diff --git a/src/DisplayManager.cpp b/src/DisplayManager.cpp index 9f77a273..5607b1b8 100644 --- a/src/DisplayManager.cpp +++ b/src/DisplayManager.cpp @@ -591,58 +591,64 @@ void DisplayManager_::generateCustomPage(const String &name, const char *json) void DisplayManager_::generateNotification(const char *json) { StaticJsonDocument<4096> doc; - deserializeJson(doc, json); + DeserializationError error = deserializeJson(doc, json); + if (error) + { + doc.clear(); + return; + } + + Notification newNotification; - notify.progress = doc.containsKey("progress") ? doc["progress"].as() : -1; + newNotification.progress = doc.containsKey("progress") ? doc["progress"].as() : -1; if (doc.containsKey("progressC")) { auto progressC = doc["progressC"]; - notify.pColor = getColorFromJsonVariant(progressC, matrix->Color(0, 255, 0)); + newNotification.pColor = getColorFromJsonVariant(progressC, matrix->Color(0, 255, 0)); } else { - notify.pColor = matrix->Color(0, 255, 0); + newNotification.pColor = matrix->Color(0, 255, 0); } if (doc.containsKey("progressBC")) { auto progressBC = doc["progressBC"]; - notify.pbColor = getColorFromJsonVariant(progressBC, matrix->Color(255, 255, 255)); + newNotification.pbColor = getColorFromJsonVariant(progressBC, matrix->Color(255, 255, 255)); } else { - notify.pbColor = matrix->Color(255, 255, 255); + newNotification.pbColor = matrix->Color(255, 255, 255); } if (doc.containsKey("background")) { auto background = doc["background"]; - notify.background = getColorFromJsonVariant(background, 0); + newNotification.background = getColorFromJsonVariant(background, 0); } - notify.flag = true; if (doc.containsKey("draw")) { - notify.drawInstructions = doc["draw"].as(); + newNotification.drawInstructions = doc["draw"].as(); } else { - notify.drawInstructions = ""; - } - - notify.duration = doc.containsKey("duration") ? doc["duration"].as() * 1000 : TIME_PER_APP; - notify.repeat = doc.containsKey("repeat") ? doc["repeat"].as() : -1; - notify.rainbow = doc.containsKey("rainbow") ? doc["rainbow"].as() : false; - notify.hold = doc.containsKey("hold") ? doc["hold"].as() : false; - notify.pushIcon = doc.containsKey("pushIcon") ? doc["pushIcon"] : 0; - notify.textCase = doc.containsKey("textCase") ? doc["textCase"] : 0; - notify.textOffset = doc.containsKey("textOffset") ? doc["textOffset"] : 0; - notify.startime = millis(); - notify.scrollposition = 9 + notify.textOffset; - notify.iconWasPushed = false; - notify.iconPosition = 0; - notify.scrollDelay = 0; + newNotification.drawInstructions = ""; + } + + newNotification.duration = doc.containsKey("duration") ? doc["duration"].as() * 1000 : TIME_PER_APP; + newNotification.repeat = doc.containsKey("repeat") ? doc["repeat"].as() : -1; + newNotification.rainbow = doc.containsKey("rainbow") ? doc["rainbow"].as() : false; + newNotification.hold = doc.containsKey("hold") ? doc["hold"].as() : false; + newNotification.pushIcon = doc.containsKey("pushIcon") ? doc["pushIcon"] : 0; + newNotification.textCase = doc.containsKey("textCase") ? doc["textCase"] : 0; + newNotification.textOffset = doc.containsKey("textOffset") ? doc["textOffset"] : 0; + newNotification.startime = millis(); + newNotification.scrollposition = 9 + newNotification.textOffset; + newNotification.iconWasPushed = false; + newNotification.iconPosition = 0; + newNotification.scrollDelay = 0; if (doc.containsKey("sound")) { PeripheryManager.playFromFile(doc["sound"].as()); @@ -670,22 +676,22 @@ void DisplayManager_::generateNotification(const char *json) { maximum = d; } - notify.barData[i] = d; + newNotification.barData[i] = d; i++; } - notify.barSize = i; + newNotification.barSize = i; if (autoscale) { - for (int j = 0; j < notify.barSize; j++) + for (int j = 0; j < newNotification.barSize; j++) { - notify.barData[j] = map(notify.barData[j], 0, maximum, 0, 8); + newNotification.barData[j] = map(newNotification.barData[j], 0, maximum, 0, 8); } } } else { - notify.barSize = 0; + newNotification.barSize = 0; } if (doc.containsKey("line")) @@ -704,44 +710,44 @@ void DisplayManager_::generateNotification(const char *json) { maximum = d; } - notify.lineData[i] = d; + newNotification.lineData[i] = d; i++; } - notify.lineSize = i; + newNotification.lineSize = i; // Autoscaling if (autoscale) { - for (int j = 0; j < notify.lineSize; j++) + for (int j = 0; j < newNotification.lineSize; j++) { - notify.lineData[j] = map(notify.lineData[j], 0, maximum, 0, 8); + newNotification.lineData[j] = map(newNotification.lineData[j], 0, maximum, 0, 8); } } } else { - notify.lineSize = 0; + newNotification.lineSize = 0; } if (doc.containsKey("color")) { auto color = doc["color"]; - notify.color = getColorFromJsonVariant(color, TEXTCOLOR_565); + newNotification.color = getColorFromJsonVariant(color, TEXTCOLOR_565); } else { - notify.color = TEXTCOLOR_565; + newNotification.color = TEXTCOLOR_565; } if (doc.containsKey("text")) { String text = utf8ascii(doc["text"].as()); - parseFragmentsText(text, notify.colors, notify.fragments, notify.color); - notify.text = text; + parseFragmentsText(text, newNotification.colors, newNotification.fragments, newNotification.color); + newNotification.text = text; } else { - notify.text = ""; + newNotification.text = ""; } if (doc.containsKey("icon")) @@ -749,27 +755,29 @@ void DisplayManager_::generateNotification(const char *json) String iconFileName = doc["icon"].as(); if (LittleFS.exists("/ICONS/" + iconFileName + ".jpg")) { - notify.isGif = false; - notify.icon = LittleFS.open("/ICONS/" + iconFileName + ".jpg"); + newNotification.isGif = false; + newNotification.icon = LittleFS.open("/ICONS/" + iconFileName + ".jpg"); return; } else if (LittleFS.exists("/ICONS/" + iconFileName + ".gif")) { - notify.isGif = true; - notify.icon = LittleFS.open("/ICONS/" + iconFileName + ".gif"); + newNotification.isGif = true; + newNotification.icon = LittleFS.open("/ICONS/" + iconFileName + ".gif"); return; } else { fs::File nullPointer; - notify.icon = nullPointer; + newNotification.icon = nullPointer; } } else { fs::File nullPointer; - notify.icon = nullPointer; + newNotification.icon = nullPointer; } + + notifications.push_back(newNotification); } void DisplayManager_::loadNativeApps() @@ -1044,10 +1052,9 @@ void DisplayManager_::selectButton() { if (!MenuManager.inMenu) { - if (notify.flag && notify.hold) - { - DisplayManager.getInstance().dismissNotify(); - } + + DisplayManager.getInstance().dismissNotify(); + if (ALARM_ACTIVE && SNOOZE_TIME > 0) { PeripheryManager.stopSound(); @@ -1074,9 +1081,13 @@ void DisplayManager_::selectButtonLong() void DisplayManager_::dismissNotify() { - notify.hold = false; - notify.flag = false; - showGif = false; + if (!notifications.empty()) + { + if (notifyFlag && notifications[0].hold) + { + notifications.erase(notifications.begin()); + } + } } void timerCallback() @@ -1432,7 +1443,6 @@ void DisplayManager_::setIndicator1State(bool state) ui->setIndicator1State(state); } - void DisplayManager_::setIndicator2Color(uint16_t color) { ui->setIndicator2Color(color); diff --git a/src/Globals.cpp b/src/Globals.cpp index d61976c4..faae6896 100644 --- a/src/Globals.cpp +++ b/src/Globals.cpp @@ -216,7 +216,7 @@ IPAddress gateway; IPAddress subnet; IPAddress primaryDNS; IPAddress secondaryDNS; -const char *VERSION = "0.63"; +const char *VERSION = "0.64"; String MQTT_HOST = ""; uint16_t MQTT_PORT = 1883;