NTP clock made with ESP-12 (ESP8266) and 16-char TM1640 (JY-LM1640)
mcu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NtpClientLib.h 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. Copyright 2016 German Martin (gmag11@gmail.com). All rights reserved.
  3. Redistribution and use in source and binary forms, with or without modification, are
  4. permitted provided that the following conditions are met :
  5. 1. Redistributions of source code must retain the above copyright notice, this list of
  6. conditions and the following disclaimer.
  7. 2. Redistributions in binary form must reproduce the above copyright notice, this list
  8. of conditions and the following disclaimer in the documentation and / or other materials
  9. provided with the distribution.
  10. THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY EXPRESS OR IMPLIED
  11. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  12. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
  13. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  14. CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  15. SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  16. ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
  17. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  18. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  19. The views and conclusions contained in the software and documentation are those of the
  20. authors and should not be interpreted as representing official policies, either expressed
  21. or implied, of German Martin
  22. */
  23. /*
  24. Name: NtpClientLib
  25. Created: 17/08/2016
  26. Author: Germán Martín (gmag11@gmail.com)
  27. Maintainer:Germán Martín (gmag11@gmail.com)
  28. Editor: http://www.visualmicro.com
  29. Library to get system sync from a NTP server
  30. */
  31. #ifndef _NtpClientLib_h
  32. #define _NtpClientLib_h
  33. //#define DEBUG_NTPCLIENT //Uncomment this to enable debug messages over serial port
  34. #ifdef ESP8266
  35. //extern "C" {
  36. //#include "user_interface.h"
  37. //#include "sntp.h"
  38. //}
  39. #include <functional>
  40. using namespace std;
  41. using namespace placeholders;
  42. #endif
  43. #include <TimeLib.h>
  44. #if defined(ARDUINO) && ARDUINO >= 100
  45. #include "Arduino.h"
  46. #else
  47. #include "WProgram.h"
  48. #endif
  49. #define NETWORK_W5100 (1) // Arduino Ethernet Shield
  50. #define NETWORK_ENC28J60 (2) // Alternate Ethernet Shield
  51. #define NETWORK_WIFI101 (3) // WiFi Shield 101 or MKR1000
  52. #define NETWORK_ESP8266 (100) // ESP8266 boards, not for Arduino using AT firmware
  53. #define NETWORK_ESP32 (101) // ESP32 boards
  54. #define DEFAULT_NTP_SERVER "pool.ntp.org" // Default international NTP server. I recommend you to select a closer server to get better accuracy
  55. #define DEFAULT_NTP_PORT 123 // Default local udp port. Select a different one if neccesary (usually not needed)
  56. #define NTP_TIMEOUT 1500 // Response timeout for NTP requests
  57. #define DEFAULT_NTP_INTERVAL 1800 // Default sync interval 30 minutes
  58. #define DEFAULT_NTP_SHORTINTERVAL 15 // Sync interval when sync has not been achieved. 15 seconds
  59. #define DEFAULT_NTP_TIMEZONE 0 // Select your local time offset. 0 if UTC time has to be used
  60. const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
  61. #ifdef ARDUINO_ARCH_ESP8266
  62. #define NETWORK_TYPE NETWORK_ESP8266
  63. #elif defined ARDUINO_ARCH_SAMD || defined ARDUINO_ARCH_ARC32
  64. #define NETWORK_TYPE NETWORK_WIFI101 // SET YOUR NETWORK INTERFACE
  65. #elif defined ARDUINO_ARCH_AVR
  66. #define NETWORK_TYPE NETWORK_W5100
  67. #elif defined ARDUINO_ARCH_ESP32 || defined ESP32
  68. #define NETWORK_TYPE NETWORK_ESP32
  69. #endif
  70. #if NETWORK_TYPE == NETWORK_W5100
  71. //#include <SPI.h>
  72. #include <EthernetUdp.h>
  73. #include <Ethernet.h>
  74. //#include <Dns.h>
  75. //#include <Dhcp.h>
  76. #elif NETWORK_TYPE == NETWORK_WIFI101
  77. #include <WiFiClient.h>
  78. #include <WiFiUdp.h>
  79. #include <WiFi101.h>
  80. #elif NETWORK_TYPE == NETWORK_ESP8266
  81. #include <ESP8266WiFi.h>
  82. #include <WiFiUdp.h>
  83. #include <Udp.h>
  84. #elif NETWORK_TYPE == NETWORK_ESP32
  85. #include <WiFi.h>
  86. #include <WiFiUdp.h>
  87. #include <Udp.h>
  88. #else
  89. #error "Incorrect platform. Only ARDUINO and ESP8266 MCUs are valid."
  90. #endif // NETWORK_TYPE
  91. typedef enum {
  92. timeSyncd, // Time successfully got from NTP server
  93. noResponse, // No response from server
  94. invalidAddress // Address not reachable
  95. } NTPSyncEvent_t;
  96. #if defined ARDUINO_ARCH_ESP8266 || defined ARDUINO_ARCH_ESP32
  97. #include <functional>
  98. typedef std::function<void (NTPSyncEvent_t)> onSyncEvent_t;
  99. #else
  100. typedef void (*onSyncEvent_t)(NTPSyncEvent_t);
  101. #endif
  102. class NTPClient {
  103. public:
  104. /**
  105. * Construct NTP client.
  106. */
  107. NTPClient ();
  108. /**
  109. * Starts time synchronization.
  110. * @param[in] NTP server name as String.
  111. * @param[in] Time offset from UTC.
  112. * @param[in] true if this time zone has dayligth saving.
  113. * @param[in] Minutes offset added to hourly offset (optional).
  114. * @param[in] UDP connection instance (optional).
  115. * @param[out] true if everything went ok.
  116. */
  117. #if NETWORK_TYPE == NETWORK_W5100
  118. bool begin (String ntpServerName = DEFAULT_NTP_SERVER, int8_t timeOffset = DEFAULT_NTP_TIMEZONE, bool daylight = false, int8_t minutes = 0, EthernetUDP* udp_conn = NULL);
  119. #elif NETWORK_TYPE == NETWORK_ESP8266 || NETWORK_TYPE == NETWORK_WIFI101 || NETWORK_TYPE == NETWORK_ESP32
  120. bool begin (String ntpServerName = DEFAULT_NTP_SERVER, int8_t timeOffset = DEFAULT_NTP_TIMEZONE, bool daylight = false, int8_t minutes = 0, WiFiUDP* udp_conn = NULL);
  121. #endif
  122. /**
  123. * Sets NTP server name.
  124. * @param[in] New NTP server name.
  125. * @param[out] True if everything went ok.
  126. */
  127. bool setNtpServerName (String ntpServerName);
  128. bool setNtpServerName (char* ntpServerName);
  129. /**
  130. * Sets NTP server name. DEPRECATED, only for compatibility with older versions
  131. * @param[in] New NTP server name.
  132. * @param[in] Server index (0-2).
  133. * @param[out] True if everything went ok.
  134. */
  135. bool setNtpServerName (String ntpServerName, int idx) {
  136. if (idx < 0 || idx > 2)
  137. return false;
  138. return setNtpServerName (ntpServerName);
  139. }
  140. /**
  141. * Gets NTP server name
  142. * @param[out] NTP server name.
  143. */
  144. String getNtpServerName ();
  145. char* getNtpServerNamePtr ();
  146. /**
  147. * Gets NTP server name. DEPRECATED, only for compatibility with older versions
  148. * @param[in] Server index (0-2).
  149. * @param[out] NTP server name.
  150. */
  151. String getNtpServerName (int idx) {
  152. if (idx < 0 || idx > 2)
  153. return "";
  154. return getNtpServerName ();
  155. }
  156. /**
  157. * Starts a NTP time request to server. Returns a time in UNIX time format. Normally only called from library.
  158. * Kept in public section to allow direct NTP request.
  159. * @param[out] Time in UNIX time format.
  160. */
  161. time_t getTime ();
  162. /**
  163. * Sets timezone.
  164. * @param[in] New time offset in hours (-11 <= timeZone <= +13).
  165. * @param[out] True if everything went ok.
  166. */
  167. bool setTimeZone (int8_t timeZone, int8_t minutes = 0);
  168. /**
  169. * Gets timezone.
  170. * @param[out] Time offset in hours (plus or minus).
  171. */
  172. int8_t getTimeZone ();
  173. /**
  174. * Gets minutes fraction of timezone.
  175. * @param[out] Minutes offset (plus or minus) added to hourly offset.
  176. */
  177. int8_t getTimeZoneMinutes ();
  178. /**
  179. * Stops time synchronization.
  180. * @param[out] True if everything went ok.
  181. */
  182. bool stop ();
  183. /**
  184. * Changes sync period.
  185. * @param[in] New interval in seconds.
  186. * @param[out] True if everything went ok.
  187. */
  188. bool setInterval (int interval);
  189. /**
  190. * Changes sync period in sync'd and not sync'd status.
  191. * @param[in] New interval while time is not first adjusted yet, in seconds.
  192. * @param[in] New interval for normal operation, in seconds.
  193. * @param[out] True if everything went ok.
  194. */
  195. bool setInterval (int shortInterval, int longInterval);
  196. /**
  197. * Gets sync period.
  198. * @param[out] Interval for normal operation, in seconds.
  199. */
  200. int getInterval ();
  201. /**
  202. * Changes sync period not sync'd status.
  203. * @param[out] Interval while time is not first adjusted yet, in seconds.
  204. */
  205. int getShortInterval ();
  206. /**
  207. * Gets sync period.
  208. * @param[out] Interval for normal operation in seconds.
  209. */
  210. int getLongInterval () { return getInterval (); }
  211. /**
  212. * Set daylight time saving option.
  213. * @param[in] true is daylight time savings apply.
  214. */
  215. void setDayLight (bool daylight);
  216. /**
  217. * Get daylight time saving option.
  218. * @param[out] true is daylight time savings apply.
  219. */
  220. bool getDayLight ();
  221. /**
  222. * Convert current time to a String.
  223. * @param[out] String constructed from current time.
  224. * TODO: Add internationalization support
  225. */
  226. String getTimeStr () { return getTimeStr (now ()); }
  227. /**
  228. * Convert a time in UNIX format to a String representing time.
  229. * @param[out] String constructed from current time.
  230. * @param[in] time_t object to convert to extract time.
  231. * TODO: Add internationalization support
  232. */
  233. String getTimeStr (time_t moment);
  234. /**
  235. * Convert current date to a String.
  236. * @param[out] String constructed from current date.
  237. * TODO: Add internationalization support
  238. */
  239. String getDateStr () { return getDateStr (now ()); }
  240. /**
  241. * Convert a time in UNIX format to a String representing its date.
  242. * @param[out] String constructed from current date.
  243. * @param[in] time_t object to convert to extract date.
  244. * TODO: Add internationalization support
  245. */
  246. String getDateStr (time_t moment);
  247. /**
  248. * Convert current time and date to a String.
  249. * @param[out] String constructed from current time.
  250. * TODO: Add internationalization support
  251. */
  252. String getTimeDateString () { return getTimeDateString (now ()); }
  253. /**
  254. * Convert current time and date to a String.
  255. * @param[in] time_t object to convert to String.
  256. * @param[out] String constructed from current time.
  257. * TODO: Add internationalization support
  258. */
  259. String getTimeDateString (time_t moment);
  260. /**
  261. * Gets last successful sync time in UNIX format.
  262. * @param[out] Last successful sync time. 0 equals never.
  263. */
  264. time_t getLastNTPSync ();
  265. /**
  266. * Get uptime in human readable String format.
  267. * @param[out] Uptime.
  268. */
  269. String getUptimeString ();
  270. /**
  271. * Get uptime in UNIX format, time since MCU was last rebooted.
  272. * @param[out] Uptime. 0 equals never.
  273. */
  274. time_t getUptime ();
  275. /**
  276. * Get first boot time in UNIX format, time when MCU was last rebooted.
  277. * @param[out] Uptime. 0 equals never.
  278. */
  279. time_t getLastBootTime ();
  280. /**
  281. * Get first successful synchronization time after boot.
  282. * @param[out] First sync time.
  283. */
  284. time_t getFirstSync ();
  285. /**
  286. * Set a callback that triggers after a sync trial.
  287. * @param[in] function with void(NTPSyncEvent_t) or std::function<void(NTPSyncEvent_t)> (only for ESP8266)
  288. * NTPSyncEvent_t equals 0 is there is no error
  289. */
  290. void onNTPSyncEvent (onSyncEvent_t handler);
  291. /**
  292. * True if current time is inside DST period (aka. summer time). False otherwise of if NTP object has DST
  293. * calculation disabled
  294. * @param[out] True = summertime enabled and time in summertime period
  295. * False = sumertime disabled or time ouside summertime period
  296. */
  297. boolean isSummerTime () {
  298. if (_daylight)
  299. return isSummerTimePeriod (now ());
  300. else
  301. return false;
  302. }
  303. /**
  304. * True if given time is inside DST period (aka. summer time). False otherwise.
  305. * @param[in] time to make the calculation with
  306. * @param[out] True = time in summertime period
  307. * False = time ouside summertime period
  308. */
  309. boolean isSummerTimePeriod (time_t moment);
  310. protected:
  311. #if NETWORK_TYPE == NETWORK_W5100
  312. EthernetUDP *udp;
  313. #elif NETWORK_TYPE == NETWORK_ESP8266 || NETWORK_TYPE == NETWORK_WIFI101 || NETWORK_TYPE == NETWORK_ESP32
  314. WiFiUDP *udp;
  315. #endif
  316. bool _daylight; ///< Does this time zone have daylight saving?
  317. int8_t _timeZone = 0; ///< Keep track of set time zone offset
  318. int8_t _minutesOffset = 0; ///< Minutes offset for time zones with decimal numbers
  319. char* _ntpServerName; ///< Name of NTP server on Internet or LAN
  320. int _shortInterval; ///< Interval to set periodic time sync until first synchronization.
  321. int _longInterval; ///< Interval to set periodic time sync
  322. time_t _lastSyncd = 0; ///< Stored time of last successful sync
  323. time_t _firstSync = 0; ///< Stored time of first successful sync after boot
  324. unsigned long _uptime = 0; ///< Time since boot
  325. onSyncEvent_t onSyncEvent; ///< Event handler callback
  326. /**
  327. * Function that gets time from NTP server and convert it to Unix time format
  328. * @param[out] Time form NTP in Unix Time Format.
  329. */
  330. static time_t s_getTime ();
  331. /**
  332. * Calculates the daylight saving for a given date.
  333. * @param[in] Year.
  334. * @param[in] Month.
  335. * @param[in] Day.
  336. * @param[in] Hour.
  337. * @param[in] Time zone offset.
  338. * @param[out] true if date and time are inside summertime period.
  339. */
  340. bool summertime (int year, byte month, byte day, byte hour, byte tzHours);
  341. /**
  342. * Helper function to add leading 0 to hour, minutes or seconds if < 10.
  343. * @param[in] Digit to evaluate the need of leading 0.
  344. * @param[out] Result digit with leading 0 if needed.
  345. */
  346. //String printDigits(int digits);
  347. public:
  348. /**
  349. * Decode NTP response contained in buffer.
  350. * @param[in] Pointer to message buffer.
  351. * @param[out] Decoded time from message, 0 if error ocurred.
  352. */
  353. time_t decodeNtpMessage (char *messageBuffer);
  354. /**
  355. * Set last successful synchronization time.
  356. * @param[out] Last sync time.
  357. */
  358. void setLastNTPSync (time_t moment);
  359. private:
  360. /**
  361. * Sends NTP request packet to given IP address.
  362. * @param[in] NTP server's IP address.
  363. * @param[out] True if everything went ok.
  364. */
  365. //bool sendNTPpacket(IPAddress &address);
  366. //#endif
  367. };
  368. extern NTPClient NTP;
  369. #endif // _NtpClientLib_h