Fork of the espurna firmware for `mhsw` switches
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.

198 lines
4.9 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
6 years ago
6 years ago
8 years ago
  1. /*
  2. NTP MODULE
  3. Copyright (C) 2016-2018 by Xose Pérez <xose dot perez at gmail dot com>
  4. Module key prefix: ntp
  5. */
  6. #if NTP_SUPPORT
  7. #include <TimeLib.h>
  8. #include <NtpClientLib.h>
  9. #include <WiFiClient.h>
  10. #include <Ticker.h>
  11. unsigned long _ntp_start = 0;
  12. bool _ntp_update = false;
  13. bool _ntp_configure = false;
  14. // -----------------------------------------------------------------------------
  15. // NTP
  16. // -----------------------------------------------------------------------------
  17. #if WEB_SUPPORT
  18. bool _ntpWebSocketOnReceive(const char * key, JsonVariant& value) {
  19. return (strncmp(key, "ntp", 3) == 0);
  20. }
  21. void _ntpWebSocketOnSend(JsonObject& root) {
  22. root["ntpVisible"] = 1;
  23. root["ntpStatus"] = (timeStatus() == timeSet);
  24. root["ntpServer"] = getSetting("ntpServer", NTP_SERVER);
  25. root["ntpOffset"] = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
  26. root["ntpDST"] = getSetting("ntpDST", NTP_DAY_LIGHT).toInt() == 1;
  27. root["ntpRegion"] = getSetting("ntpRegion", NTP_DST_REGION).toInt();
  28. if (ntpSynced()) root["now"] = now();
  29. }
  30. #endif
  31. void _ntpStart() {
  32. _ntp_start = 0;
  33. NTP.begin(getSetting("ntpServer", NTP_SERVER));
  34. NTP.setInterval(NTP_SYNC_INTERVAL, NTP_UPDATE_INTERVAL);
  35. NTP.setNTPTimeout(NTP_TIMEOUT);
  36. _ntpConfigure();
  37. }
  38. void _ntpConfigure() {
  39. _ntp_configure = false;
  40. int offset = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
  41. int sign = offset > 0 ? 1 : -1;
  42. offset = abs(offset);
  43. int tz_hours = sign * (offset / 60);
  44. int tz_minutes = sign * (offset % 60);
  45. if (NTP.getTimeZone() != tz_hours || NTP.getTimeZoneMinutes() != tz_minutes) {
  46. NTP.setTimeZone(tz_hours, tz_minutes);
  47. _ntp_update = true;
  48. }
  49. bool daylight = getSetting("ntpDST", NTP_DAY_LIGHT).toInt() == 1;
  50. if (NTP.getDayLight() != daylight) {
  51. NTP.setDayLight(daylight);
  52. _ntp_update = true;
  53. }
  54. String server = getSetting("ntpServer", NTP_SERVER);
  55. if (!NTP.getNtpServerName().equals(server)) {
  56. NTP.setNtpServerName(server);
  57. }
  58. uint8_t dst_region = getSetting("ntpRegion", NTP_DST_REGION).toInt();
  59. NTP.setDSTZone(dst_region);
  60. }
  61. void _ntpUpdate() {
  62. _ntp_update = false;
  63. #if WEB_SUPPORT
  64. wsSend(_ntpWebSocketOnSend);
  65. #endif
  66. if (ntpSynced()) {
  67. time_t t = now();
  68. DEBUG_MSG_P(PSTR("[NTP] UTC Time : %s\n"), (char *) ntpDateTime(ntpLocal2UTC(t)).c_str());
  69. DEBUG_MSG_P(PSTR("[NTP] Local Time: %s\n"), (char *) ntpDateTime(t).c_str());
  70. }
  71. }
  72. void _ntpLoop() {
  73. if (0 < _ntp_start && _ntp_start < millis()) _ntpStart();
  74. if (_ntp_configure) _ntpConfigure();
  75. if (_ntp_update) _ntpUpdate();
  76. now();
  77. #if BROKER_SUPPORT
  78. static unsigned char last_minute = 60;
  79. if (ntpSynced() && (minute() != last_minute)) {
  80. last_minute = minute();
  81. brokerPublish(MQTT_TOPIC_DATETIME, ntpDateTime().c_str());
  82. }
  83. #endif
  84. }
  85. void _ntpBackwards() {
  86. // 1.12.0 - 2018-01-21
  87. moveSetting("ntpServer1", "ntpServer");
  88. delSetting("ntpServer2");
  89. delSetting("ntpServer3");
  90. // 1.12.0 - 2018-01-20
  91. int offset = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
  92. if (-30 < offset && offset < 30) {
  93. offset *= 60;
  94. setSetting("ntpOffset", offset);
  95. }
  96. }
  97. // -----------------------------------------------------------------------------
  98. bool ntpSynced() {
  99. return (year() > 2017);
  100. }
  101. String ntpDateTime(time_t t) {
  102. char buffer[20];
  103. snprintf_P(buffer, sizeof(buffer),
  104. PSTR("%04d-%02d-%02d %02d:%02d:%02d"),
  105. year(t), month(t), day(t), hour(t), minute(t), second(t)
  106. );
  107. return String(buffer);
  108. }
  109. String ntpDateTime() {
  110. if (ntpSynced()) return ntpDateTime(now());
  111. return String();
  112. }
  113. time_t ntpLocal2UTC(time_t local) {
  114. int offset = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
  115. if (NTP.isSummerTime()) offset += 60;
  116. return local - offset * 60;
  117. }
  118. // -----------------------------------------------------------------------------
  119. void ntpSetup() {
  120. // Check backwards compatibility
  121. _ntpBackwards();
  122. NTP.onNTPSyncEvent([](NTPSyncEvent_t error) {
  123. if (error) {
  124. #if WEB_SUPPORT
  125. wsSend_P(PSTR("{\"ntpStatus\": false}"));
  126. #endif
  127. if (error == noResponse) {
  128. DEBUG_MSG_P(PSTR("[NTP] Error: NTP server not reachable\n"));
  129. } else if (error == invalidAddress) {
  130. DEBUG_MSG_P(PSTR("[NTP] Error: Invalid NTP server address\n"));
  131. }
  132. } else {
  133. _ntp_update = true;
  134. }
  135. });
  136. wifiRegister([](justwifi_messages_t code, char * parameter) {
  137. if (code == MESSAGE_CONNECTED) _ntp_start = millis() + NTP_START_DELAY;
  138. });
  139. #if WEB_SUPPORT
  140. wsOnSendRegister(_ntpWebSocketOnSend);
  141. wsOnReceiveRegister(_ntpWebSocketOnReceive);
  142. wsOnAfterParseRegister([]() { _ntp_configure = true; });
  143. #endif
  144. // Register loop
  145. espurnaRegisterLoop(_ntpLoop);
  146. }
  147. #endif // NTP_SUPPORT