Skip to content

Commit ecfe0c8

Browse files
author
Cruz Monrreal
authored
Merge pull request #9955 from VeijoPesonen/esp8266_wifi_scan_timeout
ESP8266: treats Wi-Fi scan results as out-of-band data; new API to adjusting Wi-Fi scan settings
2 parents 1c23c5b + e2bd064 commit ecfe0c8

File tree

4 files changed

+119
-48
lines changed

4 files changed

+119
-48
lines changed

components/wifi/esp8266-driver/ESP8266/ESP8266.cpp

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug, PinName rts, PinName cts)
7575
_parser.oob("ALREADY CONNECTED", callback(this, &ESP8266::_oob_conn_already));
7676
_parser.oob("ERROR", callback(this, &ESP8266::_oob_err));
7777
_parser.oob("ready", callback(this, &ESP8266::_oob_ready));
78+
_parser.oob("+CWLAP:", callback(this, &ESP8266::_oob_scan_results));
7879
// Don't expect to find anything about the watchdog reset in official documentation
7980
//https://techtutorialsx.com/2017/01/21/esp8266-watchdog-functions/
8081
_parser.oob("wdt reset", callback(this, &ESP8266::_oob_watchdog_reset));
@@ -444,29 +445,28 @@ int8_t ESP8266::rssi()
444445
return rssi;
445446
}
446447

447-
int ESP8266::scan(WiFiAccessPoint *res, unsigned limit)
448+
int ESP8266::scan(WiFiAccessPoint *res, unsigned limit, scan_mode mode, unsigned t_max, unsigned t_min)
448449
{
449-
unsigned cnt = 0;
450-
nsapi_wifi_ap_t ap;
451-
452450
_smutex.lock();
453-
set_timeout(ESP8266_CONNECT_TIMEOUT);
454451

455-
if (!_parser.send("AT+CWLAP")) {
456-
_smutex.unlock();
457-
return NSAPI_ERROR_DEVICE_ERROR;
458-
}
452+
// Default timeout plus time spend scanning each channel
453+
set_timeout(ESP8266_MISC_TIMEOUT + 13 * (t_max ? t_max : ESP8266_SCAN_TIME_MAX_DEFAULT));
459454

460-
while (_recv_ap(&ap)) {
461-
if (cnt < limit) {
462-
res[cnt] = WiFiAccessPoint(ap);
463-
}
455+
_scan_r.res = res;
456+
_scan_r.limit = limit;
457+
_scan_r.cnt = 0;
464458

465-
cnt++;
466-
if (limit != 0 && cnt >= limit) {
467-
break;
459+
if (!(_parser.send("AT+CWLAP=,,,%u,%u,%u", (mode == SCANMODE_ACTIVE ? 0 : 1), t_min, t_max) && _parser.recv("OK\n"))) {
460+
tr_warning("scan(): AP info parsing aborted");
461+
// Lets be happy about partial success and not return NSAPI_ERROR_DEVICE_ERROR
462+
if (!_scan_r.cnt) {
463+
_scan_r.cnt = NSAPI_ERROR_DEVICE_ERROR;
468464
}
469465
}
466+
467+
int cnt = _scan_r.cnt;
468+
_scan_r.res = NULL;
469+
470470
set_timeout();
471471
_smutex.unlock();
472472

@@ -966,38 +966,42 @@ void ESP8266::attach(Callback<void()> status_cb)
966966

967967
bool ESP8266::_recv_ap(nsapi_wifi_ap_t *ap)
968968
{
969-
int sec;
969+
int sec = NSAPI_SECURITY_UNKNOWN;
970970
int dummy;
971-
bool ret;
971+
int ret;
972972

973973
if (FW_AT_LEAST_VERSION(_at_v.major, _at_v.minor, _at_v.patch, 0, ESP8266_AT_VERSION_WIFI_SCAN_CHANGE)) {
974-
ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu,%d,%d,%d,%d,%d,%d)\n",
975-
&sec,
976-
ap->ssid,
977-
&ap->rssi,
978-
&ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
979-
&ap->channel,
980-
&dummy,
981-
&dummy,
982-
&dummy,
983-
&dummy,
984-
&dummy,
985-
&dummy);
974+
ret = _parser.scanf("(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu,%d,%d,%d,%d,%d,%d)\n",
975+
&sec,
976+
ap->ssid,
977+
&ap->rssi,
978+
&ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
979+
&ap->channel,
980+
&dummy,
981+
&dummy,
982+
&dummy,
983+
&dummy,
984+
&dummy,
985+
&dummy);
986986
} else {
987-
ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu,%d,%d)\n",
988-
&sec,
989-
ap->ssid,
990-
&ap->rssi,
991-
&ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
992-
&ap->channel,
993-
&dummy,
994-
&dummy);
987+
ret = _parser.scanf("(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu,%d,%d)\n",
988+
&sec,
989+
ap->ssid,
990+
&ap->rssi,
991+
&ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
992+
&ap->channel,
993+
&dummy,
994+
&dummy);
995+
}
995996

