mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			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 settingspull/9904/head
						commit
						ecfe0c83ae
					
				| 
						 | 
				
			
			@ -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));
 | 
			
		||||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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()
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -193,14 +198,23 @@ public:
 | 
			
		|||
     */
 | 
			
		||||
    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
 | 
			
		||||
    *
 | 
			
		||||
| 
						 | 
				
			
			@ -447,6 +461,7 @@ private:
 | 
			
		|||
    void _oob_busy();
 | 
			
		||||
    void _oob_tcp_data_hdlr();
 | 
			
		||||
    void _oob_ready();
 | 
			
		||||
    void _oob_scan_results();
 | 
			
		||||
 | 
			
		||||
    // OOB state variables
 | 
			
		||||
    int _connect_error;
 | 
			
		||||
| 
						 | 
				
			
			@ -475,6 +490,14 @@ private:
 | 
			
		|||
    };
 | 
			
		||||
    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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -371,14 +371,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()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -157,18 +157,38 @@ public:
 | 
			
		|||
     */
 | 
			
		||||
    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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue