diff --git a/lib/WiFiManager/README.md b/lib/WiFiManager/README.md index a329f2b..3782339 100644 --- a/lib/WiFiManager/README.md +++ b/lib/WiFiManager/README.md @@ -1,3 +1,5 @@ +## Current development going on here :arrow_right: [Development Branch](https://github.com/tzapu/WiFiManager/tree/development) + # WiFiManager ESP8266 WiFi Connection manager with fallback web configuration portal @@ -43,16 +45,19 @@ First attempt at a library. Lots more changes and fixes to do. Contributions are ![ESP8266 WiFi Captive Portal Homepage](http://i.imgur.com/YPvW9eql.png) ![ESP8266 WiFi Captive Portal Configuration](http://i.imgur.com/oicWJ4gl.png) ## Wishlist -- ~~remove dependency on EEPROM library~~ -- ~~move HTML Strings to PROGMEM~~ -- ~~cleanup and streamline code~~ (although this is ongoing) -- 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~~ -- ~~add to Arduino Library Manager~~ -- ~~add to PlatformIO~~ -- add multiple sets of network credentials -- ~~allow users to customize CSS~~ +- [x] remove dependency on EEPROM library +- [x] move HTML Strings to PROGMEM +- [x] cleanup and streamline code (although this is ongoing) +- [x] if timeout is set, extend it when a page is fetched in AP mode +- [x] add ability to configure more parameters than ssid/password +- [x] maybe allow setting ip of ESP after reboot +- [x] add to Arduino Library Manager +- [x] add to PlatformIO +- [ ] add multiple sets of network credentials +- [x] allow users to customize CSS +- [ ] ESP32 support or instructions +- [ ] rewrite documentation for simplicity, based on scenarios/goals +- [ ] rely on the SDK's built in auto connect more than forcing a connect ## Quick Start diff --git a/lib/WiFiManager/WiFiManager.cpp b/lib/WiFiManager/WiFiManager.cpp index 3fbbb42..2e7884d 100644 --- a/lib/WiFiManager/WiFiManager.cpp +++ b/lib/WiFiManager/WiFiManager.cpp @@ -5,7 +5,7 @@ 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 + https://github.com/esp8266/Arduino/tree/master/libraries/DNSServer/examples/CaptivePortalAdvanced Built by AlexT https://github.com/tzapu Licensed under MIT license **************************************************************/ @@ -34,7 +34,7 @@ void WiFiManagerParameter::init(const char *id, const char *placeholder, const c _placeholder = placeholder; _length = length; _value = new char[length + 1]; - for (int i = 0; i < length; i++) { + for (int i = 0; i < length + 1; i++) { _value[i] = 0; } if (defaultValue != NULL) { @@ -44,6 +44,12 @@ void WiFiManagerParameter::init(const char *id, const char *placeholder, const c _customHTML = custom; } +WiFiManagerParameter::~WiFiManagerParameter() { + if (_value != NULL) { + delete[] _value; + } +} + const char* WiFiManagerParameter::getValue() { return _value; } @@ -60,14 +66,42 @@ const char* WiFiManagerParameter::getCustomHTML() { return _customHTML; } + WiFiManager::WiFiManager() { + _max_params = WIFI_MANAGER_MAX_PARAMS; + _params = (WiFiManagerParameter**)malloc(_max_params * sizeof(WiFiManagerParameter*)); } -void WiFiManager::addParameter(WiFiManagerParameter *p) { +WiFiManager::~WiFiManager() +{ + if (_params != NULL) + { + DEBUG_WM(F("freeing allocated params!")); + free(_params); + } +} + +bool WiFiManager::addParameter(WiFiManagerParameter *p) { + if(_paramsCount + 1 > _max_params) + { + // rezise the params array + _max_params += WIFI_MANAGER_MAX_PARAMS; + DEBUG_WM(F("Increasing _max_params to:")); + DEBUG_WM(_max_params); + WiFiManagerParameter** new_params = (WiFiManagerParameter**)realloc(_params, _max_params * sizeof(WiFiManagerParameter*)); + if (new_params != NULL) { + _params = new_params; + } else { + DEBUG_WM(F("ERROR: failed to realloc params, size not increased!")); + return false; + } + } + _params[_paramsCount] = p; _paramsCount++; - DEBUG_WM("Adding parameter"); + DEBUG_WM(F("Adding parameter")); DEBUG_WM(p->getID()); + return true; } void WiFiManager::setupConfigPortal() { @@ -109,14 +143,14 @@ void WiFiManager::setupConfigPortal() { 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("/i", std::bind(&WiFiManager::handleInfo, this)); - server->on("/r", std::bind(&WiFiManager::handleReset, this)); + server->on(String(F("/")), std::bind(&WiFiManager::handleRoot, this)); + server->on(String(F("/wifi")), std::bind(&WiFiManager::handleWifi, this, true)); + server->on(String(F("/0wifi")), std::bind(&WiFiManager::handleWifi, this, false)); + server->on(String(F("/wifisave")), std::bind(&WiFiManager::handleWifiSave, this)); + server->on(String(F("/i")), std::bind(&WiFiManager::handleInfo, this)); + server->on(String(F("/r")), std::bind(&WiFiManager::handleReset, 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->on(String(F("/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_WM(F("HTTP server started")); @@ -149,10 +183,34 @@ boolean WiFiManager::autoConnect(char const *apName, char const *apPassword) { return startConfigPortal(apName, apPassword); } +boolean WiFiManager::configPortalHasTimeout(){ + if(_configPortalTimeout == 0 || wifi_softap_get_station_num() > 0){ + _configPortalStart = millis(); // kludge, bump configportal start time to skew timeouts + return false; + } + return (millis() > _configPortalStart + _configPortalTimeout); +} + +boolean WiFiManager::startConfigPortal() { + String ssid = "ESP" + String(ESP.getChipId()); + return startConfigPortal(ssid.c_str(), NULL); +} + boolean WiFiManager::startConfigPortal(char const *apName, char const *apPassword) { - //setup AP - WiFi.mode(WIFI_AP_STA); - DEBUG_WM("SET AP STA"); + + if(!WiFi.isConnected()){ + WiFi.persistent(false); + // disconnect sta, start ap + WiFi.disconnect(); // this alone is not enough to stop the autoconnecter + WiFi.mode(WIFI_AP); + WiFi.persistent(true); + } + else { + //setup AP + WiFi.mode(WIFI_AP_STA); + DEBUG_WM(F("SET AP STA")); + } + _apName = apName; _apPassword = apPassword; @@ -165,7 +223,11 @@ boolean WiFiManager::startConfigPortal(char const *apName, char const *apPasswo connect = false; setupConfigPortal(); - while (_configPortalTimeout == 0 || millis() < _configPortalStart + _configPortalTimeout) { + while(1){ + + // check if timeout + if(configPortalHasTimeout()) break; + //DNS dnsServer->processNextRequest(); //HTTP @@ -222,7 +284,7 @@ int WiFiManager::connectWifi(String ssid, String pass) { } //fix for auto connect racing issue if (WiFi.status() == WL_CONNECTED) { - DEBUG_WM("Already connected. Bailing out."); + DEBUG_WM(F("Already connected. Bailing out.")); return WL_CONNECTED; } //check if we have ssid and pass and force those, if not, try with last saved values @@ -230,7 +292,7 @@ int WiFiManager::connectWifi(String ssid, String pass) { WiFi.begin(ssid.c_str(), pass.c_str()); } else { if (WiFi.SSID()) { - DEBUG_WM("Using last saved values, should be faster"); + DEBUG_WM(F("Using last saved values, should be faster")); //trying to fix connection in progress hanging ETS_UART_INTR_DISABLE(); wifi_station_disconnect(); @@ -238,7 +300,7 @@ int WiFiManager::connectWifi(String ssid, String pass) { WiFi.begin(); } else { - DEBUG_WM("No saved credentials"); + DEBUG_WM(F("No saved credentials")); } } @@ -246,11 +308,13 @@ int WiFiManager::connectWifi(String ssid, String pass) { DEBUG_WM ("Connection result: "); DEBUG_WM ( connRes ); //not connected, WPS enabled, no pass - first attempt + #ifdef NO_EXTRA_4K_HEAP if (_tryWPS && connRes != WL_CONNECTED && pass == "") { startWPS(); //should be connected at the end of WPS connRes = waitForConnectResult(); } + #endif return connRes; } @@ -278,9 +342,9 @@ uint8_t WiFiManager::waitForConnectResult() { } void WiFiManager::startWPS() { - DEBUG_WM("START WPS"); + DEBUG_WM(F("START WPS")); WiFi.beginWPSConfig(); - DEBUG_WM("END WPS"); + DEBUG_WM(F("END WPS")); } /* String WiFiManager::getSSID() { @@ -362,13 +426,14 @@ void WiFiManager::handleRoot() { page += FPSTR(HTTP_STYLE); page += _customHeadElement; page += FPSTR(HTTP_HEAD_END); - page += "

