timekeeper fixes

This commit is contained in:
Klaus K Wilting 2019-02-24 23:13:15 +01:00
parent c20ef02ce8
commit 6ab4a0bd9f
6 changed files with 63 additions and 51 deletions

View File

@ -17,10 +17,9 @@
#include <Wire.h> #include <Wire.h>
#endif #endif
extern QueueHandle_t LoraSendQueue; extern QueueHandle_t LoraSendQueue;
esp_err_t lora_stack_init();
void onEvent(ev_t ev); void onEvent(ev_t ev);
void gen_lora_deveui(uint8_t *pdeveui); void gen_lora_deveui(uint8_t *pdeveui);
void RevBytes(unsigned char *b, size_t c); void RevBytes(unsigned char *b, size_t c);
@ -36,7 +35,7 @@ void lora_queuereset(void);
void lora_housekeeping(void); void lora_housekeeping(void);
void user_request_network_time_callback(void *pVoidUserUTCTime, void user_request_network_time_callback(void *pVoidUserUTCTime,
int flagSuccess); int flagSuccess);
time_t set_loratime(time_t t);
esp_err_t lora_stack_init(); time_t get_loratime(void);
#endif #endif

View File

@ -20,13 +20,12 @@ void clock_init(void);
void clock_loop(void *pvParameters); void clock_loop(void *pvParameters);
void time_sync(void); void time_sync(void);
void timepulse_start(void); void timepulse_start(void);
uint8_t wait_for_pulse(void); uint8_t syncTime(getExternalTime getTimeFunction, timesource_t const caller);
uint8_t syncTime(time_t const t, timesource_t const caller);
uint8_t timepulse_init(void); uint8_t timepulse_init(void);
uint8_t TimeIsValid(time_t const t); uint8_t TimeIsValid(time_t const t);
time_t syncProvider_CB(void); time_t syncProvider_CB(void);
time_t compiledUTC(void); time_t compiledUTC(void);
time_t tmConvert(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh, time_t tmConvert(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh, uint8_t mm,
uint8_t mm, uint8_t ss); uint8_t ss);
#endif // _timekeeper_H #endif // _timekeeper_H

View File

