From bc37b9ea6856225055088d1afc6c780b807895c9 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Thu, 21 May 2015 21:10:45 +0200 Subject: [PATCH] ESP8266WiFi extended functions - begin changes allow setting BSSID/MAC and Channel of an AP for faster connection (#261) now checks if ssid and passphrase to big selecting Wifi mode in better way (fix for #28) - ESP8266WiFiMulti uses the new functions to auto select best AP even in a multi AP WiFi network (more the one AP has same SSID) - add new functions to get current Connected AP: uint8_t * BSSID(void); int32_t Channel(void); - add new functions to get infos from scanned networks: uint8_t * BSSID(uint8_t networkItem); int32_t Channel(uint8_t networkItem); bool isHidden(uint8_t networkItem); bool getNetworkInfo(uint8_t networkItem, const char** ssid, uint8_t * encryptionType, int32_t * RSSI, uint8_t ** BSSID, int32_t * channel, bool * isHidden); --- libraries/ESP8266WiFi/src/ESP8266WiFi.cpp | 136 +++++++++++++----- libraries/ESP8266WiFi/src/ESP8266WiFi.h | 76 ++++++++-- .../ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 27 +++- 3 files changed, 188 insertions(+), 51 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index 115b23763..372df9ed0 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -39,7 +39,8 @@ extern "C" void esp_yield(); ESP8266WiFiClass::ESP8266WiFiClass() { - + useApMode = false; + useClientMode = false; } void ESP8266WiFiClass::mode(WiFiMode m) @@ -49,34 +50,56 @@ void ESP8266WiFiClass::mode(WiFiMode m) ETS_UART_INTR_ENABLE(); } - -int ESP8266WiFiClass::begin(const char* ssid) -{ - return begin(ssid, 0); +int ESP8266WiFiClass::begin(char* ssid, char *passphrase, int32_t channel, uint8_t bssid[6]){ + return begin((const char*) ssid, (const char*) passphrase, channel, bssid); } +int ESP8266WiFiClass::begin(const char* ssid, const char *passphrase, int32_t channel, uint8_t bssid[6]){ + useClientMode = true; -int ESP8266WiFiClass::begin(const char* ssid, const char *passphrase) -{ - if ((wifi_get_opmode() & 1) == 0)//1 and 3 have STA enabled - { + if(useApMode) { // turn on AP+STA mode mode(WIFI_AP_STA); + } else { + // turn on STA mode + mode(WIFI_STA); + } + + if(!ssid || strlen(ssid) > 31) { + // fail SSID to long or missing! + return WL_CONNECT_FAILED; + } + + if(passphrase && strlen(passphrase) > 63) { + // fail passphrase to long! + return WL_CONNECT_FAILED; } struct station_config conf; strcpy(reinterpret_cast(conf.ssid), ssid); - if (passphrase) - strcpy(reinterpret_cast(conf.password), passphrase); - else - *conf.password = 0; - conf.bssid_set = 0; + if (passphrase) { + strcpy(reinterpret_cast(conf.password), passphrase); + } else { + *conf.password = 0; + } + + if (bssid) { + conf.bssid_set = 1; + memcpy((void *) &conf.bssid[0], (void *) bssid, 6); + } else { + conf.bssid_set = 0; + } ETS_UART_INTR_DISABLE(); wifi_station_set_config(&conf); wifi_station_connect(); ETS_UART_INTR_ENABLE(); + + if(channel > 0 && channel <= 13) { + wifi_set_channel(channel); + } + wifi_station_dhcpc_start(); return status(); } @@ -120,10 +143,22 @@ void ESP8266WiFiClass::softAP(const char* ssid) void ESP8266WiFiClass::softAP(const char* ssid, const char* passphrase, int channel) { - if (wifi_get_opmode() < WIFI_AP)//will be OFF or STA - { + if(useClientMode) { // turn on AP+STA mode mode(WIFI_AP_STA); + } else { + // turn on STA mode + mode(WIFI_AP); + } + + if(!ssid || strlen(ssid) > 31) { + // fail SSID to long or missing! + return; + } + + if(passphrase && strlen(passphrase) > 63) { + // fail passphrase to long! + return; } struct softap_config conf; @@ -209,22 +244,16 @@ char* ESP8266WiFiClass::SSID() return reinterpret_cast(conf.ssid); } -// uint8_t* ESP8266WiFiClass::BSSID(uint8_t* bssid) -// { -// uint8_t* _bssid = WiFiDrv::getCurrentBSSID(); -// memcpy(bssid, _bssid, WL_MAC_ADDR_LENGTH); -// return bssid; -// } +uint8_t* ESP8266WiFiClass::BSSID(void) +{ + static struct station_config conf; + wifi_station_get_config(&conf); + return reinterpret_cast(conf.bssid); +} -// int32_t ESP8266WiFiClass::RSSI() -// { -// return WiFiDrv::getCurrentRSSI(); -// } - -// uint8_t ESP8266WiFiClass::encryptionType() -// { -// return WiFiDrv::getCurrentEncryptionType(); -// } +int32_t ESP8266WiFiClass::Channel(void) { + return wifi_get_channel(); +} extern "C" { @@ -298,7 +327,7 @@ int8_t ESP8266WiFiClass::scanNetworks() void * ESP8266WiFiClass::_getScanInfoByIndex(int i) { - if (!ESP8266WiFiClass::_scanResult || i > ESP8266WiFiClass::_scanCount) + if (!ESP8266WiFiClass::_scanResult || (size_t)i > ESP8266WiFiClass::_scanCount) { return 0; } @@ -315,6 +344,49 @@ const char* ESP8266WiFiClass::SSID(uint8_t i) return reinterpret_cast(it->ssid); } +uint8_t * ESP8266WiFiClass::BSSID(uint8_t i) +{ + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return 0; + + return it->bssid; +} + +int32_t ESP8266WiFiClass::Channel(uint8_t i) +{ + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return 0; + + return it->channel; +} + +bool ESP8266WiFiClass::isHidden(uint8_t i) +{ + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return false; + + return (it->is_hidden != 0); +} + +bool ESP8266WiFiClass::getNetworkInfo(uint8_t i, const char** ssid, uint8_t * encType, int32_t * RSSI, uint8_t ** BSSID, int32_t * channel, bool * isHidden) +{ + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return false; + + *ssid = (const char*) &it->ssid[0]; // move ptr + *encType = encryptionType(i); + *RSSI = it->rssi; + *BSSID = &it->bssid[0]; // move ptr + *channel = it->channel; + *isHidden = (it->is_hidden != 0); + + return true; +} + int32_t ESP8266WiFiClass::RSSI(uint8_t i) { struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/libraries/ESP8266WiFi/src/ESP8266WiFi.h index feb18abf8..caefbc7df 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.h @@ -42,21 +42,18 @@ public: void mode(WiFiMode); - - /* Start Wifi connection for OPEN networks - * - * param ssid: Pointer to the SSID string. + /** + * Start Wifi connection + * if passphrase is set the most secure supported mode will be automatically selected + * @param ssid const char* Pointer to the SSID string. + * @param passphrase const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal). + * @param bssid uint8_t[6] Optional. BSSID / MAC of AP + * @param channel Optional. Channel of AP + * @return */ - int begin(const char* ssid); + int begin(const char* ssid, const char *passphrase = NULL, int32_t channel = 0, uint8_t bssid[6] = NULL); + int begin(char* ssid, char *passphrase = NULL, int32_t channel = 0, uint8_t bssid[6] = NULL); - /* Start Wifi connection with passphrase - * the most secure supported mode will be automatically selected - * - * param ssid: Pointer to the SSID string. - * param passphrase: Passphrase. Valid characters in a passphrase - * must be between ASCII 32-126 (decimal). - */ - int begin(const char* ssid, const char *passphrase); /* Wait for Wifi connection to reach a result * returns the status reached or disconnect if STA is off @@ -151,6 +148,20 @@ public: */ char* SSID(); + /* + * Return the current bssid / mac associated with the network if configured + * + * return: bssid string + */ + uint8_t * BSSID(void); + + /* + * Return the current channel associated with the network + * + * return: channel + */ + int32_t Channel(void); + /* * Return the current network RSSI. Note: this is just a stub, there is no way to * get the RSSI in the Espressif SDK yet. @@ -194,6 +205,42 @@ public: */ int32_t RSSI(uint8_t networkItem); + + /** + * return MAC / BSSID of scanned wifi + * @param networkItem specify from which network item want to get the information + * @return uint8_t * to MAC / BSSID of scanned wifi + */ + uint8_t * BSSID(uint8_t networkItem); + + /** + * return Channel of scanned wifi + * @param networkItem specify from which network item want to get the information + * @return uint32_t Channel of scanned wifi + */ + int32_t Channel(uint8_t networkItem); + + /** + * return if the scanned wifi is Hidden (no SSID) + * @param networkItem specify from which network item want to get the information + * @return bool (true == hidden) + */ + bool isHidden(uint8_t networkItem); + + /** + * loads all infos from a scanned wifi in to the ptr parameters + * @param networkItem uint8_t + * @param ssid const char** + * @param encryptionType uint8_t * + * @param RSSI int32_t * + * @param BSSID uint8_t ** + * @param channel int32_t * + * @param isHidden bool * + * @return (true if ok) + */ + bool getNetworkInfo(uint8_t networkItem, const char** ssid, uint8_t * encryptionType, int32_t * RSSI, uint8_t ** BSSID, int32_t * channel, bool * isHidden); + + /* * Return Connection status. * @@ -243,6 +290,9 @@ protected: static void _smartConfigDone(void* result); bool _smartConfigStarted = false; + bool useApMode; + bool useClientMode; + static size_t _scanCount; static void* _scanResult; diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index 3b878020f..de14a0cb5 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -44,6 +44,8 @@ wl_status_t ESP8266WiFiMulti::run(void) { WifiAPlist_t bestNetwork { NULL, NULL }; int bestNetworkDb = INT_MIN; + uint8 bestBSSID[6]; + int32_t bestChannel; // WiFi.scanNetworks will return the number of networks found int8_t n = WiFi.scanNetworks(); @@ -56,9 +58,16 @@ wl_status_t ESP8266WiFiMulti::run(void) { } else { DEBUG_WIFI_MULTI("[WIFI] %d networks found\n", n); for(int8_t i = 0; i < n; ++i) { - const char * ssid_scan = WiFi.SSID(i); - int32_t rssi_scan = WiFi.RSSI(i); - uint8_t sec_scan = WiFi.encryptionType(i); + + const char * ssid_scan; + int32_t rssi_scan; + uint8_t sec_scan; + uint8_t * BSSID_scan; + int32_t chan_scan; + bool hidden_scan; + + 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++) { @@ -69,7 +78,9 @@ wl_status_t ESP8266WiFiMulti::run(void) { 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; @@ -82,7 +93,7 @@ wl_status_t ESP8266WiFiMulti::run(void) { DEBUG_WIFI_MULTI(" "); } - DEBUG_WIFI_MULTI(" %d: %s (%d) %c\n", i, ssid_scan, rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*'); + 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, rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*'); delay(0); } } @@ -91,9 +102,9 @@ wl_status_t ESP8266WiFiMulti::run(void) { delay(0); if(bestNetwork.ssid) { - DEBUG_WIFI_MULTI("[WIFI] Connecting SSID: %s (%d)\n", bestNetwork.ssid, bestNetworkDb); + 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); - WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase); + WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); status = WiFi.status(); // wait for connection or fail @@ -103,12 +114,16 @@ wl_status_t ESP8266WiFiMulti::run(void) { } 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");