Add NTP update state. Refactoring.
This commit is contained in:
@@ -5,20 +5,32 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "udp_logger.h"
|
#include "udp_logger.h"
|
||||||
|
|
||||||
#define NTP_MAX_UPDATE_TIME_US (500 * 1000) // 500ms max update time
|
typedef enum
|
||||||
|
{
|
||||||
|
NTP_UPDATE_FAILED = 0,
|
||||||
|
NTP_UPDATE_OK = 1,
|
||||||
|
NTP_UPDATE_PENDING = 2,
|
||||||
|
NTP_UPDATE_RETRY_DELAY = 3,
|
||||||
|
NTP_UPDATE_TOO_EARLY = 4,
|
||||||
|
} ntp_update_state;
|
||||||
|
|
||||||
class TimeManager
|
class TimeManager
|
||||||
{
|
{
|
||||||
|
#define NTP_MAX_UPDATE_TIME_US (500 * 1000) // 500ms max update time
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct tm time_info(void);
|
|
||||||
bool ntp_sync_successful(void) const; // was there a NTP sync once?
|
bool ntp_sync_successful(void) const; // was there a NTP sync once?
|
||||||
bool ntp_time_update(bool init = false);
|
ntp_update_state ntp_time_update(bool init = false);
|
||||||
bool ntp_update_failed_prolonged(void) const; // indicates if maximum time since last NTP update was too long
|
bool ntp_update_failed_prolonged(void) const; // indicates if maximum time since last NTP update was too long
|
||||||
void log_time(struct tm time_info) const; // log local_time
|
struct tm time_info(void);
|
||||||
void increment_time_now_local(void);
|
void increment_time_now_local(void);
|
||||||
|
void log_time() const; // log _time_info
|
||||||
|
void log_time(struct tm time_info) const; // log argument time_info
|
||||||
|
|
||||||
int tm_min(void);
|
int tm_min(void);
|
||||||
int tm_hour(void);
|
int tm_hour(void);
|
||||||
|
int tm_day(void);
|
||||||
|
int tm_mon(void);
|
||||||
int tm_year(void);
|
int tm_year(void);
|
||||||
bool tm_isdst(void); // true if summertime
|
bool tm_isdst(void); // true if summertime
|
||||||
|
|
||||||
@@ -30,18 +42,18 @@ public:
|
|||||||
UDPLogger *logger);
|
UDPLogger *logger);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void set_up_ntp(void) const; // set up NTP server
|
void set_up_ntp(void) const; // set up NTP server
|
||||||
void set_up_timer_isr(void) const; // set up timer interrupt
|
void set_up_timer_isr(void) const; // set up timer interrupt
|
||||||
const char *_tz; // timezone
|
const char *_tz; // timezone
|
||||||
const char *_ntp_server; // used ntp server
|
const char *_ntp_server; // used ntp server
|
||||||
UDPLogger *_logger; // logger instance
|
UDPLogger *_logger; // logger instance
|
||||||
struct tm _time_info; // structure tm holds time information
|
struct tm _time_info = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // structure tm holds time information
|
||||||
time_t _time_now_local = 0; // local timer value, updated by timer interrupt and synced by NTP when needed
|
time_t _time_now_local = 0; // local timer value, updated by timer interrupt and synced by NTP when needed
|
||||||
time_t _time_now_ntp = 0; // NTP timer value, seconds since Epoch (1970) - UTC, only synced by NTP request.
|
time_t _time_now_ntp = 0; // NTP timer value, seconds since Epoch (1970) - UTC, only synced by NTP request.
|
||||||
uint32 _ntp_max_offline_time_s; // maximum time in seconds which is considered ok since last NTP update
|
uint32 _ntp_max_offline_time_s; // maximum time in seconds which is considered ok since last NTP update
|
||||||
uint32 _ntp_update_period_s; // NTP request update period in seconds
|
uint32 _ntp_update_period_s; // NTP request update period in seconds
|
||||||
uint32 _ntp_retry_delay_us; // minimum retry delay in us between two NTP requests
|
uint32 _ntp_retry_delay_us; // minimum retry delay in us between two NTP requests
|
||||||
uint32 _ntp_sync_timestamp_us = 0; // timestamp of last successful ntp update
|
uint32 _ntp_sync_timestamp_us = 0; // timestamp of last successful ntp update
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void TimeManager::increment_time_now_local(void)
|
inline void TimeManager::increment_time_now_local(void)
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
// NTP macros
|
// NTP macros
|
||||||
#define BUILD_YEAR (__DATE__ + 7) // Will expand to current year at compile time as string.
|
#define BUILD_YEAR (__DATE__ + 7) // Will expand to current year at compile time as string.
|
||||||
#define NTP_MININUM_RX_YEAR (atoi(BUILD_YEAR) - 1) // Will expand to current year minus one at compile time.
|
#define NTP_MININUM_RX_YEAR (atoi(BUILD_YEAR) - 1) // Will expand to current year minus one at compile time.
|
||||||
#define NTP_MININUM_YEAR (1900) // NTP minimum year is 1900
|
#define NTP_START_YEAR (1900) // NTP minimum year is 1900
|
||||||
#define NTP_UPDATE_PERIOD_S (12 * 3600) // 12h period between updates
|
#define NTP_UPDATE_PERIOD_S (12 * 3600) // 12h period between updates
|
||||||
#define NTP_RETRY_DELAY_US (10 * 1000 * 1000) // 10s retry delay time between failed NTP requests
|
#define NTP_RETRY_DELAY_US (10 * 1000 * 1000) // 10s retry delay time between failed NTP requests
|
||||||
#define NTP_MAX_OFFLINE_TIME_S (7 * 24 * 3600) // Watchdog value, maxmimum offline time before a restart is triggered
|
#define NTP_MAX_OFFLINE_TIME_S (7 * 24 * 3600) // Watchdog value, maxmimum offline time before a restart is triggered
|
||||||
|
|||||||
@@ -41,12 +41,17 @@ bool TimeManager::ntp_sync_successful(void) const
|
|||||||
*
|
*
|
||||||
* @retval true if last update was successful
|
* @retval true if last update was successful
|
||||||
*/
|
*/
|
||||||
bool TimeManager::ntp_time_update(bool init)
|
ntp_update_state TimeManager::ntp_time_update(bool init)
|
||||||
{
|
{
|
||||||
// Check if minimum update delay has elapsed
|
// Check if minimum update delay has elapsed
|
||||||
if (!init && (((system_get_time() - _ntp_sync_timestamp_us) <= _ntp_retry_delay_us) || ((system_get_time() - _ntp_sync_timestamp_us) <= (_ntp_update_period_s * 1000000))))
|
if (!init && ((system_get_time() - _ntp_sync_timestamp_us) <= _ntp_retry_delay_us))
|
||||||
{
|
{
|
||||||
return false;
|
return NTP_UPDATE_RETRY_DELAY; // could be replaced with appropriate enum
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!init && ((system_get_time() - _ntp_sync_timestamp_us) <= (_ntp_update_period_s * 1000000)))
|
||||||
|
{
|
||||||
|
return NTP_UPDATE_TOO_EARLY; // could be replaced with appropriate enum
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init)
|
if (init)
|
||||||
@@ -54,8 +59,8 @@ bool TimeManager::ntp_time_update(bool init)
|
|||||||
set_up_ntp(); // set up NTP server once
|
set_up_ntp(); // set up NTP server once
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ntp_update_successful = false; // NTP time update
|
ntp_update_state ntp_update_state = NTP_UPDATE_PENDING; // NTP time update
|
||||||
struct tm time_info; // local NTP time info
|
struct tm time_info; // local NTP time info
|
||||||
|
|
||||||
_ntp_sync_timestamp_us = system_get_time(); // NTP update start time
|
_ntp_sync_timestamp_us = system_get_time(); // NTP update start time
|
||||||
|
|
||||||
@@ -65,15 +70,15 @@ bool TimeManager::ntp_time_update(bool init)
|
|||||||
localtime_r(&_time_now_ntp, &time_info); // convert time
|
localtime_r(&_time_now_ntp, &time_info); // convert time
|
||||||
yield(); // since this loop could take up to NTP_MAX_UPDATE_TIME_US
|
yield(); // since this loop could take up to NTP_MAX_UPDATE_TIME_US
|
||||||
|
|
||||||
} while (((system_get_time() - _ntp_sync_timestamp_us) <= NTP_MAX_UPDATE_TIME_US) && (time_info.tm_year < (NTP_MININUM_RX_YEAR - NTP_MININUM_YEAR)));
|
} while (((system_get_time() - _ntp_sync_timestamp_us) <= NTP_MAX_UPDATE_TIME_US) && (time_info.tm_year < (NTP_MININUM_RX_YEAR - NTP_START_YEAR)));
|
||||||
|
|
||||||
ntp_update_successful = (time_info.tm_year <= (NTP_MININUM_RX_YEAR - NTP_MININUM_YEAR)) ? false : true; // sanity check
|
ntp_update_state = (time_info.tm_year <= (NTP_MININUM_RX_YEAR - NTP_START_YEAR)) ? NTP_UPDATE_FAILED : NTP_UPDATE_OK; // sanity check
|
||||||
|
|
||||||
if (ntp_update_successful == true)
|
if (ntp_update_state == NTP_UPDATE_OK)
|
||||||
{
|
{
|
||||||
_ntp_sync_timestamp_us = system_get_time(); // save NTP update timestamp
|
_ntp_sync_timestamp_us = system_get_time(); // save NTP update timestamp
|
||||||
_time_info = time_info; // take over time_info to member variable
|
_time_info = time_info; // take over time_info to member variable
|
||||||
log_time(_time_info); // log current time
|
log_time(); // log current time
|
||||||
|
|
||||||
if (!init && (abs(_time_now_ntp - _time_now_local) > 10)) // in the case that the local time drifted more than 10s in _ntp_update_period_s
|
if (!init && (abs(_time_now_ntp - _time_now_local) > 10)) // in the case that the local time drifted more than 10s in _ntp_update_period_s
|
||||||
{
|
{
|
||||||
@@ -93,7 +98,7 @@ bool TimeManager::ntp_time_update(bool init)
|
|||||||
logger.log_string("NTP-Update was not successful. Retrying in " + String(_ntp_retry_delay_us / 1000) + "ms.\n");
|
logger.log_string("NTP-Update was not successful. Retrying in " + String(_ntp_retry_delay_us / 1000) + "ms.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ntp_update_successful;
|
return ntp_update_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TimeManager::ntp_update_failed_prolonged(void) const
|
bool TimeManager::ntp_update_failed_prolonged(void) const
|
||||||
@@ -113,10 +118,22 @@ int TimeManager::tm_hour(void)
|
|||||||
return _time_info.tm_hour;
|
return _time_info.tm_hour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TimeManager::tm_day(void)
|
||||||
|
{
|
||||||
|
localtime_r(&_time_now_local, &_time_info); // convert time
|
||||||
|
return _time_info.tm_mday + 1; // add 1 to get actual day
|
||||||
|
}
|
||||||
|
|
||||||
int TimeManager::tm_year(void)
|
int TimeManager::tm_year(void)
|
||||||
{
|
{
|
||||||
localtime_r(&_time_now_local, &_time_info); // convert time
|
localtime_r(&_time_now_local, &_time_info); // convert time
|
||||||
return _time_info.tm_year;
|
return _time_info.tm_year + NTP_START_YEAR; // add start year to get actual year
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimeManager::tm_mon(void)
|
||||||
|
{
|
||||||
|
localtime_r(&_time_now_local, &_time_info); // convert time
|
||||||
|
return _time_info.tm_mon + 1; // add 1 to get actual month
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TimeManager::tm_isdst(void)
|
bool TimeManager::tm_isdst(void)
|
||||||
@@ -125,7 +142,10 @@ bool TimeManager::tm_isdst(void)
|
|||||||
return _time_info.tm_isdst > 0;
|
return _time_info.tm_isdst > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
/**
|
||||||
|
* @brief Sets up the timer ISR
|
||||||
|
*
|
||||||
|
*/
|
||||||
void TimeManager::set_up_timer_isr(void) const
|
void TimeManager::set_up_timer_isr(void) const
|
||||||
{
|
{
|
||||||
// set up timer interrupt after NTP update is done
|
// set up timer interrupt after NTP update is done
|
||||||
@@ -139,6 +159,10 @@ void TimeManager::set_up_timer_isr(void) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets up the NTP server config
|
||||||
|
*
|
||||||
|
*/
|
||||||
void TimeManager::set_up_ntp(void) const
|
void TimeManager::set_up_ntp(void) const
|
||||||
{
|
{
|
||||||
if ((_tz != nullptr) && (_ntp_server != nullptr))
|
if ((_tz != nullptr) && (_ntp_server != nullptr))
|
||||||
@@ -153,6 +177,16 @@ void TimeManager::set_up_ntp(void) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Log time_info as string.
|
||||||
|
*
|
||||||
|
* @param local_time
|
||||||
|
*/
|
||||||
|
void TimeManager::log_time() const
|
||||||
|
{
|
||||||
|
log_time(_time_info);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Log time_info as string.
|
* @brief Log time_info as string.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ void setup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get initial time
|
// get initial time
|
||||||
if (tm_mgr.ntp_time_update(true))
|
if (tm_mgr.ntp_time_update(true) == NTP_UPDATE_OK)
|
||||||
{
|
{
|
||||||
// show the current time for short time in words
|
// show the current time for short time in words
|
||||||
String timeMessage = time_to_string(tm_mgr.tm_hour(), tm_mgr.tm_min());
|
String timeMessage = time_to_string(tm_mgr.tm_hour(), tm_mgr.tm_min());
|
||||||
@@ -251,6 +251,9 @@ void loop()
|
|||||||
if ((current_time_us - last_heartbeat_us) >= PERIOD_HEARTBEAT_US)
|
if ((current_time_us - last_heartbeat_us) >= PERIOD_HEARTBEAT_US)
|
||||||
{
|
{
|
||||||
send_heartbeat(); // send heartbeat update
|
send_heartbeat(); // send heartbeat update
|
||||||
|
|
||||||
|
tm_mgr.log_time(); // TODO rm
|
||||||
|
|
||||||
last_heartbeat_us = system_get_time();
|
last_heartbeat_us = system_get_time();
|
||||||
delay(10);
|
delay(10);
|
||||||
}
|
}
|
||||||
@@ -282,11 +285,11 @@ void loop()
|
|||||||
{
|
{
|
||||||
if (tm_mgr.ntp_sync_successful() == true) // regular case
|
if (tm_mgr.ntp_sync_successful() == true) // regular case
|
||||||
{
|
{
|
||||||
tm_mgr.ntp_time_update(); // NTP time update
|
(void)tm_mgr.ntp_time_update(); // NTP time update
|
||||||
}
|
}
|
||||||
else // if there was never a NTP time update before (set up failed)
|
else // if there was never a NTP time update before (set up failed)
|
||||||
{
|
{
|
||||||
tm_mgr.ntp_time_update(true); // NTP time update with init!
|
(void)tm_mgr.ntp_time_update(true); // NTP time update with init!
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tm_mgr.ntp_update_failed_prolonged() == true)
|
if (tm_mgr.ntp_update_failed_prolonged() == true)
|
||||||
|
|||||||
Reference in New Issue
Block a user