Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sorting of scanned wifi networks #661

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 51 additions & 9 deletions src/network_interfaces/Wippersnapper_AIRLIFT.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include "SPI.h"
#include "WiFiNINA.h"
#include "Wippersnapper.h"
#include <algorithm>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want this here, or moved to be included by WipperSnapper.h or another file (networking.h?) so it's included by all the drivers?

#include <vector>

#define NINAFWVER \
"1.7.7" /*!< min. nina-fw version compatible with this library. */
Expand Down Expand Up @@ -101,10 +103,34 @@ class Wippersnapper_AIRLIFT : public Wippersnapper {
_pass = WS._config.network.pass;
}

/****************************************************************/
/*!
@brief a structure to hold network information for sorting
*/
/****************************************************************/
struct WiFiNetwork {
char ssid[33]; /*!< SSID (Max 32 characters + null terminator */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like SSID is a string in the WiFi library, so we should match the type
https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/src/WiFiScan.h#L48

int rssi; /*!< Received Signal Strength Indicator */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RSSI should be type int32_t to match the WiFi library

};

/*******************************************************************/
/*!
@brief Comparison function to sort by RSSI in descending order
@param a
WiFiNetwork object
@param b
WiFiNetwork object
@returns True if a.rssi > b.rssi
*/
/*******************************************************************/
bool static compareByRSSI(const WiFiNetwork &a, const WiFiNetwork &b) {
return a.rssi > b.rssi;
}

