AceTimeClock  1.3.0
Clock classes for Arduino that can synchronize from an NTP server or an RTC chip
Public Member Functions | Protected Member Functions | Friends | List of all members
ace_time::clock::SystemClockLoopTemplate< T_SCCI > Class Template Reference

A subclass of SystemClock that sync with its mReferenceClock using the non-blocking Clock API of the referenceClock. More...

#include <SystemClockLoop.h>

Inheritance diagram for ace_time::clock::SystemClockLoopTemplate< T_SCCI >:
Inheritance graph
[legend]
Collaboration diagram for ace_time::clock::SystemClockLoopTemplate< T_SCCI >:
Collaboration graph
[legend]

Public Member Functions

 SystemClockLoopTemplate (Clock *referenceClock, Clock *backupClock, uint16_t syncPeriodSeconds=3600, uint16_t initialSyncPeriodSeconds=5, uint16_t requestTimeoutMillis=1000, ace_common::TimingStats *timingStats=nullptr)
 Constructor. More...
 
void loop ()
 Make a request to the referenceClock every syncPeriodSeconds seconds. More...
 
- Public Member Functions inherited from ace_time::clock::SystemClockTemplate< T_SCCI >
void setup ()
 Attempt to retrieve the time from the backupClock if it exists.
 
acetime_t getNow () const override
 Return the number of seconds since the AceTime epoch (2000-01-01T00:00:00Z). More...
 
void setNow (acetime_t epochSeconds) override
 Set the time to the indicated seconds. More...
 
void forceSync ()
 Manually force a sync with the referenceClock if it exists. More...
 
acetime_t getLastSyncTime () const
 Return the time (seconds since Epoch) of the last successful syncNow() call. More...
 
uint8_t getSyncStatusCode () const
 Get sync status code.
 
int32_t getSecondsSinceSyncAttempt () const
 Return the number of seconds since the previous sync attempt, successful or not. More...
 
int32_t getSecondsToSyncAttempt () const
 Return the number of seconds until the next syncNow() attempt. More...
 
int16_t getClockSkew () const
 Difference between this clock compared to reference at last sync. More...
 
bool isInit () const
 Return true if initialized by setNow() or syncNow().
 
- Public Member Functions inherited from ace_time::clock::Clock
 Clock ()=default
 Default constructor.
 
 ~Clock ()=default
 We deliberately avoid using a virtual destructor. More...
 
virtual void sendRequest () const
 Send a time request asynchronously.
 
virtual bool isResponseReady () const
 Return true if a response is ready.
 
virtual acetime_t readResponse () const
 Returns number of seconds since AceTime epoch (2000-01-01). More...
 

Protected Member Functions

 SystemClockLoopTemplate ()
 Empty constructor used for testing.
 
 SystemClockLoopTemplate (const SystemClockLoopTemplate &)=delete
 
SystemClockLoopTemplateoperator= (const SystemClockLoopTemplate &)=delete
 
- Protected Member Functions inherited from ace_time::clock::SystemClockTemplate< T_SCCI >
 SystemClockTemplate (const SystemClockTemplate &)=delete
 
 SystemClockTemplate (Clock *referenceClock, Clock *backupClock)
 Constructor. More...
 
 SystemClockTemplate ()
 Empty constructor primarily for tests. More...
 
SystemClockTemplateoperator= (const SystemClockTemplate &)=delete
 
void initSystemClock (Clock *referenceClock, Clock *backupClock)
 Same as constructor but allows delayed initialization, e.g. More...
 
ClockgetReferenceClock () const
 Get referenceClock.
 
unsigned long clockMillis () const
 Return the Arduino millis(). More...
 
