From c180a3fe6f789b0d8c7947c12aee5731f853a442 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sat, 31 Jan 2026 19:35:18 +0100 Subject: [PATCH 1/4] implement async DNS lookup - no more stuck NTP requests - adding a wrapper class for DNS lookup (lwIP) - replaces blockig WiFi.hostByName() in NTP and virtual Bus DNS look-ups --- wled00/asyncDNS.h | 69 ++++++++++++++++++++++++++++++++++++++++++ wled00/bus_manager.cpp | 46 ++++++++++++++++++++++++---- wled00/bus_manager.h | 6 ++++ wled00/cfg.cpp | 2 +- wled00/ntp.cpp | 51 +++++++++++++++++++++++++------ 5 files changed, 157 insertions(+), 17 deletions(-) create mode 100644 wled00/asyncDNS.h diff --git a/wled00/asyncDNS.h b/wled00/asyncDNS.h new file mode 100644 index 0000000000..9e1acc098e --- /dev/null +++ b/wled00/asyncDNS.h @@ -0,0 +1,69 @@ +#pragma once +/* + asyncDNS.h - wrapper class for asynchronous DNS lookups using lwIP + by @dedehai +*/ + +#ifndef ASYNC_DNS_H +#define ASYNC_DNS_H + +#include +#include +#include + +enum class DnsResult { Idle, Busy, Success, Error }; + +class AsyncDNS { +private: + ip_addr_t _raw_addr; + volatile DnsResult _status = DnsResult::Idle; + uint16_t _errorcount = 0; + + // callback for dns_gethostbyname(), called when lookup is complete or timed out + static void _dns_callback(const char *name, const ip_addr_t *ipaddr, void *arg) { + AsyncDNS* instance = static_cast(arg); + if (ipaddr) { + instance->_raw_addr = *ipaddr; + instance->_status = DnsResult::Success; + } else { + instance->_status = DnsResult::Error; // note: if query timed out (~5s), DNS lookup is broken until WiFi connection is reset (IDF V4 bug) + instance->_errorcount++; + } + } + +public: + // note: passing the IP as a pointer to query() is not implemented because it is not thread-safe without mutexes + // with the current IDF bug external error handlig is required anyway or dns will just stay stuck + + // non-blocking query function to start DNS lookup + DnsResult query(const char* hostname) { + if (_status == DnsResult::Busy) return DnsResult::Busy; // in progress, waiting for callback + + _status = DnsResult::Busy; + err_t err = dns_gethostbyname(hostname, &_raw_addr, _dns_callback, this); + + if (err == ERR_OK) { + _status = DnsResult::Success; // result already in cache + } else if (err != ERR_INPROGRESS) { + _status = DnsResult::Error; + _errorcount++; + } + return _status; + } + + // get the IP once Success is returned + IPAddress getIP() { + if (_status != DnsResult::Success) return IPAddress(0,0,0,0); + #ifdef ARDUINO_ARCH_ESP32 + return IPAddress(_raw_addr.u_addr.ip4.addr); + #else + return IPAddress(_raw_addr.addr); + #endif + } + + void renew() { _status = DnsResult::Idle; } // reset status to allow re-query + void reset() { _status = DnsResult::Idle; _errorcount = 0; } // reset status and error count + DnsResult status() { return _status; } + uint16_t getErrorCount() { return _errorcount; } +}; +#endif // ASYNC_DNS_H \ No newline at end of file diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index a73146ec0f..ba2c2d6354 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -672,6 +672,7 @@ BusNetwork::BusNetwork(const BusConfig &bc) _hasCCT = false; _UDPchannels = _hasWhite + 3; _client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]); + _DNSlookup = nullptr; #ifdef ARDUINO_ARCH_ESP32 _hostname = bc.text; resolveHostname(); // resolve hostname to IP address if needed @@ -713,12 +714,45 @@ size_t BusNetwork::getPins(uint8_t* pinArray) const { #ifdef ARDUINO_ARCH_ESP32 void BusNetwork::resolveHostname() { static unsigned long nextResolve = 0; - if (Network.isConnected() && millis() > nextResolve && _hostname.length() > 0) { - nextResolve = millis() + 600000; // resolve only every 10 minutes - IPAddress clnt; - if (strlen(cmDNS) > 0) clnt = MDNS.queryHost(_hostname); - else WiFi.hostByName(_hostname.c_str(), clnt); - if (clnt != IPAddress()) _client = clnt; + if (Network.isConnected()) { + if (_DNSlookup != nullptr) { + if (_DNSlookup->status() == DnsResult::Success) { + _client = _DNSlookup->getIP(); + delete _DNSlookup; + _DNSlookup = nullptr; + } + } + if (millis() > nextResolve && _hostname.length() > 0) { + nextResolve = millis() + 600000; // resolve only every 10 minutes + IPAddress clnt; + if (strlen(cmDNS) > 0) { + clnt = MDNS.queryHost(_hostname); + if (clnt != IPAddress()) _client = clnt; // update client IP if not null + } + else { + if (_DNSlookup == nullptr) { + _DNSlookup = new AsyncDNS; + _DNSlookup->query(_hostname.c_str()); // start async DNS query + } else { + // there is a previous, unresolved query (should be in error state) + // TODO: all this error handling is only required because of an IDF bug, otherwise we could just query again later, should be fixed in V5 + if (_DNSlookup->status() == DnsResult::Error) { + if (_DNSlookup->getErrorCount() <= 2) { + _DNSlookup->renew(); // clear error state, keep error count + _DNSlookup->query(_hostname.c_str()); // restart async DNS query + } else { + forceReconnect = true; // reset network connection as dns is probably stuck + delete _DNSlookup; + _DNSlookup = nullptr; + } + } + else { + delete _DNSlookup; // cleanup if other error just in case (should not happen) + _DNSlookup = nullptr; + } + } + } + } } } #endif diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index a4cd370c90..8ce9a0564b 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -17,6 +17,9 @@ #include "pin_manager.h" #include #include +#ifdef ARDUINO_ARCH_ESP32 +#include "asyncDNS.h" +#endif #if __cplusplus >= 201402L using std::make_unique; @@ -364,6 +367,9 @@ class BusNetwork : public Bus { private: IPAddress _client; + #ifdef ARDUINO_ARCH_ESP32 + AsyncDNS* _DNSlookup; + #endif uint8_t _UDPtype; uint8_t _UDPchannels; bool _broadcastLock; diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 8020f24886..32a789eb64 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -131,7 +131,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { getStringFromJson(apPass, ap["psk"] , 65); //normally not present due to security //int ap_pskl = ap[F("pskl")]; CJSON(apChannel, ap[F("chan")]); - if (apChannel > 13 || apChannel < 1) apChannel = 1; + if (apChannel > 13 || apChannel < 1) apChannel = 6; // reset to default if invalid CJSON(apHide, ap[F("hide")]); if (apHide > 1) apHide = 1; CJSON(apBehavior, ap[F("behav")]); diff --git a/wled00/ntp.cpp b/wled00/ntp.cpp index abad5c3c9d..b6b26ee1b2 100644 --- a/wled00/ntp.cpp +++ b/wled00/ntp.cpp @@ -1,6 +1,7 @@ #include "src/dependencies/timezone/Timezone.h" #include "wled.h" #include "fcn_declare.h" +#include "asyncDNS.h" // WARNING: may cause errors in sunset calculations on ESP8266, see #3400 // building with `-D WLED_USE_REAL_MATH` will prevent those errors at the expense of flash and RAM @@ -180,6 +181,7 @@ void handleTime() { } } +AsyncDNS* ntpDNSlookup; void handleNetworkTime() { if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > (1000*NTP_SYNC_INTERVAL) && WLED_CONNECTED) @@ -189,26 +191,54 @@ void handleNetworkTime() #ifdef ARDUINO_ARCH_ESP32 // I had problems using udp.flush() on 8266 while (ntpUdp.parsePacket() > 0) ntpUdp.flush(); // flush any existing packets #endif - sendNTPPacket(); - ntpPacketSentTime = millis(); + if (!ntpServerIP.fromString(ntpServerName)) // check if server is IP or domain + { + if (ntpDNSlookup == nullptr) ntpDNSlookup = new AsyncDNS; + DnsResult res = ntpDNSlookup->status(); + switch (res) { + case DnsResult::Idle: + //DEBUG_PRINTF_P(PSTR("Resolving NTP server name: %s\n"), ntpServerName); + Serial.printf_P(PSTR("Resolving NTP server name: %s\n"), ntpServerName); + ntpDNSlookup->query(ntpServerName); // start dnslookup asynchronously + return; + + case DnsResult::Busy: + return; // still in progress + + case DnsResult::Success: + DEBUG_PRINTF_P(PSTR("NTP IP resolved: %s\n"), ntpServerIP.toString().c_str()); + Serial.printf_P(PSTR("NTP IP resolved: %s\n"), ntpServerIP.toString().c_str()); + ntpServerIP = ntpDNSlookup->getIP(); + sendNTPPacket(); + break; + + case DnsResult::Error: + DEBUG_PRINTLN(F("NTP DNS failed")); + ntpDNSlookup->renew(); // try a new lookup next time + if ((toki.getTimeSource() == TOKI_TS_NONE) || ntpDNSlookup->getErrorCount() >= 3) { + // no time source or after 3 failed attempts (30min), reset network connection as dns is probably stuck (TODO: IDF bug, should be fixed in V5) + if (!realtimeMode) forceReconnect = true; // do not disturb streaming clients + delete ntpDNSlookup; + ntpDNSlookup = nullptr; + } + ntpLastSyncTime = toki.getTimeSource() == TOKI_TS_NONE ? NTP_NEVER : millis() - (1000*NTP_SYNC_INTERVAL - 600000); // keep trying if no time source, otherwise pause for 10 minutes + break; + } + } + else + sendNTPPacket(); } if (checkNTPResponse()) { ntpLastSyncTime = millis(); + delete ntpDNSlookup; + ntpDNSlookup = nullptr; } } } void sendNTPPacket() { - if (!ntpServerIP.fromString(ntpServerName)) //see if server is IP or domain - { - #ifdef ESP8266 - WiFi.hostByName(ntpServerName, ntpServerIP, 750); - #else - WiFi.hostByName(ntpServerName, ntpServerIP); - #endif - } DEBUG_PRINTLN(F("send NTP")); byte pbuf[NTP_PACKET_SIZE]; @@ -227,6 +257,7 @@ void sendNTPPacket() ntpUdp.beginPacket(ntpServerIP, 123); //NTP requests are to port 123 ntpUdp.write(pbuf, NTP_PACKET_SIZE); ntpUdp.endPacket(); + ntpPacketSentTime = millis(); } static bool isValidNtpResponse(const byte* ntpPacket) { From 32cda7d793d2c275597422f43d2943f11ed491d2 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sat, 31 Jan 2026 19:51:22 +0100 Subject: [PATCH 2/4] add forgotten guarding ifdef --- wled00/bus_manager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index ba2c2d6354..4f3a891a33 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -672,7 +672,9 @@ BusNetwork::BusNetwork(const BusConfig &bc) _hasCCT = false; _UDPchannels = _hasWhite + 3; _client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]); + #ifdef ARDUINO_ARCH_ESP32 _DNSlookup = nullptr; + #endif #ifdef ARDUINO_ARCH_ESP32 _hostname = bc.text; resolveHostname(); // resolve hostname to IP address if needed From 73ae3de5b85b294470c513aeb60c523f2197e942 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 1 Feb 2026 14:24:47 +0100 Subject: [PATCH 3/4] fix suggestions, use blocking version in busmanager for simplicity, fix busmanager bug --- wled00/asyncDNS.h | 66 ++++++++++++++++++++---------------------- wled00/bus_manager.cpp | 58 ++++++++++++------------------------- wled00/bus_manager.h | 3 -- wled00/ntp.cpp | 30 +++++++++---------- 4 files changed, 64 insertions(+), 93 deletions(-) diff --git a/wled00/asyncDNS.h b/wled00/asyncDNS.h index 9e1acc098e..8e0605f3e4 100644 --- a/wled00/asyncDNS.h +++ b/wled00/asyncDNS.h @@ -4,56 +4,36 @@ by @dedehai */ -#ifndef ASYNC_DNS_H -#define ASYNC_DNS_H - #include +#include #include #include -enum class DnsResult { Idle, Busy, Success, Error }; class AsyncDNS { -private: - ip_addr_t _raw_addr; - volatile DnsResult _status = DnsResult::Idle; - uint16_t _errorcount = 0; - - // callback for dns_gethostbyname(), called when lookup is complete or timed out - static void _dns_callback(const char *name, const ip_addr_t *ipaddr, void *arg) { - AsyncDNS* instance = static_cast(arg); - if (ipaddr) { - instance->_raw_addr = *ipaddr; - instance->_status = DnsResult::Success; - } else { - instance->_status = DnsResult::Error; // note: if query timed out (~5s), DNS lookup is broken until WiFi connection is reset (IDF V4 bug) - instance->_errorcount++; - } - } - public: // note: passing the IP as a pointer to query() is not implemented because it is not thread-safe without mutexes - // with the current IDF bug external error handlig is required anyway or dns will just stay stuck + // with the IDF V4 bug external error handling is required anyway or dns can just stay stuck + enum class result { Idle, Busy, Success, Error }; // non-blocking query function to start DNS lookup - DnsResult query(const char* hostname) { - if (_status == DnsResult::Busy) return DnsResult::Busy; // in progress, waiting for callback + result query(const char* hostname) { + if (_status == result::Busy) return result::Busy; // in progress, waiting for callback - _status = DnsResult::Busy; + _status = result::Busy; err_t err = dns_gethostbyname(hostname, &_raw_addr, _dns_callback, this); - if (err == ERR_OK) { - _status = DnsResult::Success; // result already in cache + _status = result::Success; // result already in cache } else if (err != ERR_INPROGRESS) { - _status = DnsResult::Error; + _status = result::Error; _errorcount++; } return _status; } // get the IP once Success is returned - IPAddress getIP() { - if (_status != DnsResult::Success) return IPAddress(0,0,0,0); + const IPAddress getIP() { + if (_status != result::Success) return IPAddress(0,0,0,0); #ifdef ARDUINO_ARCH_ESP32 return IPAddress(_raw_addr.u_addr.ip4.addr); #else @@ -61,9 +41,25 @@ class AsyncDNS { #endif } - void renew() { _status = DnsResult::Idle; } // reset status to allow re-query - void reset() { _status = DnsResult::Idle; _errorcount = 0; } // reset status and error count - DnsResult status() { return _status; } - uint16_t getErrorCount() { return _errorcount; } + void renew() { _status = result::Idle; } // reset status to allow re-query + void reset() { _status = result::Idle; _errorcount = 0; } // reset status and error count + const result status() { return _status; } + const uint16_t getErrorCount() { return _errorcount; } + + private: + ip_addr_t _raw_addr; + std::atomic _status { result::Idle }; + uint16_t _errorcount = 0; + + // callback for dns_gethostbyname(), called when lookup is complete or timed out + static void _dns_callback(const char *name, const ip_addr_t *ipaddr, void *arg) { + AsyncDNS* instance = reinterpret_cast(arg); + if (ipaddr) { + instance->_raw_addr = *ipaddr; + instance->_status = result::Success; + } else { + instance->_status = result::Error; // note: if query timed out (~5s), DNS lookup is broken until WiFi connection is reset (IDF V4 bug) + instance->_errorcount++; + } + } }; -#endif // ASYNC_DNS_H \ No newline at end of file diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 4f3a891a33..fc17470d01 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -673,9 +673,6 @@ BusNetwork::BusNetwork(const BusConfig &bc) _UDPchannels = _hasWhite + 3; _client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]); #ifdef ARDUINO_ARCH_ESP32 - _DNSlookup = nullptr; - #endif - #ifdef ARDUINO_ARCH_ESP32 _hostname = bc.text; resolveHostname(); // resolve hostname to IP address if needed #endif @@ -715,44 +712,22 @@ size_t BusNetwork::getPins(uint8_t* pinArray) const { #ifdef ARDUINO_ARCH_ESP32 void BusNetwork::resolveHostname() { - static unsigned long nextResolve = 0; + static AsyncDNS DNSlookup; // TODO: make this dynamic? requires to handle the callback properly if (Network.isConnected()) { - if (_DNSlookup != nullptr) { - if (_DNSlookup->status() == DnsResult::Success) { - _client = _DNSlookup->getIP(); - delete _DNSlookup; - _DNSlookup = nullptr; - } + IPAddress clnt; + if (strlen(cmDNS) > 0) { + clnt = MDNS.queryHost(_hostname); + if (clnt != IPAddress()) _client = clnt; // update client IP if not null } - if (millis() > nextResolve && _hostname.length() > 0) { - nextResolve = millis() + 600000; // resolve only every 10 minutes - IPAddress clnt; - if (strlen(cmDNS) > 0) { - clnt = MDNS.queryHost(_hostname); - if (clnt != IPAddress()) _client = clnt; // update client IP if not null + else { + int timeout = 5000; // 5 seconds timeout + DNSlookup.reset(); + DNSlookup.query(_hostname.c_str()); // start async DNS query + while (DNSlookup.status() == AsyncDNS::result::Busy && timeout-- > 0) { + delay(1); } - else { - if (_DNSlookup == nullptr) { - _DNSlookup = new AsyncDNS; - _DNSlookup->query(_hostname.c_str()); // start async DNS query - } else { - // there is a previous, unresolved query (should be in error state) - // TODO: all this error handling is only required because of an IDF bug, otherwise we could just query again later, should be fixed in V5 - if (_DNSlookup->status() == DnsResult::Error) { - if (_DNSlookup->getErrorCount() <= 2) { - _DNSlookup->renew(); // clear error state, keep error count - _DNSlookup->query(_hostname.c_str()); // restart async DNS query - } else { - forceReconnect = true; // reset network connection as dns is probably stuck - delete _DNSlookup; - _DNSlookup = nullptr; - } - } - else { - delete _DNSlookup; // cleanup if other error just in case (should not happen) - _DNSlookup = nullptr; - } - } + if (DNSlookup.status() == AsyncDNS::result::Success) { + _client = DNSlookup.getIP(); // update client IP } } } @@ -1336,12 +1311,17 @@ void BusManager::on() { } } #else + static uint32_t nextResolve = 0; // initial resolve is done on bus creation + bool resolveNow = (millis() - nextResolve >= 600000); // wait at least 10 minutes between hostname resolutions (blocking call) for (auto &bus : busses) if (bus->isVirtual()) { // virtual/network bus should check for IP change if hostname is specified // otherwise there are no endpoints to force DNS resolution BusNetwork &b = static_cast(*bus); - b.resolveHostname(); + if (resolveNow) + b.resolveHostname(); } + if (resolveNow) + nextResolve = millis(); #endif #ifdef ESP32_DATA_IDLE_HIGH esp32RMTInvertIdle(); diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 8ce9a0564b..2a9fadcab4 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -367,9 +367,6 @@ class BusNetwork : public Bus { private: IPAddress _client; - #ifdef ARDUINO_ARCH_ESP32 - AsyncDNS* _DNSlookup; - #endif uint8_t _UDPtype; uint8_t _UDPchannels; bool _broadcastLock; diff --git a/wled00/ntp.cpp b/wled00/ntp.cpp index b6b26ee1b2..6e4682d6c0 100644 --- a/wled00/ntp.cpp +++ b/wled00/ntp.cpp @@ -10,7 +10,7 @@ * Acquires time from NTP server */ //#define WLED_DEBUG_NTP -#define NTP_SYNC_INTERVAL 42000UL //Get fresh NTP time about twice per day +#define NTP_SYNC_INTERVAL 15//42000UL //Get fresh NTP time about twice per day Timezone* tz; @@ -181,9 +181,9 @@ void handleTime() { } } -AsyncDNS* ntpDNSlookup; void handleNetworkTime() { + static AsyncDNS* ntpDNSlookup = nullptr; if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > (1000*NTP_SYNC_INTERVAL) && WLED_CONNECTED) { if (millis() - ntpPacketSentTime > 10000) @@ -194,34 +194,34 @@ void handleNetworkTime() if (!ntpServerIP.fromString(ntpServerName)) // check if server is IP or domain { if (ntpDNSlookup == nullptr) ntpDNSlookup = new AsyncDNS; - DnsResult res = ntpDNSlookup->status(); + AsyncDNS::result res = ntpDNSlookup->status(); switch (res) { - case DnsResult::Idle: + case AsyncDNS::result::Idle: //DEBUG_PRINTF_P(PSTR("Resolving NTP server name: %s\n"), ntpServerName); - Serial.printf_P(PSTR("Resolving NTP server name: %s\n"), ntpServerName); ntpDNSlookup->query(ntpServerName); // start dnslookup asynchronously return; - case DnsResult::Busy: + case AsyncDNS::result::Busy: return; // still in progress - case DnsResult::Success: - DEBUG_PRINTF_P(PSTR("NTP IP resolved: %s\n"), ntpServerIP.toString().c_str()); - Serial.printf_P(PSTR("NTP IP resolved: %s\n"), ntpServerIP.toString().c_str()); + case AsyncDNS::result::Success: ntpServerIP = ntpDNSlookup->getIP(); + DEBUG_PRINTF_P(PSTR("NTP IP resolved: %s\n"), ntpServerIP.toString().c_str()); sendNTPPacket(); + delete ntpDNSlookup; + ntpDNSlookup = nullptr; break; - case DnsResult::Error: + case AsyncDNS::result::Error: DEBUG_PRINTLN(F("NTP DNS failed")); ntpDNSlookup->renew(); // try a new lookup next time - if ((toki.getTimeSource() == TOKI_TS_NONE) || ntpDNSlookup->getErrorCount() >= 3) { - // no time source or after 3 failed attempts (30min), reset network connection as dns is probably stuck (TODO: IDF bug, should be fixed in V5) - if (!realtimeMode) forceReconnect = true; // do not disturb streaming clients + if (ntpDNSlookup->getErrorCount() > 6) { + // after 6 failed attempts (30min), reset network connection as dns is probably stuck (TODO: IDF bug, should be fixed in V5) + if (offMode) forceReconnect = true; // do not disturb while LEDs are running delete ntpDNSlookup; ntpDNSlookup = nullptr; } - ntpLastSyncTime = toki.getTimeSource() == TOKI_TS_NONE ? NTP_NEVER : millis() - (1000*NTP_SYNC_INTERVAL - 600000); // keep trying if no time source, otherwise pause for 10 minutes + ntpLastSyncTime = millis() - (1000*NTP_SYNC_INTERVAL - 300000); // pause for 5 minutes break; } } @@ -231,8 +231,6 @@ void handleNetworkTime() if (checkNTPResponse()) { ntpLastSyncTime = millis(); - delete ntpDNSlookup; - ntpDNSlookup = nullptr; } } } From e78b4a245daf45bd45510f24e9e11397823a2cf1 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 1 Feb 2026 22:30:38 +0100 Subject: [PATCH 4/4] revert debug timing --- wled00/ntp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/ntp.cpp b/wled00/ntp.cpp index 6e4682d6c0..61ac05c903 100644 --- a/wled00/ntp.cpp +++ b/wled00/ntp.cpp @@ -10,7 +10,7 @@ * Acquires time from NTP server */ //#define WLED_DEBUG_NTP -#define NTP_SYNC_INTERVAL 15//42000UL //Get fresh NTP time about twice per day +#define NTP_SYNC_INTERVAL 42000UL //Get fresh NTP time about twice per day Timezone* tz;