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 6 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
2 changes: 2 additions & 0 deletions src/Wippersnapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

// Cpp STD
#include <vector>
#include <algorithm>

// Nanopb dependencies
#include <nanopb/pb_common.h>
Expand Down Expand Up @@ -215,6 +216,7 @@ typedef enum {
} fsm_net_t;

#define WS_WDT_TIMEOUT 60000 ///< WDT timeout
#define WS_MAX_SORTED_NETWORKS 15 ///< Maximum number of networks to sort
#define WS_MAX_ALT_WIFI_NETWORKS 3 ///< Maximum number of alternative networks
/* MQTT Configuration */
#define WS_KEEPALIVE_INTERVAL_MS \
Expand Down
45 changes: 42 additions & 3 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 {
String ssid[32]; /*!< SSID (Max 32 characters + null terminator */
int32_t rssi = -99; /*!< 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 @@ -119,10 +145,23 @@ class Wippersnapper_AIRLIFT : public Wippersnapper {
return false;
}

WiFiNetwork networks[WS_MAX_SORTED_NETWORKS];

// Store the scanned networks in the array
for (int i = 0; i < n && i < WS_MAX_SORTED_NETWORKS; ++i) {
strncpy(networks[i].ssid, WiFi.SSID(i), sizeof(networks[i].ssid));
networks[i].rssi = WiFi.RSSI(i);
}

// Sort the networks by RSSI in descending order
std::sort(networks, networks + std::min(n, WS_MAX_SORTED_NETWORKS), compareByRSSI);

// Was the network within secrets.json found?
for (int i = 0; i < n; ++i) {
if (strcmp(_ssid, WiFi.SSID(i)) == 0) {
WS_DEBUG_PRINT("SSID found! RSSI: ");
WS_DEBUG_PRINT("SSID (");
WS_DEBUG_PRINT(_ssid);
WS_DEBUG_PRINT(") found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
return true;
}
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
Loading