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/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/timezonefunctions.ino b/timezonefunctions.ino new file mode 100644 index 0000000..c2d6422 --- /dev/null +++ b/timezonefunctions.ino @@ -0,0 +1,74 @@ +#include +#include // https://github.com/bxparks/AceTime +#include "ntp_client_plus.h" +#include "udplogger.h" + +using namespace ace_time; + +static const int CACHE_SIZE = 1; +static ExtendedZoneProcessorCache zoneProcessorCache; +static ExtendedZoneManager manager( + zonedbx::kZoneAndLinkRegistrySize, + zonedbx::kZoneAndLinkRegistry, + zoneProcessorCache); + +/** + * @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) { + 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 || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { + String payload = http.getString(); + + 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 { + Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + } + http.end(); // Close connection + } + else { + logger.logString("[HTTP] Unable to connect"); + } + return ""; +} + +/** + * @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); + 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("[ZoneManager] Timezone offset (min): " + String(offset)); + ntp.setUTCOffset(offset); + } + else { + logger.logString("[ZoneManager] 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 df16870..3605a9d 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); @@ -343,10 +345,10 @@ void setup() { logger.logString("Reset Reason: " + ESP.getResetReason()); // setup NTP + updateUTCOffsetFromTimezoneAPI(logger, ntp); ntp.setupNTPClient(); logger.logString("NTP running"); logger.logString("Time: " + ntp.getFormattedTime()); - logger.logString("TimeOffset (seconds): " + String(ntp.getTimeOffset())); // load persistent variables from EEPROM loadMainColorFromEEPROM(); @@ -457,7 +459,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; @@ -480,7 +481,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--;