From 023f1c24fb8d3dd6c0326e837ee2c4ce421cb37a Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Thu, 8 Oct 2020 07:46:20 +0800 Subject: [PATCH] RTC: add notion of 'quality' for different time sources Allow use of mesh based time until a GPS time arrives --- docs/software/gps-todo.txt | 2 -- src/gps/GPS.cpp | 11 +++++------ src/gps/NMEAGPS.cpp | 2 +- src/gps/RTC.cpp | 23 ++++++++++++++--------- src/gps/RTC.h | 21 ++++++++++++++++----- src/gps/UBloxGPS.cpp | 2 +- src/mesh/MeshService.cpp | 10 +++------- 7 files changed, 40 insertions(+), 31 deletions(-) diff --git a/docs/software/gps-todo.txt b/docs/software/gps-todo.txt index 9612da31..5dc8c273 100644 --- a/docs/software/gps-todo.txt +++ b/docs/software/gps-todo.txt @@ -6,8 +6,6 @@ bin/run.sh --set region 8 time only mode ./bin/run.sh --set gps_operation 3 -set time provisionally from net even if we have gps - ublox parsing failure record power measurements and update spreadsheet diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index f39772d3..8e75e20f 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -1,10 +1,10 @@ #include "GPS.h" #include "NodeDB.h" +#include "RTC.h" #include "configuration.h" #include "sleep.h" #include -#include "RTC.h" // If we have a serial GPS port it will not be null #ifdef GPS_RX_PIN @@ -23,10 +23,8 @@ uint8_t GPS::i2cAddress = GPS_I2C_ADDRESS; uint8_t GPS::i2cAddress = 0; #endif - GPS *gps; - bool GPS::setup() { setAwake(true); // Wake GPS power before doing any init @@ -99,7 +97,8 @@ uint32_t GPS::getSleepTime() const uint32_t t = radioConfig.preferences.gps_update_interval; auto op = getGpsOp(); - if ((timeSetFromGPS && op == GpsOperation_GpsOpTimeOnly) || (op == GpsOperation_GpsOpDisabled)) + bool gotTime = (getRTCQuality() >= RTCQualityGPS); + if ((gotTime && op == GpsOperation_GpsOpTimeOnly) || (op == GpsOperation_GpsOpDisabled)) t = UINT32_MAX; // Sleep forever now if (t == UINT32_MAX) @@ -148,7 +147,7 @@ void GPS::loop() } // If we've already set time from the GPS, no need to ask the GPS - bool gotTime = timeSetFromGPS || lookForTime(); + bool gotTime = (getRTCQuality() >= RTCQualityGPS) || lookForTime(); bool gotLoc = lookForLocation(); // We've been awake too long - force sleep @@ -158,7 +157,7 @@ void GPS::loop() // Once we get a location we no longer desperately want an update // or if we got a time and we are in GpsOpTimeOnly mode // DEBUG_MSG("gotLoc %d, tooLong %d, gotTime %d\n", gotLoc, tooLong, gotTime); - if ((gotLoc && timeSetFromGPS) || tooLong || (gotTime && getGpsOp() == GpsOperation_GpsOpTimeOnly)) { + if ((gotLoc && gotTime) || tooLong || (gotTime && getGpsOp() == GpsOperation_GpsOpTimeOnly)) { if (gotLoc) hasValidLocation = true; diff --git a/src/gps/NMEAGPS.cpp b/src/gps/NMEAGPS.cpp index 41b1d476..50367469 100644 --- a/src/gps/NMEAGPS.cpp +++ b/src/gps/NMEAGPS.cpp @@ -45,7 +45,7 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s t.tm_mon = d.month() - 1; t.tm_year = d.year() - 1900; t.tm_isdst = false; - perhapsSetRTC(t); + perhapsSetRTC(RTCQualityGPS, t); return true; } else diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp index de55ebdb..ff2e9afa 100644 --- a/src/gps/RTC.cpp +++ b/src/gps/RTC.cpp @@ -1,9 +1,14 @@ -#include "configuration.h" #include "RTC.h" +#include "configuration.h" #include #include -bool timeSetFromGPS; // We try to set our time from GPS each time we wake from sleep +static RTCQuality currentQuality = RTCQualityNone; + +RTCQuality getRTCQuality() +{ + return currentQuality; +} // stuff that really should be in in the instance instead... static uint32_t @@ -17,17 +22,17 @@ void readFromRTC() if (!gettimeofday(&tv, NULL)) { uint32_t now = millis(); - DEBUG_MSG("Read RTC time as %ld (cur millis %u) valid=%d\n", tv.tv_sec, now, timeSetFromGPS); + DEBUG_MSG("Read RTC time as %ld (cur millis %u) quality=%d\n", tv.tv_sec, now, currentQuality); timeStartMsec = now; zeroOffsetSecs = tv.tv_sec; } } /// If we haven't yet set our RTC this boot, set it from a GPS derived time -bool perhapsSetRTC(const struct timeval *tv) +bool perhapsSetRTC(RTCQuality q, const struct timeval *tv) { - if (!timeSetFromGPS) { - timeSetFromGPS = true; + if (q > currentQuality) { + currentQuality = q; DEBUG_MSG("Setting RTC %ld secs\n", tv->tv_sec); #ifndef NO_ESP32 settimeofday(tv, NULL); @@ -41,7 +46,7 @@ bool perhapsSetRTC(const struct timeval *tv) } } -bool perhapsSetRTC(struct tm &t) +bool 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 @@ -57,7 +62,7 @@ bool perhapsSetRTC(struct tm &t) // DEBUG_MSG("Ignoring invalid GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec); return false; } else { - return perhapsSetRTC(&tv); + return perhapsSetRTC(q, &tv); } } @@ -68,5 +73,5 @@ uint32_t getTime() uint32_t getValidTime() { - return timeSetFromGPS ? getTime() : 0; + return (currentQuality >= RTCQualityFromNet) ? getTime() : 0; } diff --git a/src/gps/RTC.h b/src/gps/RTC.h index 869de4b2..e17ca7a9 100644 --- a/src/gps/RTC.h +++ b/src/gps/RTC.h @@ -4,16 +4,27 @@ #include "sys/time.h" #include -extern bool timeSetFromGPS; // We try to set our time from GPS each time we wake from sleep +enum RTCQuality { + /// We haven't had our RTC set yet + RTCQualityNone = 0, + + /// Some other node gave us a time we can use + RTCQualityFromNet = 1, + + /// Our time is based on our own GPS + RTCQualityGPS = 2 +}; + +RTCQuality getRTCQuality(); /// If we haven't yet set our RTC this boot, set it from a GPS derived time -bool perhapsSetRTC(const struct timeval *tv); -bool perhapsSetRTC(struct tm &t); +bool perhapsSetRTC(RTCQuality q, const struct timeval *tv); +bool perhapsSetRTC(RTCQuality q, struct tm &t); -/// Return time since 1970 in secs. Until we have a GPS lock we will be returning time based at zero +/// Return time since 1970 in secs. While quality is RTCQualityNone we will be returning time based at zero uint32_t getTime(); -/// Return time since 1970 in secs. If we don't have a GPS lock return zero +/// Return time since 1970 in secs. If quality is RTCQualityNone return zero uint32_t getValidTime(); void readFromRTC(); \ No newline at end of file diff --git a/src/gps/UBloxGPS.cpp b/src/gps/UBloxGPS.cpp index 36541719..acbe0220 100644 --- a/src/gps/UBloxGPS.cpp +++ b/src/gps/UBloxGPS.cpp @@ -152,7 +152,7 @@ bool UBloxGPS::lookForTime() t.tm_mon = ublox.getMonth(0) - 1; t.tm_year = ublox.getYear(0) - 1900; t.tm_isdst = false; - perhapsSetRTC(t); + perhapsSetRTC(RTCQualityGPS, t); return true; } diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 5201fcd9..a3242327 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -140,7 +140,7 @@ void MeshService::handleIncomingPosition(const MeshPacket *mp) tv.tv_sec = secs; tv.tv_usec = 0; - perhapsSetRTC(&tv); + perhapsSetRTC(RTCQualityFromNet, &tv); } } else { DEBUG_MSG("Ignoring incoming packet - not a position\n"); @@ -151,12 +151,8 @@ int MeshService::handleFromRadio(const MeshPacket *mp) { powerFSM.trigger(EVENT_RECEIVED_PACKET); // Possibly keep the node from sleeping - // If it is a position packet, perhaps set our clock (if we don't have a GPS of our own, otherwise wait for that to work) - if (!gps->isConnected) - handleIncomingPosition(mp); - else { - DEBUG_MSG("Ignoring incoming time, because we have a GPS\n"); - } + // If it is a position packet, perhaps set our clock + handleIncomingPosition(mp); if (mp->which_payload == MeshPacket_decoded_tag && mp->decoded.which_payload == SubPacket_user_tag) { mp = handleFromRadioUser(mp);