feat: add status screen with system info display

This commit is contained in:
2026-02-20 02:11:21 -08:00
parent fd04dea8dd
commit ba8789797c
7 changed files with 110 additions and 5 deletions

View File

@@ -138,6 +138,12 @@ void DisplayDriverTFT::render(const ScreenState& st) {
_needsRedraw = false;
}
break;
case ScreenID::STATUS:
if(_needsRedraw) {
drawStatus(st);
_needsRedraw = false;
}
break;
case ScreenID::OFF:
if(_needsRedraw) {
_tft.fillScreen(TFT_BLACK);
@@ -194,6 +200,22 @@ void DisplayDriverTFT::drawAlert(const ScreenState& st) {
_tft.fillScreen(bg);
_tft.setTextColor(TFT_WHITE, bg);
// Progressive fill hint - draws dark overlay from bottom rising up
if(_alertTouchDown) {
uint32_t touchElapsed = millis() - _alertTouchStartMs;
float progress = (float)touchElapsed / (float)ALERT_FILL_DURATION_MS;
if(progress > 1.0f)
progress = 1.0f;
int dispH = _tft.height();
int fillHeight = (int)(dispH * progress);
if(fillHeight > 0) {
// Draw dark overlay from bottom
uint16_t overlay = _tft.color565(80, 0, 0); // Dark red
_tft.fillRect(0, dispH - fillHeight, _tft.width(), fillHeight, overlay);
}
}
setTitleFont();
_tft.setCursor(10, 28); // y=28 baseline for ~18px font
_tft.print(st.alertTitle.length() > 0 ? st.alertTitle : "ALERT");
@@ -257,6 +279,61 @@ void DisplayDriverTFT::drawDashboard(const ScreenState& st) {
}
}
void DisplayDriverTFT::drawStatus(const ScreenState& st) {
int dispW = _tft.width();
int dispH = _tft.height();
_tft.fillScreen(TFT_BLACK);
// Header
_tft.fillRect(0, 0, dispW, STYLE_HEADER_HEIGHT, 0x1A1A);
_tft.setTextSize(1);
_tft.setTextColor(TFT_WHITE);
_tft.setCursor(5, 20);
_tft.print("STATUS");
// Back button in lower right
_tft.setCursor(dispW - 60, dispH - 20);
_tft.print("[BACK]");
// Status info
setBodyFont();
int y = STYLE_HEADER_HEIGHT + 20;
// WiFi
_tft.setCursor(10, y);
_tft.printf("WiFi: %s", st.wifiSsid.length() > 0 ? st.wifiSsid.c_str() : "N/A");
y += 20;
_tft.setCursor(10, y);
_tft.printf("RSSI: %d dBm", st.wifiRssi);
y += 20;
_tft.setCursor(10, y);
_tft.printf("IP: %s", st.ipAddr.length() > 0 ? st.ipAddr.c_str() : "N/A");
y += 30;
// Uptime
uint32_t upSec = st.uptimeMs / 1000;
uint32_t upMin = upSec / 60;
uint32_t upHr = upMin / 60;
upSec = upSec % 60;
upMin = upMin % 60;
_tft.setCursor(10, y);
_tft.printf("Uptime: %02lu:%02lu:%02lu", upHr, upMin, upSec);
y += 20;
// Heap
_tft.setCursor(10, y);
_tft.printf("Heap: %d bytes", ESP.getFreeHeap());
y += 20;
// Last poll
uint32_t pollAgo = (millis() - st.lastPollMs) / 1000;
_tft.setCursor(10, y);
_tft.printf("Last poll: %lu sec ago", pollAgo);
}
// ── Touch ───────────────────────────────────────────────────
TouchEvent DisplayDriverTFT::readTouch() {
@@ -317,6 +394,15 @@ TouchEvent DisplayDriverTFT::readTouch() {
// Track previous state for next call
_touchWasPressed = touched;
// Track alert touch for progressive hint
if(evt.pressed) {
_alertTouchDown = true;
_alertTouchStartMs = millis();
} else if(evt.released) {
_alertTouchDown = false;
}
return evt;
}

View File

@@ -31,6 +31,7 @@ private:
void drawBoot(const ScreenState& st);
void drawAlert(const ScreenState& st);
void drawDashboard(const ScreenState& st);
void drawStatus(const ScreenState& st);
TFT_eSPI _tft;
@@ -40,6 +41,11 @@ private:
BootStage _lastBootStage = BootStage::SPLASH;
bool _needsRedraw = true;
// Touch hint for alert - progressive fill from bottom
bool _alertTouchDown = false;
uint32_t _alertTouchStartMs = 0;
static constexpr uint32_t ALERT_FILL_DURATION_MS = 3000;
// Touch tracking for press/release detection
bool _touchWasPressed = false;
int _touchDownX = -1;

View File

@@ -125,11 +125,13 @@ install-libs-shared:
install: install-libs-shared
#!/usr/bin/env bash
./boards/{{BOARD}}/install.sh
arduino-cli core install esp32:esp32
# Clean build artifacts
clean:
#!/usr/bin/env bash
rm -rf vendor/
rm -rf .cache/
rm -rf boards/esp32-32e/build
rm -rf boards/esp32-32e-4/build
rm -rf boards/esp32-s3-lcd-43/build

View File

@@ -354,6 +354,18 @@ int DoorbellLogic::handleTouch(const TouchEvent& evt) {
return -1;
}
// Handle STATUS screen back button (lower right corner)
if(_state.screen == ScreenID::STATUS) {
int dispW = _display->width();
int dispH = _display->height();
// Back button area: lower right (dispW-60 to dispW, dispH-30 to dispH)
if(evt.x >= dispW - 60 && evt.y >= dispH - 30) {
Serial.printf("[%lu] [TOUCH] STATUS → DASHBOARD (back)\n", millis());
setScreen(ScreenID::DASHBOARD);
return -1;
}
}
// Draw debug crosshair at touch point
#ifdef DEBUG_MODE
if(_state.screen == ScreenID::DASHBOARD) {
@@ -380,7 +392,7 @@ int DoorbellLogic::handleTouch(const TouchEvent& evt) {
silenceAlert();
break;
case TileAction::STATUS:
heartbeat();
setScreen(ScreenID::STATUS);
break;
case TileAction::REBOOT:
flushStatus("REBOOT (tile)");

View File

@@ -3,7 +3,7 @@
enum class DeviceState { BOOTED, SILENT, ALERTING, SILENCED };
enum class ScreenID { BOOT, OFF, ALERT, DASHBOARD };
enum class ScreenID { BOOT, OFF, ALERT, DASHBOARD, STATUS };
enum class BootStage { SPLASH, INIT_DISPLAY, INIT_NETWORK, CONNECTING_WIFI, READY, DONE };
@@ -94,6 +94,8 @@ inline const char* screenIdStr(ScreenID s) {
return "ALERT";
case ScreenID::DASHBOARD:
return "DASHBOARD";
case ScreenID::STATUS:
return "STATUS";
}
return "?";
}

2
vendor/.gitignore vendored
View File

@@ -1,2 +0,0 @@
*
!.gitignore

Submodule vendor/esp32-s3-lcd-43/LovyanGFX deleted from 42998359d8