From 744f8b2504e1e3c5a83aa568d934797190b07be0 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Tue, 16 May 2023 00:05:55 +0100 Subject: [PATCH] Configure SNTP --- README.md | 2 +- components/time/CMakeLists.txt | 2 +- components/time/time_manager.c | 101 +++++++++++++++++++++++++++++++-- components/time/time_manager.h | 5 ++ main/CMakeLists.txt | 2 +- main/main.c | 2 + 6 files changed, 107 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8d61d54..9ba382d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Networked bedside clock utilising an ESP32-SOLO-1. - [x] WiFi networking - [x] Console for configuration - [ ] TCP API for configuration -- [ ] SNTP synchronisation +- [x] SNTP synchronisation ## Firmware diff --git a/components/time/CMakeLists.txt b/components/time/CMakeLists.txt index a05a4b0..4de7d54 100644 --- a/components/time/CMakeLists.txt +++ b/components/time/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register( SRCS "time_manager.c" INCLUDE_DIRS "." - REQUIRES settings + REQUIRES console_wrapper lwip settings ) diff --git a/components/time/time_manager.c b/components/time/time_manager.c index b3ffc00..03d6601 100644 --- a/components/time/time_manager.c +++ b/components/time/time_manager.c @@ -5,29 +5,122 @@ #include "time_manager.h" +#include "console.h" #include "settings.h" +#include "esp_log.h" +#include "esp_sntp.h" #include +#define TAG "Time" + static void handle_timezone_update(const char *timezone) { setenv("TZ", timezone, 1); tzset(); + (void)sntp_restart(); +} + +static void handle_sntp_server_update(const char *sntp_server) +{ + esp_sntp_setservername(0, sntp_server); + if (!sntp_restart()) { + ESP_LOGW( + TAG, "Received SNTP server update before SNTP initialization"); + } +} + +static void sntp_sync_callback(struct timeval *tv) +{ + const time_t now = tv->tv_sec; + struct tm timeinfo; + (void)localtime_r(&now, &timeinfo); + ESP_LOGI( + TAG, "Received SNTP time notification: %02u:%02u", timeinfo.tm_hour, + timeinfo.tm_min); +} + +static const char *sync_status_description(sntp_sync_status_t status) +{ + switch (status) { + case SNTP_SYNC_STATUS_RESET: + return "Reset"; + case SNTP_SYNC_STATUS_COMPLETED: + return "Completed"; + case SNTP_SYNC_STATUS_IN_PROGRESS: + return "In progress"; + default: + return "Invalid"; + } +} + +static int command_func(int argc, char **argv) +{ + if (argc == 1) { + const Time time = get_time(); + printf("%02u:%02u\n", time.hour, time.minute); + return 0; + } else if (argc == 2) { + if (strcmp(argv[1], "sntp-status") == 0) { + const sntp_sync_status_t status = sntp_get_sync_status(); + printf("%s\n", sync_status_description(status)); + return 0; + } else { + Time time; + if (sscanf(argv[1], "%02u:%02u", &time.hour, &time.minute) < 2 + || time.hour > 23 || time.minute > 59) { + printf("Invalid time\n"); + return 1; + } + set_time(time); + return 0; + } + } else { + printf("Invalid number of arguments\n"); + return 1; + } } void time_manager_init(void) { char timezone[SETTINGS_MAX_VALUE_SIZE]; - (void)settings_get_timezone(timezone, sizeof(timezone)); + (void)settings_get_timezone(timezone, SETTINGS_MAX_VALUE_SIZE); handle_timezone_update(timezone); - settings_add_timezone_callback(&handle_timezone_update); + + char sntp_server[SETTINGS_MAX_VALUE_SIZE]; + (void)settings_get_sntp_server(sntp_server, SETTINGS_MAX_VALUE_SIZE); + esp_sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED); + esp_sntp_setoperatingmode(ESP_SNTP_OPMODE_POLL); + esp_sntp_setservername(0, sntp_server); + sntp_set_time_sync_notification_cb(sntp_sync_callback); + esp_sntp_init(); + settings_add_sntp_server_callback(&handle_sntp_server_update); + + console_register( + "time", "Get / set time and SNTP status", + "time OR time OR time sntp-status", command_func); } Time get_time(void) { - const time_t now = time(NULL); + struct timeval tv; + gettimeofday(&tv, NULL); struct tm timeinfo; - (void)localtime_r(&now, &timeinfo); + (void)localtime_r(&tv.tv_sec, &timeinfo); + return (Time) { .hour = timeinfo.tm_hour, .minute = timeinfo.tm_min }; } + +void set_time(Time time) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm timeinfo; + (void)localtime_r(&tv.tv_sec, &timeinfo); + + timeinfo.tm_hour = time.hour; + timeinfo.tm_min = time.minute; + tv.tv_sec = mktime(&timeinfo); + settimeofday(&tv, NULL); +} diff --git a/components/time/time_manager.h b/components/time/time_manager.h index 41e83a2..0591634 100644 --- a/components/time/time_manager.h +++ b/components/time/time_manager.h @@ -21,4 +21,9 @@ void time_manager_init(void); */ Time get_time(void); +/** + * Set the time. + */ +void set_time(Time time); + #endif diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 418886f..d354e3d 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register( SRCS "main.c" INCLUDE_DIRS "." - REQUIRES console_wrapper display settings wifi + REQUIRES console_wrapper display settings time wifi ) diff --git a/main/main.c b/main/main.c index 45d5718..0cc7cc3 100644 --- a/main/main.c +++ b/main/main.c @@ -6,6 +6,7 @@ #include "console.h" #include "display.h" #include "settings.h" +#include "time_manager.h" #include "wifi.h" void app_main(void) @@ -14,4 +15,5 @@ void app_main(void) settings_init(); display_init(); wifi_init(); + time_manager_init(); }