diff --git a/include/ntp_client_plus.h b/include/ntp_client_plus.h deleted file mode 100644 index 489a5cd..0000000 --- a/include/ntp_client_plus.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef NTPCLIENTPLUS_H -#define NTPCLIENTPLUS_H - -#include -#include - -#define UNIX_TIMESTAMP_1900 2208988800UL // careful: positive value -#define NTP_PACKET_SIZE 48 -#define NTP_DEFAULT_LOCAL_PORT 1337 -#define MAX_NTP_CONN_TRIES 50 // 50 * NTP_RECEIVE_WAIT_TIME_MS => 500ms -#define NTP_RECEIVE_WAIT_TIME_MS 10 // 10ms - -typedef enum -{ - NTP_UPDATE_TIMEOUT = -1, - NTP_UPDATE_SUCCESS = 0, - NTP_UPDATE_DIFFTOOHIGH = 1, - NTP_UPDATE_TIME_INVALID = 2 -} NtpReturnValue; - -/** - * @brief Own NTP Client library for Arduino with code from: - * - https://github.com/arduino-libraries/NTPClient - * - SPS&Technik - Projekt WordClock v1.02 - * - */ -class NTPClientPlus -{ -public: - NTPClientPlus(UDP &udp, const char *pool_server_name, int utcx, bool sw_change); - bool is_leap_year(unsigned int year); - bool check_daylight_saving_time(); - int get_hours_12() const; - int get_hours_24() const; - int get_minutes() const; - int get_month(int dayOfYear); - int get_seconds() const; - int update_ntp(); - long get_time_offset(); - String get_formatted_date(); - String get_formatted_time() const; - unsigned int get_day_of_week(); - unsigned int get_year(); - unsigned long get_epoch_time() const; - unsigned long get_secs_since_1900() const; - void calc_date(); - void end(); - void set_pool_server_name(const char *pool_server_name); - void set_time_offset(int time_offset); - void setup_ntp_client(); - -private: - UDP *_udp; - bool _udp_setup = false; - - bool _sw_change = 1; - const char *_pool_server_name = "pool.ntp.org"; // Default time server - int _utcx = 0; - IPAddress _pool_server_ip; - long _time_offset = 0; - unsigned int _port = NTP_DEFAULT_LOCAL_PORT; - - unsigned long _update_interval = 60000; // In ms - - unsigned int _date_day = 0; - unsigned int _date_month = 0; - unsigned int _date_year = 0; - unsigned int _day_of_week = 0; - unsigned long _current_epoc = 0; // In s - unsigned long _last_secs_since_1900 = 0; - unsigned long _last_update = 0; // In ms - unsigned long _secs_since_1900 = 0; // seconds since 1. Januar 1900, 00:00:00 - - unsigned char _packet_buffer[NTP_PACKET_SIZE] = {0}; - void send_ntp_packet(); - void set_summertime(bool summertime); - - static const unsigned long milliseconds_per_second = 1000; - static const unsigned long minutes_per_hour = 60; - static const unsigned long seconds_per_day = 86400; - static const unsigned long seconds_per_hour = 3600; - static const unsigned long seconds_per_minute = 60; - - // number of days in months - unsigned int _days_per_month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -}; - -void wait(unsigned long time_ms); - -#endif /* NTPCLIENTPLUS_H */ diff --git a/include/wordclock_constants.h b/include/wordclock_constants.h index 072f2e3..8ba4745 100644 --- a/include/wordclock_constants.h +++ b/include/wordclock_constants.h @@ -6,8 +6,10 @@ // ---------------------------------------------------------------------------------- // CONSTANTS // ---------------------------------------------------------------------------------- -#define AP_SSID "WordclockAP" // SSID name of Access Point -#define NTP_SERVER_URL "de.pool.ntp.org" // NTP server address +#define AP_SSID "WordclockAP" // SSID name of Access Point +#define NTP_SERVER_URL "de.pool.ntp.org" // NTP server address +#define MY_TZ "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00" // Timezone + #define HOSTNAME (String("wordclock")) // Local hostname #define LOGGER_MULTICAST_IP (IPAddress(230, 120, 10, 2)) // IP for UDP server #define LOGGER_MULTICAST_PORT (8123) // Port for UDP server diff --git a/include/wordclock_esp8266.h b/include/wordclock_esp8266.h index 97ae20c..f789f70 100644 --- a/include/wordclock_esp8266.h +++ b/include/wordclock_esp8266.h @@ -66,6 +66,8 @@ void handle_current_state(void); void handle_data_request(void); void handle_led_direct(void); void limit_value_ranges(void); +void log_time(tm local_time); +void ntp_time_update(uint32 *last_ntp_update_us); void ntp_time_update(uint32 *last_ntp_update_us); void on_state_entry(uint8_t state); void read_settings_from_EEPROM(void); diff --git a/src/connectivity/ntp_client_plus.cpp b/src/connectivity/ntp_client_plus.cpp deleted file mode 100644 index f3ae6b9..0000000 --- a/src/connectivity/ntp_client_plus.cpp +++ /dev/null @@ -1,658 +0,0 @@ -#include -#include "ntp_client_plus.h" - -/** - * @brief Construct a new NTPClientPlus::NTPClientPlus object - * - * @param udp UDP client - * @param pool_server_name time server name - * @param utcx UTC offset (in 1h) - * @param sw_change should summer/winter time be considered - */ -NTPClientPlus::NTPClientPlus(UDP &udp, const char *pool_server_name, int utcx, bool sw_change) -{ - this->_udp = &udp; - this->_utcx = utcx; - this->_time_offset = this->seconds_per_hour * this->_utcx; - this->_pool_server_name = pool_server_name; - this->_sw_change = sw_change; -} - -/** - * @brief Starts the underlying UDP client, get first NTP timestamp and calc date - * - */ -void NTPClientPlus::setup_ntp_client() -{ - this->_udp->begin(this->_port); - this->_udp_setup = true; - this->update_ntp(); - this->calc_date(); -} - -/** - * @brief Get new update from NTP - * - * @return NTP_UPDATE_TIMEOUT timeout after 500 ms - * @return NTP_UPDATE_SUCCESS after successful update - * @return NTP_UPDATE_DIFFTOOHIGH too much difference to previous received time (try again) - * @return NTP_UPDATE_TIME_INVALID time value is invalid - */ -int NTPClientPlus::update_ntp() -{ - // flush any existing packets - while (this->_udp->parsePacket() != 0) - { - this->_udp->flush(); - } - - this->send_ntp_packet(); - - // Wait till data is there or timeout... - uint8_t conn_tries = 0; - int received_bytes = 0; - - while ((received_bytes == 0) && (conn_tries++ <= MAX_NTP_CONN_TRIES)) - { - received_bytes = this->_udp->parsePacket(); - wait(NTP_RECEIVE_WAIT_TIME_MS); - } - - if (conn_tries >= MAX_NTP_CONN_TRIES) - { - return NTP_UPDATE_TIMEOUT; - } - - this->_udp->read(this->_packet_buffer, NTP_PACKET_SIZE); - - unsigned long high_word = word(this->_packet_buffer[40], this->_packet_buffer[41]); - unsigned long low_word = word(this->_packet_buffer[42], this->_packet_buffer[43]); - // combine the four bytes (two words) into a long integer - // this is NTP time (seconds since Jan 1 1900): - unsigned long temp_secs_since_1900 = high_word << 16 | low_word; - - if (temp_secs_since_1900 < UNIX_TIMESTAMP_1900) // NTP time is not valid - { - return NTP_UPDATE_TIME_INVALID; - } - - // check if time off last ntp update is roughly in the same range: 100sec apart (validation check) - if (this->_last_secs_since_1900 == 0 || temp_secs_since_1900 - this->_last_secs_since_1900 < 100000) - { - // Only update time then account for delay in reading the time - this->_last_update = (system_get_time() / 1000) - (NTP_RECEIVE_WAIT_TIME_MS * (conn_tries + 1)); - this->_secs_since_1900 = temp_secs_since_1900; - this->_current_epoc = this->_secs_since_1900 - UNIX_TIMESTAMP_1900; - - // Remember time of last update - this->_last_secs_since_1900 = temp_secs_since_1900; - return NTP_UPDATE_SUCCESS; // return 0 after successful update - } - else - { - // Remember time of last update - this->_last_secs_since_1900 = temp_secs_since_1900; - return NTP_UPDATE_DIFFTOOHIGH; - } -} - -/** - * @brief Stops the underlying UDP client - * - */ -void NTPClientPlus::end() -{ - this->_udp->stop(); - this->_udp_setup = false; -} - -/** - * @brief Setter TimeOffset - * - * @param time_offset offset from UTC in seconds - */ -void NTPClientPlus::set_time_offset(int time_offset) -{ - this->_time_offset = time_offset; -} - -long NTPClientPlus::get_time_offset() -{ - return this->_time_offset; -} - -/** - * @brief Set time server name - * - * @param pool_server_name - */ -void NTPClientPlus::set_pool_server_name(const char *pool_server_name) -{ - this->_pool_server_name = pool_server_name; -} - -/** - * @brief Calc seconds since 1. Jan. 1900 - * - * @return unsigned long seconds since 1. Jan. 1900 - */ -unsigned long NTPClientPlus::get_secs_since_1900() const -{ - return this->_time_offset + // User offset - this->_secs_since_1900 + // seconds returned by the NTP server - (((system_get_time() / 1000) - this->_last_update) / 1000); // Time since last update -} - -/** - * @brief Get UNIX Epoch time since 1. Jan. 1970 - * - * @return unsigned long UNIX Epoch time since 1. Jan. 1970 in seconds - */ -unsigned long NTPClientPlus::get_epoch_time() const -{ - return this->get_secs_since_1900() - UNIX_TIMESTAMP_1900; -} - -/** - * @brief Get current hours in 24h format - * - * @return int - */ -int NTPClientPlus::get_hours_24() const -{ - int hours = ((this->get_epoch_time() % 86400L) / 3600); - return hours; -} - -/** - * @brief Get current hours in 12h format - * - * @return int - */ -int NTPClientPlus::get_hours_12() const -{ - return this->get_hours_24() % 12; -} - -/** - * @brief Get current minutes - * - * @return int - */ -int NTPClientPlus::get_minutes() const -{ - return ((this->get_epoch_time() % 3600) / 60); -} - -/** - * @brief Get current seconds - * - * @return int - */ -int NTPClientPlus::get_seconds() const -{ - return this->get_epoch_time() % 60; -} - -/** - * @brief - * - * @return String time formatted like `hh:mm:ss` - */ -String NTPClientPlus::get_formatted_time() const -{ - unsigned long raw_time = this->get_epoch_time(); - unsigned long hours = (raw_time % 86400L) / 3600; - String hours_str = hours < 10 ? "0" + String(hours) : String(hours); - - unsigned long minutes = (raw_time % 3600) / 60; - String minute_str = minutes < 10 ? "0" + String(minutes) : String(minutes); - - unsigned long seconds = raw_time % 60; - String second_str = seconds < 10 ? "0" + String(seconds) : String(seconds); - - return hours_str + ":" + minute_str + ":" + second_str; -} - -/** - * @brief - * - * @return String date formatted like `dd.mm.yyyy` - */ -String NTPClientPlus::get_formatted_date() -{ - this->calc_date(); - unsigned int dateDay = this->_date_day; - unsigned int dateMonth = this->_date_month; - unsigned int dateYear = this->_date_year; - - String dayStr = dateDay < 10 ? "0" + String(dateDay) : String(dateDay); - String monthStr = dateMonth < 10 ? "0" + String(dateMonth) : String(dateMonth); - String yearStr = dateYear < 10 ? "0" + String(dateYear) : String(dateYear); - - return dayStr + "." + monthStr + "." + yearStr; -} - -/** - * @brief Calc date from seconds since 1900 - * - */ -void NTPClientPlus::calc_date() -{ - // get days since 1900 - unsigned long days1900 = this->get_secs_since_1900() / seconds_per_day; - - // calc current year - this->_date_year = this->get_year(); - - // calc how many leap days since 1.Jan 1900 - int leap_days = 0; - for (unsigned int i = 1900; i < this->_date_year; i++) - { - // check if leap year - if (this->is_leap_year(i)) - { - leap_days++; - } - } - leap_days = leap_days - 1; - - // check if current year is leap year - if (this->is_leap_year(this->_date_year)) - { - _days_per_month[2] = 29; - } - else - { - _days_per_month[2] = 28; - } - - unsigned int day_of_year = (days1900 - ((this->_date_year - 1900) * 365) - leap_days); - - // calc current month - this->_date_month = this->get_month(day_of_year); - - this->_date_day = 0; - - // calc day of month - for (unsigned int i = 0; i < this->_date_month; i++) - { - this->_date_day = this->_date_day + _days_per_month[i]; - } - this->_date_day = day_of_year - this->_date_day; - - // calc day of week: - // Monday = 1, Tuesday = 2, Wednesday = 3, Thursday = 4, Friday = 5, Saturday = 6, Sunday = 7 - // 1. Januar 1900 was a monday - this->_day_of_week = 1; - - for (unsigned int i = 0; i < days1900; i++) - { - if (this->_day_of_week < 7) - { - this->_day_of_week = this->_day_of_week + 1; - } - else - { - this->_day_of_week = 1; - } - } - - // End: Calc date (dateDay, dateMonth, dateYear) - - // calc if summer time active - - this->check_daylight_saving_time(); -} - -/** - * @brief Getter for day of the week - * - * @return unsigned int - */ -unsigned int NTPClientPlus::get_day_of_week() -{ - return this->_day_of_week; -} - -/** - * @brief Function to calc current year - * - * @return unsigned int - */ -unsigned int NTPClientPlus::get_year() -{ - unsigned long secs_since_1900 = this->get_secs_since_1900(); - - // NTP starts at 1. Jan 1900 - unsigned int result = 1900; - unsigned int days_in_year = 0; - unsigned int days = 0; - unsigned int days_since_1900 = 0; - - unsigned int for_i = 0; - bool leap_year = false; - - days_since_1900 = secs_since_1900 / this->seconds_per_day; - - for (for_i = 0; for_i < days_since_1900; for_i++) - { - leap_year = this->is_leap_year(result); - - if (leap_year) - { - days_in_year = 366; - } - else - { - days_in_year = 365; - } - days++; - - if (days >= days_in_year) - { - result++; - days = 0; - } - } - - return result; -} - -/** - * @brief Function to check if given year is leap year - * - * @param year - * @return true - * @return false - */ -bool NTPClientPlus::is_leap_year(unsigned int year) -{ - - bool result = false; - - // check for leap year - if ((year % 4) == 0) - { - result = true; - - if ((year % 100) == 0) - { - result = false; - - if ((year % 400) == 0) - { - result = true; - } - } - } - else - { - result = false; - } - - return result; -} - -/** - * @brief Get Month of given day of year - * - * @param day_of_year - * @return int - */ -int NTPClientPlus::get_month(int day_of_year) -{ - bool leap_year = this->is_leap_year(this->get_year()); - - // Month beginnings - int month_min[13] = {0, 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}; - // Month endings - int month_max[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; - int month = 0; - int y = 0; - - // Calculation of the beginning and end of each month in the leap year - if (leap_year == true) - { - for (y = 3; y < 13; y++) - { - ++month_min[y]; - } - - for (y = 2; y < 13; y++) - { - ++month_max[y]; - } - } - - // January - if (day_of_year >= month_min[1] && day_of_year <= month_max[1]) - { - month = 1; - } - - // February - if (day_of_year >= month_min[2] && day_of_year <= month_max[2]) - { - month = 2; - } - - // March - if (day_of_year >= month_min[3] && day_of_year <= month_max[3]) - { - month = 3; - } - - // April - if (day_of_year >= month_min[4] && day_of_year <= month_max[4]) - { - month = 4; - } - - // May - if (day_of_year >= month_min[5] && day_of_year <= month_max[5]) - { - month = 5; - } - - // June - if (day_of_year >= month_min[6] && day_of_year <= month_max[6]) - { - month = 6; - } - - // July - if (day_of_year >= month_min[7] && day_of_year <= month_max[7]) - { - month = 7; - } - - // August - if (day_of_year >= month_min[8] && day_of_year <= month_max[8]) - { - month = 8; - } - - // September - if (day_of_year >= month_min[9] && day_of_year <= month_max[9]) - { - month = 9; - } - - // October - if (day_of_year >= month_min[10] && day_of_year <= month_max[10]) - { - month = 10; - } - - // November - if (day_of_year >= month_min[11] && day_of_year <= month_max[11]) - { - month = 11; - } - - // December - if (day_of_year >= month_min[12] && day_of_year <= month_max[12]) - { - month = 12; - } - - return month; -} - -/** - * @brief (private) Send NTP Packet to NTP server - * - */ -void NTPClientPlus::send_ntp_packet() -{ - // set all bytes in the buffer to 0 - memset(this->_packet_buffer, 0, NTP_PACKET_SIZE); - // Initialize values needed to form NTP request - this->_packet_buffer[0] = 0b11100011; // LI, Version, Mode - this->_packet_buffer[1] = 0; // Stratum, or type of clock - this->_packet_buffer[2] = 6; // Polling Interval - this->_packet_buffer[3] = 0xEC; // Peer Clock Precision - // 8 bytes of zero for Root Delay & Root Dispersion - this->_packet_buffer[12] = 49; - this->_packet_buffer[13] = 0x4E; - this->_packet_buffer[14] = 49; - this->_packet_buffer[15] = 52; - - // all NTP fields have been given values, now - // you can send a packet requesting a timestamp: - if (this->_pool_server_name) - { - this->_udp->beginPacket(this->_pool_server_name, 123); - } - else - { - this->_udp->beginPacket(this->_pool_server_ip, 123); - } - this->_udp->write(this->_packet_buffer, NTP_PACKET_SIZE); - this->_udp->endPacket(); -} - -/** - * @brief (private) Set time offset accordance to summer time - * - * @param summertime - */ -void NTPClientPlus::set_summertime(bool summertime) -{ - if (summertime) - { - this->_time_offset = this->seconds_per_hour * (this->_utcx + 1); - } - else - { - this->_time_offset = this->seconds_per_hour * (this->_utcx); - } -} - -/** - * @brief (private) Update Summer/Winter time change - * - * @returns bool summertime active - */ -bool NTPClientPlus::check_daylight_saving_time() -{ - unsigned int day_of_week = this->_day_of_week; - unsigned int date_day = this->_date_day; - unsigned int date_month = this->_date_month; - - bool summertime_active = false; - - if (this->_sw_change) - { - // Start: Set summer-/ winter time - // current month is march - if (date_month == 3) - { - - // it is last week in march - if ((this->_days_per_month[3] - date_day) < 7) - { - // Example year 2020: March 31 days; Restart March 26, 2020 (Thursday = weekday = 4); 5 days remaining; Last Sunday March 29, 2020 - // Calculation: 31 - 26 = 5; 5 + 4 = 9; - // Result: Last day in March is a Tuesday. There folfalses another Sunday in October => set winter time - - // Example year 2021: March 31 days; Restart March 30, 2021 (Tuesday = weekday = 2); 1 days remaining; Last Sunday March 28, 2021 - // Calculation: 31 - 30 = 1; 1 + 2 = 3; - // Result: Last day in March is a Wednesday. Changeover to summer time already done => set summer time - - // There folfalses within the last week in March one more Sunday => set winter time - if (((this->_days_per_month[3] - date_day) + day_of_week) >= 7) - { - this->set_summertime(0); - summertime_active = false; - } - else // last sunday in march already over -> summer time - { - this->set_summertime(1); - summertime_active = true; - } - } - else // restart in first three weeks of march -> winter time - { - this->set_summertime(0); - summertime_active = false; - } - } - - // current month is october - else if (date_month == 10) - { - // restart last week of october - if ((this->_days_per_month[10] - date_day) < 7) - { - - // Example year 2020: October 31 days; restart October 26, 2020 (Monday = weekday = 1); 5 days remaining; last Sunday October 25, 2020 - // Calculation: 31 - 26 = 5; 5 + 1 = 6; - // Result: Last day in October is a Saturday. Changeover to winter time already done => set winter time - - // Example year 2021: October 31 days; Restart 26. October 2021 (Tuesday = weekday = 2); 5 days remaining; Last Sunday 31. October 2021 - // Calculation: 31 - 26 = 5; 5 + 2 = 7; - // Result: Last day in October is a Sunday. There folfalses another Sunday in October => set summer time - - // There folfalses within the last week in October one more Sunday => summer time - if (((this->_days_per_month[10] - date_day) + day_of_week) >= 7) - { - this->set_summertime(1); - summertime_active = true; - } - else // last sunday in october already over -> winter time - { - this->set_summertime(0); - summertime_active = false; - } - } - else // restart in first three weeks of october -> summer time - { - this->set_summertime(1); - summertime_active = true; - } - } - else if (date_month > 3 && date_month < 10) // restart in summer time - { - this->set_summertime(1); - summertime_active = true; - } - else if (date_month < 3 || date_month > 10) // restart in winter time - { - this->set_summertime(0); - summertime_active = false; - } - } - - return summertime_active; -} - -void wait(unsigned long time_ms) -{ - unsigned long start = (system_get_time() / 1000); // in ms - while (((system_get_time() / 1000) - start) < time_ms) - { - yield(); - }; -} diff --git a/src/wordclock_esp8266.cpp b/src/wordclock_esp8266.cpp index ba974ff..b8e1cfa 100644 --- a/src/wordclock_esp8266.cpp +++ b/src/wordclock_esp8266.cpp @@ -29,15 +29,14 @@ #include //from ESP8266 Arduino Core (automatically installed when ESP8266 was installed via Boardmanager) #include #include -#include //https://github.com/tzapu/WiFiManager WiFi Configuration Magic -#include +#include +#include // https://github.com/tzapu/WiFiManager WiFi Configuration Magic // own libraries #include "animation_functions.h" #include "base64_wrapper.h" // copied from https://github.com/Xander-Electronics/Base64 #include "led_matrix.h" #include "littlefs_wrapper.h" -#include "ntp_client_plus.h" #include "ota_functions.h" #include "pong.h" #include "render_functions.h" @@ -49,14 +48,15 @@ // ---------------------------------------------------------------------------------- // GLOBAL VARIABLES // ---------------------------------------------------------------------------------- +UDPLogger logger; // Logger 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 -UDPLogger logger; // Logger +char strftime_buf[64]; // Time string buffer ESP8266WebServer webserver(HTTP_PORT); // Webserver LEDMatrix led_matrix = LEDMatrix(&matrix, DEFAULT_BRIGHTNESS, &logger); // NeoMatrix wrapper -WiFiUDP wifi_udp; -NTPClientPlus ntp_client = NTPClientPlus(wifi_udp, NTP_SERVER_URL, 1, true); +struct tm timeinfo; // Structure tm holds time information +time_t now; // Seconds since Epoch (1970) - UTC // ---------------------------------------------------------------------------------- // STATIC VARIABLES @@ -70,6 +70,8 @@ static Pong pong = Pong(&led_matrix, &logger); static Snake snake = Snake(&led_matrix, &logger); static Tetris tetris = Tetris(&led_matrix, &logger); +static uint32 last_ntp_update_us = 0; // time of last NTP update + static bool flg_night_mode = false; // state of nightmode static bool flg_reset_wifi_creds = false; // used to reset stored wifi credentials static bool spiral_direction = false; @@ -87,7 +89,7 @@ static const uint32_t period_timings[NUM_STATES] = {PERIOD_CLOCK_UPDATE_US, PERI PERIOD_ANIMATION_US, PERIOD_TETRIS_US, PERIOD_SNAKE_US, PERIOD_PONG_US, PERIOD_ANIMATION_US}; -// Quarterly brightness factor for dynamic brightness +// Quarterly brightness factor for dynamic brightness (4 quarters a 24 hours) static const float qtly_brightness_factor[96] = { 0.0f, 0.0f, 0.0f, 0.001f, 0.003f, 0.007f, 0.014f, 0.026f, 0.044f, 0.069f, 0.101f, 0.143f, 0.194f, 0.253f, 0.32f, 0.392f, 0.468f, 0.545f, 0.62f, 0.691f, 0.755f, 0.811f, 0.858f, 0.896f, 0.927f, 0.949f, 0.966f, 0.978f, 0.986f, @@ -212,17 +214,13 @@ void setup() } // setup NTP - ntp_client.setup_ntp_client(); - logger.log_string("NTP running"); - logger.log_string("Time: " + ntp_client.get_formatted_time()); - logger.log_string("TimeOffset (seconds): " + String(ntp_client.get_time_offset())); + configTime(MY_TZ, NTP_SERVER_URL); + ntp_time_update(&last_ntp_update_us); // NTP time update // show the current time for short time in words - int hours = ntp_client.get_hours_24(); - int minutes = ntp_client.get_minutes(); - String timeMessage = time_to_string(hours, minutes); + String timeMessage = time_to_string(timeinfo.tm_hour, timeinfo.tm_min); show_string_on_clock(timeMessage, main_color_clock); - draw_minute_indicator(minutes, main_color_clock); + draw_minute_indicator(timeinfo.tm_min, main_color_clock); led_matrix.draw_on_matrix_smooth(filter_factor); // init all animation modes @@ -233,7 +231,7 @@ void setup() // init random tetris random_tetris(true); - // Range limits + // Set range limits limit_value_ranges(); logger.log_string("Nightmode starts at: " + String(night_mode_times_ps->start_hour) + ":" + String(night_mode_times_ps->start_min)); @@ -256,7 +254,6 @@ void loop() 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_ntp_update_us = 0; // time of last NTP update handleOTA(); // handle OTA @@ -313,69 +310,95 @@ void loop() // OTHER FUNCTIONS // ---------------------------------------------------------------------------------- +/** + * @brief Updates the NTP time + * + * @return boolean - true if NTP update was successful, false otherwise + */ +bool get_ntp_time(uint32 sec) +{ + uint32 start = system_get_time() / 1000; // ms + do + { + time(&now); + localtime_r(&now, &timeinfo); + delay(10); + } while (((system_get_time() / 1000 - start) <= (1000 * sec)) && (timeinfo.tm_year < (2023 - 1900))); + + if (timeinfo.tm_year <= (2023 - 1900)) + { + return false; // the NTP call was not successful + } + else + { + return true; + } +} + +void log_time(tm local_time) +{ + strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); + logger.log_string(String(strftime_buf)); +} + void handle_current_state() { switch (current_state) { - case ST_CLOCK: // state clock - { - int hours = ntp_client.get_hours_24(); - int minutes = ntp_client.get_minutes(); - - (void)show_string_on_clock(time_to_string((uint8_t)hours, (uint8_t)minutes), main_color_clock); - draw_minute_indicator((uint8_t)minutes, main_color_clock); - break; - } - case ST_DICLOCK: // state diclock - { - int hours = ntp_client.get_hours_24(); - int minutes = ntp_client.get_minutes(); - show_digital_clock((uint8_t)hours, (uint8_t)minutes, main_color_clock); - break; - } - case ST_SPIRAL: // state spiral - { - int res = draw_spiral(false, spiral_direction, MATRIX_WIDTH - 2); - if ((bool)res && spiral_direction == 0) + case ST_CLOCK: // state clock { - // change spiral direction to closing (draw empty leds) - spiral_direction = true; - // init spiral with new spiral direction - draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); + (void)show_string_on_clock(time_to_string((uint8_t)timeinfo.tm_hour, (uint8_t)timeinfo.tm_min), main_color_clock); + draw_minute_indicator((uint8_t)timeinfo.tm_min, main_color_clock); + break; } - else if (res && spiral_direction == 1) + case ST_DICLOCK: // state diclock { - // reset spiral direction to normal drawing leds - spiral_direction = false; - // init spiral with new spiral direction - draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); + show_digital_clock((uint8_t)timeinfo.tm_hour, (uint8_t)timeinfo.tm_min, main_color_clock); + break; + } + case ST_SPIRAL: // state spiral + { + int res = draw_spiral(false, spiral_direction, MATRIX_WIDTH - 2); + if ((bool)res && spiral_direction == 0) + { + // change spiral direction to closing (draw empty leds) + spiral_direction = true; + // init spiral with new spiral direction + draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); + } + else if (res && spiral_direction == 1) + { + // reset spiral direction to normal drawing leds + spiral_direction = false; + // init spiral with new spiral direction + draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); + } + break; + } + case ST_TETRIS: // state tetris + { + tetris.loopCycle(); + break; + } + case ST_SNAKE: // state snake + { + snake.loopCycle(); + break; + } + case ST_PINGPONG: // state ping pong + { + pong.loopCycle(); + break; + } + case ST_HEARTS: + { + draw_heart_animation(); + break; + } + default: + { + break; } - break; - } - case ST_TETRIS: // state tetris - { - tetris.loopCycle(); - break; - } - case ST_SNAKE: // state snake - { - snake.loopCycle(); - break; - } - case ST_PINGPONG: // state ping pong - { - pong.loopCycle(); - break; - } - case ST_HEARTS: - { - draw_heart_animation(); - break; - } - default: - { - break; - } } } @@ -424,8 +447,8 @@ void check_wifi_status() void check_night_mode() { // check if nightmode need to be activated - int hours = ntp_client.get_hours_24(); - int minutes = ntp_client.get_minutes(); + int hours = timeinfo.tm_hour; + int minutes = timeinfo.tm_min; if ((hours == night_mode_times_ps->start_hour) && (minutes == night_mode_times_ps->start_min)) { @@ -445,44 +468,19 @@ void check_night_mode() void ntp_time_update(uint32 *last_ntp_update_us) { // NTP time update - int ntp_retval = ntp_client.update_ntp(); + bool ntp_retval = get_ntp_time(*last_ntp_update_us / 10000000); - switch (ntp_retval) + if (ntp_retval == true) { - case NTP_UPDATE_SUCCESS: - { - ntp_client.calc_date(); - logger.log_string("NTP-Update successful, Time: " + ntp_client.get_formatted_time()); + log_time(timeinfo); *last_ntp_update_us = system_get_time(); watchdog_counter = 30; - break; } - case NTP_UPDATE_TIMEOUT: + else { - logger.log_string("NTP-Update not successful. Reason: Timeout"); + logger.log_string("NTP-Update was not successful."); *last_ntp_update_us += 10000000; watchdog_counter--; - break; - } - case NTP_UPDATE_DIFFTOOHIGH: - { - logger.log_string("NTP-Update not successful. Reason: Too large time difference"); - logger.log_string("Time: " + ntp_client.get_formatted_time()); - logger.log_string("Date: " + ntp_client.get_formatted_date()); - logger.log_string("TimeOffset (seconds): " + String(ntp_client.get_time_offset())); - logger.log_string("Summertime: " + String(ntp_client.check_daylight_saving_time())); - *last_ntp_update_us += 10000000; - watchdog_counter--; - break; - } - case NTP_UPDATE_TIME_INVALID: - default: - { - logger.log_string("NTP-Update not successful. Reason: NTP time not valid (<1970)"); - *last_ntp_update_us += 10000000; - watchdog_counter--; - break; - } } logger.log_string("Watchdog counter: " + String(watchdog_counter)); @@ -504,34 +502,34 @@ void on_state_entry(uint8_t state) filter_factor = 0.5f; switch (state) { - case ST_SPIRAL: - { - spiral_direction = 0; // Init spiral with normal drawing mode - draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); - break; - } - case ST_TETRIS: - { - filter_factor = 1.0f; // no smoothing - tetris.ctrlStart(); - break; - } - case ST_SNAKE: - { - filter_factor = 1.0f; // no smoothing - snake.initGame(); - break; - } - case ST_PINGPONG: - { - filter_factor = 1.0f; // no smoothing - pong.initGame(1); - break; - } - default: - { - break; - } + case ST_SPIRAL: + { + spiral_direction = 0; // Init spiral with normal drawing mode + draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); + break; + } + case ST_TETRIS: + { + filter_factor = 1.0f; // no smoothing + tetris.ctrlStart(); + break; + } + case ST_SNAKE: + { + filter_factor = 1.0f; // no smoothing + snake.initGame(); + break; + } + case ST_PINGPONG: + { + filter_factor = 1.0f; // no smoothing + pong.initGame(1); + break; + } + default: + { + break; + } } } @@ -1032,9 +1030,9 @@ uint8_t update_brightness() { new_brightness = calculate_dynamic_brightness(brightness_ps->dyn_brightness_min, brightness_ps->dyn_brightness_max, - ntp_client.get_hours_24(), - ntp_client.get_minutes(), - ntp_client.check_daylight_saving_time()); + timeinfo.tm_hour, + timeinfo.tm_min, + timeinfo.tm_isdst); } else // use static brightness {