Fix of NTP logic. Minor refactoring.

This commit is contained in:
2024-04-02 03:43:42 +02:00
parent 73aa168152
commit ef6061fc21
2 changed files with 51 additions and 54 deletions

View File

@@ -2,6 +2,7 @@
#define WORDCLOCK_ESP8266_H #define WORDCLOCK_ESP8266_H
#include <Arduino.h> #include <Arduino.h>
#include <stdlib.h>
#include <ESP8266WebServer.h> #include <ESP8266WebServer.h>
#include "led_matrix.h" #include "led_matrix.h"
#include "udp_logger.h" #include "udp_logger.h"
@@ -11,6 +12,13 @@
#define EEPROM_SIZE (sizeof(EepromLayout_st) / sizeof(uint8_t)) #define EEPROM_SIZE (sizeof(EepromLayout_st) / sizeof(uint8_t))
#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 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
typedef struct typedef struct
{ {
int start_hour; int start_hour;
@@ -54,6 +62,7 @@ typedef enum
NUM_STATES NUM_STATES
} ClockState_en; } ClockState_en;
bool get_ntp_time(uint32 usec);
String leading_zero2digit(int value); 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 calculate_dynamic_brightness(uint8_t min_brightness, uint8_t max_brightness, int hours, int minutes, bool summertime);
uint8_t update_brightness(void); uint8_t update_brightness(void);
@@ -67,8 +76,7 @@ void handle_data_request(void);
void handle_led_direct(void); void handle_led_direct(void);
void limit_value_ranges(void); void limit_value_ranges(void);
void log_time(tm local_time); void log_time(tm local_time);
void ntp_time_update(uint32 *last_ntp_update_us); void ntp_time_update(uint32 max_update_time);
void ntp_time_update(uint32 *last_ntp_update_us);
void on_state_entry(uint8_t state); void on_state_entry(uint8_t state);
void read_settings_from_EEPROM(void); void read_settings_from_EEPROM(void);
void reset_wifi_credentials(void); void reset_wifi_credentials(void);

View File

