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

EXPERIMENTAL: Access Portal reporting back successful and unsuccessful connections #27

Open
wants to merge 18 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
324 changes: 303 additions & 21 deletions PersWiFiManager.cpp

Large diffs are not rendered by default.

37 changes: 35 additions & 2 deletions PersWiFiManager.h
Original file line number Diff line number Diff line change
@@ -1,28 +1,45 @@
#ifndef PERSWIFIMANAGER_H
#define PERSWIFIMANAGER_H

#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#elif defined(ESP32)
#include <WiFi.h>
#include <WebServer.h>
#else
#error "Unknown board class"
#endif
#include <DNSServer.h>

#define WIFI_CONNECT_TIMEOUT 30
//#define WIFI_CONNECT_TIMEOUT 30

class PersWiFiManager {

public:

typedef std::function<void(void)> WiFiChangeHandlerFunction;

#if defined(ESP8266)
PersWiFiManager(ESP8266WebServer& s, DNSServer& d);
#elif defined(ESP32)
PersWiFiManager(WebServer& s, DNSServer& d);
#endif

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

void setupWiFiHandlers();

bool begin(const String& ssid = "", const String& pass = "");
bool begin(const String& ssid = "", const String& pass = "", time_t apModeTimeoutSeconds = 300);

void stop();

void resetSettings();

String getApSsid();

String getSsid();

void setApCredentials(const String& apSsid, const String& apPass = "");

void setConnectNonBlock(bool b);
Expand All @@ -31,21 +48,37 @@ class PersWiFiManager {

void startApMode();

void closeAp();

void onConnect(WiFiChangeHandlerFunction fn);

void onAp(WiFiChangeHandlerFunction fn);

void onApClose(WiFiChangeHandlerFunction fn);

private:
#if defined(ESP8266)
ESP8266WebServer * _server;
#elif defined(ESP32)
WebServer * _server;
#endif
DNSServer * _dnsServer;
String _apSsid, _apPass;

bool _connectNonBlock;
unsigned long _connectStartTime;
bool _freshConnectionAttempt;

WiFiChangeHandlerFunction _connectHandler;
WiFiChangeHandlerFunction _apHandler;
WiFiChangeHandlerFunction _apCloseHandler;

String buildReport();

void sendNoCacheHeaders();

time_t _apModeTimeoutMillis;
time_t _apModeStartMillis;
};//class

#endif
Expand Down
222 changes: 117 additions & 105 deletions data/wifi.htm
Original file line number Diff line number Diff line change
@@ -1,108 +1,120 @@
<!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;
function scan(){
if(X) return;
X=new XMLHttpRequest(),wl=document.getElementById('wl');
wl[H]="Scanning...";
X.onreadystatechange=function(){
if (this.readyState==4&&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'));
});
}
};
X.open("GET","wifi/list",true);
X.send();
};
</script>
<style>
input {
padding:5px;
font-size:1em;
width:95%;
filter:invert(100%);
}

body {
text-align:center;
font-family:verdana;
background-color:black;
color:white;
}

a {
color:#1fa3ec;
}

button {
border:0;
border-radius:0.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()">&#x21bb; Scan</button>
<p id='wl'></p>
<form method='post' action='/wifi/connect'>
<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>
<br>
<button onclick="p('Start WPS?','/wifi/wps')">WPS Setup</button>
<br>
<button onclick="p('Start AP mode?','/wifi/ap')">AP Mode</button>
<br>
<button onclick="p('Reboot device?','/wifi/rst')">Reboot</button>
<br>
<a href="javascript:history.back()">Back</a> |
<a href="/">Home</a>
</div>
</body>

<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<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;
function scan(){
if(X) return;
X=new XMLHttpRequest(),wl=document.getElementById('wl');
wl[H]="Scanning...";
X.onreadystatechange=function(){
if (this.readyState==4&&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'));
});
}
};
X.open("GET","wifi/list",true);
X.send();
};
var XC, XU;
function connect(reportOnly) {
if(XC) return;
var rpt=document.getElementById('rpt');
rpt[H]= "Connecting...";
XC= new XMLHttpRequest();
XC.onreadystatechange=function(){
if(this.readyState==4&&this.status==200){
var report=JSON.parse(this.responseText);
XC=0;
if(report.connected){
rpt[H]="Successfully connected to " + report.SSID;
}else if(report.SSID != undefined){
rpt[H]="Could not connect to " + report.SSID;
}else{
rpt[H]="No network configured";
}
}
};
if(reportOnly) {
XC.open("GET","wifi/report",true);
} else {
var ssid = document.getElementById('s').value;
var pass = document.getElementById('p').value;
XC.open("GET",encodeURI("wifi/connect?n=" + ssid + "&p=" + pass),true);
}
XC.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:0.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 id='btns' onclick="scan()">&#x21bb; Scan</button>
<p id='wl'></p>
<form method='post' action='/wifi/connect'>
<input id='s' name='n' length=32 placeholder='SSID'>
<br>
<input id='p' name='p' length=64 type='password' placeholder='password'>
<br><br>
</form>
<button id='btnc' onclick='connect(false)'>Connect</button>
<br><br>
<button id='btnr' onclick="p('Reboot device?','/wifi/rst')">Reboot</button>
<br>
<p id='rpt'></p>
<br>
<a href="javascript:history.back()">Back</a> |<a href="/">Home</a>
</div>
<script>connect(true);</script>
</body>
</html>
2 changes: 1 addition & 1 deletion data/wifi.min.htm
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!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;function scan(){if(X) return;X=new XMLHttpRequest(),wl=document.getElementById('wl');wl[H]="Scanning...";X.onreadystatechange=function(){if (this.readyState==4&&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'));});}};X.open("GET","wifi/list",true);X.send();};</script><style>input{padding:5px;font-size:1em;width:95%;filter:invert(100%);}body{text-align:center;font-family:verdana;background-color:black;color:white;}a{color:#1fa3ec;}button{border:0;border-radius:0.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()">&#x21bb; Scan</button><p id='wl'></p><form method='post' action='/wifi/connect'><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><br><button onclick="p('Start WPS?','/wifi/wps')">WPS Setup</button><br><button onclick="p('Start AP mode?','/wifi/ap')">AP Mode</button><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>
<!DOCTYPE html><html> <head> <meta content="text/html;charset=utf-8" http-equiv="Content-Type"> <meta content="utf-8" http-equiv="encoding"> <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; function scan(){if(X) return; X=new XMLHttpRequest(),wl=document.getElementById('wl'); wl[H]="Scanning..."; X.onreadystatechange=function(){if (this.readyState==4&&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'));});}}; X.open("GET","wifi/list",true); X.send();}; var XC, XU; function connect(reportOnly){if(XC) return; var rpt=document.getElementById('rpt'); rpt[H]="Connecting..."; XC=new XMLHttpRequest(); XC.onreadystatechange=function(){if(this.readyState==4&&this.status==200){var report=JSON.parse(this.responseText); XC=0; if(report.connected){rpt[H]="Successfully connected to " + report.SSID;}else if(report.SSID !=undefined){rpt[H]="Could not connect to " + report.SSID;}else{rpt[H]="No network configured";}}}; if(reportOnly){XC.open("GET","wifi/report",true);}else{var ssid=document.getElementById('s').value; var pass=document.getElementById('p').value; XC.open("GET",encodeURI("wifi/connect?n=" + ssid + "&p=" + pass),true);}XC.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:0.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 id='btns' onclick="scan()">&#x21bb; Scan</button> <p id='wl'></p><form method='post' action='/wifi/connect'> <input id='s' name='n' length=32 placeholder='SSID'> <br><input id='p' name='p' length=64 type='password' placeholder='password'> <br><br></form> <button id='btnc' onclick='connect(false)'>Connect</button> <br><br><button id='btnr' onclick="p('Reboot device?','/wifi/rst')">Reboot</button> <br><p id='rpt'></p><br><a href="javascript:history.back()">Back</a> |<a href="/">Home</a> </div><script>connect(true);</script> </body></html>
32 changes: 28 additions & 4 deletions examples/basic_rest_api/basic_rest_api.ino
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,37 @@

//includes
#include <PersWiFiManager.h>
#include <ArduinoJson.h>
// #include <ArduinoJson.h> // ArduinoJson is a bit of an overkill for this use case
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266SSDP.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <FS.h>
#elif defined(ESP32)
#include <WiFi.h>
#include <ESP32SSDP.h>
#include <WebServer.h>
#include <SPIFFS.h>
#else
#error "Unsupported board class"
#endif
#include <DNSServer.h>

#if defined(ESP8266)
#define DEVICE_NAME "ESP8266 DEVICE"
#elif defined(ESP32)
#define DEVICE_NAME "ESP32 DEVICE"
#endif

//const char *metaRefreshStr = "<head><meta http-equiv=\"refresh\" content=\"1; url=/\" /></head><body><a href=\"/\">redirecting...</a></body>";
const char *metaRefreshStr = "<script>window.location='/'</script><a href='/'>redirecting...</a>";

//server objects
#if defined(ESP8266)
ESP8266WebServer server(80);
#elif defined(ESP32)
WebServer server(80);
#endif
DNSServer dnsServer;
PersWiFiManager persWM(server, dnsServer);

Expand Down Expand Up @@ -95,6 +112,10 @@ void setup() {

//allows serving of files from SPIFFS
SPIFFS.begin();

//reset saved settings, clears WiFi credentials e.g. for testing
//persWM.resetSettings();

persWM.begin();

//serve files from SPIFFS
Expand All @@ -117,6 +138,7 @@ void setup() {
DEBUG_PRINT("y: "+y);
} //if

/*
//build json object of program data
StaticJsonBuffer<200> jsonBuffer;
JsonObject &json = jsonBuffer.createObject();
Expand All @@ -125,6 +147,9 @@ void setup() {

char jsonchar[200];
json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
*/
char jsonchar[200];
sprintf(jsonchar, "{\"x\":%d,\"y\":\"%s\"}", x, y.c_str()); // Easy alternative for ArduinoJson
server.send(200, "application/json", jsonchar);

}); //server.on api
Expand All @@ -138,10 +163,9 @@ void setup() {
SSDP.setHTTPPort(80);
SSDP.setName(DEVICE_NAME);
SSDP.setURL("/");
SSDP.begin();
SSDP.setDeviceType("upnp:rootdevice");
SSDP.begin();

server.begin();
DEBUG_PRINT("setup complete.");
} //void setup

Expand Down
Loading