Skip to content

Commit b8b7c0e

Browse files
committed
Added NTPClient to the project to fix an upstream bug
Commit from upstream: https://github.com/arduino-libraries/NTPClient/tree/61684d4516839b579b81105be3447499c1417908 This is version 3.2.1 of the library.
1 parent faa5735 commit b8b7c0e

File tree

8 files changed

+437
-0
lines changed

8 files changed

+437
-0
lines changed

firmware/lib/NTPClient/.clang-format

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
DisableFormat: true,
3+
SortIncludes: Never
4+
}

firmware/lib/NTPClient/.codespellrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# See: https://github.com/codespell-project/codespell#using-a-config-file
2+
[codespell]
3+
# In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here:
4+
ignore-words-list = ,
5+
check-filenames =
6+
check-hidden =
7+
skip = ./.git

firmware/lib/NTPClient/CHANGELOG

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
NTPClient 3.1.0 - 2016.05.31
2+
3+
* Added functions for changing the timeOffset and updateInterval later. Thanks @SirUli
4+
5+
NTPClient 3.0.0 - 2016.04.19
6+
7+
* Constructors now require UDP instance argument, to add support for non-ESP8266 boards
8+
* Added optional begin API to override default local port
9+
* Added end API to close UDP socket
10+
* Changed return type of update and forceUpdate APIs to bool, and return success or failure
11+
* Change return type of getDay, getHours, getMinutes, and getSeconds to int
12+
13+
Older
14+
15+
* Changes not recorded