@@ -48,15 +48,14 @@
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// GLOBAL VARIABLES // GLOBAL VARIABLES
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
UDPLogger logger; // Logger UDPLogger logger; // Global UDP logger instance
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(MATRIX_WIDTH, MATRIX_HEIGHT + 1, NEOPIXEL_PIN, 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_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG,
NEO_GRB + NEO_KHZ800); // NeoMatrix NEO_GRB + NEO_KHZ800); // NeoMatrix
char strftime_buf[64]; // Time string buffer
ESP8266WebServer webserver(HTTP_PORT); // Webserver ESP8266WebServer webserver(HTTP_PORT); // Webserver
LEDMatrix led_matrix = LEDMatrix(&matrix, DEFAULT_BRIGHTNESS, &logger); // NeoMatrix wrapper LEDMatrix led_matrix = LEDMatrix(&matrix, DEFAULT_BRIGHTNESS, &logger); // NeoMatrix wrapper
struct tm timeinfo; // Structure tm holds time information struct tm time_info; // Structure tm holds time information
time_t now; // Seconds since Epoch (1970) - UTC time_t time_now; // Seconds since Epoch (1970) - UTC
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// STATIC VARIABLES // STATIC VARIABLES
@@ -70,19 +69,20 @@ static Pong pong = Pong(&led_matrix, &logger);
static Snake snake = Snake(&led_matrix, &logger); static Snake snake = Snake(&led_matrix, &logger);
static Tetris tetris = Tetris(&led_matrix, &logger); static Tetris tetris = Tetris(&led_matrix, &logger);
static uint32 last_ntp_update_us = 0; // time of last NTP update static uint32 last_ntp_update_us = 0; // Time of last NTP update
static char strftime_buf[64]; // Time string buffer
static bool flg_night_mode = false; // state of nightmode static bool flg_night_mode = false; // State of nightmode
static bool flg_reset_wifi_creds = false; // used to reset stored wifi credentials static bool flg_reset_wifi_creds = false; // Used to reset stored wifi credentials
static bool spiral_direction = false; static bool spiral_direction = false;
static float filter_factor = DEFAULT_SMOOTHING_FACTOR; // stores smoothing factor for led transition static float filter_factor = DEFAULT_SMOOTHING_FACTOR; // Stores smoothing factor for led transition, value of 1 represents no smoothing.
static int watchdog_counter = 30; // Watchdog counter to trigger restart if NTP update was not possible 30 times in a row (5min) static int watchdog_counter = 30; // Watchdog counter to trigger restart if NTP update was not possible 30 times in a row (5min)
static uint32 last_led_direct_us = 0; // time of last direct LED command (=> fall back to normal mode after timeout) static uint32 last_led_direct_us = 0; // Time of last direct LED command (=> fall back to normal mode after timeout)
static uint32_t heartbeat_counter = 0; // for heartbeat on-time in seconds static uint32_t heartbeat_counter = 0; // Heartbeat on-time in seconds
static uint32_t main_color_clock = colors_24bit[2]; // color of the clock and digital clock static uint32_t main_color_clock = colors_24bit[2]; // Color of the clock and digital clock
static uint32_t main_color_snake = colors_24bit[1]; // color of the random snake animation static uint32_t main_color_snake = colors_24bit[1]; // Color of the random snake animation
static uint8_t current_brightness = DEFAULT_BRIGHTNESS; // current brightness of LEDs static uint8_t current_brightness = DEFAULT_BRIGHTNESS; // Current brightness of LEDs
static uint8_t current_state = (uint8_t)ST_CLOCK; // stores current state static uint8_t current_state = (uint8_t)ST_CLOCK; // Stores current state
static const String state_names[NUM_STATES] = {"Clock", "DiClock", "Spiral", "Tetris", "Snake", "PingPong", "Hearts"}; static const String state_names[NUM_STATES] = {"Clock", "DiClock", "Spiral", "Tetris", "Snake", "PingPong", "Hearts"};
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_CLOCK_UPDATE_US, PERIOD_CLOCK_UPDATE_US,
@@ -170,16 +170,12 @@ void setup()
// create UDP Logger to send logging messages via UDP multicast // create UDP Logger to send logging messages via UDP multicast
logger = UDPLogger(WiFi.localIP(), LOGGER_MULTICAST_IP, LOGGER_MULTICAST_PORT, "Wordclock 2.0"); logger = UDPLogger(WiFi.localIP(), LOGGER_MULTICAST_IP, LOGGER_MULTICAST_PORT, "Wordclock 2.0");
logger.log_string("Start program\n"); logger.log_string("Start program\n");
delay(10);
logger.log_string("Sketchname: " + String(__FILE__)); logger.log_string("Sketchname: " + String(__FILE__));
delay(10);
logger.log_string("Build: " + String(__TIMESTAMP__)); logger.log_string("Build: " + String(__TIMESTAMP__));
delay(10);
logger.log_string("IP: " + WiFi.localIP().toString()); logger.log_string("IP: " + WiFi.localIP().toString());
delay(10);
logger.log_string("Reset Reason: " + ESP.getResetReason()); logger.log_string("Reset Reason: " + ESP.getResetReason());
if (resetInfo->reason != REASON_SOFT_RESTART) if (resetInfo->reason != REASON_SOFT_RESTART) // only if there was a cold start/hard reset
{ {
// quickly test each LED // quickly test each LED
for (int16_t row = 0; row < MATRIX_HEIGHT; row++) for (int16_t row = 0; row < MATRIX_HEIGHT; row++)
@@ -215,12 +211,12 @@ void setup()
// setup NTP // setup NTP
configTime(MY_TZ, NTP_SERVER_URL); configTime(MY_TZ, NTP_SERVER_URL);
ntp_time_update(&last_ntp_update_us); // NTP time update ntp_time_update(NTP_MAX_UPDATE_TIME_US); // NTP time update
// show the current time for short time in words // show the current time for short time in words
String timeMessage = time_to_string(timeinfo.tm_hour, timeinfo.tm_min); String timeMessage = time_to_string(time_info.tm_hour, time_info.tm_min);
show_string_on_clock(timeMessage, main_color_clock); show_string_on_clock(timeMessage, main_color_clock);
draw_minute_indicator(timeinfo.tm_min, main_color_clock); draw_minute_indicator(time_info.tm_min, main_color_clock);
led_matrix.draw_on_matrix_smooth(filter_factor); led_matrix.draw_on_matrix_smooth(filter_factor);
// init all animation modes // init all animation modes
@@ -289,7 +285,7 @@ void loop()
check_wifi_status(); // check WiFi status before NTP update check_wifi_status(); // check WiFi status before NTP update
delay(10); delay(10);
ntp_time_update(&last_ntp_update_us); // NTP time update ntp_time_update(NTP_MAX_UPDATE_TIME_US); // NTP time update
delay(10); delay(10);
current_brightness = update_brightness(); // update brightness every PERIOD_NTP_UPDATE_US current_brightness = update_brightness(); // update brightness every PERIOD_NTP_UPDATE_US
@@ -315,29 +311,22 @@ void loop()
* *
* @return boolean - true if NTP update was successful, false otherwise * @return boolean - true if NTP update was successful, false otherwise
*/ */
bool get_ntp_time(uint32 sec) bool get_ntp_time(uint32 usec)
{ {
uint32 start = system_get_time() / 1000; // ms uint32 start_time_us = system_get_time();
do do
{ {
time(&now); time(&time_now);
localtime_r(&now, &timeinfo); localtime_r(&time_now, &time_info);
delay(10); delay(10);
} while (((system_get_time() / 1000 - start) <= (1000 * sec)) && (timeinfo.tm_year < (2023 - 1900))); } while (((system_get_time() - start_time_us) <= usec) && (time_info.tm_year < (NTP_MININUM_RX_YEAR - NTP_MININUM_YEAR)));
if (timeinfo.tm_year <= (2023 - 1900)) return ((time_info.tm_year <= (NTP_MININUM_RX_YEAR - NTP_MININUM_YEAR)) ? false : true);
{
return false; // the NTP call was not successful
}
else
{
return true;
}
} }
void log_time(tm local_time) void log_time(tm local_time)
{ {
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); strftime(strftime_buf, sizeof(strftime_buf), "%c", &time_info);
logger.log_string(String(strftime_buf)); logger.log_string(String(strftime_buf));
} }
@@ -347,13 +336,13 @@ void handle_current_state()
{ {
case ST_CLOCK: // state clock case ST_CLOCK: // state clock
{ {
(void)show_string_on_clock(time_to_string((uint8_t)timeinfo.tm_hour, (uint8_t)timeinfo.tm_min), main_color_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)timeinfo.tm_min, main_color_clock); draw_minute_indicator((uint8_t)time_info.tm_min, main_color_clock);
break; break;
} }
case ST_DICLOCK: // state diclock case ST_DICLOCK: // state diclock
{ {
show_digital_clock((uint8_t)timeinfo.tm_hour, (uint8_t)timeinfo.tm_min, main_color_clock); show_digital_clock((uint8_t)time_info.tm_hour, (uint8_t)time_info.tm_min, main_color_clock);
break; break;
} }
case ST_SPIRAL: // state spiral case ST_SPIRAL: // state spiral
@@ -447,8 +436,8 @@ void check_wifi_status()
void check_night_mode() void check_night_mode()
{ {
// check if nightmode need to be activated // check if nightmode need to be activated
int hours = timeinfo.tm_hour; int hours = time_info.tm_hour;
int minutes = timeinfo.tm_min; int minutes = time_info.tm_min;
if ((hours == night_mode_times_ps->start_hour) && (minutes == night_mode_times_ps->start_min)) if ((hours == night_mode_times_ps->start_hour) && (minutes == night_mode_times_ps->start_min))
{ {
@@ -465,21 +454,21 @@ void check_night_mode()
* *
* @param None * @param None
*/ */
void ntp_time_update(uint32 *last_ntp_update_us) void ntp_time_update(uint32 max_update_time)
{ {
// NTP time update // NTP time update
bool ntp_retval = get_ntp_time(*last_ntp_update_us / 10000000); bool ntp_retval = get_ntp_time(max_update_time);
if (ntp_retval == true) if (ntp_retval == true)
{ {
log_time(timeinfo); log_time(time_info);
*last_ntp_update_us = system_get_time(); last_ntp_update_us = system_get_time();
watchdog_counter = 30; watchdog_counter = NTP_WATCHDOG_COUNTER_INIT;
} }
else else
{ {
logger.log_string("NTP-Update was not successful."); logger.log_string("NTP-Update was not successful.");
*last_ntp_update_us += 10000000; last_ntp_update_us += NTP_NEXT_UPDATE_DELAY_US;
watchdog_counter--; watchdog_counter--;
} }
@@ -499,7 +488,7 @@ void ntp_time_update(uint32 *last_ntp_update_us)
*/ */
void on_state_entry(uint8_t state) void on_state_entry(uint8_t state)
{ {
filter_factor = 0.5f; filter_factor = DEFAULT_SMOOTHING_FACTOR;
switch (state) switch (state)
{ {
case ST_SPIRAL: case ST_SPIRAL:
@@ -1030,9 +1019,9 @@ uint8_t update_brightness()
{ {
new_brightness = calculate_dynamic_brightness(brightness_ps->dyn_brightness_min, new_brightness = calculate_dynamic_brightness(brightness_ps->dyn_brightness_min,
brightness_ps->dyn_brightness_max, brightness_ps->dyn_brightness_max,
timeinfo.tm_hour, time_info.tm_hour,
timeinfo.tm_min, time_info.tm_min,
timeinfo.tm_isdst); time_info.tm_isdst);
} }
else // use static brightness else // use static brightness
{ {