sanitized time handling code

This commit is contained in:
Klaus K Wilting 2019-01-28 23:59:52 +01:00
parent bf1d8ab1d4
commit bdcace14b9
10 changed files with 73 additions and 78 deletions

View File

@ -17,7 +17,6 @@
#endif #endif
void doHousekeeping(void); void doHousekeeping(void);
void do_timesync(void);
uint64_t uptime(void); uint64_t uptime(void);
void reset_counters(void); void reset_counters(void);
int redirect_log(const char *fmt, va_list args); int redirect_log(const char *fmt, va_list args);

View File

@ -16,5 +16,6 @@ extern TaskHandle_t GpsTask;
int gps_init(void); int gps_init(void);
void gps_read(void); void gps_read(void);
void gps_loop(void *pvParameters); void gps_loop(void *pvParameters);
time_t get_gpstime(void);
#endif #endif

View File

@ -30,7 +30,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng
[common] [common]
; for release_version use max. 10 chars total, use any decimal format like "a.b.c" ; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
release_version = 1.7.14 release_version = 1.7.141
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
debug_level = 3 debug_level = 3

View File

@ -7,8 +7,8 @@
// Local logging tag // Local logging tag
static const char TAG[] = "main"; static const char TAG[] = "main";
uint32_t userUTCTime; // Seconds since the UTC epoch time_t userUTCTime; // Seconds since the UTC epoch
unsigned long nextTimeSync = millis(); unsigned long nextLoraTimeSync = millis();
// do all housekeeping // do all housekeeping
void doHousekeeping() { void doHousekeeping() {
@ -23,12 +23,14 @@ void doHousekeeping() {
spi_housekeeping(); spi_housekeeping();
lora_housekeeping(); lora_housekeeping();
// time sync once per TIME_SYNC_INTERVAL // do cyclic time sync with LORA network
#ifdef TIME_SYNC_INTERVAL #ifdef TIME_SYNC_INTERVAL_LORA
if (millis() >= nextTimeSync) { if (millis() >= nextLoraTimeSync) {
nextTimeSync = nextLoraTimeSync = millis() + TIME_SYNC_INTERVAL_LORA *
millis() + TIME_SYNC_INTERVAL * 60000; // set up next time sync period 60000; // set up next time sync period
do_timesync(); // Schedule a network time sync request at the next possible time
LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime);
ESP_LOGI(TAG, "LORAWAN time request scheduled");
} }
#endif #endif
@ -120,37 +122,6 @@ void reset_counters() {
macs_ble = 0; macs_ble = 0;
} }
void do_timesync() {
#ifdef TIME_SYNC_INTERVAL
// set system time to time source GPS, if we have valid gps time
#ifdef HAS_GPS
if (gps.time.isValid()) {
setTime(gps.time.hour(), gps.time.minute(), gps.time.second(),
gps.date.day(), gps.date.month(), gps.date.year());
// set RTC time to time source GPS, if RTC is present
#ifdef HAS_RTC
if (!set_rtctime(RtcDateTime(now())))
ESP_LOGE(TAG, "RTC set time failure");
#endif
time_t tt = myTZ.toLocal(now());
ESP_LOGI(TAG, "GPS has set system time to %02d/%02d/%d %02d:%02d:%02d",
month(tt), day(tt), year(tt), hour(tt), minute(tt), second(tt));
return;
} else {
ESP_LOGI(TAG, "No valid GPS time");
}
// set system time to time source LoRa Network, if network supports DevTimeReq
#elif defined LMIC_ENABLE_DeviceTimeReq
// Schedule a network time sync request at the next possible time
LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime);
ESP_LOGI(TAG, "Network time request scheduled");
#endif // HAS_GPS
#endif // TIME_SYNC_INTERVAL
} // do_timesync()
#ifndef VERBOSE #ifndef VERBOSE
int redirect_log(const char *fmt, va_list args) { int redirect_log(const char *fmt, va_list args) {
// do nothing // do nothing

View File

@ -53,6 +53,32 @@ void gps_read() {
gps.passedChecksum(), gps.failedChecksum(), gps.sentencesWithFix()); gps.passedChecksum(), gps.failedChecksum(), gps.sentencesWithFix());
} }
// helper function to convert gps date/time into time_t
time_t tmConvert_t(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh,
uint8_t mm, uint8_t ss) {
tmElements_t tm;
tm.Year = YYYY - 1970; // note year argument is offset from 1970 in time.h
tm.Month = MM;
tm.Day = DD;
tm.Hour = hh;
tm.Minute = mm;
tm.Second = ss;
return makeTime(tm);
}
// function to fetch current time from gps
time_t get_gpstime(void) {
// never call now() in this function, this would cause a recursion!
time_t t = 0;
if (gps.time.age() < 1500) {
t = tmConvert_t(gps.date.year(), gps.date.month(), gps.date.day(),
gps.time.hour(), gps.time.minute(), gps.time.second());
} else {
ESP_LOGW(TAG, "GPS has no confident time");
}
return t;
} // get_gpstime()
// GPS serial feed FreeRTos Task // GPS serial feed FreeRTos Task
void gps_loop(void *pvParameters) { void gps_loop(void *pvParameters) {

View File

@ -41,7 +41,7 @@
#define BOARD_HAS_PSRAM // use extra 4MB extern RAM #define BOARD_HAS_PSRAM // use extra 4MB extern RAM
#define HAS_GPS 1 // use if board has GPS #define HAS_GPS 1 // use if board has GPS
#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration #define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_17, GPIO_NUM_16 // UBlox NEO 6M or 7M with default configuration
// Pins for I2C interface of OLED Display // Pins for I2C interface of OLED Display
#define MY_OLED_SDA (4) #define MY_OLED_SDA (4)
@ -50,6 +50,10 @@
// Pins for on board DS3231 RTC chip // Pins for on board DS3231 RTC chip
#define HAS_RTC MY_OLED_SDA, MY_OLED_SCL // SDA, SCL #define HAS_RTC MY_OLED_SDA, MY_OLED_SCL // SDA, SCL
#define RTC_INT GPIO_NUM_34 // interrupt input from rtc
// Settings for IF482 interface
#define HAS_IF482 9600, SERIAL_7E1, GPIO_NUM_12, GPIO_NUM_14 // IF482 serial port parameters
// Pins for LORA chip SPI interface, reset line and interrupt lines // Pins for LORA chip SPI interface, reset line and interrupt lines
#define LORA_SCK (5) #define LORA_SCK (5)

View File

@ -187,7 +187,13 @@ void setup() {
#ifdef HAS_RTC #ifdef HAS_RTC
strcat_P(features, " RTC"); strcat_P(features, " RTC");
assert(rtc_init()); assert(rtc_init());
sync_rtctime(); setSyncProvider(&get_rtctime);
if (timeStatus() != timeSet)
ESP_LOGI(TAG, "Unable to sync system time with RTC");
else
ESP_LOGI(TAG, "RTC has set the system time");
setSyncInterval(TIME_SYNC_INTERVAL_RTC);
#ifdef HAS_IF482 #ifdef HAS_IF482
strcat_P(features, " IF482"); strcat_P(features, " IF482");
assert(if482_init()); assert(if482_init());
@ -200,6 +206,7 @@ void setup() {
&IF482Task, // task handle &IF482Task, // task handle
0); // CPU core 0); // CPU core
#endif // HAS_IF482 #endif // HAS_IF482
#endif // HAS_RTC #endif // HAS_RTC
// initialize wifi antenna // initialize wifi antenna
@ -411,6 +418,15 @@ void setup() {
#endif #endif
#endif // HAS_BUTTON #endif // HAS_BUTTON
#ifdef HAS_GPS
setSyncProvider(&get_gpstime);
if (timeStatus() != timeSet)
ESP_LOGI(TAG, "Unable to sync system time with GPS");
else
ESP_LOGI(TAG, "GPS has set the system time");
setSyncInterval(TIME_SYNC_INTERVAL_GPS);
#endif
// start RTC interrupt // start RTC interrupt
#if defined HAS_IF482 && defined HAS_RTC #if defined HAS_IF482 && defined HAS_RTC
// setup external interupt for active low RTC INT pin // setup external interupt for active low RTC INT pin

View File

@ -82,9 +82,11 @@
#define RESPONSE_TIMEOUT_MS 60000 // firmware binary server connection timeout [milliseconds] #define RESPONSE_TIMEOUT_MS 60000 // firmware binary server connection timeout [milliseconds]
// settings for syncing time of node and external time sources // settings for syncing time of node and external time sources
#define TIME_SYNC_INTERVAL 60 // sync time each ... minutes with external source [default = 60], comment out means off #define TIME_SYNC_INTERVAL_GPS 5 // sync time each ... minutes with GPS [default = 5], comment out means off
#define TIME_SYNC_INTERVAL_RTC 5 // sync time each ... minutes with RTC [default = 5], comment out means off #define TIME_SYNC_INTERVAL_RTC 5 // sync time each ... minutes with RTC [default = 5], comment out means off
//#define TIME_SYNC_INTERVAL_LORA 60 // sync time each ... minutes with LORA network [default = 60], comment out means off
#define IF482_OFFSET 984 // 1sec minus IF482 serial transmit time [ms]: e.g. 9 bits * 17 bytes * 1/9600 bps = 16ms #define IF482_OFFSET 984 // 1sec minus IF482 serial transmit time [ms]: e.g. 9 bits * 17 bytes * 1/9600 bps = 16ms
// time zone, see https://github.com/JChristensen/Timezone/blob/master/examples/WorldClock/WorldClock.ino // time zone, see https://github.com/JChristensen/Timezone/blob/master/examples/WorldClock/WorldClock.ino
#define DAYLIGHT_TIME {"CEST", Last, Sun, Mar, 2, 120} // Central European Summer Time #define DAYLIGHT_TIME {"CEST", Last, Sun, Mar, 2, 120} // Central European Summer Time
#define STANDARD_TIME {"CET ", Last, Sun, Oct, 3, 60} // Central European Standard Time #define STANDARD_TIME {"CET ", Last, Sun, Oct, 3, 60} // Central European Standard Time

View File

@ -62,11 +62,11 @@ error:
} // rtc_init() } // rtc_init()
int set_rtctime(uint32_t UTCTime) { int set_rtctime(uint32_t t) {
// return = 0 -> error / return = 1 -> success // return = 0 -> error / return = 1 -> success
// block i2c bus access // block i2c bus access
if (I2C_MUTEX_LOCK()) { if (I2C_MUTEX_LOCK()) {
Rtc.SetDateTime(RtcDateTime(UTCTime)); Rtc.SetDateTime(RtcDateTime(t));
I2C_MUTEX_UNLOCK(); // release i2c bus access I2C_MUTEX_UNLOCK(); // release i2c bus access
return 1; return 1;
} }
@ -86,44 +86,20 @@ int set_rtctime(RtcDateTime t) {
time_t get_rtctime(void) { time_t get_rtctime(void) {
// never call now() in this function, this would cause a recursion! // never call now() in this function, this would cause a recursion!
time_t tt = 0; time_t t = 0;
// block i2c bus access // block i2c bus access
if (I2C_MUTEX_LOCK()) { if (I2C_MUTEX_LOCK()) {
if (!Rtc.IsDateTimeValid()) { if (Rtc.IsDateTimeValid()) {
ESP_LOGW(TAG, "RTC has no confident time"); RtcDateTime tt = Rtc.GetDateTime();
t = tt.Epoch32Time();
} else { } else {
RtcDateTime t = Rtc.GetDateTime(); ESP_LOGW(TAG, "RTC has no confident time");
tt = t.Epoch32Time();
} }
I2C_MUTEX_UNLOCK(); // release i2c bus access I2C_MUTEX_UNLOCK(); // release i2c bus access
return tt;
} }
return tt; return t;
} // get_rtctime() } // get_rtctime()
void sync_rtctime(void) {
if (timeStatus() != timeSet) { // do we need time sync?
time_t t = get_rtctime();
if (t) { // have we got a valid time from RTC?
setTime(t);
time_t tt = myTZ.toLocal(t);
ESP_LOGI(TAG, "RTC has set system time to %02d/%02d/%d %02d:%02d:%02d",
month(tt), day(tt), year(tt), hour(tt), minute(tt), second(tt));
} else
ESP_LOGW(TAG, "System time was not synced");
}
#ifdef TIME_SYNC_INTERVAL_RTC
setSyncProvider(&get_rtctime); // does not sync if callback function returns 0
if (timeStatus() != timeSet)
ESP_LOGI("Unable to sync with the RTC");
else
ESP_LOGI("RTC has set the system time");
setSyncInterval(TIME_SYNC_INTERVAL_RTC);
#endif
} // sync_rtctime;
float get_rtctemp(void) { float get_rtctemp(void) {
// block i2c bus access // block i2c bus access
if (I2C_MUTEX_LOCK()) { if (I2C_MUTEX_LOCK()) {
@ -132,6 +108,6 @@ float get_rtctemp(void) {
return temp.AsFloatDegC(); return temp.AsFloatDegC();
} // while } // while
return 0; return 0;
} // get_rtc() } // get_rtctemp()
#endif // HAS_RTC #endif // HAS_RTC