From ee2f866b104bcf19d61facd4a36c3f9fa3f7ceb6 Mon Sep 17 00:00:00 2001 From: agessaman Date: Fri, 14 Aug 2026 19:58:39 -0700 Subject: [PATCH] fix(mqtt): clear the stale SNTP status before starting the new request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reset was on the wrong side of configTime(). configTime() configures the server, calls sntp_init(), and returns — the new request is live before it comes back — so a fast reply could set SNTP_SYNC_STATUS_COMPLETED inside that call, and the reset immediately after would erase it. The following ten seconds of polling would then see nothing and reject a server that had in fact answered. On the `set mqtt.ntp` path that surfaces as a good server failing validation. Stop any running session first, discard its status, then start the new one, so the only completion observable is the one being waited for. --- src/helpers/bridges/MQTTBridge.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/helpers/bridges/MQTTBridge.cpp b/src/helpers/bridges/MQTTBridge.cpp index 1a3c2d15..4da87149 100644 --- a/src/helpers/bridges/MQTTBridge.cpp +++ b/src/helpers/bridges/MQTTBridge.cpp @@ -3986,15 +3986,21 @@ bool MQTTBridge::syncTimeWithNTP(bool force, bool primary_only) { for (int s = 0; s < server_count && !ntp_ok; s++) { const char* server = servers[s]; MQTT_DEBUG_PRINTLN("SNTP fallback trying %s...", server); - configTime(0, 0, server); // A plausible clock is not evidence this server answered. The device usually // already holds valid time here — from an earlier sync, or the RTC — so polling // time(nullptr) declared the very first server successful without a packet ever // arriving, stopped the fallback walk there, and refreshed _last_ntp_sync. Worse // on the `set mqtt.ntp` validation path, where a typo is supposed to fail fast. // Wait for SNTP itself to report completion. The status is one-shot — reading - // COMPLETED clears it — so drop any result an earlier sync left behind. + // COMPLETED clears it — so drop any result an earlier sync left behind, and do + // that *before* starting this one: configTime() returns after sntp_init(), so a + // fast reply can complete inside it, and clearing afterwards would erase the + // very result being waited for. + if (sntp_enabled()) { + sntp_stop(); + } sntp_set_sync_status(SNTP_SYNC_STATUS_RESET); + configTime(0, 0, server); for (int i = 0; i < 20; i++) { delay(500); if (sntp_get_sync_status() != SNTP_SYNC_STATUS_COMPLETED) continue;