Introduction: WiFiTimeManager - Arduino IDE ESP32 Time Library

A favorite hobbyist project is some version of a digital clock. Common requirements for such a clock are:

  • Ability to keep accurate time through power cycles.
  • Ability to automatically handle DST time changes without human intervention.

Of course, many other projects rely on these requirements as well.

The WiFiTimeManger library for the ESP32 handles these requirements in a generic way that may find use in many projects that need accurate time keeping. It provides the following features:

  • Specify WiFi credentials via web page. No need to re-build software to change WiFi credentials.
  • Selectable timezone via the Setup web page.
  • Selectable use of daylight savings time (DST) or not.
  • Selectable DST start and end information via the Setup web page.
  • Select and automatically connect to a specified network time protocol (NTP) server to keep accurate time.
  • Easily add additional fields to the Setup web page.
  • Easily integrate real time clock (RTC) hardware to allow for accurate time keeping even when not connected to an NTP server.
  • Easily fetch accurate UTC or local time.

WiFiTimeManager builds upon tzapu's WiFiManager library which is a WiFi Connection manager with fallback web configuration portal. It works with the ESP32 Arduino platform, and has been tested with the Adafruit Feather Huzzah 32 board. Latest code, documentation, and examples can be found at the WiFiTimeManager github site.

Supplies

Step 1: Install the WiFiTimeManager Library

WiFiTimeManager must be installed into the Arduino IDE manually. This process is well documented HERE. Other libraries that are needed to support WiFiTimeManager are:

Step 2: Basic Use

This section describes the minimum sketch required to use WiFiTimeManager. It uses the default blocking mode. This mode attempts to connect to a WiFi network at startup, and blocks until such a connection is made. See the Examples for code using the non-blocking mode and other advanced features.

The sketch must include the WiFiTimeManager class header file. Note that it is not necessary to include the WiFiManager.h file since WiFiTimeManager already includes it:

#include "WiFiTimeManager.h" // Manages timezone, DST, and NTP.


The WiFiTimeManager class is implemented as a singleton. Its static Instance() method must be called at least once to create the singleton and fetch a pointer to it. The Instance() method may be called in as many places as needed.

// Point to the WiFiTimeManager singleton instance.
WiFiTimeManager *pWtm = WiFiTimeManager::Instance();


The WiFiTimeManager must be initialized via a call to Init(). By default, Init() will set the WiFiManager configuration portal to use blocking mode, and will default to the dark theme. Init() takes three arguments as described below.

  • The first argument points to a NULL terminated character string representing the name for the network Access Point (AP) that will be created.
  • The second argument is optional, and points to a NULL terminated character string representing the password to be used in accessing the AP. If not supplied, the AP will not require a password. If used, the password should be 8 to 63 characters.
  • The third argument is optional, and specifies whether a separate 'Setup' button will appear on the WiFiTimeManager home page. If set to true, then a separate 'Setup' button will be displayed. If set to false, the timezone, DST, and NTP fields will reside below the WiFi credentials on the 'Configure WiFi' page. This argument defaults to a value of true.
// Initialize with our AP name and button selections.
pWtm->Init("AP_NAME", "AP_PASSWORD", true);


Finally, the WiFiTimeManager must connect to the WiFi via the autoConnect() method. The AP name and password that were supplied in the call to Init() are used.

// Attempt to connect with our AP name, and password (supplied via Init()).
pWtm->autoConnect();


With this minimal code, when the ESP32 starts it will try to connect to the WiFi. If it fails, it will start in Access Point (AP) mode. While in AP mode, its web page may be accessed via an IP address of 192.146.4.1. Selecting the 'Setup' button of the web page will allow the user to set timezone, DST, and NTP parameters for the local area. Selecting the 'Configure WiFi' button allows for setting credentials for the local WiFi network. The 'Setup' page should be updated and saved before the 'Configure WiFi' page since once the WiFi credentials are configured, AP mode is disabled.