997+
if (ret < 0) {
998+
_parser.abort();
999+
tr_warning("_recv_ap(): AP info missing");
9961000
}
9971001

9981002
ap->security = sec < 5 ? (nsapi_security_t)sec : NSAPI_SECURITY_UNKNOWN;
9991003

1000-
return ret;
1004+
return ret < 0 ? false : true;
10011005
}
10021006

10031007
void ESP8266::_oob_watchdog_reset()
@@ -1063,6 +1067,19 @@ void ESP8266::_oob_tcp_data_hdlr()
10631067
_sock_i[_sock_active_id].tcp_data_rcvd = len;
10641068
}
10651069

1070+
void ESP8266::_oob_scan_results()
1071+
{
1072+
nsapi_wifi_ap_t ap;
1073+
1074+
if (_recv_ap(&ap)) {
1075+
if (_scan_r.res && _scan_r.cnt < _scan_r.limit) {
1076+
_scan_r.res[_scan_r.cnt] = WiFiAccessPoint(ap);
1077+
}
1078+
1079+
_scan_r.cnt++;
1080+
}
1081+
}
1082+
10661083
void ESP8266::_oob_connect_err()
10671084
{
10681085
_fail = false;

components/wifi/esp8266-driver/ESP8266/ESP8266.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
#define ESP8266_MISC_TIMEOUT 2000
4545
#endif
4646

47+
#define ESP8266_SCAN_TIME_MIN 0 // [ms]
48+
#define ESP8266_SCAN_TIME_MAX 1500 // [ms]
49+
#define ESP8266_SCAN_TIME_MIN_DEFAULT 120 // [ms]
50+
#define ESP8266_SCAN_TIME_MAX_DEFAULT 360 // [ms]
51+
4752
// Firmware version
4853
#define ESP8266_SDK_VERSION 2000000
4954
#define ESP8266_SDK_VERSION_MAJOR ESP8266_SDK_VERSION/1000000
@@ -193,14 +198,23 @@ class ESP8266 {
193198
*/
194199
int8_t rssi();
195200

201+
/** Scan mode
202+
*/
203+
enum scan_mode {
204+
SCANMODE_ACTIVE = 0, /*!< active mode */
205+
SCANMODE_PASSIVE = 1 /*!< passive mode */
206+
};
207+
196208
/** Scan for available networks
197209
*
198210
* @param ap Pointer to allocated array to store discovered AP
199211
* @param limit Size of allocated @a res array, or 0 to only count available AP
212+
* @param t_max Maximum scan time per channel
213+
* @param t_min Minimum scan time per channel in active mode, can be omitted in passive mode
200214
* @return Number of entries in @a res, or if @a count was 0 number of available networks, negative on error
201215
* see @a nsapi_error
202216
*/
203-
int scan(WiFiAccessPoint *res, unsigned limit);
217+
int scan(WiFiAccessPoint *res, unsigned limit, scan_mode mode, unsigned t_max, unsigned t_min);
204218

205219
/**Perform a dns query
206220
*
@@ -447,6 +461,7 @@ class ESP8266 {
447461
void _oob_busy();
448462
void _oob_tcp_data_hdlr();
449463
void _oob_ready();
464+
void _oob_scan_results();
450465

451466
// OOB state variables
452467
int _connect_error;
@@ -475,6 +490,14 @@ class ESP8266 {
475490
};
476491
struct _sock_info _sock_i[SOCKET_COUNT];
477492

493+
// Scan results
494+
struct _scan_results {
495+
WiFiAccessPoint *res;
496+
unsigned limit;
497+
unsigned cnt;
498+
};
499+
struct _scan_results _scan_r;
500+
478501
// Connection state reporting
479502
nsapi_connection_status_t _conn_status;
480503
mbed::Callback<void()> _conn_stat_cb; // ESP8266Interface registered

components/wifi/esp8266-driver/ESP8266Interface.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,14 +371,25 @@ int8_t ESP8266Interface::get_rssi()
371371

372372
int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count)
373373
{
374-
nsapi_error_t status;
374+
return scan(res, count, SCANMODE_ACTIVE, 0, 0);
375+
}
375376

376-
status = _init();
377+
int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count, scan_mode mode, unsigned t_max, unsigned t_min)
378+
{
379+
if (t_max > ESP8266_SCAN_TIME_MAX) {
380+
return NSAPI_ERROR_PARAMETER;
381+
}
382+
if (mode == SCANMODE_ACTIVE && t_min > t_max) {
383+
return NSAPI_ERROR_PARAMETER;
384+
}
385+
386+
nsapi_error_t status = _init();
377387
if (status != NSAPI_ERROR_OK) {
378388
return status;
379389
}
380390

381-
return _esp.scan(res, count);
391+
return _esp.scan(res, count, (mode == SCANMODE_ACTIVE ? ESP8266::SCANMODE_ACTIVE : ESP8266::SCANMODE_PASSIVE),
392+
t_min, t_max);
382393
}
383394

384395
bool ESP8266Interface::_get_firmware_ok()

components/wifi/esp8266-driver/ESP8266Interface.h

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,18 +157,38 @@ class ESP8266Interface : public NetworkStack, public WiFiInterface {
157157
*/
158158
virtual int8_t get_rssi();
159159

160+
/** Scan mode
161+
*/
162+
enum scan_mode {
163+
SCANMODE_ACTIVE, /*!< active mode */
164+
SCANMODE_PASSIVE /*!< passive mode */
165+
};
166+
160167
/** Scan for available networks
161168
*
162169
* This function will block.
163170
*
164-
* @param ap Pointer to allocated array to store discovered AP
165-
* @param count Size of allocated @a res array, or 0 to only count available AP
166-
* @param timeout Timeout in milliseconds; 0 for no timeout (Default: 0)
167-
* @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error
168-
* see @a nsapi_error
171+
* @param ap Pointer to allocated array to store discovered AP
172+
* @param count Size of allocated @a res array, or 0 to only count available AP
173+
* @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error
174+
* see @a nsapi_error
169175
*/
170176
virtual int scan(WiFiAccessPoint *res, unsigned count);
171177

178+
/** Scan for available networks
179+
*
180+
* This function will block.
181+
*
182+
* @param ap Pointer to allocated array to store discovered AP
183+
* @param count Size of allocated @a res array, or 0 to only count available AP
184+
* @param t_max Scan time for each channel - 0-1500ms. If 0 - uses default value
185+
* @param t_min Minimum for each channel in active mode - 0-1500ms. If 0 - uses default value. Omit in passive mode
186+
* @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error
187+
* see @a nsapi_error
188+
*/
189+
virtual int scan(WiFiAccessPoint *res, unsigned count, scan_mode mode = SCANMODE_PASSIVE,
190+
unsigned t_max = 0, unsigned t_min = 0);
191+
172192
/** Translates a hostname to an IP address with specific version
173193
*
174194
* The hostname may be either a domain name or an IP address. If the

0 commit comments

Comments
 (0)