NTPClient blocks for 1.5s every 15s if network connectivity is down/poor
dalbert2 opened this issue · 3 comments
getTimePtr()->getTime() is called every syncInterval which is 15 seconds by default in times of poor connectivity or NTP server down. Unfortunately, getTime() also blocks for NTP_TIMEOUT (1.5 seconds) with each failed attempt. Blocking for that long in an embedded system is usually bad news and is disastrous if called from within an ISR.
GetTime() also feeds the watchdog, but doesn't yield() to give other core OS threads time to run. In other words, NTP Timeouts will be bad news in many systems as currently implemented. There are multiple potential solutions including https://github.com/me-no-dev/ESPAsyncUDP
Note: this is a particularly serious problem if now() is called from within an ISR context (e.g. a Ticker). NTPClientLib installs a sync function (getTime()) for TimeLib and if the sync period has expired, that function will be called when now() is called. Because getTime() uses the network and can block for an extended period, it is particularly bad (and will usually cause an exception) if it happens when called in an ISR context.
A solution for now is to avoid calling now() within an ISR context or to create a non-blocking version of now() that avoids the call to getTime() and to use this non-blocking version for any calls that may be made from an ISR context.
You can reduce timeout for NTP of set a lower retrial rate using bool setInterval (int shortInterval, int longInterval)
I'm thinking about using AsyncUDP library but this would make this project compatible only with Espresif microcontrollers.
I've added a way to configure NTP timeout. Maybe it may work as a workaround.
To avoid frequent NTP requests in case of bad connection I've added a condition to keep long interval if time is already set. This will only happen on 1st error, because Time library set status to needSync after it.