Compare commits

..
25 Commits
Author SHA1 Message Date
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
Alex Tudorache e55057f686 auto generated AP name
pretty buttons
2015-11-10 11:04:01 +02:00
Alex Tudorache 87911808ab added ability to set custom config for access point 2015-11-10 08:46:38 +02:00
Alex Tudorache 8f38a0fbaf added no scan option 2015-11-10 08:20:53 +02:00
tzapu 5ef78c6938 Merge pull request #9 from zaporylie/ip-address
Show local IP address in STA mode thanks to @zaporylie
2015-11-02 17:37:53 +02:00
zaporylie 57d9d1f33e Show local IP address in STA mode 2015-11-01 21:02:05 +01:00
Alex Tudorache ce8c9fea61 added initialisation to setup so wifi is no longer global and it gets cleaned
dnsServer and webServer are also no longer global
readme updated
2015-10-09 18:33:41 +03:00
Alex Tudorache 97b74f2b19 added debug messages enable/disable 2015-10-08 16:42:43 +03:00
tzapu 413959df5a Merge pull request #7 from niklaswall/master
Improved support for Android and Chrome OS Captive Portal detection thanks to niklaswall
2015-09-18 15:29:50 +03:00
Niklas Wall 12dfccf9e3 Merge pull request #1 from niklaswall/android-captive-portal-improvements
Improved support for Android and Chrome OS CP detection
2015-09-18 14:22:41 +02:00
Niklas Wall 72aaccf4e5 Improved support for Android and Chrome OS CP detection
Improved the support for Android and Chrome OS “Captive
Portal”detection. By returning a correct 204 status page when
/generate_204 is requested we prevent the device from disabling the
Wifi and roaming over to mobile data.
2015-09-18 14:21:33 +02:00
Alex Tudorache cac2d9973b updated readme.md 2015-09-11 18:54:18 +03:00
Alex Tudorache d2bd81121d added captive portal
removed mdsn lib
changed dependencies and constructor
2015-09-11 18:51:21 +03:00
tzapu 20dbfed7c6 Update README.md 2015-08-28 14:51:09 +03:00
tzapu e74b39d833 Update README.md 2015-08-28 14:48:39 +03:00
tzapu 50e8b1d278 Update README.md 2015-08-28 14:47:20 +03:00
5 changed files with 504 additions and 268 deletions
+67 -16
View File
@@ -1,39 +1,90 @@
# WiFiManager
ESP8266 WiFi Connection manager with save to EEPROM and web config portal
ESP8266 WiFi Connection manager with fallback web configuration portal
First attempt at a library. Lots more changes and fixes to do. Adding examples also needs doing.
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. Contributions are welcome.
## 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
This works with the ESP8266 Arduino platform https://github.com/esp8266/Arduino
####Quick Start
## Releases
> 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
> **v0.2 and newer need 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.
## 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 <WiFiClient.h>
#include <EEPROM.h>
#include <ESP8266mDNS.h>
```cpp
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
```
- Initialise library, the paramater is the Acces Point Name
```
//parameter is eeprom start
WiFiManager wifi(0);
- Initialise library, in your setup function add
```cpp
WiFiManager wifiManager;
```
- In your setup function add
```
- Also in the setup function add
```cpp
//parameter is name of access point
wifi.autoConnect("AP-NAME");
wifiManager.autoConnect("AP-NAME");
```
or if you want to use and auto generated name from 'ESP' and the esp's Chip ID use
```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.
While in AP mode, connect to it then open a browser to the gateway IP, default 192.168.4.1, configure wifi, save and it should reboot and connect.
Also see examples.
####Inspiration
### 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
```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
wifiManager.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
```
#### Inspiration
- http://www.esp8266.com/viewtopic.php?f=29&t=2520
To be continued...
+341 -204
View File
@@ -3,21 +3,23 @@
* (https://github.com/esp8266/Arduino) to enable easy
* configuration and reconfiguration of WiFi credentials and
* store them in EEPROM.
* inspired by http://www.esp8266.com/viewtopic.php?f=29&t=2520
* inspired by:
* http://www.esp8266.com/viewtopic.php?f=29&t=2520
* https://github.com/chriscook8/esp-arduino-apboot
* https://github.com/esp8266/Arduino/tree/esp8266/hardware/esp8266com/esp8266/libraries/DNSServer/examples/CaptivePortalAdvanced
* Built by AlexT https://github.com/tzapu
* Licensed under MIT license
**************************************************************/
#include "WiFiManager.h"
MDNSResponder mdns;
WiFiServer server(80);
//DNSServer dnsServer;
WiFiManager::WiFiManager(int eepromStart)
{
_eepromStart = eepromStart;
// Web server
//ESP8266WebServer server(80);
WiFiManager::WiFiManager() : server(80) {
}
void WiFiManager::begin() {
@@ -25,46 +27,131 @@ void WiFiManager::begin() {
}
void WiFiManager::begin(char const *apName) {
DEBUG_PRINT("");
_apName = apName;
start = millis();
EEPROM.begin(512);
delay(10);
DEBUG_PRINT("Configuring access point... ");
DEBUG_PRINT(_apName);
//optional soft ip config
if (_ip) {
DEBUG_PRINT("Custom IP/GW/Subnet");
WiFi.softAPConfig(_ip, _gw, _sn);
}
WiFi.softAP(_apName);//TODO: add password option
delay(500); // Without delay I've seen the IP address blank
DEBUG_PRINT("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());
/* 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");
}
boolean WiFiManager::autoConnect() {
return autoConnect("NoNetESP");
String ssid = "ESP" + String(ESP.getChipId());
return autoConnect(ssid.c_str());
}
boolean WiFiManager::autoConnect(char const *apName) {
begin(apName);
DEBUG_PRINT("");
DEBUG_PRINT("AutoConnect");
// read eeprom for ssid and pass
String ssid = getSSID();
String pass = getPassword();
if ( ssid.length() > 1 ) {
DEBUG_PRINT("Waiting for Wifi to connect");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), pass.c_str());
if ( hasConnected() ) {
return true;
}
//use SDK functions to get SSID and pass
//String ssid = WiFi.SSID();
//String pass = WiFi.psk();
WiFi.mode(WIFI_STA);
connectWifi(ssid, pass);
int s = WiFi.status();
if (s == WL_CONNECTED) {
DEBUG_PRINT("IP Address:");
DEBUG_PRINT(WiFi.localIP());
//connected
return true;
}
// delay(1000);
//not connected
//setup AP
beginConfigMode();
//start portal and loop
startWebConfig();
return false;
WiFi.mode(WIFI_AP);
connect = false;
begin(apName);
bool looping = true;
//while(1) {
while(timeout == 0 || millis() < start + timeout) {
//DNS
dnsServer.processNextRequest();
//HTTP
server.handleClient();
/*if(connect) {
delay(5000);
ESP.reset();
delay(1000);
}*/
if(connect) {
delay(2000);
DEBUG_PRINT("Connecting to new AP");
connect = false;
//ssid = getSSID();
//pass = getPassword();
connectWifi(_ssid, _pass);
int s = WiFi.status();
if (s != WL_CONNECTED) {
DEBUG_PRINT("Failed to connect.");
//not connected, should retry everything
//ESP.reset();
//delay(1000);
//return false;
} else {
//connected
WiFi.mode(WIFI_STA);
return true;
}
}
yield();
}
return WiFi.status() == WL_CONNECTED;
}
void WiFiManager::connectWifi(String ssid, String pass) {
DEBUG_PRINT("Connecting as wifi client...");
//WiFi.disconnect();
WiFi.begin(ssid.c_str(), pass.c_str());
int connRes = WiFi.waitForConnectResult();
DEBUG_PRINT ("Connection result: ");
DEBUG_PRINT ( connRes );
}
String WiFiManager::getSSID() {
if (_ssid == "") {
DEBUG_PRINT("Reading EEPROM SSID");
_ssid = getEEPROMString(0, 32);
_ssid = WiFi.SSID();//getEEPROMString(0, 32);
DEBUG_PRINT("SSID: ");
DEBUG_PRINT(_ssid);
}
@@ -74,204 +161,58 @@ String WiFiManager::getSSID() {
String WiFiManager::getPassword() {
if (_pass == "") {
DEBUG_PRINT("Reading EEPROM Password");
_pass = getEEPROMString(32, 64);
DEBUG_PRINT("Password: ");
DEBUG_PRINT(_pass);
_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);
String string = "";
for (int i = _eepromStart + start; i < _eepromStart + start + len; i++) {
//DEBUG_PRINT(i);
string += char(EEPROM.read(i));
}
EEPROM.end();
return string;
}
*/
/*
void WiFiManager::setEEPROMString(int start, int len, String string) {
EEPROM.begin(512);
delay(10);
int si = 0;
for (int i = _eepromStart + start; i < _eepromStart + start + len; i++) {
char c;
if (si < string.length()) {
c = string[si];
DEBUG_PRINT("Wrote: ");
DEBUG_PRINT(c);
//DEBUG_PRINT("Wrote: ");
//DEBUG_PRINT(c);
} else {
c = 0;
}
EEPROM.write(i, c);
si++;
}
}
boolean WiFiManager::hasConnected(void) {
int c = 0;
while ( c < 50 ) {
if (WiFi.status() == WL_CONNECTED) {
return true;
}
delay(200);
DEBUG_PRINT(".");
c++;
}
DEBUG_PRINT("");
DEBUG_PRINT("Could not connect to WiFi");
return false;
}
void WiFiManager::startWebConfig() {
DEBUG_PRINT("");
DEBUG_PRINT("WiFi connected");
DEBUG_PRINT(WiFi.localIP());
DEBUG_PRINT(WiFi.softAPIP());
if (!mdns.begin(_apName, WiFi.localIP())) {
DEBUG_PRINT("Error setting up MDNS responder!");
while (1) {
delay(1000);
}
}
DEBUG_PRINT("mDNS responder started");
// Start the server
server.begin();
DEBUG_PRINT("Server started");
while (serverLoop() == WM_WAIT) {
//looping
if(timeout > 0 && start + timeout < millis()) {
//we passed timeout value, release
DEBUG_PRINT("timeout reached");
return;
}
}
DEBUG_PRINT("Setup done");
delay(5000);
ESP.reset();
}
String WiFiManager::beginConfigMode(void) {
WiFi.softAP(_apName);
DEBUG_PRINT("Started Soft Access Point");
IPAddress apIp = WiFi.softAPIP();
char ip[24];
sprintf(ip, "%d.%d.%d.%d", apIp[0], apIp[1], apIp[2], apIp[3]);
return ip;
}
int WiFiManager::serverLoop()
{
// Check for any mDNS queries and send responses
mdns.update();
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return (WM_WAIT);
}
DEBUG_PRINT("New client");
// Wait for data from client to become available
while (client.connected() && !client.available()) {
delay(1);
}
// Read the first line of HTTP request
String req = client.readStringUntil('\r');
// First line of HTTP request looks like "GET /path HTTP/1.1"
// Retrieve the "/path" part by finding the spaces
int addr_start = req.indexOf(' ');
int addr_end = req.indexOf(' ', addr_start + 1);
if (addr_start == -1 || addr_end == -1) {
DEBUG_PRINT("Invalid request: ");
DEBUG_PRINT(req);
return (WM_WAIT);
}
req = req.substring(addr_start + 1, addr_end);
DEBUG_PRINT("Request: ");
DEBUG_PRINT(req);
client.flush();
String s;
if (req == "/")
{
s = HTTP_200;
String head = HTTP_HEAD;
head.replace("{v}", "Config ESP");
s += head;
s += HTTP_SCRIPT;
s += HTTP_STYLE;
s += HTTP_HEAD_END;
int n = WiFi.scanNetworks();
DEBUG_PRINT("scan done");
if (n == 0) {
DEBUG_PRINT("no networks found");
s += "<div>No networks found. Refresh to scan again.</div>";
}
else {
for (int i = 0; i < n; ++i)
{
DEBUG_PRINT(WiFi.SSID(i));
DEBUG_PRINT(WiFi.RSSI(i));
String item = HTTP_ITEM;
item.replace("{v}", WiFi.SSID(i));
s += item;
delay(10);
}
}
s += HTTP_FORM;
s += HTTP_END;
DEBUG_PRINT("Sending config page");
}
else if ( req.startsWith("/s") ) {
String qssid;
qssid = urldecode(req.substring(8, req.indexOf('&')).c_str());
DEBUG_PRINT(qssid);
DEBUG_PRINT("");
String qpass;
qpass = urldecode(req.substring(req.lastIndexOf('=') + 1).c_str());
DEBUG_PRINT(qpass);
DEBUG_PRINT("");
setEEPROMString(0, 32, qssid);
setEEPROMString(32, 64, qpass);
EEPROM.commit();
s = HTTP_200;
String head = HTTP_HEAD;
head.replace("{v}", "Saved config");
s += HTTP_STYLE;
s += HTTP_HEAD_END;
s += "saved to eeprom...<br/>resetting in 10 seconds";
s += HTTP_END;
client.print(s);
client.flush();
DEBUG_PRINT("Saved WiFiConfig...restarting.");
return WM_DONE;
}
else
{
s = HTTP_404;
DEBUG_PRINT("Sending 404");
}
client.print(s);
DEBUG_PRINT("Done with client");
return (WM_WAIT);
}
EEPROM.end();
DEBUG_PRINT("Wrote " + string);
}*/
String WiFiManager::urldecode(const char *src)
{
@@ -311,16 +252,212 @@ 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, "-");
//setEEPROMString(0, 32, "-");
//setEEPROMString(32, 64, "-");
EEPROM.commit();
DEBUG_PRINT("settings invalidated");
delay(200);
WiFi.disconnect();
delay(200);
}
void WiFiManager::setTimeout(unsigned long seconds) {
timeout = seconds * 1000;
}
void WiFiManager::setDebugOutput(boolean debug) {
_debug = debug;
}
void WiFiManager::setAPConfig(IPAddress ip, IPAddress gw, IPAddress sn) {
_ip = ip;
_gw = gw;
_sn = sn;
}
/** Handle root or redirect to captive portal */
void WiFiManager::handleRoot() {
DEBUG_PRINT("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.
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.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.
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);
if (scan) {
int n = WiFi.scanNetworks();
DEBUG_PRINT("Scan done");
if (n == 0) {
DEBUG_PRINT("No networks found");
server.sendContent("<div>No networks found. Refresh to scan again.</div>");
}
else {
for (int i = 0; i < n; ++i)
{
DEBUG_PRINT(WiFi.SSID(i));
DEBUG_PRINT(WiFi.RSSI(i));
String item = HTTP_ITEM;
item.replace("{v}", WiFi.SSID(i));
server.sendContent(item);
yield();
}
}
}
server.sendContent(HTTP_FORM);
server.sendContent(HTTP_END);
server.client().stop();
DEBUG_PRINT("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);
//SAVE/connect here
//setSSID(urldecode(server.arg("s").c_str()));
//setPassword(urldecode(server.arg("p").c_str()));
_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(HTTP_SAVED);
server.sendContent(HTTP_END);
server.client().stop();
DEBUG_PRINT("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", "");
}
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 += "\nMethod: ";
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\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 );
}
/** 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
return true;
}
return false;
}
template <typename Generic>
void WiFiManager::DEBUG_PRINT(Generic text) {
if(_debug) {
Serial.print("*WM: ");
Serial.println(text);
}
}
/** Is this an IP? */
boolean WiFiManager::isIp(String str) {
for (int i = 0; i < str.length(); i++) {
int c = str.charAt(i);
if (c != '.' && (c < '0' || c > '9')) {
return false;
}
}
return true;
}
/** IP to String? */
String WiFiManager::toStringIp(IPAddress ip) {
String res = "";
for (int i = 0; i < 3; i++) {
res += String((ip >> (8 * i)) & 0xFF) + ".";
}
res += String(((ip >> 8 * 3)) & 0xFF);
return res;
}
+56 -25
View File
@@ -14,58 +14,67 @@
#include <ESP8266WiFi.h>
#include <EEPROM.h>
#include <ESP8266mDNS.h>
#include <WiFiClient.h>
#define DEBUG //until arduino ide can include defines at compile time from main sketch
#ifdef DEBUG
#define DEBUG_PRINT(x) Serial.println(x)
#else
#define DEBUG_PRINT(x)
#endif
//#include <EEPROM.h>
//#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
class WiFiManager
{
public:
WiFiManager(int eepromStart);
void begin();
void begin(char const *apName);
WiFiManager();
void begin();
void begin(char const *apName);
boolean autoConnect();
boolean autoConnect(char const *apName);
boolean hasConnected();
String beginConfigMode(void);
void startWebConfig();
String beginConfigMode(void);
void startWebConfig();
String getSSID();
String getPassword();
void resetSettings();
String getSSID();
String getPassword();
void setSSID(String s);
void setPassword(String p);
void resetSettings();
//for conveniennce
String urldecode(const char*);
String urldecode(const char*);
//sets timeout before webserver loop ends and exits even if there has been no setup.
//usefully for devices that failed to connect at some point and got stuck in a webserver loop
//in seconds
void setTimeout(unsigned long seconds);
void setTimeout(unsigned long seconds);
void setDebugOutput(boolean debug);
//sets a custom ip /gateway /subnet configuration
void setAPConfig(IPAddress ip, IPAddress gw, IPAddress sn);
int serverLoop();
private:
DNSServer dnsServer;
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 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;}</style>";
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='s'><input id='s' name='ssid' length=32 placeholder='SSID'><input id='p' name='pass' length=64 placeholder='password'><br/><input type='submit'></form>";
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>
//)=====";
int _eepromStart;
const char* _apName = "no-net";
@@ -73,13 +82,35 @@ private:
String _pass = "";
unsigned long timeout = 0;
unsigned long start = 0;
IPAddress _ip;
IPAddress _gw;
IPAddress _sn;
String getEEPROMString(int start, int len);
void setEEPROMString(int start, int len, String string);
int serverLoop();
bool keepLooping = true;
int status = WL_IDLE_STATUS;
void connectWifi(String ssid, String pass);
void handleRoot();
void handleWifi(bool scan);
void handleWifiSave();
void handleNotFound();
void handle204();
boolean captivePortal();
// DNS server
const byte DNS_PORT = 53;
boolean isIp(String str);
String toStringIp(IPAddress ip);
boolean connect;
boolean _debug = true;
template <typename Generic>
void DEBUG_PRINT(Generic text);
};
+25 -16
View File
@@ -2,29 +2,38 @@
//needed for library
#include <EEPROM.h>
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
//this intitilises the library, parameter is eeprom start
WiFiManager wifi(0);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
// put your setup code here, to run once:
Serial.begin(115200);
//WiFiManager
//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
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifi;
//reset saved settings
//wifi.resetSettings();
//set custom ip for portal
//wifi.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
//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");
//or use this for auto generated name ESP + ChipID
//wifi.autoConnect();
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
}
void loop() {
// put your main code here, to run repeatedly:
// put your main code here, to run repeatedly:
}
@@ -1,23 +1,31 @@
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
//needed for library
#include <EEPROM.h>
#include <ESP8266mDNS.h>
//#include <EEPROM.h>
//#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
//this intitilises the library, parameter is eeprom start
WiFiManager wifi(0);
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;
//reset settings - for testing
wifi.resetSettings();
//sets timeout until configuration portal gets turned off
//useful to make it all retry or go to sleep
//in seconds
wifi.setTimeout(120);
wifi.setTimeout(180);
//fetches ssid and pass from eeprom and tries to connect
//if it does not connect it starts an access point with the specified name
@@ -25,7 +33,7 @@ void setup() {
//and goes into a blocking loop awaiting configuration
if(!wifi.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);