@ -75,9 +75,6 @@ void gps_read() {
// function to fetch current time from gps // function to fetch current time from gps
time_t get_gpstime(void) { 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; time_t t = 0;
if ((gps.time.age() < 950) && (gps.time.isValid())) { if ((gps.time.age() < 950) && (gps.time.isValid())) {
@ -87,11 +84,11 @@ time_t get_gpstime(void) {
// use recent gps time // use recent gps time
t = tmConvert(gps.date.year(), gps.date.month(), gps.date.day(), 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(), // ESP_LOGD(TAG, "GPS time: %02d.%02d.%04d %02d:%02d:%02d", gps.date.day(),
gps.date.month(), gps.date.year(), gps.time.hour(), // gps.date.month(), gps.date.year(), gps.time.hour(),
gps.time.minute(), gps.time.second()); // gps.time.minute(), gps.time.second());
} }
return t; return t;
} // get_gpstime() } // get_gpstime()

View File

@ -472,9 +472,19 @@ void user_request_network_time_callback(void *pVoidUserUTCTime,
*pUserUTCTime += requestDelaySec; *pUserUTCTime += requestDelaySec;
// Update system time with time read from the network // Update system time with time read from the network
if (syncTime(*pUserUTCTime, _lora)) { // have we got a valid time? set_loratime(*pUserUTCTime); // store time in time sync provider function
ESP_LOGI(TAG, "LORA has set the system time"); if (syncTime(get_loratime, _lora))
} else ESP_LOGI(TAG, "Received recent time from LoRa");
ESP_LOGI(TAG, "Unable to sync system time with LORA"); else
ESP_LOGI(TAG, "Invalid time received from LoRa");
#endif // HAS_LORA #endif // HAS_LORA
} // user_request_network_time_callback } // 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); }

View File

@ -59,8 +59,6 @@ uint8_t set_rtctime(time_t t) { // t is UTC in seconds epoch time
} // set_rtctime() } // set_rtctime()
time_t get_rtctime(void) { 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; time_t t = 0;
if (I2C_MUTEX_LOCK()) { if (I2C_MUTEX_LOCK()) {
if (Rtc.IsDateTimeValid() && Rtc.GetIsRunning()) { if (Rtc.IsDateTimeValid() && Rtc.GetIsRunning()) {

View File

@ -6,23 +6,24 @@ static const char TAG[] = "main";
// symbol to display current time source // symbol to display current time source
const char timeSetSymbols[] = {'G', 'R', 'L', '?'}; const char timeSetSymbols[] = {'G', 'R', 'L', '?'};
getExternalTime TimeSourcePtr; // pointer to time source function
void time_sync() { void time_sync() {
// synchonization of systime with external time source (GPS/LORA) // check synchonization of systime, called by cyclic.cpp
// frequently called from cyclic.cpp
#ifdef TIME_SYNC_INTERVAL #ifdef TIME_SYNC_INTERVAL
if (timeStatus() == timeSet) if (timeStatus() == timeSet) // timeStatus() is flipped in Time.h
return; return;
#ifdef HAS_GPS #ifdef HAS_GPS
if (syncTime(get_gpstime(), _gps)) if (syncTime(get_gpstime, _gps))
return; // attempt sync with GPS time return; // attempt sync with GPS time
#endif #endif
// no GPS -> fallback to RTC time while trying lora sync // no GPS -> fallback to RTC time while trying lora sync
#ifdef HAS_RTC #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"); ESP_LOGW(TAG, "no confident RTC time");
#endif #endif
@ -34,43 +35,50 @@ void time_sync() {
#endif // TIME_SYNC_INTERVAL #endif // TIME_SYNC_INTERVAL
} // time_sync() } // time_sync()
// sync time on start of next second // sync time on start of next second from GPS or RTC
uint8_t syncTime(time_t const t, timesource_t const caller) { 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)) { if (TimeIsValid(t)) {
uint8_t const TimeIsPulseSynced = if (caller == _gps) // gps time concerns past second
wait_for_pulse(); // wait for next 1pps timepulse t++;
setTime(t); // sync time and reset timeStatus() to timeSet setTime(t); // flips timeStatus() in Time.h
adjustTime(1); // forward time to next second
timeSource = caller; timeSource = caller;
ESP_LOGD(TAG, "Time source %c set time to %02d:%02d:%02d", ESP_LOGD(TAG, "Time source %c set time to %02d:%02d:%02d",
timeSetSymbols[timeSource], hour(t), minute(t), second(t)); timeSetSymbols[timeSource], hour(t), minute(t), second(t));
#ifdef HAS_RTC
if ((TimeIsPulseSynced) && (caller != _rtc))
set_rtctime(now());
#endif
return 1; // success
} else { #ifdef HAS_RTC
ESP_LOGD(TAG, "Time source %c sync attempt failed", timeSetSymbols[caller]); if (caller != _rtc)
timeSource = _unsynced; set_rtctime(t);
return 0; // failure #endif
return 1; // success
} }
error:
ESP_LOGD(TAG, "Time source %c sync attempt failed", timeSetSymbols[caller]);
timeSource = _unsynced;
return 0; // failure
} // syncTime() } // syncTime()
// callback function called by Time.h in interval set in main.cpp // callback function called by Time.h in interval set in main.cpp
time_t syncProvider_CB(void) { time_t syncProvider_CB(void) {
timeSource = _unsynced; timeSource = _unsynced;
return 0; 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 // helper function to setup a pulse per second for time synchronisation
uint8_t timepulse_init() { uint8_t timepulse_init() {
@ -209,7 +217,8 @@ void clock_loop(void *pvParameters) { // ClockTask
xTaskNotifyWait(0x00, ULONG_MAX, &wakeTime, xTaskNotifyWait(0x00, ULONG_MAX, &wakeTime,
portMAX_DELAY); // wait for timepulse 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; continue;
t = now(); // payload to send to clock t = now(); // payload to send to clock