From 9a1ff7f70dab5b948e4cd48f90ddc0fba5a17be8 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Tue, 16 Jun 2015 18:26:34 +0200 Subject: [PATCH] add WiFi scan Async mode --- libraries/ESP8266WiFi/src/ESP8266WiFi.cpp | 76 ++++++-- libraries/ESP8266WiFi/src/ESP8266WiFi.h | 27 ++- .../ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 168 ++++++++++-------- 3 files changed, 176 insertions(+), 95 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index 958dade69..b67f6dd91 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -40,7 +40,9 @@ extern "C" void esp_schedule(); extern "C" void esp_yield(); ESP8266WiFiClass::ESP8266WiFiClass() -: _useApMode(false) +: _smartConfigStarted(false) +, _smartConfigDone(false) +, _useApMode(false) , _useClientMode(false) , _useStaticIp(false) { @@ -121,7 +123,7 @@ uint8_t ESP8266WiFiClass::waitForConnectResult(){ } -// You will have to set the DNS-Server manually later since this will not enable DHCP +// You will have to set the DNS-Server manually later since this will not enable DHCP2 void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { struct ip_info info; @@ -357,12 +359,47 @@ void ESP8266WiFiClass::_scanDone(void* result, int status) } } - esp_schedule(); + + ESP8266WiFiClass::_scanStarted = false; + ESP8266WiFiClass::_scanComplete = true; + + if(!ESP8266WiFiClass::_scanAsync) { + esp_schedule(); + } } +int8_t ESP8266WiFiClass::scanComplete() { -int8_t ESP8266WiFiClass::scanNetworks() + if(_scanStarted) { + return WIFI_SCAN_RUNNING; + } + + if(_scanComplete) { + return ESP8266WiFiClass::_scanCount; + } + + return WIFI_SCAN_FAILD; +} + +void ESP8266WiFiClass::scanDelete() { + if (ESP8266WiFiClass::_scanResult) + { + delete[] reinterpret_cast(ESP8266WiFiClass::_scanResult); + ESP8266WiFiClass::_scanResult = 0; + ESP8266WiFiClass::_scanCount = 0; + } + _scanComplete = false; +} + +int8_t ESP8266WiFiClass::scanNetworks(bool async) +{ + if(ESP8266WiFiClass::_scanStarted) { + return WIFI_SCAN_RUNNING; + } + + ESP8266WiFiClass::_scanAsync = async; + if(_useApMode) { // turn on AP+STA mode mode(WIFI_AP_STA); @@ -376,22 +413,29 @@ int8_t ESP8266WiFiClass::scanNetworks() { disconnect(); } - - if (ESP8266WiFiClass::_scanResult) - { - delete[] reinterpret_cast(ESP8266WiFiClass::_scanResult); - ESP8266WiFiClass::_scanResult = 0; - ESP8266WiFiClass::_scanCount = 0; - } + scanDelete(); + struct scan_config config; config.ssid = 0; config.bssid = 0; config.channel = 0; config.show_hidden = 0; - wifi_station_scan(&config, reinterpret_cast(&ESP8266WiFiClass::_scanDone)); - esp_yield(); - return ESP8266WiFiClass::_scanCount; + if(wifi_station_scan(&config, reinterpret_cast(&ESP8266WiFiClass::_scanDone))) { + ESP8266WiFiClass::_scanComplete = false; + ESP8266WiFiClass::_scanStarted = true; + + if(ESP8266WiFiClass::_scanAsync) { + delay(0); // time for the OS to trigger the scan + return WIFI_SCAN_RUNNING; + } + + esp_yield(); + return ESP8266WiFiClass::_scanCount; + } else { + return WIFI_SCAN_FAILD; + } + } void * ESP8266WiFiClass::_getScanInfoByIndex(int i) @@ -644,6 +688,10 @@ void ESP8266WiFiClass::printDiag(Print& p) } +bool ESP8266WiFiClass::_scanAsync = false; +bool ESP8266WiFiClass::_scanStarted = false; +bool ESP8266WiFiClass::_scanComplete = false; + size_t ESP8266WiFiClass::_scanCount = 0; void* ESP8266WiFiClass::_scanResult = 0; diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/libraries/ESP8266WiFi/src/ESP8266WiFi.h index a97ed934d..e3ba3e143 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.h @@ -32,6 +32,9 @@ extern "C" { #include "WiFiClient.h" #include "WiFiServer.h" +#define WIFI_SCAN_RUNNING (-1) +#define WIFI_SCAN_FAILD (-2) + enum WiFiMode { WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3 }; class ESP8266WiFiClass @@ -189,12 +192,26 @@ public: int32_t RSSI(); + + /* + * called to get the scan state in Async mode + * + * return -1 if scan not fin + * return -2 if scan not triggered + */ + int8_t scanComplete(); + + /* + * delete last scan result from RAM + */ + void scanDelete(); + /* * Start scan WiFi networks available * * return: Number of discovered networks */ - int8_t scanNetworks(); + int8_t scanNetworks(bool async = false); /* * Return the SSID discovered during the network scan. @@ -314,13 +331,17 @@ protected: void * _getScanInfoByIndex(int i); static void _smartConfigCallback(uint32_t status, void* result); static void _eventCallback(void *event); - bool _smartConfigStarted = false; - bool _smartConfigDone = false; + bool _smartConfigStarted; + bool _smartConfigDone; bool _useApMode; bool _useClientMode; bool _useStaticIp; + static bool _scanAsync; + static bool _scanStarted; + static bool _scanComplete; + static size_t _scanCount; static void* _scanResult; diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index 34f249637..789c1d77e 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -40,107 +40,119 @@ bool ESP8266WiFiMulti::addAP(const char* ssid, const char *passphrase) { wl_status_t ESP8266WiFiMulti::run(void) { + int8_t scanResult; wl_status_t status = WiFi.status(); if(status == WL_DISCONNECTED || status == WL_NO_SSID_AVAIL || status == WL_IDLE_STATUS || status == WL_CONNECT_FAILED) { - WifiAPlist_t bestNetwork { NULL, NULL }; - int bestNetworkDb = INT_MIN; - uint8 bestBSSID[6]; - int32_t bestChannel; + scanResult = WiFi.scanComplete(); + if(scanResult == WIFI_SCAN_RUNNING) { + // scan is running + return WL_NO_SSID_AVAIL; + } else if(scanResult > 0) { + // scan done analyze + WifiAPlist_t bestNetwork { NULL, NULL }; + int bestNetworkDb = INT_MIN; + uint8 bestBSSID[6]; + int32_t bestChannel; - DEBUG_WIFI_MULTI("[WIFI] delete old wifi config...\n"); - WiFi.disconnect(); + DEBUG_WIFI_MULTI("[WIFI] scan done\n"); + delay(0); - DEBUG_WIFI_MULTI("[WIFI] start scan\n"); - // WiFi.scanNetworks will return the number of networks found - int8_t n = WiFi.scanNetworks(); + if(scanResult <= 0) { + DEBUG_WIFI_MULTI("[WIFI] no networks found\n"); + } else { + DEBUG_WIFI_MULTI("[WIFI] %d networks found\n", scanResult); + for(int8_t i = 0; i < scanResult; ++i) { - DEBUG_WIFI_MULTI("[WIFI] scan done\n"); - delay(0); + String ssid_scan; + int32_t rssi_scan; + uint8_t sec_scan; + uint8_t* BSSID_scan; + int32_t chan_scan; + bool hidden_scan; - if(n <= 0) { - DEBUG_WIFI_MULTI("[WIFI] no networks found\n"); - } else { - DEBUG_WIFI_MULTI("[WIFI] %d networks found\n", n); - for(int8_t i = 0; i < n; ++i) { + WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan); - String ssid_scan; - int32_t rssi_scan; - uint8_t sec_scan; - uint8_t* BSSID_scan; - int32_t chan_scan; - bool hidden_scan; + bool known = false; + for(uint32_t x = 0; x < APlist.size(); x++) { + WifiAPlist_t entry = APlist[x]; - WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan); - - bool known = false; - for(uint32_t x = 0; x < APlist.size(); x++) { - WifiAPlist_t entry = APlist[x]; - - if(ssid_scan == entry.ssid) { // SSID match - known = true; - if(rssi_scan > bestNetworkDb) { // best network - if(sec_scan == ENC_TYPE_NONE || entry.passphrase) { // check for passphrase if not open wlan - bestNetworkDb = rssi_scan; - bestChannel = chan_scan; - memcpy((void*) &bestNetwork, (void*) &entry, sizeof(bestNetwork)); - memcpy((void*) &bestBSSID, (void*) BSSID_scan, sizeof(bestBSSID)); + if(ssid_scan == entry.ssid) { // SSID match + known = true; + if(rssi_scan > bestNetworkDb) { // best network + if(sec_scan == ENC_TYPE_NONE || entry.passphrase) { // check for passphrase if not open wlan + bestNetworkDb = rssi_scan; + bestChannel = chan_scan; + memcpy((void*) &bestNetwork, (void*) &entry, sizeof(bestNetwork)); + memcpy((void*) &bestBSSID, (void*) BSSID_scan, sizeof(bestBSSID)); + } } + break; } - break; } - } - if(known) { - DEBUG_WIFI_MULTI(" ---> "); - } else { - DEBUG_WIFI_MULTI(" "); - } + if(known) { + DEBUG_WIFI_MULTI(" ---> "); + } else { + DEBUG_WIFI_MULTI(" "); + } - DEBUG_WIFI_MULTI(" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c\n", 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 == ENC_TYPE_NONE) ? ' ' : '*'); - delay(0); + DEBUG_WIFI_MULTI(" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c\n", 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 == ENC_TYPE_NONE) ? ' ' : '*'); + delay(0); + } } - } - DEBUG_WIFI_MULTI("\n\n"); - delay(0); + // clean up ram + WiFi.scanDelete(); - if(bestNetwork.ssid) { - DEBUG_WIFI_MULTI("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channal: %d (%d)\n", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb); + DEBUG_WIFI_MULTI("\n\n"); + delay(0); - WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); - status = WiFi.status(); + if(bestNetwork.ssid) { + DEBUG_WIFI_MULTI("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channal: %d (%d)\n", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb); - // wait for connection or fail - while(status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED) { - delay(10); + WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); status = WiFi.status(); - } - IPAddress ip; - uint8_t * mac; - switch(status) { - case WL_CONNECTED: - ip = WiFi.localIP(); - mac = WiFi.BSSID(); - DEBUG_WIFI_MULTI("[WIFI] Connecting done.\n"); - DEBUG_WIFI_MULTI("[WIFI] SSID: %s\n", WiFi.SSID()); - DEBUG_WIFI_MULTI("[WIFI] IP: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); - DEBUG_WIFI_MULTI("[WIFI] MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - DEBUG_WIFI_MULTI("[WIFI] Channel: %d\n", WiFi.channel()); - break; - case WL_NO_SSID_AVAIL: - DEBUG_WIFI_MULTI("[WIFI] Connecting Faild AP not found.\n"); - break; - case WL_CONNECT_FAILED: - DEBUG_WIFI_MULTI("[WIFI] Connecting Faild.\n"); - break; - default: - DEBUG_WIFI_MULTI("[WIFI] Connecting Faild (%d).\n", status); - break; + // wait for connection or fail + while(status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED) { + delay(10); + status = WiFi.status(); + } + + IPAddress ip; + uint8_t * mac; + switch(status) { + case WL_CONNECTED: + ip = WiFi.localIP(); + mac = WiFi.BSSID(); + DEBUG_WIFI_MULTI("[WIFI] Connecting done.\n"); + DEBUG_WIFI_MULTI("[WIFI] SSID: %s\n", WiFi.SSID()); + DEBUG_WIFI_MULTI("[WIFI] IP: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); + DEBUG_WIFI_MULTI("[WIFI] MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + DEBUG_WIFI_MULTI("[WIFI] Channel: %d\n", WiFi.channel()); + break; + case WL_NO_SSID_AVAIL: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild AP not found.\n"); + break; + case WL_CONNECT_FAILED: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild.\n"); + break; + default: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild (%d).\n", status); + break; + } + } else { + DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n"); } } else { - DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n"); + // start scan + DEBUG_WIFI_MULTI("[WIFI] delete old wifi config...\n"); + WiFi.disconnect(); + + DEBUG_WIFI_MULTI("[WIFI] start scan\n"); + // scan wifi async mode + WiFi.scanNetworks(true); } } return status;