Skip to content

Commit

Permalink
v0.86
Browse files Browse the repository at this point in the history
### ✨ Features
- 🎵 Adds `/rtttl` API to play a rtttl melody string directly
- 🖥️ Adds HTTP fullscreen liveview at `/fullscreen`

### 🐛 Bug Fixes
- 🎨 Fixes Matrix color for HA entity. Closes #314
- 🌈 Fixes moodlight bug. Closes #311
- 📆 Fixes drawing coordinates for time calendar icon. Closes #312
- 🔡 Fixes a bug with the free pixel between icon and text
- 🟠 Fixes circle drawing
- 📝 Fixes a bug while using textOffset and pushIcon. Closes #305

### 🔥 Removals
- ❌ Removes reset after X failed WiFi reconnect attempts, because some users disables WiFi over night. Closes #310
  • Loading branch information
Blueforcer committed Sep 13, 2023
1 parent 5907bf9 commit d76c8a7
Show file tree
Hide file tree
Showing 12 changed files with 91 additions and 89 deletions.
10 changes: 9 additions & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ Retrieve the current matrix screen as an array of 24bit colors:
When triggering the MQTT API, AWTRIX sends the array to `[PREFIX]/screen`.

**Extras:**
- Access a live view of the screen in your browser: `http://[IP]/screen`.
- Access a live view of the screen in your browser: `http://[IP]/screen`.
- Options to download a screenshot or generate a GIF from the current display content.
- `http://[IP]/fullscreen` gives you a fullscreen liveview. Here you can optionally set the `fps` as parameter (standard 30)

## Power Control

Expand All @@ -48,6 +49,13 @@ Play a RTTTL sound from the MELODIES folder:
| ----------------- | ---------------------------- | ------------------- | ----------- |
| `[PREFIX]/sound` | `http://[IP]/api/sound` | `{"sound":"alarm"}` | POST |

Play a RTTTL sound from a given RTTTL string:

| MQTT Topic | HTTP URL | Payload/Body | HTTP Method |
| ----------------- | ---------------------------- | ------------------- | ----------- |
| `[PREFIX]/rtttl` | `http://[IP]/api/rtttl` | `rttl string` | POST |


## Mood Lighting

Set the entire matrix to a custom color or temperature:
Expand Down
15 changes: 0 additions & 15 deletions lib/webserver/esp-fs-webserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,12 @@ void FSWebServer::run()
m_dnsServer.processNextRequest();

unsigned long currentMillis = millis();
// if WiFi is down, try reconnecting
if ((WiFi.status() != WL_CONNECTED) && (currentMillis - previousMillis >= interval) && !m_apmode)
{
Serial.println("Reconnecting to WiFi...");
WiFi.disconnect();
WiFi.reconnect();
previousMillis = currentMillis;
if (WiFi.status() != WL_CONNECTED)
{
failedAttempts++;
if (failedAttempts >= 60)
{
Serial.println("60 failed attempts to connect. Restarting ESP...");
ESP.restart();
}
}
else
{
Serial.println("Reconnected!");
failedAttempts = 0;
}
}
}

Expand Down
26 changes: 12 additions & 14 deletions src/Apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ String WEATHER_HUM;

struct CustomApp
{
bool hasCustomColor = false;
uint32_t currentFrame = 0;
String iconName;
String iconFile;
Expand All @@ -37,7 +38,6 @@ struct CustomApp
uint32_t color;
File icon;
bool isGif;
bool iconSearched = false;
bool rainbow;
bool center;
int fade = 0;
Expand Down Expand Up @@ -222,23 +222,23 @@ void TimeApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x,
strftime(t, sizeof(t), timeformat, localtime(&now));
}

uint8_t wdPosY;
uint8_t timePosY;
int16_t wdPosY;
int16_t timePosY;

