AceTimeClock  1.3.0
Clock classes for Arduino that can synchronize from an NTP server or an RTC chip
All Classes Functions Variables Pages
Public Member Functions | Static Public Member Functions | Static Public Attributes | List of all members
ace_time::clock::NtpClock Class Reference

A Clock that retrieves the time from an NTP server. More...

#include <NtpClock.h>

Inheritance diagram for ace_time::clock::NtpClock:
Inheritance graph
[legend]
Collaboration diagram for ace_time::clock::NtpClock:
Collaboration graph
[legend]

Public Member Functions

 NtpClock (const char *server=kNtpServerName, uint16_t localPort=kLocalPort, uint16_t requestTimeout=kRequestTimeoutMillis)
 Constructor. More...
 
void setup (const char *ssid=nullptr, const char *password=nullptr, uint16_t connectTimeoutMillis=kConnectTimeoutMillis)
 Set up the WiFi connection using the given ssid and password, and prepare the UDP connection. More...
 
const char * getServer () const
 Return the name of the NTP server.
 
bool isSetup () const
 Return true if setup() suceeded.
 
acetime_t getNow () const override
 Return the number of seconds since the AceTime epoch (2000-01-01T00:00:00Z). More...
 
void sendRequest () const override
 Send a time request asynchronously.
 
bool isResponseReady () const override
 Return true if a response is ready.
 
acetime_t readResponse () const override
 Returns number of seconds since AceTime epoch (2000-01-01). More...
 
- 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 setNow (acetime_t)
 Set the time to the indicated seconds. More...
 

Static Public Member Functions

static acetime_t convertNtpSecondsToAceTimeSeconds (uint32_t ntpSeconds)
 Convert an NTP seconds to AceTime seconds relative to the current AceTime epoch defined by Epoch::currentEpochYear(). More...
 

Static Public Attributes

static const char kNtpServerName [] = "us.pool.ntp.org"
 Default NTP Server.
 
static const uint16_t kLocalPort = 2390
 Default port used for UDP packets.
 
static const uint16_t kRequestTimeoutMillis = 1000
 Request time out milliseconds.
 
static const uint16_t kRequestTimeout = kRequestTimeoutMillis
 Deprecated. More...
 
static const uint16_t kConnectTimeoutMillis = 10000
 Number of millis to wait during connect before timing out.
 
- 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

A Clock that retrieves the time from an NTP server.

This class has the deficiency that the DNS name resolver WiFi.hostByName() is a blocking call. So every now and then, it can take 5-6 seconds for the call to return, blocking everything (e.g. display refresh, button clicks) until it times out.

NTP seconds is an unsigned 32-bit integer offset from the NTP epoch of 1900-01-01. It rolls over every 136 years, with the first rollover happening just after 2036-02-07 06:28:15 UTC. Each NTP rollover enters into the next NTP Era. I have seen documentation that says that NTP v4 packets contain the NTP era number but I have yet to find information on how to extract that number. So currently this class ignores the NTP Era from the NTP packet. Instead, the NTP Era is automatically inferred to be the ones that completely span the currently defined AceTime epoch range, as described next.

The AceTime seconds is a signed 32-bit integer with a range of 136 years centered around the Epoch::currentEpochYear(). This class converts NTP seconds to AceTime seconds by mapping the the AceTime seconds range onto the NTP seconds range, straddling any NTP era necessary to meet the AceTime seconds range. For example, for the default AceTime v2 epoch of 2050, the NTP seconds will be interpreted to be from 1982 to 2118, crossing from NTP era 0 to NTP era 1. If the AceTime epoch is changed to 2150, then the NTP seconds will be interpreted to be from 2082 to 2218, crossing from NTP era 1 to NTP era 2.