"; + page += String(F("

")); page += _apName; - page += "

"; - page += F("

WiFiManager

"); + page += String(F("")); + page += String(F("

WiFiManager

")); page += FPSTR(HTTP_PORTAL_OPTIONS); page += FPSTR(HTTP_END); + server->sendHeader("Content-Length", String(page.length())); server->send(200, "text/html", page); } @@ -459,7 +524,7 @@ void WiFiManager::handleWifi(boolean scan) { } page += FPSTR(HTTP_FORM_START); - char parLength[2]; + char parLength[5]; // add the extra parameters to the form for (int i = 0; i < _paramsCount; i++) { if (_params[i] == NULL) { @@ -471,7 +536,7 @@ void WiFiManager::handleWifi(boolean scan) { pitem.replace("{i}", _params[i]->getID()); pitem.replace("{n}", _params[i]->getID()); pitem.replace("{p}", _params[i]->getPlaceholder()); - snprintf(parLength, 2, "%d", _params[i]->getValueLength()); + snprintf(parLength, 5, "%d", _params[i]->getValueLength()); pitem.replace("{l}", parLength); pitem.replace("{v}", _params[i]->getValue()); pitem.replace("{c}", _params[i]->getCustomHTML()); @@ -522,6 +587,7 @@ void WiFiManager::handleWifi(boolean scan) { page += FPSTR(HTTP_END); + server->sendHeader("Content-Length", String(page.length())); server->send(200, "text/html", page); @@ -544,7 +610,7 @@ void WiFiManager::handleWifiSave() { //read parameter String value = server->arg(_params[i]->getID()).c_str(); //store it in array - value.toCharArray(_params[i]->_value, _params[i]->_length); + value.toCharArray(_params[i]->_value, _params[i]->_length + 1); DEBUG_WM(F("Parameter")); DEBUG_WM(_params[i]->getID()); DEBUG_WM(value); @@ -579,6 +645,7 @@ void WiFiManager::handleWifiSave() { page += FPSTR(HTTP_SAVED); page += FPSTR(HTTP_END); + server->sendHeader("Content-Length", String(page.length())); server->send(200, "text/html", page); DEBUG_WM(F("Sent wifi save page")); @@ -621,6 +688,7 @@ void WiFiManager::handleInfo() { page += F(""); page += FPSTR(HTTP_END); + server->sendHeader("Content-Length", String(page.length())); server->send(200, "text/html", page); DEBUG_WM(F("Sent info page")); @@ -638,6 +706,8 @@ void WiFiManager::handleReset() { page += FPSTR(HTTP_HEAD_END); page += F("Module will reset in a few seconds."); page += FPSTR(HTTP_END); + + server->sendHeader("Content-Length", String(page.length())); server->send(200, "text/html", page); DEBUG_WM(F("Sent reset page")); @@ -646,17 +716,6 @@ void WiFiManager::handleReset() { delay(2000); } - - -//removed as mentioned here https://github.com/tzapu/WiFiManager/issues/114 -/*void WiFiManager::handle204() { - DEBUG_WM(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; @@ -676,6 +735,7 @@ void WiFiManager::handleNotFound() { server->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); server->sendHeader("Pragma", "no-cache"); server->sendHeader("Expires", "-1"); + server->sendHeader("Content-Length", String(message.length())); server->send ( 404, "text/plain", message ); } @@ -737,7 +797,7 @@ int WiFiManager::getRSSIasQuality(int RSSI) { /** Is this an IP? */ boolean WiFiManager::isIp(String str) { - for (int i = 0; i < str.length(); i++) { + for (size_t i = 0; i < str.length(); i++) { int c = str.charAt(i); if (c != '.' && (c < '0' || c > '9')) { return false; diff --git a/lib/WiFiManager/WiFiManager.h b/lib/WiFiManager/WiFiManager.h index 827c985..3da163e 100644 --- a/lib/WiFiManager/WiFiManager.h +++ b/lib/WiFiManager/WiFiManager.h @@ -5,7 +5,7 @@ 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 + https://github.com/esp8266/Arduino/tree/master/libraries/DNSServer/examples/CaptivePortalAdvanced Built by AlexT https://github.com/tzapu Licensed under MIT license **************************************************************/ @@ -29,19 +29,26 @@ const char HTTP_HEAD_END[] PROGMEM = "
{v} {r}%
"; const char HTTP_FORM_START[] PROGMEM = "


