From f22349daf457229696819a1579297d585cb020bf Mon Sep 17 00:00:00 2001 From: Edgar W Date: Sun, 5 Jan 2025 16:23:04 +0100 Subject: [PATCH 1/4] Refactor NTPClientPlus to use UTC offset in minutes and update related methods --- ntp_client_plus.cpp | 32 ++++++++++---------------------- ntp_client_plus.h | 7 +++---- wordclock_esp8266.ino | 7 +++---- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/ntp_client_plus.cpp b/ntp_client_plus.cpp index 5cdd252..451bde3 100644 --- a/ntp_client_plus.cpp +++ b/ntp_client_plus.cpp @@ -12,7 +12,6 @@ NTPClientPlus::NTPClientPlus(UDP &udp, const char *poolServerName, int utcx, boo { this->_udp = &udp; this->_utcx = utcx; - this->_timeOffset = this->secondperhour * this->_utcx; this->_poolServerName = poolServerName; this->_swChange = _swChange; } @@ -104,18 +103,13 @@ void NTPClientPlus::end() } /** - * @brief Setter TimeOffset + * @brief Setter UTC offset * - * @param timeOffset offset from UTC in seconds + * @param utcOffset offset from UTC in minutes */ -void NTPClientPlus::setTimeOffset(int timeOffset) +void NTPClientPlus::setUTCOffset(int utcOffset) { - this->_timeOffset = timeOffset; -} - -long NTPClientPlus::getTimeOffset() -{ - return this->_timeOffset; + this->_utcx = utcOffset; } /** @@ -135,9 +129,10 @@ void NTPClientPlus::setPoolServerName(const char *poolServerName) */ unsigned long NTPClientPlus::getSecsSince1900() const { - return this->_timeOffset + // User offset - this->_secsSince1900 + // seconds returned by the NTP server - ((millis() - this->_lastUpdate) / 1000); // Time since last update + return this->_utcx * this->secondperminute + // UTC offset + this->_summertime * this->secondperhour + // Summer time offset + this->_secsSince1900 + // seconds returned by the NTP server + ((millis() - this->_lastUpdate) / 1000); // Time since last update } /** @@ -556,18 +551,11 @@ void NTPClientPlus::sendNTPPacket() */ void NTPClientPlus::setSummertime(bool summertime) { - if (summertime) - { - this->_timeOffset = this->secondperhour * (this->_utcx + 1); - } - else - { - this->_timeOffset = this->secondperhour * (this->_utcx); - } + this->_summertime = summertime; } /** - * @brief (private) Update Summer/Winter time change + * @brief Update Summer/Winter time change * * @returns bool summertime active */ diff --git a/ntp_client_plus.h b/ntp_client_plus.h index 001cca5..847306c 100644 --- a/ntp_client_plus.h +++ b/ntp_client_plus.h @@ -21,7 +21,7 @@ class NTPClientPlus{ void setupNTPClient(); int updateNTP(); void end(); - void setTimeOffset(int timeOffset); + void setUTCOffset(int utcOffset); void setPoolServerName(const char* poolServerName); unsigned long getSecsSince1900() const; unsigned long getEpochTime() const; @@ -36,7 +36,6 @@ class NTPClientPlus{ unsigned int getYear(); bool isLeapYear(unsigned int year); int getMonth(int dayOfYear); - long getTimeOffset(); bool updateSWChange(); @@ -47,9 +46,9 @@ class NTPClientPlus{ const char* _poolServerName = "pool.ntp.org"; // Default time server IPAddress _poolServerIP; unsigned int _port = NTP_DEFAULT_LOCAL_PORT; - long _timeOffset = 0; int _utcx = 0; - bool _swChange = 1; + bool _swChange = 1; + bool _summertime = false; unsigned long _updateInterval = 60000; // In ms diff --git a/wordclock_esp8266.ino b/wordclock_esp8266.ino index e563f2b..b51ebe0 100644 --- a/wordclock_esp8266.ino +++ b/wordclock_esp8266.ino @@ -125,6 +125,8 @@ const String hostname = "wordclock"; // URL DNS server const char WebserverURL[] = "www.wordclock.local"; +int utcOffset = 60; // UTC offset in minutes + // ---------------------------------------------------------------------------------- // GLOBAL VARIABLES // ---------------------------------------------------------------------------------- @@ -174,7 +176,7 @@ uint16_t behaviorUpdatePeriod = PERIOD_TIMEVISUUPDATE; // holdes the period in w // Create necessary global objects UDPLogger logger; WiFiUDP NTPUDP; -NTPClientPlus ntp = NTPClientPlus(NTPUDP, "pool.ntp.org", 1, true); +NTPClientPlus ntp = NTPClientPlus(NTPUDP, "pool.ntp.org", utcOffset, true); LEDMatrix ledmatrix = LEDMatrix(&matrix, brightness, &logger); Tetris mytetris = Tetris(&ledmatrix, &logger); Snake mysnake = Snake(&ledmatrix, &logger); @@ -341,7 +343,6 @@ void setup() { ntp.setupNTPClient(); logger.logString("NTP running"); logger.logString("Time: " + ntp.getFormattedTime()); - logger.logString("TimeOffset (seconds): " + String(ntp.getTimeOffset())); // load persistent variables from EEPROM loadMainColorFromEEPROM(); @@ -446,7 +447,6 @@ void loop() { logger.logString("Time: " + ntp.getFormattedTime()); logger.logString("Date: " + ntp.getFormattedDate()); logger.logString("Day of Week (Mon=1, Sun=7): " + String(ntp.getDayOfWeek())); - logger.logString("TimeOffset (seconds): " + String(ntp.getTimeOffset())); logger.logString("Summertime: " + String(ntp.updateSWChange())); lastNTPUpdate = millis(); watchdogCounter = 30; @@ -469,7 +469,6 @@ void loop() { logger.logString("Time: " + ntp.getFormattedTime()); logger.logString("Date: " + ntp.getFormattedDate()); logger.logString("Day of Week (Mon=1, Sun=7): " + ntp.getDayOfWeek()); - logger.logString("TimeOffset (seconds): " + String(ntp.getTimeOffset())); logger.logString("Summertime: " + String(ntp.updateSWChange())); lastNTPUpdate += 10000; watchdogCounter--; From e6cd5789984d4ace6d39b52df100ef16d6014b57 Mon Sep 17 00:00:00 2001 From: Edgar W Date: Sun, 5 Jan 2025 17:05:04 +0100 Subject: [PATCH 2/4] Add timezone functions to retrieve and update UTC offset from MaxMind API --- timezonefunctions.ino | 90 +++++++++++++++++++++++++++++++++++++++++++ wordclock_esp8266.ino | 1 + 2 files changed, 91 insertions(+) create mode 100644 timezonefunctions.ino diff --git a/timezonefunctions.ino b/timezonefunctions.ino new file mode 100644 index 0000000..75b5ad9 --- /dev/null +++ b/timezonefunctions.ino @@ -0,0 +1,90 @@ +#include +#include +#include +#include "ntp_client_plus.h" +#include "udplogger.h" + +// URL for timezone API +const char *url = "https://js.maxmind.com/geoip/v2.1/city/me?referrer=https%3A%2F%2Fwww.maxmind.com"; + +using namespace ace_time; + +static const int CACHE_SIZE = 1; +static ExtendedZoneProcessorCache zoneProcessorCache; +static ExtendedZoneManager manager( + zonedbx::kZoneAndLinkRegistrySize, + zonedbx::kZoneAndLinkRegistry, + zoneProcessorCache); + +/** + * @brief Get the Timezone as string from the MaxMind API + * + * @param logger UDPLogger object to log messages + * @return String timezone string + */ +String getTimezoneString(UDPLogger &logger) { + std::unique_ptr client(new BearSSL::WiFiClientSecure); + client->setInsecure(); + HTTPClient https; + logger.logString("[HTTPS] Requesting timezone from MaxMind API"); + if (https.begin(*client, url)) { + int httpCode = https.GET(); + + if (httpCode > 0) { + if (httpCode == HTTP_CODE_OK) { + String payload = https.getString(); + logger.logString("[HTTPS] Response received, length: " + String(payload.length())); + + // Search for "time_zone" in the response + int index = payload.indexOf("time_zone"); + if (index != -1) { + int startIndex = payload.indexOf('"', index + 10) + 1; // Find the first '"' after "time_zone" + int endIndex = payload.indexOf('"', startIndex); // Find the closing '"' + if (startIndex != -1 && endIndex != -1) { + String timeZone = payload.substring(startIndex, endIndex); + logger.logString("[HTTPS] Extracted time_zone: " + timeZone); + return timeZone; + } + else { + logger.logString("[HTTPS] Error: Could not extract time_zone value."); + } + } + else { + logger.logString("[HTTPS] Error: time_zone not found in response."); + } + } + } + else { + logger.logString("[HTTPS] request failed, error: " + https.errorToString(httpCode)); + } + https.end(); // Close connection + } + else { + logger.logString("[HTTPS] Unable to connect"); + } + + return ""; +} + +/** + * @brief Update the UTC offset from the timezone string obtained from the MaxMind API + * + * @param logger UDPLogger object to log messages + * @param ntp NTPClientPlus object to set the UTC offset + * @return int + */ +void updateUTCOffsetFromTimezoneAPI(UDPLogger &logger, NTPClientPlus &ntp) { + String timezone = getTimezoneString(logger); + if (timezone.length() > 0) { + uint16_t zone_index = manager.indexForZoneName(timezone.c_str()); + if (zone_index != ZoneManager::kInvalidIndex) { + ExtendedZone zone = manager.getZoneForIndex(zone_index); + int offset = zone.stdOffset().toMinutes(); + logger.logString("[HTTPS] Timezone offset: " + String(offset)); + ntp.setUTCOffset(offset); + } + else { + logger.logString("[HTTPS] Error: Could not find time_zone value in DB. Use hardcoded UTC offset."); + } + } +} \ No newline at end of file diff --git a/wordclock_esp8266.ino b/wordclock_esp8266.ino index b51ebe0..af60bbb 100644 --- a/wordclock_esp8266.ino +++ b/wordclock_esp8266.ino @@ -340,6 +340,7 @@ void setup() { logger.logString("Reset Reason: " + ESP.getResetReason()); // setup NTP + updateUTCOffsetFromTimezoneAPI(logger, ntp); ntp.setupNTPClient(); logger.logString("NTP running"); logger.logString("Time: " + ntp.getFormattedTime()); From 8db36e8fed69b579ca10c030a4fd0bad92e4eb8b Mon Sep 17 00:00:00 2001 From: Edgar W Date: Sat, 15 Feb 2025 13:17:26 +0100 Subject: [PATCH 3/4] Refactor timezone API integration to use IP-API and simplify HTTP requests --- timezonefunctions.ino | 64 ++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/timezonefunctions.ino b/timezonefunctions.ino index 75b5ad9..3e373ce 100644 --- a/timezonefunctions.ino +++ b/timezonefunctions.ino @@ -1,12 +1,8 @@ #include -#include #include #include "ntp_client_plus.h" #include "udplogger.h" -// URL for timezone API -const char *url = "https://js.maxmind.com/geoip/v2.1/city/me?referrer=https%3A%2F%2Fwww.maxmind.com"; - using namespace ace_time; static const int CACHE_SIZE = 1; @@ -17,74 +13,62 @@ static ExtendedZoneManager manager( zoneProcessorCache); /** - * @brief Get the Timezone as string from the MaxMind API + * @brief Request the timezone as string from the IP-API * * @param logger UDPLogger object to log messages * @return String timezone string */ -String getTimezoneString(UDPLogger &logger) { - std::unique_ptr client(new BearSSL::WiFiClientSecure); - client->setInsecure(); - HTTPClient https; - logger.logString("[HTTPS] Requesting timezone from MaxMind API"); - if (https.begin(*client, url)) { - int httpCode = https.GET(); +String getTimeZoneString(UDPLogger &logger) { + WiFiClient client; + HTTPClient http; + logger.logString("[HTTP] Requesting timezone from IP-API"); + if (http.begin(client, "http://ip-api.com/json/")) { + int httpCode = http.GET(); if (httpCode > 0) { - if (httpCode == HTTP_CODE_OK) { - String payload = https.getString(); - logger.logString("[HTTPS] Response received, length: " + String(payload.length())); + if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { + String payload = http.getString(); - // Search for "time_zone" in the response - int index = payload.indexOf("time_zone"); - if (index != -1) { - int startIndex = payload.indexOf('"', index + 10) + 1; // Find the first '"' after "time_zone" - int endIndex = payload.indexOf('"', startIndex); // Find the closing '"' - if (startIndex != -1 && endIndex != -1) { - String timeZone = payload.substring(startIndex, endIndex); - logger.logString("[HTTPS] Extracted time_zone: " + timeZone); - return timeZone; - } - else { - logger.logString("[HTTPS] Error: Could not extract time_zone value."); - } - } - else { - logger.logString("[HTTPS] Error: time_zone not found in response."); + int tzIndex = payload.indexOf("\"timezone\":\""); + if (tzIndex != -1) { + int tzStart = tzIndex + 12; + int tzEnd = payload.indexOf("\"", tzStart); + String timezone = payload.substring(tzStart, tzEnd); + logger.logString("[HTTP] Received timezone: " + timezone); + return timezone; } } - } + } else { - logger.logString("[HTTPS] request failed, error: " + https.errorToString(httpCode)); + Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); } - https.end(); // Close connection + http.end(); // Close connection } else { - logger.logString("[HTTPS] Unable to connect"); + logger.logString("[HTTP] Unable to connect"); } - return ""; } /** - * @brief Update the UTC offset from the timezone string obtained from the MaxMind API + * @brief Update the UTC offset from the timezone string obtained from the IP-API * * @param logger UDPLogger object to log messages * @param ntp NTPClientPlus object to set the UTC offset * @return int */ void updateUTCOffsetFromTimezoneAPI(UDPLogger &logger, NTPClientPlus &ntp) { - String timezone = getTimezoneString(logger); + String timezone = getTimeZoneString(logger); if (timezone.length() > 0) { uint16_t zone_index = manager.indexForZoneName(timezone.c_str()); if (zone_index != ZoneManager::kInvalidIndex) { ExtendedZone zone = manager.getZoneForIndex(zone_index); int offset = zone.stdOffset().toMinutes(); - logger.logString("[HTTPS] Timezone offset: " + String(offset)); + logger.logString("[ZoneManager] Timezone offset (min): " + String(offset)); ntp.setUTCOffset(offset); } else { - logger.logString("[HTTPS] Error: Could not find time_zone value in DB. Use hardcoded UTC offset."); + logger.logString("[ZoneManager] Error: Could not find time_zone value in DB. Use hardcoded UTC offset."); } } } \ No newline at end of file From b808fff60f06505badf209fce21d1deb0da1083e Mon Sep 17 00:00:00 2001 From: Edgar W Date: Sat, 15 Feb 2025 13:22:08 +0100 Subject: [PATCH 4/4] Update README.md to include library installation via Arduino IDE and add AceTime library reference --- README.md | 5 ++++- timezonefunctions.ino | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0668086..7bc3db4 100644 --- a/README.md +++ b/README.md @@ -69,8 +69,11 @@ Please download all these libraries as ZIP from GitHub, and extract them in the - https://github.com/adafruit/Adafruit_NeoPixel - https://github.com/tzapu/WiFiManager - https://github.com/adafruit/Adafruit_BusIO +- https://github.com/bxparks/AceTime -folder structure should look like this: +You can als install these libraries via the library manager in the Arduino IDE. + +The folder structure should look like this: ``` MySketchbookLocation diff --git a/timezonefunctions.ino b/timezonefunctions.ino index 3e373ce..c2d6422 100644 --- a/timezonefunctions.ino +++ b/timezonefunctions.ino @@ -1,5 +1,5 @@ #include -#include +#include // https://github.com/bxparks/AceTime #include "ntp_client_plus.h" #include "udplogger.h"