Skip to content

ESP8266: treats Wi-Fi scan results as out-of-band data; new API to adjusting Wi-Fi scan settings #9955

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 56 additions & 39 deletions components/wifi/esp8266-driver/ESP8266/ESP8266.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug, PinName rts, PinName cts)
_parser.oob("ALREADY CONNECTED", callback(this, &ESP8266::_oob_conn_already));
_parser.oob("ERROR", callback(this, &ESP8266::_oob_err));
_parser.oob("ready", callback(this, &ESP8266::_oob_ready));
_parser.oob("+CWLAP:", callback(this, &ESP8266::_oob_scan_results));
// Don't expect to find anything about the watchdog reset in official documentation
//https://techtutorialsx.com/2017/01/21/esp8266-watchdog-functions/
_parser.oob("wdt reset", callback(this, &ESP8266::_oob_watchdog_reset));
Expand Down Expand Up @@ -444,29 +445,28 @@ int8_t ESP8266::rssi()
return rssi;
}

int ESP8266::scan(WiFiAccessPoint *res, unsigned limit)
int ESP8266::scan(WiFiAccessPoint *res, unsigned limit, scan_mode mode, unsigned t_max, unsigned t_min)
{
unsigned cnt = 0;
nsapi_wifi_ap_t ap;

_smutex.lock();
set_timeout(ESP8266_CONNECT_TIMEOUT);

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

while (_recv_ap(&ap)) {
if (cnt < limit) {
res[cnt] = WiFiAccessPoint(ap);
}
_scan_r.res = res;
_scan_r.limit = limit;
_scan_r.cnt = 0;

cnt++;
if (limit != 0 && cnt >= limit) {
break;
if (!(_parser.send("AT+CWLAP=,,,%u,%u,%u", (mode == SCANMODE_ACTIVE ? 0 : 1), t_min, t_max) && _parser.recv("OK\n"))) {
tr_warning("scan(): AP info parsing aborted");
// Lets be happy about partial success and not return NSAPI_ERROR_DEVICE_ERROR
if (!_scan_r.cnt) {
_scan_r.cnt = NSAPI_ERROR_DEVICE_ERROR;
}
}

int cnt = _scan_r.cnt;
_scan_r.res = NULL;

set_timeout();
_smutex.unlock();

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

bool ESP8266::_recv_ap(nsapi_wifi_ap_t *ap)
{
int sec;
int sec = NSAPI_SECURITY_UNKNOWN;
int dummy;
bool ret;
int ret;

if (FW_AT_LEAST_VERSION(_at_v.major, _at_v.minor, _at_v.patch, 0, ESP8266_AT_VERSION_WIFI_SCAN_CHANGE)) {
ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu,%d,%d,%d,%d,%d,%d)\n",
&sec,
ap->ssid,
&ap->rssi,
&ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
&ap->channel,
&dummy,
&dummy,
&dummy,
&dummy,
&dummy,
&dummy);
ret = _parser.scanf("(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu,%d,%d,%d,%d,%d,%d)\n",
&sec,
ap->ssid,
&ap->rssi,
&ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
&ap->channel,
&dummy,
&dummy,
&dummy,
&dummy,
&dummy,
&dummy);
} else {
ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu,%d,%d)\n",
&sec,
ap->ssid,
&ap->rssi,
&ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
&ap->channel,
&dummy,
&dummy);
ret = _parser.scanf("(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu,%d,%d)\n",
&sec,
ap->ssid,
&ap->rssi,
&ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
&ap->channel,
&dummy,
&dummy);
}

if (ret < 0) {
_parser.abort();
tr_warning("_recv_ap(): AP info missing");
}

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

return ret;
return ret < 0 ? false : true;
}

void ESP8266::_oob_watchdog_reset()
Expand Down Expand Up @@ -1063,6 +1067,19 @@ void ESP8266::_oob_tcp_data_hdlr()
_sock_i[_sock_active_id].tcp_data_rcvd = len;
}

void ESP8266::_oob_scan_results()
{
nsapi_wifi_ap_t ap;

if (_recv_ap(&ap)) {
if (_scan_r.res && _scan_r.cnt < _scan_r.limit) {
_scan_r.res[_scan_r.cnt] = WiFiAccessPoint(ap);
}

_scan_r.cnt++;
}
}

