diff --git a/src/graphics/TimeFormatters.cpp b/src/graphics/TimeFormatters.cpp index 47036078b..0a1c23341 100644 --- a/src/graphics/TimeFormatters.cpp +++ b/src/graphics/TimeFormatters.cpp @@ -101,3 +101,23 @@ void getTimeAgoStr(uint32_t agoSecs, char *timeStr, uint8_t maxLength) else snprintf(timeStr, maxLength, "unknown age"); } + +void getUptimeStr(uint32_t uptimeMillis, const char *prefix, char *uptimeStr, uint8_t maxLength, bool includeSecs) +{ + uint32_t days = uptimeMillis / 86400000; + uint32_t hours = (uptimeMillis % 86400000) / 3600000; + uint32_t mins = (uptimeMillis % 3600000) / 60000; + uint32_t secs = (uptimeMillis % 60000) / 1000; + + if (days) { + snprintf(uptimeStr, maxLength, "%s: %ud %uh", prefix, days, hours); + } else if (hours) { + snprintf(uptimeStr, maxLength, "%s: %uh %um", prefix, hours, mins); + } else if (!includeSecs) { + snprintf(uptimeStr, maxLength, "%s: %um", prefix, mins); + } else if (mins) { + snprintf(uptimeStr, maxLength, "%s: %um %us", prefix, mins, secs); + } else { + snprintf(uptimeStr, maxLength, "%s: %us", prefix, secs); + } +} diff --git a/src/graphics/TimeFormatters.h b/src/graphics/TimeFormatters.h index b3d8413a2..f86c6725c 100644 --- a/src/graphics/TimeFormatters.h +++ b/src/graphics/TimeFormatters.h @@ -24,3 +24,10 @@ bool deltaToTimestamp(uint32_t secondsAgo, uint8_t *hours, uint8_t *minutes, int * @param maxLength Maximum length of the resulting string buffer */ void getTimeAgoStr(uint32_t agoSecs, char *timeStr, uint8_t maxLength); + +/** + * Get a compact human-readable string that only shows the largest non-zero time components. + * For example, 0 days 1 hour 2 minutes will display as "1h 2m" but 1 day 2 hours 3 minutes + * will display as "1d 2h". + */ +void getUptimeStr(uint32_t uptimeMillis, const char *prefix, char *uptimeStr, uint8_t maxLength, bool includeSecs = false); diff --git a/src/graphics/draw/DebugRenderer.cpp b/src/graphics/draw/DebugRenderer.cpp index d098fa304..79c1e7e61 100644 --- a/src/graphics/draw/DebugRenderer.cpp +++ b/src/graphics/draw/DebugRenderer.cpp @@ -11,6 +11,7 @@ #include "gps/RTC.h" #include "graphics/ScreenFonts.h" #include "graphics/SharedUIDisplay.h" +#include "graphics/TimeFormatters.h" #include "graphics/images.h" #include "main.h" #include "mesh/Channels.h" @@ -650,17 +651,7 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x if (SCREEN_HEIGHT > 64 || (SCREEN_HEIGHT <= 64 && line <= 5)) { // Only show uptime if the screen can show it char uptimeStr[32] = ""; - uint32_t uptime = millis() / 1000; - uint32_t days = uptime / 86400; - uint32_t hours = (uptime % 86400) / 3600; - uint32_t mins = (uptime % 3600) / 60; - // Show as "Up: 2d 3h", "Up: 5h 14m", or "Up: 37m" - if (days) - snprintf(uptimeStr, sizeof(uptimeStr), " Up: %ud %uh", days, hours); - else if (hours) - snprintf(uptimeStr, sizeof(uptimeStr), " Up: %uh %um", hours, mins); - else - snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %um", mins); + getUptimeStr(millis(), "Up", uptimeStr, sizeof(uptimeStr)); textWidth = display->getStringWidth(uptimeStr); nameX = (SCREEN_WIDTH - textWidth) / 2; display->drawString(nameX, getTextPositions(display)[line++], uptimeStr); @@ -729,4 +720,4 @@ void drawChirpy(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int1 } // namespace DebugRenderer } // namespace graphics -#endif \ No newline at end of file +#endif diff --git a/src/graphics/draw/UIRenderer.cpp b/src/graphics/draw/UIRenderer.cpp index 538c32842..c50fe5cf1 100644 --- a/src/graphics/draw/UIRenderer.cpp +++ b/src/graphics/draw/UIRenderer.cpp @@ -11,6 +11,7 @@ #include "graphics/Screen.h" #include "graphics/ScreenFonts.h" #include "graphics/SharedUIDisplay.h" +#include "graphics/TimeFormatters.h" #include "graphics/images.h" #include "main.h" #include "target_specific.h" @@ -383,17 +384,7 @@ void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *st // === 4. Uptime (only show if metric is present) === char uptimeStr[32] = ""; if (node->has_device_metrics && node->device_metrics.has_uptime_seconds) { - uint32_t uptime = node->device_metrics.uptime_seconds; - uint32_t days = uptime / 86400; - uint32_t hours = (uptime % 86400) / 3600; - uint32_t mins = (uptime % 3600) / 60; - // Show as "Up: 2d 3h", "Up: 5h 14m", or "Up: 37m" - if (days) - snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %ud %uh", days, hours); - else if (hours) - snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %uh %um", hours, mins); - else - snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %um", mins); + getUptimeStr(node->device_metrics.uptime_seconds * 1000, " Up", uptimeStr, sizeof(uptimeStr)); } if (uptimeStr[0] && line < 5) { display->drawString(x, getTextPositions(display)[line++], uptimeStr); @@ -592,18 +583,8 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta drawNodes(display, x + 1, getTextPositions(display)[line] + 2, nodeStatus, -1, false, "online"); #endif char uptimeStr[32] = ""; - uint32_t uptime = millis() / 1000; - uint32_t days = uptime / 86400; - uint32_t hours = (uptime % 86400) / 3600; - uint32_t mins = (uptime % 3600) / 60; - // Show as "Up: 2d 3h", "Up: 5h 14m", or "Up: 37m" #if !defined(M5STACK_UNITC6L) - if (days) - snprintf(uptimeStr, sizeof(uptimeStr), "Up: %ud %uh", days, hours); - else if (hours) - snprintf(uptimeStr, sizeof(uptimeStr), "Up: %uh %um", hours, mins); - else - snprintf(uptimeStr, sizeof(uptimeStr), "Up: %um", mins); + getUptimeStr(millis(), "Up", uptimeStr, sizeof(uptimeStr)); #endif display->drawString(SCREEN_WIDTH - display->getStringWidth(uptimeStr), getTextPositions(display)[line++], uptimeStr); @@ -1048,36 +1029,17 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU if (strcmp(displayLine, "GPS off") != 0 && strcmp(displayLine, "No GPS") != 0) { // === Second Row: Last GPS Fix === if (gpsStatus->getLastFixMillis() > 0) { - uint32_t delta = (millis() - gpsStatus->getLastFixMillis()) / 1000; // seconds since last fix - uint32_t days = delta / 86400; - uint32_t hours = (delta % 86400) / 3600; - uint32_t mins = (delta % 3600) / 60; - uint32_t secs = delta % 60; - - char buf[32]; + uint32_t delta = millis() - gpsStatus->getLastFixMillis(); + char uptimeStr[32]; #if defined(USE_EINK) // E-Ink: skip seconds, show only days/hours/mins - if (days > 0) { - snprintf(buf, sizeof(buf), "Last: %ud %uh", days, hours); - } else if (hours > 0) { - snprintf(buf, sizeof(buf), "Last: %uh %um", hours, mins); - } else { - snprintf(buf, sizeof(buf), "Last: %um", mins); - } + getUptimeStr(delta, "Last", uptimeStr, sizeof(uptimeStr), false); #else // Non E-Ink: include seconds where useful - if (days > 0) { - snprintf(buf, sizeof(buf), "Last: %ud %uh", days, hours); - } else if (hours > 0) { - snprintf(buf, sizeof(buf), "Last: %uh %um", hours, mins); - } else if (mins > 0) { - snprintf(buf, sizeof(buf), "Last: %um %us", mins, secs); - } else { - snprintf(buf, sizeof(buf), "Last: %us", secs); - } + getUptimeStr(delta, "Last", uptimeStr, sizeof(uptimeStr), true); #endif - display->drawString(0, getTextPositions(display)[line++], buf); + display->drawString(0, getTextPositions(display)[line++], uptimeStr); } else { display->drawString(0, getTextPositions(display)[line++], "Last: ?"); } @@ -1422,4 +1384,4 @@ std::string UIRenderer::drawTimeDelta(uint32_t days, uint32_t hours, uint32_t mi } // namespace graphics -#endif // HAS_SCREEN \ No newline at end of file +#endif // HAS_SCREEN