fix app sorting

This commit is contained in:
Stephan Mühl
2023-04-06 00:15:23 +02:00
parent 44bcb4b0d8
commit 4d690fbf2d
7 changed files with 131 additions and 144 deletions

View File

@@ -54,6 +54,7 @@
"list": "cpp", "list": "cpp",
"ratio": "cpp", "ratio": "cpp",
"mutex": "cpp", "mutex": "cpp",
"thread": "cpp" "thread": "cpp",
"set": "cpp"
} }
} }

View File

@@ -38,6 +38,7 @@ struct CustomApp
bool soundPlayed; bool soundPlayed;
uint16_t duration = 0; uint16_t duration = 0;
String sound; String sound;
byte textCase = 0;
int16_t repeat = 0; int16_t repeat = 0;
int16_t currentRepeat = 0; int16_t currentRepeat = 0;
String name; String name;
@@ -65,6 +66,7 @@ struct Notification
uint16_t duration = 0; uint16_t duration = 0;
int16_t repeat = -1; int16_t repeat = -1;
bool hold = false; bool hold = false;
byte textCase = 0;
byte pushIcon = 0; byte pushIcon = 0;
int16_t iconPosition = 0; int16_t iconPosition = 0;
bool iconWasPushed = false; bool iconWasPushed = false;
@@ -91,7 +93,7 @@ String getAppNameByFunction(AppCallback AppFunction)
} }
} }
return ""; // Gibt einen leeren String zurück, wenn die App-Funktion nicht gefunden wurde return "";
} }
int findAppIndexByName(const String &name) int findAppIndexByName(const String &name)
@@ -407,12 +409,12 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState
// Display text with rainbow effect if enabled // Display text with rainbow effect if enabled
if (ca->rainbow) if (ca->rainbow)
{ {
DisplayManager.HSVtext(x + textX, 6 + y, ca->text.c_str(), false); DisplayManager.HSVtext(x + textX, 6 + y, ca->text.c_str(), false, ca->textCase);
} }
else else
{ {
// Display text // Display text
DisplayManager.printText(x + textX, y + 6, ca->text.c_str(), false, false); DisplayManager.printText(x + textX, y + 6, ca->text.c_str(), false, ca->textCase);
} }
} }
else else
@@ -420,11 +422,11 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState
// Display scrolling text with rainbow effect if enabled // Display scrolling text with rainbow effect if enabled
if (ca->rainbow) if (ca->rainbow)
{ {
DisplayManager.HSVtext(x + ca->scrollposition, 6 + y, ca->text.c_str(), false); DisplayManager.HSVtext(x + ca->scrollposition, 6 + y, ca->text.c_str(), false, ca->textCase);
} }
else else
{ {
DisplayManager.printText(x + ca->scrollposition, 6 + y, ca->text.c_str(), false, false); DisplayManager.printText(x + ca->scrollposition, 6 + y, ca->text.c_str(), false, ca->textCase);
} }
} }
} }
@@ -581,12 +583,12 @@ void NotifyApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state)
if (notify.rainbow) if (notify.rainbow)
{ {
// Display text in rainbow color if enabled // Display text in rainbow color if enabled
DisplayManager.HSVtext(textX, 6, notify.text.c_str(), false); DisplayManager.HSVtext(textX, 6, notify.text.c_str(), false, notify.textCase);
} }
else else
{ {
// Display text in solid color // Display text in solid color
DisplayManager.printText(textX, 6, notify.text.c_str(), false, false); DisplayManager.printText(textX, 6, notify.text.c_str(), false, notify.textCase);
} }
} }
else else
@@ -594,12 +596,12 @@ void NotifyApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state)
if (notify.rainbow) if (notify.rainbow)
{ {
// Display scrolling text in rainbow color if enabled // Display scrolling text in rainbow color if enabled
DisplayManager.HSVtext(notify.scrollposition, 6, notify.text.c_str(), false); DisplayManager.HSVtext(notify.scrollposition, 6, notify.text.c_str(), false, notify.textCase);
} }
else else
{ {
// Display scrolling text in solid color // Display scrolling text in solid color
DisplayManager.printText(notify.scrollposition, 6, notify.text.c_str(), false, false); DisplayManager.printText(notify.scrollposition, 6, notify.text.c_str(), false, notify.textCase);
} }
} }
} }