void ESP8266::_oob_connect_err()
{
_fail = false;
Expand Down
25 changes: 24 additions & 1 deletion components/wifi/esp8266-driver/ESP8266/ESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
#define ESP8266_MISC_TIMEOUT 2000
#endif

#define ESP8266_SCAN_TIME_MIN 0 // [ms]
#define ESP8266_SCAN_TIME_MAX 1500 // [ms]
#define ESP8266_SCAN_TIME_MIN_DEFAULT 120 // [ms]
#define ESP8266_SCAN_TIME_MAX_DEFAULT 360 // [ms]

// Firmware version
#define ESP8266_SDK_VERSION 2000000
#define ESP8266_SDK_VERSION_MAJOR ESP8266_SDK_VERSION/1000000
Expand Down Expand Up @@ -193,14 +198,23 @@ class ESP8266 {
*/
int8_t rssi();

/** Scan mode
*/
enum scan_mode {
SCANMODE_ACTIVE = 0, /*!< active mode */
SCANMODE_PASSIVE = 1 /*!< passive mode */
};

/** Scan for available networks
*
* @param ap Pointer to allocated array to store discovered AP
* @param limit Size of allocated @a res array, or 0 to only count available AP
* @param t_max Maximum scan time per channel
* @param t_min Minimum scan time per channel in active mode, can be omitted in passive mode
* @return Number of entries in @a res, or if @a count was 0 number of available networks, negative on error
* see @a nsapi_error
*/
int scan(WiFiAccessPoint *res, unsigned limit);
int scan(WiFiAccessPoint *res, unsigned limit, scan_mode mode, unsigned t_max, unsigned t_min);

/**Perform a dns query
*
Expand Down Expand Up @@ -438,6 +452,7 @@ class ESP8266 {
void _oob_busy();
void _oob_tcp_data_hdlr();
void _oob_ready();
void _oob_scan_results();

// OOB state variables
int _connect_error;
Expand Down Expand Up @@ -466,6 +481,14 @@ class ESP8266 {
};
struct _sock_info _sock_i[SOCKET_COUNT];

// Scan results
struct _scan_results {
WiFiAccessPoint *res;
unsigned limit;
unsigned cnt;
};
struct _scan_results _scan_r;

// Connection state reporting
nsapi_connection_status_t _conn_status;
mbed::Callback<void()> _conn_stat_cb; // ESP8266Interface registered
Expand Down
17 changes: 14 additions & 3 deletions components/wifi/esp8266-driver/ESP8266Interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,14 +361,25 @@ int8_t ESP8266Interface::get_rssi()

int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count)
{
nsapi_error_t status;
return scan(res, count, SCANMODE_ACTIVE, 0, 0);
}

status = _init();
int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count, scan_mode mode, unsigned t_max, unsigned t_min)
{
if (t_max > ESP8266_SCAN_TIME_MAX) {
return NSAPI_ERROR_PARAMETER;
}
if (mode == SCANMODE_ACTIVE && t_min > t_max) {
return NSAPI_ERROR_PARAMETER;
}

nsapi_error_t status = _init();
if (status != NSAPI_ERROR_OK) {
return status;
}

return _esp.scan(res, count);
return _esp.scan(res, count, (mode == SCANMODE_ACTIVE ? ESP8266::SCANMODE_ACTIVE : ESP8266::SCANMODE_PASSIVE),
t_min, t_max);
}

bool ESP8266Interface::_get_firmware_ok()
Expand Down
30 changes: 25 additions & 5 deletions components/wifi/esp8266-driver/ESP8266Interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,38 @@ class ESP8266Interface : public NetworkStack, public WiFiInterface {
*/
virtual int8_t get_rssi();

/** Scan mode
*/
enum scan_mode {
SCANMODE_ACTIVE, /*!< active mode */
SCANMODE_PASSIVE /*!< passive mode */
};

/** Scan for available networks
*
* This function will block.
*
* @param ap Pointer to allocated array to store discovered AP
* @param count Size of allocated @a res array, or 0 to only count available AP
* @param timeout Timeout in milliseconds; 0 for no timeout (Default: 0)
* @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error
* see @a nsapi_error
* @param ap Pointer to allocated array to store discovered AP
* @param count Size of allocated @a res array, or 0 to only count available AP
* @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error
* see @a nsapi_error
*/
virtual int scan(WiFiAccessPoint *res, unsigned count);

/** Scan for available networks
*
* This function will block.
*
* @param ap Pointer to allocated array to store discovered AP
* @param count Size of allocated @a res array, or 0 to only count available AP
* @param t_max Scan time for each channel - 0-1500ms. If 0 - uses default value
* @param t_min Minimum for each channel in active mode - 0-1500ms. If 0 - uses default value. Omit in passive mode
* @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error
* see @a nsapi_error
*/
virtual int scan(WiFiAccessPoint *res, unsigned count, scan_mode mode = SCANMODE_PASSIVE,
unsigned t_max = 0, unsigned t_min = 0);

/** Translates a hostname to an IP address with specific version
*
* The hostname may be either a domain name or an IP address. If the
Expand Down