/*
# ============================================
# code is placed under the MIT license
# Copyright (c) 2024 J-M-L
# For the Arduino Forum : https://forum.arduino.cc/u/j-m-l
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# ===============================================
*/
#include <WiFi.h>
#include <esp_sntp.h>
const char *ssid = "Wokwi-GUEST";
const char *wifiPassword = "";
// Array of NTP servers
const char *ntpServers[] = {
"time.apple.com", // Apple
"time.google.com", // Google
"time.windows.com", // Microsoft
"pool.ntp.org", // NTP Pool Project
"time.nist.gov", // NIST
"time.cloudflare.com", // Cloudflare
"ntp.ubuntu.com", // Ubuntu
};
const size_t numNtpServers = sizeof ntpServers / sizeof *ntpServers;
bool syncCompleted = false;
bool wifiConnected = false;
size_t currentServerIndex = 0;
unsigned long syncStartTime = 0;
const unsigned long maxSyncWait = 10000; // Max time to wait for each server in ms
void onNTPTimeSync(struct timeval *tv) {
syncCompleted = true;
time_t lastNtpSync = time(NULL);
struct tm *pTime = localtime(&lastNtpSync);
Serial.print("NTP synchronized with ");
Serial.println(ntpServers[currentServerIndex]);
Serial.println(pTime, "%d/%m/%Y %H:%M:%S");
}
void onWiFiStationConnected(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.println("...Network connection established");
}
void syncWithCurrentServer() {
Serial.print("Trying NTP server: ");
Serial.println(ntpServers[currentServerIndex]);
// Configure NTP server and timezone (here configigured for France)
configTzTime("CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00", ntpServers[currentServerIndex]);
// Set the NTP time sync callback
sntp_set_time_sync_notification_cb(onNTPTimeSync);
syncCompleted = false;
syncStartTime = millis();
}
void onWiFiStationGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.print("Obtained IP address = ");
Serial.println(WiFi.localIP());
wifiConnected = true;
syncWithCurrentServer(); // Start syncing with the first server
}
void onWiFiStationDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
wifiConnected = false;
Serial.print("Network disconnected. (reason: ");
Serial.println(info.wifi_sta_disconnected.reason);
Serial.println(")\nAttempting to reconnect.");
WiFi.begin(ssid, wifiPassword, 6); // use 6 for wokwi, not needed on physical hardware
}
void requestFromNextServer() {
if (++currentServerIndex >= numNtpServers) {
Serial.println("All NTP servers have been tried. Cycling through.");
currentServerIndex = 0;
}
syncWithCurrentServer();
}
void setup() {
Serial.begin(115200);
Serial.println("NTP time management demonstration");
Serial.println("Connecting to WiFi network");
WiFi.onEvent(onWiFiStationConnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_CONNECTED);
WiFi.onEvent(onWiFiStationGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
WiFi.onEvent(onWiFiStationDisconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
WiFi.begin(ssid, wifiPassword, 6);
}
void loop() {
if (wifiConnected) {
if (syncCompleted) {
delay(1000); // Wait for 1 second before trying the next server
requestFromNextServer();
}
} else {
// Check if we have timed out waiting for sync
if (millis() - syncStartTime >= maxSyncWait) {
Serial.print("Failed to sync with ");
Serial.println(ntpServers[currentServerIndex]);
requestFromNextServer();
}
}
}