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.

183 lines
4.8 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
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. // -----------------------------------------------------------------------------
  14. // NTP
  15. // -----------------------------------------------------------------------------
  16. #if WEB_SUPPORT
  17. bool _ntpWebSocketOnReceive(const char * key, JsonVariant& value) {
  18. return (strncmp(key, "ntp", 3) == 0);
  19. }
  20. void _ntpWebSocketOnSend(JsonObject& root) {
  21. root["ntpVisible"] = 1;
  22. root["ntpStatus"] = (timeStatus() == timeSet);
  23. root["ntpServer"] = getSetting("ntpServer", NTP_SERVER);
  24. root["ntpOffset"] = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
  25. root["ntpDST"] = getSetting("ntpDST", NTP_DAY_LIGHT).toInt() == 1;
  26. root["ntpRegion"] = getSetting("ntpRegion", NTP_DST_REGION).toInt();
  27. if (rtcReady()) root["now"] = now();
  28. }
  29. #endif
  30. void _ntpStart() {
  31. _ntp_start = 0;
  32. NTP.begin(getSetting("ntpServer", NTP_SERVER));
  33. NTP.setInterval(NTP_SYNC_INTERVAL, NTP_UPDATE_INTERVAL);
  34. NTP.setNTPTimeout(NTP_TIMEOUT);
  35. _ntpConfigure();
  36. }
  37. void _ntpConfigure() {
  38. _ntp_configure = false;
  39. int offset = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
  40. int sign = offset > 0 ? 1 : -1;
  41. offset = abs(offset);
  42. int tz_hours = sign * (offset / 60);
  43. int tz_minutes = sign * (offset % 60);
  44. if (NTP.getTimeZone() != tz_hours || NTP.getTimeZoneMinutes() != tz_minutes) {
  45. NTP.setTimeZone(tz_hours, tz_minutes);
  46. _ntp_update = true;
  47. }
  48. bool daylight = getSetting("ntpDST", NTP_DAY_LIGHT).toInt() == 1;
  49. if (NTP.getDayLight() != daylight) {
  50. NTP.setDayLight(daylight);
  51. _ntp_update = true;
  52. }
  53. String server = getSetting("ntpServer", NTP_SERVER);
  54. if (!NTP.getNtpServerName().equals(server)) {
  55. NTP.setNtpServerName(server);
  56. }
  57. uint8_t dst_region = getSetting("ntpRegion", NTP_DST_REGION).toInt();
  58. NTP.setDSTZone(dst_region);
  59. }
  60. void _ntpUpdate() {
  61. _ntp_update = false;
  62. #if WEB_SUPPORT
  63. wsSend(_ntpWebSocketOnSend);
  64. #endif
  65. if (rtcReady()) {
  66. time_t t = now();
  67. #if RTC_SUPPORT && RTC_NTP_SYNC_ENA
  68. rtcSetTime(t);
  69. #endif
  70. DEBUG_MSG_P(PSTR("[NTP] UTC Time : %s\n"), (char *) rtcDateTime(ntpLocal2UTC(t)).c_str());
  71. DEBUG_MSG_P(PSTR("[NTP] Local Time: %s\n"), (char *) rtcDateTime(t).c_str());
  72. }
  73. }
  74. void _ntpLoop() {
  75. if (0 < _ntp_start && _ntp_start < millis()) _ntpStart();
  76. if (_ntp_configure) _ntpConfigure();
  77. if (_ntp_update) _ntpUpdate();
  78. now();
  79. #if BROKER_SUPPORT
  80. static unsigned char last_minute = 60;
  81. if (rtcReady() && (minute() != last_minute)) {
  82. last_minute = minute();
  83. brokerPublish(MQTT_TOPIC_DATETIME, rtcDateTime(now()).c_str());
  84. }
  85. #endif
  86. }
  87. void _ntpBackwards() {
  88. moveSetting("ntpServer1", "ntpServer");
  89. delSetting("ntpServer2");
  90. delSetting("ntpServer3");
  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. time_t ntpLocal2UTC(time_t local) {
  99. int offset = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
  100. if (NTP.isSummerTime()) offset += 60;
  101. return local - offset * 60;
  102. }
  103. // -----------------------------------------------------------------------------
  104. void ntpSetup() {
  105. _ntpBackwards();
  106. NTP.onNTPSyncEvent([](NTPSyncEvent_t error) {
  107. if (error) {
  108. #if WEB_SUPPORT
  109. wsSend_P(PSTR("{\"ntpStatus\": false}"));
  110. #endif
  111. if (error == noResponse) {
  112. DEBUG_MSG_P(PSTR("[NTP] Error: NTP server not reachable\n"));
  113. } else if (error == invalidAddress) {
  114. DEBUG_MSG_P(PSTR("[NTP] Error: Invalid NTP server address\n"));
  115. }
  116. _ntp_update = false;
  117. } else {
  118. _ntp_update = true;
  119. }
  120. });
  121. wifiRegister([](justwifi_messages_t code, char * parameter) {
  122. if (code == MESSAGE_CONNECTED) _ntp_start = millis() + NTP_START_DELAY;
  123. #if RTC_SUPPORT
  124. // system time from local RTC, but still try recovery if enabled (without success)
  125. else
  126. if (code == MESSAGE_ACCESSPOINT_CREATED) _ntp_start = millis() + NTP_START_DELAY;
  127. #endif
  128. });
  129. #if WEB_SUPPORT
  130. wsOnSendRegister(_ntpWebSocketOnSend);
  131. wsOnReceiveRegister(_ntpWebSocketOnReceive);
  132. wsOnAfterParseRegister([]() { _ntp_configure = true; });
  133. #endif
  134. // Register loop
  135. espurnaRegisterLoop(_ntpLoop);
  136. }
  137. #endif // NTP_SUPPORT