feat: wire NTP client into firmware build and initialization
- Add ntp.c to CMakeLists.txt SRCS so it's compiled and linked - Load ntp_server from NVS in load_nvs_config() (default: pool.ntp.org) - Add ntp_server field to spaxel_state_t - Initialize NTP after WiFi connects with 10s sync timeout, WARN on failure - Re-sync NTP after WiFi reconnect (WIFI_LOST state) - Start periodic 10-minute resync timer via esp_timer - Add ntp_synced boolean to health JSON message - Handle ntp_server field in downstream config message - Fix periodic resync callback to properly stop/restart SNTP Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
83a86faee4
commit
a42c5e7ea1
5 changed files with 48 additions and 2 deletions
|
|
@ -6,6 +6,7 @@ idf_component_register(
|
|||
"ble.c"
|
||||
"provision.c"
|
||||
"nvs_migration.c"
|
||||
"ntp.c"
|
||||
INCLUDE_DIRS "." "${CMAKE_BINARY_DIR}/spaxel-firmware/main"
|
||||
REQUIRES esp_wifi esp_netif nvs_flash mdns esp_http_client esp_timer bt driver log esp_http_server mbedtls esp_ota
|
||||
)
|
||||
|
|
|
|||
|
|
@ -131,6 +131,12 @@ static esp_err_t load_nvs_config(void) {
|
|||
g_state.debug = (debug == 1);
|
||||
}
|
||||
|
||||
// Load NTP server
|
||||
len = sizeof(g_state.ntp_server);
|
||||
if (nvs_get_str(nvs, NVS_KEY_NTP_SERVER, g_state.ntp_server, &len) != ESP_OK) {
|
||||
strncpy(g_state.ntp_server, "pool.ntp.org", sizeof(g_state.ntp_server));
|
||||
}
|
||||
|
||||
nvs_close(nvs);
|
||||
|
||||
ESP_LOGI(TAG, "NVS config loaded: provisioned=%d, role=%s, rate=%d Hz",
|
||||
|
|
@ -200,8 +206,18 @@ static void state_machine_task(void *arg) {
|
|||
if (bits & SPAXEL_EVENT_WIFI_CONNECTED) {
|
||||
ESP_LOGI(TAG, "WiFi connected");
|
||||
wifi_fail_count = 0;
|
||||
g_state.state = NODE_STATE_MOTHERSHIP_DISCOVERY;
|
||||
discovery_fail_count = 0;
|
||||
|
||||
// Initialize NTP after WiFi is up
|
||||
ESP_LOGI(TAG, "Starting NTP sync with server: %s", g_state.ntp_server);
|
||||
ntp_init();
|
||||
ntp_start_sync(g_state.ntp_server);
|
||||
if (!ntp_wait_sync(10000)) {
|
||||
ESP_LOGW(TAG, "NTP sync failed, proceeding without stagger");
|
||||
}
|
||||
ntp_start_periodic_resync();
|
||||
|
||||
g_state.state = NODE_STATE_MOTHERSHIP_DISCOVERY;
|
||||
} else if (bits & SPAXEL_EVENT_WIFI_FAILED) {
|
||||
wifi_fail_count++;
|
||||
ESP_LOGW(TAG, "WiFi failed (attempt %d)", wifi_fail_count);
|
||||
|
|
@ -315,6 +331,15 @@ static void state_machine_task(void *arg) {
|
|||
|
||||
if (bits & SPAXEL_EVENT_WIFI_CONNECTED) {
|
||||
ESP_LOGI(TAG, "WiFi reconnected");
|
||||
|
||||
// Re-sync NTP after reconnect
|
||||
ntp_init();
|
||||
ntp_start_sync(g_state.ntp_server);
|
||||
if (!ntp_wait_sync(10000)) {
|
||||
ESP_LOGW(TAG, "NTP resync failed after WiFi reconnect");
|
||||
}
|
||||
ntp_start_periodic_resync();
|
||||
|
||||
g_state.state = NODE_STATE_MOTHERSHIP_DISCOVERY;
|
||||
} else {
|
||||
wifi_fail_count++;
|
||||
|
|
|
|||
|
|
@ -35,9 +35,15 @@ static void sntp_sync_time_callback(struct timeval *tv) {
|
|||
// Periodic resync timer callback
|
||||
static void periodic_resync_callback(void *arg) {
|
||||
ESP_LOGI(TAG, "Periodic NTP resync triggered");
|
||||
esp_sntp_stop();
|
||||
s_is_synced = false;
|
||||
if (s_ntp_events) {
|
||||
xEventGroupClearBits(s_ntp_events, NTP_SYNC_BIT);
|
||||
}
|
||||
esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||
esp_sntp_setservername(0, s_ntp_server);
|
||||
sntp_set_time_sync_notification_cb(sntp_sync_time_callback);
|
||||
esp_sntp_init();
|
||||
// No need to wait here - the callback will handle completion
|
||||
}
|
||||
|
||||
esp_err_t ntp_init(void) {
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ typedef struct {
|
|||
bool provisioned;
|
||||
bool debug;
|
||||
uint8_t mac[6];
|
||||
char ntp_server[64];
|
||||
EventGroupHandle_t events;
|
||||
} spaxel_state_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "spaxel.h"
|
||||
#include "csi.h"
|
||||
#include "wifi.h"
|
||||
#include "ntp.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_system.h"
|
||||
|
|
@ -348,6 +349,9 @@ esp_err_t websocket_send_health(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// NTP sync status
|
||||
cJSON_AddBoolToObject(root, "ntp_synced", ntp_is_synced());
|
||||
|
||||
char *json = cJSON_PrintUnformatted(root);
|
||||
cJSON_Delete(root);
|
||||
|
||||
|
|
@ -584,6 +588,15 @@ static void handle_config_msg(cJSON *root) {
|
|||
g_variance_threshold = (float)var_thresh->valuedouble;
|
||||
}
|
||||
|
||||
// NTP server (runtime reconfiguration)
|
||||
cJSON *ntp = cJSON_GetObjectItem(root, "ntp_server");
|
||||
if (ntp && cJSON_IsString(ntp) && strlen(ntp->valuestring) > 0) {
|
||||
strncpy(g_state.ntp_server, ntp->valuestring, sizeof(g_state.ntp_server) - 1);
|
||||
g_state.ntp_server[sizeof(g_state.ntp_server) - 1] = '\0';
|
||||
ESP_LOGI(TAG, "NTP server changed to: %s", g_state.ntp_server);
|
||||
ntp_start_sync(g_state.ntp_server);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
csi_set_rate(g_state.packet_rate);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue