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

Multi access point functionality #1

Open
wants to merge 9 commits into
base: master
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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
PersWiFiManager.ino
data/*
!data/wifi*
!data/wifi*
.pioenvs/*
.vscode/*
platformio.ini
532 changes: 490 additions & 42 deletions PersWiFiManager.cpp

Large diffs are not rendered by default.

41 changes: 40 additions & 1 deletion PersWiFiManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,23 @@
#include <Ticker.h>

//#define WIFI_HTM_PROGMEM
#define WIFI_HTM_GZ_PROGMEM
//#define WIFI_HTM_GZ_PROGMEM
//#define WIFI_HTM2_PROGMEM
#define WIFI_HTM2_GZ_PROGMEM

#define WIFI_CONNECT_TIMEOUT 30
#define WIFI_RETRY_TIME 60
#define PERSWIFI_DEBUG 1
//#define DEBUG_WIFI_MULTI(fmt, ...) if(Serial) Serial.printf( (PGM_P)PSTR(fmt), ##__VA_ARGS__ )
#define DEBUG_WIFI_MULTI(fmt,...)

struct persWifiAPEntry {
char * ssid;
char * passphrase;
unsigned long ID;
};

typedef std::vector<persWifiAPEntry> persWifiAPlist;

class PersWiFiManager
{
Expand All @@ -24,6 +38,7 @@ class PersWiFiManager
typedef std::function<void(void)> WiFiChangeHandlerFunction;

PersWiFiManager(AsyncWebServer &s, AsyncDNSServer &d, const fs::FS& fs = SPIFFS);
~PersWiFiManager();

bool attemptConnection(const String &ssid = "", const String &pass = "");

Expand All @@ -45,8 +60,26 @@ class PersWiFiManager

void onConnect(WiFiChangeHandlerFunction fn);

void onDisConnect(WiFiChangeHandlerFunction fn);

void onAp(WiFiChangeHandlerFunction fn);

void onStore(WiFiChangeHandlerFunction fn);

bool addAP(const char* ssid, const char *passphrase = NULL);
bool removeAP(const char* ssid);
bool existsAP(const char* ssid, const char *passphrase = NULL);
persWifiAPlist getAPlist();
wl_status_t GetStatus();


private:
persWifiAPlist APlist;
bool APlistAdd(const char* ssid, const char *passphrase = NULL);
bool APlistRemove(const char* ssid);
bool APlistExists(const char* ssid, const char *passphrase = NULL);
void APlistClean(void);

private:

Ticker _tkWiFiH;
Expand All @@ -57,10 +90,16 @@ class PersWiFiManager
String _fsUser = "admin", _fsPass = "password";

bool _connectNonBlock;
bool _autoReconnect;
bool _scanSorted;
unsigned long _connectStartTime;
unsigned long _scanTime;


WiFiChangeHandlerFunction _connectHandler;
WiFiChangeHandlerFunction _disconnectHandler;
WiFiChangeHandlerFunction _apHandler;
WiFiChangeHandlerFunction _storeHandler;

}; //class

Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,21 @@ This Persistent WiFi Manager provides a WiFi Settings web interface for ESP8266-
This library and UI was inspired by tzapu's [WiFiManager library](https://github.com/tzapu/WiFiManager). The main difference is that it allows the program to continue functioning normally, even in AP mode. It is also more memory efficient, as it does not have to dynamically build the page, and can serve it from SPIFFS rather than PROGMEM.

[Full Documentation](http://ryandowning.net/PersWiFiManager)

## Info on multiple stored access points

Added event handlers :

* onDisConnect : is called when loosing a connection. This can be used to store the credentials of the last connection or trigger the reconnect to a different AP
* onStore : is triggered by a succesfull connection to an AP, to store the current credentials in a safe storage. (in the demo it use AESLIB to encrypt the credential before storing them in a json file)

Added functions:

(similar to the ESP8266 [wifiMulti](https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/station-examples.html) AP handling but async )

* bool addAP(const char* ssid, const char *passphrase = NULL) : adds AP credentials to the AP-list which will be used to try to connect to
* bool removeAP(const char* ssid) : removes an AP from the AP-list
* bool existsAP(const char* ssid, const char *passphrase = NULL) : checks if the AP exists in the AP-list with the same credentials
* persWifiAPlist getAPlist() : returns the current list of AP's
* wl_status_t GetStatus(): returns the status of the current connection.

41 changes: 41 additions & 0 deletions data/wifimulti.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>

<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<title>ESP WiFi</title>
<script>function g(i){return document.getElementById(i)};function p(t,l){if(confirm(t))window.location=l};function E(s){return document.createElement(s)};var S="setAttribute",A="appendChild",H="innerHTML",X,wl,R,al;function scan(){if(X)return;X=new XMLHttpRequest(),wl=document.getElementById('wl');wl[H]="Scanning...";X.onreadystatechange=function(){if(this.readyState==4){if(this.status==200){X=0;wl[H]="";this.responseText.split('\n').forEach(function(e){let t=e.split(','),s=t.slice(2).join(',');var d=E('div'),i=E('a'),c=E('a');i[S]('class','s');c[S]('class','q');i.onclick=function(){g('s').value=s;g('p').focus()};i[A](document.createTextNode(s));c[H]=t[0]+"%"+(parseInt(t[1])?"\uD83D\uDD12":"\u26A0");wl[A](i);wl[A](c);wl[A](document.createElement('br'))})}
else if(this.status==202){X=0;wl[H]=this.responseText;setInterval(scan(),3000)}}};X.open("GET","wifi/list",!0);X.send()};function getAPs(){if(R)return;R=new XMLHttpRequest();al=document.getElementById('al');al[H]="Retrieving Access points...";R.onreadystatechange=function(){if(this.readyState==4&&this.status==200){document.getElementById("i").style.display="block";document.getElementById("st").style.display="block";document.getElementById("a").style.display="none";R=0;al[H]="";this.responseText.split('\n').forEach(function(e){var d=E('div'),c=E('a');c[S]('class','s');c.onclick=function(){g('i').value=e};c[A](document.createTextNode(e));al[A](c);al[A](document.createElement('br'))})}};R.open('GET','wifi/ap',!0);R.send()}</script>
<style>Input{padding:5px;font-size:1em;width:95%}body{text-align:center;font-family:verdana;background-color:black;color:white}a{color:#1fa3ec}button{border:0;border-radius:.3em;background-color:#1fa3ec;color:#fff;line-height:2.4em;font-size:1.2em;width:100%;display:block}.q{float:right}.s{display:inline-block;width:14em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#wl{line-height:1.5em}</style>
</head>

<body>
<div style='text-align:left;display:inline-block;width:320px;padding:5px'>
<button onclick="scan()">Scan</button>
<p id='wl'></p>
<form method='post' action='/wifi/connect' onsubmit="getAPs()">
<input id='s' name='n' length=32 placeholder='SSID'>
<br>
<input id='p' name='p' length=64 type='password' placeholder='password'>
<br>
<br>
<button type='submit'>Connect</button>
</form>
<br>
<p id='al'></p>
<button id='a' onclick="getAPs()">APs</button>
<form method='post' action='/wifi/store'>
<input id='i' name='i' length=7 placeholder='SSIDx' style="display:none;">
<br>
<button id='st' style="display:none;" type='submit'>Store</button>
</form>
<br>
<br>
<button onclick="p('Reboot device?','/wifi/rst')">Reboot</button>
<br>
<a href="javascript:history.back()">Back</a> |
<a href="/">Home</a>
</div>
</body>

</html>
2 changes: 2 additions & 0 deletions data/wifimulti.min.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<!doctypehtml><meta content="width=device-width,initial-scale=1,user-scalable=no"name=viewport><title>ESP WiFi</title><script>function g(i){return document.getElementById(i)};function p(t,l){if(confirm(t))window.location=l};function E(s){return document.createElement(s)};var S="setAttribute",A="appendChild",H="innerHTML",X,wl,R,al;function scan(){if(X)return;X=new XMLHttpRequest(),wl=document.getElementById('wl');wl[H]="Scanning...";X.onreadystatechange=function(){if(this.readyState==4){if(this.status==200){X=0;wl[H]="";this.responseText.split('\n').forEach(function(e){let t=e.split(','),s=t.slice(2).join(',');var d=E('div'),i=E('a'),c=E('a');i[S]('class','s');c[S]('class','q');i.onclick=function(){g('s').value=s;g('p').focus()};i[A](document.createTextNode(s));c[H]=t[0]+"%"+(parseInt(t[1])?"\uD83D\uDD12":"\u26A0");wl[A](i);wl[A](c);wl[A](document.createElement('br'))})}
else if(this.status==202){X=0;wl[H]=this.responseText;setInterval(scan(),3000)}}};X.open("GET","wifi/list",!0);X.send()};function getAPs(){if(R)return;R=new XMLHttpRequest();al=document.getElementById('al');al[H]="Retrieving Access points...";R.onreadystatechange=function(){if(this.readyState==4&&this.status==200){document.getElementById("i").style.display="block";document.getElementById("st").style.display="block";document.getElementById("a").style.display="none";R=0;al[H]="";this.responseText.split('\n').forEach(function(e){var d=E('div'),c=E('a');c[S]('class','s');c.onclick=function(){g('i').value=e};c[A](document.createTextNode(e));al[A](c);al[A](document.createElement('br'))})}};R.open('GET','wifi/ap',!0);R.send()}</script><style>Input{padding:5px;font-size:1em;width:95%}body{text-align:center;font-family:verdana;background-color:#000;color:#fff}a{color:#1fa3ec}button{border:0;border-radius:.3em;background-color:#1fa3ec;color:#fff;line-height:2.4em;font-size:1.2em;width:100%;display:block}.q{float:right}.s{display:inline-block;width:14em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#wl{line-height:1.5em}</style><div style=text-align:left;display:inline-block;width:320px;padding:5px><button onclick=scan()>Scan</button><p id=wl><form action=/wifi/connect method=post onsubmit=getAPs()><input id=s length=32 name=n placeholder=SSID><br><input id=p length=64 name=p placeholder=password type=password><br><br><button type=submit>Connect</button></form><br><p id=al></p><button onclick=getAPs() id=a>APs</button><form action=/wifi/store method=post><input id=i length=7 name=i placeholder=SSIDx style=display:none><br><button id=st style=display:none type=submit>Store</button></form><br><br><button onclick='p("Reboot device?","/wifi/rst")'>Reboot</button><br><a href=javascript:history.back()>Back</a>|<a href=/ >Home</a></div>
Loading