From 108a40acfd3af5fd703b049c9b28dc9dd1a7d131 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 16 May 2015 22:40:53 +0200 Subject: [PATCH] add support for list of AP connections - auto select ssid with best signal - for debugging enable DEBUG_WIFI_MULTI macro and call Serial.setDebugOutput(true); change ESP8266WiFiClass::status() return type to wl_status_t --- libraries/ESP8266WiFi/src/ESP8266WiFi.cpp | 2 +- libraries/ESP8266WiFi/src/ESP8266WiFi.h | 2 +- .../ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 167 ++++++++++++++++++ libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h | 59 +++++++ .../ESP8266WiFi/src/include/wl_definitions.h | 16 +- 5 files changed, 236 insertions(+), 10 deletions(-) create mode 100644 libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp create mode 100644 libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index caf63982c..9915d1bd6 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -336,7 +336,7 @@ uint8_t ESP8266WiFiClass::encryptionType(uint8_t i) return -1; } -uint8_t ESP8266WiFiClass::status() +wl_status_t ESP8266WiFiClass::status() { int status = wifi_station_get_connect_status(); diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/libraries/ESP8266WiFi/src/ESP8266WiFi.h index c98f32b8b..be257d152 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.h @@ -195,7 +195,7 @@ public: * * return: one of the value defined in wl_status_t */ - uint8_t status(); + wl_status_t status(); /* * Resolve the given hostname to an IP address. diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp new file mode 100644 index 000000000..a284be754 --- /dev/null +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -0,0 +1,167 @@ +/** + * + * @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 "ESP8266WiFi.h" +#include "ESP8266WiFiMulti.h" +#include + +ESP8266WiFiMulti::ESP8266WiFiMulti() { +} + +ESP8266WiFiMulti::~ESP8266WiFiMulti() { + APlistClean(); +} + +bool ESP8266WiFiMulti::addAP(const char* ssid, const char *passphrase) { + return APlistAdd(ssid, passphrase); +} + +wl_status_t ESP8266WiFiMulti::run(void) { + + wl_status_t status = WiFi.status(); + if(status == WL_DISCONNECTED || status == WL_NO_SSID_AVAIL || status == WL_IDLE_STATUS || status == WL_CONNECT_FAILED) { + + WifiAPlist_t bestNetwork { NULL, NULL }; + int bestNetworkDb = INT_MIN; + + // WiFi.scanNetworks will return the number of networks found + int8_t n = WiFi.scanNetworks(); + + DEBUG_WIFI_MULTI("[WIFI] scan done\n"); + delay(0); + + if(n <= 0) { + DEBUG_WIFI_MULTI("[WIFI] no networks found\n"); + } else { + DEBUG_WIFI_MULTI("[WIFI] %d networks found\n", n); + for(int8_t i = 0; i < n; ++i) { + const char * ssid_scan = WiFi.SSID(i); + int32_t rssi_scan = WiFi.RSSI(i); + uint8_t sec_scan = WiFi.encryptionType(i); + + bool known = false; + for(uint32_t x = 0; x < APlist.size(); x++) { + WifiAPlist_t entry = APlist[x]; + + if(strcmp(entry.ssid, ssid_scan) == 0) { // 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; + memcpy((void*) &bestNetwork, (void*) &entry, sizeof(bestNetwork)); + } + } + break; + } + } + if(known) { + DEBUG_WIFI_MULTI(" ---> "); + } else { + DEBUG_WIFI_MULTI(" "); + } + + DEBUG_WIFI_MULTI(" %d: %s (%d) %c\n", i, ssid_scan, rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*'); + delay(0); + } + } + + DEBUG_WIFI_MULTI("\n\n"); + delay(0); + + if(bestNetwork.ssid) { + DEBUG_WIFI_MULTI("[WIFI] Connecting SSID: %s (%d)\n", bestNetwork.ssid, bestNetworkDb); + + WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase); + status = WiFi.status(); + + // wait for connection or fail + while(status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED) { + delay(10); + status = WiFi.status(); + } + + switch(status) { + case WL_CONNECTED: + DEBUG_WIFI_MULTI("[WIFI] Connecting Done.\n"); + break; + case WL_NO_SSID_AVAIL: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild AP not found.\n"); + break; + case WL_CONNECT_FAILED: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild.\n"); + break; + default: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild (%d).\n", status); + break; + } + } else { + DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n"); + } + } + return status; +} + +// ################################################################################## + +bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) { + + WifiAPlist_t newAP; + + newAP.ssid = (char*) malloc(strlen(ssid)); + + if(!newAP.ssid) { + return false; + } + + strcpy(newAP.ssid, ssid); + + if(passphrase && *passphrase != 0x00) { + newAP.passphrase = (char*) malloc(strlen(passphrase)); + } + + if(!newAP.passphrase) { + free(newAP.ssid); + return false; + } + + strcpy(newAP.passphrase, passphrase); + + APlist.push_back(newAP); + return true; +} + +void ESP8266WiFiMulti::APlistClean(void) { + for(uint32_t i = 0; i < APlist.size(); i++) { + WifiAPlist_t entry = APlist[i]; + if(entry.ssid) { + free(entry.ssid); + } + if(entry.passphrase) { + free(entry.passphrase); + } + } + APlist.clear(); +} + diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h new file mode 100644 index 000000000..285fca755 --- /dev/null +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h @@ -0,0 +1,59 @@ +/** + * + * @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 + +//#define DEBUG_WIFI_MULTI(...) os_printf( __VA_ARGS__ ) + +#ifndef DEBUG_WIFI_MULTI +#define DEBUG_WIFI_MULTI(...) +#endif + +typedef struct { + char * ssid; + char * passphrase; +} WifiAPlist_t; + +class ESP8266WiFiMulti { + public: + ESP8266WiFiMulti(); + ~ESP8266WiFiMulti(); + + bool addAP(const char* ssid, const char *passphrase = NULL); + + wl_status_t run(void); + + private: + std::vector APlist; + bool APlistAdd(const char* ssid, const char *passphrase = NULL); + void APlistClean(void); + +}; + +#endif /* WIFICLIENTMULTI_H_ */ diff --git a/libraries/ESP8266WiFi/src/include/wl_definitions.h b/libraries/ESP8266WiFi/src/include/wl_definitions.h index a32ba45b2..45bee6764 100644 --- a/libraries/ESP8266WiFi/src/include/wl_definitions.h +++ b/libraries/ESP8266WiFi/src/include/wl_definitions.h @@ -48,14 +48,14 @@ #define WL_MAX_ATTEMPT_CONNECTION 10 typedef enum { - WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library - WL_IDLE_STATUS = 0, - WL_NO_SSID_AVAIL, - WL_SCAN_COMPLETED, - WL_CONNECTED, - WL_CONNECT_FAILED, - WL_CONNECTION_LOST, - WL_DISCONNECTED + WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library + WL_IDLE_STATUS = 0, + WL_NO_SSID_AVAIL = 1, + WL_SCAN_COMPLETED = 2, + WL_CONNECTED = 3, + WL_CONNECT_FAILED = 4, + WL_CONNECTION_LOST = 5, + WL_DISCONNECTED = 6 } wl_status_t; /* Encryption modes */