PaulStoffregen / Time

Time library for Arduino
http://playground.arduino.cc/code/time
1.24k stars 665 forks source link

Update for non-blocking SyncProvider function #130

Open gfvalvo opened 5 years ago

gfvalvo commented 5 years ago

The proposed changes will allow for low-latency, non-blocking code to be used in the user’s SyncProvider function. The specific application in mind is when the sync is provided via NTP since there's an unknown and variable delay between sending the NTP request and getting a response. Two optional parameters are added to the setSyncProvider function prototype:

void setSyncProvider(getExternalTime getTimeFunction, bool immedRetry = false, bool wait = false);

immedRetry -- when true, instructs the ‘now()’ function not to update ‘nextSyncTime’ if the user’s SyncProvider function returns ‘0’.

wait -- when, true forces setSyncProvider() to wait for valid synchronization.

With this new version, now() will call the user’s SyncProvider function, assuming the nextSyncTimecondition is satisfied, just like previously. However, if that function returns '0' and immedRetryis true, then now() will not update nextSyncTime. So, each subsequent call to now() will also call the user’s SyncProvider function until it returns a valid time. The idea is for the SyncProvider function to be non-blocking and quickly return either '0' or the valid time. For example, a SyncProvider function based on NTP would simply send the NTP request packet and return '0' the first time it's called. On each subsequent call it would do one of three things:

  1. Receive a valid NTP packet, reset itself to send another NTP request packet the next time it is called, and return the time.
  2. Recognize that a packet has not yet been received and immediately return ‘0’.
  3. Time out, reset itself to send another NTP request packet the next time it is called, and return ‘0’.

Only when Case #1 happens will now() update nextSyncTime to be syncInterval seconds in the future. This will halt the continual calls to the user’s SyncProvider function for syncInterval seconds.

The waitargument instructs setSyncProvider() to continually call the user’s SyncProvider function and not return to user code until a valid time is set. This is needed because of the non-blocking SyncProvider function behavior described above.

To maintain backwards compatibility for existing applications the immedRetry and wait arguments can be omitted from the call to setSyncProvider(). In this case, the library will behave exactly the same as before.

An updated 'TimeNTP_ESP8266WiFi.ino' example is included to demonstrate the new technique.