Skip to content

Commit

Permalink
Merge pull request #26 from Jeroen88/feature/ESP32
Browse files Browse the repository at this point in the history
Add ESP32 support, changed layout of inline HTML, small fixes
  • Loading branch information
r-downing authored Mar 16, 2019
2 parents acd6784 + cfa1f05 commit f8486ec
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 9 deletions.
157 changes: 151 additions & 6 deletions PersWiFiManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,128 @@

#include "PersWiFiManager.h"

#if defined(ESP32)
#include <esp_wifi.h>
#endif

#ifdef WIFI_HTM_PROGMEM
const char wifi_htm[] PROGMEM = R"=====(<!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%;}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('Reboot device?','/wifi/rst')">Reboot</button><br><a href="javascript:history.back()">Back</a> |<a href="/">Home</a></div></body></html>)=====";
const char wifi_htm[] PROGMEM = R"=====(
<!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%;
}
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('Reboot device?','/wifi/rst')">Reboot</button>
<br>
<a href="javascript:history.back()">Back</a> |<a href="/">Home</a>
</div>
</body>
</html>
)=====";
#endif

#if defined(ESP8266)
PersWiFiManager::PersWiFiManager(ESP8266WebServer& s, DNSServer& d) {
#elif defined(ESP32)
PersWiFiManager::PersWiFiManager(WebServer& s, DNSServer& d) {
#endif
_server = &s;
_dnsServer = &d;
_apPass = "";
_freshConnectionAttempt = false;
} //PersWiFiManager

bool PersWiFiManager::attemptConnection(const String& ssid, const String& pass) {
//attempt to connect to wifi
WiFi.mode(WIFI_STA);
if (ssid.length()) {
resetSettings(); // To avoid issues (experience from WiFiManager)
if (pass.length()) WiFi.begin(ssid.c_str(), pass.c_str());
else WiFi.begin(ssid.c_str());
} else {
WiFi.begin();
if((getSsid() == "") && (WiFi.status() != WL_CONNECTED)) { // No saved credentials, so skip trying to connect
_connectStartTime = millis();
_freshConnectionAttempt = true;
return false;
} else {
WiFi.begin();
}
}

//if in nonblock mode, skip this loop
Expand All @@ -45,17 +149,18 @@ void PersWiFiManager::handleWiFi() {
return;
}

//if failed or not connected and time is up
if ((WiFi.status() == WL_CONNECT_FAILED) || ((WiFi.status() != WL_CONNECTED) && ((millis() - _connectStartTime) > (1000 * WIFI_CONNECT_TIMEOUT)))) {
//if failed or no saved SSID or no WiFi credentials were found or not connected and time is up
if ((WiFi.status() == WL_CONNECT_FAILED) || _freshConnectionAttempt || ((WiFi.status() != WL_CONNECTED) && ((millis() - _connectStartTime) > (1000 * WIFI_CONNECT_TIMEOUT)))) {
startApMode();
_connectStartTime = 0; //reset connect start time
_freshConnectionAttempt = false;
}

} //handleWiFi

void PersWiFiManager::startApMode(){
//start AP mode
IPAddress apIP(192, 168, 1, 1);
IPAddress apIP(192, 168, 4, 1);
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
_apPass.length() ? WiFi.softAP(getApSsid().c_str(), _apPass.c_str()) : WiFi.softAP(getApSsid().c_str());
Expand All @@ -67,7 +172,7 @@ void PersWiFiManager::setConnectNonBlock(bool b) {
} //setConnectNonBlock

void PersWiFiManager::setupWiFiHandlers() {
IPAddress apIP(192, 168, 1, 1);
IPAddress apIP(192, 168, 4, 1);
_dnsServer->setErrorReplyCode(DNSReplyCode::NoError);
_dnsServer->start((byte)53, "*", apIP); //used for captive portal in AP mode

Expand All @@ -90,8 +195,13 @@ void PersWiFiManager::setupWiFiHandlers() {
s.reserve(2050);
for (int i = 0; i < n && s.length() < 2000; i++) { //check s.length to limit memory usage
if (ix[i] != -1) {
#if defined(ESP8266)
s += String(i ? "\n" : "") + ((constrain(WiFi.RSSI(ix[i]), -100, -50) + 100) * 2) + ","
+ ((WiFi.encryptionType(ix[i]) == ENC_TYPE_NONE) ? 0 : 1) + "," + WiFi.SSID(ix[i]);
#elif defined(ESP32)
s += String(i ? "\n" : "") + ((constrain(WiFi.RSSI(ix[i]), -100, -50) + 100) * 2) + ","
+ ((WiFi.encryptionType(ix[i]) == WIFI_AUTH_OPEN) ? 0 : 1) + "," + WiFi.SSID(ix[i]);
#endif
}
}

Expand All @@ -114,28 +224,63 @@ void PersWiFiManager::setupWiFiHandlers() {
delay(100);
//ESP.restart();
// Adding Safer Restart method
#if defined(ESP8266)
ESP.wdtDisable();
ESP.reset();
#elif defined(ESP32)
ESP.restart();
#endif
delay(2000);
});

#ifdef WIFI_HTM_PROGMEM
_server->on("/wifi.htm", [&]() {
_server->sendHeader("Cache-Control", " no-cache, no-store, must-revalidate");
_server->sendHeader("Expires", " 0");
_server->send(200, "text/html", wifi_htm);
});
#endif

}//setupWiFiHandlers

bool PersWiFiManager::begin(const String& ssid, const String& pass) {
#if defined(ESP32)
WiFi.mode(WIFI_STA); // ESP32 needs this before setupWiFiHandlers(). Might be good for ESP8266 too?
#endif
setupWiFiHandlers();
return attemptConnection(ssid, pass); //switched order of these two for return
} //begin

void PersWiFiManager::resetSettings() {
#if defined(ESP8266)
WiFi.disconnect();
#elif defined(ESP32)
wifi_mode_t m = WiFi.getMode();
if(!(m & WIFI_MODE_STA)) WiFi.mode(WIFI_STA);
WiFi.disconnect(false, true);
if(!(m & WIFI_MODE_STA)) WiFi.mode(m);
#endif
} // resetSettings

String PersWiFiManager::getApSsid() {
#if defined(ESP8266)
return _apSsid.length() ? _apSsid : "ESP8266";
#elif defined(ESP32)
return _apSsid.length() ? _apSsid : "ESP32";
#endif
} //getApSsid

String PersWiFiManager::getSsid() {
#if defined(ESP8266)
return WiFi.SSID();
#elif defined(ESP32)
wifi_config_t conf;
esp_wifi_get_config(WIFI_IF_STA, &conf); // load wifi settings to struct comf
const char *SSID = reinterpret_cast<const char*>(conf.sta.ssid);
return String(SSID);
#endif
} //getSsid

void PersWiFiManager::setApCredentials(const String& apSsid, const String& apPass) {
if (apSsid.length()) _apSsid = apSsid;
if (apPass.length() >= 8) _apPass = apPass;
Expand Down
20 changes: 20 additions & 0 deletions PersWiFiManager.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
#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
Expand All @@ -13,16 +20,24 @@ class PersWiFiManager {

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 = "");

void resetSettings();

String getApSsid();

String getSsid();

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

void setConnectNonBlock(bool b);
Expand All @@ -36,12 +51,17 @@ class PersWiFiManager {
void onAp(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;
Expand Down
24 changes: 22 additions & 2 deletions examples/basic_rest_api/basic_rest_api.ino
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,36 @@
//includes
#include <PersWiFiManager.h>
#include <ArduinoJson.h>
#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 @@ -96,6 +113,9 @@ void setup() {
//allows serving of files from SPIFFS
SPIFFS.begin();
persWM.begin();
//reset saved settings, clears WiFi credentials e.g. for testing
//persWM.resetSettings();


//serve files from SPIFFS
server.onNotFound([]() {
Expand Down Expand Up @@ -138,8 +158,8 @@ 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.");
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ sentence=Persistent WiFi Manager
paragraph=A non-blocking, persistant wifi manager for ESP8266 that allows network changes at any time
category=Communication
url=http://ryandowning.net/PersWiFiManager/
architectures=esp8266
architectures=esp8266,esp32

0 comments on commit f8486ec

Please sign in to comment.