6 #ifndef ACE_TIME_NTP_CLOCK_H 7 #define ACE_TIME_NTP_CLOCK_H 9 #if defined(ESP8266) || defined(ESP32) 13 #include <ESP8266WiFi.h> 18 #include "../common/logging.h" 21 extern "C" unsigned long millis();
23 #ifndef ACE_TIME_NTP_CLOCK_DEBUG 24 #define ACE_TIME_NTP_CLOCK_DEBUG 0 43 class NtpClock:
public Clock {
46 static const char kNtpServerName[];
49 static const uint16_t kLocalPort = 8888;
52 static const uint16_t kRequestTimeout = 1000;
63 const char* server = kNtpServerName,
64 uint16_t localPort = kLocalPort,
65 uint16_t requestTimeout = kRequestTimeout):
67 mLocalPort(localPort),
68 mRequestTimeout(requestTimeout) {}
71 void setup(
const char* ssid,
const char* password) {
72 uint16_t startMillis = millis();
73 WiFi.begin(ssid, password);
74 while (WiFi.status() != WL_CONNECTED) {
75 uint16_t elapsedMillis = millis() - startMillis;
76 if (elapsedMillis >= kConnectTimeoutMillis) {
84 mUdp.begin(mLocalPort);
86 #if ACE_TIME_NTP_CLOCK_DEBUG == 1 88 SERIAL_PORT_MONITOR.print(F(
"Local port: "));
89 SERIAL_PORT_MONITOR.println(mUdp.localPort());
96 const char* getServer()
const {
return mServer; }
98 bool isSetup()
const {
return mIsSetUp; }
100 acetime_t getNow()
const override {
101 if (!mIsSetUp)
return kInvalidSeconds;
105 uint16_t startTime = millis();
106 while ((uint16_t) (millis() - startTime) < mRequestTimeout) {
107 if (isResponseReady()) {
108 return readResponse();
111 return kInvalidSeconds;
114 void sendRequest()
const override {
115 if (!mIsSetUp)
return;
118 while (mUdp.parsePacket() > 0) {}
127 IPAddress ntpServerIP;
128 WiFi.hostByName(mServer, ntpServerIP);
129 sendNtpPacket(ntpServerIP);
132 bool isResponseReady()
const override {
133 if (!mIsSetUp)
return false;
134 return mUdp.parsePacket() >= kNtpPacketSize;
137 acetime_t readResponse()
const override {
138 if (!mIsSetUp)
return kInvalidSeconds;
141 mUdp.read(mPacketBuffer, kNtpPacketSize);
144 uint32_t secsSince1900 = (uint32_t) mPacketBuffer[40] << 24;
145 secsSince1900 |= (uint32_t) mPacketBuffer[41] << 16;
146 secsSince1900 |= (uint32_t) mPacketBuffer[42] << 8;
147 secsSince1900 |= (uint32_t) mPacketBuffer[43];
149 return (secsSince1900 == 0)
151 : secsSince1900 - kSecondsSinceNtpEpoch;
156 static const uint8_t kNtpPacketSize = 48;
162 static const uint32_t kSecondsSinceNtpEpoch = 3155673600;
165 static const uint16_t kConnectTimeoutMillis = 5000;
168 void sendNtpPacket(
const IPAddress& address)
const {
169 #if ACE_TIME_NTP_CLOCK_DEBUG == 1 170 uint16_t startTime = millis();
173 memset(mPacketBuffer, 0, kNtpPacketSize);
176 mPacketBuffer[0] = 0b11100011;
177 mPacketBuffer[1] = 0;
178 mPacketBuffer[2] = 6;
179 mPacketBuffer[3] = 0xEC;
181 mPacketBuffer[12] = 49;
182 mPacketBuffer[13] = 0x4E;
183 mPacketBuffer[14] = 49;
184 mPacketBuffer[15] = 52;
187 mUdp.beginPacket(address, 123);
188 mUdp.write(mPacketBuffer, kNtpPacketSize);
190 #if ACE_TIME_NTP_CLOCK_DEBUG == 1 191 logging::println(
"NtpClock::sendNtpPacket(): %u ms",
192 (uint16_t) (millis() - startTime));
196 const char*
const mServer;
197 uint16_t
const mLocalPort;
198 uint16_t
const mRequestTimeout;
200 mutable WiFiUDP mUdp;
202 mutable uint8_t mPacketBuffer[kNtpPacketSize];
203 bool mIsSetUp =
false;
209 #endif // defined(ESP8266) || defined(ESP32)