View File

@@ -14,6 +14,7 @@
#include "MenuManager.h" #include "MenuManager.h"
#include "Apps.h" #include "Apps.h"
#include "Dictionary.h" #include "Dictionary.h"
#include <set>
Ticker AlarmTicker; Ticker AlarmTicker;
Ticker TimerTicker; Ticker TimerTicker;
@@ -147,11 +148,11 @@ bool jpg_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap)
return 0; return 0;
} }
void DisplayManager_::printText(int16_t x, int16_t y, const char *text, bool centered, bool ignoreUppercase) void DisplayManager_::printText(int16_t x, int16_t y, const char *text, bool centered, byte textCase)
{ {
if (centered) if (centered)
{ {
uint16_t textWidth = getTextWidth(text, ignoreUppercase); uint16_t textWidth = getTextWidth(text, textCase);
int16_t textX = ((32 - textWidth) / 2); int16_t textX = ((32 - textWidth) / 2);
matrix->setCursor(textX, y); matrix->setCursor(textX, y);
} }
@@ -160,7 +161,7 @@ void DisplayManager_::printText(int16_t x, int16_t y, const char *text, bool cen
matrix->setCursor(x, y); matrix->setCursor(x, y);
} }
if (UPPERCASE_LETTERS && !ignoreUppercase) if ((UPPERCASE_LETTERS && textCase == 0) || textCase == 1)
{ {
size_t length = strlen(text); size_t length = strlen(text);
char upperText[length + 1]; // +1 for the null terminator char upperText[length + 1]; // +1 for the null terminator
@@ -179,7 +180,7 @@ void DisplayManager_::printText(int16_t x, int16_t y, const char *text, bool cen
} }
} }
void DisplayManager_::HSVtext(int16_t x, int16_t y, const char *text, bool clear) void DisplayManager_::HSVtext(int16_t x, int16_t y, const char *text, bool clear, byte textCase)
{ {
if (clear) if (clear)
matrix->clear(); matrix->clear();
@@ -193,7 +194,7 @@ void DisplayManager_::HSVtext(int16_t x, int16_t y, const char *text, bool clear
const char *myChar = &text[i]; const char *myChar = &text[i];
matrix->setCursor(xpos + x, y); matrix->setCursor(xpos + x, y);
if (UPPERCASE_LETTERS) if ((UPPERCASE_LETTERS && textCase == 0) || textCase == 1)
{ {
matrix->print((char)toupper(text[i])); matrix->print((char)toupper(text[i]));
} }
@@ -235,7 +236,7 @@ void pushCustomApp(String name, int position)
} }
} }
void removeCustomApp(const String &name) void removeCustomAppFromApps(const String &name)
{ {
auto it = std::find_if(Apps.begin(), Apps.end(), [&name](const std::pair<String, AppCallback> &appPair) auto it = std::find_if(Apps.begin(), Apps.end(), [&name](const std::pair<String, AppCallback> &appPair)
{ return appPair.first == name; }); { return appPair.first == name; });
@@ -251,7 +252,7 @@ void DisplayManager_::generateCustomPage(const String &name, const char *json)
{ {
Serial.println("delete"); Serial.println("delete");
customApps.erase(customApps.find(name)); customApps.erase(customApps.find(name));
removeCustomApp(name); removeCustomAppFromApps(name);
showGif = false; showGif = false;
return; return;
} }
@@ -309,6 +310,7 @@ void DisplayManager_::generateCustomPage(const String &name, const char *json)
int pos = doc.containsKey("pos") ? doc["pos"].as<uint8_t>() : -1; int pos = doc.containsKey("pos") ? doc["pos"].as<uint8_t>() : -1;
customApp.rainbow = doc.containsKey("rainbow") ? doc["rainbow"] : false; customApp.rainbow = doc.containsKey("rainbow") ? doc["rainbow"] : false;
customApp.pushIcon = doc.containsKey("pushIcon") ? doc["pushIcon"] : 0; customApp.pushIcon = doc.containsKey("pushIcon") ? doc["pushIcon"] : 0;
customApp.textCase = doc.containsKey("textCase") ? doc["textCase"] : 0;
customApp.name = name; customApp.name = name;
customApp.text = utf8ascii(doc["text"].as<String>()); customApp.text = utf8ascii(doc["text"].as<String>());
@@ -394,7 +396,7 @@ void DisplayManager_::generateNotification(const char *json)
notify.rainbow = doc.containsKey("rainbow") ? doc["rainbow"].as<bool>() : false; notify.rainbow = doc.containsKey("rainbow") ? doc["rainbow"].as<bool>() : false;
notify.hold = doc.containsKey("hold") ? doc["hold"].as<bool>() : false; notify.hold = doc.containsKey("hold") ? doc["hold"].as<bool>() : false;
notify.pushIcon = doc.containsKey("pushIcon") ? doc["pushIcon"] : 0; notify.pushIcon = doc.containsKey("pushIcon") ? doc["pushIcon"] : 0;
notify.textCase = doc.containsKey("textCase") ? doc["textCase"] : 0;
notify.startime = millis(); notify.startime = millis();
notify.scrollposition = 9; notify.scrollposition = 9;
notify.iconWasPushed = false; notify.iconWasPushed = false;
@@ -560,7 +562,7 @@ void DisplayManager_::tick()
{ {
if (AP_MODE) if (AP_MODE)
{ {
HSVtext(2, 6, "AP MODE", true); HSVtext(2, 6, "AP MODE", true, 1);
} }
else else
{ {
@@ -725,7 +727,7 @@ void DisplayManager_::drawProgressBar(int cur, int total)
matrix->clear(); matrix->clear();
int progress = (cur * 100) / total; int progress = (cur * 100) / total;
char progressStr[5]; char progressStr[5];
snprintf(progressStr, 5, "%d%%", progress); // Formatieren des Prozentzeichens snprintf(progressStr, 5, "%d%%", progress);
printText(0, 6, progressStr, true, false); printText(0, 6, progressStr, true, false);
int leds_for_progress = (progress * MATRIX_WIDTH * MATRIX_HEIGHT) / 100; int leds_for_progress = (progress * MATRIX_WIDTH * MATRIX_HEIGHT) / 100;
matrix->drawFastHLine(0, 7, MATRIX_WIDTH, matrix->Color(100, 100, 100)); matrix->drawFastHLine(0, 7, MATRIX_WIDTH, matrix->Color(100, 100, 100));
@@ -758,7 +760,6 @@ void DisplayManager_::drawBarChart(int16_t x, int16_t y, const int data[], byte
int maximum = 0; int maximum = 0;
int newData[dataSize]; int newData[dataSize];
// Finde das Maximum in der Datenliste
for (int i = 0; i < dataSize; i++) for (int i = 0; i < dataSize; i++)
{ {
int d = data[i]; int d = data[i];
@@ -768,14 +769,12 @@ void DisplayManager_::drawBarChart(int16_t x, int16_t y, const int data[], byte
} }
} }
// Berechne neue Datenwerte zwischen 0 und 8 basierend auf dem Maximum
for (int i = 0; i < dataSize; i++) for (int i = 0; i < dataSize; i++)
{ {
int d = data[i]; int d = data[i];
newData[i] = map(d, 0, maximum, 0, 8); newData[i] = map(d, 0, maximum, 0, 8);
} }
// Berechne die Breite der Balken basierend auf der Anzahl der Daten und der Breite der Matrix
int barWidth; int barWidth;
if (withIcon) if (withIcon)
{ {
@@ -786,10 +785,8 @@ void DisplayManager_::drawBarChart(int16_t x, int16_t y, const int data[], byte
barWidth = (32 / (dataSize)-1); barWidth = (32 / (dataSize)-1);
} }
// Berechne die Startposition des Graphen basierend auf dem Icon-Parameter
int startX = withIcon ? 9 : 0; int startX = withIcon ? 9 : 0;
// Zeichne die Balken auf die Matrix
for (int i = 0; i < dataSize; i++) for (int i = 0; i < dataSize; i++)
{ {
int x1 = x + startX + (barWidth + 1) * i; int x1 = x + startX + (barWidth + 1) * i;
@@ -799,126 +796,92 @@ void DisplayManager_::drawBarChart(int16_t x, int16_t y, const int data[], byte
} }
} }
std::pair<String, AppCallback> getNativeAppByName(const String &appName)
{
if (appName == "time")
{
return std::make_pair("time", TimeApp);
}
else if (appName == "date")
{
return std::make_pair("date", DateApp);
}
else if (appName == "temp")
{
return std::make_pair("temp", TempApp);
}
else if (appName == "hum")
{
return std::make_pair("hum", HumApp);
}
else if (appName == "bat")
{
return std::make_pair("bat", BatApp);
}
return std::make_pair("", nullptr);
}
void DisplayManager_::updateAppVector(const char *json) void DisplayManager_::updateAppVector(const char *json)
{ {
// Parse the JSON input StaticJsonDocument<512> doc; // Erhöhen Sie die Größe des Dokuments bei Bedarf
DynamicJsonDocument doc(1024); deserializeJson(doc, json);
auto error = deserializeJson(doc, json);
if (error) JsonArray appArray;
if (doc.is<JsonObject>())
{ {
// If parsing fails, print an error message and return JsonArray tempArray = doc.to<JsonArray>();
Serial.print("Failed to parse JSON: "); tempArray.add(doc.as<JsonObject>());
Serial.println(error.c_str()); appArray = tempArray;
return; }
else if (doc.is<JsonArray>())
{
appArray = doc.as<JsonArray>();
} }
// Create new vectors to store updated apps for (JsonObject appObj : appArray)
std::vector<std::pair<String, AppCallback>> newApps; {
std::vector<String> activeApps; String appName = appObj["name"].as<String>();
bool show = appObj["show"].as<bool>();
int position = appObj.containsKey("pos") ? appObj["pos"].as<int>() : Apps.size();
// Loop through all apps in the JSON input auto appIt = std::find_if(Apps.begin(), Apps.end(), [&appName](const std::pair<String, AppCallback> &app)
for (const auto &app : doc.as<JsonArray>()) { return app.first == appName; });
{
// Get the app name, active status, and position (if specified)
String name = app["name"].as<String>();
bool show = true;
int position = -1;
if (app.containsKey("show"))
std::pair<String, AppCallback> nativeApp = getNativeAppByName(appName);
if (!show)
{ {
show = app["show"].as<bool>(); if (appIt != Apps.end())
}
if (app.containsKey("pos"))
{ {
position = app["pos"].as<int>(); Apps.erase(appIt);
}
// Find the corresponding AppCallback function based on the app name
AppCallback callback;
if (name == "time")
{
callback = TimeApp;
SHOW_TIME = show;
}
else if (name == "date")
{
callback = DateApp;
SHOW_DATE = show;
}
else if (name == "temp")
{
callback = TempApp;
SHOW_TEMP = show;
}
else if (name == "hum")
{
callback = HumApp;
SHOW_HUM = show;
}
#ifdef ULANZI
else if (name == "bat")
{
callback = BatApp;
SHOW_BAT = show;
}
#endif
else
{
// If the app is not one of the built-in apps, check if it's already in the vector
int appIndex = findAppIndexByName(name);
if (appIndex >= 0)
{
// The app is in the vector, so we can move it to a new position or remove it
auto it = Apps.begin() + appIndex;
if (show)
{
if (position >= 0 && static_cast<size_t>(position) < newApps.size())
{
Apps.erase(it);
newApps.insert(newApps.begin() + position, std::make_pair(name, it->second));
} }
} }
else else
{ {
// If the app is being removed, also remove it from the customApps map if (nativeApp.second != nullptr)
if (customApps.count(name))
{ {
customApps.erase(customApps.find(name)); if (appIt != Apps.end())
removeCustomApp(name);
}
}
}
continue;
}
if (show)
{ {
// Add the app to the new vector Apps.erase(appIt);
if (position >= 0 && static_cast<size_t>(position) < newApps.size()) }
{ position = position < 0 ? 0 : position >= Apps.size() ? Apps.size()
newApps.insert(newApps.begin() + position, std::make_pair(name, callback)); : position;
Apps.insert(Apps.begin() + position, nativeApp);
} }
else else
{ {
newApps.emplace_back(name, callback); if (appIt != Apps.end() && appObj.containsKey("pos"))
}
}
activeApps.push_back(name);
}
// Loop through all apps currently in the vector
for (const auto &app : Apps)
{ {
// If the app is not in the updated activeApps vector, add it to the newApps vector std::pair<String, AppCallback> app = *appIt;
if (std::find(activeApps.begin(), activeApps.end(), app.first) == activeApps.end()) Apps.erase(appIt);
{ position = position < 0 ? 0 : position >= Apps.size() ? Apps.size()
newApps.push_back(app); : position;
Apps.insert(Apps.begin() + position, app);
}
}
} }
} }
// Update the apps vector, set it in the UI, and save settings // Set the updated apps vector in the UI and save settings
Apps = std::move(newApps);
ui->setApps(Apps); ui->setApps(Apps);
saveSettings(); saveSettings();
} }
@@ -974,3 +937,21 @@ void DisplayManager_::setMatrixLayout(int layout)
delete ui; // Free memory from the current ui object delete ui; // Free memory from the current ui object
ui = new MatrixDisplayUi(matrix); // Create a new ui object with the new matrix ui = new MatrixDisplayUi(matrix); // Create a new ui object with the new matrix
} }
String DisplayManager_::getAppsAsJson()
{
// Create a JSON object to hold the app positions and names
DynamicJsonDocument doc(1024);
JsonObject appsObject = doc.to<JsonObject>();
// Add each app position and name to the object
for (size_t i = 0; i < Apps.size(); i++)
{
appsObject[String(i)] = Apps[i].first;
}
// Serialize the JSON object to a string and return it
String json;
serializeJson(appsObject, json);
return json;
}

View File

@@ -35,7 +35,7 @@ public:
void applyAllSettings(); void applyAllSettings();
void rightButton(); void rightButton();
void dismissNotify(); void dismissNotify();
void HSVtext(int16_t, int16_t, const char *, bool); void HSVtext(int16_t, int16_t, const char *, bool, byte textCase);
void loadNativeApps(); void loadNativeApps();
void nextApp(); void nextApp();
void previousApp(); void previousApp();
@@ -51,7 +51,7 @@ public:
void MatrixState(bool); void MatrixState(bool);
void generateNotification(const char *json); void generateNotification(const char *json);
void generateCustomPage(const String &name, const char *json); void generateCustomPage(const String &name, const char *json);
void printText(int16_t x, int16_t y, const char *text, bool centered, bool ignoreUppercase); void printText(int16_t x, int16_t y, const char *text, bool centered, byte textCase);
bool setAutoTransition(bool active); bool setAutoTransition(bool active);
void switchToApp(const char *json); void switchToApp(const char *json);
void setNewSettings(const char *json); void setNewSettings(const char *json);
@@ -64,6 +64,7 @@ public:
void updateAppVector(const char *json); void updateAppVector(const char *json);
void setMatrixLayout(int layout); void setMatrixLayout(int layout);
void setAppTime(uint16_t duration); void setAppTime(uint16_t duration);
String getAppsAsJson();
String getStat(); String getStat();
}; };

View File

@@ -32,13 +32,13 @@ uint16_t hexToRgb565(String hexValue)
return color; return color;
} }
uint16_t getTextWidth(const char *text, bool ignoreUpperCase) uint16_t getTextWidth(const char *text, byte textCase)
{ {
uint16_t width = 0; uint16_t width = 0;
for (const char *c = text; *c != '\0'; ++c) for (const char *c = text; *c != '\0'; ++c)
{ {
char current_char = *c; char current_char = *c;
if (UPPERCASE_LETTERS && !ignoreUpperCase) if ((UPPERCASE_LETTERS && textCase == 0) || textCase == 1)
{ {
current_char = toupper(current_char); current_char = toupper(current_char);
} }

View File

@@ -91,6 +91,8 @@ void ServerManager_::setup()
{ DisplayManager.updateAppVector(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); { DisplayManager.updateAppVector(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); });
mws.addHandler("/api/switch", HTTP_POST, []() mws.addHandler("/api/switch", HTTP_POST, []()
{ DisplayManager.switchToApp(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); { DisplayManager.switchToApp(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); });
mws.addHandler("/api/loop", HTTP_GET, []()
{ mws.webserver->sendContent(DisplayManager.getAppsAsJson()); });
mws.addHandler("/api/settings", HTTP_POST, []() mws.addHandler("/api/settings", HTTP_POST, []()
{ DisplayManager.setNewSettings(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); }); { DisplayManager.setNewSettings(mws.webserver->arg("plain").c_str()); mws.webserver->send(200,"OK"); });
mws.addHandler("/api/custom", HTTP_POST, []() mws.addHandler("/api/custom", HTTP_POST, []()

View File

@@ -51,7 +51,7 @@ void BootAnimation(void *parameter)
{ {
break; break;
} }
DisplayManager.HSVtext(4, 6, "AWTRIX", true); DisplayManager.HSVtext(4, 6, "AWTRIX", true, 0);
vTaskDelay(xDelay); vTaskDelay(xDelay);
} }
vTaskDelete(NULL); vTaskDelete(NULL);
@@ -64,10 +64,10 @@ void setup()
PeripheryManager.setup(); PeripheryManager.setup();
ServerManager.loadSettings(); ServerManager.loadSettings();
DisplayManager.setup(); DisplayManager.setup();
DisplayManager.HSVtext(9, 6, VERSION, true); DisplayManager.HSVtext(9, 6, VERSION, true, 0);
delay(500); delay(500);
PeripheryManager.playBootSound(); PeripheryManager.playBootSound();
xTaskCreatePinnedToCore(BootAnimation, "Task", 10000, NULL, 1, &taskHandle, 1); xTaskCreatePinnedToCore(BootAnimation, "Task", 10000, NULL, 1, &taskHandle, 0);
ServerManager.setup(); ServerManager.setup();
if (ServerManager.isConnected) if (ServerManager.isConnected)
{ {
@@ -79,7 +79,7 @@ void setup()
float x = 4; float x = 4;
while (x >= -85) while (x >= -85)
{ {
DisplayManager.HSVtext(x, 6, ("AWTRIX " + ServerManager.myIP.toString()).c_str(), true); DisplayManager.HSVtext(x, 6, ("AWTRIX " + ServerManager.myIP.toString()).c_str(), true, 0);
x -= 0.18; x -= 0.18;
} }
BeaconScanner.setup(); BeaconScanner.setup();