if (TIME_MODE == 1 || TIME_MODE == 2)
{
wdPosY = TIME_MODE == 1 ? 7 : 0;
timePosY = TIME_MODE == 1 ? 6 : 7;
DisplayManager.printText(12 + x, timePosY + y, t, false, 2);
DisplayManager.drawFilledRect(0 + x, 0 + y, 9 + x, 2 + y, CALENDAR_HEADER_COLOR);
DisplayManager.drawFilledRect(0 + x, 2 + y, 9 + x, 7 + y, CALENDAR_BODY_COLOR);
DisplayManager.drawFilledRect(x, y, 9, 8, CALENDAR_BODY_COLOR);
DisplayManager.drawFilledRect(0 + x, 0 + y, 9, 2, CALENDAR_HEADER_COLOR);
}
else if (TIME_MODE == 3 || TIME_MODE == 4)
{
wdPosY = TIME_MODE == 3 ? 7 : 0;
timePosY = TIME_MODE == 3 ? 6 : 7;
DisplayManager.printText(12 + x, timePosY + y, t, false, 2);
DisplayManager.drawFilledRect(0 + x, 0 + y, 9 + x, 8 + y, CALENDAR_BODY_COLOR);
DisplayManager.drawFilledRect(0 + x, 0 + y, 9, 8, CALENDAR_BODY_COLOR);
DisplayManager.drawLine(1, 0, 2, 0, 0x000000);
DisplayManager.drawLine(6, 0, 7, 0, 0x000000);
}
Expand All @@ -263,8 +263,8 @@ void TimeApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x,
DisplayManager.setCursor(1 + x, 7 + y);
}
DisplayManager.matrixPrint(day_str);
uint8_t wdPosY = TIME_MODE > 0 ? 0 : 8;
uint8_t timePosY = TIME_MODE > 0 ? 6 : 0;
int16_t wdPosY = TIME_MODE > 0 ? 0 : 8;
int16_t timePosY = TIME_MODE > 0 ? 6 : 0;
}

if (!SHOW_WEEKDAY)
Expand Down Expand Up @@ -507,7 +507,6 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState
{
ca->isGif = isGifFlags[i];
ca->icon = LittleFS.open(filePath);
ca->currentFrame=0;
break; // Exit loop if icon was found
}
}
Expand Down Expand Up @@ -557,7 +556,7 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState
}
if (ca->isGif)
{
iconWidth = gifPlayer->playGif(x + ca->iconPosition + ca->iconOffset, y, &ca->icon,ca->currentFrame);
iconWidth = gifPlayer->playGif(x + ca->iconPosition + ca->iconOffset, y, &ca->icon, ca->currentFrame);
ca->currentFrame = gifPlayer->getFrame();
}
else
Expand Down Expand Up @@ -608,9 +607,8 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState

