mirror of
https://github.com/vicliu624/trail-mate.git
synced 2026-08-14 06:39:45 +00:00
fix(wifi): sync time on each IP lease
This commit is contained in:
@@ -28,7 +28,6 @@ static bool s_netif_ready;
|
||||
static bool s_wifi_initialized;
|
||||
static bool s_wifi_started;
|
||||
static bool s_time_sync_in_progress;
|
||||
static bool s_time_sync_attempted;
|
||||
static time_t s_time_sync_epoch;
|
||||
static esp_timer_handle_t s_time_sync_timeout_timer;
|
||||
static TaskHandle_t s_time_sync_emit_task;
|
||||
@@ -82,21 +81,28 @@ static void stop_sntp_once(void)
|
||||
esp_sntp_set_time_sync_notification_cb(NULL);
|
||||
}
|
||||
|
||||
static void cancel_network_time_sync(void)
|
||||
// Keep the timer as Wi-Fi runtime state to avoid repeated heap allocation on
|
||||
// every DHCP lease, but always return its active resources on each terminal
|
||||
// path. A subsequent GOT_IP can then start a fresh one-shot sync.
|
||||
static void finish_network_time_sync(void)
|
||||
{
|
||||
s_time_sync_in_progress = false;
|
||||
if (s_time_sync_timeout_timer != NULL)
|
||||
{
|
||||
(void)esp_timer_stop(s_time_sync_timeout_timer);
|
||||
}
|
||||
stop_sntp_once();
|
||||
s_time_sync_in_progress = false;
|
||||
}
|
||||
|
||||
static void cancel_network_time_sync(void)
|
||||
{
|
||||
finish_network_time_sync();
|
||||
}
|
||||
|
||||
static void time_sync_emit_task(void* arg)
|
||||
{
|
||||
(void)arg;
|
||||
const time_t epoch_seconds = s_time_sync_epoch;
|
||||
stop_sntp_once();
|
||||
|
||||
if (valid_network_epoch(epoch_seconds))
|
||||
{
|
||||
@@ -109,7 +115,7 @@ static void time_sync_emit_task(void* arg)
|
||||
emit_time_sync_event(TM_C6_ERROR_INTERNAL, 0, "c6_wifi_sntp");
|
||||
}
|
||||
|
||||
s_time_sync_in_progress = false;
|
||||
finish_network_time_sync();
|
||||
s_time_sync_emit_task = NULL;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
@@ -139,8 +145,7 @@ static void time_sync_notification_cb(struct timeval* tv)
|
||||
5,
|
||||
&s_time_sync_emit_task) != pdPASS)
|
||||
{
|
||||
stop_sntp_once();
|
||||
s_time_sync_in_progress = false;
|
||||
finish_network_time_sync();
|
||||
s_time_sync_emit_task = NULL;
|
||||
ESP_LOGW(TAG, "Failed to start SNTP emit task");
|
||||
}
|
||||
@@ -155,8 +160,7 @@ static void time_sync_timeout_cb(void* arg)
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "SNTP sync timed out server=%s", TM_WIFI_SNTP_SERVER);
|
||||
stop_sntp_once();
|
||||
s_time_sync_in_progress = false;
|
||||
finish_network_time_sync();
|
||||
}
|
||||
|
||||
static bool ensure_time_sync_timer(void)
|
||||
@@ -204,12 +208,12 @@ static void start_or_restart_sntp(void)
|
||||
|
||||
static void request_network_time_sync(void)
|
||||
{
|
||||
if (s_time_sync_attempted || s_time_sync_in_progress)
|
||||
if (s_time_sync_in_progress)
|
||||
{
|
||||
ESP_LOGI(TAG, "Ignoring duplicate GOT_IP while SNTP is in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
s_time_sync_attempted = true;
|
||||
if (!ensure_time_sync_timer())
|
||||
{
|
||||
return;
|
||||
@@ -220,7 +224,7 @@ static void request_network_time_sync(void)
|
||||
esp_timer_start_once(s_time_sync_timeout_timer, (uint64_t)TM_WIFI_SNTP_TIMEOUT_MS * 1000ULL);
|
||||
if (timer_err != ESP_OK)
|
||||
{
|
||||
s_time_sync_in_progress = false;
|
||||
finish_network_time_sync();
|
||||
ESP_LOGW(TAG, "Failed to start SNTP timeout timer: %s", esp_err_to_name(timer_err));
|
||||
return;
|
||||
}
|
||||
@@ -290,7 +294,6 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t e
|
||||
}
|
||||
case WIFI_EVENT_STA_DISCONNECTED:
|
||||
cancel_network_time_sync();
|
||||
s_time_sync_attempted = false;
|
||||
emit_simple_event(TM_C6_WIFI_EVENT_STA_DISCONNECTED, TM_C6_OK, NULL, 0);
|
||||
break;
|
||||
case WIFI_EVENT_AP_START:
|
||||
@@ -314,6 +317,7 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t e
|
||||
ipv4 = event->ip_info.ip.addr;
|
||||
}
|
||||
emit_simple_event(TM_C6_WIFI_EVENT_STA_GOT_IP, TM_C6_OK, s_config.sta_ssid, ipv4);
|
||||
ESP_LOGI(TAG, "GOT_IP triggers one-shot SNTP");
|
||||
request_network_time_sync();
|
||||
}
|
||||
}
|
||||
@@ -381,7 +385,6 @@ esp_err_t tm_wifi_apply_config(const tm_c6_wifi_config_t* config)
|
||||
if (!config->wifi_enabled)
|
||||
{
|
||||
cancel_network_time_sync();
|
||||
s_time_sync_attempted = false;
|
||||
if (s_wifi_started)
|
||||
{
|
||||
(void)esp_wifi_disconnect();
|
||||
@@ -470,7 +473,6 @@ esp_err_t tm_wifi_handle_control(const tm_c6_wifi_control_t* control)
|
||||
case TM_C6_WIFI_CMD_CONNECT:
|
||||
{
|
||||
cancel_network_time_sync();
|
||||
s_time_sync_attempted = false;
|
||||
s_config.wifi_enabled = 1;
|
||||
s_config.sta_enabled = 1;
|
||||
copy_text(s_config.sta_ssid, sizeof(s_config.sta_ssid), control->ssid);
|
||||
@@ -480,7 +482,6 @@ esp_err_t tm_wifi_handle_control(const tm_c6_wifi_control_t* control)
|
||||
}
|
||||
case TM_C6_WIFI_CMD_DISCONNECT:
|
||||
cancel_network_time_sync();
|
||||
s_time_sync_attempted = false;
|
||||
return esp_wifi_disconnect();
|
||||
case TM_C6_WIFI_CMD_GET_IP:
|
||||
{
|
||||
|
||||
@@ -21,6 +21,24 @@ bool contains(const std::string& haystack, const char* needle)
|
||||
return haystack.find(needle) != std::string::npos;
|
||||
}
|
||||
|
||||
std::size_t occurrences(const std::string& haystack, const char* needle)
|
||||
{
|
||||
const std::string target = needle ? needle : "";
|
||||
if (target.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t count = 0;
|
||||
std::size_t offset = 0;
|
||||
while ((offset = haystack.find(target, offset)) != std::string::npos)
|
||||
{
|
||||
++count;
|
||||
offset += target.size();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv)
|
||||
@@ -36,6 +54,8 @@ int main(int argc, char** argv)
|
||||
const std::string wifi_runtime = readFile(
|
||||
repo_root /
|
||||
"platform/esp/common/include/platform/esp/common/wifi_runtime_impl.h");
|
||||
const std::string c6_wifi_runtime =
|
||||
readFile(repo_root / "firmware/c6_companion/components/tm_wifi/tm_wifi.c");
|
||||
const std::string team_pairing_transport = readFile(
|
||||
repo_root /
|
||||
"platform/esp/arduino_common/src/team/pairing/team_pairing_transport_espnow.cpp");
|
||||
@@ -58,6 +78,17 @@ int main(int argc, char** argv)
|
||||
assert(contains(wifi_runtime, "void profile_retry_timer_cb(void*)"));
|
||||
assert(contains(wifi_runtime, "schedule_profile_retry();"));
|
||||
assert(contains(wifi_runtime, "(void)connect(nullptr);"));
|
||||
assert(!contains(wifi_runtime, "network_time_sync_attempted"));
|
||||
assert(contains(wifi_runtime, "void finish_network_time_sync()"));
|
||||
assert(contains(wifi_runtime, "GOT_IP triggers one-shot SNTP"));
|
||||
assert(contains(wifi_runtime, "duplicate GOT_IP ignored while SNTP is in progress"));
|
||||
assert(occurrences(wifi_runtime, "finish_network_time_sync();") >= 5);
|
||||
|
||||
assert(!contains(c6_wifi_runtime, "s_time_sync_attempted"));
|
||||
assert(contains(c6_wifi_runtime, "static void finish_network_time_sync(void)"));
|
||||
assert(contains(c6_wifi_runtime, "GOT_IP triggers one-shot SNTP"));
|
||||
assert(contains(c6_wifi_runtime, "Ignoring duplicate GOT_IP while SNTP is in progress"));
|
||||
assert(occurrences(c6_wifi_runtime, "finish_network_time_sync();") >= 5);
|
||||
assert(contains(team_pairing_transport,
|
||||
"set_non_preemptible_activity(true, \"team_pairing\")"));
|
||||
assert(contains(team_pairing_transport, "set_non_preemptible_activity(false)"));
|
||||
|
||||
@@ -87,7 +87,6 @@ struct RuntimeState
|
||||
bool wifi_initialized = false;
|
||||
bool ble_paused_for_wifi = false;
|
||||
bool network_time_sync_in_progress = false;
|
||||
bool network_time_sync_attempted = false;
|
||||
std::time_t network_time_sync_epoch = 0;
|
||||
bool config_cached = false;
|
||||
bool profiles_cached = false;
|
||||
@@ -758,7 +757,6 @@ void clear_connection_details()
|
||||
cancel_network_time_sync();
|
||||
s_runtime.connected = false;
|
||||
s_runtime.connecting = false;
|
||||
s_runtime.network_time_sync_attempted = false;
|
||||
s_runtime.rssi = -127;
|
||||
s_runtime.ssid[0] = '\0';
|
||||
s_runtime.ip[0] = '\0';
|
||||
@@ -848,20 +846,28 @@ void stop_sntp_once()
|
||||
esp_sntp_set_time_sync_notification_cb(nullptr);
|
||||
}
|
||||
|
||||
void cancel_network_time_sync()
|
||||
// A time sync is strictly bound to the current IP lease. Keep the timer
|
||||
// allocated with the Wi-Fi runtime so repeated DHCP events do not fragment
|
||||
// scarce internal memory, but make every terminal path stop it and unregister
|
||||
// the SNTP callback before another lease can start a new sync.
|
||||
void finish_network_time_sync()
|
||||
{
|
||||
s_runtime.network_time_sync_in_progress = false;
|
||||
if (s_runtime.network_time_sync_timeout_timer != nullptr)
|
||||
{
|
||||
(void)esp_timer_stop(s_runtime.network_time_sync_timeout_timer);
|
||||
}
|
||||
stop_sntp_once();
|
||||
s_runtime.network_time_sync_in_progress = false;
|
||||
}
|
||||
|
||||
void cancel_network_time_sync()
|
||||
{
|
||||
finish_network_time_sync();
|
||||
}
|
||||
|
||||
void network_time_apply_task(void*)
|
||||
{
|
||||
const std::time_t epoch_seconds = s_runtime.network_time_sync_epoch;
|
||||
stop_sntp_once();
|
||||
|
||||
if (is_valid_network_epoch(epoch_seconds))
|
||||
{
|
||||
@@ -877,7 +883,7 @@ void network_time_apply_task(void*)
|
||||
static_cast<long long>(epoch_seconds));
|
||||
}
|
||||
|
||||
s_runtime.network_time_sync_in_progress = false;
|
||||
finish_network_time_sync();
|
||||
s_runtime.network_time_apply_task = nullptr;
|
||||
vTaskDelete(nullptr);
|
||||
}
|
||||
@@ -908,8 +914,7 @@ void network_time_sync_notification_cb(timeval* tv)
|
||||
&s_runtime.network_time_apply_task);
|
||||
if (created != pdPASS)
|
||||
{
|
||||
stop_sntp_once();
|
||||
s_runtime.network_time_sync_in_progress = false;
|
||||
finish_network_time_sync();
|
||||
s_runtime.network_time_apply_task = nullptr;
|
||||
std::printf("[WiFi][Time] failed to start SNTP apply task\n");
|
||||
}
|
||||
@@ -923,8 +928,7 @@ void network_time_sync_timeout_cb(void*)
|
||||
}
|
||||
|
||||
std::printf("[WiFi][Time] SNTP sync timed out server=%s\n", kNetworkTimeSyncServer);
|
||||
stop_sntp_once();
|
||||
s_runtime.network_time_sync_in_progress = false;
|
||||
finish_network_time_sync();
|
||||
}
|
||||
|
||||
bool ensure_network_time_sync_timer()
|
||||
@@ -971,12 +975,12 @@ void start_or_restart_sntp()
|
||||
|
||||
void request_network_time_sync()
|
||||
{
|
||||
if (s_runtime.network_time_sync_attempted || s_runtime.network_time_sync_in_progress)
|
||||
if (s_runtime.network_time_sync_in_progress)
|
||||
{
|
||||
std::printf("[WiFi][Time] duplicate GOT_IP ignored while SNTP is in progress\n");
|
||||
return;
|
||||
}
|
||||
|
||||
s_runtime.network_time_sync_attempted = true;
|
||||
if (!ensure_network_time_sync_timer())
|
||||
{
|
||||
return;
|
||||
@@ -988,7 +992,7 @@ void request_network_time_sync()
|
||||
static_cast<uint64_t>(kNetworkTimeSyncTimeoutMs) * 1000ULL);
|
||||
if (timer_err != ESP_OK)
|
||||
{
|
||||
s_runtime.network_time_sync_in_progress = false;
|
||||
finish_network_time_sync();
|
||||
std::printf("[WiFi][Time] failed to start SNTP timeout timer err=0x%x\n",
|
||||
static_cast<unsigned>(timer_err));
|
||||
return;
|
||||
@@ -1225,6 +1229,7 @@ void wifi_event_handler(void*,
|
||||
s_runtime.ip[0] ? s_runtime.ip : "<none>",
|
||||
s_runtime.ssid[0] ? s_runtime.ssid : current_config().ssid,
|
||||
s_runtime.rssi);
|
||||
std::printf("[WiFi][Time] GOT_IP triggers one-shot SNTP\n");
|
||||
request_network_time_sync();
|
||||
ensure_reconnect_memory_reserve();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user