Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
/Tools
.pio
.DS_Store
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
/Tools
src/Globals.cpp
1 change: 1 addition & 0 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- [Apps](apps.md)
- [Native Apps](apps.md#native-apps)
- [Custom Apps](apps.md#custom-apps)
- [Countdown](countdown.md)
- [Effects](effects.md)
- [Icons](icons.md)
- [Sounds](sounds.md)
Expand Down
14 changes: 9 additions & 5 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,21 +390,25 @@ You can adjust each property in the JSON object according to your preferences. I
| `CTEMP` | array of ints | Color temperature for the matrix. | RGB array | N/A |
| `TFORMAT` | string | Time format for the TimeApp. | Varies (see below) | N/A |
| `DFORMAT` | string | Date format for the DateApp. | Varies (see below) | N/A |
| `CDATE` | string | Target date for the Countdown app. The target day shows only the icon; past dates turn Countdown off. | `YYYY-MM-DD` | empty |
| `CICON` | string | Icon ID or filename for the Countdown app, using the existing `/ICONS` icon storage. | Icon name without extension | empty |
| `SOM` | boolean | Start the week on Monday. | `true`/`false` | true |
| `CEL` | boolean | Shows the temperature in Celsius (Fahrenheit when false). | `true`/`false` | true |
| `BLOCKN` | boolean | Block physical navigation keys (still sends input to MQTT). | `true`/`false` | false |
| `UPPERCASE` | boolean | Display text in uppercase. | `true`/`false` | true |
| `TIME_COL` | string/array of ints | Text color of the time app. Use 0 for global text color. | RGB array or hex color | N/A |
| `DATE_COL` | string/array of ints | Text color of the date app. Use 0 for global text color. | RGB array or hex color | N/A |
| `COUNT_COL` | string/array of ints | Text color of the countdown app. Use 0 for global text color. | RGB array or hex color | N/A |
| `TEMP_COL` | string/array of ints | Text color of the temperature app. Use 0 for global text color. | RGB array or hex color | N/A |
| `HUM_COL` | string/array of ints | Text color of the humidity app. Use 0 for global text color. | RGB array or hex color | N/A |
| `BAT_COL` | string/array of ints | Text color of the battery app. Use 0 for global text color. | RGB array or hex color | N/A |
| `SSPEED` | integer | Scroll speed modification. | Percentage of original scroll speed | 100 |
| `TIM` | boolean | Enable or disable the native time app (requires reboot). | `true`/`false` | true |
| `DAT` | boolean | Enable or disable the native date app (requires reboot). | `true`/`false` | true |
| `HUM` | boolean | Enable or disable the native humidity app (requires reboot). | `true`/`false` | true |
| `TEMP` | boolean | Enable or disable the native temperature app (requires reboot). | `true`/`false` | true |
| `BAT` | boolean | Enable or disable the native battery app (requires reboot). | `true`/`false` | true |
| `TIM` | boolean | Enable or disable the native time app. | `true`/`false` | true |
| `DAT` | boolean | Enable or disable the native date app. | `true`/`false` | true |
| `COUNT` | boolean | Enable or disable the native countdown app. | `true`/`false` | false |
| `HUM` | boolean | Enable or disable the native humidity app. | `true`/`false` | true |
| `TEMP` | boolean | Enable or disable the native temperature app. | `true`/`false` | true |
| `BAT` | boolean | Enable or disable the native battery app. | `true`/`false` | true |
| `MATP` | boolean | Enable or disable the matrix. Similar to `power` endpoint but without the animation. | `true`/`false` | true |
| `VOL` | integer | Allows to set the volume of the buzzer and DFplayer. | 0–30 | true |
| `OVERLAY` | string | Sets a global effect overlay (cannot be used with app specific overlays). | Varies (see below) | N/A |
Expand Down
21 changes: 19 additions & 2 deletions docs/apps.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,25 @@ The Dateapp shows the current date of course. There are several dateformats 'DFO
| `%d/%m` | `16/04` | Day/Month |
| `%m-%d-%y` | `04-16-22` | Month-Day-Year |

---
## Countdown

The Countdown app shows how many calendar days remain until a configured target date. Before the target date, the left side displays the target day of month together with a custom icon from the existing icon manager, and the right side displays the remaining day count. On the target date, only the configured icon is shown. After the target date has passed, Countdown automatically turns itself off.

Configure it through the Settings API:

```json
{
"COUNT": true,
"CDATE": "2026-06-01",
"CICON": "1234"
}
```

`CDATE` must use `YYYY-MM-DD`. `CICON` is the icon ID or filename without extension from the `/ICONS` folder. `COUNT_COL` can be used to set the countdown text color, or `0` to use the global text color.

See [Countdown](countdown.md) for HTTP and MQTT setup examples.

---
## Temperature

Expand Down Expand Up @@ -330,5 +349,3 @@ This Node-RED flow retrieves and displays the subscriber count of a specified Yo
To use this flow, replace the "XXX" in the "Data" node with your YouTube API key and ensure that the MQTT broker settings in the "MQTT out" node are correct.
The flow will then retrieve the subscriber count of the specified YouTube channel and display it on your AWTRIX device along with the icon.
This Flow uses icon 5029 from LM (Just download it from the awtrix webinterface). You can change the icon in the flow to your favorite one.


106 changes: 106 additions & 0 deletions docs/countdown.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Countdown App

The Countdown app is a native app that shows how many calendar days remain until a configured target date.

The display layout is:

- Left: target day of month and the configured icon.
- Right: remaining days.

On the target date, the app hides the target day and remaining-day count, and only shows the configured icon. After the target date has passed, the Countdown app turns itself off until a future target date is configured and the app is enabled again.

## Enable Countdown

Set `COUNT` to `true` through the Settings API.

HTTP example:

```bash
curl -X POST "http://[IP]/api/settings" \
-H "Content-Type: application/json" \
-d '{"COUNT":true,"CDATE":"2026-06-01","CICON":"1234"}'
```

MQTT example:

```text
Topic: [PREFIX]/settings
Payload: {"COUNT":true,"CDATE":"2026-06-01","CICON":"1234"}
```

Replace:

- `[IP]` with the AWTRIX IP address.
- `[PREFIX]` with the configured MQTT prefix.
- `2026-06-01` with your target date.
- `1234` with the icon ID or filename from the existing icon manager.

## Set The Initial Target Date

The target date is configured with `CDATE`.

```json
{
"CDATE": "2026-06-01"
}
```

`CDATE` must use `YYYY-MM-DD`.

The app counts full calendar days based on the device's local date:

- Today to tomorrow: `1`
- Today to today: only the configured icon is shown.
- Today to yesterday: Countdown automatically turns off.

## Set The Icon

The icon is configured with `CICON`.

```json
{
"CICON": "1234"
}
```

`CICON` uses the existing icon management system. Use the icon ID or filename without extension. The firmware looks for:

- `/ICONS/1234.jpg`
- `/ICONS/1234.gif`

If the icon is missing before the target date, the Countdown app still shows the date and remaining days. On the target date, a missing icon leaves the Countdown screen blank.

## Optional Text Color

Set `COUNT_COL` to customize the countdown text color.

```json
{
"COUNT_COL": "#00FF00"
}
```

Use `0` to fall back to the global text color.

## Disable Countdown

Set `COUNT` to `false`.

```bash
curl -X POST "http://[IP]/api/settings" \
-H "Content-Type: application/json" \
-d '{"COUNT":false}'
```

## Full Example

This enables Countdown, sets the initial target date, sets the icon, and sets the text color:

```json
{
"COUNT": true,
"CDATE": "2026-06-01",
"CICON": "1234",
"COUNT_COL": "#FFFFFF"
}
```
110 changes: 110 additions & 0 deletions src/Apps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "MQTTManager.h"
#include "Overlays.h"
#include "timer.h"
#include "CountdownUtils.h"

const uint8_t bigdigits_mask[12][7] = {
{132, 48, 48, 48, 48, 48, 132}, // 0
Expand Down Expand Up @@ -336,6 +337,115 @@ void DateApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x,
}
}

void CountdownApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, GifPlayer *gifPlayer)
{
if (notifyFlag)
return;
CURRENT_APP = "Countdown";
currentCustomApp = "";

CountdownDate target;
if (!parseCountdownDate(COUNTDOWN_TARGET.c_str(), target))
{
return;
}

struct tm *currentTime = timer_localtime();
if (currentTime == nullptr)
{
return;
}

long days = countdownDaysBetweenDates(
currentTime->tm_year + 1900,
currentTime->tm_mon + 1,
currentTime->tm_mday,
target.year,
target.month,
target.day);
CountdownDisplayState displayState = countdownDisplayState(days);

if (displayState == CountdownDisplayState::Expired)
{
SHOW_COUNTDOWN = false;
DisplayManager.loadNativeApps();
saveSettings();
return;
}

if (COUNTDOWN_COLOR > 0)
{
DisplayManager.setTextColor(COUNTDOWN_COLOR);
}
else
{
DisplayManager.getInstance().resetTextColor();
}

bool iconOnly = displayState == CountdownDisplayState::DueToday;
if (!iconOnly)
{
char targetDay[3];
snprintf(targetDay, sizeof(targetDay), "%d", target.day);

DisplayManager.drawFilledRect(x, y, 9, 8, CALENDAR_BODY_COLOR);
DisplayManager.drawFilledRect(x, y, 9, 2, CALENDAR_HEADER_COLOR);
DisplayManager.setTextColor(CALENDAR_TEXT_COLOR);
DisplayManager.setCursor((target.day < 10 ? 3 : 1) + x, 7 + y);
DisplayManager.matrixPrint(targetDay);
}

static File countdownIcon;
static String openedIconName;
static bool isGif = false;
static uint8_t currentFrame = 0;

if (COUNTDOWN_ICON != openedIconName)
{
countdownIcon.close();
openedIconName = COUNTDOWN_ICON;
currentFrame = 0;
isGif = false;

if (COUNTDOWN_ICON.length() > 0)
{
String jpgPath = "/ICONS/" + COUNTDOWN_ICON + ".jpg";
String gifPath = "/ICONS/" + COUNTDOWN_ICON + ".gif";
if (LittleFS.exists(jpgPath))
{
countdownIcon = LittleFS.open(jpgPath);
}
else if (LittleFS.exists(gifPath))
{
countdownIcon = LittleFS.open(gifPath);
isGif = true;
}
}
}

if (countdownIcon)
{
int16_t iconX = (iconOnly ? 12 : 10) + x;
if (isGif)
{
gifPlayer->playGif(iconX, y, &countdownIcon, currentFrame);
currentFrame = gifPlayer->getFrame();
}
else
{
DisplayManager.drawJPG(iconX, y, countdownIcon);
}
}

if (!iconOnly)
{
char remainingDays[8];
snprintf(remainingDays, sizeof(remainingDays), "%ld", days);
DisplayManager.setTextColor(COUNTDOWN_COLOR > 0 ? COUNTDOWN_COLOR : TEXTCOLOR_888);
DisplayManager.printText(20 + x, 6 + y, remainingDays, false, 2);
}
}

void TempApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, GifPlayer *gifPlayer)
{
if (notifyFlag)
Expand Down
4 changes: 3 additions & 1 deletion src/Apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ void TimeApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x,

void DateApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, GifPlayer *gifPlayer);

void CountdownApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, GifPlayer *gifPlayer);

void TempApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, GifPlayer *gifPlayer);

void HumApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, GifPlayer *gifPlayer);
Expand Down Expand Up @@ -108,4 +110,4 @@ void CApp17(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, i
void CApp18(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, GifPlayer *gifPlayer);
void CApp19(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, GifPlayer *gifPlayer);
void CApp20(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, GifPlayer *gifPlayer);
#endif
#endif
Loading