From e18bdeaaaa799169e6c4a7fdba91d945a0f12bad Mon Sep 17 00:00:00 2001 From: fabik111 Date: Wed, 23 Oct 2024 13:57:24 +0200 Subject: [PATCH 1/3] WiFiS3: make scanNetworks return the first 10 AP with higer RSSI --- libraries/WiFiS3/src/WiFi.cpp | 142 ++++++++++++++++++++++------------ libraries/WiFiS3/src/WiFi.h | 35 +++++++-- 2 files changed, 119 insertions(+), 58 deletions(-) diff --git a/libraries/WiFiS3/src/WiFi.cpp b/libraries/WiFiS3/src/WiFi.cpp index 249a9ef0..8be758fd 100644 --- a/libraries/WiFiS3/src/WiFi.cpp +++ b/libraries/WiFiS3/src/WiFi.cpp @@ -1,5 +1,7 @@ #include "WiFi.h" +#define SSID_MAX_COUNT 12 + 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,56 @@ 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))) { - - split(aps, res, string("\r\n")); - for(uint16_t i = 0; i < aps.size(); i++) { + char *startAp = (char*)res.c_str(); + char *endAP = strstr(startAp, "\r\n"); + for(; endAP != NULL; startAp = endAP, endAP = strstr(startAp, "\r\n")) { 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); + char *token[5]; + *endAP++ = '\0'; // Replace \r with \0 + endAP++; + char *startToken = startAp; + char *endToken = strstr(startAp, " | "); + uint8_t i = 0; + for(; i < 5 && endToken != NULL; i++){ + token[i] = startToken; + *endToken++ = '\0'; + endToken = endToken + 2; + startToken = endToken; + endToken = strstr(startToken, " | "); + if(endToken == NULL){ + token[++i] = startToken; + } + } + + if(i>=5) { + if(strlen(token[0]) > WL_SSID_MAX_LENGTH || strlen(token[1]) != WL_MAX_BSSID_LENGTH){ + continue; + } + 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 < WL_MAX_AP_LIST ){ + access_points[_apsFound] = ap; + _apsFound++; + _sortAPlist(_apsFound); + }else{ + if (ap.rssi > access_points[WL_MAX_AP_LIST-1].rssi){ + access_points[WL_MAX_AP_LIST-1] = ap; + _sortAPlist(WL_MAX_AP_LIST); + } + } } } } - return (int8_t)access_points.size(); + return _apsFound; } /* -------------------------------------------------------------------------- */ @@ -376,8 +440,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 +449,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 +471,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 +480,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 +492,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..22888a73 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" +#define WL_MAX_AP_LIST 10 +#define WL_MAX_BSSID_LENGTH 17 +#define WL_MAX_SSID_LENGHT_S WL_SSID_MAX_LENGTH + 1 // +1 for null terminator + 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_MAX_SSID_LENGHT_S]; 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[WL_MAX_AP_LIST]; + uint8_t _apsFound = 0; std::string ssid; std::string apssid; From 2850297ab0766c4fb59b1b02638b31f1e4df9366 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Wed, 5 Feb 2025 15:42:40 +0100 Subject: [PATCH 2/3] WiFiS3: remove unused define --- libraries/WiFiS3/src/WiFi.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/WiFiS3/src/WiFi.cpp b/libraries/WiFiS3/src/WiFi.cpp index 8be758fd..0ee42a4c 100644 --- a/libraries/WiFiS3/src/WiFi.cpp +++ b/libraries/WiFiS3/src/WiFi.cpp @@ -1,7 +1,5 @@ #include "WiFi.h" -#define SSID_MAX_COUNT 12 - using namespace std; /* -------------------------------------------------------------------------- */ From ec15716f021847999fb79baff31129941f1fb17e Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 27 Feb 2025 12:13:27 +0100 Subject: [PATCH 3/3] WiFiS3: scanNetwors refactor --- libraries/WiFiS3/src/WiFi.cpp | 72 +++++++++++++++++++---------------- libraries/WiFiS3/src/WiFi.h | 10 ++--- 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/libraries/WiFiS3/src/WiFi.cpp b/libraries/WiFiS3/src/WiFi.cpp index 0ee42a4c..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; /* -------------------------------------------------------------------------- */ @@ -306,44 +308,48 @@ int8_t CWifi::scanNetworks() { 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, endAP = strstr(startAp, "\r\n")) { - CAccessPoint ap; + 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]; - *endAP++ = '\0'; // Replace \r with \0 - endAP++; - char *startToken = startAp; - char *endToken = strstr(startAp, " | "); - uint8_t i = 0; - for(; i < 5 && endToken != NULL; i++){ - token[i] = startToken; - *endToken++ = '\0'; - endToken = endToken + 2; - startToken = endToken; - endToken = strstr(startToken, " | "); + uint8_t i = 1; + token[0] = startAp; + for(; i < 5; i++){ + char *endToken = strstr(token[i-1], " | "); if(endToken == NULL){ - token[++i] = startToken; + break; } + memset(endToken, '\0', 3); + token[i] = endToken + 3; } - if(i>=5) { - if(strlen(token[0]) > WL_SSID_MAX_LENGTH || strlen(token[1]) != WL_MAX_BSSID_LENGTH){ - continue; - } - 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 < WL_MAX_AP_LIST ){ - access_points[_apsFound] = ap; - _apsFound++; - _sortAPlist(_apsFound); - }else{ - if (ap.rssi > access_points[WL_MAX_AP_LIST-1].rssi){ - access_points[WL_MAX_AP_LIST-1] = ap; - _sortAPlist(WL_MAX_AP_LIST); - } + 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; + } + + CAccessPoint 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); } } } diff --git a/libraries/WiFiS3/src/WiFi.h b/libraries/WiFiS3/src/WiFi.h index 22888a73..cfb8bf01 100644 --- a/libraries/WiFiS3/src/WiFi.h +++ b/libraries/WiFiS3/src/WiFi.h @@ -19,9 +19,9 @@ #define WIFI_FIRMWARE_LATEST_VERSION "0.5.2" -#define WL_MAX_AP_LIST 10 -#define WL_MAX_BSSID_LENGTH 17 -#define WL_MAX_SSID_LENGHT_S WL_SSID_MAX_LENGTH + 1 // +1 for null terminator +#ifndef WIFI_MAX_SSID_COUNT + #define WIFI_MAX_SSID_COUNT 10 +#endif class CAccessPoint { public: @@ -41,7 +41,7 @@ class CAccessPoint { encryption_mode = obj.encryption_mode; memcpy(uint_bssid, obj.uint_bssid, sizeof(uint_bssid)); } - char ssid[WL_MAX_SSID_LENGHT_S]; + char ssid[WL_SSID_MAX_LENGTH + 1]; // +1 for null terminator uint8_t uint_bssid[6]; int rssi; uint8_t channel; @@ -54,7 +54,7 @@ class CWifi { void _config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2); void _sortAPlist(uint8_t num); unsigned long _timeout; - CAccessPoint access_points[WL_MAX_AP_LIST]; + CAccessPoint access_points[WIFI_MAX_SSID_COUNT]; uint8_t _apsFound = 0; std::string ssid; std::string apssid;