Step 3: Non-Blocking Mode

Blocking mode may be fine for many applications. However, it is often necessary to continue normal operation, even if a WiFi connection cannot be established. This is where non-blocking mode comes in handy. While using non-blocking mode, autoConnect() will return after a specified timeout even if not yet connected to WiFi. In this case, the Access Point is still active providing web access to the 'Configure WiFi' and Setup web pages. A skeleton of code that is used to implement non-blocking mode is as follows:

// Arduino setup().
void setup()
{
. . .
// Point to the WiFiTimeManager instance.
WiFiTimeManager *pWtm = WiFiTimeManager::Instance();
. . .
// Initialize the WiFiTimeManager.
pWtm->Init(AP_NAME, AP_PWD, SETUP_BUTTON);
. . .
// Set to non-blocking mode with a 10 second timeout.
pWtm->setConfigPortalBlocking(false);
pWtm->setConfigPortalTimeout(10);
. . .
// Try to connect to WiFi. Return after timeout if not connected.
pWtm->autoConnect();
. . .
}

// Arduino loop().
void loop()
{
. . .
// Point to the WiFiTimeManager instance.
WiFiTimeManager *pWtm = WiFiTimeManager::Instance();
. . .
pWtm->process();
. . .
delay(1);
}


Note that the major code differences between blocking mode and non-blocking mode are:

  • setConfigPortalBlocking(false) must be called before autoConnect() to set non-blocking mode.
  • setConfigPortalTimeout() may be called to set a timeout, in seconds. It specifies how long to wait for a WiFi connection.
  • process() must be called periodically, usually from the Arduino loop() function. This allows for handling of the config portal. See the NonBlocking, EditWebPage, or RTCExample for use of the non-blocking mode.

Step 4: User Setup Parameters

As shown above, WiFiTimeManager provides built-in parameters to specify the timezone, DST start and end, and NTP server address and port. This will be sufficient for most applications. However, WiFiTimeManager supplies an easy method for users to add user specified parameters as needed. The WebPages.h file contains the long NULL terminated string that is used to create the Setup page of the config portal. This string contains several comments at strategic points that may be used to insert HTML or JavaScript code. These points are:

  • "<!-- HTML START -->"

This marks the start of HTML, which is also the start of the web page string.

  • "<!-- HTML END -->"

This marks the end of HTML and is just before the end of the web page body.

  • "// JS START"

This marks the start of the JavaScript, just after the <script> declaration.

  • "// JS ONLOAD"

This marks a spot within the onload() JavaScript function where JavaScript initialization code can be added.

  • "// JS SAVE"

This marks a spot within the function that is executed when the submit (Save) button is pressed. It can be used to perform JavaScript save actions.

  • "// JS END"

This marks the end of of the JavaScript, just before the </script> declaration.


Two methods are used to support user parameters:

  • SetUpdateWebPageCallback() allows the user to set a callback that gets called when the Setup page is being updated. The called back function my insert code at any or all of the strategic comments listed above to support the new user parameter. See SetUpdateWebPageCallback() on the github page and the EditWebPage example for more information.
  • setSaveParamsCallback() allows the user to read the value(s) of any added parameter(s). The called back function is invoked after the user clicks the Save button of the Setup page. See setSaveParamsCallback() on the github page and the EditWebPage example for more information.

Step 5: Examples

Several well commented examples are provided:

  • Blocking.ino is an example of simple blocking mode.
  • NonBlocking.ino is an example of simple non-blocking mode.
  • EditWebPage.ino is an example of adding a simple user parameter to the Setup web page.
  • RTCExample.ino is an example of using a RTC with WiFiTimeManager.

Step 6: Conclusion

WiFiTimeManager provides an easy to use solution to setting up local time information on an ESP32 project. It may be used with minimal change on ESP8266 projects, but has not been tested.

See the WiFiTimeManager github repository for additional documentation and latest files.