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.

223 lines
5.7 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
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. */
  5. #if NTP_SUPPORT
  6. #include <TimeLib.h>
  7. #include <NtpClientLib.h>
  8. #include <WiFiClient.h>
  9. #include <Ticker.h>
  10. unsigned long _ntp_start = 0;
  11. bool _ntp_update = false;
  12. bool _ntp_configure = false;
  13. #if RTC_SUPPORT && RTC_NTP_SYNC_ENA
  14. bool _rtc_update = false;
  15. #endif
  16. // -----------------------------------------------------------------------------
  17. // NTP
  18. // -----------------------------------------------------------------------------
  19. #if WEB_SUPPORT
  20. bool _ntpWebSocketOnReceive(const char * key, JsonVariant& value) {
  21. return (strncmp(key, "ntp", 3) == 0);
  22. }
  23. void _ntpWebSocketOnSend(JsonObject& root) {
  24. root["ntpVisible"] = 1;
  25. root["ntpStatus"] = (timeStatus() == timeSet);
  26. root["ntpServer"] = getSetting("ntpServer", NTP_SERVER);
  27. root["ntpOffset"] = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
  28. root["ntpDST"] = getSetting("ntpDST", NTP_DAY_LIGHT).toInt() == 1;
  29. root["ntpRegion"] = getSetting("ntpRegion", NTP_DST_REGION).toInt();
  30. if (ntpSynced()) root["now"] = now();
  31. }
  32. #endif
  33. void _ntpStart() {
  34. _ntp_start = 0;
  35. NTP.begin(getSetting("ntpServer", NTP_SERVER));
  36. #if RTC_SUPPORT
  37. // set alter sync provider. two attempts for NTP synchro at start occure...
  38. setSyncProvider(ntp_getTime);
  39. #endif
  40. NTP.setInterval(NTP_SYNC_INTERVAL, NTP_UPDATE_INTERVAL);
  41. NTP.setNTPTimeout(NTP_TIMEOUT);
  42. _ntpConfigure();
  43. }
  44. void _ntpConfigure() {
  45. _ntp_configure = false;
  46. int offset = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
  47. int sign = offset > 0 ? 1 : -1;
  48. offset = abs(offset);
  49. int tz_hours = sign * (offset / 60);
  50. int tz_minutes = sign * (offset % 60);
  51. if (NTP.getTimeZone() != tz_hours || NTP.getTimeZoneMinutes() != tz_minutes) {
  52. NTP.setTimeZone(tz_hours, tz_minutes);
  53. _ntp_update = true;
  54. }
  55. bool daylight = getSetting("ntpDST", NTP_DAY_LIGHT).toInt() == 1;
  56. if (NTP.getDayLight() != daylight) {
  57. NTP.setDayLight(daylight);
  58. _ntp_update = true;
  59. }
  60. String server = getSetting("ntpServer", NTP_SERVER);
  61. if (!NTP.getNtpServerName().equals(server)) {
  62. NTP.setNtpServerName(server);
  63. }
  64. uint8_t dst_region = getSetting("ntpRegion", NTP_DST_REGION).toInt();
  65. NTP.setDSTZone(dst_region);
  66. }
  67. void _ntpUpdate() {
  68. _ntp_update = false;
  69. #if WEB_SUPPORT
  70. wsSend(_ntpWebSocketOnSend);
  71. #endif
  72. if (ntpSynced()) {
  73. time_t t = now();
  74. #if RTC_SUPPORT && RTC_NTP_SYNC_ENA
  75. // sync/update rtc here!!!!!!!!!!!!
  76. if(_rtc_update) setTime_rtc(t);
  77. #endif
  78. DEBUG_MSG_P(PSTR("[NTP] UTC Time : %s\n"), (char *) ntpDateTime(ntpLocal2UTC(t)).c_str());
  79. DEBUG_MSG_P(PSTR("[NTP] Local Time: %s\n"), (char *) ntpDateTime(t).c_str());
  80. }
  81. }
  82. void _ntpLoop() {
  83. if (0 < _ntp_start && _ntp_start < millis()) _ntpStart();
  84. if (_ntp_configure) _ntpConfigure();
  85. if (_ntp_update) _ntpUpdate();
  86. now();
  87. #if BROKER_SUPPORT
  88. static unsigned char last_minute = 60;
  89. if (ntpSynced() && (minute() != last_minute)) {
  90. last_minute = minute();
  91. brokerPublish(MQTT_TOPIC_DATETIME, ntpDateTime().c_str());
  92. }
  93. #endif
  94. }
  95. void _ntpBackwards() {
  96. moveSetting("ntpServer1", "ntpServer");
  97. delSetting("ntpServer2");
  98. delSetting("ntpServer3");
  99. int offset = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
  100. if (-30 < offset && offset < 30) {
  101. offset *= 60;
  102. setSetting("ntpOffset", offset);
  103. }
  104. }
  105. // -----------------------------------------------------------------------------
  106. bool ntpSynced() {
  107. return (year() > 2017);
  108. }
  109. String ntpDateTime(time_t t) {
  110. char buffer[20];
  111. snprintf_P(buffer, sizeof(buffer),
  112. PSTR("%04d-%02d-%02d %02d:%02d:%02d"),
  113. year(t), month(t), day(t), hour(t), minute(t), second(t)
  114. );
  115. return String(buffer);
  116. }
  117. String ntpDateTime() {
  118. if (ntpSynced()) return ntpDateTime(now());
  119. return String();
  120. }
  121. time_t ntpLocal2UTC(time_t local) {
  122. int offset = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
  123. if (NTP.isSummerTime()) offset += 60;
  124. return local - offset * 60;
  125. }
  126. // -----------------------------------------------------------------------------
  127. void ntpSetup() {
  128. _ntpBackwards();
  129. NTP.onNTPSyncEvent([](NTPSyncEvent_t error) {
  130. if (error) {
  131. #if WEB_SUPPORT
  132. wsSend_P(PSTR("{\"ntpStatus\": false}"));
  133. #endif
  134. if (error == noResponse) {
  135. DEBUG_MSG_P(PSTR("[NTP] Error: NTP server not reachable\n"));
  136. } else if (error == invalidAddress) {
  137. DEBUG_MSG_P(PSTR("[NTP] Error: Invalid NTP server address\n"));
  138. }
  139. _ntp_update = false;
  140. } else {
  141. _ntp_update = true;
  142. #if RTC_SUPPORT && RTC_NTP_SYNC_ENA
  143. _rtc_update = true;
  144. #endif
  145. }
  146. });
  147. wifiRegister([](justwifi_messages_t code, char * parameter) {
  148. if (code == MESSAGE_CONNECTED) _ntp_start = millis() + NTP_START_DELAY;
  149. #if RTC_SUPPORT
  150. // system time from local RTC, but still try recovery if enabled (without success)
  151. else
  152. if(code == MESSAGE_ACCESSPOINT_CREATED) _ntp_start = millis() + NTP_START_DELAY;
  153. #endif
  154. });
  155. #if WEB_SUPPORT
  156. wsOnSendRegister(_ntpWebSocketOnSend);
  157. wsOnReceiveRegister(_ntpWebSocketOnReceive);
  158. wsOnAfterParseRegister([]() { _ntp_configure = true; });
  159. #endif
  160. // Register loop
  161. espurnaRegisterLoop(_ntpLoop);
  162. #if RTC_SUPPORT
  163. #if TERMINAL_SUPPORT
  164. _rtcInitCommands();
  165. #endif
  166. #endif
  167. }
  168. #endif // NTP_SUPPORT