Warning: If you are using an ESP8266, AND you are using the analogRead() function, calling analogRead() too quickly will cause the WiFi connection to disconnect after 5-10 seconds. Calling NtpClock::setup() will not fix the disconnect. See https://github.com/esp8266/Arduino/issues/1634 and https://github.com/esp8266/Arduino/issues/5083. The solution is to add a slightly delay between calls to analogRead(). I don't know what the minimum value should be, but using a 10ms delay (i.e. no faster than 100 times a second) seems to work for me.

Borrowed from https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/NTPClient/NTPClient.ino and https://github.com/PaulStoffregen/Time/blob/master/examples/TimeNTP/TimeNTP.ino

TODO: Create a version that uses a non-blocking DNS look up.

Definition at line 68 of file NtpClock.h.

Constructor & Destructor Documentation

◆ NtpClock()

ace_time::clock::NtpClock::NtpClock ( const char *  server = kNtpServerName,
uint16_t  localPort = kLocalPort,
uint16_t  requestTimeout = kRequestTimeoutMillis 
)
inlineexplicit

Constructor.

Parameters
servername of the NTP server (default us.pool.ntp.org)
localPortused by the UDP client (default 8888)
requestTimeoutmilliseconds for a request timeout (default 1000)

Definition at line 91 of file NtpClock.h.

Member Function Documentation

◆ convertNtpSecondsToAceTimeSeconds()

acetime_t ace_time::clock::NtpClock::convertNtpSecondsToAceTimeSeconds ( uint32_t  ntpSeconds)
static

Convert an NTP seconds to AceTime seconds relative to the current AceTime epoch defined by Epoch::currentEpochYear().

Since NTP epoch is 1900-01-01 and is due to rollover just after 2036-02-07 06:28:15, this function automatically accounts for the rollover of NTP seconds by shifting the NTP seconds into AceTime seconds using modulo 2^32 unsigned operations.

The result of this function is that it takes the entire 32-bit range of the (signed) AceTime seconds (centered around the currentEpochYear(), and overlays it on top of the (unsigned) NTP seconds time line (with rollovers into new NTP eras every 2^32 seconds), and converts each NTP seconds (regardless of its NTP era) into its corresonding AceTime seconds.

Definition at line 172 of file NtpClock.cpp.

◆ getNow()

acetime_t ace_time::clock::NtpClock::getNow ( ) const
overridevirtual

Return the number of seconds since the AceTime epoch (2000-01-01T00:00:00Z).

Returns kInvalidSeconds if an error has occured.

This is a blocking call. Some clocks (e.g. NTP client) this may take many seconds. On those clocks, use the asynchronous methods (sendRequest(), isResponseReady(), and readResponse()) instead.

Implements ace_time::clock::Clock.

Definition at line 58 of file NtpClock.cpp.

◆ readResponse()

acetime_t ace_time::clock::NtpClock::readResponse ( ) const
overridevirtual

Returns number of seconds since AceTime epoch (2000-01-01).

Return kInvalidSeconds if there is an error. Valid only if isResponseReady() returns true.

Reimplemented from ace_time::clock::Clock.

Definition at line 123 of file NtpClock.cpp.

◆ setup()

void ace_time::clock::NtpClock::setup ( const char *  ssid = nullptr,
const char *  password = nullptr,
uint16_t  connectTimeoutMillis = kConnectTimeoutMillis 
)

Set up the WiFi connection using the given ssid and password, and prepare the UDP connection.

If the WiFi connection was set up elsewhere, you can call the method with no arguments to bypass the WiFi setup.

Parameters
ssidwireless SSID (default nullptr)
passwordpassword of the SSID (default nullptr)
connectTimeoutMillishow long to wait for a WiFi connection (default 10000 ms)

Definition at line 21 of file NtpClock.cpp.

Member Data Documentation

◆ kRequestTimeout

const uint16_t ace_time::clock::NtpClock::kRequestTimeout = kRequestTimeoutMillis
static

Deprecated.

Use kRequestTimeoutMillis instead.

Definition at line 80 of file NtpClock.h.


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