if (textWidth > availableWidth && !(state->appState == IN_TRANSITION))
{
if (ca->scrollposition <= (-textWidth - ca->textOffset))
if (ca->scrollposition + ca->textOffset <= (-textWidth))
{

if (ca->iconWasPushed && ca->pushIcon == 2)
{
ca->iconWasPushed = false;
Expand All @@ -634,7 +632,7 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState
}
if (!noScrolling)
{
if ((ca->scrollDelay > MATRIX_FPS * 1.2) || ((hasIcon ? ca->textOffset + 9 : ca->textOffset) > 31))
if ((ca->scrollDelay > MATRIX_FPS ) || ((hasIcon ? ca->textOffset + 9 : ca->textOffset) > 31))
{
if (state->appState == FIXED && !ca->noScrolling)
{
Expand Down Expand Up @@ -898,7 +896,7 @@ void NotifyOverlay(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPl
}

// Check if text needs to be scrolled
if (textWidth > availableWidth && notifications[0].scrollposition <= -textWidth)
if (textWidth > availableWidth && notifications[0].scrollposition + notifications[0].textOffset <= (-textWidth))
{
// Reset scroll position and icon position if needed
notifications[0].scrollDelay = 0;
Expand Down
63 changes: 35 additions & 28 deletions src/DisplayManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ bool parseFragmentsText(const JsonArray &fragmentArray, std::vector<uint32_t> &c

for (JsonObject fragmentObj : fragmentArray)
{
String textFragment = utf8ascii(fragmentObj["t"].as<String>());
String textFragment = fragmentObj["t"];
uint32_t color;
if (fragmentObj.containsKey("c"))
{
Expand All @@ -398,7 +398,7 @@ bool parseFragmentsText(const JsonArray &fragmentArray, std::vector<uint32_t> &c
color = standardColor;
}

fragments.push_back(textFragment);
fragments.push_back(utf8ascii(textFragment));
colors.push_back(color);
}
return true;
Expand Down Expand Up @@ -610,16 +610,14 @@ bool DisplayManager_::generateCustomPage(const String &name, JsonObject doc, boo
{
customApp.iconName = newIconName;
customApp.icon.close();
customApp.currentFrame = 0;
customApp.iconSearched = false;
customApp.iconPosition = 0;
}
}
else
{
customApp.icon.close();
customApp.currentFrame = 0;
customApp.iconSearched = false;
customApp.iconName = "";
customApp.iconPosition = 0;
}

customApp.gradient[0] = -1;
Expand All @@ -640,11 +638,13 @@ bool DisplayManager_::generateCustomPage(const String &name, JsonObject doc, boo

if (doc.containsKey("color"))
{
customApp.hasCustomColor = true;
auto color = doc["color"];
customApp.color = getColorFromJsonVariant(color, TEXTCOLOR_888);
}
else
{
customApp.hasCustomColor = false;
customApp.color = TEXTCOLOR_888;
}

Expand All @@ -656,7 +656,8 @@ bool DisplayManager_::generateCustomPage(const String &name, JsonObject doc, boo
}
else if (doc.containsKey("text") && doc["text"].is<String>())
{
customApp.text = utf8ascii(doc["text"].as<String>());
String text = doc["text"];
customApp.text = utf8ascii(text);
}
else
{
Expand Down Expand Up @@ -858,7 +859,8 @@ bool DisplayManager_::generateNotification(uint8_t source, const char *json)
}
else if (doc["text"].is<String>())
{
newNotification.text = utf8ascii(doc["text"].as<String>());
String text = doc["text"];
newNotification.text = utf8ascii(text);
}
else
{
Expand Down Expand Up @@ -1072,7 +1074,6 @@ void ResetCustomApps()
app.iconPosition = 0;
app.scrollDelay = 0;
app.currentRepeat = 0;
app.iconSearched = false;
app.icon.close();
app.currentFrame = 0;
}
Expand All @@ -1081,7 +1082,6 @@ void ResetCustomApps()

void checkLifetime(uint8_t pos)
{

if (customApps.empty())
{
return;
Expand Down Expand Up @@ -2036,14 +2036,7 @@ void DisplayManager_::setNewSettings(const char *json)
{
auto TCOL = doc["TCOL"];
uint32_t TempColor = getColorFromJsonVariant(TCOL, 0xFFFFFF);
for (auto it = customApps.begin(); it != customApps.end(); ++it)
{
CustomApp &app = it->second;
if (app.color == TEXTCOLOR_888)
{
app.color = TempColor;
}
}
setCustomAppColors(TempColor);
TEXTCOLOR_888 = TempColor;
}

Expand Down Expand Up @@ -2079,6 +2072,18 @@ void DisplayManager_::setNewSettings(const char *json)
DEBUG_PRINTLN("Settings loaded");
}

void DisplayManager_::setCustomAppColors(uint32_t color)
{
for (auto it = customApps.begin(); it != customApps.end(); ++it)
{
CustomApp &app = it->second;
if (!app.hasCustomColor)
{
app.color = color;
}
}
}

String DisplayManager_::ledsAsJson()
{
StaticJsonDocument<JSON_ARRAY_SIZE(MATRIX_WIDTH * MATRIX_HEIGHT)> jsonDoc;
Expand Down Expand Up @@ -2191,7 +2196,7 @@ void DisplayManager_::processDrawInstructions(int16_t xOffset, int16_t yOffset,
int y1 = params[3].as<int>();
auto color2 = params[4];
uint32_t color = getColorFromJsonVariant(color2, TEXTCOLOR_888);
DisplayManager.drawLine(x0 + xOffset, y0 + yOffset, x1 + xOffset, y1 + yOffset, color);
drawLine(x0 + xOffset, y0 + yOffset, x1 + xOffset, y1 + yOffset, color);
}
else if (command == "dr")
{
Expand All @@ -2201,7 +2206,7 @@ void DisplayManager_::processDrawInstructions(int16_t xOffset, int16_t yOffset,
int h = params[3].as<int>();
auto color3 = params[4];
uint32_t color = getColorFromJsonVariant(color3, TEXTCOLOR_888);
DisplayManager.drawRect(x + xOffset, y + yOffset, w, h, color);
drawRect(x + xOffset, y + yOffset, w, h, color);
}
else if (command == "df")
{
Expand All @@ -2211,7 +2216,7 @@ void DisplayManager_::processDrawInstructions(int16_t xOffset, int16_t yOffset,
int h = params[3].as<int>();
auto color4 = params[4];
uint32_t color = getColorFromJsonVariant(color4, TEXTCOLOR_888);
DisplayManager.drawFilledRect(x + xOffset, y + yOffset, w, h, color);
drawFilledRect(x + xOffset, y + yOffset, w, h, color);
}
else if (command == "dc")
{
Expand All @@ -2220,7 +2225,7 @@ void DisplayManager_::processDrawInstructions(int16_t xOffset, int16_t yOffset,
int r = params[2].as<int>();
auto color5 = params[3];
uint32_t color = getColorFromJsonVariant(color5, TEXTCOLOR_888);
matrix->drawCircle(x + xOffset, y + yOffset, r, color);
drawCircle(x + xOffset, y + yOffset, r, color);
}
else if (command == "dfc")
{
Expand All @@ -2229,7 +2234,7 @@ void DisplayManager_::processDrawInstructions(int16_t xOffset, int16_t yOffset,
double r = params[2].as<double>();
auto color6 = params[3];
uint32_t color = getColorFromJsonVariant(color6, TEXTCOLOR_888);
matrix->fillCircle(x + xOffset, y + yOffset, r, color);
fillCircle(x + xOffset, y + yOffset, r, color);
}
else if (command == "dt")
{
Expand Down Expand Up @@ -2301,7 +2306,7 @@ bool DisplayManager_::moodlight(const char *json)
{
auto c = doc["color"];
uint32_t color888 = getColorFromJsonVariant(c, TEXTCOLOR_888);
matrix->fillScreen(color888);
drawFilledRect(0, 0, 32, 8, color888);
}
else
{
Expand Down Expand Up @@ -2367,14 +2372,16 @@ void DisplayManager_::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint3
}
}

void DisplayManager_::drawFastVLine(int16_t x, int16_t y, int16_t h, uint32_t color)
{
drawLine(x, y, x, y + h - 1, color);
}

void DisplayManager_::drawFilledRect(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color)
{
for (int16_t i = x; i < x + w; i++)
{
for (int16_t j = y; j < y + h; j++)
{
matrix->drawPixel(i, j, color);
}
drawFastVLine(i, y, h, color);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/DisplayManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class DisplayManager_
void drawRGBBitmap(int16_t x, int16_t y, uint32_t *bitmap, int16_t w, int16_t h);
void drawCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color);
void fillCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color);
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint32_t color);
void matrixPrint(const char *str);
void matrixPrint(char c);
void matrixPrint(String str);
Expand All @@ -96,6 +97,7 @@ class DisplayManager_
void setCursor(int16_t x, int16_t y);
void setTextColor(uint32_t color);
void matrixPrint(double number, uint8_t digits);
void setCustomAppColors(uint32_t color);
};

extern DisplayManager_ &DisplayManager;
Expand Down
Loading

0 comments on commit d76c8a7

Please sign in to comment.