#include "time_sync.h" #include "mimi_config.h" #include #include #include "esp_log.h" #include "esp_sntp.h" #include "nvs.h" static const char *TAG = "time_sync"; static volatile bool s_synced = false; static volatile time_t s_last_synced_time = 0; static char s_ntp_server[128] = MIMI_DEFAULT_NTP_SERVER; static void sntp_sync_cb(struct timeval *tv) { (void)tv; s_synced = true; s_last_synced_time = tv->tv_sec; /* Apply timezone from NVS */ char tz_str[64] = {0}; nvs_handle_t nvs; if (nvs_open("system_config", NVS_READONLY, &nvs) == ESP_OK) { size_t len = sizeof(tz_str); if (nvs_get_str(nvs, MIMI_NVS_KEY_TIMEZONE, tz_str, &len) == ESP_OK && tz_str[0]) { setenv("TZ", tz_str, 1); tzset(); ESP_LOGI(TAG, "Applied timezone from NVS: %s", tz_str); } else { setenv("TZ", MIMI_TIMEZONE, 1); tzset(); ESP_LOGI(TAG, "Using build-time timezone: %s", MIMI_TIMEZONE); } nvs_close(nvs); } else { setenv("TZ", MIMI_TIMEZONE, 1); tzset(); ESP_LOGI(TAG, "Using build-time timezone: %s", MIMI_TIMEZONE); } time_t now = time(NULL); struct tm tm_now; localtime_r(&now, &tm_now); char time_str[64]; strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S %Z", &tm_now); ESP_LOGI(TAG, "Time synchronized: %s", time_str); } static void load_custom_server(void) { nvs_handle_t nvs; if (nvs_open("system_config", NVS_READONLY, &nvs) == ESP_OK) { size_t len = sizeof(s_ntp_server); if (nvs_get_str(nvs, MIMI_NVS_KEY_NTP_SERVER, s_ntp_server, &len) == ESP_OK && s_ntp_server[0]) { ESP_LOGI(TAG, "Loaded custom NTP server from NVS: %s", s_ntp_server); } else { strlcpy(s_ntp_server, MIMI_DEFAULT_NTP_SERVER, sizeof(s_ntp_server)); } nvs_close(nvs); } } static void start_sntp(void) { esp_sntp_stop(); esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); esp_sntp_setservername(0, s_ntp_server); esp_sntp_set_time_sync_notification_cb(sntp_sync_cb); esp_sntp_init(); ESP_LOGI(TAG, "SNTP configured with server: %s", s_ntp_server); } esp_err_t time_sync_init(void) { ESP_LOGI(TAG, "Initializing SNTP..."); load_custom_server(); start_sntp(); s_synced = false; s_last_synced_time = 0; ESP_LOGI(TAG, "SNTP started, waiting for sync..."); return ESP_OK; } bool time_sync_is_synced(void) { return s_synced; } const char *time_sync_status_str(void) { if (s_synced) return "synced"; if (esp_sntp_getservername(0) != NULL) return "syncing"; return "not_synced"; } bool time_sync_get_last_synced(char *out, size_t out_size) { if (s_last_synced_time == 0) return false; time_t t = (time_t)s_last_synced_time; struct tm tm_now; localtime_r(&t, &tm_now); strftime(out, out_size, "%Y-%m-%d %H:%M:%S", &tm_now); return true; } const char *time_sync_get_server(void) { return s_ntp_server; } esp_err_t time_sync_set_server(const char *server) { if (!server || !server[0]) return ESP_ERR_INVALID_ARG; strlcpy(s_ntp_server, server, sizeof(s_ntp_server)); nvs_handle_t nvs; esp_err_t err = nvs_open("system_config", NVS_READWRITE, &nvs); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to open NVS: %s", esp_err_to_name(err)); return err; } err = nvs_set_str(nvs, MIMI_NVS_KEY_NTP_SERVER, server); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to save NTP server: %s", esp_err_to_name(err)); nvs_close(nvs); return err; } err = nvs_commit(nvs); nvs_close(nvs); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to commit NVS: %s", esp_err_to_name(err)); return err; } ESP_LOGI(TAG, "NTP server saved to NVS: %s", server); return ESP_OK; } esp_err_t time_sync_restart(void) { ESP_LOGI(TAG, "Restarting SNTP with server: %s", s_ntp_server); s_synced = false; s_last_synced_time = 0; start_sntp(); return ESP_OK; }