/***********************************************************/
/*!
@brief Performs a scan of local WiFi networks.
@returns True if `_network_ssid` is found, False otherwise.
@brief Performs a scan of local WiFi networks.
@returns True if `_network_ssid` is found, False otherwise.
*/
/***********************************************************/
bool check_valid_ssid() {
Expand All @@ -119,22 +145,38 @@ class Wippersnapper_AIRLIFT : public Wippersnapper {
return false;
}

// Was the network within secrets.json found?
// Dynamically allocate memory for the network list
std::vector<WiFiNetwork> networks(n);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about using a vector/dynamic alloc. here, allowing too many possible networks will increase sort time.

Instead, could you define a global MAX_WIFI_NETWORK macro of 15 possible network options?


// Store the scanned networks in the vector
for (int i = 0; i < n; ++i) {
if (strcmp(_ssid, WiFi.SSID(i)) == 0) {
WS_DEBUG_PRINT("SSID found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
strncpy(networks[i].ssid, WiFi.SSID(i), sizeof(networks[i].ssid) - 1);
networks[i].ssid[sizeof(networks[i].ssid) - 1] =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you switch SSID to a String type, it will be null-terminated during compilation.

'\0'; // Ensure null termination
networks[i].rssi = WiFi.RSSI(i);
}

// Sort the networks by RSSI in descending order
std::sort(networks.begin(), networks.end(), compareByRSSI);

// Was the network within secrets.json found?
for (const auto &network : networks) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we using autotype assignment here? Instead of this overhead, we could iterate until the end of the array

if (strcmp(_ssid, network.ssid) == 0) {
WS_DEBUG_PRINT("SSID (");
WS_DEBUG_PRINT(_ssid);
WS_DEBUG_PRINT(") found! RSSI: ");
WS_DEBUG_PRINTLN(network.rssi);
return true;
}
}

// User-set network not found, print scan results to serial console
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: ");
for (int i = 0; i < n; ++i) {
WS_DEBUG_PRINT(WiFi.SSID(i));
for (const auto &network : networks) {
WS_DEBUG_PRINT(network.ssid);
WS_DEBUG_PRINT(" ");
WS_DEBUG_PRINT(WiFi.RSSI(i));
WS_DEBUG_PRINT(network.rssi);
WS_DEBUG_PRINTLN("dB");
}

Expand Down
57 changes: 49 additions & 8 deletions src/network_interfaces/Wippersnapper_ESP32.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include "WiFiMulti.h"
#include <NetworkClient.h>
#include <NetworkClientSecure.h>
#include <algorithm>
#include <vector>
extern Wippersnapper WS;

/****************************************************************************/
Expand Down Expand Up @@ -90,6 +92,30 @@ class Wippersnapper_ESP32 : public Wippersnapper {
_pass = WS._config.network.pass;
}

/****************************************************************/
/*!
@brief a structure to hold network information for sorting
*/
/****************************************************************/
struct WiFiNetwork {
char ssid[33]; /*!< SSID (Max 32 characters + null terminator */
int rssi; /*!< Received Signal Strength Indicator */
};

/*******************************************************************/
/*!
@brief Comparison function to sort by RSSI in descending order
@param a
WiFiNetwork object
@param b
WiFiNetwork object
@returns True if a.rssi > b.rssi
*/
/*******************************************************************/
bool static compareByRSSI(const WiFiNetwork &a, const WiFiNetwork &b) {
return a.rssi > b.rssi;
}

/***********************************************************/
/*!
@brief Performs a scan of local WiFi networks.
Expand Down Expand Up @@ -120,23 +146,38 @@ class Wippersnapper_ESP32 : public Wippersnapper {
return false;
}

// Was the network within secrets.json found?
// Dynamically allocate memory for the network list
std::vector<WiFiNetwork> networks(n);

// Store the scanned networks in the vector
for (int i = 0; i < n; ++i) {
if (strcmp(_ssid, WiFi.SSID(i).c_str()) == 0) {
strncpy(networks[i].ssid, WiFi.SSID(i).c_str(),
sizeof(networks[i].ssid) - 1);
networks[i].ssid[sizeof(networks[i].ssid) - 1] =
'\0'; // Ensure null termination
networks[i].rssi = WiFi.RSSI(i);
}

// Sort the networks by RSSI in descending order
std::sort(networks.begin(), networks.end(), compareByRSSI);

// Was the network within secrets.json found?
for (const auto &network : networks) {
if (strcmp(_ssid, network.ssid) == 0) {
WS_DEBUG_PRINT("SSID (");
WS_DEBUG_PRINT(_ssid);
WS_DEBUG_PRINT(") found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
WS_DEBUG_PRINTLN(network.rssi);
return true;
}
if (WS._isWiFiMulti) {
// multi network mode
for (int j = 0; j < WS_MAX_ALT_WIFI_NETWORKS; j++) {
if (strcmp(WS._multiNetworks[j].ssid, WiFi.SSID(i).c_str()) == 0) {
if (strcmp(WS._multiNetworks[j].ssid, network.ssid) == 0) {
WS_DEBUG_PRINT("SSID (");
WS_DEBUG_PRINT(WS._multiNetworks[j].ssid);
WS_DEBUG_PRINT(") found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
WS_DEBUG_PRINTLN(network.rssi);
return true;
}
}
Expand All @@ -146,10 +187,10 @@ class Wippersnapper_ESP32 : public Wippersnapper {
// User-set network not found, print scan results to serial console
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: ");
for (int i = 0; i < n; ++i) {
WS_DEBUG_PRINT(WiFi.SSID(i));
for (const auto &network : networks) {
WS_DEBUG_PRINT(network.ssid);
WS_DEBUG_PRINT(" ");
WS_DEBUG_PRINT(WiFi.RSSI(i));
WS_DEBUG_PRINT(network.rssi);
WS_DEBUG_PRINTLN("dB");
}

Expand Down
57 changes: 49 additions & 8 deletions src/network_interfaces/Wippersnapper_ESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "ESP8266WiFi.h"
#include "ESP8266WiFiMulti.h"
#include "Wippersnapper.h"
#include <algorithm>
#include <vector>

/* NOTE - Projects that require "Secure MQTT" (TLS/SSL) also require a new
* SSL certificate every year. If adding Secure MQTT to your ESP8266 project is
Expand Down Expand Up @@ -113,6 +115,30 @@ class Wippersnapper_ESP8266 : public Wippersnapper {
_pass = WS._config.network.pass;
}

/****************************************************************/
/*!
@brief a structure to hold network information for sorting
*/
/****************************************************************/
struct WiFiNetwork {
char ssid[33]; /*!< SSID (Max 32 characters + null terminator */
int rssi; /*!< Received Signal Strength Indicator */
};

/*******************************************************************/
/*!
@brief Comparison function to sort by RSSI in descending order
@param a
WiFiNetwork object
@param b
WiFiNetwork object
@returns True if a.rssi > b.rssi
*/
/*******************************************************************/
bool static compareByRSSI(const WiFiNetwork &a, const WiFiNetwork &b) {
return a.rssi > b.rssi;
}

/***********************************************************/
/*!
@brief Performs a scan of local WiFi networks.
Expand All @@ -133,23 +159,38 @@ class Wippersnapper_ESP8266 : public Wippersnapper {
return false;
}

// Was the network within secrets.json found?
// Dynamically allocate memory for the network list
std::vector<WiFiNetwork> networks(n);

// Store the scanned networks in the vector
for (int i = 0; i < n; ++i) {
if (strcmp(_ssid, WiFi.SSID(i).c_str()) == 0) {
strncpy(networks[i].ssid, WiFi.SSID(i).c_str(),
sizeof(networks[i].ssid) - 1);
networks[i].ssid[sizeof(networks[i].ssid) - 1] =
'\0'; // Ensure null termination
networks[i].rssi = WiFi.RSSI(i);
}

// Sort the networks by RSSI in descending order
std::sort(networks.begin(), networks.end(), compareByRSSI);

// Was the network within secrets.json found?
for (const auto &network : networks) {
if (strcmp(_ssid, network.ssid) == 0) {
WS_DEBUG_PRINT("SSID (");
WS_DEBUG_PRINT(_ssid);
WS_DEBUG_PRINT(") found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
WS_DEBUG_PRINTLN(network.rssi);
return true;
}
if (WS._isWiFiMulti) {
// multi network mode
for (int j = 0; j < WS_MAX_ALT_WIFI_NETWORKS; j++) {
if (strcmp(WS._multiNetworks[j].ssid, WiFi.SSID(i).c_str()) == 0) {
if (strcmp(WS._multiNetworks[j].ssid, network.ssid) == 0) {
WS_DEBUG_PRINT("SSID (");
WS_DEBUG_PRINT(WS._multiNetworks[j].ssid);
WS_DEBUG_PRINT(") found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
WS_DEBUG_PRINTLN(network.rssi);
return true;
}
}
Expand All @@ -159,10 +200,10 @@ class Wippersnapper_ESP8266 : public Wippersnapper {
// User-set network not found, print scan results to serial console
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: ");
for (int i = 0; i < n; ++i) {
WS_DEBUG_PRINT(WiFi.SSID(i));
for (const auto &network : networks) {
WS_DEBUG_PRINT(network.ssid);
WS_DEBUG_PRINT(" ");
WS_DEBUG_PRINT(WiFi.RSSI(i));
WS_DEBUG_PRINT(network.rssi);
WS_DEBUG_PRINTLN("dB");
}

Expand Down
60 changes: 51 additions & 9 deletions src/network_interfaces/Wippersnapper_WIFININA.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <Arduino.h>
#include <SPI.h>
#include <WiFiNINA.h>
#include <algorithm>
#include <vector>

#include "Wippersnapper.h"

Expand Down Expand Up @@ -109,10 +111,34 @@ class Wippersnapper_WIFININA : public Wippersnapper {
strlcpy(WS._config.network.pass, _pass, sizeof(WS._config.network.pass));
}

/****************************************************************/
/*!
@brief a structure to hold network information for sorting
*/
/****************************************************************/
struct WiFiNetwork {
char ssid[33]; /*!< SSID (Max 32 characters + null terminator */
int rssi; /*!< Received Signal Strength Indicator */
};

/*******************************************************************/
/*!
@brief Comparison function to sort by RSSI in descending order
@param a
WiFiNetwork object
@param b
WiFiNetwork object
@returns True if a.rssi > b.rssi
*/
/*******************************************************************/
bool static compareByRSSI(const WiFiNetwork &a, const WiFiNetwork &b) {
return a.rssi > b.rssi;
}

/***********************************************************/
/*!
@brief Performs a scan of local WiFi networks.
@returns True if `_network_ssid` is found, False otherwise.
@brief Performs a scan of local WiFi networks.
@returns True if `_network_ssid` is found, False otherwise.
*/
/***********************************************************/
bool check_valid_ssid() {
Expand All @@ -128,22 +154,38 @@ class Wippersnapper_WIFININA : public Wippersnapper {
return false;
}

// Was the network within secrets.json found?
// Dynamically allocate memory for the network list
std::vector<WiFiNetwork> networks(n);

// Store the scanned networks in the vector
for (int i = 0; i < n; ++i) {
if (strcmp(_ssid, WiFi.SSID(i)) == 0) {
WS_DEBUG_PRINT("SSID found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
strncpy(networks[i].ssid, WiFi.SSID(i), sizeof(networks[i].ssid) - 1);
networks[i].ssid[sizeof(networks[i].ssid) - 1] =
'\0'; // Ensure null termination
networks[i].rssi = WiFi.RSSI(i);
}

// Sort the networks by RSSI in descending order
std::sort(networks.begin(), networks.end(), compareByRSSI);

// Was the network within secrets.json found?
for (const auto &network : networks) {
if (strcmp(_ssid, network.ssid) == 0) {
WS_DEBUG_PRINT("SSID (");
WS_DEBUG_PRINT(_ssid);
WS_DEBUG_PRINT(") found! RSSI: ");
WS_DEBUG_PRINTLN(network.rssi);
return true;
}
}

// User-set network not found, print scan results to serial console
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: ");
for (int i = 0; i < n; ++i) {
WS_DEBUG_PRINT(WiFi.SSID(i));
for (const auto &network : networks) {
WS_DEBUG_PRINT(network.ssid);
WS_DEBUG_PRINT(" ");
WS_DEBUG_PRINT(WiFi.RSSI(i));
WS_DEBUG_PRINT(network.rssi);
WS_DEBUG_PRINTLN("dB");
}

Expand Down
Loading