Merge pull request #5564 from TD-er/bugfix/wifi_setup_crash

[WiFi] Fix stack overflow crash when no credentials set
This commit is contained in:
TD-er
2026-06-25 17:23:20 +02:00
committed by GitHub
22 changed files with 617 additions and 421 deletions
+36 -4
View File
@@ -244,6 +244,8 @@
"
``WiFi#Connected``
Triggered when the ESP has connected to Wi-Fi.
N.B. Similar events are also given for other network interfaces like ``ap``, ``eth`` or ``ppp``.
","
.. code-block:: none
@@ -256,6 +258,8 @@
"
``WiFi#Disconnected``
Triggered when the ESP has disconnected from Wi-Fi.
N.B. Similar events are also given for other network interfaces like ``ap``, ``eth`` or ``ppp``.
","
.. code-block:: none
@@ -271,6 +275,34 @@
SendToHTTP,url.com,80,/report.php?hash=123abc456&t=[temp2#out]
Endon
"
"
``WiFi#Enabled``
Triggered when the network interface ``WiFi`` was enabled.
N.B. Similar events are also given for other network interfaces like ``ap``, ``eth`` or ``ppp``.
","
.. code-block:: none
on WiFi#Enabled do
GPIO,2,1 // Turn on WiFi led
endon
"
"
``WiFi#Disabled``
Triggered when the network interface ``WiFi`` was disabled.
N.B. Similar events are also given for other network interfaces like ``ap``, ``eth`` or ``ppp``.
","
.. code-block:: none
On WiFi#Disabled Do
GPIO,2,0 // Turn off WiFi led
Endon
"
"
``WiFi#ChangedAccesspoint``
@@ -298,7 +330,7 @@
"
"
``WiFi#APmodeEnabled``
``ap#Enabled``
Triggered when the ESP has set the AP mode (access point) active.
This may happen when no valid WiFi settings are found or the ESP cannot connect to the set AP, but it can also be enabled via some command.
N.B. Sending a publish command may not be very useful on this event, since this will mainly happen when there is no WiFi connection.
@@ -306,20 +338,20 @@
.. code-block:: none
on WiFi#APmodeEnabled do
on ap#Enabled do
... // Some command
endon
"
"
``WiFi#APmodeDisabled``
``ap#Disabled``
Triggered when the ESP has disabled the AP mode (access point).
This can happen some time (default 60 seconds) after a WiFi connection has been made. Or disabled using some command.
","
.. code-block:: none
on WiFi#APmodeDisabled do
on ap#Disabled do
Publish,%sysname%/status,AP disabled
endon
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

+32 -11
View File
@@ -4,17 +4,38 @@ WiFi
WiFi State Machine
==================
ESPEasy WiFi modes
------------------
.. figure:: StateDiagramESPEasyWiFi_mode_e.svg
:width: 70 %
:align: center
State Diagram ESPEasy WiFi_mode_e
WiFi STA states
---------------
#. STA off -> ESPEASY_WIFI_DISCONNECTED
#. STA connecting
#. STA connected -> ESPEASY_WIFI_CONNECTED
#. STA got IP -> ESPEASY_WIFI_GOT_IP
#. STA connected && got IP -> ESPEASY_WIFI_SERVICES_INITIALIZED
#. ``Disabled`` WiFi STA radio is off. When timeout is set to 0, no new attempt should be made (e.g. low power mode or Ethernet active) Will only change to STA_Initializing when WiFi is allowed/required to start
#. ``TimeOut/Error`` Error state, some action failed
#. ``STA Initializing`` State from where we decide to start scanning or connecting
#. ``STA Scanning`` STA mode + scanning
#. ``STA+AP Scanning`` STA+AP mode + scanning, (scanning per channel) needs some careful handling to prevent disconnecting the connected stations.
#. ``STA Connecting`` Connecting to an AP
#. ``STA Reconnecting`` Reconnecting to an AP. May need to handle some specific disconnect reasons differently from connecting for the first time.
#. ``STA Connected`` Connected to an AP.
#. ``STA Connected Stable`` Connected to an AP for at least 5 minutes
.. figure:: StateDiagramESPEasyWiFi_STA_State_e.svg
:width: 70 %
:align: center
State Diagram ESPEasy WiFi_STA_State_e
N.B. the states are flags, meaning both "connected" and "got IP" must be set
to be considered ESPEASY_WIFI_SERVICES_INITIALIZED
The flag wifiConnectAttemptNeeded indicates whether a new connect attempt is needed.
This is set to true when:
@@ -28,9 +49,9 @@ This is set to true when:
WiFi AP mode states
-------------------
#. AP on -> reset AP disable timer
#. AP client connect/disconnect -> reset AP disable timer
#. AP off -> AP disable timer = 0;
#. ``AP on`` reset AP disable timer
#. ``AP client connect/disconnect`` reset AP disable timer
#. ``AP off`` AP disable timer = 0;
AP mode will be disabled when both apply:
@@ -141,7 +162,7 @@ Case 1, your PC does not know the MAC address of the ESP:
* Your PC tries to find the MAC address belonging to an IP address using an ARP packet (question is like: "Who has 1.2.3.4?")
* ARP packets gets broadcasted to the entire network
* If the ESP misses such an ARP request, you cannot route the IP packet to your ESP. -> fail
* If the ESP misses such an ARP request, you cannot route the IP packet to your ESP. -> fail
Case 2, your PR does know the MAC address of the ESP, but a switch or access point does not:
+1 -1
View File
@@ -625,7 +625,7 @@ int HTTPClientLight::sendRequest(const char * type, uint8_t * payload, size_t si
// connect to server
if(!connect()) {
if (_secure) {
if (_secure && _transportTraits) {
int32_t ret = _transportTraits->getLastError(*_client);
if (ret) {
return returnError(-1000 - ret); // BearSSL error 46 transformed to -1046
+2
View File
@@ -244,6 +244,8 @@ build_flags = -DESP32_STAGE
-DNO_GLOBAL_WIFIPROV
; -Wsuggest-override
-mstrict-align
-DUSE_WEBCLIENT_HTTPS
-DFEATURE_TLS=1
lib_ignore = BLE
Zigbee
@@ -246,12 +246,16 @@ void NWPluginData_static_runtime::processEvents()
if (connected_changed || establishConnect_changed)
{
if (_connectedStats.isOn()) {
log_connected();
if (_establishConnectStats.isSet()) {
if (_connectedStats.isOn()) {
log_connected();
// _establishConnectStats.resetCount();
} else if (_connectedStats.isOff() && !_establishConnectStats.isOn()) {
log_disconnected();
// _establishConnectStats.resetCount();
} else if (_establishConnectStats.isSet() &&
_connectedStats.isOff() &&
!_establishConnectStats.isOn()) {
log_disconnected();
}
}
}
@@ -280,19 +284,9 @@ void NWPluginData_static_runtime::processEvents()
if (Settings.UseRules && _eventInterfaceName.length())
{
if (_operationalStats.isOn()) {
if (_isAP) {
eventQueue.addDeDup(F("WiFi#APmodeConnected"));
}
else {
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Connected")));
}
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Connected")));
} else if (_operationalStats.isOff()) {
if (_isAP) {
eventQueue.addDeDup(F("WiFi#APmodeDisconnected"));
}
else {
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Disconnected")));
}
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Disconnected")));
}
}
statusLED(true);
@@ -300,19 +294,9 @@ void NWPluginData_static_runtime::processEvents()
if (_startStopStats.changedSinceLastCheck_and_clear() && Settings.UseRules) {
if (_startStopStats.isOn()) {
if (_isAP) {
eventQueue.addDeDup(F("WiFi#APmodeEnabled"));
}
else {
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Enabled")));
}
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Enabled")));
} else if (_startStopStats.isOff()) {
if (_isAP) {
eventQueue.addDeDup(F("WiFi#APmodeDisabled"));
}
else {
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Disabled")));
}
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Disabled")));
}
}
}
@@ -105,13 +105,26 @@ public:
private:
WiFi_AP_Candidate_List_t candidates;
// Known credentials supplying the following:
// - Credentials index
// - Priority
// - SSID
// - Key
WiFi_AP_Candidate_List_t known;
WiFi_AP_Candidate_List_t scanned;
// Unprocessed found from latest scan
WiFi_AP_Candidate_List_t scanned_new;
// Processed found via one or more scans
// When processing scanned_new, matching elements from a previous scan (in 'scanned')
// will be updated with new information, like channel, RSSI, supported protocols, etc.
WiFi_AP_Candidate_List_t scanned;
// Sorted list of possible APs to connect to. Matching known and scanned.
// First element in the candidates list is the best candidate to try first.
// Failed connect attempts will be removed from the candidates list.
WiFi_AP_Candidate_List_t candidates;
WiFi_AP_Candidate_const_iterator known_it;
WiFi_AP_Candidate currentCandidate;
@@ -0,0 +1,60 @@
StateDiagram [frame=true framecolor=steelblue label="State Diagram ESPEasy WiFi_STA_State_e"] {
state Disabled [fillcolor=lightblue]
state TimeOut as "TimeOut/\nError" [fillcolor=orangered]
state STA_Initializing as "STA\nInitializing"
state STA_Scanning as "STA\nScanning"
state STA_AP_Scanning as "STA+AP\nScanning"
state STA_Connecting as "STA\nConnecting"
state STA_Reconnecting as "STA\nReconnecting"
state STA_Connected as "STA\nConnected" [fillcolor=palegreen]
choice AlreadyConnected
choice HasScanned_NoCredentials
choice AP_on_no_nw_found
choice KnownAPfound
choice ExitSTA
choice ScanDone
initialState->Disabled
Disabled -> STA_Initializing "Init\nSTA"
STA_Initializing -> AlreadyConnected "Already\nConnected?"
AlreadyConnected -> STA_Connected "Connected" [color=green]
AlreadyConnected -> HasScanned_NoCredentials "Has Credentials?"
Disabled <- HasScanned_NoCredentials "Scanned &\nNo Credentials"
HasScanned_NoCredentials -> KnownAPfound "Known\nNetwork\nfound?"
KnownAPfound -> AP_on_no_nw_found "Scan\nNeeded"
KnownAPfound -> STA_Connecting "No Scan\nNeeded"
AP_on_no_nw_found -> STA_AP_Scanning "AP"
AP_on_no_nw_found -> STA_Scanning "No AP"
TimeOut <- ScanDone "Scan\nFail" [color=red]
Disabled <- ScanDone "Scan\nSuccess" [color=green]
STA_Reconnecting <- STA_Connected "Disconnect" [color=red]
STA_Reconnecting -> STA_Connected "Connected" [color=green]
STA_Connecting -> STA_Connected "Connected" [color=green]
STA_Connected -> STA_Connected "After 5 min:\nMark Stable"
ScanDone <- STA_Scanning "Scan\nDone"
ScanDone <- STA_AP_Scanning "Scan\nDone"
STA_AP_Scanning <- STA_AP_Scanning "Next\nChannel"
TimeOut <- STA_Connecting "Connect\nFail" [color=red]
TimeOut <- STA_Initializing "Init\nSTA\nFail" [color=red]
Disabled <- Disabled "Wait for\nStartup Delay/\nSetup"
Disabled <- TimeOut "Restart\nWiFi"
Disabled <- ExitSTA "Exit\nSTA"
TimeOut <- STA_Reconnecting "Reconnect\nFail" [color=red]
}
@@ -0,0 +1,55 @@
StateDiagram [frame=true framecolor=steelblue label="State Diagram ESPEasyWiFi_mode_e"] {
choice NeedSetup
choice HasCredentials
choice HasCredentialsSetupRequired
choice APalwaysOn
choice APalwaysOnNoCred
state STA_only as "STA\nOnly" [fillcolor=cyan]
state STA_AP as "STA\n+\nAP" [fillcolor=olivedrab1]
state AP_only as "AP\nOnly" [fillcolor=orange1]
state Off [fillcolor=lightblue]
state Setup with behaviors "WiFi scan\nStart webUI\nEnter Credentials\nSave" [fillcolor=yellow] {
state Scan as "STA Only\nScan"
state StartAP as "AP Only\nWebUI"
state ClientConnect as "User Connects\nCaptive Portal to /setup"
state EnterCredentials as "Enter WiFi Credentials"
state ClientDisconnect as "User\nDisconnects"
state CredentialsUpdated as "Credentials Updated"
initialState -> Scan
Scan -> StartAP
StartAP -> ClientConnect
ClientDisconnect <- ClientConnect
Scan <- ClientDisconnect
Scan <- StartAP "Time Out"
ClientConnect -> EnterCredentials
EnterCredentials -> CredentialsUpdated
CredentialsUpdated -> finalState
}
initialState->Off
NeedSetup <- Off "Check\nNeed Setup?"
NeedSetup -> HasCredentials "Setup not\nAllowed/\nRequired"
HasCredentials -> APalwaysOn "Has\nCredentials"
APalwaysOn -> STA_AP "AP Always On\nor\nSetup 1st connect"
APalwaysOn -> STA_only "No AP"
HasCredentials -> APalwaysOnNoCred "No\nCredentials"
Off <- APalwaysOnNoCred "No AP"
APalwaysOnNoCred -> AP_only "AP"
NeedSetup -> HasCredentialsSetupRequired "Setup\nAllowed"
HasCredentialsSetupRequired -> APalwaysOn "Has Credentials,\nNo Setup"
Setup <- HasCredentialsSetupRequired "No Credentials,\nEnter Setup"
Setup -> NeedSetup "Setup\nDone"
STA_only <- STA_only "Retry/\nReconnect"
STA_AP -> AP_only "No Known\nNetwork found"
STA_AP <- STA_AP "Retry/\nReconnect"
Setup <- STA_AP "Setup\nFailed 1st\nConnect"
}
+236 -289
View File
@@ -1,5 +1,5 @@
#include "../wifi/ESPEasyWiFi_state_machine.h"
#include "ESPEasy/net/wifi/WiFi_State.h"
#include "ESPEasy/net/wifi/WiFi_STA_State.h"
#if FEATURE_WIFI
@@ -24,9 +24,14 @@ namespace wifi {
# define WIFI_STATE_MACHINE_STA_SCANNING_TIMEOUT 10000
# define WIFI_STATE_MACHINE_AP_ONLY_TIMEOUT 60000
# define WIFI_STATE_MACHINE_STA_CONNECTED_STABLE 300000 // 5 minutes
void ESPEasyWiFi_t::setup() {
if (!Settings.getNetworkEnabled(NETWORK_INDEX_WIFI_STA)) { return; }
WiFi_AP_Candidates.clearCache();
WiFi_AP_Candidates.load_knownCredentials();
// TODO TD-er: Must maybe also call 'disable()' first?
// TODO TD-er: Load settings
@@ -43,276 +48,203 @@ void ESPEasyWiFi_t::setup() {
void ESPEasyWiFi_t::enable() {}
void ESPEasyWiFi_t::disable() { setState(WiFiState_e::Disabled, 100); }
void ESPEasyWiFi_t::disable() { setState(WiFi_STA_State_e::Disabled, 0); }
void ESPEasyWiFi_t::begin() {
if (connected()) setState(WiFiState_e::STA_Connected);
if (WiFi_AP_Candidates.hasCandidates()) {
setState(WiFiState_e::IdleWaiting, 100);
if (connected()) {
setState(WiFi_STA_State_e::STA_Connected);
} else {
if (WiFi_AP_Candidates.hasScanned()) {
// Has no candidates, but scan was performed.
if (shouldStartAP_fallback()) {
setState(WiFiState_e::AP_only, WIFI_STATE_MACHINE_AP_ONLY_TIMEOUT);
}
} else {
if (WifiIsAP(WiFi.getMode())) {
// TODO TD-er: Must check if any client is connected.
// If not, then we can disable AP mode and switch to WiFiState_e::STA_Scanning
setState(WiFiState_e::STA_AP_Scanning, WIFI_STATE_MACHINE_STA_AP_SCANNING_TIMEOUT);
} else {
// setState(WiFiState_e::STA_AP_Scanning, WIFI_STATE_MACHINE_STA_AP_SCANNING_TIMEOUT);
setState(WiFiState_e::STA_Scanning, WIFI_STATE_MACHINE_STA_SCANNING_TIMEOUT);
}
}
setState(WiFi_STA_State_e::STA_Initializing, 100);
}
}
void ESPEasyWiFi_t::loop()
{
// TODO TD-er: Must inspect WiFiEventData to see if we need to update some state here.
auto wifi_STA_data = getWiFi_STA_NWPluginData_static_runtime();
/*
if ((_state != WiFi_STA_State_e::Disabled) &&
(getWiFi_STA_NWPluginData_static_runtime() == nullptr)) {
setState(WiFi_STA_State_e::Disabled, 100);
return;
}
*/
if (!wifi_STA_data) { return; }
const bool stateTimeoutReached = _state_timeout.isSet() && _state_timeout.timeReached();
if (_state != WiFiState_e::IdleWaiting) {
if (_callbackError ||
(_state_timeout.isSet() && _state_timeout.timeReached()))
if (_state != WiFi_STA_State_e::TimeOut) {
if (_callbackError || stateTimeoutReached)
{
// TODO TD-er: Must check what error was given???
_callbackError = false;
if (getMode() == ESPEasyWiFi_mode_e::Setup /* && _state == WiFiState_e::AP_Fallback */) {
// TODO TD-er: Must perhaps check what action was pending and act on it?
if (stateTimeoutReached) {
if (_state == WiFi_STA_State_e::Disabled) {
setState(WiFi_STA_State_e::STA_Initializing, 100);
return;
}
setState(_state == WiFiState_e::STA_Connected_Setup ? WiFiState_e::STA_Connected : WiFiState_e::IdleWaiting);
} else {
setState(WiFiState_e::WiFiOFF);
if (_state == WiFi_STA_State_e::STA_Connected) {
setState(WiFi_STA_State_e::STA_Connected_Stable);
return;
}
}
setState(WiFi_STA_State_e::TimeOut, 100);
return;
}
}
switch (_state)
{
case WiFiState_e::Disabled:
case WiFi_STA_State_e::Disabled:
// Do nothing here, as the device is disabled.
break;
case WiFiState_e::WiFiOFF:
begin();
// setState(WiFiState_e::IdleWaiting, 100);
case WiFi_STA_State_e::TimeOut:
// We always go from TimeOut to Disabled.
// Called this from the loop() to prevent recursive calls to setState
setState(WiFi_STA_State_e::Disabled, 100);
break;
case WiFiState_e::AP_only:
case WiFiState_e::AP_Fallback:
// TODO TD-er: Should also check for 'setup' mode, so we switch to connecting state instead of IdleWaiting
// For sure not just when there are candidates.
if (!ESPEasy::net::wifi::wifiAPmodeActivelyUsed()) {
if (WiFi_AP_Candidates.hasCandidates() ||
_state_timeout.timeReached()) {
setState(WiFiState_e::IdleWaiting, 100);
}
}
break;
case WiFiState_e::IdleWaiting:
case WiFi_STA_State_e::STA_Initializing:
WiFi_AP_Candidates.purge_expired();
if (connected()) {
if (getMode() == ESPEasyWiFi_mode_e::Setup) {
setState(WiFiState_e::STA_Connected_Setup, 60000);
}
else {
setState(WiFiState_e::STA_Connected, 100);
}
setState(WiFi_STA_State_e::STA_Connected);
break;
}
if (_state_timeout.timeReached() || (getSTA_connected_state() == STA_connected_state::Idle)) {
if (WiFi_AP_Candidates.hasScanned() && !WiFi_AP_Candidates.hasCandidateCredentials()) {
// We don't have any credentials and we do have some scanned, so we are prepared for setup.
// However we don't need to quickly switch between Disabled and STA_Initializing, thus set to 10 sec.
setState(WiFi_STA_State_e::Disabled, 10000);
break;
}
if (getWiFi_STA_NWPluginData_static_runtime() == nullptr) {
Scheduler.setNetworkInitTimer(0, NETWORK_INDEX_WIFI_STA);
}
if (getWiFi_STA_NWPluginData_static_runtime() != nullptr) {
// This is where we decide what to do next:
// - Reconnect
// - Scan
//
// Do we have candidate to connect to ?
if (WiFi_AP_Candidates.hasCandidates()) {
setState(WiFiState_e::STA_Connecting, WIFI_STATE_MACHINE_STA_CONNECTING_TIMEOUT);
} else if ((WiFi_AP_Candidates.scanComplete() == 0)
|| (WiFi_AP_Candidates.scanComplete() == -3)) {
if (WifiIsAP(WiFi.getMode())) {
// TODO TD-er: Must check if any client is connected.
// If not, then we can disable AP mode and switch to WiFiState_e::STA_Scanning
setState(WiFiState_e::STA_AP_Scanning, WIFI_STATE_MACHINE_STA_AP_SCANNING_TIMEOUT);
} else {
// setState(WiFiState_e::STA_AP_Scanning, WIFI_STATE_MACHINE_STA_AP_SCANNING_TIMEOUT);
setState(WiFiState_e::STA_Scanning, WIFI_STATE_MACHINE_STA_SCANNING_TIMEOUT);
}
// Move up?
} else if (!WiFi_AP_Candidates.hasCandidateCredentials() ||
!Settings.DoNotStartAPfallback_ConnectFail()) {
if (!WiFi_AP_Candidates.hasCandidateCredentials()
// && !WiFiEventData.warnedNoValidWiFiSettings
)
{
// Check for whether No Valid WiFi settings was already logged
static uint32_t lastTimeLoggedNoWiFiCredentials = 0;
if (timePassedSince(lastTimeLoggedNoWiFiCredentials) > 5000) {
addLog(LOG_LEVEL_ERROR, F("WIFI : No valid wifi settings"));
lastTimeLoggedNoWiFiCredentials = millis();
}
// WiFiEventData.warnedNoValidWiFiSettings = true;
}
wifi_STA_data->mark_connect_failed();
wifi_STA_data->_establishConnectStats.clear();
// WiFiEventData.wifiConnectAttemptNeeded = false;
// end move up??
setState(WiFi_STA_State_e::STA_Connecting, WIFI_STATE_MACHINE_STA_CONNECTING_TIMEOUT);
break;
}
// No known candidates, so need to scan first.
if (WifiIsAP(WiFi.getMode())) {
// TODO TD-er: Must check if any client is connected.
// If not, then we can disable AP mode and switch to WiFi_STA_State_e::STA_Scanning
setState(WiFi_STA_State_e::STA_AP_Scanning, WIFI_STATE_MACHINE_STA_AP_SCANNING_TIMEOUT);
break;
}
setState(WiFi_STA_State_e::STA_Scanning, WIFI_STATE_MACHINE_STA_SCANNING_TIMEOUT);
}
break;
case WiFiState_e::STA_Scanning:
case WiFi_STA_State_e::STA_Scanning:
case WiFi_STA_State_e::STA_AP_Scanning:
{
// -1 if scan not finished
auto scanCompleteStatus = WiFi_AP_Candidates.scanComplete();
if (scanCompleteStatus >= 0) {
WiFi_AP_Candidates.load_knownCredentials();
WiFi_AP_Candidates.process_WiFiscan();
# ifndef BUILD_NO_DEBUG
addLog(LOG_LEVEL_INFO, strformat(
F("WiFi : Scan done, found %d APs"),
WiFi_AP_Candidates.scanComplete()));
# endif // ifndef BUILD_NO_DEBUG
} else if (scanCompleteStatus == -2) { // WIFI_SCAN_FAILED
addLog(LOG_LEVEL_ERROR, F("WiFi : Scan failed"));
// WiFi.scanDelete();
setState(WiFiState_e::WiFiOFF, 1000);
}
if (_state_timeout.timeReached() || (scanCompleteStatus >= 0)) {
// WiFi.scanDelete();
if (_state_timeout.timeReached()) {
# ifndef BUILD_NO_DEBUG
addLog(LOG_LEVEL_ERROR, F("WiFi : Scan Running Timeout"));
# endif
}
if (WiFi_AP_Candidates.hasCandidates()) {
setState(WiFiState_e::WiFiOFF, 100);
} else {
// FIXME TD-er: This might not be a responsibility of this state machine....
if (shouldStartAP_fallback()) {
setState(WiFiState_e::AP_Fallback, Settings.APfallback_minimal_on_time_sec() * 1000);
// TODO TD-er: Must keep track of whether the user has forced AP to be autostarted.
} else {
setState(WiFiState_e::WiFiOFF, 1000);
}
}
}
break;
}
case WiFiState_e::STA_AP_Scanning:
{
// -1 if scan not finished
auto scanCompleteStatus = WiFi_AP_Candidates.scanComplete();
if (scanCompleteStatus >= 0) {
WiFi_AP_Candidates.load_knownCredentials();
WiFi_AP_Candidates.process_WiFiscan();
# ifndef BUILD_NO_DEBUG
addLog(LOG_LEVEL_INFO, strformat(
F("WiFi : Scan channel %d done, found %d APs"),
_scan_channel,
WiFi_AP_Candidates.scanComplete()));
# endif // ifndef BUILD_NO_DEBUG
} else if (scanCompleteStatus == -2) { // WIFI_SCAN_FAILED
addLog(LOG_LEVEL_ERROR, F("WiFi : Scan failed"));
// WiFi.scanDelete();
setState(WiFiState_e::WiFiOFF, 1000);
}
if (_state_timeout.timeReached() || (scanCompleteStatus >= 0)) {
// WiFi.scanDelete();
if (_state_timeout.timeReached()) {
# ifndef BUILD_NO_DEBUG
addLog(LOG_LEVEL_ERROR, F("WiFi : Scan Running Timeout"));
# endif
}
++_scan_channel;
if (_scan_channel > 14) {
_scan_channel = 0;
if (!WiFi_AP_Candidates.hasCandidateCredentials() &&
!Settings.DoNotStartAPfallback_ConnectFail()) {
setState(WiFiState_e::AP_only, WIFI_STATE_MACHINE_AP_ONLY_TIMEOUT);
} else {
setState(WiFiState_e::WiFiOFF, 100);
}
}
else {
setState(WiFiState_e::STA_AP_Scanning, 500);
}
}
break;
// Check if scanning is finished
// When scanning per channel, call for scanning next channel
}
case WiFiState_e::STA_Connecting:
case WiFiState_e::STA_Reconnecting:
if (scanCompleteStatus >= 0) {
WiFi_AP_Candidates.load_knownCredentials();
WiFi_AP_Candidates.process_WiFiscan();
# ifndef BUILD_NO_DEBUG
// Check if (re)connecting has finished
{
const STA_connected_state sta_connected_state = getSTA_connected_state();
if (sta_connected_state == STA_connected_state::Connected) {
if (getMode() == ESPEasyWiFi_mode_e::Setup) {
setState(WiFiState_e::STA_Connected_Setup, 60000);
}
else {
setState(WiFiState_e::STA_Connected, 100);
}
} else if (_state_timeout.timeReached()) {
if (_state == WiFiState_e::STA_Connecting) {
setState(WiFiState_e::STA_Reconnecting, WIFI_STATE_MACHINE_STA_CONNECTING_TIMEOUT);
if (_state == WiFi_STA_State_e::STA_Scanning) {
addLog(LOG_LEVEL_INFO, strformat(
F("WiFi : Scan done, found %d APs"),
scanCompleteStatus));
} else {
wifi_STA_data->mark_connect_failed();
setState(WiFiState_e::WiFiOFF);
addLog(LOG_LEVEL_INFO, strformat(
F("WiFi : Scan channel %d done, found %d APs"),
_scan_channel,
scanCompleteStatus));
}
# endif // ifndef BUILD_NO_DEBUG
if (_state == WiFi_STA_State_e::STA_AP_Scanning) {
++_scan_channel;
// TODO TD-er: What to do with 5 GHz WiFi?
if (_scan_channel > 14) {
_scan_channel = 0;
// "Scan Success"
setState(WiFi_STA_State_e::Disabled, 100);
}
else {
setState(WiFi_STA_State_e::STA_AP_Scanning, 500);
}
} else {
// "Scan Success"
setState(WiFi_STA_State_e::Disabled, 100);
}
} else if (scanCompleteStatus == -2) { // WIFI_SCAN_FAILED
addLog(LOG_LEVEL_ERROR, F("WiFi : Scan failed"));
// WiFi.scanDelete();
setState(WiFi_STA_State_e::TimeOut, 1000);
}
break;
}
case WiFi_STA_State_e::STA_Connecting:
case WiFi_STA_State_e::STA_Reconnecting:
{
// Check if (re)connecting has finished
auto wifi_STA_data = getWiFi_STA_NWPluginData_static_runtime();
if (wifi_STA_data) {
wifi_STA_data->processEvents();
}
if (getSTA_connected_state() == STA_connected_state::Connected) {
setState(WiFi_STA_State_e::STA_Connected);
}
break;
}
case WiFiState_e::STA_Connected:
case WiFi_STA_State_e::STA_Connected:
case WiFi_STA_State_e::STA_Connected_Stable:
// Check if still connected
if (getSTA_connected_state() != STA_connected_state::Connected) {
// setState(WiFiState_e::WiFiOFF);
if (WiFi_AP_Candidates.hasCandidates()) {
setState(WiFiState_e::STA_Connecting, WIFI_STATE_MACHINE_STA_CONNECTING_TIMEOUT);
} else {
setState(WiFiState_e::STA_Scanning, WIFI_STATE_MACHINE_STA_SCANNING_TIMEOUT);
// "Disconnect"
auto wifi_STA_data = getWiFi_STA_NWPluginData_static_runtime();
if (wifi_STA_data) {
wifi_STA_data->mark_disconnected();
}
/*
if (Settings.UseRules)
{
eventQueue.addDeDup(F("WiFi#Disconnected"));
}
statusLED(false);
*/
if (WiFi.status() == WL_CONNECTED) {
WiFi.disconnect(true);
}
if (wifi_STA_data) {
wifi_STA_data->processEvents();
}
if (WiFi_AP_Candidates.hasCandidates()) {
setState(WiFi_STA_State_e::STA_Reconnecting, WIFI_STATE_MACHINE_STA_CONNECTING_TIMEOUT);
} else {
setState(WiFi_STA_State_e::TimeOut, 100);
}
} else {
// Else mark last timestamp seen as connected
_last_seen_connected.setNow();
# if FEATURE_SET_WIFI_TX_PWR
SetWiFiTXpower();
# endif
@@ -334,43 +266,15 @@ bool ESPEasyWiFi_t::connected() const
void ESPEasyWiFi_t::disconnect() { doWiFiDisconnect(); }
void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
void ESPEasyWiFi_t::setState(WiFi_STA_State_e newState, uint32_t timeout) {
if (newState == _state) { return; }
//# ifndef BUILD_NO_DEBUG
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
addLog(
LOG_LEVEL_INFO,
concat(F("WiFi : Set state from: "), toString(_state)) +
concat(F(" to: "), toString(newState)) +
concat(F(" timeout: "), timeout));
}
//# endif // ifndef BUILD_NO_DEBUG
const WiFi_STA_State_e oldState = _state;
if ((_state == WiFiState_e::AP_only) ||
(_state == WiFiState_e::AP_Fallback)) {
Scheduler.setNetworkExitTimer(0, NETWORK_INDEX_WIFI_AP);
// setAP(false);
}
// Need to set the newState first as some of the functions below will call
// setState, causing a loop, or calling to change state multiple times.
if (_state == WiFiState_e::STA_Connected)
{
auto wifi_STA_data = getWiFi_STA_NWPluginData_static_runtime();
if (wifi_STA_data) {
wifi_STA_data->mark_disconnected();
if (WiFi.status() == WL_CONNECTED) {
WiFi.disconnect(true);
}
}
}
if ((_state == WiFiState_e::STA_AP_Scanning) ||
(_state == WiFiState_e::STA_Scanning))
{
WiFi_AP_Candidates.process_WiFiscan();
}
auto wifi_STA_data = getWiFi_STA_NWPluginData_static_runtime();
if (timeout == 0)
{
@@ -383,37 +287,94 @@ void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
_last_state_change.setNow();
_state = newState;
// # ifndef BUILD_NO_DEBUG
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
addLog(
LOG_LEVEL_INFO,
concat(F("WiFi : Set state from: "), toString(oldState)) +
concat(F(" to: "), toString(newState)) +
concat(F(" timeout: "), timeout));
}
// # endif // ifndef BUILD_NO_DEBUG
if ((oldState == WiFi_STA_State_e::STA_AP_Scanning) ||
(oldState == WiFi_STA_State_e::STA_Scanning))
{
WiFi_AP_Candidates.load_knownCredentials();
WiFi_AP_Candidates.process_WiFiscan();
}
// Make sure not to call setState from this function
// This may cause quite a lot of recursive calls.
switch (newState)
{
case WiFiState_e::Disabled:
// Do nothing here, as the device is disabled.
case WiFi_STA_State_e::Disabled:
// TODO TD-er: Maybe call scheduler?
// if (WifiIsSTA(WiFi.getMode()))
// Scheduler.setNetworkExitTimer(0, NETWORK_INDEX_WIFI_STA);
WifiDisconnect();
setSTA(false);
break;
case WiFiState_e::WiFiOFF:
// TODO TD-er: Must cancel all and turn off WiFi.
setSTA_AP(false, false);
case WiFi_STA_State_e::TimeOut:
{
// From a failed state we always turn off at least WiFi STA.
// Only when we end up here from STA_Initializing, we also need to turn off AP.
if (oldState == WiFi_STA_State_e::STA_Initializing) {
// "Init STA Fail"
// TODO TD-er: Maybe call scheduler?
// if (WifiIsAP(WiFi.getMode()))
// Scheduler.setNetworkExitTimer(0, NETWORK_INDEX_WIFI_AP);
setAP(false);
} else if (oldState == WiFi_STA_State_e::STA_Connecting) {
// "Connect Fail"
if (wifi_STA_data) {
wifi_STA_data->mark_connect_failed();
}
// setState(WiFi_STA_State_e::STA_Reconnecting, WIFI_STATE_MACHINE_STA_CONNECTING_TIMEOUT);
} else if (oldState == WiFi_STA_State_e::STA_Reconnecting) {
// "Reconnect Fail"
if (wifi_STA_data) {
wifi_STA_data->mark_connect_failed();
}
} else if (oldState == WiFi_STA_State_e::STA_Initializing) {
// "Init STA Fail"
} else if ((oldState == WiFi_STA_State_e::STA_Scanning) ||
(oldState == WiFi_STA_State_e::STA_AP_Scanning)) {
// "Scan Fail"
}
// TODO TD-er: Handle "Scan Fail" and "Init STA Fail"
// For "Scan Fail" set state to Disabled, with some timeout?
// Do we also need to turn off WiFi STA after successful scan?
break;
case WiFiState_e::AP_only:
case WiFiState_e::AP_Fallback:
Scheduler.setNetworkInitTimer(0, NETWORK_INDEX_WIFI_AP);
}
case WiFi_STA_State_e::STA_Initializing:
/*
if (getWiFi_STA_NWPluginData_static_runtime() == nullptr) {
Scheduler.setNetworkInitTimer(0, NETWORK_INDEX_WIFI_STA);
}
_state_timeout.setMillisFromNow(Settings.getNetworkInterfaceStartupDelay(NETWORK_INDEX_WIFI_STA) + 100);
*/
break;
case WiFiState_e::IdleWaiting:
// Do nothing here as we're waiting till the timeout is over
break;
case WiFiState_e::STA_AP_Scanning:
case WiFi_STA_State_e::STA_AP_Scanning:
// Start scanning per channel
if (_scan_channel == 0) { _scan_channel = 1; }
// break;
case WiFiState_e::STA_Scanning:
// fall through
case WiFi_STA_State_e::STA_Scanning:
// Start scanning
startScanning();
break;
case WiFiState_e::STA_Connecting:
case WiFiState_e::STA_Reconnecting:
case WiFi_STA_State_e::STA_Connecting:
case WiFi_STA_State_e::STA_Reconnecting:
// Start connecting
++_connect_attempt;
@@ -421,28 +382,12 @@ void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
if (!connectSTA()) {
// TODO TD-er: Must keep track of failed attempts and start AP when either no credentials present or nr. of attempts failed > some
// threshold.
if (!WiFi_AP_Candidates.hasCandidates()) {
setState(WiFiState_e::STA_Scanning, WIFI_STATE_MACHINE_STA_CONNECTING_TIMEOUT);
} else {
setState(WiFiState_e::IdleWaiting, 100);
}
addLog(LOG_LEVEL_ERROR, F("WiFi : Connect STA failed"));
setState(WiFi_STA_State_e::TimeOut, 100);
}
break;
case WiFiState_e::STA_Connected_Setup:
{
Scheduler.setNetworkInitTimer(0, NETWORK_INDEX_WIFI_AP);
_last_seen_connected.setNow();
auto wifi_STA_data = getWiFi_STA_NWPluginData_static_runtime();
if (wifi_STA_data) {
wifi_STA_data->mark_connected();
}
break;
}
case WiFiState_e::STA_Connected:
case WiFi_STA_State_e::STA_Connected:
{
# ifdef ESP32
@@ -450,20 +395,14 @@ void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
// WiFi.STA.setDefault();
# endif // ifdef ESP32
if (_state == WiFiState_e::STA_Connected_Setup) {
Scheduler.setNetworkExitTimer(0, NETWORK_INDEX_WIFI_AP);
setMode(ESPEasyWiFi_mode_e::STA_only);
}
_connect_attempt = 0;
_last_seen_connected.setNow();
_state_timeout.clear();
auto wifi_STA_data = getWiFi_STA_NWPluginData_static_runtime();
_state_timeout.setMillisFromNow(WIFI_STATE_MACHINE_STA_CONNECTED_STABLE);
if (wifi_STA_data) {
wifi_STA_data->mark_connected();
}
/*
if (Settings.UseRules)
{
@@ -472,11 +411,14 @@ void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
statusLED(true);
*/
break;
}
case WiFi_STA_State_e::STA_Connected_Stable:
_state_timeout.clear();
// TODO TD-er: Must mark connection as stable
break;
}
auto wifi_STA_data = getWiFi_STA_NWPluginData_static_runtime();
if (wifi_STA_data) {
wifi_STA_data->processEvents();
@@ -487,7 +429,7 @@ void ESPEasyWiFi_t::checkConnectProgress() {}
void ESPEasyWiFi_t::startScanning()
{
_state = _scan_channel == 0 ? WiFiState_e::STA_Scanning : WiFiState_e::STA_AP_Scanning;
_state = _scan_channel == 0 ? WiFi_STA_State_e::STA_Scanning : WiFi_STA_State_e::STA_AP_Scanning;
setSTA(true);
WifiScan(true, _scan_channel);
_last_state_change.setNow();
@@ -668,8 +610,13 @@ bool ESPEasyWiFi_t::shouldStartAP_fallback() const
bool ESPEasyWiFi_t::shouldRedirectTo_setup() const
{
if (!Settings.ApCaptivePortal()) return false;
if (Settings.StartAPfallback_NoCredentials() && !SecuritySettings.hasWiFiCredentials()) {
if (!Settings.ApCaptivePortal()) { return false; }
if (Settings.StartAPfallback_NoCredentials()
&& !WiFi_AP_Candidates.hasCandidateCredentials()
// && !SecuritySettings.hasWiFiCredentials()
) {
return true;
}
@@ -7,7 +7,7 @@
# include "../../../src/Helpers/LongTermTimer.h"
# include "../wifi/WiFi_STA_connected_state.h"
# include "../wifi/WiFi_State.h"
# include "../wifi/WiFi_STA_State.h"
# include <IPAddress.h>
@@ -63,7 +63,7 @@ public:
// Process the state machine for managing WiFi connection
void loop();
WiFiState_e getState() const
WiFi_STA_State_e getState() const
{
return _state;
}
@@ -80,7 +80,7 @@ public:
private:
void setState(WiFiState_e newState,
void setState(WiFi_STA_State_e newState,
uint32_t timeout = 0);
// Handle timeouts + start of AP mode
@@ -110,7 +110,7 @@ private:
// String _last_ssid;
// MAC_address _last_bssid;
// uint8_t _last_channel = 0;
WiFiState_e _state = WiFiState_e::Disabled;
WiFi_STA_State_e _state = WiFi_STA_State_e::Disabled;
ESPEasyWiFi_mode_e _mode = ESPEasyWiFi_mode_e::Off;
@@ -0,0 +1,56 @@
StateDiagram [frame=true framecolor=steelblue label="State Diagram ESPEasy WiFi_STA_State_e"] {
state Disabled
state TimeOut
state begin
state WiFiOFF
state AP_only
state AP_Fallback
state IdleWaiting
state STA_Scanning
state STA_AP_Scanning
state STA_Connecting
state STA_Reconnecting
state STA_Connected
state STA_Connected_Setup
choice bConn
choice bCand
choice bScan
choice bAPmode
choice timeoutSetupMode
initialState->WiFiOFF
TimeOut -> timeoutSetupMode "Setup"
timeoutSetupMode -> IdleWaiting "!connected"
timeoutSetupMode -> WiFiOFF "!Setup"
WiFiOFF -> begin
begin -> bConn
bConn -> STA_Connected "connected"
bConn -> bCand "!connected"
bCand -> IdleWaiting "hasCandidates"
bCand -> bScan "!hasCandidates"
bScan -> AP_only "scanned"
bScan -> bAPmode "!scanned"
bAPmode -> STA_AP_Scanning "APmode"
bAPmode -> STA_Scanning "!APmode"
AP_only -> IdleWaiting "!APactiveUsed & (hasCandidates || timeout)"
AP_Fallback -> IdleWaiting "!APactiveUsed & (hasCandidates || timeout)"
IdleWaiting -> STA_Connected_Setup "connected() && mode==setup"
IdleWaiting -> STA_Connected "connected() && mode!=setup"
IdleWaiting -> STA_Connecting "timeout & hasCandidates"
IdleWaiting -> STA_AP_Scanning "timeout & !hasCandidates & scanfail & APmode"
IdleWaiting -> STA_Scanning "timeout & !hasCandidates & scanfail & !APmode"
STA_Scanning -> WiFiOFF "scanfail || scansuccess || !startAP_fallback"
STA_Scanning -> AP_Fallback "scanfail & startAP_fallback"
STA_AP_Scanning -> WiFiOFF "scanfail || scansuccess || !startAP_fallback"
STA_AP_Scanning -> AP_Fallback "scanfail & startAP_fallback"
STA_AP_Scanning -> AP_only "scanfail & !startAP_fallback"
STA_AP_Scanning -> STA_AP_Scanning "scan next channel"
STA_Connecting -> STA_Connected_Setup "connected & SetupMode"
STA_Connecting -> STA_Connected "connected & !SetupMode"
STA_Connecting -> STA_Reconnecting "!connected & timeout"
STA_Reconnecting -> IdleWaiting "!connected & timeout"
STA_Reconnecting -> STA_Connected_Setup "connected & SetupMode"
STA_Reconnecting -> STA_Connected "connected & !SetupMode"
STA_Connected -> STA_Connecting "!connected & hasCandidates"
STA_Connected -> STA_Scanning "!connected & !hasCandidates"
STA_Connected -> STA_Connected "connected + setTXpwr"
}
+3 -1
View File
@@ -21,7 +21,9 @@
# define SOFTAP_STATION_COUNT WiFi.AP.stationCount()
# endif
# ifdef ESP8266
# define SOFTAP_STATION_COUNT WiFi.softAPgetStationNum()
//# define SOFTAP_STATION_COUNT WiFi.softAPgetStationNum()
# define SOFTAP_STATION_COUNT wifi_softap_get_station_num()
# endif
+31
View File
@@ -0,0 +1,31 @@
#include "../wifi/WiFi_STA_State.h"
#if FEATURE_WIFI
namespace ESPEasy {
namespace net {
namespace wifi {
const __FlashStringHelper* toString(WiFi_STA_State_e state)
{
switch (state)
{
case ESPEasy::net::wifi::WiFi_STA_State_e::Disabled: return F("Disabled");
case ESPEasy::net::wifi::WiFi_STA_State_e::TimeOut: return F("TimeOut");
case ESPEasy::net::wifi::WiFi_STA_State_e::STA_Initializing: return F("STA_Initializing");
case ESPEasy::net::wifi::WiFi_STA_State_e::STA_Scanning: return F("STA_Scanning");
case ESPEasy::net::wifi::WiFi_STA_State_e::STA_AP_Scanning: return F("STA_AP_Scanning");
case ESPEasy::net::wifi::WiFi_STA_State_e::STA_Connecting: return F("STA_Connecting");
case ESPEasy::net::wifi::WiFi_STA_State_e::STA_Reconnecting: return F("STA_Reconnecting");
case ESPEasy::net::wifi::WiFi_STA_State_e::STA_Connected: return F("STA_Connected");
case ESPEasy::net::wifi::WiFi_STA_State_e::STA_Connected_Stable: return F("STA_Conn_Stable");
}
return F("");
}
} // namespace wifi
} // namespace net
} // namespace ESPEasy
#endif // if FEATURE_WIFI
@@ -52,24 +52,18 @@ namespace wifi {
*/
enum class WiFiState_e
enum class WiFi_STA_State_e
{
// WiFi radio is off and no new attempt should be made (e.g. low power mode or Ethernet active)
// WiFi STA radio is off.
// When timeout is set to 0, no new attempt should be made (e.g. low power mode or Ethernet active)
// Will only change to STA_Initializing when WiFi is allowed/required to start
Disabled,
// WiFi radio off, to continue, everything needs to be (re)initialized
WiFiOFF,
// Error state, some action failed
TimeOut,
// Only running in AP mode
// Typically this is only used when STA is off and AP Auto Start is checked
// TODO TD-er: Must implement this.
AP_only,
// Fallback mode which is started when connecting to AP was not possible
AP_Fallback,
// WiFi was in some kind of error state or needs waiting period
IdleWaiting,
// State from where we decide to start scanning or connecting
STA_Initializing,
// STA mode + scanning
STA_Scanning,
@@ -87,12 +81,10 @@ enum class WiFiState_e
// Connected to an AP
STA_Connected,
STA_Connected_Setup
STA_Connected_Stable
};
const __FlashStringHelper* toString(WiFiState_e state);
const __FlashStringHelper* toString(WiFi_STA_State_e state);
} // namespace wifi
-33
View File
@@ -1,33 +0,0 @@
#include "../wifi/WiFi_State.h"
#if FEATURE_WIFI
namespace ESPEasy {
namespace net {
namespace wifi {
const __FlashStringHelper* toString(WiFiState_e state)
{
switch (state)
{
case ESPEasy::net::wifi::WiFiState_e::Disabled: return F("Disabled");
case ESPEasy::net::wifi::WiFiState_e::WiFiOFF: return F("OFF");
case ESPEasy::net::wifi::WiFiState_e::AP_only: return F("AP_only");
case ESPEasy::net::wifi::WiFiState_e::AP_Fallback: return F("AP_Fallback");
case ESPEasy::net::wifi::WiFiState_e::IdleWaiting: return F("IdleWaiting");
case ESPEasy::net::wifi::WiFiState_e::STA_Scanning: return F("STA_Scanning");
case ESPEasy::net::wifi::WiFiState_e::STA_AP_Scanning: return F("STA_AP_Scanning");
case ESPEasy::net::wifi::WiFiState_e::STA_Connecting: return F("STA_Connecting");
case ESPEasy::net::wifi::WiFiState_e::STA_Reconnecting: return F("STA_Reconnecting");
case ESPEasy::net::wifi::WiFiState_e::STA_Connected: return F("STA_Connected");
case ESPEasy::net::wifi::WiFiState_e::STA_Connected_Setup: return F("STA_Connected_Setup");
}
return F("");
}
} // namespace wifi
} // namespace net
} // namespace ESPEasy
#endif // if FEATURE_WIFI
+3
View File
@@ -236,6 +236,9 @@ bool set_Gpio_PWM(int gpio, uint32_t dutyCycle, uint32_t fadeDuration_ms, uint32
#if ESP_IDF_VERSION_MAJOR >= 5
// FIXME TD-er: For now fade is disabled. See: https://github.com/espressif/arduino-esp32/issues/12709
fadeDuration_ms = 0;
if (fadeDuration_ms == 0)
{
analogWriteESP32(gpio, dutyCycle, frequency);
+12 -7
View File
@@ -1506,7 +1506,7 @@ String getDigestAuth(const String& authReq,
md5.toString().c_str()); // response
}
# ifndef BUILD_NO_DEBUG
# if !defined(BUILD_NO_DEBUG) || defined(ESP32)
void log_http_result(const ESPEasy_HTTPClient& http,
const String & logIdentifier,
@@ -1617,7 +1617,7 @@ int http_authenticate(const String& logIdentifier,
http.setRedirectLimit(2);
}
# if FEATURE_TLS
http.setTimeout(timeout);
http.setConnectTimeout(10000);
#else
# ifdef MUSTFIX_CLIENT_TIMEOUT_IN_SECONDS
@@ -1643,6 +1643,9 @@ int http_authenticate(const String& logIdentifier,
# if defined(CORE_POST_2_6_0) || defined(ESP32)
# if FEATURE_TLS
const String fullURL = joinURL(user, pass, host, port, uri, protocol);
#ifndef LIMIT_BUILD_SIZE
addLog(LOG_LEVEL_INFO, concat(F("SendToHTTP full URL: "), fullURL));
#endif
if (fullURL.startsWith(F("https")))
http.begin(fullURL, nullptr); // HTTPS
else
@@ -1676,12 +1679,14 @@ int http_authenticate(const String& logIdentifier,
// }
}
}
String tmp = HttpMethod;
const char* httpMethod_cstr = &tmp[0];
// start connection and send HTTP header (and body)
if (equals(HttpMethod, F("HEAD")) || equals(HttpMethod, F("GET"))) {
httpCode = http.sendRequest(HttpMethod.c_str());
httpCode = http.sendRequest(httpMethod_cstr);
} else {
httpCode = http.sendRequest(HttpMethod.c_str(), postStr);
httpCode = http.sendRequest(httpMethod_cstr, postStr);
}
// Check to see if we need to try digest auth
@@ -1723,9 +1728,9 @@ int http_authenticate(const String& logIdentifier,
// start connection and send HTTP header (and body)
if (equals(HttpMethod, F("HEAD")) || equals(HttpMethod, F("GET"))) {
httpCode = http.sendRequest(HttpMethod.c_str());
httpCode = http.sendRequest(httpMethod_cstr);
} else {
httpCode = http.sendRequest(HttpMethod.c_str(), postStr);
httpCode = http.sendRequest(httpMethod_cstr, postStr);
}
}
}
@@ -1750,7 +1755,7 @@ int http_authenticate(const String& logIdentifier,
}
// -----------------------------------------------------------
# ifndef BUILD_NO_DEBUG
# if !defined(BUILD_NO_DEBUG) || defined(ESP32)
log_http_result(http, logIdentifier, host + ':' + port, HttpMethod, httpCode, EMPTY_STRING);
# endif
return httpCode;
+1 -1
View File
@@ -38,7 +38,7 @@
#include "../../ESPEasy/net/Globals/ESPEasyWiFiEvent.h"
#include "../../ESPEasy/net/Globals/NetworkState.h"
#include "../../ESPEasy/net/Globals/NWPlugins.h"
#include "../../ESPEasy/net/wifi/WiFi_State.h"
#include "../../ESPEasy/net/wifi/WiFi_STA_State.h"
#ifdef USES_C015
+28 -12
View File
@@ -703,15 +703,19 @@ bool getCheckWebserverArg_int(const String& key,
}
bool update_whenset_FormItemInt(const __FlashStringHelper * key,
int & value)
int & value,
bool* changed)
{
return update_whenset_FormItemInt(String(key), value);
return update_whenset_FormItemInt(String(key), value, changed);
}
bool update_whenset_FormItemInt(const String& key, int& value) {
bool update_whenset_FormItemInt(const String& key, int& value,
bool* changed) {
int tmpVal;
if (getCheckWebserverArg_int(key, tmpVal)) {
if (changed != nullptr && value != tmpVal)
*changed = true;
value = tmpVal;
return true;
}
@@ -719,17 +723,21 @@ bool update_whenset_FormItemInt(const String& key, int& value) {
}
bool update_whenset_FormItemInt(const __FlashStringHelper * key,
uint32_t & value)
uint32_t & value,
bool* changed)
{
return update_whenset_FormItemInt(String(key), value);
return update_whenset_FormItemInt(String(key), value, changed);
}
bool update_whenset_FormItemInt(const String& key,
uint32_t & value)
uint32_t & value,
bool* changed)
{
uint32_t tmpVal;
if (getCheckWebserverArg_int(key, tmpVal)) {
if (changed != nullptr && value != tmpVal)
*changed = true;
value = tmpVal;
return true;
}
@@ -738,16 +746,20 @@ bool update_whenset_FormItemInt(const String& key,
bool update_whenset_FormItemInt(const __FlashStringHelper * key,
int8_t& value)
int8_t& value,
bool* changed)
{
return update_whenset_FormItemInt(String(key), value);
return update_whenset_FormItemInt(String(key), value, changed);
}
bool update_whenset_FormItemInt(const String& key, int8_t& value) {
bool update_whenset_FormItemInt(const String& key, int8_t& value,
bool* changed) {
int tmpVal;
if (getCheckWebserverArg_int(key, tmpVal)) {
if (changed != nullptr && value != tmpVal)
*changed = true;
value = tmpVal;
return true;
}
@@ -755,16 +767,20 @@ bool update_whenset_FormItemInt(const String& key, int8_t& value) {
}
bool update_whenset_FormItemInt(const __FlashStringHelper * key,
uint8_t& value)
uint8_t& value,
bool* changed)
{
return update_whenset_FormItemInt(String(key), value);
return update_whenset_FormItemInt(String(key), value, changed);
}
bool update_whenset_FormItemInt(const String& key, uint8_t& value) {
bool update_whenset_FormItemInt(const String& key, uint8_t& value,
bool* changed) {
int tmpVal;
if (getCheckWebserverArg_int(key, tmpVal)) {
if (changed != nullptr && value != tmpVal)
*changed = true;
value = tmpVal;
return true;
}
+16 -8
View File
@@ -330,28 +330,36 @@ bool getCheckWebserverArg_int(const String& key,
uint32_t & value);
bool update_whenset_FormItemInt(const __FlashStringHelper * key,
int & value);
int & value,
bool* changed = nullptr);
bool update_whenset_FormItemInt(const String& key,
int & value);
int & value,
bool* changed = nullptr);
bool update_whenset_FormItemInt(const __FlashStringHelper * key,
uint32_t & value);
uint32_t & value,
bool* changed = nullptr);
bool update_whenset_FormItemInt(const String& key,
uint32_t & value);
uint32_t & value,
bool* changed = nullptr);
bool update_whenset_FormItemInt(const __FlashStringHelper * key,
int8_t & value);
int8_t & value,
bool* changed = nullptr);
bool update_whenset_FormItemInt(const String& key,
int8_t & value);
int8_t & value,
bool* changed = nullptr);
bool update_whenset_FormItemInt(const __FlashStringHelper * key,
uint8_t & value);
uint8_t & value,
bool* changed = nullptr);
bool update_whenset_FormItemInt(const String& key,
uint8_t & value);
uint8_t & value,
bool* changed = nullptr);
// Note: Checkbox values will not appear in POST Form data if unchecked.
// So if webserver does not have an argument for a checkbox form, it means it should be considered unchecked.