Skip to content

Commit

Permalink
V0.80
Browse files Browse the repository at this point in the history
- Changes the way how Icons are loaded, this results in a massive improvemnet of the RAM usage. e.g.: Before: 13 CustomApps = 60kb RAM left. Now 132kb with 20 Apps!
- Enables multiple customapps via array again, wich doesnt cosumes any further RAM now. Sorry to all who had converted this first :)
  • Loading branch information
Blueforcer committed Aug 22, 2023
1 parent f5ed86f commit cae03a5
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 85 deletions.
17 changes: 17 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,23 @@ Simply send an array of your fragments, containing `"t"` as your textfragment an
}
```

### Send multiple custompage at once
This allows you to send multiple custompage at once. Instead of a single custompage object, you can send an array of objects. like

**Topic:**
/custom/test

```json
`[{"text":"1"},{"text":"2"}]`
```
Internally the appname gets a suffix like test0, test1 and so on.
You can update each app like before, or you can update all apps at once.
While removing apps, awtrix doesnt search for the exact name, but uses the app that starts with the given name.
So if you want to delete all apps just send empty payload to /custom/test. This will remove test0, test1 and so on.
you can also remove one app by removing /custom/test1.
Please keep in mind that if you delete only one app, you cant get the correct Order again because all apps in the loop move, since there can be no placeholder. ^


## Delete a custom app
To delete a custom app simply send a empty payload/body to the same topic/url.

Expand Down
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ lib_deps =
adafruit/Adafruit SHT31 Library@^2.2.0
bblanchon/ArduinoJson@^6.20.0
evert-arias/EasyButton@2.0.1
fastled/FastLED@^3.5.0
fastled/FastLED@^3.6.0
marcmerlin/FastLED NeoMatrix@^1.2
knolleary/PubSubClient@^2.8

Expand Down
29 changes: 21 additions & 8 deletions src/Apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@
#include "LittleFS.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <Ticker.h>
#include <ArduinoJson.h>

#include "effects.h"
Ticker downloader;


tm timeInfo;
uint16_t nativeAppsCount;
Expand All @@ -29,6 +27,7 @@ String WEATHER_HUM;

struct CustomApp
{
String iconName;
String drawInstructions;
float scrollposition = 0;
int16_t scrollDelay = 0;
Expand Down Expand Up @@ -422,9 +421,24 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState
CURRENT_APP = ca->name;
currentCustomApp = name;

bool hasIcon = ca->icon;
if (!ca->icon && ca->iconName.length() > 0)
{
const char* extensions[] = { ".jpg", ".gif" };
bool isGifFlags[] = { false, true };

for (int i = 0; i < 2; i++)
{
String filePath = "/ICONS/" + ca->iconName + extensions[i];
if (LittleFS.exists(filePath))
{
ca->isGif = isGifFlags[i];
ca->icon = LittleFS.open(filePath);
break; // Exit loop if icon was found
}
}
}

// matrix->fillRect(x, y, 32, 8, ca->background);
bool hasIcon = ca->icon;

// Calculate text and available width
uint16_t textWidth = 0;
Expand Down Expand Up @@ -527,7 +541,6 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState
ca->scrollposition = 9 + ca->textOffset;
}
}

if (!noScrolling)
{
if ((ca->scrollDelay > MATRIX_FPS * 1.2) || ((hasIcon ? ca->textOffset + 9 : ca->textOffset) > 31))
Expand Down Expand Up @@ -665,7 +678,7 @@ void NotifyApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer
}

// Set current app name
CURRENT_APP = "Notification";
CURRENT_APP = F("Notification");

if (notifications[0].wakeup && MATRIX_OFF)
{
Expand All @@ -676,7 +689,7 @@ void NotifyApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer
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
DEBUG_PRINTLN("Notification deleted");
DEBUG_PRINTLN(F("Notification deleted"));
PeripheryManager.stopSound();
if (notifications.size() >= 2)
{
Expand Down
92 changes: 40 additions & 52 deletions src/DisplayManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include "GifPlayer.h"
#include <ArtnetWifi.h>


unsigned long lastArtnetStatusTime = 0;
const int numberOfChannels = 256 * 3;
// Artnet settings
Expand Down Expand Up @@ -82,7 +81,6 @@ void DisplayManager_::setBrightness(int bri)
}
}


void DisplayManager_::setTextColor(uint16_t color)
{
matrix->setTextColor(color);
Expand Down Expand Up @@ -247,7 +245,7 @@ void pushCustomApp(String name, int position)
if (availableCallbackIndex == -1)
{
if (DEBUG_MODE)
DEBUG_PRINTLN("Error adding custom app -> Maximum number of custom apps reached");
DEBUG_PRINTLN(F("Error adding custom app -> Maximum number of custom apps reached"));
return;
}

Expand Down Expand Up @@ -358,25 +356,45 @@ bool parseFragmentsText(const JsonArray &fragmentArray, std::vector<uint16_t> &c
return true;
}

bool DisplayManager_::generateCustomPage(const String &name, const char *json, bool preventSave)
bool DisplayManager_::parseCustomPage(const String &name, const char *json, bool preventSave)
{
if ((strcmp(json, "") == 0) || (strcmp(json, "{}") == 0))
{
removeCustomAppFromApps(name, true);
return true;
}
DynamicJsonDocument doc(6144);

DynamicJsonDocument doc(8192);
DeserializationError error = deserializeJson(doc, json);
if (error)
{
if (DEBUG_MODE)
DEBUG_PRINTLN("PARSING FAILED");
if (DEBUG_MODE)
DEBUG_PRINTLN(error.c_str());
DEBUG_PRINTLN(error.c_str());
doc.clear();
return false;
}

if (doc.is<JsonObject>())
{
JsonObject rootObj = doc.as<JsonObject>();
return generateCustomPage(name, rootObj, preventSave);
}
else if (doc.is<JsonArray>())
{
JsonArray customPagesArray = doc.as<JsonArray>();
int cpIndex = 0;
for (JsonObject customPageObject : customPagesArray)
{
generateCustomPage(name + String(cpIndex), customPageObject, preventSave);
++cpIndex;
}
}

doc.clear();
return true;
}

bool DisplayManager_::generateCustomPage(const String &name, JsonObject doc, bool preventSave)
{
CustomApp customApp;

if (customApps.find(name) != customApps.end())
Expand All @@ -397,21 +415,17 @@ bool DisplayManager_::generateCustomPage(const String &name, const char *json, b
bool saveApp = doc["save"].as<bool>();
if (saveApp)
{
// Create the file name based on the app name
String fileName = "/CUSTOMAPPS/" + name + ".json";

// Create the directory if it doesn't exist
if (!LittleFS.exists("/CUSTOMAPPS"))
{
LittleFS.mkdir("/CUSTOMAPPS");
}

// Open the file for writing (this will overwrite the file if it already exists)
File file = LittleFS.open(fileName, "w");
File file = LittleFS.open("/CUSTOMAPPS/" + name + ".json", "w");
if (!file)
{
if (DEBUG_MODE)
DEBUG_PRINTLN("Failed to open file for writing: " + fileName);

return false;
}

Expand Down Expand Up @@ -514,6 +528,7 @@ bool DisplayManager_::generateCustomPage(const String &name, const char *json, b
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.iconName = doc.containsKey("icon") ? doc["icon"].as<String>() : "";
customApp.textCase = doc.containsKey("textCase") ? doc["textCase"] : 0;
customApp.lifetime = doc.containsKey("lifetime") ? doc["lifetime"] : 0;
customApp.iconOffset = doc.containsKey("iconOffset") ? doc["iconOffset"] : 0;
Expand Down Expand Up @@ -562,40 +577,6 @@ bool DisplayManager_::generateCustomPage(const String &name, const char *json, b
customApp.repeat = -1;
}

if (doc.containsKey("icon"))
{
String iconFileName = String(doc["icon"].as<String>());
if (customApp.icon && String(customApp.icon.name()).startsWith(iconFileName))
{
}
else
{
if (customApp.icon)
{
customApp.icon.close();
}
if (LittleFS.exists("/ICONS/" + iconFileName + ".jpg"))
{
customApp.isGif = false;
customApp.icon = LittleFS.open("/ICONS/" + iconFileName + ".jpg");
}
else if (LittleFS.exists("/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;
}
doc.clear();
pushCustomApp(name, pos - 1);
customApps[name] = customApp;
Expand Down Expand Up @@ -873,7 +854,7 @@ void DisplayManager_::loadCustomApps()
file.close();

String name = fileName.substring(fileName.lastIndexOf('/') + 1, fileName.lastIndexOf('.')); // remove path and .json extension
generateCustomPage(name, json.c_str(), true);
parseCustomPage(name, json.c_str(), true);

file = root.openNextFile();
}
Expand Down Expand Up @@ -970,6 +951,7 @@ void ResetCustomApps()
app.scrollposition = (app.icon ? 9 : 0) + app.textOffset;
app.iconPosition = 0;
app.scrollDelay = 0;
app.icon.close();
}
}
}
Expand Down Expand Up @@ -1181,9 +1163,14 @@ bool DisplayManager_::switchToApp(const char *json)
DynamicJsonDocument doc(512);
DeserializationError error = deserializeJson(doc, json);
if (error)
{
doc.clear();
return false;
}

String name = doc["name"].as<String>();
bool fast = doc["fast"] | false;
doc.clear();
int index = findAppIndexByName(name);
if (index > -1)
{
Expand Down Expand Up @@ -1646,7 +1633,6 @@ bool DisplayManager_::indicatorParser(uint8_t indicator, const char *json)
}
}


if (doc.containsKey("fade"))
{
switch (indicator)
Expand Down Expand Up @@ -1681,6 +1667,7 @@ bool DisplayManager_::indicatorParser(uint8_t indicator, const char *json)
break;
}
}
doc.clear();
MQTTManager.setIndicatorState(indicator, ui->indicator1State, ui->indicator1Color);
return true;
}
Expand Down Expand Up @@ -2159,11 +2146,12 @@ bool DisplayManager_::moodlight(const char *json)
}
else
{
doc.clear();
return true;
}

MOODLIGHT_MODE = true;

doc.clear();
matrix->show();
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions src/DisplayManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class DisplayManager_
void setBrightness(int);
void setTextColor(uint16_t color);
bool generateNotification(uint8_t source, const char *json);
bool generateCustomPage(const String &name, const char *json, bool preventSave);
bool generateCustomPage(const String &name, JsonObject doc, bool preventSave);
void printText(int16_t x, int16_t y, const char *text, bool centered, byte textCase);
bool setAutoTransition(bool active);
bool switchToApp(const char *json);
Expand Down Expand Up @@ -93,7 +93,7 @@ class DisplayManager_
String ledsAsJson();
String getAppsWithIcon();
void startArtnet();
bool parseCustomPage(const String &name, const char *json);
bool parseCustomPage(const String &name, const char *json, bool preventSave);
bool moodlight(const char *json);
int *getLedColors();
void sendBMP(Stream &stream);
Expand Down
13 changes: 3 additions & 10 deletions src/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,6 @@ void loadDevSettings()
STATS_INTERVAL = doc["stats_interval"].as<long>();
}

if (doc.containsKey("uppercase"))
{
UPPERCASE_LETTERS = doc["uppercase"].as<bool>();
}

if (doc.containsKey("update_check"))
{
Expand All @@ -129,11 +125,6 @@ void loadDevSettings()
DEBUG_MODE = doc["debug_mode"].as<bool>();
}

if (doc.containsKey("gamma"))
{
GAMMA = doc["gamma"].as<float>();
}

if (doc.containsKey("color_correction"))
{
auto correction = doc["color_correction"];
Expand Down Expand Up @@ -180,6 +171,7 @@ void loadSettings()
Settings.begin("awtrix", false);
BRIGHTNESS = Settings.getUInt("BRI", 120);
AUTO_BRIGHTNESS = Settings.getBool("ABRI", false);
UPPERCASE_LETTERS = Settings.getBool("UPPER", true);
TEXTCOLOR_565 = Settings.getUInt("TCOL", 0xFFFF);
CALENDAR_COLOR = Settings.getUInt("CCOL", 0xF800);
CALENDAR_TEXT_COLOR = Settings.getUInt("CTCOL", 0x0000);
Expand Down Expand Up @@ -235,6 +227,7 @@ void saveSettings()
Settings.putBool("ABRI", AUTO_BRIGHTNESS);
Settings.putBool("BLOCKN", BLOCK_NAVIGATION);
Settings.putBool("ATRANS", AUTO_TRANSITION);
Settings.putUInt("UPPER", UPPERCASE_LETTERS);
Settings.putUInt("TCOL", TEXTCOLOR_565);
Settings.putUInt("TMODE", TIME_MODE);
Settings.putUInt("TIME_COL", TIME_COLOR);
Expand Down Expand Up @@ -273,7 +266,7 @@ IPAddress gateway;
IPAddress subnet;
IPAddress primaryDNS;
IPAddress secondaryDNS;
const char *VERSION = "0.79";
const char *VERSION = "0.80";

String MQTT_HOST = "";
uint16_t MQTT_PORT = 1883;
Expand Down
2 changes: 1 addition & 1 deletion src/MQTTManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ void onMqttMessage(const char *topic, const uint8_t *payload, uint16_t length)
if (topic_str.startsWith(prefix))
{
topic_str = topic_str.substring(prefix.length());
DisplayManager.generateCustomPage(topic_str, payloadCopy,false);
DisplayManager.parseCustomPage(topic_str, payloadCopy, false);
}

delete[] payloadCopy;
Expand Down
Loading

0 comments on commit cae03a5

Please sign in to comment.