Suspend failed ESP32 MQTT and NTP uplinks for power saving
Share one bounded WiFi outage and recovery schedule across MQTT, automatic NTP, Companion station ownership and WebConfig. Preserve enabled settings and foreground access while allowing normal sleep after confirmed physical shutdown. Honor failed SDK client stops before handing off WiFi, protect clean teardown and reconfiguration, and retry transient ESP-NOW channel restoration without repeated disconnects. Add production-method, SDK failure and real sleep regressions to CI. Validation: native MQTT/NTP/clock/reconnect suites; production power and wrapper failure tests; browser, room HTTP, OTA and combined bridge regressions; Full Heltec V4 repeater, room and companion builds with capability, flash and linked-memory checks.
This commit is contained in:
1 parent
f62cc7b527
commit
6b3f7df4d0
37 files changed
+3258
-82
No files matched your search
@@ -4721,7 +4721,10 @@ void MyMesh::serviceMQTT(const char* wifi_ssid, const char* wifi_password) {
|
||||
}
|
||||
}
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED && _mqtt_configured && !_mqtt_started && _mqtt_bridge
|
||||
// Start the recovery scheduler even when the router is down at boot. The
|
||||
// Companion still owns association; waiting for GOT_IP here would leave its
|
||||
// failed station outside MQTT/NTP's shared power budget indefinitely.
|
||||
if (_mqtt_configured && !_mqtt_started && _mqtt_bridge
|
||||
#ifdef WITH_WEBCONFIG
|
||||
&& !isWebConfigSetupActive()
|
||||
#endif
|
||||
|
||||
@@ -100,6 +100,7 @@ MultiSerialInterface interface_manager;
|
||||
#include <helpers/WiFiReconnectPolicy.h>
|
||||
#include <helpers/WiFiPowerSave.h>
|
||||
#include <helpers/CompanionWiFiNtpPolicy.h>
|
||||
#include <helpers/WiFiNetworkPowerPolicy.h>
|
||||
#include <helpers/ui/DisplayTextLayout.h>
|
||||
#include <helpers/ui/IndicatorRenderProfile.h>
|
||||
#include <helpers/ui/WiFiSetupQrDisplay.h>
|
||||
@@ -1508,6 +1509,12 @@ void halt() {
|
||||
static bool companion_wifi_active = false;
|
||||
static bool companion_wifi_disable_in_progress = false;
|
||||
static bool companion_wifi_services_stopped = false;
|
||||
static bool companion_wifi_background_stopped = false;
|
||||
static bool companion_wifi_espnow_restore_pending = false;
|
||||
static uint32_t companion_wifi_espnow_restore_at = 0;
|
||||
#ifdef WITH_WEBCONFIG
|
||||
static bool companion_wifi_webconfig_start_pending = false;
|
||||
#endif
|
||||
static volatile bool companion_wifi_setup_requested = false;
|
||||
static volatile bool companion_wifi_setup_stop_requested = false;
|
||||
static bool companion_wifi_credential_reload_pending = false;
|
||||
@@ -1634,6 +1641,10 @@ void halt() {
|
||||
}
|
||||
|
||||
static void serviceCompanionWiFiNtp() {
|
||||
if (mesh::wifi::networkPower().backgroundSuspended()) {
|
||||
cancelCompanionWiFiNtp(false);
|
||||
return;
|
||||
}
|
||||
// Configured MQTT builds already perform a fresh startup NTP sync and a
|
||||
// daily refresh. The common Companion owner covers every non-MQTT or
|
||||
// runtime-unconfigured WiFi node without racing MQTT's SNTP proof.
|
||||
@@ -1832,6 +1843,7 @@ void halt() {
|
||||
|
||||
void scheduleCompanionWiFiCredentialReload() {
|
||||
loadCompanionWiFiCredentials();
|
||||
mesh::wifi::networkPower().requestProbe();
|
||||
companion_wifi_credential_reload_pending = true;
|
||||
companion_wifi_credential_reload_at = millis() + 1500UL;
|
||||
if (companion_wifi_credential_reload_at == 0) {
|
||||
@@ -1898,6 +1910,7 @@ void halt() {
|
||||
|
||||
void requestCompanionWiFiSetup() {
|
||||
if (mesh::wireless::control().blocked(mesh::wireless::WiFi)) return;
|
||||
mesh::wifi::networkPower().requestProbe();
|
||||
companion_wifi_setup_stop_requested = false;
|
||||
companion_wifi_setup_requested = true;
|
||||
}
|
||||
@@ -1921,6 +1934,7 @@ void halt() {
|
||||
return false;
|
||||
}
|
||||
companion_wifi_requested = enabled;
|
||||
if (enabled) mesh::wifi::networkPower().requestProbe();
|
||||
if (!companion_wifi_requested && companion_wifi_active) {
|
||||
companion_wifi_disable_in_progress = true;
|
||||
}
|
||||
@@ -2230,6 +2244,60 @@ void halt() {
|
||||
#endif
|
||||
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
static bool companionWiFiBackgroundSuspended() {
|
||||
// MQTT publishes this flag only after its own TLS and SNTP work is quiet.
|
||||
// A foreground OTA command can acquire the radio before its next pass.
|
||||
return mesh::wifi::networkPower().backgroundSuspended()
|
||||
&& !mesh::wifi::networkPower().foregroundActive()
|
||||
&& !board.isOTAUpdateRunning();
|
||||
}
|
||||
|
||||
static bool companionWiFiAutomaticRecoveryAllowed() {
|
||||
// MQTT owns one combined outage/cooldown clock. Raising an automatic AP
|
||||
// during that grace period would create a foreground owner indefinitely.
|
||||
return !mesh::wifi::networkPower().managed();
|
||||
}
|
||||
|
||||
#ifdef WITH_WEBCONFIG
|
||||
static void startCompanionWiFiAutoWebConfig() {
|
||||
companion_wifi_webconfig_start_pending = false;
|
||||
if (!WebConfigServer::loadEnabled(true)) return;
|
||||
if (companion_wifi_has_credentials && WiFi.status() != WL_CONNECTED) {
|
||||
// The Companion owns the initial saved-SSID attempt. Do not ask the
|
||||
// portal to start its separate fifteen-second AP fallback at boot.
|
||||
companion_wifi_webconfig_start_pending = true;
|
||||
return;
|
||||
}
|
||||
char web_reply[160];
|
||||
the_mesh.startWebConfig(!companion_wifi_has_credentials, web_reply);
|
||||
WIFI_DEBUG_PRINTLN("%s", web_reply);
|
||||
}
|
||||
|
||||
static void serviceCompanionWiFiAutoWebConfig() {
|
||||
if (!companion_wifi_webconfig_start_pending || !companion_wifi_requested
|
||||
|| !companion_wifi_active || companionWiFiBackgroundSuspended()) return;
|
||||
if (!WebConfigServer::loadEnabled(true)) {
|
||||
companion_wifi_webconfig_start_pending = false;
|
||||
return;
|
||||
}
|
||||
if (WiFi.status() != WL_CONNECTED
|
||||
|| the_mesh.isWebConfigActiveOrStopping()) return;
|
||||
startCompanionWiFiAutoWebConfig();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void serviceCompanionWiFiNetworkPowerHold() {
|
||||
bool active = wifi_interface.isConnected()
|
||||
|| companion_wifi_credential_reload_pending
|
||||
|| companion_wifi_setup_requested
|
||||
|| board.isOTAUpdateRunning();
|
||||
#ifdef ENABLE_OTA
|
||||
active = active || ota_console_client.connected();
|
||||
#endif
|
||||
mesh::wifi::networkPower().setHold(
|
||||
mesh::wifi::NetworkPowerHold::CompanionClient, active);
|
||||
}
|
||||
|
||||
static void resetCompanionWiFiRecoveryState() {
|
||||
wifi_reconnect_tracker = WiFiReconnectPolicy::Tracker();
|
||||
wifi_setup_attempted = false;
|
||||
@@ -2242,6 +2310,7 @@ void halt() {
|
||||
|| static_cast<int32_t>(millis() - companion_wifi_credential_reload_at) < 0) {
|
||||
return;
|
||||
}
|
||||
if (companionWiFiBackgroundSuspended()) return;
|
||||
#ifdef WITH_WEBCONFIG
|
||||
if (the_mesh.isWebConfigActiveOrStopping()) return;
|
||||
#endif
|
||||
@@ -2250,6 +2319,7 @@ void halt() {
|
||||
|
||||
companion_wifi_credential_reload_pending = false;
|
||||
companion_wifi_credential_reload_at = 0;
|
||||
companion_wifi_espnow_restore_pending = false;
|
||||
loadCompanionWiFiCredentials();
|
||||
resetCompanionWiFiRecoveryState();
|
||||
if (!companion_wifi_requested || !companion_wifi_active
|
||||
@@ -2270,9 +2340,11 @@ void halt() {
|
||||
static void startCompanionWiFi() {
|
||||
if (mesh::wireless::control().blocked(mesh::wireless::WiFi)) return;
|
||||
if (companion_wifi_active) return;
|
||||
if (companionWiFiBackgroundSuspended()) return;
|
||||
if (!mesh::wifi::stationMutationAllowed()) return;
|
||||
|
||||
board.setInhibitSleep(true);
|
||||
companion_wifi_espnow_restore_pending = false;
|
||||
mesh::wifi::setStationAutoReconnect(true);
|
||||
resetCompanionWiFiRecoveryState();
|
||||
|
||||
@@ -2290,11 +2362,7 @@ void halt() {
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_WEBCONFIG
|
||||
if (WebConfigServer::loadEnabled(true)) {
|
||||
char web_reply[160];
|
||||
the_mesh.startWebConfig(!companion_wifi_has_credentials, web_reply);
|
||||
WIFI_DEBUG_PRINTLN("%s", web_reply);
|
||||
}
|
||||
startCompanionWiFiAutoWebConfig();
|
||||
#endif
|
||||
|
||||
applyCompanionWiFiPowerSave();
|
||||
@@ -2305,6 +2373,7 @@ void halt() {
|
||||
#endif
|
||||
companion_wifi_active = true;
|
||||
companion_wifi_services_stopped = false;
|
||||
companion_wifi_background_stopped = false;
|
||||
WIFI_DEBUG_PRINTLN("WiFi enabled by BOOT/GPIO 0 control");
|
||||
}
|
||||
|
||||
@@ -2329,17 +2398,80 @@ void halt() {
|
||||
|
||||
static void stopCompanionInfrastructureWiFi() {
|
||||
WiFi.setAutoReconnect(false);
|
||||
#if defined(MESH_PRIMARY_ESPNOW) && MESH_PRIMARY_ESPNOW
|
||||
// ESP-NOW is the mesh radio on this target. Drop the station/AP services
|
||||
// without stopping the driver, then restore its fixed LR mesh channel.
|
||||
WiFi.disconnect(false, false);
|
||||
WiFi.mode(WIFI_STA);
|
||||
mesh::wifi::applyProtocolMask(WIFI_IF_STA);
|
||||
mesh::wifi::restoreEspNowChannel();
|
||||
#else
|
||||
WiFi.disconnect(true, false);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
if (mesh::wifi::espNowChannelConstrained()) {
|
||||
// Primary ESP-NOW and a live optional bridge both share this driver.
|
||||
// Drop only station association and keep their fixed mesh channel.
|
||||
WiFi.disconnect(false, false);
|
||||
WiFi.mode(WIFI_STA);
|
||||
mesh::wifi::applyProtocolMask(WIFI_IF_STA);
|
||||
companion_wifi_espnow_restore_pending =
|
||||
mesh::wifi::restoreEspNowChannel() != ESP_OK;
|
||||
companion_wifi_espnow_restore_at = millis() + 1000UL;
|
||||
} else {
|
||||
companion_wifi_espnow_restore_pending = false;
|
||||
WiFi.disconnect(true, false);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
static void serviceCompanionEspNowChannelRestore() {
|
||||
if (!companion_wifi_espnow_restore_pending) return;
|
||||
if (!mesh::wifi::espNowChannelConstrained()) {
|
||||
companion_wifi_espnow_restore_pending = false;
|
||||
return;
|
||||
}
|
||||
if (board.isOTAUpdateRunning()
|
||||
|| mesh::wifi::networkPower().foregroundActive()
|
||||
|| !mesh::wifi::stationMutationAllowed()) return;
|
||||
const uint32_t now = millis();
|
||||
if (static_cast<int32_t>(now - companion_wifi_espnow_restore_at) < 0) return;
|
||||
// esp_wifi_set_channel may fail until an asynchronous disconnect/scan
|
||||
// completes. Retry the channel only; repeated disconnects would prevent
|
||||
// the shared ESP-NOW receiver from recovering during a long cooldown.
|
||||
companion_wifi_espnow_restore_pending =
|
||||
mesh::wifi::restoreEspNowChannel() != ESP_OK;
|
||||
companion_wifi_espnow_restore_at = now + 1000UL;
|
||||
}
|
||||
|
||||
static void serviceCompanionWiFiBackgroundPower() {
|
||||
serviceCompanionEspNowChannelRestore();
|
||||
if (!companion_wifi_active || !companion_wifi_requested) return;
|
||||
if (companionWiFiBackgroundSuspended()) {
|
||||
if (companion_wifi_background_stopped) return;
|
||||
// Settings and MQTT's scheduling task stay enabled. These idle socket
|
||||
// listeners and the common NTP request own no useful foreground work.
|
||||
cancelCompanionWiFiNtp(false);
|
||||
wifi_interface.end();
|
||||
#ifdef ENABLE_OTA
|
||||
ota_console_stop();
|
||||
#endif
|
||||
stopCompanionInfrastructureWiFi();
|
||||
board.setInhibitSleep(mesh::wifi::espNowChannelConstrained());
|
||||
companion_wifi_background_stopped = true;
|
||||
WIFI_DEBUG_PRINTLN("Network unavailable; WiFi suspended until the next recovery probe");
|
||||
return;
|
||||
}
|
||||
if (!companion_wifi_background_stopped) return;
|
||||
if (!mesh::wifi::stationMutationAllowed()) return;
|
||||
|
||||
board.setInhibitSleep(true);
|
||||
companion_wifi_espnow_restore_pending = false;
|
||||
resetCompanionWiFiRecoveryState();
|
||||
if (companion_wifi_has_credentials) {
|
||||
WiFi.mode(WIFI_STA);
|
||||
mesh::wifi::applyProtocolMask(WIFI_IF_STA);
|
||||
mesh::wifi::setStationAutoReconnect(true);
|
||||
wifi_reconnect_tracker.noteDisconnected(millis());
|
||||
mesh::wifi::beginStation(configured_wifi_ssid, configured_wifi_password);
|
||||
}
|
||||
applyCompanionWiFiPowerSave();
|
||||
wifi_interface.begin(TCP_PORT);
|
||||
wifi_interface.enable();
|
||||
#ifdef ENABLE_OTA
|
||||
ota_console_start();
|
||||
#endif
|
||||
companion_wifi_background_stopped = false;
|
||||
WIFI_DEBUG_PRINTLN("WiFi resumed for a bounded network recovery probe");
|
||||
}
|
||||
|
||||
static bool finishStoppingCompanionWiFi() {
|
||||
@@ -2368,6 +2500,10 @@ void halt() {
|
||||
board.setInhibitSleep(false);
|
||||
resetCompanionWiFiRecoveryState();
|
||||
companion_wifi_active = false;
|
||||
companion_wifi_background_stopped = false;
|
||||
#ifdef WITH_WEBCONFIG
|
||||
companion_wifi_webconfig_start_pending = false;
|
||||
#endif
|
||||
#if defined(MESH_PRIMARY_ESPNOW) && MESH_PRIMARY_ESPNOW
|
||||
WIFI_DEBUG_PRINTLN(
|
||||
"Companion WiFi services disabled; ESP-NOW mesh radio remains active");
|
||||
@@ -2388,6 +2524,10 @@ void halt() {
|
||||
if (companion_wifi_requested && !companion_wifi_active) {
|
||||
startCompanionWiFi();
|
||||
}
|
||||
serviceCompanionWiFiBackgroundPower();
|
||||
#ifdef WITH_WEBCONFIG
|
||||
serviceCompanionWiFiAutoWebConfig();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3014,7 +3154,25 @@ static bool companionNativeUsbLightSleepReady() {
|
||||
// Full compiles every transport, but a compiled driver is not an active
|
||||
// receiver. Preserve live services and pending replies while permitting
|
||||
// the same short sleep slice when those services have been turned off.
|
||||
if (companion_wireless.enabled() != 0 || interface_manager.hasPendingIO()
|
||||
uint8_t enabled_services = companion_wireless.enabled();
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
// The user's saved WiFi preference and an idle WebConfig listener remain
|
||||
// enabled during automatic suspension. Only a confirmed physical power-off
|
||||
// releases their sleep blocker; foreground work and shared ESP-NOW retain it.
|
||||
if (companion_wifi_background_stopped
|
||||
&& mesh::wifi::networkPower().backgroundSuspended()
|
||||
&& !mesh::wifi::networkPower().foregroundActive()
|
||||
&& !mesh::wifi::espNowChannelConstrained()) {
|
||||
wifi_mode_t parked_mode = WIFI_MODE_NULL;
|
||||
const esp_err_t parked_result = esp_wifi_get_mode(&parked_mode);
|
||||
if ((parked_result == ESP_OK && parked_mode == WIFI_MODE_NULL)
|
||||
|| parked_result == ESP_ERR_WIFI_NOT_INIT
|
||||
|| parked_result == ESP_ERR_WIFI_NOT_STARTED) {
|
||||
enabled_services &= static_cast<uint8_t>(~mesh::wireless::WiFi);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (enabled_services != 0 || interface_manager.hasPendingIO()
|
||||
|| board.isOTAUpdateRunning() || board.isRadioTestActive()
|
||||
|| sensors.gpsUsesSerialUart(1)) return false;
|
||||
#if defined(BLE_PIN_CODE) && !CONFIG_IDF_TARGET_ESP32C6
|
||||
@@ -3624,6 +3782,9 @@ void loop() {
|
||||
}
|
||||
#endif
|
||||
mesh::wireless::control().service(millis());
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
serviceCompanionWiFiNetworkPowerHold();
|
||||
#endif
|
||||
#if defined(NRF52_PLATFORM)
|
||||
board.feedWatchdog();
|
||||
#endif
|
||||
@@ -3800,8 +3961,11 @@ void loop() {
|
||||
}
|
||||
#endif
|
||||
serviceCompanionWiFiCredentialReload();
|
||||
serviceCompanionWiFiNetworkPowerHold();
|
||||
serviceCompanionWiFiState();
|
||||
if (companion_wifi_requested && companion_wifi_active) {
|
||||
if (companion_wifi_requested && companion_wifi_active
|
||||
&& !companionWiFiBackgroundSuspended()
|
||||
&& !companion_wifi_background_stopped) {
|
||||
#ifdef ENABLE_OTA
|
||||
ota_console_loop(); // service the local text console (port 5002)
|
||||
#endif
|
||||
@@ -3847,7 +4011,7 @@ void loop() {
|
||||
}
|
||||
} else if (configured_wifi_ssid[0]) {
|
||||
wifi_reconnect_tracker.noteDisconnected(wifi_now);
|
||||
if (!wifi_setup_recovery_mode
|
||||
if (!wifi_setup_recovery_mode && companionWiFiAutomaticRecoveryAllowed()
|
||||
#ifdef WITH_WEBCONFIG
|
||||
&& !the_mesh.isWebConfigSetupActive()
|
||||
#else
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "MyMesh.h"
|
||||
#if defined(ESP32_PLATFORM)
|
||||
#include <helpers/esp32/BootFileSystem.h>
|
||||
#include <helpers/WiFiNetworkPowerPolicy.h>
|
||||
#if defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) \
|
||||
|| defined(LIGHTWEIGHT_WIFI_OTA) || (defined(ADMIN_PASSWORD) && !defined(DISABLE_WIFI_OTA))
|
||||
#include <WiFi.h>
|
||||
@@ -11125,6 +11126,9 @@ bool MyMesh::startWebConfigImpl(bool force_ap, char* reply, bool automatic_setup
|
||||
return true;
|
||||
}
|
||||
if (_webconfig && (_webconfig->isRunning() || _webconfig->isStopping())) {
|
||||
if (!automatic_setup && !_webconfig->isStopping()) {
|
||||
_webconfig->requestNetworkAccess();
|
||||
}
|
||||
strcpy(reply, _webconfig->isStopping() ? "Err: webconfig still stopping, retry shortly"
|
||||
: "Err: webconfig already running");
|
||||
return true;
|
||||
@@ -11163,6 +11167,7 @@ bool MyMesh::startWebConfigImpl(bool force_ap, char* reply, bool automatic_setup
|
||||
}
|
||||
}
|
||||
|
||||
if (!automatic_setup) _webconfig->requestNetworkAccess();
|
||||
const bool setup_was_suspended = _unconfigured_setup_espnow_suspended;
|
||||
#ifdef WITH_ESPNOW_BRIDGE
|
||||
const bool espnow_was_running = isEspNowBridgeRunning();
|
||||
@@ -13819,11 +13824,15 @@ void MyMesh::serviceIdleWiFi() {
|
||||
&& (!defined(MESH_PRIMARY_ESPNOW) || !MESH_PRIMARY_ESPNOW) \
|
||||
&& (!defined(MESH_ESPNOW_RADIO) || !MESH_ESPNOW_RADIO)
|
||||
if (_cli.getBoard()->isOTAUpdateRunning()) return;
|
||||
if (mesh::wifi::networkPower().foregroundActive()) return;
|
||||
#ifdef WITH_WEBCONFIG
|
||||
if (isWebConfigActive()) return;
|
||||
if (isWebConfigActive() && (!mesh::wifi::networkPower().backgroundSuspended()
|
||||
|| _webconfig->isNetworkForegroundActive(millis()))) return;
|
||||
#endif
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
if (_ota_update_at) return;
|
||||
// The MQTT worker owns physical shutdown and resume, including cooldown.
|
||||
// Never race its Core 0 Arduino/SDK interface transition from this loop.
|
||||
if (mqtt_bridge && (mqtt_bridge->isRunning() || mqtt_bridge->isStopping())) return;
|
||||
#endif
|
||||
#ifdef WITH_ESPNOW_BRIDGE
|
||||
@@ -13852,8 +13861,12 @@ void MyMesh::serviceIdleWiFi() {
|
||||
bool MyMesh::hasPendingWork() const {
|
||||
if (isDualRadioActive()) return true;
|
||||
if (hasPendingOtaApply()) return true;
|
||||
#if defined(ESP32_PLATFORM)
|
||||
if (mesh::wifi::networkPower().foregroundActive()) return true;
|
||||
#endif
|
||||
#ifdef WITH_WEBCONFIG
|
||||
if (isWebConfigActive()) return true;
|
||||
if (isWebConfigActive() && (!mesh::wifi::networkPower().backgroundSuspended()
|
||||
|| _webconfig->isNetworkForegroundActive(millis()))) return true;
|
||||
#endif
|
||||
#if defined(ESP32_PLATFORM) \
|
||||
&& (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) \
|
||||
@@ -13871,7 +13884,13 @@ bool MyMesh::hasPendingWork() const {
|
||||
if (deferred_cli_command.pending || pending_self_advert || _cli.hasActiveUserGpioTimer()) return true;
|
||||
#if defined(WITH_BRIDGE)
|
||||
const AbstractBridge* active_bridge = activeBridge();
|
||||
if (active_bridge && active_bridge->isRunning()) return true;
|
||||
if (active_bridge && active_bridge->isRunning()) {
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
if (active_bridge != mqtt_bridge || !mqtt_bridge->isNetworkSuspended()) return true;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
if (mqtt_bridge && mqtt_bridge->isStopping()) return true;
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "MyMesh.h"
|
||||
#if defined(ESP32_PLATFORM)
|
||||
#include <helpers/esp32/BootFileSystem.h>
|
||||
#include <helpers/WiFiNetworkPowerPolicy.h>
|
||||
#if defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) \
|
||||
|| defined(LIGHTWEIGHT_WIFI_OTA) || (defined(ADMIN_PASSWORD) && !defined(DISABLE_WIFI_OTA))
|
||||
#include <WiFi.h>
|
||||
@@ -3119,6 +3120,9 @@ bool MyMesh::startWebConfigImpl(bool force_ap, char* reply, bool automatic_setup
|
||||
return true;
|
||||
}
|
||||
if (_webconfig && (_webconfig->isRunning() || _webconfig->isStopping())) {
|
||||
if (!automatic_setup && !_webconfig->isStopping()) {
|
||||
_webconfig->requestNetworkAccess();
|
||||
}
|
||||
strcpy(reply, _webconfig->isStopping() ? "Err: webconfig still stopping, retry shortly"
|
||||
: "Err: webconfig already running");
|
||||
return true;
|
||||
@@ -3154,6 +3158,7 @@ bool MyMesh::startWebConfigImpl(bool force_ap, char* reply, bool automatic_setup
|
||||
}
|
||||
}
|
||||
|
||||
if (!automatic_setup) _webconfig->requestNetworkAccess();
|
||||
const bool setup_was_suspended = _unconfigured_setup_espnow_suspended;
|
||||
#ifdef WITH_ESPNOW_BRIDGE
|
||||
const bool espnow_was_running = isEspNowBridgeRunning();
|
||||
@@ -4198,11 +4203,15 @@ void MyMesh::serviceIdleWiFi() {
|
||||
&& (!defined(MESH_PRIMARY_ESPNOW) || !MESH_PRIMARY_ESPNOW) \
|
||||
&& (!defined(MESH_ESPNOW_RADIO) || !MESH_ESPNOW_RADIO)
|
||||
if (_cli.getBoard()->isOTAUpdateRunning()) return;
|
||||
if (mesh::wifi::networkPower().foregroundActive()) return;
|
||||
#ifdef WITH_WEBCONFIG
|
||||
if (isWebConfigActive()) return;
|
||||
if (isWebConfigActive() && (!mesh::wifi::networkPower().backgroundSuspended()
|
||||
|| _webconfig->isNetworkForegroundActive(millis()))) return;
|
||||
#endif
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
if (_ota_update_at) return;
|
||||
// The MQTT worker also owns its suspended station: Core 1 must not race
|
||||
// the worker's shutdown or the next bounded probe on Core 0.
|
||||
if (bridge && (bridge->isRunning() || bridge->isStopping())) return;
|
||||
#endif
|
||||
#ifdef WITH_ESPNOW_BRIDGE
|
||||
@@ -4226,8 +4235,12 @@ void MyMesh::serviceIdleWiFi() {
|
||||
bool MyMesh::hasPendingWork() const {
|
||||
if (isDualRadioActive()) return true;
|
||||
if (hasPendingOtaApply()) return true;
|
||||
#if defined(ESP32_PLATFORM)
|
||||
if (mesh::wifi::networkPower().foregroundActive()) return true;
|
||||
#endif
|
||||
#ifdef WITH_WEBCONFIG
|
||||
if (isWebConfigActive()) return true;
|
||||
if (isWebConfigActive() && (!mesh::wifi::networkPower().backgroundSuspended()
|
||||
|| _webconfig->isNetworkForegroundActive(millis()))) return true;
|
||||
#endif
|
||||
#if defined(ESP32_PLATFORM) \
|
||||
&& (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) \
|
||||
@@ -4243,7 +4256,11 @@ bool MyMesh::hasPendingWork() const {
|
||||
if (_local_cli_output.busy()) return true;
|
||||
#endif
|
||||
#if defined(WITH_BRIDGE)
|
||||
if (bridge && bridge->isRunning()) return true; // bridge needs WiFi radio, can't sleep
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
if (bridge && bridge->isRunning() && !bridge->isNetworkSuspended()) return true;
|
||||
#else
|
||||
if (bridge && bridge->isRunning()) return true;
|
||||
#endif
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
if (bridge && bridge->isStopping()) return true;
|
||||
#endif
|
||||
|
||||
Reference in new issue
Block a user