From 4247737896e7061e6dd996de00aba051cd940079 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 15 Sep 2026 21:57:25 +0200 Subject: [PATCH] fix auto version fetch, make it non-blocking --- src/web/WebStatusService.cpp | 12 ++++++++---- src/web/WebStatusService.h | 12 +++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index 8ce5ff465..69d50103a 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -359,6 +359,8 @@ void WebStatusService::getVersions(JsonObject root) { dev = versions_dev_; } + versions_fetch_requested_ = true; + if (!cache_valid) { // no successful fetch yet (no network, fetch pending, or parse error) return; @@ -402,12 +404,12 @@ void WebStatusService::schedule_versions_refresh() { versions_next_fetch_ms_ = next; } -// periodic refresh (1 hour) of the cached versions.json, only when auto_fw_check is enabled -// runs on the main loop task so the blocking fetch never happens in an AsyncTCP callback +// refresh of the cached versions.json, at most once a day void WebStatusService::loop() { #ifndef EMSESP_STANDALONE - // only reach out to emsesp.org if the user has asked us to - if (!EMSESP::system_.auto_fw_check()) { + // with auto_fw_check off we only reach out to emsesp.org when the WebUI asks for version + // information, so an unattended system never contacts it at all + if (!EMSESP::system_.auto_fw_check() && !versions_fetch_requested_) { return; } @@ -426,6 +428,8 @@ void WebStatusService::loop() { return; } + versions_fetch_requested_ = false; + uint32_t interval; if (refresh_versions_cache()) { versions_failures_ = 0; diff --git a/src/web/WebStatusService.h b/src/web/WebStatusService.h index 2aa0555e2..935a54b6f 100644 --- a/src/web/WebStatusService.h +++ b/src/web/WebStatusService.h @@ -7,6 +7,7 @@ #include "../core/firmwareVersion.h" #include "../emsesp_version.h" +#include #include namespace emsesp { @@ -23,6 +24,7 @@ class WebStatusService { // called from EMSESP::loop() to refresh the cached versions.json from emsesp.org // so that the web request handler never has to do blocking HTTPS on the small AsyncTCP stack + // fetches on a daily schedule when auto_fw_check is on, otherwise only when getVersions asks void loop(); // true once we've had at least one successful versions.json fetch @@ -71,6 +73,10 @@ class WebStatusService { uint32_t versions_next_fetch_ms_ = 0; // uuid::get_uptime() of the next attempt; 0 = idle uint8_t versions_failures_ = 0; // consecutive failed fetches, drives the retry backoff + // set by getVersions() on the AsyncTCP task, consumed by the loop task, so that the WebUI still + // gets version information when auto_fw_check is off + std::atomic versions_fetch_requested_{false}; + // the cache is written by the loop task in refresh_versions_cache() and read by the AsyncTCP // task in getVersions()/current_upgradeable(), so the std::strings need guarding - without it a // request landing mid-update reads a buffer that has just been freed @@ -80,9 +86,9 @@ class WebStatusService { static constexpr const char * VERSIONS_URL = "http://emsesp.org/versions.json"; - static constexpr uint32_t VERSIONS_REFRESH_INTERVAL_MS = 60UL * 60UL * 1000UL; // 1 hour on success - static constexpr uint32_t VERSIONS_RETRY_INTERVAL_MS = 5UL * 60UL * 1000UL; // 5 min after the first failure - static constexpr uint32_t VERSIONS_INITIAL_FETCH_DELAY_MS = 5UL * 1000UL; // 5 s after a link comes up + static constexpr uint32_t VERSIONS_REFRESH_INTERVAL_MS = 24UL * 60UL * 60UL * 1000UL; // once a day on success + static constexpr uint32_t VERSIONS_RETRY_INTERVAL_MS = 5UL * 60UL * 1000UL; // 5 min after the first failure + static constexpr uint32_t VERSIONS_INITIAL_FETCH_DELAY_MS = 5UL * 1000UL; // 5 s after a link comes up // each attempt blocks the loop task for as long as the DNS lookup, connect and read timeouts // allow, so double the retry delay per consecutive failure: 5, 10, 20, 40, 80, 160 minutes