mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-27 19:57:38 +00:00
[WiFi] Simplify state machine for WiFi STA
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
StateDiagram [frame=true framecolor=steelblue label="State Diagram ESPEasy WiFi_STA_State_e"] {
|
||||
state Disabled
|
||||
state TimeOut
|
||||
state Idle
|
||||
state IdleWaiting
|
||||
state STA_Scanning
|
||||
state STA_AP_Scanning
|
||||
state STA_Connecting
|
||||
state STA_Reconnecting
|
||||
state STA_Connected
|
||||
|
||||
choice AlreadyConnected
|
||||
choice AP_on_no_nw_found
|
||||
choice KnownAPfound
|
||||
choice KnownAPonDisconnect
|
||||
|
||||
choice ExitSTA
|
||||
|
||||
initialState->Disabled
|
||||
|
||||
|
||||
Disabled -> IdleWaiting "Init STA"
|
||||
Disabled <- ExitSTA "Exit STA"
|
||||
IdleWaiting -> AlreadyConnected "Already\nConnected?"
|
||||
AlreadyConnected -> STA_Connected "Connected"
|
||||
AlreadyConnected -> Idle "Ready"
|
||||
Idle -> 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"
|
||||
|
||||
STA_Connecting -> STA_Connected
|
||||
STA_Reconnecting -> STA_Connected
|
||||
KnownAPonDisconnect -> STA_Reconnecting "No Scan\nNeeded"
|
||||
KnownAPonDisconnect <- STA_Connected "Disconnect"
|
||||
IdleWaiting <- KnownAPonDisconnect "Scan\nNeeded"
|
||||
|
||||
|
||||
IdleWaiting <- STA_Scanning "Scan\nDone"
|
||||
IdleWaiting <- STA_AP_Scanning "Scan\nDone"
|
||||
|
||||
STA_AP_Scanning <- STA_AP_Scanning "Next\nChannel"
|
||||
|
||||
TimeOut <- STA_Scanning "Scan\nFail"
|
||||
TimeOut <- STA_AP_Scanning "Scan\nFail"
|
||||
TimeOut <- STA_Connecting "Connect\nFail"
|
||||
|
||||
TimeOut -> IdleWaiting
|
||||
|
||||
IdleWaiting <- IdleWaiting "Wait for\nStartup Delay/\nSetup"
|
||||
|
||||
TimeOut <- STA_Reconnecting "Reconnect\nFail"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
StateDiagram [frame=true framecolor=steelblue label="State Diagram ESPEasyWiFi_mode_e"] {
|
||||
state Off
|
||||
state CredentialsUpdated
|
||||
state STA_only
|
||||
state STA_AP
|
||||
state AP_only
|
||||
state Setup
|
||||
|
||||
choice AllowSetup
|
||||
choice HasCredentials
|
||||
choice HasCredentialsSetupAllowed
|
||||
choice APalwaysOn
|
||||
choice APalwaysOnNoCred
|
||||
|
||||
|
||||
|
||||
initialState->Off
|
||||
Off -> AllowSetup "Check\nAllowSetup"
|
||||
AllowSetup -> HasCredentials "Setup not\nAllowed"
|
||||
HasCredentials -> APalwaysOn "Has\nCredentials"
|
||||
APalwaysOn -> STA_AP "AP"
|
||||
APalwaysOn -> STA_only "No AP"
|
||||
HasCredentials -> APalwaysOnNoCred "No\nCredentials"
|
||||
APalwaysOnNoCred -> Off "No AP"
|
||||
APalwaysOnNoCred -> AP_only "AP"
|
||||
AllowSetup -> HasCredentialsSetupAllowed "Setup\nAllowed"
|
||||
HasCredentialsSetupAllowed -> Setup "No\nCredentials"
|
||||
HasCredentialsSetupAllowed -> APalwaysOn "Has\nCredentials"
|
||||
|
||||
CredentialsUpdated <- Setup "Setup\nDone"
|
||||
CredentialsUpdated -> AllowSetup
|
||||
|
||||
STA_AP -> AP_only "No Known\nNetwork found"
|
||||
|
||||
STA_AP <- STA_AP "Retry/\nReconnect"
|
||||
STA_only <- STA_only "Retry/\nReconnect"
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -27,6 +27,9 @@ namespace wifi {
|
||||
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,28 +46,13 @@ 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, 100); }
|
||||
|
||||
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, 0);
|
||||
} 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::IdleWaiting, 100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,245 +63,118 @@ void ESPEasyWiFi_t::loop()
|
||||
|
||||
if (!wifi_STA_data) { return; }
|
||||
|
||||
if (_state != WiFiState_e::IdleWaiting) {
|
||||
if ((_state != WiFi_STA_State_e::IdleWaiting) &&
|
||||
(_state != WiFi_STA_State_e::TimeOut)) {
|
||||
if (_callbackError ||
|
||||
(_state_timeout.isSet() && _state_timeout.timeReached()))
|
||||
{
|
||||
// TODO TD-er: Must check what error was given???
|
||||
_callbackError = false;
|
||||
|
||||
if (getMode() == ESPEasyWiFi_mode_e::Setup /* && _state == WiFiState_e::AP_Fallback */) {
|
||||
|
||||
setState(_state == WiFiState_e::STA_Connected_Setup ? WiFiState_e::STA_Connected : WiFiState_e::IdleWaiting);
|
||||
} else {
|
||||
setState(WiFiState_e::WiFiOFF, 100);
|
||||
}
|
||||
// TODO TD-er: Must perhaps check what action was pending and act on it?
|
||||
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:
|
||||
// TODO TD-er: Not sure yet what else to do here.
|
||||
setState(WiFi_STA_State_e::IdleWaiting, 100);
|
||||
break;
|
||||
case WiFiState_e::AP_only:
|
||||
case WiFiState_e::AP_Fallback:
|
||||
case WiFi_STA_State_e::IdleWaiting:
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
// TODO TD-er: Must check whether we are allowed to continue
|
||||
|
||||
setState(WiFi_STA_State_e::Idle, 100);
|
||||
break;
|
||||
case WiFiState_e::IdleWaiting:
|
||||
|
||||
if (connected()) {
|
||||
if (getMode() == ESPEasyWiFi_mode_e::Setup) {
|
||||
setState(WiFiState_e::STA_Connected_Setup, 60000);
|
||||
}
|
||||
else {
|
||||
setState(WiFiState_e::STA_Connected, 100);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (_state_timeout.timeReached() || (getSTA_connected_state() == STA_connected_state::Idle)) {
|
||||
// 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??
|
||||
}
|
||||
}
|
||||
case WiFi_STA_State_e::Idle:
|
||||
// All done when setState was called
|
||||
// Just a placeholder in the loop()
|
||||
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()) {
|
||||
if (shouldStartAP_fallback()) {
|
||||
setState(WiFiState_e::AP_Fallback, Settings.APfallback_minimal_on_time_sec() * 1000);
|
||||
} else {
|
||||
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
|
||||
if (scanCompleteStatus >= 0) {
|
||||
WiFi_AP_Candidates.load_knownCredentials();
|
||||
WiFi_AP_Candidates.process_WiFiscan();
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (_state == WiFi_STA_State_e::STA_Scanning) {
|
||||
addLog(LOG_LEVEL_INFO, strformat(
|
||||
F("WiFi : Scan done, found %d APs"),
|
||||
scanCompleteStatus));
|
||||
} else {
|
||||
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;
|
||||
|
||||
if (_scan_channel > 14) {
|
||||
_scan_channel = 0;
|
||||
setState(WiFi_STA_State_e::IdleWaiting, 100);
|
||||
}
|
||||
else {
|
||||
setState(WiFi_STA_State_e::STA_AP_Scanning, 500);
|
||||
}
|
||||
} else {
|
||||
setState(WiFi_STA_State_e::IdleWaiting, 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 WiFiState_e::STA_Connecting:
|
||||
case WiFiState_e::STA_Reconnecting:
|
||||
case WiFi_STA_State_e::STA_Connecting:
|
||||
case WiFi_STA_State_e::STA_Reconnecting:
|
||||
|
||||
// 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);
|
||||
} else {
|
||||
wifi_STA_data->mark_connect_failed();
|
||||
setState(WiFiState_e::WiFiOFF, 100);
|
||||
}
|
||||
setState(WiFi_STA_State_e::STA_Connected, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WiFiState_e::STA_Connected:
|
||||
case WiFi_STA_State_e::STA_Connected:
|
||||
|
||||
// Check if still connected
|
||||
if (getSTA_connected_state() != STA_connected_state::Connected) {
|
||||
// setState(WiFiState_e::WiFiOFF);
|
||||
|
||||
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 (WiFi_AP_Candidates.hasCandidates()) {
|
||||
setState(WiFiState_e::STA_Connecting, WIFI_STATE_MACHINE_STA_CONNECTING_TIMEOUT);
|
||||
setState(WiFi_STA_State_e::STA_Reconnecting, WIFI_STATE_MACHINE_STA_CONNECTING_TIMEOUT);
|
||||
} else {
|
||||
setState(WiFiState_e::STA_Scanning, WIFI_STATE_MACHINE_STA_SCANNING_TIMEOUT);
|
||||
setState(WiFi_STA_State_e::IdleWaiting, 100);
|
||||
}
|
||||
|
||||
/*
|
||||
if (Settings.UseRules)
|
||||
{
|
||||
eventQueue.addDeDup(F("WiFi#Disconnected"));
|
||||
}
|
||||
statusLED(false);
|
||||
*/
|
||||
|
||||
} else {
|
||||
// Else mark last timestamp seen as connected
|
||||
_last_seen_connected.setNow();
|
||||
@@ -338,23 +199,12 @@ 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;
|
||||
|
||||
|
||||
const WiFiState_e oldState = _state;
|
||||
|
||||
// Need to set the newState first as some of the functions below will call
|
||||
// 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.
|
||||
|
||||
|
||||
@@ -369,73 +219,100 @@ void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
|
||||
_last_state_change.setNow();
|
||||
_state = newState;
|
||||
|
||||
// # ifndef BUILD_NO_DEBUG
|
||||
|
||||
|
||||
if (oldState == 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 (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));
|
||||
}
|
||||
|
||||
if ((oldState == WiFiState_e::STA_AP_Scanning) ||
|
||||
(oldState == WiFiState_e::STA_Scanning))
|
||||
// # endif // ifndef BUILD_NO_DEBUG
|
||||
|
||||
|
||||
if (oldState == WiFi_STA_State_e::STA_Connected)
|
||||
{}
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
if ((oldState == WiFiState_e::AP_only) ||
|
||||
(oldState == WiFiState_e::AP_Fallback)) {
|
||||
Scheduler.setNetworkExitTimer(0, NETWORK_INDEX_WIFI_AP);
|
||||
// setAP(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
switch (newState)
|
||||
{
|
||||
case WiFiState_e::Disabled:
|
||||
case WiFi_STA_State_e::Disabled:
|
||||
// Do nothing here, as the device is disabled.
|
||||
|
||||
// TODO TD-er: Maybe call scheduler?
|
||||
// if (doWifiIsSTA(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.
|
||||
|
||||
if (doWifiIsAP(WiFi.getMode()))
|
||||
Scheduler.setNetworkExitTimer(0, NETWORK_INDEX_WIFI_AP);
|
||||
/*
|
||||
if (doWifiIsSTA(WiFi.getMode()))
|
||||
Scheduler.setNetworkExitTimer(0, NETWORK_INDEX_WIFI_STA);
|
||||
*/
|
||||
setSTA_AP(false, false);
|
||||
break;
|
||||
case WiFiState_e::AP_only:
|
||||
case WiFiState_e::AP_Fallback:
|
||||
Scheduler.setNetworkInitTimer(0, NETWORK_INDEX_WIFI_AP);
|
||||
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::TimeOut:
|
||||
{
|
||||
auto wifi_STA_data = getWiFi_STA_NWPluginData_static_runtime();
|
||||
|
||||
if (oldState == WiFi_STA_State_e::STA_Connecting) {
|
||||
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) {
|
||||
if (wifi_STA_data) {
|
||||
wifi_STA_data->mark_connect_failed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setState(WiFi_STA_State_e::IdleWaiting, 100);
|
||||
break;
|
||||
}
|
||||
case WiFi_STA_State_e::IdleWaiting:
|
||||
if (connected()) {
|
||||
setState(WiFi_STA_State_e::STA_Connected);
|
||||
}
|
||||
// Nothing else to do here as we're waiting till the timeout is over
|
||||
break;
|
||||
case WiFi_STA_State_e::Idle:
|
||||
if (!doWifiIsSTA(WiFi.getMode()))
|
||||
Scheduler.setNetworkInitTimer(0, NETWORK_INDEX_WIFI_STA);
|
||||
|
||||
// This is where we decide what to do next:
|
||||
// - Reconnect
|
||||
// - Scan
|
||||
//
|
||||
// Do we have candidate to connect to ?
|
||||
if (WiFi_AP_Candidates.hasCandidates()) {
|
||||
setState(WiFi_STA_State_e::STA_Connecting, WIFI_STATE_MACHINE_STA_CONNECTING_TIMEOUT);
|
||||
} else {
|
||||
// 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);
|
||||
} else {
|
||||
setState(WiFi_STA_State_e::STA_Scanning, WIFI_STATE_MACHINE_STA_SCANNING_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
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;
|
||||
@@ -443,28 +320,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
|
||||
|
||||
@@ -472,10 +333,6 @@ void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
|
||||
// WiFi.STA.setDefault();
|
||||
# endif // ifdef ESP32
|
||||
|
||||
if (oldState == 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();
|
||||
@@ -509,7 +366,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();
|
||||
@@ -690,8 +547,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"
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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::Idle: return F("Idle");
|
||||
case ESPEasy::net::wifi::WiFi_STA_State_e::IdleWaiting: return F("IdleWaiting");
|
||||
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");
|
||||
}
|
||||
return F("");
|
||||
}
|
||||
|
||||
} // namespace wifi
|
||||
} // namespace net
|
||||
} // namespace ESPEasy
|
||||
|
||||
#endif // if FEATURE_WIFI
|
||||
@@ -52,23 +52,20 @@ 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)
|
||||
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,
|
||||
// State from where we decide to start scanning or connecting
|
||||
Idle,
|
||||
|
||||
// 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
|
||||
// Not allowed yet to continue (re)connecting.
|
||||
// For example when the interface is a fallback interface and not yet allowed to start
|
||||
// Or when in setup mode and no need to connect.
|
||||
IdleWaiting,
|
||||
|
||||
// STA mode + scanning
|
||||
@@ -86,13 +83,10 @@ enum class WiFiState_e
|
||||
STA_Reconnecting,
|
||||
|
||||
// Connected to an AP
|
||||
STA_Connected,
|
||||
|
||||
STA_Connected_Setup
|
||||
|
||||
STA_Connected
|
||||
};
|
||||
|
||||
const __FlashStringHelper* toString(WiFiState_e state);
|
||||
const __FlashStringHelper* toString(WiFi_STA_State_e state);
|
||||
|
||||
|
||||
} // namespace wifi
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user