Compare commits

..
37 Commits
Author SHA1 Message Date
Alex Tudorache 99f37db88e Merge branch 'master' of https://github.com/tzapu/WiFiManager 2016-01-04 16:48:33 +02:00
Alex Tudorache 2ad6d0897c changed category
fixed keywords
2016-01-04 16:48:17 +02:00
Alex Tudorache caa808c265 changed category 2016-01-04 16:42:35 +02:00
Alex Tudorache d8683d9f50 updated to 0.5 2016-01-04 16:32:32 +02:00
Alex Tudorache 1a58897ab4 added some more thanks 2016-01-02 09:49:47 +02:00
tzapu 7ba1f3ada5 Merge pull request #41 from domonetic/patch-4
add library.json
thank you
2016-01-02 09:44:44 +02:00
tzapu e6cbb8fa05 Merge pull request #40 from domonetic/patch-5
add library.properties
THANK YOU, you are amazing
2016-01-02 09:44:00 +02:00
tzapu 81d48d7612 Merge pull request #39 from domonetic/patch-3
add keywords.txt 
THANK YOU GUYS
2016-01-02 09:42:41 +02:00
Maximiliano Duarte ab23ca7b18 change category 2015-12-31 09:53:35 -03:00
Maximiliano Duarte 94eef239eb change space for tabs 2015-12-30 12:49:53 -03:00
Maximiliano Duarte 30f5a220ce add library.properties
to standardize the library and appear in Library Manager
2015-12-30 12:16:42 -03:00
Maximiliano Duarte 9350856d33 add library.json
to standardize the library and appear in Library Manager
2015-12-30 12:14:22 -03:00
Maximiliano Duarte a69c5e2b93 add keywords.txt
to standardize the library and appear in Library Manager
2015-12-30 12:12:57 -03:00
Alex Tudorache 777c2fab1b presentation tweaks 2015-12-28 18:07:02 +02:00
Alex Tudorache ec1a55bffc new padlock icon 2015-12-28 14:32:36 +02:00
Alex Tudorache ffdc117a6e added AP quality
added padlock for secured networks
moved more stuff to PROGMEM
2015-12-27 11:17:29 +02:00
Alex Tudorache 44419e10a2 moved most stuff to PROGMEM
added warning for invalid password
2015-12-23 18:15:58 +02:00
Alex Tudorache a0237d80f6 updated readme 2015-12-19 21:25:06 +02:00
tzapu 41990177ce Merge pull request #23 from j0hnlittle/master
Added password option to AP wifiManager.autoConnect("apname","password")
thank you j0hnlittle
2015-12-19 13:41:25 +02:00
Alex Tudorache acc6624406 information about access point callback 2015-12-17 19:14:50 +02:00
John Little c2f11e8bd9 Synced my changes with tzapu's 2015-12-17 14:59:56 +00:00
John Little c44d3643a8 Added password option to AP wifiManager.autoConnect("apname","password") 2015-12-17 14:05:20 +00:00
Alex Tudorache e9dd81d163 cleanup 2015-12-17 15:30:19 +02:00
Alex Tudorache 6ff9712b65 added config mode callback 2015-12-17 09:25:09 +02:00
tzapu f9b6db797f Merge pull request #20 from alltheblinkythings/for-upstream
Allocate the DNSServer and ESP8266WebServer on the heap at begin() time and free them when autoConnect() terminates. thanks @alltheblinkythings ;)
2015-12-15 18:25:22 +02:00
Christopher Pascoe d3274bc5b9 Allocate the DNSServer and ESP8266WebServer on the heap at begin() time and free them when autoConnect() terminates.
This reduces the likelihood of a stack overflow when WifiManager is instantiated in setup(),
and lowers memory usage (after wifi is connected) when it's instantiated globally.
2015-12-13 16:03:13 -08:00
Alex Tudorache e36f7959c7 examples updated 2015-12-09 09:37:23 +02:00
Alex Tudorache 614516596b readme update 2015-12-09 09:26:35 +02:00
Alex Tudorache e09c5803b2 even more readme 2015-12-08 08:33:05 +02:00
Alex Tudorache a95000e91a more readme updates 2015-12-08 08:32:18 +02:00
Alex Tudorache 070448db4e updated Readme 2015-12-08 08:30:45 +02:00
Alex Tudorache 659df9cb27 removed EEPROM dependencies
removed need to reset on save
2015-12-05 09:52:32 +02:00
Alex Tudorache c03570faba fixed setTimeout 2015-12-02 17:38:52 +02:00
Alex Tudorache 3d550ab78f Merge branch 'master' of https://github.com/tzapu/WiFiManager
# Conflicts:
#	README.md
2015-11-19 09:54:43 +02:00
Alex Tudorache ec23ed45b0 added staging version notice 2015-11-19 09:53:29 +02:00
Alex Tudorache faed661d25 added staging version notice 2015-11-19 09:52:49 +02:00
Alex Tudorache 0ead57671c added how it works 2015-11-19 08:25:23 +02:00
9 changed files with 456 additions and 241 deletions
+98 -29
View File
@@ -1,43 +1,75 @@
# WiFiManager
ESP8266 WiFi Connection manager with save to EEPROM and web config portal
ESP8266 WiFi Connection manager with fallback web configuration portal
Captive portal should also work, I have tested it only on iOS.
The configuration portal is of the captive variety, so on various devices it will present the configuration dialogue as soon as you connect to the created access point.
First attempt at a library. Lots more changes and fixes to do. Adding examples also needs doing.
First attempt at a library. Lots more changes and fixes to do. Contributions are welcome.
This works with the ESP8266 Arduino platform https://github.com/esp8266/Arduino
#### This works with the ESP8266 Arduino platform with a recent stable release(2.0.0 or newer) https://github.com/esp8266/Arduino
## How It works
- when your ESP starts up, it sets it up in Station mode and tries to connect to a previously saved Access Point
- if this is unsuccessful (or no previous network saved) it moves the ESP into Access Point mode and spins up a DNS and WebServer (default ip 192.168.4.1)
- using any wifi enabled device with a browser (computer, phone, tablet) connect to the newly created Access Point
- because of the Captive Portal and the DNS server you will either get a 'Join to network' type of popup or get any domain you try to access redirected to the configuration portal
- choose one of the access points scanned, enter password, click save
- ESP will try to connect. If successful, it relinquishes control back to your app. If not, reconnect to AP and reconfigure.
## Still left to do
- ~~remove dependency on EEPROM library~~
- move HTML Strings to PROGMEM
- cleanup and streamline code
- if timeout is set, extend it when a page is fetched in AP mode
- add ability to configure more parameters than ssid/password
- maybe allow setting ip of ESP after reboot
## Releases
#### v0.4 - user contributed changes - Thank you
- added ability to password protect the configuration Access Point
- callback for enter configuration mode
- memory allocation improvements
##### v0.3
- removed the need for EEPROM and works with the 2.0.0 and above stable release of the ESP8266 for Arduino IDE package
- removed restart on save of credentials
- updated examples
##### v0.2
needs the latest staging version (or at least a recent release of the staging version) to work
##### v0.1
works with the staging release ver. 1.6.5-1044-g170995a, built on Aug 10, 2015 of the ESP8266 Arduino library.
> v0.1 works with the staging release ver. 1.6.5-1044-g170995a, built on Aug 10, 2015 of the ESP8266 Arduino library.
> latest comit should work with the latest staging version
## Quick Start
- Make sure you have a recent package of the ESP8266 for Arduino IDE
- Checkout library to your Arduino libraries folder
- Include in your sketch
```Arduino
#include <EEPROM.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
```cpp
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
```
- Initialise library, in your setup function add
```
//parameter is eeprom start
WiFiManager wifi;
```cpp
WiFiManager wifiManager;
```
- Also in the setup function add
```cpp
//first parameter is name of access point, second is the password
wifiManager.autoConnect("AP-NAME", "AP-PASSWORD");
```
//parameter is name of access point
wifi.autoConnect("AP-NAME");
if you just want an unsecured access point
```cpp
wifiManager.autoConnect("AP-NAME");
```
or if you want to use and auto generated name from 'ESP' and the esp's Chip ID use
```
wifi.autoConnect();
```cpp
wifiManager.autoConnect();
```
After you write your sketch and start the ESP, it will try to connect to WiFi. If it fails it starts in Access Point mode.
@@ -45,28 +77,65 @@ While in AP mode, connect to it then open a browser to the gateway IP, default 1
Also see examples.
### Timeout
If you need to set a timeout so the ESP doesn't hang waiting to be configured, for instance after a power failure, you can add
### Password protect the configuration Access Point
You can and should password protect the configuration access point. Simply add the password as a second parameter to `autoConnect`.
A short password seems to have unpredictable results so use one that's around 8 characters or more in length.
The guidelines are that a wifi password must consist of 8 to 63 ASCII-encoded characters in the range of 32 to 126 (decimal)
```cpp
wifiManager.autoConnect("AutoConnectAP", "password")
```
wifi.setTimeout(180);
### Callbacks
##### Enter Config mode
Use this if you need to do something when your device enters configuration mode on failed WiFi connection attempt.
Before `autoConnect()`
```cpp
wifiManager.setAPCallback(configModeCallback);
```
`configModeCallback` declaration and example
```cpp
void configModeCallback () {
Serial.println("Entered config mode");
Serial.println(WiFi.softAPIP());
}
```
### Timeout
If you need to set a timeout so the ESP doesn't hang waiting to be configured, for instance after a power failure, you can add
```cpp
wifiManager.setTimeout(180);
```
which will wait 3 minutes (180 seconds). When the time passes, the autoConnect function will return, no matter the outcome.
Check for connection and if it's still not established do whatever is needed (on some modules I restart them to retry, on others I enter deep sleep)
### Debug
Debug is enabled by default on Serial. To disable add before autoConnect
```
wifi.setDebugOutput(false);
```cpp
wifiManager.setDebugOutput(false);
```
### Custom IP Configuration
This will set your captive portal to a specific IP should you need/want such a feature. Add the following snippet before `autoConnect()`
```
```cpp
//set custom ip for portal
wifi.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
wifiManager.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
```
### Contributions and thanks
The support and help I got from the community has been nothing short of fenomenal. I can't thank you guys enough. This is my first real attept in developing open source stuff and I must say, now I understand why people are so dedicated to it, it is because of all the wonderful people involved.
####Inspiration
__THANK YOU__
[Maximiliano Duarte](https://github.com/domonetic)
[alltheblinkythings](https://github.com/alltheblinkythings)
[Niklas Wall](https://github.com/niklaswall)
[Jakub Piasecki](https://github.com/zaporylie)
[Peter Allan](https://github.com/alwynallan)
[John Little](https://github.com/j0hnlittle)
#### Inspiration
- http://www.esp8266.com/viewtopic.php?f=29&t=2520
To be continued...
+192 -155
View File
@@ -13,13 +13,7 @@
#include "WiFiManager.h"
//DNSServer dnsServer;
// Web server
//ESP8266WebServer server(80);
WiFiManager::WiFiManager() : server(80) {
WiFiManager::WiFiManager() {
}
void WiFiManager::begin() {
@@ -27,48 +21,72 @@ void WiFiManager::begin() {
}
void WiFiManager::begin(char const *apName) {
begin(apName,NULL);
}
void WiFiManager::begin(char const *apName, char const *apPasswd) {
dnsServer.reset(new DNSServer());
server.reset(new ESP8266WebServer(80));
DEBUG_PRINT("");
DEBUG_PRINT(F(""));
_apName = apName;
_apPasswd = apPasswd;
start = millis();
DEBUG_PRINT("Configuring access point... ");
DEBUG_PRINT(F("Configuring access point... "));
DEBUG_PRINT(_apName);
if (_apPasswd != NULL) {
if(strlen(_apPasswd) < 8 || strlen(_apPasswd) > 63) {
// fail passphrase to short or long!
DEBUG_PRINT(F("Invalid AccessPoint password"));
}
DEBUG_PRINT(_apPasswd);
}
//optional soft ip config
if (_ip) {
DEBUG_PRINT("Custom IP/GW/Subnet");
DEBUG_PRINT(F("Custom IP/GW/Subnet"));
WiFi.softAPConfig(_ip, _gw, _sn);
}
WiFi.softAP(_apName);//TODO: add password option
if (_apPasswd != NULL) {
WiFi.softAP(_apName, _apPasswd);//password option
} else {
WiFi.softAP(_apName);
}
delay(500); // Without delay I've seen the IP address blank
DEBUG_PRINT("AP IP address: ");
DEBUG_PRINT(F("AP IP address: "));
DEBUG_PRINT(WiFi.softAPIP());
/* Setup the DNS server redirecting all the domains to the apIP */
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(DNS_PORT, "*", WiFi.softAPIP());
dnsServer->setErrorReplyCode(DNSReplyCode::NoError);
dnsServer->start(DNS_PORT, "*", WiFi.softAPIP());
/* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */
server.on("/", std::bind(&WiFiManager::handleRoot, this));
server.on("/wifi", std::bind(&WiFiManager::handleWifi, this, true));
server.on("/0wifi", std::bind(&WiFiManager::handleWifi, this, false));
server.on("/wifisave", std::bind(&WiFiManager::handleWifiSave, this));
server.on("/generate_204", std::bind(&WiFiManager::handle204, this)); //Android/Chrome OS captive portal check.
server.on("/fwlink", std::bind(&WiFiManager::handleRoot, this)); //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
server.onNotFound (std::bind(&WiFiManager::handleNotFound, this));
server.begin(); // Web server start
DEBUG_PRINT("HTTP server started");
server->on("/", std::bind(&WiFiManager::handleRoot, this));
server->on("/wifi", std::bind(&WiFiManager::handleWifi, this, true));
server->on("/0wifi", std::bind(&WiFiManager::handleWifi, this, false));
server->on("/wifisave", std::bind(&WiFiManager::handleWifiSave, this));
server->on("/generate_204", std::bind(&WiFiManager::handle204, this)); //Android/Chrome OS captive portal check.
server->on("/fwlink", std::bind(&WiFiManager::handleRoot, this)); //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
server->onNotFound (std::bind(&WiFiManager::handleNotFound, this));
server->begin(); // Web server start
DEBUG_PRINT(F("HTTP server started"));
}
boolean WiFiManager::autoConnect() {
String ssid = "ESP" + String(ESP.getChipId());
return autoConnect(ssid.c_str());
return autoConnect(ssid.c_str(),NULL);
}
boolean WiFiManager::autoConnect(char const *apName) {
DEBUG_PRINT("");
DEBUG_PRINT("AutoConnect");
return autoConnect(apName,NULL);
}
boolean WiFiManager::autoConnect(char const *apName, char const *apPasswd) {
DEBUG_PRINT(F(""));
DEBUG_PRINT(F("AutoConnect"));
// read eeprom for ssid and pass
String ssid = getSSID();
@@ -81,56 +99,63 @@ boolean WiFiManager::autoConnect(char const *apName) {
connectWifi(ssid, pass);
int s = WiFi.status();
if (s == WL_CONNECTED) {
DEBUG_PRINT("IP Address:");
DEBUG_PRINT(F("IP Address:"));
DEBUG_PRINT(WiFi.localIP());
//connected
return true;
}
// delay(1000);
//not connected
//setup AP
WiFi.mode(WIFI_AP);
//notify we entered AP mode
if( _apcallback != NULL) {
_apcallback();
}
connect = false;
begin(apName);
begin(apName,apPasswd);
while(1) {
bool looping = true;
while(timeout == 0 || millis() < start + timeout) {
//DNS
dnsServer.processNextRequest();
dnsServer->processNextRequest();
//HTTP
server.handleClient();
server->handleClient();
if(connect) {
delay(5000);
ESP.reset();
delay(1000);
}
/*
if(connect) {
DEBUG_PRINT("Connecting to new AP");
delay(2000);
DEBUG_PRINT(F("Connecting to new AP"));
connect = false;
ssid = getSSID();
pass = getPassword();
connectWifi(ssid, pass);
//ssid = getSSID();
//pass = getPassword();
connectWifi(_ssid, _pass);
int s = WiFi.status();
if (s == WL_CONNECTED) {
//connected
return true;
if (s != WL_CONNECTED) {
DEBUG_PRINT(F("Failed to connect."));
//not connected, should retry everything
//ESP.reset();
//delay(1000);
//return false;
} else {
//connected
WiFi.mode(WIFI_STA);
break;
}
}*/
}
yield();
}
return false;
server.reset();
dnsServer.reset();
return WiFi.status() == WL_CONNECTED;
}
void WiFiManager::connectWifi(String ssid, String pass) {
DEBUG_PRINT("Connecting as wifi client...");
WiFi.disconnect();
DEBUG_PRINT(F("Connecting as wifi client..."));
//WiFi.disconnect();
WiFi.begin(ssid.c_str(), pass.c_str());
int connRes = WiFi.waitForConnectResult();
DEBUG_PRINT ("Connection result: ");
@@ -140,9 +165,9 @@ void WiFiManager::connectWifi(String ssid, String pass) {
String WiFiManager::getSSID() {
if (_ssid == "") {
DEBUG_PRINT("Reading EEPROM SSID");
_ssid = getEEPROMString(0, 32);
DEBUG_PRINT("SSID: ");
DEBUG_PRINT(F("Reading SSID"));
_ssid = WiFi.SSID();//getEEPROMString(0, 32);
DEBUG_PRINT(F("SSID: "));
DEBUG_PRINT(_ssid);
}
return _ssid;
@@ -150,27 +175,15 @@ String WiFiManager::getSSID() {
String WiFiManager::getPassword() {
if (_pass == "") {
DEBUG_PRINT("Reading EEPROM Password");
_pass = getEEPROMString(32, 64);
DEBUG_PRINT(F("Reading Password"));
_pass = WiFi.psk();//getEEPROMString(32, 64);
DEBUG_PRINT("Password: " + _pass);
//DEBUG_PRINT(_pass);
}
return _pass;
}
void WiFiManager::setSSID(String s) {
_ssid = s;
setEEPROMString(0, 32, _ssid);
}
void WiFiManager::setPassword(String p) {
DEBUG_PRINT("Save password:");
DEBUG_PRINT(p);
_pass = p;
setEEPROMString(32, 64, _pass);
}
/*
String WiFiManager::getEEPROMString(int start, int len) {
EEPROM.begin(512);
delay(10);
@@ -182,7 +195,8 @@ String WiFiManager::getEEPROMString(int start, int len) {
EEPROM.end();
return string;
}
*/
/*
void WiFiManager::setEEPROMString(int start, int len, String string) {
EEPROM.begin(512);
delay(10);
@@ -191,7 +205,7 @@ void WiFiManager::setEEPROMString(int start, int len, String string) {
char c;
if (si < string.length()) {
c = string[si];
//DEBUG_PRINT("Wrote: ");
//DEBUG_PRINT(F("Wrote: ");
//DEBUG_PRINT(c);
} else {
c = 0;
@@ -200,8 +214,8 @@ void WiFiManager::setEEPROMString(int start, int len, String string) {
si++;
}
EEPROM.end();
DEBUG_PRINT("Wrote " + string);
}
DEBUG_PRINT(F("Wrote " + string);
}*/
String WiFiManager::urldecode(const char *src)
{
@@ -240,13 +254,10 @@ String WiFiManager::urldecode(const char *src)
}
void WiFiManager::resetSettings() {
//need to call it only after lib has been started with autoConnect or begin
setEEPROMString(0, 32, "-");
setEEPROMString(32, 64, "-");
DEBUG_PRINT("settings invalidated");
delay(200);
WiFi.disconnect();
DEBUG_PRINT(F("settings invalidated"));
DEBUG_PRINT(F("THIS MAY CAUSE AP NOT TO STRT UP PROPERLY. YOU NEED TO COMMENT IT OUT AFTER ERASING THE DATA."));
WiFi.disconnect(true);
//delay(200);
}
void WiFiManager::setTimeout(unsigned long seconds) {
@@ -266,152 +277,167 @@ void WiFiManager::setAPConfig(IPAddress ip, IPAddress gw, IPAddress sn) {
/** Handle root or redirect to captive portal */
void WiFiManager::handleRoot() {
DEBUG_PRINT("Handle root");
DEBUG_PRINT(F("Handle root"));
if (captivePortal()) { // If caprive portal redirect instead of displaying the page.
return;
}
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
server->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server->sendHeader("Pragma", "no-cache");
server->sendHeader("Expires", "-1");
server->send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
String head = HTTP_HEAD;
head.replace("{v}", "Options");
server.sendContent(head);
server.sendContent(HTTP_SCRIPT);
server.sendContent(HTTP_STYLE);
server.sendContent(HTTP_HEAD_END);
server.sendContent(
"<form action=\"/wifi\" method=\"get\"><button>Configure WiFi</button></form><br/>"
);
server.sendContent(
"<form action=\"/0wifi\" method=\"get\"><button>Configure WiFi (No Scan)</button></form>"
);
server.sendContent(HTTP_END);
server->sendContent(head);
server->sendContent_P(HTTP_SCRIPT);
server->sendContent_P(HTTP_STYLE);
server->sendContent_P(HTTP_HEAD_END);
server.client().stop(); // Stop is needed because we sent no content length
//server->sendContent(F("<h1>"));
String title = "<h1>";
title += _apName;
title += "</h1>";
server->sendContent(title);
server->sendContent(F("<h3>WiFiManager</h3>"));
server->sendContent_P(HTTP_PORTAL_OPTIONS);
server->sendContent_P(HTTP_END);
server->client().stop(); // Stop is needed because we sent no content length
}
/** Wifi config page handler */
void WiFiManager::handleWifi(bool scan) {
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
server->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server->sendHeader("Pragma", "no-cache");
server->sendHeader("Expires", "-1");
server->send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
String head = HTTP_HEAD;
head.replace("{v}", "Config ESP");
server.sendContent(head);
server.sendContent(HTTP_SCRIPT);
server.sendContent(HTTP_STYLE);
server.sendContent(HTTP_HEAD_END);
server->sendContent(head);
server->sendContent_P(HTTP_SCRIPT);
server->sendContent_P(HTTP_STYLE);
server->sendContent_P(HTTP_HEAD_END);
if (scan) {
int n = WiFi.scanNetworks();
DEBUG_PRINT("Scan done");
DEBUG_PRINT(F("Scan done"));
if (n == 0) {
DEBUG_PRINT("No networks found");
server.sendContent("<div>No networks found. Refresh to scan again.</div>");
DEBUG_PRINT(F("No networks found"));
server->sendContent("No networks found. Refresh to scan again.");
}
else {
for (int i = 0; i < n; ++i)
{
DEBUG_PRINT(WiFi.SSID(i));
DEBUG_PRINT(WiFi.RSSI(i));
String item = HTTP_ITEM;
String item = FPSTR(HTTP_ITEM);
String rssiQ;
rssiQ += getRSSIasQuality(WiFi.RSSI(i));
item.replace("{v}", WiFi.SSID(i));
server.sendContent(item);
yield();
item.replace("{r}", rssiQ);
if(WiFi.encryptionType(i) != ENC_TYPE_NONE) {
item.replace("{i}", FPSTR(HTTP_ITEM_PADLOCK));
} else {
item.replace("{i}", "");
}
//DEBUG_PRINT(item);
server->sendContent(item);
delay(0);
}
server->sendContent("<br/>");
}
}
server.sendContent(HTTP_FORM);
server.sendContent(HTTP_END);
server.client().stop();
server->sendContent_P(HTTP_FORM);
server->sendContent_P(HTTP_END);
server->client().stop();
DEBUG_PRINT("Sent config page");
DEBUG_PRINT(F("Sent config page"));
}
/** Handle the WLAN save form and redirect to WLAN config page again */
void WiFiManager::handleWifiSave() {
DEBUG_PRINT("WiFi save");
//server.arg("s").toCharArray(ssid, sizeof(ssid) - 1);
//server.arg("p").toCharArray(password, sizeof(password) - 1);
setSSID(urldecode(server.arg("s").c_str()));
setPassword(urldecode(server.arg("p").c_str()));
DEBUG_PRINT(F("WiFi save"));
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
//SAVE/connect here
_ssid = urldecode(server->arg("s").c_str());
_pass = urldecode(server->arg("p").c_str());
server->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server->sendHeader("Pragma", "no-cache");
server->sendHeader("Expires", "-1");
server->send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
String head = HTTP_HEAD;
head.replace("{v}", "Credentials Saved");
server.sendContent(head);
server.sendContent(HTTP_SCRIPT);
server.sendContent(HTTP_STYLE);
server.sendContent(HTTP_HEAD_END);
server->sendContent(head);
server->sendContent_P(HTTP_SCRIPT);
server->sendContent_P(HTTP_STYLE);
server->sendContent_P(HTTP_HEAD_END);
server.sendContent(HTTP_SAVED);
server->sendContent_P(HTTP_SAVED);
server.sendContent(HTTP_END);
server.client().stop();
server->sendContent_P(HTTP_END);
server->client().stop();
DEBUG_PRINT("Sent wifi save page");
DEBUG_PRINT(F("Sent wifi save page"));
//saveCredentials();
connect = true; //signal ready to connect/reset
}
void WiFiManager::handle204() {
DEBUG_PRINT("204 No Response");
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.send ( 204, "text/plain", "");
DEBUG_PRINT(F("204 No Response"));
server->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server->sendHeader("Pragma", "no-cache");
server->sendHeader("Expires", "-1");
server->send ( 204, "text/plain", "");
}
void WiFiManager::handleNotFound() {
if (captivePortal()) { // If captive portal redirect instead of displaying the error page.
return;
}
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += server->uri();
message += "\nMethod: ";
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
message += ( server->method() == HTTP_GET ) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += server->args();
message += "\n";
for ( uint8_t i = 0; i < server.args(); i++ ) {
message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
for ( uint8_t i = 0; i < server->args(); i++ ) {
message += " " + server->argName ( i ) + ": " + server->arg ( i ) + "\n";
}
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.send ( 404, "text/plain", message );
server->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server->sendHeader("Pragma", "no-cache");
server->sendHeader("Expires", "-1");
server->send ( 404, "text/plain", message );
}
/** Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */
boolean WiFiManager::captivePortal() {
if (!isIp(server.hostHeader()) ) {
DEBUG_PRINT("Request redirected to captive portal");
server.sendHeader("Location", String("http://") + toStringIp(server.client().localIP()), true);
server.send ( 302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
server.client().stop(); // Stop is needed because we sent no content length
if (!isIp(server->hostHeader()) ) {
DEBUG_PRINT(F("Request redirected to captive portal"));
server->sendHeader("Location", String("http://") + toStringIp(server->client().localIP()), true);
server->send ( 302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
server->client().stop(); // Stop is needed because we sent no content length
return true;
}
return false;
}
//start up config portal callback
void WiFiManager::setAPCallback( void (*func)(void) ) {
_apcallback = func;
}
template <typename Generic>
void WiFiManager::DEBUG_PRINT(Generic text) {
@@ -422,7 +448,18 @@ void WiFiManager::DEBUG_PRINT(Generic text) {
}
int WiFiManager::getRSSIasQuality(int RSSI) {
int quality = 0;
if(RSSI <= -100){
quality = 0;
}else if(RSSI >= -50){
quality = 100;
} else {
quality = 2 * (RSSI + 100);
}
return quality;
}
/** Is this an IP? */
boolean WiFiManager::isIp(String str) {
+50 -36
View File
@@ -14,34 +14,40 @@
#include <ESP8266WiFi.h>
#include <EEPROM.h>
#include <WiFiClient.h>
//#include <EEPROM.h>
//#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <memory>
const char HTTP_200[] PROGMEM = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
//const char HTTP_HEAD[] PROGMEM = "<!DOCTYPE html><html lang=\"en\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/><title>{v}</title>";
const char HTTP_STYLE[] PROGMEM = "<style>div,input{padding:5px;font-size:1em;} input{width:95%;} body{text-align: center;} button{border:0;border-radius:0.3rem;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%;}</style>";
const char HTTP_SCRIPT[] PROGMEM = "<script>function c(l){document.getElementById('s').value=l.innerText||l.textContent;document.getElementById('p').focus();}</script>";
const char HTTP_HEAD_END[] PROGMEM = "</head><body><div style='text-align: left; display: inline-block;'>";
const char HTTP_PORTAL_OPTIONS[] PROGMEM = "<form action=\"/wifi\" method=\"get\"><button>Configure WiFi</button></form><br/><form action=\"/0wifi\" method=\"get\"><button>Configure WiFi (No Scan)</button></form>";
const char HTTP_ITEM[] PROGMEM = "<div><a href='#' onclick='c(this)'>{v}</a> {r}% {i}</div>";
const char HTTP_ITEM_PADLOCK[] PROGMEM = "<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAKCAMAAAC+Ge+yAAAACVBMVEUAAAC7u7v///9etNz6AAAAI0lEQVQI133GsQ3AMAAEoXv2H9qNJacKFbEaWTQJ+uQB/nMdEaYAXeJkZ9AAAAAASUVORK5CYII='/>";
const char HTTP_FORM[] PROGMEM = "<form method='get' action='wifisave'><input id='s' name='s' length=32 placeholder='SSID'><br/><input id='p' name='p' length=64 placeholder='password'><br/><br/><button type='submit'>save</button></form>";
const char HTTP_SAVED[] PROGMEM = "<div>Credentials Saved<br />Trying to connect ESP to network.<br />If it fails reconnect to AP to try again</div>";
const char HTTP_END[] PROGMEM = "</div></body></html>";
class WiFiManager
{
public:
WiFiManager();
void begin();
void begin(char const *apName);
boolean autoConnect();
boolean autoConnect(char const *apName);
boolean hasConnected();
String beginConfigMode(void);
void startWebConfig();
boolean autoConnect(char const *apName, char const *apPasswd);
String getSSID();
String getPassword();
void setSSID(String s);
void setPassword(String p);
void resetSettings();
//for conveniennce
//for convenience
String urldecode(const char*);
//sets timeout before webserver loop ends and exits even if there has been no setup.
@@ -52,39 +58,43 @@ public:
//sets a custom ip /gateway /subnet configuration
void setAPConfig(IPAddress ip, IPAddress gw, IPAddress sn);
int serverLoop();
void setAPCallback( void (*func)(void) );
private:
DNSServer dnsServer;
ESP8266WebServer server;
std::unique_ptr<DNSServer> dnsServer;
std::unique_ptr<ESP8266WebServer> server;
const int WM_DONE = 0;
const int WM_WAIT = 10;
const String HTTP_404 = "HTTP/1.1 404 Not Found\r\n\r\n";
const String HTTP_200 = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
//const char PROGMEM HTTP_404[] = "HTTP/1.1 404 Not Found\r\n\r\n";
//const String HTTP_200 = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
const String HTTP_HEAD = "<!DOCTYPE html><html lang=\"en\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/><title>{v}</title>";
const String HTTP_STYLE = "<style>div,input {margin-bottom: 5px;} body{width:200px;display:block;margin-left:auto;margin-right:auto;} button{padding:0.75rem 1rem;border:0;border-radius:0.317rem;background-color:#1fa3ec;color:#fff;line-height:1.5;cursor:pointer;}</style>";
const String HTTP_SCRIPT = "<script>function c(l){document.getElementById('s').value=l.innerText||l.textContent;document.getElementById('p').focus();}</script>";
const String HTTP_HEAD_END = "</head><body>";
const String HTTP_ITEM = "<div><a href='#' onclick='c(this)'>{v}</a></div>";
const String HTTP_FORM = "<form method='get' action='wifisave'><input id='s' name='s' length=32 placeholder='SSID'><input id='p' name='p' length=64 placeholder='password'><br/><button type='submit'>save</button></form>";
const String HTTP_SAVED = "<div>Credentials Saved<br />Node will reboot in 5 seconds.</div>";
const String HTTP_END = "</body></html>";
//const String HTTP_STYLE = "<style>div,input {margin-bottom: 5px;} body{width:200px;display:block;margin-left:auto;margin-right:auto;} button{padding:0.75rem 1rem;border:0;border-radius:0.317rem;background-color:#1fa3ec;color:#fff;line-height:1.5;cursor:pointer;}</style>";
//const String HTTP_SCRIPT = "<script>function c(l){document.getElementById('s').value=l.innerText||l.textContent;document.getElementById('p').focus();}</script>";
//const String HTTP_HEAD_END = "</head><body>";
//const String HTTP_ITEM = "<div><a href='#' onclick='c(this)'>{v}</a></div>";
//const String HTTP_FORM = "<form method='get' action='wifisave'><input id='s' name='s' length=32 placeholder='SSID'><input id='p' name='p' length=64 placeholder='password'><br/><button type='submit'>save</button></form>";
//const String HTTP_SAVED = "<div>Credentials Saved<br />Trying to connect ESP to network.<br />If it fails reconnect to AP to try again</div>";
//const String HTTP_END = "</body></html>";
//const char HTTP_END[] PROGMEM = R"=====(
//</body></html>
//)=====";
void begin();
void begin(char const *apName);
void begin(char const *apName, char const *apPasswd);
int _eepromStart;
int _eepromStart;
const char* _apName = "no-net";
String _ssid = "";
String _pass = "";
const char* _apPasswd = NULL;
String _ssid = "";
String _pass = "";
unsigned long timeout = 0;
unsigned long start = 0;
IPAddress _ip;
IPAddress _gw;
IPAddress _sn;
IPAddress _ip;
IPAddress _gw;
IPAddress _sn;
String getEEPROMString(int start, int len);
void setEEPROMString(int start, int len, String string);
@@ -102,13 +112,17 @@ private:
// DNS server
const byte DNS_PORT = 53;
//helpers
int getRSSIasQuality(int RSSI);
boolean isIp(String str);
String toStringIp(IPAddress ip);
boolean connect;
boolean _debug = true;
void (*_apcallback)(void) = NULL;
template <typename Generic>
void DEBUG_PRINT(Generic text);
};
+7 -8
View File
@@ -1,10 +1,9 @@
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
//needed for library
#include <EEPROM.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
void setup() {
@@ -13,20 +12,20 @@ void setup() {
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifi;
WiFiManager wifiManager;
//reset saved settings
//wifi.resetSettings();
//wifiManager.resetSettings();
//set custom ip for portal
//wifi.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
//wifiManager.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
//fetches ssid and pass from eeprom and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
wifi.autoConnect("AutoConnectAP");
wifiManager.autoConnect("AutoConnectAP");
//or use this for auto generated name ESP + ChipID
//wifi.autoConnect();
//wifiManager.autoConnect();
//if you get here you have connected to the WiFi
@@ -0,0 +1,44 @@
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
void configModeCallback () {
Serial.println("Entered config mode");
Serial.println(WiFi.softAPIP());
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;
//reset settings - for testing
//wifiManager.resetSettings();
//set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
wifiManager.setAPCallback(configModeCallback);
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
if(!wifiManager.autoConnect("AutoConnectAP")) {
Serial.println("failed to connect and hit timeout");
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(1000);
}
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
}
void loop() {
// put your main code here, to run repeatedly:
}
@@ -1,39 +1,34 @@
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
//needed for library
#include <EEPROM.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
//this intitilises the library, parameter is eeprom start
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifi;
WiFiManager wifiManager;
//reset settings - for testing
//wifi.resetSettings();
//wifiManager.resetSettings();
//sets timeout until configuration portal gets turned off
//useful to make it all retry or go to sleep
//in seconds
wifi.setTimeout(180);
wifiManager.setTimeout(180);
//fetches ssid and pass from eeprom and tries to connect
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
if(!wifi.autoConnect("AutoConnectAP")) {
if(!wifiManager.autoConnect("AutoConnectAP")) {
Serial.println("failed to connect and hit timeout");
delay(5000);
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
+29
View File
@@ -0,0 +1,29 @@
#######################################
# Syntax Coloring Map For WifiManager
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
WiFiManager KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
autoConnect KEYWORD2
getSSID KEYWORD2
getPassword KEYWORD2
resetSettings KEYWORD2
urldecode KEYWORD2
setTimeout KEYWORD2
setDebugOutput KEYWORD2
setAPConfig KEYWORD2
setAPCallback KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
# LITERAL1
+19
View File
@@ -0,0 +1,19 @@
{
"name": "WifiManager",
"keywords": "wifi, wi-fi, ESP8266",
"description": "ESP8266 WiFi Connection manager with fallback web configuration portal",
"repository":
{
"type": "git",
"url": "https://github.com/tzapu/WiFiManager.git"
},
"authors":
{
"name": "tzapu",
"url": "http://tzapu.com"
},
"frameworks": "arduino",
"platforms": "esp8266"
"version": "0.5",
"architecture": "esp8266",
}
+9
View File
@@ -0,0 +1,9 @@
name=WiFiManager
version=0.5
author=tzapu
maintainer=tzapu
sentence=ESP8266 WiFi Connection manager with fallback web configuration portal
paragraph=Library for configuring ESP8266 modules WiFi credentials at runtime.
category=Communication
url=https://github.com/tzapu/WiFiManager.git
architectures=esp8266