firmware/lib/NTPClient/NTPClient.cpp

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/**
2+
* The MIT License (MIT)
3+
* Copyright (c) 2015 by Fabrice Weinberg
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
* SOFTWARE.
20+
*/
21+
22+
#include "NTPClient.h"
23+
24+
NTPClient::NTPClient(UDP& udp) {
25+
this->_udp = &udp;
26+
}
27+
28+
NTPClient::NTPClient(UDP& udp, long timeOffset) {
29+
this->_udp = &udp;
30+
this->_timeOffset = timeOffset;
31+
}
32+
33+
NTPClient::NTPClient(UDP& udp, const char* poolServerName) {
34+
this->_udp = &udp;
35+
this->_poolServerName = poolServerName;
36+
}
37+
38+
NTPClient::NTPClient(UDP& udp, IPAddress poolServerIP) {
39+
this->_udp = &udp;
40+
this->_poolServerIP = poolServerIP;
41+
this->_poolServerName = NULL;
42+
}
43+
44+
NTPClient::NTPClient(UDP& udp, const char* poolServerName, long timeOffset) {
45+
this->_udp = &udp;
46+
this->_timeOffset = timeOffset;
47+
this->_poolServerName = poolServerName;
48+
}
49+
50+
NTPClient::NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset){
51+
this->_udp = &udp;
52+
this->_timeOffset = timeOffset;
53+
this->_poolServerIP = poolServerIP;
54+
this->_poolServerName = NULL;
55+
}
56+
57+
NTPClient::NTPClient(UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval) {
58+
this->_udp = &udp;
59+
this->_timeOffset = timeOffset;
60+
this->_poolServerName = poolServerName;
61+
this->_updateInterval = updateInterval;
62+
}
63+
64+
NTPClient::NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset, unsigned long updateInterval) {
65+
this->_udp = &udp;
66+
this->_timeOffset = timeOffset;
67+
this->_poolServerIP = poolServerIP;
68+
this->_poolServerName = NULL;
69+
this->_updateInterval = updateInterval;
70+
}
71+
72+
void NTPClient::begin() {
73+
this->begin(NTP_DEFAULT_LOCAL_PORT);
74+
}
75+
76+
void NTPClient::begin(unsigned int port) {
77+
this->_port = port;
78+
79+
this->_udp->begin(this->_port);
80+
81+
this->_udpSetup = true;
82+
}
83+
84+
bool NTPClient::forceUpdate() {
85+
#ifdef DEBUG_NTPClient
86+
Serial.println("Update from NTP Server");
87+
#endif
88+
89+
// flush any existing packets
90+
while(this->_udp->parsePacket() != 0)
91+
this->_udp->flush();
92+
93+
this->sendNTPPacket();
94+
95+
// Wait till data is there or timeout...
96+
byte timeout = 0;
97+
int cb = 0;
98+
do {
99+
delay ( 10 );
100+
cb = this->_udp->parsePacket();
101+
if (timeout > 100) return false; // timeout after 1000 ms
102+
timeout++;
103+
} while (cb == 0);
104+
105+
this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time
106+
107+
this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);
108+
109+
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
110+
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
111+
// combine the four bytes (two words) into a long integer
112+
// this is NTP time (seconds since Jan 1 1900):
113+
unsigned long secsSince1900 = highWord << 16 | lowWord;
114+
115+
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
116+
117+
return true; // return true after successful update
118+
}
119+
120+
bool NTPClient::update() {
121+
if ((millis() - this->_lastUpdate >= this->_updateInterval) // Update after _updateInterval
122+
|| this->_lastUpdate == 0) { // Update if there was no update yet.
123+
if (!this->_udpSetup || this->_port != NTP_DEFAULT_LOCAL_PORT) this->begin(this->_port); // setup the UDP client if needed
124+
return this->forceUpdate();
125+
}
126+
return false; // return false if update does not occur
127+
}
128+
129+
bool NTPClient::isTimeSet() const {
130+
return (this->_lastUpdate != 0); // returns true if the time has been set, else false
131+
}
132+
133+
unsigned long NTPClient::getEpochTime() const {
134+
return this->_timeOffset + // User offset
135+
this->_currentEpoc + // Epoch returned by the NTP server
136+
((millis() - this->_lastUpdate) / 1000); // Time since last update
137+
}
138+
139+
int NTPClient::getDay() const {
140+
return (((this->getEpochTime() / 86400L) + 4 ) % 7); //0 is Sunday
141+
}
142+
int NTPClient::getHours() const {
143+
return ((this->getEpochTime() % 86400L) / 3600);
144+
}
145+
int NTPClient::getMinutes() const {
146+
return ((this->getEpochTime() % 3600) / 60);
147+
}
148+
int NTPClient::getSeconds() const {
149+
return (this->getEpochTime() % 60);
150+
}
151+
152+
String NTPClient::getFormattedTime() const {
153+
unsigned long rawTime = this->getEpochTime();
154+
unsigned long hours = (rawTime % 86400L) / 3600;
155+
String hoursStr = hours < 10 ? "0" + String(hours) : String(hours);
156+
157+
unsigned long minutes = (rawTime % 3600) / 60;
158+
String minuteStr = minutes < 10 ? "0" + String(minutes) : String(minutes);
159+
160+
unsigned long seconds = rawTime % 60;
161+
String secondStr = seconds < 10 ? "0" + String(seconds) : String(seconds);
162+
163+
return hoursStr + ":" + minuteStr + ":" + secondStr;
164+
}
165+
166+
void NTPClient::end() {
167+
this->_udp->stop();
168+
169+
this->_udpSetup = false;
170+
}
171+
172+
void NTPClient::setTimeOffset(int timeOffset) {
173+
this->_timeOffset = timeOffset;
174+
}
175+
176+
void NTPClient::setUpdateInterval(unsigned long updateInterval) {
177+
this->_updateInterval = updateInterval;
178+
}
179+
180+
void NTPClient::setPoolServerName(const char* poolServerName) {
181+
this->_poolServerName = poolServerName;
182+
}
183+
184+
void NTPClient::sendNTPPacket() {
185+
// set all bytes in the buffer to 0
186+
memset(this->_packetBuffer, 0, NTP_PACKET_SIZE);
187+
// Initialize values needed to form NTP request
188+
this->_packetBuffer[0] = 0b11100011; // LI, Version, Mode
189+
this->_packetBuffer[1] = 0; // Stratum, or type of clock
190+
this->_packetBuffer[2] = 6; // Polling Interval
191+
this->_packetBuffer[3] = 0xEC; // Peer Clock Precision
192+
// 8 bytes of zero for Root Delay & Root Dispersion
193+
this->_packetBuffer[12] = 49;
194+
this->_packetBuffer[13] = 0x4E;
195+
this->_packetBuffer[14] = 49;
196+
this->_packetBuffer[15] = 52;
197+
198+
// all NTP fields have been given values, now
199+
// you can send a packet requesting a timestamp:
200+
if (this->_poolServerName) {
201+
this->_udp->beginPacket(this->_poolServerName, 123);
202+
} else {
203+
this->_udp->beginPacket(this->_poolServerIP, 123);
204+
}
205+
this->_udp->write(this->_packetBuffer, NTP_PACKET_SIZE);
206+
this->_udp->endPacket();
207+
}
208+
209+
void NTPClient::setRandomPort(unsigned int minValue, unsigned int maxValue) {
210+
randomSeed(analogRead(0));
211+
this->_port = random(minValue, maxValue);
212+
}

