1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-25 20:02:37 +03:00

Redesign ESP8266WiFiMulti.[cpp|h]

Fixed critical issues WiFiMulti library:
- WiFi scan timeout implemented to prevent endless connect loop
- Fallback implemented on WiFi connect failure to prevent endless loop
- Fast WiFi connection at startup
- Improved debug prints
- Doxygen added
- Code maturing
- Example update

Make functions not related to ESP8266WiFiMulti class static
Revert static functions startScan and printWiFiScan()
Use PolledTimeout.h to protect while loops
Move static functions beginning of the file
Add connect timeout to example
This commit is contained in:
Erriez 2020-09-30 21:44:42 +02:00
parent cc042b99d1
commit fceb390a1a
3 changed files with 626 additions and 349 deletions

View File

@ -1,33 +1,49 @@
/*
This sketch trys to Connect to the best AP based on a given list
This sketch shows how to use multiple WiFi networks.
In this example, ESP8266 works in AP mode.
It demonstrates:
- Fast connect to previous WiFi network at startup
- Registering multiple networks (at least 1)
- Connect to WiFi with strongest signal (RSSI)
- Fall back to connect to next WiFi when a connection failed or lost
To enable debugging output, select in the Arduino iDE:
- Tools | Debug Port: Serial
- Tools | Debug Level: WiFi
*/
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti wifiMulti;
// WiFi connect timeout per AP. Increase when connecting takes longer.
const uint32_t connectTimeoutMs = 5000;
void setup() {
Serial.begin(115200);
Serial.println("\nESP8266 Multi WiFi example");
// Set WiFi to station mode
WiFi.mode(WIFI_STA);
// Register multi WiFi networks
wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1");
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2");
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");
Serial.println("Connecting Wifi...");
if (wifiMulti.run() == WL_CONNECTED) {
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
// More is possible
}
void loop() {
if (wifiMulti.run() != WL_CONNECTED) {
// Maintain WiFi connection
if (wifiMulti.run(connectTimeoutMs) == WL_CONNECTED) {
Serial.print("WiFi connected: ");
Serial.print(WiFi.SSID());
Serial.print(" ");
Serial.println(WiFi.localIP());
} else {
Serial.println("WiFi not connected!");
delay(1000);
}
delay(1000);
}

View File

@ -1,267 +1,512 @@
/**
*
* @file ESP8266WiFiMulti.cpp
* @date 16.05.2015
* @author Markus Sattler
*
* Copyright (c) 2015 Markus Sattler. All rights reserved.
* This file is part of the esp8266 core for Arduino environment.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "ESP8266WiFiMulti.h"
#include <limits.h>
#include <string.h>
ESP8266WiFiMulti::ESP8266WiFiMulti() {
}
ESP8266WiFiMulti::~ESP8266WiFiMulti() {
APlistClean();
}
bool ESP8266WiFiMulti::addAP(const char* ssid, const char *passphrase) {
return APlistAdd(ssid, passphrase);
}
void ESP8266WiFiMulti::cleanAPlist(void) {
APlistClean();
}
bool ESP8266WiFiMulti::existsAP(const char* ssid, const char *passphrase) {
return APlistExists(ssid, passphrase);
}
wl_status_t ESP8266WiFiMulti::run(uint32_t connectTimeoutMs) {
wl_status_t status = WiFi.status();
if(status == WL_DISCONNECTED || status == WL_NO_SSID_AVAIL || status == WL_IDLE_STATUS || status == WL_CONNECT_FAILED) {
int8_t scanResult = WiFi.scanComplete();
if(scanResult == WIFI_SCAN_RUNNING) {
// scan is running, do nothing yet
status = WL_NO_SSID_AVAIL;
return status;
}
if(scanResult == 0) {
// scan done, no ssids found. Start another scan.
DEBUG_WIFI_MULTI("[WIFI] scan done\n");
DEBUG_WIFI_MULTI("[WIFI] no networks found\n");
WiFi.scanDelete();
DEBUG_WIFI_MULTI("\n\n");
delay(0);
WiFi.disconnect();
DEBUG_WIFI_MULTI("[WIFI] start scan\n");
// scan wifi async mode
WiFi.scanNetworks(true);
return status;
}
if(scanResult > 0) {
// scan done, analyze
WifiAPEntry bestNetwork { NULL, NULL };
int bestNetworkDb = INT_MIN;
uint8 bestBSSID[6];
int32_t bestChannel;
DEBUG_WIFI_MULTI("[WIFI] scan done\n");
delay(0);
DEBUG_WIFI_MULTI("[WIFI] %d networks found\n", scanResult);
for(int8_t i = 0; i < scanResult; ++i) {
String 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(auto entry : APlist) {
if(ssid_scan == entry.ssid) { // SSID match
known = true;
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;
bestNetwork = entry;
memcpy((void*) &bestBSSID, (void*) BSSID_scan, sizeof(bestBSSID));
}
}
break;
}
}
if(known) {
DEBUG_WIFI_MULTI(" ---> ");
} else {
DEBUG_WIFI_MULTI(" ");
}
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.c_str(), rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*');
delay(0);
}
// clean up ram
WiFi.scanDelete();
DEBUG_WIFI_MULTI("\n\n");
delay(0);
if(bestNetwork.ssid) {
DEBUG_WIFI_MULTI("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channel: %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, bestChannel, bestBSSID);
status = WiFi.status();
auto startTime = millis();
// wait for connection, fail, or timeout
while(status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED && (millis() - startTime) <= connectTimeoutMs) {
delay(10);
status = WiFi.status();
}
#ifdef DEBUG_ESP_WIFI
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().c_str());
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 Failed AP not found.\n");
break;
case WL_CONNECT_FAILED:
DEBUG_WIFI_MULTI("[WIFI] Connecting Failed.\n");
break;
default:
DEBUG_WIFI_MULTI("[WIFI] Connecting Failed (%d).\n", status);
break;
}
#endif
} else {
DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n");
}
return status;
}
// scan failed, or some other condition not handled above. Start another scan.
DEBUG_WIFI_MULTI("[WIFI] delete old wifi config...\n");
WiFi.disconnect();
DEBUG_WIFI_MULTI("[WIFI] start scan\n");
// scan wifi async mode
WiFi.scanNetworks(true);
}
return status;
}
// ##################################################################################
bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) {
WifiAPEntry newAP;
if(!ssid || *ssid == 0x00 || strlen(ssid) > 32) {
// fail SSID too long or missing!
DEBUG_WIFI_MULTI("[WIFI][APlistAdd] no ssid or ssid too long\n");
return false;
}
//for passphrase, max is 63 ascii + null. For psk, 64hex + null.
if(passphrase && strlen(passphrase) > 64) {
// fail passphrase too long!
DEBUG_WIFI_MULTI("[WIFI][APlistAdd] passphrase too long\n");
return false;
}
if(APlistExists(ssid, passphrase)) {
DEBUG_WIFI_MULTI("[WIFI][APlistAdd] SSID: %s already exists\n", ssid);
return true;
}
newAP.ssid = strdup(ssid);
if(!newAP.ssid) {
DEBUG_WIFI_MULTI("[WIFI][APlistAdd] fail newAP.ssid == 0\n");
return false;
}
if(passphrase) {
newAP.passphrase = strdup(passphrase);
} else {
newAP.passphrase = strdup("");
}
if(!newAP.passphrase) {
DEBUG_WIFI_MULTI("[WIFI][APlistAdd] fail newAP.passphrase == 0\n");
free(newAP.ssid);
return false;
}
APlist.push_back(newAP);
DEBUG_WIFI_MULTI("[WIFI][APlistAdd] add SSID: %s\n", newAP.ssid);
return true;
}
bool ESP8266WiFiMulti::APlistExists(const char* ssid, const char *passphrase) {
if(!ssid || *ssid == 0x00 || strlen(ssid) > 32) {
// fail SSID too long or missing!
DEBUG_WIFI_MULTI("[WIFI][APlistExists] no ssid or ssid too long\n");
return false;
}
for(auto entry : APlist) {
if(!strcmp(entry.ssid, ssid)) {
if(!passphrase) {
if(!strcmp(entry.passphrase, "")) {
return true;
}
} else {
if(!strcmp(entry.passphrase, passphrase)) {
return true;
}
}
}
}
return false;
}
void ESP8266WiFiMulti::APlistClean(void) {
for(auto entry : APlist) {
if(entry.ssid) {
free(entry.ssid);
}
if(entry.passphrase) {
free(entry.passphrase);
}
}
APlist.clear();
}
/**
*
* @file ESP8266WiFiMulti.cpp
* @date 30.09.2020
* @author Markus Sattler, Erriez
*
* Copyright (c) 2015-2020 Markus Sattler. All rights reserved.
* This file is part of the esp8266 core for Arduino environment.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "PolledTimeout.h"
#include "ESP8266WiFiMulti.h"
#include <limits.h>
#include <string.h>
/**
* @brief Print WiFi status
* @details
* Macro DEBUG_ESP_WIFI and DEBUG_ESP_PORT must be configured
* @param status
* WiFi status
*/
static void printWiFiStatus(wl_status_t status)
{
#ifdef DEBUG_ESP_WIFI
IPAddress ip;
uint8_t *mac;
switch (status) {
case WL_CONNECTED:
ip = WiFi.localIP();
mac = WiFi.BSSID();
DEBUG_WIFI_MULTI("[WIFIM] Connected:\n");
DEBUG_WIFI_MULTI("[WIFIM] SSID: %s\n", WiFi.SSID().c_str());
DEBUG_WIFI_MULTI("[WIFIM] IP: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
DEBUG_WIFI_MULTI("[WIFIM] MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
DEBUG_WIFI_MULTI("[WIFIM] CH: %d\n", WiFi.channel());
DEBUG_WIFI_MULTI("[WIFIM] RSSI: %d\n", WiFi.RSSI());
break;
case WL_NO_SSID_AVAIL:
DEBUG_WIFI_MULTI("[WIFIM] Connecting failed AP not found.\n");
break;
case WL_CONNECT_FAILED:
DEBUG_WIFI_MULTI("[WIFIM] Connecting failed.\n");
break;
default:
DEBUG_WIFI_MULTI("[WIFIM] Connecting failed (%d).\n", status);
break;
}
#else
// Suppress warning unused variable
(void)(status);
#endif
}
/**
* @brief Wait for WiFi connect status change, protected with timeout
* @param connectTimeoutMs
* WiFi connection timeout in ms
* @return
* WiFi connection status
*/
static wl_status_t waitWiFiConnect(uint32_t connectTimeoutMs)
{
wl_status_t status;
// Set WiFi connect timeout
using esp8266::polledTimeout::oneShotMs;
oneShotMs connectTimeout(connectTimeoutMs);
// Wait for WiFi status change or timeout
do {
// Refresh watchdog
delay(0);
// Get WiFi status
status = WiFi.status();
// Check status
if (status == WL_CONNECTED) {
// Connected, print WiFi status
printWiFiStatus(status);
// Return WiFi status
return status;
} else if (status == WL_CONNECT_FAILED) {
DEBUG_WIFI_MULTI("[WIFIM] Connect failed\n");
// Return WiFi connect failed
return WL_CONNECT_FAILED;
}
} while (!connectTimeout);
DEBUG_WIFI_MULTI("[WIFIM] Connect timeout\n");
return WL_CONNECT_FAILED;
}
/**
* @brief Constructor
*/
ESP8266WiFiMulti::ESP8266WiFiMulti() : _firstRun(true)
{
}
/**
* @brief Destructor
*/
ESP8266WiFiMulti::~ESP8266WiFiMulti()
{
// Cleanup memory
APlistClean();
}
/**
* @brief Add Access Point
* @param ssid
* WiFi SSID char array, max 32 characters + NULL character
* @param passphrase
* WiFi password char array, max 63 characters + NULL character
* @retval true
* Success
* @retval false
* Failure
*/
bool ESP8266WiFiMulti::addAP(const char *ssid, const char *passphrase)
{
return APlistAdd(ssid, passphrase);
}
/**
* @brief Remove all Access Points from list
*/
void ESP8266WiFiMulti::cleanAPlist(void)
{
APlistClean();
}
/**
* @brief Check if Access Point exists in list
* @param ssid
* WiFi SSID
* @param passphrase
* WiFi Password
* @retval true
* Success
* @retval false
* Failure
*/
bool ESP8266WiFiMulti::existsAP(const char *ssid, const char *passphrase)
{
return APlistExists(ssid, passphrase);
}
/**
* @brief Keep WiFi connected to Access Point with strongest WiFi signal (RSSI)
* @param connectTimeoutMs
* Timeout in ms per WiFi connection (excluding fixed 5 seconds scan timeout)
* @return
* WiFi status
*/
wl_status_t ESP8266WiFiMulti::run(uint32_t connectTimeoutMs)
{
int8_t scanResult;
wl_status_t status;
// Fast connect to previous WiFi on startup
if (_firstRun) {
_firstRun = false;
// Check if previous WiFi connection saved
if (strlen(WiFi.SSID().c_str())) {
DEBUG_WIFI_MULTI("[WIFIM] Connecting saved WiFi\n");
// Connect to previous saved WiFi
WiFi.begin();
// Wait for status change
status = waitWiFiConnect(connectTimeoutMs);
}
}
// Check connection state
status = WiFi.status();
if (status == WL_CONNECTED) {
// Already connected
return status;
}
// Start WiFi scan
scanResult = startScan();
if (scanResult < 0) {
// No WiFi scan results
return WL_NO_SSID_AVAIL;
}
// Try to connect to multiple WiFi's with strongest signal (RSSI)
return connectWiFiMulti(connectTimeoutMs);
}
/**
* @brief Start WiFi scan
* @retval >0
* Number of detected WiFi SSID's
* @retval 0
* No WiFi connections found
* @retval -2
* WiFi scan failed
*/
int8_t ESP8266WiFiMulti::startScan()
{
int8_t scanResult;
DEBUG_WIFI_MULTI("[WIFIM] Start scan\n");
// Clean previous scan
WiFi.scanDelete();
// Remove previous WiFi SSID/password
WiFi.disconnect();
// Start wifi scan in async mode
WiFi.scanNetworks(true);
// Set WiFi scan timeout
using esp8266::polledTimeout::oneShotMs;
oneShotMs scanTimeout(WIFI_SCAN_TIMEOUT_MS);
// Wait for WiFi scan change or timeout
do {
// Refresh watchdog
delay(0);
// Check scan timeout which may occur when scan does not report completion
if (scanTimeout) {
DEBUG_WIFI_MULTI("[WIFIM] Scan timeout\n");
return WIFI_SCAN_FAILED;
}
// Get scan result
scanResult = WiFi.scanComplete();
} while (scanResult < 0);
// Print WiFi scan result
printWiFiScan();
// Return (positive) number of detected WiFi networks
return scanResult;
}
/**
* @brief Connect to multiple WiFi's
* @param connectTimeoutMs
* WiFi connect timeout in ms
* @return
* WiFi conneciton status
*/
wl_status_t ESP8266WiFiMulti::connectWiFiMulti(uint32_t connectTimeoutMs)
{
int8_t scanResult;
String ssid;
int32_t rssi;
uint8_t encType;
uint8_t *bssid;
int32_t channel;
bool hidden;
// Get scan results
scanResult = WiFi.scanComplete();
// Find known WiFi networks
uint8_t known[_APlist.size()];
uint8_t numNetworks = 0;
for (int8_t i = 0; i < scanResult; i++) {
// Get network information
WiFi.getNetworkInfo(i, ssid, encType, rssi, bssid, channel, hidden);
// Check if the WiFi network contains an entry in AP list
for (auto entry : _APlist) {
// Check SSID
if (ssid == entry.ssid) {
// Known network
known[numNetworks++] = i;
}
}
}
// Sort WiFi networks by RSSI
for (int i = 0; i < numNetworks; i++) {
for (int j = i + 1; j < numNetworks; j++) {
if (WiFi.RSSI(known[j]) > WiFi.RSSI(known[i])) {
int8_t tmp;
// Swap indices
tmp = known[i];
known[i] = known[j];
known[j] = tmp;
}
}
}
// Print sorted indices
DEBUG_WIFI_MULTI("[WIFIM] Sorted indices: ");
for (int8_t i = 0; i < numNetworks; i++) {
DEBUG_WIFI_MULTI("%d ", known[i]);
}
DEBUG_WIFI_MULTI("\n");
// Connect to known WiFi AP's sorted by RSSI
for (int8_t i = 0; i < numNetworks; i++) {
// Get network information
WiFi.getNetworkInfo(known[i], ssid, encType, rssi, bssid, channel, hidden);
for (auto entry : _APlist) {
// Check SSID
if (ssid == entry.ssid) {
DEBUG_WIFI_MULTI("[WIFIM] Connecting %s\n", ssid);
// Connect to WiFi
WiFi.begin(ssid, entry.passphrase, channel, bssid);
// Wait for status change
if (waitWiFiConnect(connectTimeoutMs) == WL_CONNECTED) {
return WL_CONNECTED;
}
}
}
}
DEBUG_WIFI_MULTI("[WIFIM] Could not connect\n", ssid);
// Coult not connect to any WiFi network
return WL_CONNECT_FAILED;
}
// ##################################################################################
/**
* @brief Add WiFi connection to internal AP list
* @param ssid
* WiFi SSID
* @param passphrase
* WiFi Password
* @retval true
* Success
* @retval false
* Failure
*/
bool ESP8266WiFiMulti::APlistAdd(const char *ssid, const char *passphrase)
{
WifiAPEntry newAP;
if (!ssid || (*ssid == 0x00) || (strlen(ssid) > 32)) {
// Fail SSID too long or missing!
DEBUG_WIFI_MULTI("[WIFIM][APlistAdd] No ssid or ssid too long\n");
return false;
}
// For passphrase, max is 63 ascii + null. For psk, 64hex + null.
if (passphrase && (strlen(passphrase) > 64)) {
// fail passphrase too long!
DEBUG_WIFI_MULTI("[WIFIM][APlistAdd] Passphrase too long\n");
return false;
}
if (APlistExists(ssid, passphrase)) {
DEBUG_WIFI_MULTI("[WIFIM][APlistAdd] SSID: %s already exists\n", ssid);
return true;
}
newAP.ssid = strdup(ssid);
if (!newAP.ssid) {
DEBUG_WIFI_MULTI("[WIFIM][APlistAdd] Fail newAP.ssid == 0\n");
return false;
}
if (passphrase) {
newAP.passphrase = strdup(passphrase);
} else {
newAP.passphrase = strdup("");
}
if (!newAP.passphrase) {
DEBUG_WIFI_MULTI("[WIFIM][APlistAdd] Fail newAP.passphrase == 0\n");
free(newAP.ssid);
return false;
}
_APlist.push_back(newAP);
DEBUG_WIFI_MULTI("[WIFIM][APlistAdd] Add SSID: %s\n", newAP.ssid);
return true;
}
/**
* @brief Check if AP exists in list
* @param ssid
* WiFi SSID
* @param passphrase
* WiFi Password
* @return
*/
bool ESP8266WiFiMulti::APlistExists(const char *ssid, const char *passphrase)
{
if (!ssid || (*ssid == 0x00) || (strlen(ssid) > 32)) {
// Fail SSID too long or missing
DEBUG_WIFI_MULTI("[WIFIM][APlistExists] No ssid or ssid too long\n");
return false;
}
for (auto entry : _APlist) {
if (!strcmp(entry.ssid, ssid)) {
if (!passphrase) {
if (!strcmp(entry.passphrase, "")) {
return true;
}
} else {
if (!strcmp(entry.passphrase, passphrase)) {
return true;
}
}
}
}
return false;
}
/**
* @brief Remove all AP's from list
*/
void ESP8266WiFiMulti::APlistClean(void)
{
// Remove all entries from APlist
for (auto entry : _APlist) {
if (entry.ssid) {
free(entry.ssid);
}
if (entry.passphrase) {
free(entry.passphrase);
}
}
_APlist.clear();
}
/**
* @brief Print WiFi scan results
* @details
* Macro DEBUG_ESP_WIFI and DEBUG_ESP_PORT must be configured
*/
void ESP8266WiFiMulti::printWiFiScan()
{
#ifdef DEBUG_ESP_WIFI
String ssid;
int32_t rssi;
uint8_t encryptionType;
uint8_t* bssid;
int32_t channel;
bool hidden;
int8_t scanResult;
scanResult = WiFi.scanComplete();
DEBUG_WIFI_MULTI("[WIFIM] %d networks found:\n", scanResult);
// Print unsorted scan results
for (int8_t i = 0; i < scanResult; i++) {
bool known = false;
WiFi.getNetworkInfo(i, ssid, encryptionType, rssi, bssid, channel, hidden);
for(auto entry : _APlist) {
if(ssid == entry.ssid) {
// SSID match
known = true;
}
}
if (known) {
DEBUG_WIFI_MULTI(" --->");
} else {
DEBUG_WIFI_MULTI(" ");
}
DEBUG_WIFI_MULTI(" %d: [CH %02d] [%02X:%02X:%02X:%02X:%02X:%02X] %ddBm %c %s\n",
i,
channel,
bssid[0], bssid[1], bssid[2],
bssid[3], bssid[4], bssid[5],
rssi,
(encryptionType == ENC_TYPE_NONE) ? ' ' : '*',
ssid.c_str());
delay(0);
}
#endif
}

View File

@ -1,70 +1,86 @@
/**
*
* @file ESP8266WiFiMulti.h
* @date 16.05.2015
* @author Markus Sattler
*
* Copyright (c) 2015 Markus Sattler. All rights reserved.
* This file is part of the esp8266 core for Arduino environment.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef WIFICLIENTMULTI_H_
#define WIFICLIENTMULTI_H_
#include "ESP8266WiFi.h"
#include <vector>
#ifdef DEBUG_ESP_WIFI
#ifdef DEBUG_ESP_PORT
#define DEBUG_WIFI_MULTI(fmt, ...) DEBUG_ESP_PORT.printf_P( (PGM_P)PSTR(fmt), ##__VA_ARGS__ )
#endif
#endif
#ifndef DEBUG_WIFI_MULTI
#define DEBUG_WIFI_MULTI(...) do { (void)0; } while (0)
#endif
struct WifiAPEntry {
char * ssid;
char * passphrase;
};
typedef std::vector<WifiAPEntry> WifiAPlist;
class ESP8266WiFiMulti {
public:
ESP8266WiFiMulti();
~ESP8266WiFiMulti();
bool addAP(const char* ssid, const char *passphrase = NULL);
bool existsAP(const char* ssid, const char *passphrase = NULL);
wl_status_t run(uint32_t connectTimeoutMs=5000);
void cleanAPlist(void);
private:
WifiAPlist APlist;
bool APlistAdd(const char* ssid, const char *passphrase = NULL);
bool APlistExists(const char* ssid, const char *passphrase = NULL);
void APlistClean(void);
};
#endif /* WIFICLIENTMULTI_H_ */
/**
*
* @file ESP8266WiFiMulti.h
* @date 30.09.2020
* @author Markus Sattler, Erriez
*
* Copyright (c) 2015-2020 Markus Sattler. All rights reserved.
* This file is part of the esp8266 core for Arduino environment.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef WIFI_CLIENT_MULTI_H_
#define WIFI_CLIENT_MULTI_H_
#include "ESP8266WiFi.h"
#include <vector>
#ifdef DEBUG_ESP_WIFI
#ifdef DEBUG_ESP_PORT
#define DEBUG_WIFI_MULTI(fmt, ...) DEBUG_ESP_PORT.printf_P( (PGM_P)PSTR(fmt), ##__VA_ARGS__ )
#endif
#endif
#ifndef DEBUG_WIFI_MULTI
#define DEBUG_WIFI_MULTI(...) do { (void)0; } while (0)
#endif
//! Default WiFi connection timeout in ms
#ifndef WIFI_CONNECT_TIMEOUT_MS
#define WIFI_CONNECT_TIMEOUT_MS 5000
#endif
//! Default WiFi scan timeout in ms
#ifndef WIFI_SCAN_TIMEOUT_MS
#define WIFI_SCAN_TIMEOUT_MS 5000
#endif
struct WifiAPEntry {
char *ssid;
char *passphrase;
};
typedef std::vector<WifiAPEntry> WifiAPlist;
class ESP8266WiFiMulti
{
public:
ESP8266WiFiMulti();
~ESP8266WiFiMulti();
bool addAP(const char *ssid, const char *passphrase = NULL);
bool existsAP(const char *ssid, const char *passphrase = NULL);
wl_status_t run(uint32_t connectTimeoutMs=WIFI_CONNECT_TIMEOUT_MS);
void cleanAPlist();
private:
WifiAPlist _APlist;
bool _firstRun;
bool APlistAdd(const char *ssid, const char *passphrase = NULL);
bool APlistExists(const char *ssid, const char *passphrase = NULL);
void APlistClean();
wl_status_t connectWiFiMulti(uint32_t connectTimeoutMs);
int8_t startScan();
void printWiFiScan();
};
#endif // WIFI_CLIENT_MULTI_H_