implement dashboard on wake

This commit is contained in:
2026-02-16 02:53:08 -08:00
parent e24d19eb94
commit 3e62c7d481
6 changed files with 202 additions and 96 deletions

View File

@@ -1,12 +1,17 @@
#include "DisplayManager.h"
#include "Config.h"
DisplayManager::DisplayManager()
: _dash(_tft)
{
}
void DisplayManager::begin() {
pinMode(PIN_LCD_BL, OUTPUT);
setBacklight(true);
_tft.init();
_tft.setRotation(1);
_tft.setRotation(1); // landscape: 480x320
_tft.fillScreen(COL_BLACK);
}
@@ -25,6 +30,11 @@ TouchEvent DisplayManager::readTouch() {
return evt;
}
int DisplayManager::dashboardTouch(uint16_t x, uint16_t y) {
if (_lastScreen != ScreenID::DASHBOARD) return -1;
return _dash.handleTouch(x, y);
}
void DisplayManager::render(const ScreenState& state) {
// Detect screen change → force full redraw
if (state.screen != _lastScreen) {
@@ -46,7 +56,6 @@ void DisplayManager::render(const ScreenState& state) {
if (_needsFullRedraw) drawWifiFailed();
break;
case ScreenID::ALERT:
// Alert redraws every blink cycle
if (_needsFullRedraw || state.blinkPhase != _lastBlink) {
drawAlertScreen(state);
_lastBlink = state.blinkPhase;
@@ -55,6 +64,9 @@ void DisplayManager::render(const ScreenState& state) {
case ScreenID::STATUS:
if (_needsFullRedraw) drawStatusScreen(state);
break;
case ScreenID::DASHBOARD:
drawDashboard(state);
break;
case ScreenID::OFF:
break;
}
@@ -62,6 +74,23 @@ void DisplayManager::render(const ScreenState& state) {
_needsFullRedraw = false;
}
// ----- Dashboard -----
void DisplayManager::drawDashboard(const ScreenState& s) {
if (_needsFullRedraw) {
if (!_dashSpriteReady) {
_dash.begin(); // create sprite (once)
_dashSpriteReady = true;
}
_dash.drawAll(); // fill screen + draw all tiles
_dash.refreshFromState(s); // update with real data
_lastDashRefresh = millis();
} else if (millis() - _lastDashRefresh > 2000) {
_lastDashRefresh = millis();
_dash.refreshFromState(s); // only redraws changed tiles
}
}
// ----- Helpers -----
void DisplayManager::drawCentered(const char* txt, int y, int sz, uint16_t col) {
@@ -122,12 +151,11 @@ void DisplayManager::drawWifiFailed() {
void DisplayManager::drawAlertScreen(const ScreenState& s) {
uint16_t bg = s.blinkPhase ? COL_NEON_TEAL : COL_HOT_FUCHSIA;
uint16_t fg = s.blinkPhase ? COL_BLACK : COL_WHITE;
uint16_t fg = s.blinkPhase ? COL_BLACK : COL_WHITE;
_tft.fillScreen(bg);
drawHeaderBar(fg, "ALERT", s.timeString);
// Scale text to fit 480px wide screen
int sz = 5;
int len = strlen(s.alertMessage);
if (len > 10) sz = 4;
@@ -135,7 +163,6 @@ void DisplayManager::drawAlertScreen(const ScreenState& s) {
if (len > 30) sz = 2;
if (len > 12) {
// Two-line split
String msg(s.alertMessage);
int mid = len / 2;
int sp = msg.lastIndexOf(' ', mid);
@@ -165,42 +192,41 @@ void DisplayManager::drawStatusScreen(const ScreenState& s) {
int x = 20;
snprintf(buf, sizeof(buf), "WiFi: %s (%ddBm)",
s.wifiConnected ? s.wifiSSID : "DOWN", s.wifiRSSI);
s.wifiConnected ? s.wifiSSID : "DOWN", s.wifiRSSI);
drawInfoLine(x, y, COL_WHITE, buf); y += sp;
snprintf(buf, sizeof(buf), "IP: %s",
s.wifiConnected ? s.wifiIP : "---");
snprintf(buf, sizeof(buf), "IP: %s",
s.wifiConnected ? s.wifiIP : "---");
drawInfoLine(x, y, COL_WHITE, buf); y += sp;
snprintf(buf, sizeof(buf), "Up: %lu min Heap: %lu KB",
s.uptimeMinutes, s.freeHeapKB);
snprintf(buf, sizeof(buf), "Up: %lu min Heap: %lu KB",
s.uptimeMinutes, s.freeHeapKB);
drawInfoLine(x, y, COL_WHITE, buf); y += sp;
snprintf(buf, sizeof(buf), "NTP: %s UTC",
s.ntpSynced ? s.timeString : "not synced");
snprintf(buf, sizeof(buf), "NTP: %s UTC",
s.ntpSynced ? s.timeString : "not synced");
drawInfoLine(x, y, COL_WHITE, buf); y += sp;
const char* stName = s.deviceState == DeviceState::SILENT ? "SILENT" :
s.deviceState == DeviceState::ALERTING ? "ALERTING" : "WAKE";
const char* stName = s.deviceState == DeviceState::SILENT ? "SILENT" :
s.deviceState == DeviceState::ALERTING ? "ALERTING" : "WAKE";
snprintf(buf, sizeof(buf), "State: %s Net: %s",
stName, s.networkOK ? "OK" : "FAIL");
stName, s.networkOK ? "OK" : "FAIL");
uint16_t stCol = s.deviceState == DeviceState::ALERTING ? COL_RED :
s.deviceState == DeviceState::SILENT ? COL_GREEN : COL_NEON_TEAL;
s.deviceState == DeviceState::SILENT ? COL_GREEN : COL_NEON_TEAL;
drawInfoLine(x, y, stCol, buf); y += sp;
// Recent alerts
if (s.alertHistoryCount > 0) {
drawInfoLine(x, y, COL_MINT, "Recent Alerts:"); y += sp;
for (int i = 0; i < s.alertHistoryCount; i++) {
uint16_t col = (i == 0) ? COL_YELLOW : COL_DARK_GRAY;
snprintf(buf, sizeof(buf), "%s %.35s",
s.alertHistory[i].timestamp,
s.alertHistory[i].message);
drawInfoLine(x, y, col, buf); y += sp;
if (s.alertHistoryCount > 0) {
drawInfoLine(x, y, COL_MINT, "Recent Alerts:"); y += sp;
for (int i = 0; i < s.alertHistoryCount; i++) {
uint16_t col = (i == 0) ? COL_YELLOW : COL_DARK_GRAY;
snprintf(buf, sizeof(buf), "%s %.35s",
s.alertHistory[i].timestamp,
s.alertHistory[i].message);
drawInfoLine(x, y, col, buf); y += sp;
}
} else {
drawInfoLine(x, y, COL_DARK_GRAY, "No alerts yet"); y += sp;
}
} else {
drawInfoLine(x, y, COL_DARK_GRAY, "No alerts yet"); y += sp;
}
if (s.debugMode) {
drawInfoLine(x, y, COL_YELLOW, "DEBUG MODE - _test topics");