From 77cf5c62008a1e8e3c331fb52dbe9bf1985a35e9 Mon Sep 17 00:00:00 2001 From: andrew-moroz <67253360+andrew-moroz@users.noreply.github.com> Date: Sun, 26 May 2024 08:04:31 -0400 Subject: [PATCH] Fix time updates from client device and potentially incorrect UI frame receiving 'toggle watch face' button tap (#3974) --- src/gps/RTC.cpp | 8 ++++++-- src/gps/RTC.h | 2 +- src/graphics/Screen.cpp | 27 ++++++++++++--------------- src/modules/PositionModule.cpp | 24 +++++++++++++++++++++--- src/modules/PositionModule.h | 2 +- 5 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp index a2cdb5b30..864b246a3 100644 --- a/src/gps/RTC.cpp +++ b/src/gps/RTC.cpp @@ -96,13 +96,17 @@ 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 perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate) { static uint32_t lastSetMsec = 0; uint32_t now = millis(); bool shouldSet; - if (q > currentQuality) { + if (forceUpdate) { + shouldSet = true; + LOG_DEBUG("Overriding current RTC quality (%s) with incoming time of RTC quality of %s\n", RtcName(currentQuality), + RtcName(q)); + } else if (q > currentQuality) { shouldSet = true; LOG_DEBUG("Upgrading time to quality %s\n", RtcName(q)); } else if (q >= RTCQualityNTP && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) { diff --git a/src/gps/RTC.h b/src/gps/RTC.h index 1d609f136..4b065b376 100644 --- a/src/gps/RTC.h +++ b/src/gps/RTC.h @@ -25,7 +25,7 @@ enum RTCQuality { RTCQuality getRTCQuality(); /// 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 perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate = false); bool perhapsSetRTC(RTCQuality q, struct tm &t); /// Return a string name for the quality diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 9758e97fd..15e69b1ed 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1459,18 +1459,13 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ const char *username = node->has_user ? node->user.long_name : "Unknown Name"; static char signalStr[20]; - - //section here to choose whether to display hops away rather than signal strength if more than 0 hops away. - if(node->hops_away>0) - { + + // section here to choose whether to display hops away rather than signal strength if more than 0 hops away. + if (node->hops_away > 0) { snprintf(signalStr, sizeof(signalStr), "Hops Away: %d", node->hops_away); - } - else - { + } else { snprintf(signalStr, sizeof(signalStr), "Signal: %d%%", clamp((int)((node->snr + 10) * 5), 0, 100)); } - - uint32_t agoSecs = sinceLastSeen(node); static char lastStr[20]; @@ -2099,6 +2094,10 @@ void Screen::setFrames() if (error_code) normalFrames[numframes++] = drawCriticalFaultFrame; +#ifdef T_WATCH_S3 + normalFrames[numframes++] = screen->digitalWatchFace ? &Screen::drawDigitalClockFrame : &Screen::drawAnalogClockFrame; +#endif + // If we have a text message - show it next, unless it's a phone message and we aren't using any special modules if (devicestate.has_rx_text_message && shouldDrawMessage(&devicestate.rx_text_message)) { normalFrames[numframes++] = drawTextMessageFrame; @@ -2108,10 +2107,6 @@ void Screen::setFrames() normalFrames[numframes++] = drawWaypointFrame; } -#ifdef T_WATCH_S3 - normalFrames[numframes++] = screen->digitalWatchFace ? &Screen::drawDigitalClockFrame : &Screen::drawAnalogClockFrame; -#endif - // then all the nodes // We only show a few nodes in our scrolling list - because meshes with many nodes would have too many screens size_t numToShow = min(numMeshNodes, 4U); @@ -2686,8 +2681,10 @@ int Screen::handleInputEvent(const InputEvent *event) #ifdef T_WATCH_S3 // For the T-Watch, intercept touches to the 'toggle digital/analog watch face' button - if (this->ui->getUiState()->currentFrame == 0 && event->touchX >= 204 && event->touchX <= 240 && event->touchY >= 204 && - event->touchY <= 240) { + uint8_t watchFaceFrame = error_code ? 1 : 0; + + if (this->ui->getUiState()->currentFrame == watchFaceFrame && event->touchX >= 204 && event->touchX <= 240 && + event->touchY >= 204 && event->touchY <= 240) { screen->digitalWatchFace = !screen->digitalWatchFace; setFrames(); diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index 9986f860d..f3a70f4c5 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -55,6 +55,15 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes isLocal = true; if (config.position.fixed_position) { LOG_DEBUG("Ignore incoming position update from myself except for time, because position.fixed_position is true\n"); + +#ifdef T_WATCH_S3 + // Since we return early if position.fixed_position is true, set the T-Watch's RTC to the time received from the + // client device here + if (p.time && channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) { + trySetRtc(p, isLocal, true); + } +#endif + nodeDB->setLocalPosition(p, true); return false; } else { @@ -71,8 +80,17 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes p.time); if (p.time && channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) { + bool force = false; + +#ifdef T_WATCH_S3 + // The T-Watch appears to "pause" its RTC when shut down, such that the time it reads upon powering on is the same as when + // it was shut down. So we need to force the update here, since otherwise RTC::perhapsSetRTC will ignore it because it + // will always be an equivalent or lesser RTCQuality (RTCQualityNTP or RTCQualityNet). + force = true; +#endif + // Set from phone RTC Quality to RTCQualityNTP since it should be approximately so - trySetRtc(p, isLocal); + trySetRtc(p, isLocal, force); } nodeDB->updatePosition(getFrom(&mp), p); @@ -104,14 +122,14 @@ void PositionModule::alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtastic } } -void PositionModule::trySetRtc(meshtastic_Position p, bool isLocal) +void PositionModule::trySetRtc(meshtastic_Position p, bool isLocal, bool forceUpdate) { struct timeval tv; uint32_t secs = p.time; tv.tv_sec = secs; tv.tv_usec = 0; - perhapsSetRTC(isLocal ? RTCQualityNTP : RTCQualityFromNet, &tv); + perhapsSetRTC(isLocal ? RTCQualityNTP : RTCQualityFromNet, &tv, forceUpdate); } meshtastic_MeshPacket *PositionModule::allocReply() diff --git a/src/modules/PositionModule.h b/src/modules/PositionModule.h index 1161159f7..763b51e5c 100644 --- a/src/modules/PositionModule.h +++ b/src/modules/PositionModule.h @@ -54,7 +54,7 @@ class PositionModule : public ProtobufModule, private concu private: struct SmartPosition getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition); meshtastic_MeshPacket *allocAtakPli(); - void trySetRtc(meshtastic_Position p, bool isLocal); + void trySetRtc(meshtastic_Position p, bool isLocal, bool forceUpdate = false); uint32_t precision; void sendLostAndFoundText();