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
This commit is contained in:
Ben Meadors 2025-07-07 19:35:57 -05:00 committed by GitHub
parent f2fb473ecf
commit 415dc4aa47
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 27 additions and 12 deletions

View File

@ -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) { 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, 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()); 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; return true;
} else } else
return false; return false;

View File

@ -105,7 +105,7 @@ void readFromRTC()
* *
* If we haven't yet set our RTC this boot, set it from a GPS derived time * 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; static uint32_t lastSetMsec = 0;
uint32_t now = millis(); uint32_t now = millis();
@ -113,7 +113,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
#ifdef BUILD_EPOCH #ifdef BUILD_EPOCH
if (tv->tv_sec < BUILD_EPOCH) { if (tv->tv_sec < BUILD_EPOCH) {
LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH); LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
return false; return RTCSetResultInvalidTime;
} }
#endif #endif
@ -184,9 +184,9 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
readFromRTC(); readFromRTC();
#endif #endif
return true; return RTCSetResultSuccess;
} else { } 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. * @param t The time to potentially set the RTC to.
* @return True if the RTC was set to the provided time, false otherwise. * @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 /* 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 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); // 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) { 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); // 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 { } else {
return perhapsSetRTC(q, &tv); return perhapsSetRTC(q, &tv);
} }

View File

@ -22,13 +22,22 @@ enum RTCQuality {
RTCQualityGPS = 4 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(); RTCQuality getRTCQuality();
extern uint32_t lastSetFromPhoneNtpOrGps; extern uint32_t lastSetFromPhoneNtpOrGps;
/// If we haven't yet set our RTC this boot, set it from a GPS derived time /// 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); RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate = false);
bool perhapsSetRTC(RTCQuality q, struct tm &t); RTCSetResult perhapsSetRTC(RTCQuality q, struct tm &t);
/// Return a string name for the quality /// Return a string name for the quality
const char *RtcName(RTCQuality quality); const char *RtcName(RTCQuality quality);

View File

@ -42,7 +42,7 @@ uint32_t NotificationRenderer::currentNumber = 0;
uint32_t pow_of_10(uint32_t n) uint32_t pow_of_10(uint32_t n)
{ {
uint32_t ret = 1; uint32_t ret = 1;
for (int i = 0; i < n; i++) { for (uint32_t i = 0; i < n; i++) {
ret *= 10; ret *= 10;
} }
return ret; return ret;
@ -80,6 +80,9 @@ void NotificationRenderer::drawBannercallback(OLEDDisplay *display, OLEDDisplayU
if (!isOverlayBannerShowing() || pauseBanner) if (!isOverlayBannerShowing() || pauseBanner)
return; return;
switch (current_notification_type) { switch (current_notification_type) {
case notificationTypeEnum::none:
// Do nothing - no notification to display
break;
case notificationTypeEnum::text_banner: case notificationTypeEnum::text_banner:
case notificationTypeEnum::selection_picker: case notificationTypeEnum::selection_picker:
drawAlertBannerOverlay(display, state); 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 const char *linePointers[totalLines + 1] = {0}; // this is sort of a dynamic allocation
// copy the linestarts to display to the linePointers holder // 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]; linePointers[i] = lineStarts[i];
} }
std::string digits = " "; std::string digits = " ";
std::string arrowPointer = " "; 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 // 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))) + " "; digits += std::to_string((currentNumber % (pow_of_10(numDigits - i))) / (pow_of_10(numDigits - i - 1))) + " ";
if (curSelected == i) { if (curSelected == i) {