diff --git a/libraries/WiFiS3/src/WiFi.cpp b/libraries/WiFiS3/src/WiFi.cpp index 249a9ef0..9cb2b5c0 100644 --- a/libraries/WiFiS3/src/WiFi.cpp +++ b/libraries/WiFiS3/src/WiFi.cpp @@ -1,5 +1,7 @@ #include "WiFi.h" +#define WIFI_MAX_BSSID_STRING_LENGTH 17 + using namespace std; /* -------------------------------------------------------------------------- */ @@ -256,6 +258,42 @@ uint8_t* CWifi::macAddress(uint8_t* _mac) { return _mac; } +/* -------------------------------------------------------------------------- */ +void CWifi::_sortAPlist(uint8_t num) { +/* -------------------------------------------------------------------------- */ + for(uint8_t i = 0; i < num; i++) { + for(uint8_t j = i+1; j < num; j++) { + if(access_points[j].rssi > access_points[i].rssi) { + CAccessPoint temp = access_points[i]; + access_points[i] = access_points[j]; + access_points[j] = temp; + } + } + } +} + +static uint8_t Encr2wl_enc(string e) { + if (e == string("open")) { + return ENC_TYPE_NONE; + } else if (e == string("WEP")) { + return ENC_TYPE_WEP; + } else if (e == string("WPA")) { + return ENC_TYPE_WPA; + } else if (e == string("WPA2")) { + return ENC_TYPE_WPA2; + } else if (e == string("WPA+WPA2")) { + return ENC_TYPE_WPA2; + } else if (e == string("WPA2-EAP")) { + return ENC_TYPE_WPA2_ENTERPRISE; + } else if (e == string("WPA2+WPA3")) { + return ENC_TYPE_WPA3; + } else if (e == string("WPA3")) { + return ENC_TYPE_WPA3; + } else { + return ENC_TYPE_UNKNOWN; + } +} + /* -------------------------------------------------------------------------- */ int8_t CWifi::scanNetworks() { /* -------------------------------------------------------------------------- */ @@ -264,30 +302,60 @@ int8_t CWifi::scanNetworks() { modem.avoid_trim_results(); modem.read_using_size(); - access_points.clear(); + memset(access_points,0x00,sizeof(access_points)); + _apsFound = 0; string res; - - vector aps; if(modem.write(string(PROMPT(_WIFISCAN)),res,CMD(_WIFISCAN))) { + char *startAp = (char*)res.c_str(); + char *endAP = strstr(startAp, "\r\n"); + for(; endAP != NULL; startAp = endAP + 2, endAP = strstr(startAp, "\r\n")) { + /* split the modem response in multiple lines and parse once at time. + * The output will be something like: + * SSID | BSSID | RSSI | CHANNEL | SECURITY + */ + *endAP = '\0'; // Replace \r with \0 + + char *token[5]; + uint8_t i = 1; + token[0] = startAp; + for(; i < 5; i++){ + char *endToken = strstr(token[i-1], " | "); + if(endToken == NULL){ + break; + } + memset(endToken, '\0', 3); + token[i] = endToken + 3; + } + + if(i < 5 || strlen(token[0]) == 0 || strlen(token[0]) > WL_SSID_MAX_LENGTH || + strlen(token[1]) != WIFI_MAX_BSSID_STRING_LENGTH || + strlen(token[2]) == 0 || strlen(token[3]) == 0 || strlen(token[4]) == 0){ + /* Skip the row and process the next one */ + continue; + } - split(aps, res, string("\r\n")); - for(uint16_t i = 0; i < aps.size(); i++) { CAccessPoint ap; - vector tokens; - split(tokens, aps[i], string("|")); - if(tokens.size() >= 5) { - ap.ssid = tokens[0]; - ap.bssid = tokens[1]; - macStr2macArray(ap.uint_bssid, ap.bssid.c_str()); - ap.rssi = tokens[2]; - ap.channel = tokens[3]; - ap.encryption_mode = tokens[4]; - access_points.push_back(ap); + strcpy(ap.ssid, token[0]); + macStr2macArray(ap.uint_bssid, token[1]); + ap.rssi = atoi(token[2]); + ap.channel = atoi(token[3]); + ap.encryption_mode = Encr2wl_enc(token[4]); + + // insert in list + if( _apsFound < WIFI_MAX_SSID_COUNT ){ + access_points[_apsFound] = ap; + _apsFound++; + _sortAPlist(_apsFound); + }else{ + if (ap.rssi > access_points[WIFI_MAX_SSID_COUNT-1].rssi){ + access_points[WIFI_MAX_SSID_COUNT-1] = ap; + _sortAPlist(WIFI_MAX_SSID_COUNT); + } } } } - return (int8_t)access_points.size(); + return _apsFound; } /* -------------------------------------------------------------------------- */ @@ -376,8 +444,8 @@ IPAddress CWifi::gatewayIP() { /* -------------------------------------------------------------------------- */ const char* CWifi::SSID(uint8_t networkItem) { /* -------------------------------------------------------------------------- */ - if(networkItem < access_points.size()) { - return access_points[networkItem].ssid.c_str(); + if(networkItem < _apsFound) { + return access_points[networkItem].ssid; } return nullptr; } @@ -385,42 +453,20 @@ const char* CWifi::SSID(uint8_t networkItem) { /* -------------------------------------------------------------------------- */ int32_t CWifi::RSSI(uint8_t networkItem) { /* -------------------------------------------------------------------------- */ - if(networkItem < access_points.size()) { - return atoi(access_points[networkItem].rssi.c_str()); + if(networkItem < _apsFound) { + return access_points[networkItem].rssi; } return -1000; } -static uint8_t Encr2wl_enc(string e) { - if (e == string("open")) { - return ENC_TYPE_NONE; - } else if (e == string("WEP")) { - return ENC_TYPE_WEP; - } else if (e == string("WPA")) { - return ENC_TYPE_WPA; - } else if (e == string("WPA2")) { - return ENC_TYPE_WPA2; - } else if (e == string("WPA+WPA2")) { - return ENC_TYPE_WPA2; - } else if (e == string("WPA2-EAP")) { - return ENC_TYPE_WPA2_ENTERPRISE; - } else if (e == string("WPA2+WPA3")) { - return ENC_TYPE_WPA3; - } else if (e == string("WPA3")) { - return ENC_TYPE_WPA3; - } else { - return ENC_TYPE_UNKNOWN; - } -} - /* -------------------------------------------------------------------------- */ uint8_t CWifi::encryptionType() { /* -------------------------------------------------------------------------- */ scanNetworks(); string myssid(SSID()); - for(unsigned int i = 0; i < access_points.size(); i++) { + for(unsigned int i = 0; i < _apsFound; i++) { if(myssid == access_points[i].ssid) { - return Encr2wl_enc(access_points[i].encryption_mode); + return access_points[i].encryption_mode; } } return ENC_TYPE_UNKNOWN; @@ -429,8 +475,8 @@ uint8_t CWifi::encryptionType() { /* -------------------------------------------------------------------------- */ uint8_t CWifi::encryptionType(uint8_t networkItem) { /* -------------------------------------------------------------------------- */ - if(networkItem < access_points.size()) { - return Encr2wl_enc(access_points[networkItem].encryption_mode); + if(networkItem < _apsFound) { + return access_points[networkItem].encryption_mode; } return 0; } @@ -438,7 +484,7 @@ uint8_t CWifi::encryptionType(uint8_t networkItem) { /* -------------------------------------------------------------------------- */ uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { /* -------------------------------------------------------------------------- */ - if(networkItem < access_points.size()) { + if(networkItem < _apsFound) { for(int i = 0; i < 6; i++) { *(bssid + i) = access_points[networkItem].uint_bssid[i]; } @@ -450,8 +496,8 @@ uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { /* -------------------------------------------------------------------------- */ uint8_t CWifi::channel(uint8_t networkItem) { /* -------------------------------------------------------------------------- */ - if(networkItem < access_points.size()) { - return atoi(access_points[networkItem].channel.c_str()); + if(networkItem < _apsFound) { + return access_points[networkItem].channel; } return 0; } diff --git a/libraries/WiFiS3/src/WiFi.h b/libraries/WiFiS3/src/WiFi.h index 0e2999b7..cfb8bf01 100644 --- a/libraries/WiFiS3/src/WiFi.h +++ b/libraries/WiFiS3/src/WiFi.h @@ -19,24 +19,43 @@ #define WIFI_FIRMWARE_LATEST_VERSION "0.5.2" +#ifndef WIFI_MAX_SSID_COUNT + #define WIFI_MAX_SSID_COUNT 10 +#endif + class CAccessPoint { public: - std::string ssid; - std::string bssid; + CAccessPoint() {} + CAccessPoint(const CAccessPoint &obj) + { + strcpy(ssid, obj.ssid); + rssi = obj.rssi; + channel = obj.channel; + encryption_mode = obj.encryption_mode; + memcpy(uint_bssid, obj.uint_bssid, sizeof(uint_bssid)); + } + CAccessPoint &operator=(const CAccessPoint &obj) { + strcpy(ssid, obj.ssid); + rssi = obj.rssi; + channel = obj.channel; + encryption_mode = obj.encryption_mode; + memcpy(uint_bssid, obj.uint_bssid, sizeof(uint_bssid)); + } + char ssid[WL_SSID_MAX_LENGTH + 1]; // +1 for null terminator uint8_t uint_bssid[6]; - std::string rssi; - std::string channel; - std::string encryption_mode; + int rssi; + uint8_t channel; + uint8_t encryption_mode; }; - - class CWifi { private: void _config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2); + void _sortAPlist(uint8_t num); unsigned long _timeout; - std::vector access_points; + CAccessPoint access_points[WIFI_MAX_SSID_COUNT]; + uint8_t _apsFound = 0; std::string ssid; std::string apssid;