From 415dc4aa471640cd4e55967e4381fb62ff59203d Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Mon, 7 Jul 2025 19:35:57 -0500 Subject: [PATCH] Try-fix: L76K spamming bad times can crash nodes (#7261) * Try-fix: Clear GPS buffer when we encounter a bad time in NMEA * Fix signed int warnings --- src/gps/GPS.cpp | 5 ++++- src/gps/RTC.cpp | 12 ++++++------ src/gps/RTC.h | 13 +++++++++++-- src/graphics/draw/NotificationRenderer.cpp | 9 ++++++--- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 142241c43..345c738d6 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -1536,7 +1536,10 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s if (t.tm_mon > -1) { LOG_DEBUG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d age %d", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, ti.age()); - perhapsSetRTC(RTCQualityGPS, t); + if (perhapsSetRTC(RTCQualityGPS, t) == RTCSetResultInvalidTime) { + // Clear the GPS buffer if we got an invalid time + clearBuffer(); + } return true; } else return false; diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp index 219a593e0..5054be3f0 100644 --- a/src/gps/RTC.cpp +++ b/src/gps/RTC.cpp @@ -105,7 +105,7 @@ void readFromRTC() * * If we haven't yet set our RTC this boot, set it from a GPS derived time */ -bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate) +RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate) { static uint32_t lastSetMsec = 0; uint32_t now = millis(); @@ -113,7 +113,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate) #ifdef BUILD_EPOCH if (tv->tv_sec < BUILD_EPOCH) { LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH); - return false; + return RTCSetResultInvalidTime; } #endif @@ -184,9 +184,9 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate) readFromRTC(); #endif - return true; + return RTCSetResultSuccess; } else { - return false; + return RTCSetResultNotSet; // RTC was already set with a higher quality time } } @@ -215,7 +215,7 @@ const char *RtcName(RTCQuality quality) * @param t The time to potentially set the RTC to. * @return True if the RTC was set to the provided time, false otherwise. */ -bool perhapsSetRTC(RTCQuality q, struct tm &t) +RTCSetResult perhapsSetRTC(RTCQuality q, struct tm &t) { /* Convert to unix time The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970 @@ -231,7 +231,7 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t) // LOG_DEBUG("Got time from GPS month=%d, year=%d, unixtime=%ld", t.tm_mon, t.tm_year, tv.tv_sec); if (t.tm_year < 0 || t.tm_year >= 300) { // LOG_DEBUG("Ignore invalid GPS month=%d, year=%d, unixtime=%ld", t.tm_mon, t.tm_year, tv.tv_sec); - return false; + return RTCSetResultInvalidTime; } else { return perhapsSetRTC(q, &tv); } diff --git a/src/gps/RTC.h b/src/gps/RTC.h index caa48dc06..96dec575b 100644 --- a/src/gps/RTC.h +++ b/src/gps/RTC.h @@ -22,13 +22,22 @@ enum RTCQuality { RTCQualityGPS = 4 }; +/// The RTC set result codes +/// Used to indicate the result of an attempt to set the RTC. +enum RTCSetResult { + RTCSetResultNotSet = 0, ///< RTC was set successfully + RTCSetResultSuccess = 1, ///< RTC was set successfully + RTCSetResultInvalidTime = 3, ///< The provided time was invalid (e.g., before the build epoch) + RTCSetResultError = 4 ///< An error occurred while setting the RTC +}; + RTCQuality getRTCQuality(); extern uint32_t lastSetFromPhoneNtpOrGps; /// If we haven't yet set our RTC this boot, set it from a GPS derived time -bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate = false); -bool perhapsSetRTC(RTCQuality q, struct tm &t); +RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate = false); +RTCSetResult perhapsSetRTC(RTCQuality q, struct tm &t); /// Return a string name for the quality const char *RtcName(RTCQuality quality); diff --git a/src/graphics/draw/NotificationRenderer.cpp b/src/graphics/draw/NotificationRenderer.cpp index 3b682cc55..057c91008 100644 --- a/src/graphics/draw/NotificationRenderer.cpp +++ b/src/graphics/draw/NotificationRenderer.cpp @@ -42,7 +42,7 @@ uint32_t NotificationRenderer::currentNumber = 0; uint32_t pow_of_10(uint32_t n) { uint32_t ret = 1; - for (int i = 0; i < n; i++) { + for (uint32_t i = 0; i < n; i++) { ret *= 10; } return ret; @@ -80,6 +80,9 @@ void NotificationRenderer::drawBannercallback(OLEDDisplay *display, OLEDDisplayU if (!isOverlayBannerShowing() || pauseBanner) return; switch (current_notification_type) { + case notificationTypeEnum::none: + // Do nothing - no notification to display + break; case notificationTypeEnum::text_banner: case notificationTypeEnum::selection_picker: drawAlertBannerOverlay(display, state); @@ -144,12 +147,12 @@ void NotificationRenderer::drawNumberPicker(OLEDDisplay *display, OLEDDisplayUiS const char *linePointers[totalLines + 1] = {0}; // this is sort of a dynamic allocation // copy the linestarts to display to the linePointers holder - for (int i = 0; i < lineCount; i++) { + for (uint16_t i = 0; i < lineCount; i++) { linePointers[i] = lineStarts[i]; } std::string digits = " "; std::string arrowPointer = " "; - for (int i = 0; i < numDigits; i++) { + for (uint16_t i = 0; i < numDigits; i++) { // Modulo minus modulo to return just the current number digits += std::to_string((currentNumber % (pow_of_10(numDigits - i))) / (pow_of_10(numDigits - i - 1))) + " "; if (curSelected == i) {