void keepAlive ()
 Call this (or getNow() every 65.535 seconds or faster to keep the internal counter in sync with millis(). More...
 
void backupNow (acetime_t nowSeconds)
 Write the nowSeconds to the backupClock (which can be an RTC that has non-volatile memory). More...
 
void syncNow (acetime_t epochSeconds)
 Set the current mEpochSeconds to the given epochSeconds. More...
 
void setNextSyncAttemptMillis (uint32_t ms)
 Set the millis to next sync attempt.
 
void setPrevSyncAttemptMillis (uint32_t ms)
 Set the millis of prev sync attempt.
 
void setSyncStatusCode (uint8_t code)
 Set the status code of most recent sync attempt.
 

Friends

class ::SystemClockLoopTest
 
class ::SystemClockLoopTest_loop
 
class ::SystemClockLoopTest_syncNow
 
class ::SystemClockLoopTest_setup
 
class ::SystemClockLoopTest_backupNow
 
class ::SystemClockLoopTest_getNow
 

Additional Inherited Members

- Static Public Attributes inherited from ace_time::clock::SystemClockTemplate< T_SCCI >
static const uint8_t kSyncStatusOk
 Sync was successful.
 
static const uint8_t kSyncStatusError
 Sync request failed.
 
static const uint8_t kSyncStatusTimedOut
 Sync request timed out.
 
static const uint8_t kSyncStatusUnknown
 Sync was never done.
 
- Static Public Attributes inherited from ace_time::clock::Clock
static const acetime_t kInvalidSeconds = LocalTime::kInvalidSeconds
 Error value returned by getNow() and other methods when this object is not yet initialized.
 

Detailed Description

template<typename T_SCCI>
class ace_time::clock::SystemClockLoopTemplate< T_SCCI >

A subclass of SystemClock that sync with its mReferenceClock using the non-blocking Clock API of the referenceClock.

This is helpful when the referenceClock issues a network request to an NTP server. The SystemClockLoop::loop() function should be called from the global loop() function.

Syncing occurs at initialSyncPeriodSeconds interval, until the first successful sync, then subsequent syncing occurs at syncPeriodSeconds interval. Initial syncing implements an exponential backoff when the sync request fails, increasing from initialSyncPeriodSeconds to until a maximum of syncPeriodSeconds.

Initially, SystemClockLoop used the blocking API of Clock, and SystemClockCoroutine used the non-blocking API. That meant that SystemClockCoroutine was better suited for referenceClocks that could block for a long time (e.g. NtpClock). at some point however, SystemClockLoop was converted to use the non-blocking API as well, so the two classes are now functionally equivalent. I keep around the SystemClockCoroutine class because I find the code easier to understand. But for the end-users of the library, they are equivalent.

Template Parameters
T_SCCIthe SystemClock ClockInterface

Definition at line 48 of file SystemClockLoop.h.

Constructor & Destructor Documentation

◆ SystemClockLoopTemplate()

template<typename T_SCCI >
ace_time::clock::SystemClockLoopTemplate< T_SCCI >::SystemClockLoopTemplate ( Clock referenceClock,
Clock backupClock,
uint16_t  syncPeriodSeconds = 3600,
uint16_t  initialSyncPeriodSeconds = 5,
uint16_t  requestTimeoutMillis = 1000,
ace_common::TimingStats *  timingStats = nullptr 
)
inlineexplicit

Constructor.

Parameters
referenceClockThe authoritative source of the time. If this is null, the object relies just on clockMillis() and the user to set the proper time using setNow().
backupClockAn RTC chip which continues to keep time even when power is lost. Can be null.
syncPeriodSecondsseconds between normal sync attempts (default 3600)
initialSyncPeriodSecondsseconds between sync attempts when the systemClock is not initialized (default 5), exponentially increasing (2X) at each attempt until syncPeriodSeconds is reached
requestTimeoutMillisnumber of milliseconds before the request to referenceClock times out
timingStatsinternal statistics (nullable)

Definition at line 67 of file SystemClockLoop.h.

Member Function Documentation

◆ loop()

template<typename T_SCCI >
void ace_time::clock::SystemClockLoopTemplate< T_SCCI >::loop ( )
inline

Make a request to the referenceClock every syncPeriodSeconds seconds.

Wait for the request, then set the SystemClock (the parent class) to the time returned by the referenceClock. If the referenceClock returns an error, implement a retry algorithm with an exponential backoff, until a maximum of syncPeriodSeconds interval is reached.

This method should be called from the global loop() method.

Definition at line 89 of file SystemClockLoop.h.


The documentation for this class was generated from the following file: