@@ -33,10 +33,9 @@ WiFiMulti::WiFiMulti()
3333 ipv6_support = false ;
3434}
3535
36- WiFiMulti::~WiFiMulti ( )
36+ void WiFiMulti::APlistClean ( void )
3737{
38- for (uint32_t i = 0 ; i < APlist.size (); i++) {
39- WifiAPlist_t entry = APlist[i];
38+ for (auto entry : APlist) {
4039 if (entry.ssid ) {
4140 free (entry.ssid );
4241 }
@@ -47,17 +46,22 @@ WiFiMulti::~WiFiMulti()
4746 APlist.clear ();
4847}
4948
49+ WiFiMulti::~WiFiMulti ()
50+ {
51+ APlistClean ();
52+ }
53+
5054bool WiFiMulti::addAP (const char * ssid, const char *passphrase)
5155{
5256 WifiAPlist_t newAP;
5357
54- if (!ssid || *ssid == 0x00 || strlen (ssid) > 31 ) {
58+ if (!ssid || *ssid == ' \0 ' || strlen (ssid) > 31 ) {
5559 // fail SSID too long or missing!
5660 log_e (" [WIFI][APlistAdd] no ssid or ssid too long" );
5761 return false ;
5862 }
5963
60- if (passphrase && strlen (passphrase) > 64 ) {
64+ if (passphrase && strlen (passphrase) > 63 ) {
6165 // fail passphrase too long!
6266 log_e (" [WIFI][APlistAdd] passphrase too long" );
6367 return false ;
@@ -70,7 +74,7 @@ bool WiFiMulti::addAP(const char* ssid, const char *passphrase)
7074 return false ;
7175 }
7276
73- if (passphrase && *passphrase != 0x00 ) {
77+ if (passphrase && *passphrase != ' \0 ' ) {
7478 newAP.passphrase = strdup (passphrase);
7579 if (!newAP.passphrase ) {
7680 log_e (" [WIFI][APlistAdd] fail newAP.passphrase == 0" );
@@ -80,7 +84,7 @@ bool WiFiMulti::addAP(const char* ssid, const char *passphrase)
8084 } else {
8185 newAP.passphrase = NULL ;
8286 }
83-
87+ newAP. hasFailed = false ;
8488 APlist.push_back (newAP);
8589 log_i (" [WIFI][APlistAdd] add SSID: %s" , newAP.ssid );
8690 return true ;
@@ -91,9 +95,20 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout)
9195 int8_t scanResult;
9296 uint8_t status = WiFi.status ();
9397 if (status == WL_CONNECTED) {
94- for (uint32_t x = 0 ; x < APlist.size (); x++) {
95- if (WiFi.SSID ()==APlist[x].ssid ) {
98+ if (!_bWFMInit && _connectionTestCBFunc != NULL ){
99+ if (_connectionTestCBFunc () == true ) {
100+ _bWFMInit = true ;
101+ return status;
102+ }
103+ } else {
104+ if (!_bStrict) {
96105 return status;
106+ } else {
107+ for (auto ap : APlist) {
108+ if (WiFi.SSID () == ap.ssid ) {
109+ return status;
110+ }
111+ }
97112 }
98113 }
99114 WiFi.disconnect (false ,false );
@@ -102,22 +117,27 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout)
102117 }
103118
104119 scanResult = WiFi.scanNetworks ();
105- if (scanResult == WIFI_SCAN_RUNNING) {
120+ if (scanResult == WIFI_SCAN_RUNNING) {
106121 // scan is running
107122 return WL_NO_SSID_AVAIL;
108- } else if (scanResult >= 0 ) {
123+ } else if (scanResult >= 0 ) {
109124 // scan done analyze
110- WifiAPlist_t bestNetwork { NULL , NULL };
125+ int32_t bestIndex = 0 ;
126+ WifiAPlist_t bestNetwork { NULL , NULL , false };
111127 int bestNetworkDb = INT_MIN;
128+ int bestNetworkSec = WIFI_AUTH_MAX;
112129 uint8_t bestBSSID[6 ];
113130 int32_t bestChannel = 0 ;
114131
115132 log_i (" [WIFI] scan done" );
116133
117- if (scanResult == 0 ) {
134+ if (scanResult == 0 ) {
118135 log_e (" [WIFI] no networks found" );
119136 } else {
120137 log_i (" [WIFI] %d networks found" , scanResult);
138+
139+ int8_t failCount = 0 ;
140+ int8_t foundCount = 0 ;
121141 for (int8_t i = 0 ; i < scanResult; ++i) {
122142
123143 String ssid_scan;
@@ -127,22 +147,47 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout)
127147 int32_t chan_scan;
128148
129149 WiFi.getNetworkInfo (i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan);
150+ // add any Open WiFi AP to the list, if allowed with setAllowOpenAP(true)
151+ if (_bAllowOpenAP && sec_scan == WIFI_AUTH_OPEN){
152+ bool found = false ;
153+ for (auto check : APlist) {
154+ if (ssid_scan == check.ssid ){
155+ found = true ;
156+ break ;
157+ }
158+ }
159+ // If we didn't find it, add this Open WiFi AP to the list
160+ if (!found){
161+ log_i (" [WIFI][APlistAdd] adding Open WiFi SSID: %s" , ssid_scan.c_str ());
162+ addAP (ssid_scan.c_str ());
163+ }
164+ }
130165
131166 bool known = false ;
132- for (uint32_t x = APlist.size () ; x > 0 ; x-- ) {
133- WifiAPlist_t entry = APlist[x- 1 ];
167+ for (uint32_t x = 0 ; x < APlist.size (); x++ ) {
168+ WifiAPlist_t entry = APlist[x];
134169
135170 if (ssid_scan == entry.ssid ) { // SSID match
136- known = true ;
137- if (rssi_scan > bestNetworkDb) { // best network
138- if (sec_scan == WIFI_AUTH_OPEN || entry.passphrase ) { // check for passphrase if not open wlan
139- bestNetworkDb = rssi_scan;
140- bestChannel = chan_scan;
141- memcpy ((void *) &bestNetwork, (void *) &entry, sizeof (bestNetwork));
142- memcpy ((void *) &bestBSSID, (void *) BSSID_scan, sizeof (bestBSSID));
171+ log_v (" known ssid: %s, has failed: %s" , entry.ssid , entry.hasFailed ? " yes" : " no" );
172+ foundCount++;
173+ if (!entry.hasFailed ){
174+ known = true ;
175+ log_v (" rssi_scan: %d, bestNetworkDb: %d" , rssi_scan, bestNetworkDb);
176+ if (rssi_scan > bestNetworkDb) { // best network
177+ if (_bAllowOpenAP || (sec_scan == WIFI_AUTH_OPEN || entry.passphrase )) { // check for passphrase if not open wlan
178+ log_v (" best network is now: %s" , ssid_scan);
179+ bestIndex = x;
180+ bestNetworkSec = sec_scan;
181+ bestNetworkDb = rssi_scan;
182+ bestChannel = chan_scan;
183+ memcpy ((void *) &bestNetwork, (void *) &entry, sizeof (bestNetwork));
184+ memcpy ((void *) &bestBSSID, (void *) BSSID_scan, sizeof (bestBSSID));
185+ }
143186 }
187+ break ;
188+ } else {
189+ failCount++;
144190 }
145- break ;
146191 }
147192 }
148193
@@ -152,8 +197,12 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout)
152197 log_d (" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c" , i, chan_scan, BSSID_scan[0 ], BSSID_scan[1 ], BSSID_scan[2 ], BSSID_scan[3 ], BSSID_scan[4 ], BSSID_scan[5 ], ssid_scan.c_str (), rssi_scan, (sec_scan == WIFI_AUTH_OPEN) ? ' ' : ' *' );
153198 }
154199 }
200+ log_v (" foundCount = %d, failCount = %d" , foundCount, failCount);
201+ // if all the APs in the list have failed, reset the failure flags
202+ if (foundCount == failCount) {
203+ resetFails (); // keeps trying the APs in the list
204+ }
155205 }
156-
157206 // clean up ram
158207 WiFi.scanDelete ();
159208
@@ -163,12 +212,15 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout)
163212 if (ipv6_support == true ) {
164213 WiFi.enableIPv6 ();
165214 }
166- WiFi.begin (bestNetwork.ssid , bestNetwork.passphrase , bestChannel, bestBSSID);
215+ WiFi.disconnect ();
216+ delay (10 );
217+ WiFi.begin (bestNetwork.ssid , (_bAllowOpenAP && bestNetworkSec == WIFI_AUTH_OPEN) ? NULL : bestNetwork.passphrase , bestChannel, bestBSSID);
167218 status = WiFi.status ();
219+ _bWFMInit = true ;
168220
169221 auto startTime = millis ();
170222 // wait for connection, fail, or timeout
171- while (status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED && ( millis () - startTime) <= connectTimeout) {
223+ while (status != WL_CONNECTED && ( millis () - startTime) <= connectTimeout) { // && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED
172224 delay (10 );
173225 status = WiFi.status ();
174226 }
@@ -180,15 +232,32 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout)
180232 log_d (" [WIFI] IP: %s" , WiFi.localIP ().toString ().c_str ());
181233 log_d (" [WIFI] MAC: %s" , WiFi.BSSIDstr ().c_str ());
182234 log_d (" [WIFI] Channel: %d" , WiFi.channel ());
235+
236+ if (_connectionTestCBFunc != NULL ) {
237+ // We connected to an AP but if it's a captive portal we're not going anywhere. Test it.
238+ if (_connectionTestCBFunc ()) {
239+ resetFails ();
240+ } else {
241+ markAsFailed (bestIndex);
242+ WiFi.disconnect ();
243+ delay (10 );
244+ status = WiFi.status ();
245+ }
246+ } else {
247+ resetFails ();
248+ }
183249 break ;
184250 case WL_NO_SSID_AVAIL:
185251 log_e (" [WIFI] Connecting Failed AP not found." );
252+ markAsFailed (bestIndex);
186253 break ;
187254 case WL_CONNECT_FAILED:
188255 log_e (" [WIFI] Connecting Failed." );
256+ markAsFailed (bestIndex);
189257 break ;
190258 default :
191259 log_e (" [WIFI] Connecting Failed (%d)." , status);
260+ markAsFailed (bestIndex);
192261 break ;
193262 }
194263 } else {
@@ -210,3 +279,27 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout)
210279void WiFiMulti::enableIPv6 (bool state) {
211280 ipv6_support = state;
212281}
282+
283+ void WiFiMulti::markAsFailed (int32_t i) {
284+ APlist[i].hasFailed = true ;
285+ log_d (" [WIFI] Marked SSID %s as failed" , APlist[i].ssid );
286+ }
287+
288+ void WiFiMulti::resetFails (){
289+ for (uint32_t i = 0 ; i < APlist.size (); i++) {
290+ APlist[i].hasFailed = false ;
291+ }
292+ log_d (" [WIFI] Resetting failure flags" );
293+ }
294+
295+ void WiFiMulti::setStrictMode (bool bStrict) {
296+ _bStrict = bStrict;
297+ }
298+
299+ void WiFiMulti::setAllowOpenAP (bool bAllowOpenAP) {
300+ _bAllowOpenAP = bAllowOpenAP;
301+ }
302+
303+ void WiFiMulti::setConnectionTestCallbackFunc (ConnectionTestCB_t cbFunc) {
304+ _connectionTestCBFunc = cbFunc;
305+ }
0 commit comments