- App transistion is now inacitve if there is only 1 app
- Adds bargraph to notify and customapps
- Every awtrix now gets a unique id for AP, MQTT and HA
- Adds firmware as HA sensor
- Adds wifi strength as HA sensor
- Adds ram usage as HA sensor
- Adds version as HA sensor
- Adds uptime as ISO 8601 as HA sensot
- HA discorvery now gets correct device classes
- fixes bug where date formats are not saved

closes #24
closes #23
closes #21
This commit is contained in:
Stephan Mühl
2023-03-29 00:24:38 +02:00
parent 3de324605e
commit c51c769cb5
16 changed files with 1217 additions and 967 deletions

View File

@@ -12,12 +12,17 @@
#include "Functions.h"
#include "ServerManager.h"
#include "MenuManager.h"
#include "Frames.h"
#include "Apps.h"
Ticker AlarmTicker;
Ticker TimerTicker;
#ifdef ULANZI
#define MATRIX_PIN 32
#else
#define MATRIX_PIN D2
#endif
#define MATRIX_WIDTH 32
#define MATRIX_HEIGHT 8
@@ -68,6 +73,11 @@ void DisplayManager_::MatrixState(bool on)
bool DisplayManager_::setAutoTransition(bool active)
{
if (ui.AppCount < 2)
{
ui.disablesetAutoTransition();
return false;
}
if (active && AUTO_TRANSITION)
{
ui.enablesetAutoTransition();
@@ -198,31 +208,31 @@ void DisplayManager_::HSVtext(int16_t x, int16_t y, const char *text, bool clear
matrix.show();
}
void pushCustomFrame(String name, int position)
void pushCustomApp(String name, int position)
{
if (customFrames.count(name) == 0)
if (customApps.count(name) == 0)
{
++customPagesCount;
void (*customFrames[10])(FastLED_NeoMatrix *, MatrixDisplayUiState *, int16_t, int16_t, bool, bool) = {CFrame1, CFrame2, CFrame3, CFrame4, CFrame5, CFrame6, CFrame7, CFrame8, CFrame9, CFrame10};
void (*customApps[10])(FastLED_NeoMatrix *, MatrixDisplayUiState *, int16_t, int16_t, bool, bool) = {CApp1, CApp2, CApp3, CApp4, CApp5, CApp6, CApp7, CApp8, CApp9, CApp10};
if (position < 0) // Insert at the end of the vector
{
Apps.push_back(std::make_pair(name, customFrames[customPagesCount]));
Apps.push_back(std::make_pair(name, customApps[customPagesCount]));
}
else if (position < Apps.size()) // Insert at a specific position
{
Apps.insert(Apps.begin() + position, std::make_pair(name, customFrames[customPagesCount]));
Apps.insert(Apps.begin() + position, std::make_pair(name, customApps[customPagesCount]));
}
else // Invalid position, Insert at the end of the vector
{
Apps.push_back(std::make_pair(name, customFrames[customPagesCount]));
Apps.push_back(std::make_pair(name, customApps[customPagesCount]));
}
ui.setApps(Apps); // Add frames
ui.setApps(Apps); // Add Apps
}
}
void removeCustomFrame(const String &name)
void removeCustomApp(const String &name)
{
auto it = std::find_if(Apps.begin(), Apps.end(), [&name](const std::pair<String, AppCallback> &appPair)
{ return appPair.first == name; });
@@ -236,10 +246,10 @@ void removeCustomFrame(const String &name)
void DisplayManager_::generateCustomPage(String name, String payload)
{
if (payload == "" && customFrames.count(name))
if (payload == "" && customApps.count(name))
{
customFrames.erase(customFrames.find(name));
removeCustomFrame(name);
customApps.erase(customApps.find(name));
removeCustomApp(name);
return;
}
@@ -248,31 +258,52 @@ void DisplayManager_::generateCustomPage(String name, String payload)
if (error)
return;
CustomFrame customFrame;
CustomApp customApp;
if (doc.containsKey("sound"))
{
customFrame.sound = ("/" + doc["sound"].as<String>() + ".txt");
customApp.sound = ("/" + doc["sound"].as<String>() + ".txt");
}
else
{
customFrame.sound = "";
customApp.sound = "";
}
customFrame.rainbow = doc.containsKey("rainbow") ? doc["rainbow"] : false;
customFrame.pushIcon = doc.containsKey("pushIcon") ? doc["pushIcon"] : 0;
customFrame.name = name;
customFrame.text = utf8ascii(doc["text"].as<String>());
customFrame.color = doc.containsKey("color") ? doc["color"].is<String>() ? hexToRgb565(doc["color"]) : doc["color"].is<JsonArray>() ? hexToRgb565(doc["color"].as<String>())
: TEXTCOLOR_565
: TEXTCOLOR_565;
if (currentCustomFrame != name)
if (doc.containsKey("bar"))
{
customFrame.scrollposition = 9;
JsonArray barData = doc["bar"];
int i = 0;
for (JsonVariant v : barData)
{
if (i >= 16)
{
break;
}
customApp.barData[i] = v.as<int>();
i++;
}
customApp.barSize = i;
}
else
{
customApp.barSize = 0;
}
customFrame.repeat = doc.containsKey("repeat") ? doc["repeat"].as<uint8_t>() : -1;
int pos = doc.containsKey("pos") ? doc["pos"].as<uint8_t>() : -1;
customApp.rainbow = doc.containsKey("rainbow") ? doc["rainbow"] : false;
customApp.pushIcon = doc.containsKey("pushIcon") ? doc["pushIcon"] : 0;
customApp.name = name;
customApp.text = utf8ascii(doc["text"].as<String>());
customApp.color = doc.containsKey("color") ? doc["color"].is<String>() ? hexToRgb565(doc["color"]) : doc["color"].is<JsonArray>() ? hexToRgb565(doc["color"].as<String>())
: TEXTCOLOR_565
: TEXTCOLOR_565;
if (currentCustomApp != name)
{
customApp.scrollposition = 9;
}
customApp.repeat = doc.containsKey("repeat") ? doc["repeat"].as<uint8_t>() : -1;
if (doc.containsKey("icon"))
{
@@ -280,20 +311,28 @@ void DisplayManager_::generateCustomPage(String name, String payload)
if (LittleFS.exists("/ICONS/" + iconFileName + ".jpg"))
{
customFrame.isGif = false;
customFrame.icon = LittleFS.open("/ICONS/" + iconFileName + ".jpg");
customApp.isGif = false;
customApp.icon = LittleFS.open("/ICONS/" + iconFileName + ".jpg");
}
else if (LittleFS.exists("/ICONS/" + iconFileName + ".gif"))
{
customFrame.isGif = true;
customFrame.icon = LittleFS.open("/ICONS/" + iconFileName + ".gif");
customApp.isGif = true;
customApp.icon = LittleFS.open("/ICONS/" + iconFileName + ".gif");
}
else
{
fs::File nullPointer;
customApp.icon = nullPointer;
}
}
else
{
fs::File nullPointer;
customApp.icon = nullPointer;
}
int pos = doc.containsKey("pos") ? doc["pos"].as<uint8_t>() : -1;
pushCustomFrame(name, pos - 1);
customFrames[name] = customFrame;
pushCustomApp(name, pos - 1);
customApps[name] = customApp;
}
void DisplayManager_::generateNotification(String payload)
@@ -318,6 +357,26 @@ void DisplayManager_::generateNotification(String payload)
PeripheryManager.playFromFile("/MELODIES/" + doc["sound"].as<String>() + ".txt");
}
if (doc.containsKey("bar"))
{
JsonArray barData = doc["bar"];
int i = 0;
for (JsonVariant v : barData)
{
if (i >= 16)
{
break;
}
notify.barData[i] = v.as<int>();
i++;
}
notify.barSize = i;
}
else
{
notify.barSize = 0;
}
notify.color = doc.containsKey("color") ? doc["color"].is<String>() ? hexToRgb565(doc["color"]) : doc["color"].is<JsonArray>() ? hexToRgb565(doc["color"].as<String>())
: TEXTCOLOR_565
: TEXTCOLOR_565;
@@ -329,17 +388,24 @@ void DisplayManager_::generateNotification(String payload)
{
notify.isGif = false;
notify.icon = LittleFS.open("/ICONS/" + iconFileName + ".jpg");
return;
}
else if (LittleFS.exists("/ICONS/" + iconFileName + ".gif"))
{
notify.isGif = true;
notify.icon = LittleFS.open("/ICONS/" + iconFileName + ".gif");
return;
}
else
{
fs::File nullPointer;
notify.icon = nullPointer;
}
}
else
{
File f;
notify.icon = f;
fs::File nullPointer;
notify.icon = nullPointer;
}
}
@@ -374,25 +440,23 @@ void DisplayManager_::loadNativeApps()
};
// Update the "time" app at position 0
updateApp("time", TimeFrame, SHOW_TIME, 0);
updateApp("time", TimeApp, SHOW_TIME, 0);
// Update the "date" app at position 1
updateApp("date", DateFrame, SHOW_DATE, 1);
updateApp("date", DateApp, SHOW_DATE, 1);
// Update the "temp" app at position 2
updateApp("temp", TempFrame, SHOW_TEMP, 2);
updateApp("temp", TempApp, SHOW_TEMP, 2);
// Update the "hum" app at position 3
updateApp("hum", HumFrame, SHOW_HUM, 3);
updateApp("hum", HumApp, SHOW_HUM, 3);
// Update the "bat" app at position 4
updateApp("bat", BatFrame, SHOW_BAT, 4);
updateApp("bat", BatApp, SHOW_BAT, 4);
ui.setApps(Apps);
if (AUTO_TRANSITION && Apps.size() == 1)
{
setAutoTransition(false);
}
setAutoTransition(true);
}
void DisplayManager_::setup()
@@ -415,12 +479,12 @@ void DisplayManager_::tick()
else
{
ui.update();
if (ui.getUiState()->frameState == IN_TRANSITION && !appIsSwitching)
if (ui.getUiState()->appState == IN_TRANSITION && !appIsSwitching)
{
appIsSwitching = true;
MQTTManager.setCurrentApp(CURRENT_APP);
}
else if (ui.getUiState()->frameState == FIXED && appIsSwitching)
else if (ui.getUiState()->appState == FIXED && appIsSwitching)
{
appIsSwitching = false;
MQTTManager.setCurrentApp(CURRENT_APP);
@@ -593,4 +657,50 @@ void DisplayManager_::drawMenuIndicator(int cur, int total, uint16_t color)
matrix.drawLine(x, 7, x + menuItemWidth - 1, 7, matrix.Color(100, 100, 100));
}
}
}
void DisplayManager_::drawBarChart(int16_t x, int16_t y, const int data[], byte dataSize, bool withIcon, uint16_t color)
{
int maximum = 0;
int newData[dataSize];
// Finde das Maximum in der Datenliste
for (int i = 0; i < dataSize; i++)
{
int d = data[i];
if (d > maximum)
{
maximum = d;
}
}
// Berechne neue Datenwerte zwischen 0 und 8 basierend auf dem Maximum
for (int i = 0; i < dataSize; i++)
{
int d = data[i];
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;
if (withIcon)
{
barWidth = ((32 - 9) / (dataSize)-1);
}
else
{
barWidth = (32 / (dataSize)-1);
}
// Berechne die Startposition des Graphen basierend auf dem Icon-Parameter
int startX = withIcon ? 9 : 0;
// Zeichne die Balken auf die Matrix
for (int i = 0; i < dataSize; i++)
{
int x1 = x + startX + (barWidth + 1) * i;
int barHeight = newData[i];
int y1 = min(8 - barHeight, 7);
matrix.fillRect(x1, y1 + y, barWidth, barHeight, color);
}
}