"; -const char HTTP_FORM_PARAM[] PROGMEM = "
"; +const char HTTP_FORM_PARAM[] PROGMEM = "
"; const char HTTP_FORM_END[] PROGMEM = "
"; const char HTTP_SCAN_LINK[] PROGMEM = "
Scan
"; const char HTTP_SAVED[] PROGMEM = "
Credentials Saved
Trying to connect ESP to network.
If it fails reconnect to AP to try again
"; const char HTTP_END[] PROGMEM = ""; +#ifndef WIFI_MANAGER_MAX_PARAMS #define WIFI_MANAGER_MAX_PARAMS 10 +#endif class WiFiManagerParameter { public: + /** + Create custom parameters that can be added to the WiFiManager setup web page + @id is used for HTTP queries and must not contain spaces nor other special characters + */ WiFiManagerParameter(const char *custom); WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length); WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom); + ~WiFiManagerParameter(); const char *getID(); const char *getValue(); @@ -65,11 +72,13 @@ class WiFiManager { public: WiFiManager(); + ~WiFiManager(); boolean autoConnect(); boolean autoConnect(char const *apName, char const *apPassword = NULL); //if you want to always start the config portal, without trying to connect first + boolean startConfigPortal(); boolean startConfigPortal(char const *apName, char const *apPassword = NULL); // get the AP name of the config portal, so it can be used in the callback @@ -78,12 +87,12 @@ class WiFiManager void resetSettings(); //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 + //useful for devices that failed to connect at some point and got stuck in a webserver loop //in seconds setConfigPortalTimeout is a new name for setTimeout void setConfigPortalTimeout(unsigned long seconds); void setTimeout(unsigned long seconds); - //sets timeout for which to attempt connecting, usefull if you get a lot of failed connects + //sets timeout for which to attempt connecting, useful if you get a lot of failed connects void setConnectTimeout(unsigned long seconds); @@ -98,9 +107,9 @@ class WiFiManager void setAPCallback( void (*func)(WiFiManager*) ); //called when settings have been changed and connection was successful void setSaveConfigCallback( void (*func)(void) ); - //adds a custom parameter - void addParameter(WiFiManagerParameter *p); - //if this is set, it will exit after config, even if connection is unsucessful. + //adds a custom parameter, returns false on failure + bool addParameter(WiFiManagerParameter *p); + //if this is set, it will exit after config, even if connection is unsuccessful. void setBreakAfterConfig(boolean shouldBreak); //if this is set, try WPS setup when starting (this will delay config portal for up to 2 mins) //TODO @@ -159,6 +168,7 @@ class WiFiManager void handleNotFound(); void handle204(); boolean captivePortal(); + boolean configPortalHasTimeout(); // DNS server const byte DNS_PORT = 53; @@ -174,7 +184,8 @@ class WiFiManager void (*_apcallback)(WiFiManager*) = NULL; void (*_savecallback)(void) = NULL; - WiFiManagerParameter* _params[WIFI_MANAGER_MAX_PARAMS]; + int _max_params; + WiFiManagerParameter** _params; template void DEBUG_WM(Generic text); diff --git a/lib/WiFiManager/examples/AutoConnect/AutoConnect.ino b/lib/WiFiManager/examples/AutoConnect/AutoConnect.ino index 37ff392..0c44909 100644 --- a/lib/WiFiManager/examples/AutoConnect/AutoConnect.ino +++ b/lib/WiFiManager/examples/AutoConnect/AutoConnect.ino @@ -17,7 +17,7 @@ void setup() { //wifiManager.resetSettings(); //set custom ip for portal - //wifiManager.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); + //wifiManager.setAPStaticIPConfig(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 diff --git a/lib/WiFiManager/examples/AutoConnectWithFSParameters/AutoConnectWithFSParameters.ino b/lib/WiFiManager/examples/AutoConnectWithFSParameters/AutoConnectWithFSParameters.ino index 1d58e5c..7e6c373 100644 --- a/lib/WiFiManager/examples/AutoConnectWithFSParameters/AutoConnectWithFSParameters.ino +++ b/lib/WiFiManager/examples/AutoConnectWithFSParameters/AutoConnectWithFSParameters.ino @@ -61,6 +61,7 @@ void setup() { } else { Serial.println("failed to load json config"); } + configFile.close(); } } } else { diff --git a/lib/WiFiManager/examples/OnDemandConfigPortal/OnDemandConfigPortal.ino b/lib/WiFiManager/examples/OnDemandConfigPortal/OnDemandConfigPortal.ino index edf4f46..2f2d0cc 100644 --- a/lib/WiFiManager/examples/OnDemandConfigPortal/OnDemandConfigPortal.ino +++ b/lib/WiFiManager/examples/OnDemandConfigPortal/OnDemandConfigPortal.ino @@ -5,7 +5,7 @@ #include #include //https://github.com/tzapu/WiFiManager -// select wich pin will trigger the configuraton portal when set to LOW +// select which pin will trigger the configuration portal when set to LOW // ESP-01 users please note: the only pins available (0 and 2), are shared // with the bootloader, so always set them HIGH at power-up #define TRIGGER_PIN 0 diff --git a/lib/WiFiManager/extras/WiFiManager.template.html b/lib/WiFiManager/extras/WiFiManager.template.html index 0cf8604..e15593b 100644 --- a/lib/WiFiManager/extras/WiFiManager.template.html +++ b/lib/WiFiManager/extras/WiFiManager.template.html @@ -1,38 +1,80 @@ -{v} - + + + + + + {v} + + + + + + + + + + +
+ - -
- - - + -
{v} {r}%
-
PMisa 100%
- -
PMisa 8%
- - - -
- - -


-
-
-

-
-
- + + + + +



+ + +
{v} {r}%
+
PMisa 100%
+ +
PMisa 8%
+ + +
{v} {r}%
+ + +


+ + +
+ + +
+ + +
+ + +
Credentials Saved
Trying to connect ESP to network.
If it fails reconnect to AP to try again
+ + + + + +
- \ No newline at end of file + + + diff --git a/lib/WiFiManager/extras/parse.js b/lib/WiFiManager/extras/parse.js new file mode 100644 index 0000000..97a3e38 --- /dev/null +++ b/lib/WiFiManager/extras/parse.js @@ -0,0 +1,60 @@ +'use strict'; + +const fs = require('fs'); + +console.log('starting'); + +const inFile = 'WiFiManager.template.html'; +const outFile = 'template.h'; + +const defineRegEx = //gm; +console.log('parsing', inFile); + +fs.readFile(inFile, 'utf8', function (err,data) { + if (err) { + return console.log(err); + } + //console.log(data); + + let defines = data.match(defineRegEx); + + //console.log(defines); + var stream = fs.createWriteStream(outFile); + stream.once('open', function(fd) { + for (const i in defines) { + + const start = defines[i]; + const end = start.replace('