firmware/lib/NTPClient/NTPClient.h

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#pragma once
2+
3+
#include "Arduino.h"
4+
5+
#include <Udp.h>
6+
7+
#define SEVENZYYEARS 2208988800UL
8+
#define NTP_PACKET_SIZE 48
9+
#define NTP_DEFAULT_LOCAL_PORT 1337
10+
11+
class NTPClient {
12+
private:
13+
UDP* _udp;
14+
bool _udpSetup = false;
15+
16+
const char* _poolServerName = "pool.ntp.org"; // Default time server
17+
IPAddress _poolServerIP;
18+
unsigned int _port = NTP_DEFAULT_LOCAL_PORT;
19+
long _timeOffset = 0;
20+
21+
unsigned long _updateInterval = 60000; // In ms
22+
23+
unsigned long _currentEpoc = 0; // In s
24+
unsigned long _lastUpdate = 0; // In ms
25+
26+
byte _packetBuffer[NTP_PACKET_SIZE];
27+
28+
void sendNTPPacket();
29+
30+
public:
31+
NTPClient(UDP& udp);
32+
NTPClient(UDP& udp, long timeOffset);
33+
NTPClient(UDP& udp, const char* poolServerName);
34+
NTPClient(UDP& udp, const char* poolServerName, long timeOffset);
35+
NTPClient(UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval);
36+
NTPClient(UDP& udp, IPAddress poolServerIP);
37+
NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset);
38+
NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset, unsigned long updateInterval);
39+
40+
/**
41+
* Set time server name
42+
*
43+
* @param poolServerName
44+
*/
45+
void setPoolServerName(const char* poolServerName);
46+
47+
/**
48+
* Set random local port
49+
*/
50+
void setRandomPort(unsigned int minValue = 49152, unsigned int maxValue = 65535);
51+
52+
/**
53+
* Starts the underlying UDP client with the default local port
54+
*/
55+
void begin();
56+
57+
/**
58+
* Starts the underlying UDP client with the specified local port
59+
*/
60+
void begin(unsigned int port);
61+
62+
/**
63+
* This should be called in the main loop of your application. By default an update from the NTP Server is only
64+
* made every 60 seconds. This can be configured in the NTPClient constructor.
65+
*
66+
* @return true on success, false on failure
67+
*/
68+
bool update();
69+
70+
/**
71+
* This will force the update from the NTP Server.
72+
*
73+
* @return true on success, false on failure
74+
*/
75+
bool forceUpdate();
76+
77+
/**
78+
* This allows to check if the NTPClient successfully received a NTP packet and set the time.
79+
*
80+
* @return true if time has been set, else false
81+
*/
82+
bool isTimeSet() const;
83+
84+
int getDay() const;
85+
int getHours() const;
86+
int getMinutes() const;
87+
int getSeconds() const;
88+
89+
/**
90+
* Changes the time offset. Useful for changing timezones dynamically
91+
*/
92+
void setTimeOffset(int timeOffset);
93+
94+
/**
95+
* Set the update interval to another frequency. E.g. useful when the
96+
* timeOffset should not be set in the constructor
97+
*/
98+
void setUpdateInterval(unsigned long updateInterval);
99+
100+
/**
101+
* @return time formatted like `hh:mm:ss`
102+
*/
103+
String getFormattedTime() const;
104+
105+
/**
106+
* @return time in seconds since Jan. 1, 1970
107+
*/
108+
unsigned long getEpochTime() const;
109+
110+
/**
111+
* Stops the underlying UDP client
112+
*/
113+
void end();
114+
};

0 commit comments

Comments
 (0)