diff --git a/include/time_manager.h b/include/time_manager.h new file mode 100644 index 0000000..0d65bbb --- /dev/null +++ b/include/time_manager.h @@ -0,0 +1,52 @@ +#ifndef TIME_MANAGER_H +#define TIME_MANAGER_H + +#include +#include +#include "udp_logger.h" + +#define NTP_MAX_UPDATE_TIME_US (500 * 1000) // 500ms max update time + +class TimeManager +{ +public: + struct tm time_info(void); + bool ntp_sync_successful(void) const; // was there a NTP sync once? + bool ntp_time_update(bool init = false); + bool ntp_update_failed_prolonged(void) const; // indicates if maximum time since last NTP update was too long + void log_time(struct tm time_info) const; // log local_time + void increment_time_now_local(void); + + int tm_min(void); + int tm_hour(void); + int tm_year(void); + bool tm_isdst(void); // true if summertime + + TimeManager(const char *tz, + const char *ntp_server, + uint32 ntp_update_period_s, + uint32 ntp_retry_delay_us, + uint32 ntp_max_offline_time_s, + UDPLogger *logger); + +private: + void set_up_ntp(void) const; // set up NTP server + void set_up_timer_isr(void) const; // set up timer interrupt + const char *_tz; // timezone + const char *_ntp_server; // used ntp server + UDPLogger *_logger; // logger instance + struct tm _time_info; // structure tm holds time information + time_t _time_now_local = 0; // local timer value, updated by timer interrupt and synced by NTP when needed + time_t _time_now_ntp = 0; // NTP timer value, seconds since Epoch (1970) - UTC, only synced by NTP request. + uint32 _ntp_max_offline_time_s; // maximum time in seconds which is considered ok since last NTP update + uint32 _ntp_update_period_s; // NTP request update period in seconds + uint32 _ntp_retry_delay_us; // minimum retry delay in us between two NTP requests + uint32 _ntp_sync_timestamp_us = 0; // timestamp of last successful ntp update +}; + +inline void TimeManager::increment_time_now_local(void) +{ + _time_now_local++; +} + +#endif /* TIME_MANAGER_H */ diff --git a/include/wordclock_constants.h b/include/wordclock_constants.h index 202b652..f6c918c 100644 --- a/include/wordclock_constants.h +++ b/include/wordclock_constants.h @@ -33,17 +33,18 @@ #define NIGHTMODE_END_MIN (0) // Timings in us -#define PERIOD_ANIMATION_US (200 * 1000) // 200ms -#define PERIOD_CLOCK_UPDATE_US (1 * 1000 * 1000) // 1s -#define PERIOD_HEARTBEAT_US (1 * 1000 * 1000) // 1s -#define PERIOD_MATRIX_UPDATE_US (100 * 1000) // 100ms -#define PERIOD_NIGHTMODE_CHECK_US (20 * 1000 * 1000) // 20s -#define PERIOD_NTP_UPDATE_US (30 * 1000 * 1000) // 30s -#define PERIOD_PONG_US (10 * 1000) // 10ms -#define PERIOD_SNAKE_US (50 * 1000) // 50ms -#define PERIOD_STATE_CHANGE_US (10 * 1000 * 1000) // 10s -#define PERIOD_TETRIS_US (50 * 1000) // 50ms -#define TIMEOUT_LEDDIRECT_US (5 * 1000 * 1000) // 5s +#define PERIOD_ANIMATION_US (200 * 1000) // 200ms +#define PERIOD_CLOCK_UPDATE_US (1 * 1000 * 1000) // 1s +#define PERIOD_HEARTBEAT_US (1 * 1000 * 1000) // 1s +#define PERIOD_MATRIX_UPDATE_US (100 * 1000) // 100ms +#define PERIOD_NIGHTMODE_CHECK_US (20 * 1000 * 1000) // 20s +#define PERIOD_TIME_UPDATE_US (500 * 1000) // 500ms +#define PERIOD_PONG_US (10 * 1000) // 10ms +#define PERIOD_SNAKE_US (50 * 1000) // 50ms +#define PERIOD_STATE_CHANGE_US (10 * 1000 * 1000) // 10s +#define PERIOD_TETRIS_US (50 * 1000) // 50ms +#define TIMEOUT_LEDDIRECT_US (5 * 1000 * 1000) // 5s +#define PERIOD_BRIGHTNESS_UPDATE_US (5 * 60 * 1000 * 1000) // 300s #define SHORT_PRESS_US (100 * 1000) // 100ms #define LONG_PRESS_US (2 * 1000 * 1000) // 2s @@ -68,11 +69,11 @@ #define MATRIX_HEIGHT (11) // NTP macros -#define BUILD_YEAR (__DATE__ + 7) /* Will expand to current year at compile time as string. */ -#define NTP_MININUM_RX_YEAR (atoi(BUILD_YEAR) - 1) /* Will expand to current year at compile time minus one. */ +#define BUILD_YEAR (__DATE__ + 7) // Will expand to current year at compile time as string. +#define NTP_MININUM_RX_YEAR (atoi(BUILD_YEAR) - 1) // Will expand to current year minus one at compile time. #define NTP_MININUM_YEAR (1900) // NTP minimum year is 1900 -#define NTP_MAX_UPDATE_TIME_US (500000) // 500ms max update time -#define NTP_NEXT_UPDATE_DELAY_US (10000000) // 10s delay time between updates -#define NTP_WATCHDOG_COUNTER_INIT (30) // Watchdog value, count of retries before restart +#define NTP_UPDATE_PERIOD_S (12 * 3600) // 12h period between updates +#define NTP_RETRY_DELAY_US (10 * 1000 * 1000) // 10s retry delay time between failed NTP requests +#define NTP_MAX_OFFLINE_TIME_S (7 * 24 * 3600) // Watchdog value, maxmimum offline time before a restart is triggered #endif /* WORDCLOCK_CONSTANTS_H */ diff --git a/include/wordclock_esp8266.h b/include/wordclock_esp8266.h index 7bcc84b..b839ee2 100644 --- a/include/wordclock_esp8266.h +++ b/include/wordclock_esp8266.h @@ -61,12 +61,11 @@ typedef enum // ---------------------------------------------------------------------------------- // FUNCTIONS DECLARATIONS // ---------------------------------------------------------------------------------- -bool get_ntp_time(uint32 timeout); +bool check_wifi_status(void); String leading_zero2digit(int value); uint8_t calculate_dynamic_brightness(uint8_t min_brightness, uint8_t max_brightness, int hours, int minutes, bool summertime); uint8_t update_brightness(void); void check_night_mode(void); -void check_wifi_status(void); void cold_start_setup(void); void draw_main_color(void); void handle_button(void); @@ -76,8 +75,6 @@ void handle_data_request(void); void handle_led_direct(void); void limit_value_ranges(void); void log_data(void); -void log_time(tm local_time); -void ntp_time_update(uint32 max_update_time); void on_state_entry(uint8_t state); void read_settings_from_EEPROM(void); void reset_wifi_credentials(void); diff --git a/platformio.ini b/platformio.ini index 5c21c7d..c98bd21 100644 --- a/platformio.ini +++ b/platformio.ini @@ -14,13 +14,15 @@ default_envs = nodemcuv2 [env] platform = espressif8266 board = nodemcuv2 +build_flags = -DUSING_TIM_DIV16=1 framework = arduino lib_deps = - adafruit/Adafruit BusIO@^1.15.0 - adafruit/Adafruit NeoMatrix@^1.3.0 - adafruit/Adafruit NeoPixel@^1.11.0 - densaugeo/base64@^1.4.0 - tzapu/WiFiManager@^0.16.0 + adafruit/Adafruit BusIO@^1.15.0 + adafruit/Adafruit NeoMatrix@^1.3.0 + adafruit/Adafruit NeoPixel@^1.11.0 + densaugeo/base64@^1.4.0 + khoih-prog/ESP8266TimerInterrupt@^1.6.0 + tzapu/WiFiManager@^0.16.0 [env:nodemcuv2] monitor_speed = 115200 diff --git a/src/connectivity/time_manager.cpp b/src/connectivity/time_manager.cpp new file mode 100644 index 0000000..0447583 --- /dev/null +++ b/src/connectivity/time_manager.cpp @@ -0,0 +1,166 @@ +#include "time_manager.h" +#include // https://github.com/khoih-prog/ESP8266TimerInterrupt +#include "wordclock_constants.h" +#include "time.h" + +extern UDPLogger logger; +extern ESP8266Timer ITimer; // ESP8266 Timer +extern void IRAM_ATTR TimerHandler(); // ISR function + +// ---------------------------------------------------------------------------------- +// Class +// ---------------------------------------------------------------------------------- +TimeManager::TimeManager(const char *tz, + const char *ntp_server, + uint32 ntp_update_period_s, + uint32 ntp_retry_delay_us, + uint32 ntp_max_offline_time_s, + UDPLogger *logger) +{ + _tz = tz; + _ntp_server = ntp_server; + _ntp_max_offline_time_s = ntp_max_offline_time_s; + _ntp_retry_delay_us = ntp_retry_delay_us; + _ntp_update_period_s = ntp_update_period_s; + _logger = logger; +} + +struct tm TimeManager::time_info(void) +{ + localtime_r(&_time_now_local, &_time_info); // convert time + return _time_info; +} + +bool TimeManager::ntp_sync_successful(void) const +{ + return (_time_now_ntp > 0); +} + +/** + * @brief NTP time update, should be called in loop(). + * + * @retval true if last update was successful + */ +bool TimeManager::ntp_time_update(bool init) +{ + // Check if minimum update delay has elapsed + if (!init && (((system_get_time() - _ntp_sync_timestamp_us) <= _ntp_retry_delay_us) || ((system_get_time() - _ntp_sync_timestamp_us) <= (_ntp_update_period_s * 1000000)))) + { + return false; + } + + if (init) + { + set_up_ntp(); // set up NTP server once + } + + bool ntp_update_successful = false; // NTP time update + struct tm time_info; // local NTP time info + + _ntp_sync_timestamp_us = system_get_time(); // NTP update start time + + do + { + time(&_time_now_ntp); // get time from server and save it into _time_now_ntp + localtime_r(&_time_now_ntp, &time_info); // convert time + yield(); // since this loop could take up to NTP_MAX_UPDATE_TIME_US + + } while (((system_get_time() - _ntp_sync_timestamp_us) <= NTP_MAX_UPDATE_TIME_US) && (time_info.tm_year < (NTP_MININUM_RX_YEAR - NTP_MININUM_YEAR))); + + ntp_update_successful = (time_info.tm_year <= (NTP_MININUM_RX_YEAR - NTP_MININUM_YEAR)) ? false : true; // sanity check + + if (ntp_update_successful == true) + { + _ntp_sync_timestamp_us = system_get_time(); // save NTP update timestamp + _time_info = time_info; // take over time_info to member variable + log_time(_time_info); // log current time + + if (!init && (abs(_time_now_ntp - _time_now_local) > 10)) // in the case that the local time drifted more than 10s in _ntp_update_period_s + { + _logger->log_string(String("Difference between local and NTP time was more than 10 seconds!\n")); + _logger->log_string("Local time was: " + String(_time_now_local) + ", NTP time is: " + String(_time_now_ntp) + "\n"); + } + + _time_now_local = _time_now_ntp; // sync local time with NTP time + + if (init) // only set up the timer once after NTP update was successful + { + set_up_timer_isr(); + } + } + else + { + logger.log_string("NTP-Update was not successful. Retrying in " + String(_ntp_retry_delay_us / 1000) + "ms.\n"); + } + + return ntp_update_successful; +} + +bool TimeManager::ntp_update_failed_prolonged(void) const +{ + return _time_now_local >= (_time_now_ntp + (time_t)_ntp_max_offline_time_s); +} + +int TimeManager::tm_min(void) +{ + localtime_r(&_time_now_local, &_time_info); // convert time + return _time_info.tm_min; +} + +int TimeManager::tm_hour(void) +{ + localtime_r(&_time_now_local, &_time_info); // convert time + return _time_info.tm_hour; +} + +int TimeManager::tm_year(void) +{ + localtime_r(&_time_now_local, &_time_info); // convert time + return _time_info.tm_year; +} + +bool TimeManager::tm_isdst(void) +{ + localtime_r(&_time_now_local, &_time_info); // convert time + return _time_info.tm_isdst > 0; +} + +// TODO +void TimeManager::set_up_timer_isr(void) const +{ + // set up timer interrupt after NTP update is done + if (ntp_sync_successful()) + { + (void)ITimer.attachInterruptInterval(PERIOD_CLOCK_UPDATE_US, TimerHandler); + } + else + { + logger.log_string("WARNING: Timer interrupt was not attached!"); + } +} + +void TimeManager::set_up_ntp(void) const +{ + if ((_tz != nullptr) && (_ntp_server != nullptr)) + { + // set up NTP server and timezone at init + configTime(_tz, _ntp_server); + logger.log_string(String("NTP server was initialized!")); + } + else + { + logger.log_string(String("Timezone and/or NTP-Server were not given!")); + } +} + +/** + * @brief Log time_info as string. + * + * @param local_time + */ +void TimeManager::log_time(struct tm time_info) const +{ + char strftime_buf[64]; // Time string buffer + strftime(strftime_buf, sizeof(strftime_buf), "%c", &time_info); + logger.log_string(String(strftime_buf)); +} diff --git a/src/wordclock_esp8266.cpp b/src/wordclock_esp8266.cpp index 900e5e6..78ab92a 100644 --- a/src/wordclock_esp8266.cpp +++ b/src/wordclock_esp8266.cpp @@ -27,10 +27,11 @@ #include // https://github.com/adafruit/Adafruit_NeoMatrix #include // NeoPixel library used to run the NeoPixel LEDs: https://github.com/adafruit/Adafruit_NeoPixel #include -#include //from ESP8266 Arduino Core (automatically installed when ESP8266 was installed via Boardmanager) +#include // from ESP8266 Arduino Core (automatically installed when ESP8266 was installed via Boardmanager) +#include // https://github.com/khoih-prog/ESP8266TimerInterrupt +#include // https://github.com/khoih-prog/ESP8266TimerInterrupt #include #include -#include #include // https://github.com/tzapu/WiFiManager WiFi Configuration Magic // own libraries @@ -42,6 +43,7 @@ #include "render_functions.h" #include "snake.h" #include "tetris.h" +#include "time_manager.h" #include "udp_logger.h" #include "wordclock_constants.h" @@ -52,8 +54,8 @@ UDPLogger logger; // Global UDP logger instance Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(MATRIX_WIDTH, MATRIX_HEIGHT + 1, NEOPIXEL_PIN, NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG, NEO_GRB + NEO_KHZ800); // NeoMatrix -ESP8266WebServer webserver(HTTP_PORT); // Webserver LEDMatrix led_matrix = LEDMatrix(&matrix, DEFAULT_BRIGHTNESS, &logger); // NeoMatrix wrapper +ESP8266WebServer webserver(HTTP_PORT); // Webserver // ---------------------------------------------------------------------------------- // STATIC VARIABLES @@ -69,14 +71,14 @@ static Pong pong = Pong(&led_matrix, &logger); static Snake snake = Snake(&led_matrix, &logger); static Tetris tetris = Tetris(&led_matrix, &logger); -// Time -static struct tm time_info; // Structure tm holds time information -static time_t time_now; // Seconds since Epoch (1970) - UTC +// Time ManagerW +static TimeManager tm_mgr = TimeManager(MY_TZ, NTP_SERVER_URL, + NTP_UPDATE_PERIOD_S, + NTP_RETRY_DELAY_US, + NTP_MAX_OFFLINE_TIME_S, + &logger); -// NTP -static uint32 last_ntp_update_us = 0; // Time of last NTP update - -// State variables +// State variablesW static bool flg_night_mode = false; // State of nightmode static bool flg_reset_wifi_creds = false; // Used to reset stored wifi credentials static float filter_factor = DEFAULT_SMOOTHING_FACTOR; // Stores smoothing factor for led transition, value of 1 represents no smoothing. @@ -98,9 +100,23 @@ static const float qtly_brightness_factor[96] = { 0.998f, 0.997f, 0.995f, 0.991f, 0.986f, 0.978f, 0.966f, 0.949f, 0.927f, 0.896f, 0.858f, 0.811f, 0.755f, 0.691f, 0.62f, 0.545f, 0.468f, 0.392f, 0.32f, 0.253f, 0.194f, 0.143f, 0.101f, 0.069f, 0.044f, 0.026f, 0.014f, 0.007f, 0.003f, 0.001f, 0.0f, 0.0f}; -static const uint32_t period_timings[NUM_STATES] = {PERIOD_CLOCK_UPDATE_US, PERIOD_CLOCK_UPDATE_US, +static const uint32_t period_timings[NUM_STATES] = {PERIOD_TIME_UPDATE_US, PERIOD_TIME_UPDATE_US, PERIOD_ANIMATION_US, PERIOD_TETRIS_US, PERIOD_SNAKE_US, PERIOD_PONG_US, PERIOD_ANIMATION_US}; + +// ---------------------------------------------------------------------------------- +// STATIC VARIABLES +// ---------------------------------------------------------------------------------- +ESP8266Timer ITimer; // ESP8266 Timer + +// ---------------------------------------------------------------------------------- +// ISR +// ---------------------------------------------------------------------------------- +void IRAM_ATTR TimerHandler() +{ + tm_mgr.increment_time_now_local(); +} + // ---------------------------------------------------------------------------------- // SETUP // ---------------------------------------------------------------------------------- @@ -162,12 +178,12 @@ void setup() // init ESP8266 File manager (LittleFS) setup_filesystem(); - // setup OTA + // set up OTA setupOTA(HOSTNAME); webserver.on("/cmd", handle_command); // process commands webserver.on("/data", handle_data_request); // process data requests - webserver.on("/leddirect", HTTP_POST, handle_led_direct); // Call the 'handle_led_direct' function when a POST request is made to URI "/leddirect" + webserver.on("/leddirect", HTTP_POST, handle_led_direct); // call the 'handle_led_direct' function when a POST request is made to URI "/leddirect" webserver.begin(); // create UDP Logger to send logging messages via UDP multicast @@ -178,15 +194,19 @@ void setup() cold_start_setup(); } - // setup NTP - configTime(MY_TZ, NTP_SERVER_URL); - ntp_time_update(NTP_MAX_UPDATE_TIME_US); // NTP time update - - // show the current time for short time in words - String timeMessage = time_to_string(time_info.tm_hour, time_info.tm_min); - show_string_on_clock(timeMessage, main_color_clock); - draw_minute_indicator(time_info.tm_min, main_color_clock); - led_matrix.draw_on_matrix_smooth(filter_factor); + // get initial time + if (tm_mgr.ntp_time_update(true)) + { + // show the current time for short time in words + String timeMessage = time_to_string(tm_mgr.tm_hour(), tm_mgr.tm_min()); + show_string_on_clock(timeMessage, main_color_clock); + draw_minute_indicator(tm_mgr.tm_min(), main_color_clock); + led_matrix.draw_on_matrix_smooth(filter_factor); + } + else + { + logger.log_string("Warning: Initial time sync failed! Retrying in a bit."); + } // init all animation modes // init snake @@ -214,17 +234,21 @@ void loop() uint32 current_time_us = system_get_time(); // Timestamp variables - static uint32 last_animation_step_us = 0; // time of last animation step - static uint32 last_matrix_update_us = 0; // time of last Matrix update - static uint32 last_heartbeat_us = 0; // time of last heartbeat sending - static uint32 last_nightmode_check_us = 0; // time of last nightmode check + static uint32 last_animation_step_us = 0; // timestamp of last animation step + static uint32 last_matrix_update_us = 0; // timestamp of last Matrix update + static uint32 last_time_update_us = 0; // timestamp of last time update + static uint32 last_heartbeat_us = 0; // timestamp of last heartbeat sending + static uint32 last_nightmode_check_us = 0; // timestamp of last nightmode check + static uint32 last_brightness_update_us = 0; // timestamp of last brightness update handleOTA(); // handle OTA webserver.handleClient(); // handle webserver + handle_button(); // handle button press + // send regularly heartbeat messages via UDP multicast - if ((current_time_us - last_heartbeat_us) > PERIOD_HEARTBEAT_US) + if ((current_time_us - last_heartbeat_us) >= PERIOD_HEARTBEAT_US) { send_heartbeat(); // send heartbeat update last_heartbeat_us = system_get_time(); @@ -232,38 +256,48 @@ void loop() } if (!flg_night_mode && ((current_time_us - last_animation_step_us) > period_timings[current_state]) && - ((current_time_us - last_led_direct_us) > TIMEOUT_LEDDIRECT_US)) + ((current_time_us - last_led_direct_us) >= TIMEOUT_LEDDIRECT_US)) { handle_current_state(); // handle current state last_animation_step_us = system_get_time(); delay(10); } - if ((current_time_us - last_matrix_update_us) > PERIOD_MATRIX_UPDATE_US) + if ((current_time_us - last_brightness_update_us) >= PERIOD_BRIGHTNESS_UPDATE_US) + { + current_brightness = update_brightness(); // update brightness + logger.log_string("Brightness: " + String(((uint16_t)current_brightness * 100) / UINT8_MAX) + "%"); + last_brightness_update_us = system_get_time(); + delay(10); + } + + if ((current_time_us - last_matrix_update_us) >= PERIOD_MATRIX_UPDATE_US) { update_matrix(); // update matrix last_matrix_update_us = system_get_time(); delay(10); } - handle_button(); // handle button press - - if ((current_time_us - last_ntp_update_us) > PERIOD_NTP_UPDATE_US) + if ((current_time_us - last_time_update_us) >= PERIOD_TIME_UPDATE_US) { - check_wifi_status(); // check WiFi status before NTP update - delay(10); + if (tm_mgr.ntp_sync_successful() == true) // regular case + { + tm_mgr.ntp_time_update(); // NTP time update + } + else // if there was never a NTP time update before (set up failed) + { + tm_mgr.ntp_time_update(true); // NTP time update with init! + } - ntp_time_update(NTP_MAX_UPDATE_TIME_US); // NTP time update - delay(10); - - current_brightness = update_brightness(); // update brightness every PERIOD_NTP_UPDATE_US - delay(10); - - logger.log_string("Brightness: " + String(((uint16_t)current_brightness * 100) / UINT8_MAX) + "%"); - delay(10); + if (tm_mgr.ntp_update_failed_prolonged() == true) + { + logger.log_string("Trigger restart due to being offline for too long..."); + delay(100); + ESP.restart(); + } } - if ((current_time_us - last_nightmode_check_us) > PERIOD_NIGHTMODE_CHECK_US) + if ((current_time_us - last_nightmode_check_us) >= PERIOD_NIGHTMODE_CHECK_US) { check_night_mode(); // check night mode last_nightmode_check_us = system_get_time(); @@ -288,7 +322,7 @@ void log_data() logger.log_string("Nightmode starts at: " + String(night_mode_times_ps->start_hour) + ":" + String(night_mode_times_ps->start_min)); logger.log_string("Nightmode ends at: " + String(night_mode_times_ps->end_hour) + ":" + String(night_mode_times_ps->end_min)); - logger.log_string("Brightness: " + String(((uint16_t)current_brightness * 100) / UINT8_MAX) + "%"); + logger.log_string("Brightness: " + String(((uint16_t)current_brightness * 100) / UINT8_MAX) + "%\n"); } /** @@ -329,38 +363,6 @@ void cold_start_setup() led_matrix.draw_on_matrix_instant(); } -/** - * @brief Updates the NTP time - * - * @return boolean - true if NTP update was successful, false otherwise - */ -bool get_ntp_time(uint32 timeout) -{ - uint32 start_time_us = system_get_time(); - do - { - time(&time_now); - localtime_r(&time_now, &time_info); - yield(); - } while (((system_get_time() - start_time_us) <= timeout) && (time_info.tm_year < (NTP_MININUM_RX_YEAR - NTP_MININUM_YEAR))); - - logger.log_string(String("NTP-Update duration: " + String(system_get_time() - start_time_us) + String("us"))); - - return ((time_info.tm_year <= (NTP_MININUM_RX_YEAR - NTP_MININUM_YEAR)) ? false : true); -} - -/** - * @brief Log local_time. - * - * @param local_time - */ -void log_time(tm local_time) -{ - char strftime_buf[64]; // Time string buffer - strftime(strftime_buf, sizeof(strftime_buf), "%c", &time_info); - logger.log_string(String(strftime_buf)); -} - /** * @brief Update and control word clock states. */ @@ -370,13 +372,13 @@ void handle_current_state() { case ST_CLOCK: // state clock { - (void)show_string_on_clock(time_to_string((uint8_t)time_info.tm_hour, (uint8_t)time_info.tm_min), main_color_clock); - draw_minute_indicator((uint8_t)time_info.tm_min, main_color_clock); + (void)show_string_on_clock(time_to_string((uint8_t)tm_mgr.tm_hour(), (uint8_t)tm_mgr.tm_min()), main_color_clock); + draw_minute_indicator((uint8_t)tm_mgr.tm_min(), main_color_clock); break; } case ST_DICLOCK: // state diclock { - show_digital_clock((uint8_t)time_info.tm_hour, (uint8_t)time_info.tm_min, main_color_clock); + show_digital_clock((uint8_t)tm_mgr.tm_hour(), (uint8_t)tm_mgr.tm_min(), main_color_clock); break; } case ST_SPIRAL: // state spiral @@ -452,14 +454,18 @@ void send_heartbeat() * @brief Check WiFi status and try to reconnect if needed. Should be called in loop() before NTP update. * * @param None + * + * @retval bool - true if WiFi is connected, false otherwise */ -void check_wifi_status() +bool check_wifi_status() { + bool connected = (WiFi.status() == WL_CONNECTED); // Check wifi status - if (WiFi.status() != WL_CONNECTED) + if (!connected) { Serial.println("WiFi connection lost! Trying to reconnect automatically..."); } + return connected; } /** @@ -470,8 +476,8 @@ void check_wifi_status() void check_night_mode() { // check if nightmode need to be activated - int hours = time_info.tm_hour; - int minutes = time_info.tm_min; + int hours = tm_mgr.tm_hour(); + int minutes = tm_mgr.tm_min(); if ((hours == night_mode_times_ps->start_hour) && (minutes == night_mode_times_ps->start_min)) { @@ -483,38 +489,6 @@ void check_night_mode() } } -/** - * @brief NTP time update, should be called in loop(). - * - * @param None - */ -void ntp_time_update(uint32 max_update_time) -{ - static int watchdog_counter = NTP_WATCHDOG_COUNTER_INIT; // Watchdog counter to trigger restart if NTP update was not possible 30 times in a row (5min) - bool ntp_retval = get_ntp_time(max_update_time); // NTP time update - - if (ntp_retval == true) - { - log_time(time_info); - last_ntp_update_us = system_get_time(); - watchdog_counter = NTP_WATCHDOG_COUNTER_INIT; - } - else - { - logger.log_string("NTP-Update was not successful."); - last_ntp_update_us += NTP_NEXT_UPDATE_DELAY_US; - watchdog_counter--; - } - - logger.log_string("Watchdog counter: " + String(watchdog_counter)); - if (watchdog_counter <= 0) - { - logger.log_string("Trigger restart due to watchdog..."); - delay(100); - ESP.restart(); - } -} - /** * @brief call entry action of given state * @@ -1052,9 +1026,9 @@ uint8_t update_brightness() { new_brightness = calculate_dynamic_brightness(brightness_ps->dyn_brightness_min, brightness_ps->dyn_brightness_max, - time_info.tm_hour, - time_info.tm_min, - time_info.tm_isdst); + tm_mgr.tm_hour(), + tm_mgr.tm_min(), + tm_mgr.tm_isdst()); } else // use static brightness {