diff --git a/include/lorawan.h b/include/lorawan.h index 76a57397..d02e8931 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -17,10 +17,9 @@ #include #endif - - extern QueueHandle_t LoraSendQueue; +esp_err_t lora_stack_init(); void onEvent(ev_t ev); void gen_lora_deveui(uint8_t *pdeveui); void RevBytes(unsigned char *b, size_t c); @@ -36,7 +35,7 @@ void lora_queuereset(void); void lora_housekeeping(void); void user_request_network_time_callback(void *pVoidUserUTCTime, int flagSuccess); - -esp_err_t lora_stack_init(); +time_t set_loratime(time_t t); +time_t get_loratime(void); #endif \ No newline at end of file diff --git a/include/timekeeper.h b/include/timekeeper.h index 90441736..2b36bbf2 100644 --- a/include/timekeeper.h +++ b/include/timekeeper.h @@ -20,13 +20,12 @@ void clock_init(void); void clock_loop(void *pvParameters); void time_sync(void); void timepulse_start(void); -uint8_t wait_for_pulse(void); -uint8_t syncTime(time_t const t, timesource_t const caller); +uint8_t syncTime(getExternalTime getTimeFunction, timesource_t const caller); uint8_t timepulse_init(void); uint8_t TimeIsValid(time_t const t); time_t syncProvider_CB(void); time_t compiledUTC(void); -time_t tmConvert(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh, - uint8_t mm, uint8_t ss); +time_t tmConvert(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh, uint8_t mm, + uint8_t ss); #endif // _timekeeper_H \ No newline at end of file diff --git a/src/gpsread.cpp b/src/gpsread.cpp index a1ddadc3..514499f5 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -75,9 +75,6 @@ void gps_read() { // function to fetch current time from gps time_t get_gpstime(void) { - // !! never call now() or delay in this function, this would break this - // function to be used as SyncProvider for Time.h - time_t t = 0; if ((gps.time.age() < 950) && (gps.time.isValid())) { @@ -87,11 +84,11 @@ time_t get_gpstime(void) { // use recent gps time t = tmConvert(gps.date.year(), gps.date.month(), gps.date.day(), - gps.time.hour(), gps.time.minute(), gps.time.second()); + gps.time.hour(), gps.time.minute(), gps.time.second()); - ESP_LOGD(TAG, "GPS time: %02d.%02d.%04d %02d:%02d:%02d", gps.date.day(), - gps.date.month(), gps.date.year(), gps.time.hour(), - gps.time.minute(), gps.time.second()); + // ESP_LOGD(TAG, "GPS time: %02d.%02d.%04d %02d:%02d:%02d", gps.date.day(), + // gps.date.month(), gps.date.year(), gps.time.hour(), + // gps.time.minute(), gps.time.second()); } return t; } // get_gpstime() diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 7c0cee66..b4067cd9 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -472,9 +472,19 @@ void user_request_network_time_callback(void *pVoidUserUTCTime, *pUserUTCTime += requestDelaySec; // Update system time with time read from the network - if (syncTime(*pUserUTCTime, _lora)) { // have we got a valid time? - ESP_LOGI(TAG, "LORA has set the system time"); - } else - ESP_LOGI(TAG, "Unable to sync system time with LORA"); + set_loratime(*pUserUTCTime); // store time in time sync provider function + if (syncTime(get_loratime, _lora)) + ESP_LOGI(TAG, "Received recent time from LoRa"); + else + ESP_LOGI(TAG, "Invalid time received from LoRa"); #endif // HAS_LORA -} // user_request_network_time_callback \ No newline at end of file +} // user_request_network_time_callback + +time_t set_loratime(time_t t) { + static time_t loratime = 0; // stores time for retrieval + if (t > loratime) + loratime = t; // store time if it is recent + return loratime; +} + +time_t get_loratime(void) { return set_loratime(0); } diff --git a/src/rtctime.cpp b/src/rtctime.cpp index 5b7952e3..ff542318 100644 --- a/src/rtctime.cpp +++ b/src/rtctime.cpp @@ -59,8 +59,6 @@ uint8_t set_rtctime(time_t t) { // t is UTC in seconds epoch time } // set_rtctime() time_t get_rtctime(void) { - // !! never call now() or delay in this function, this would break this - // function to be used as SyncProvider for Time.h time_t t = 0; if (I2C_MUTEX_LOCK()) { if (Rtc.IsDateTimeValid() && Rtc.GetIsRunning()) { diff --git a/src/timekeeper.cpp b/src/timekeeper.cpp index a34ff6a3..316835ec 100644 --- a/src/timekeeper.cpp +++ b/src/timekeeper.cpp @@ -6,23 +6,24 @@ static const char TAG[] = "main"; // symbol to display current time source const char timeSetSymbols[] = {'G', 'R', 'L', '?'}; +getExternalTime TimeSourcePtr; // pointer to time source function + void time_sync() { - // synchonization of systime with external time source (GPS/LORA) - // frequently called from cyclic.cpp + // check synchonization of systime, called by cyclic.cpp #ifdef TIME_SYNC_INTERVAL - if (timeStatus() == timeSet) + if (timeStatus() == timeSet) // timeStatus() is flipped in Time.h return; #ifdef HAS_GPS - if (syncTime(get_gpstime(), _gps)) + if (syncTime(get_gpstime, _gps)) return; // attempt sync with GPS time #endif // no GPS -> fallback to RTC time while trying lora sync #ifdef HAS_RTC - if (!syncTime(get_rtctime(), _rtc)) // sync with RTC time + if (!syncTime(get_rtctime, _rtc)) // sync with RTC time ESP_LOGW(TAG, "no confident RTC time"); #endif @@ -34,43 +35,50 @@ void time_sync() { #endif // TIME_SYNC_INTERVAL } // time_sync() -// sync time on start of next second -uint8_t syncTime(time_t const t, timesource_t const caller) { +// sync time on start of next second from GPS or RTC +uint8_t syncTime(getExternalTime getTimeFunction, timesource_t const caller) { + + TimeSourcePtr = getTimeFunction; + time_t t; + + if (!TimeSourcePtr) + goto error; + + if ((caller == _gps || caller == _rtc)) // ticking timesource? + xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1000)); // then wait on pps + + t = TimeSourcePtr(); // get time from given timesource + if (TimeIsValid(t)) { - uint8_t const TimeIsPulseSynced = - wait_for_pulse(); // wait for next 1pps timepulse - setTime(t); // sync time and reset timeStatus() to timeSet - adjustTime(1); // forward time to next second + if (caller == _gps) // gps time concerns past second + t++; + setTime(t); // flips timeStatus() in Time.h timeSource = caller; ESP_LOGD(TAG, "Time source %c set time to %02d:%02d:%02d", timeSetSymbols[timeSource], hour(t), minute(t), second(t)); -#ifdef HAS_RTC - if ((TimeIsPulseSynced) && (caller != _rtc)) - set_rtctime(now()); -#endif - return 1; // success - } else { - ESP_LOGD(TAG, "Time source %c sync attempt failed", timeSetSymbols[caller]); - timeSource = _unsynced; - return 0; // failure +#ifdef HAS_RTC + if (caller != _rtc) + set_rtctime(t); +#endif + + return 1; // success } + +error: + ESP_LOGD(TAG, "Time source %c sync attempt failed", timeSetSymbols[caller]); + timeSource = _unsynced; + return 0; // failure + } // syncTime() + // callback function called by Time.h in interval set in main.cpp time_t syncProvider_CB(void) { timeSource = _unsynced; return 0; } -// helper function to sync moment on timepulse -uint8_t wait_for_pulse(void) { - // sync on top of next second with 1pps timepulse - if (xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1010)) == pdTRUE) - return 1; // success - ESP_LOGD(TAG, "Missing timepulse"); - return 0; // failure -} // helper function to setup a pulse per second for time synchronisation uint8_t timepulse_init() { @@ -209,7 +217,8 @@ void clock_loop(void *pvParameters) { // ClockTask xTaskNotifyWait(0x00, ULONG_MAX, &wakeTime, portMAX_DELAY); // wait for timepulse - if (timeStatus() == timeNotSet) // no confident time -> no output to clock + // no confident time -> suppress clock output + if (timeStatus() == timeNotSet) continue; t = now(); // payload to send to clock