diff --git a/README.md b/README.md index 62707b1..f65dae2 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ First attempt at a library. Lots more changes and fixes to do. Contributions are You can either install through the Arduino Library Manager or checkout the latest changes or a release from github #### Install through Library Manager -__Currently version 0.8 works with release 2.0.0 or newer of the [ESP8266 core for Arduino](https://github.com/esp8266/Arduino)__ +__Currently version 0.8+ works with release 2.0.0 or newer of the [ESP8266 core for Arduino](https://github.com/esp8266/Arduino)__ - in Arduino IDE got to Sketch/Include Library/Manage Libraries ![Manage Libraries](http://i.imgur.com/9BkEBkR.png) @@ -233,12 +233,18 @@ Changes added on 0.8 should make the latest trunk work without compilation error I am trying to keep releases working with release versions of the core, so they can be installed through boards manager, but if you checkout the latest version directly from github, sometimes, the library will only work if you update the ESP8266 core to the latest version because I am using some newly added function. - If you connect to the created configuration Access Point but the configuration portal does not show up, just open a browser and type in the IP of the web portal, by default `192.168.4.1`. +If trying to connect ends up in an endless loop, try to add `setConnectTimeout(60)` before `autoConnect();`. The parameter is timeout to try connecting in seconds. ## Releases -#### 0.9 +#### 0.10 +- some css changes +- bug fixes and speed improvements +- added an alternative to waitForConnectResult() for debugging +- changed `setTimeout(seconds)` to `setConfigPortalTimeout(seconds)` + +##### 0.9 - fixed support for encoded characters in ssid/pass ##### 0.8 @@ -284,6 +290,8 @@ The support and help I got from the community has been nothing short of phenomen __THANK YOU__ +[Shawn A](https://github.com/tablatronix) + [Maximiliano Duarte](https://github.com/domonetic) [alltheblinkythings](https://github.com/alltheblinkythings) diff --git a/WiFiManager.cpp b/WiFiManager.cpp index 45ffb9f..25f5823 100644 --- a/WiFiManager.cpp +++ b/WiFiManager.cpp @@ -12,7 +12,24 @@ #include "WiFiManager.h" +WiFiManagerParameter::WiFiManagerParameter(const char *custom) { + _id = NULL; + _placeholder = NULL; + _length = 0; + _value = NULL; + + _customHTML = custom; +} + WiFiManagerParameter::WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length) { + init(id, placeholder, defaultValue, length, ""); +} + +WiFiManagerParameter::WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom) { + init(id, placeholder, defaultValue, length, custom); +} + +void WiFiManagerParameter::init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom) { _id = id; _placeholder = placeholder; _length = length; @@ -23,6 +40,8 @@ WiFiManagerParameter::WiFiManagerParameter(const char *id, const char *placehold if (defaultValue != NULL) { strncpy(_value, defaultValue, length); } + + _customHTML = custom; } const char* WiFiManagerParameter::getValue() { @@ -37,6 +56,9 @@ const char* WiFiManagerParameter::getPlaceholder() { int WiFiManagerParameter::getValueLength() { return _length; } +const char* WiFiManagerParameter::getCustomHTML() { + return _customHTML; +} WiFiManager::WiFiManager() { } @@ -129,8 +151,8 @@ boolean WiFiManager::autoConnect(char const *apName, char const *apPassword) { boolean WiFiManager::startConfigPortal(char const *apName, char const *apPassword) { //setup AP - WiFi.mode(WIFI_AP); - DEBUG_WM("SET AP"); + WiFi.mode(WIFI_AP_STA); + DEBUG_WM("SET AP STA"); _apName = apName; _apPassword = apPassword; @@ -198,13 +220,26 @@ int WiFiManager::connectWifi(String ssid, String pass) { WiFi.config(_sta_static_ip, _sta_static_gw, _sta_static_sn); DEBUG_WM(WiFi.localIP()); } - + //fix for auto connect racing issue + if (WiFi.status() == WL_CONNECTED) { + DEBUG_WM("Already connected. Bailing out."); + return WL_CONNECTED; + } //check if we have ssid and pass and force those, if not, try with last saved values if (ssid != "") { WiFi.begin(ssid.c_str(), pass.c_str()); } else { - DEBUG_WM("Using last saved values, should be faster"); - WiFi.begin(); + if(WiFi.SSID()) { + DEBUG_WM("Using last saved values, should be faster"); + //trying to fix connection in progress hanging + ETS_UART_INTR_DISABLE(); + wifi_station_disconnect(); + ETS_UART_INTR_ENABLE(); + + WiFi.begin(); + } else { + DEBUG_WM("No saved credentials"); + } } int connRes = waitForConnectResult(); @@ -325,6 +360,7 @@ void WiFiManager::handleRoot() { page.replace("{v}", "Options"); page += FPSTR(HTTP_SCRIPT); page += FPSTR(HTTP_STYLE); + page += _customHeadElement; page += FPSTR(HTTP_HEAD_END); page += "

"; page += _apName; @@ -344,6 +380,7 @@ void WiFiManager::handleWifi(boolean scan) { page.replace("{v}", "Config ESP"); page += FPSTR(HTTP_SCRIPT); page += FPSTR(HTTP_STYLE); + page += _customHeadElement; page += FPSTR(HTTP_HEAD_END); if (scan) { @@ -354,13 +391,13 @@ void WiFiManager::handleWifi(boolean scan) { page += F("No networks found. Refresh to scan again."); } else { //sort networks - int indices[n]; + /*int indices[n]; - for (int i = 0; i < n; i++) { + for (int i = 0; i < n; i++) { indices[i] = i; - } + } - for (int i = 0; i < n; i++) { + for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { //int temp = indices[j]; @@ -369,8 +406,19 @@ void WiFiManager::handleWifi(boolean scan) { std::swap(indices[i], indices[j]); } } + } + */ + int indices[n]; + for (int i = 0; i < n; i++) { + indices[i] = i; } + std::sort(indices, indices + n, [](const int & a, const int & b) -> bool + { + return WiFi.RSSI(a) > WiFi.RSSI(b); + }); + + //display networks in page for (int i = 0; i < n; i++) { DEBUG_WM(WiFi.SSID(indices[i])); @@ -409,12 +457,17 @@ void WiFiManager::handleWifi(boolean scan) { } String pitem = FPSTR(HTTP_FORM_PARAM); - 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()); - pitem.replace("{l}", parLength); - pitem.replace("{v}", _params[i]->getValue()); + if (_params[i]->getID() != NULL) { + 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()); + pitem.replace("{l}", parLength); + pitem.replace("{v}", _params[i]->getValue()); + pitem.replace("{c}", _params[i]->getCustomHTML()); + } else { + pitem = _params[i]->getCustomHTML(); + } page += pitem; } @@ -511,6 +564,7 @@ void WiFiManager::handleWifiSave() { page.replace("{v}", "Credentials Saved"); page += FPSTR(HTTP_SCRIPT); page += FPSTR(HTTP_STYLE); + page += _customHeadElement; page += FPSTR(HTTP_HEAD_END); page += FPSTR(HTTP_SAVED); page += FPSTR(HTTP_END); @@ -530,6 +584,7 @@ void WiFiManager::handleInfo() { page.replace("{v}", "Info"); page += FPSTR(HTTP_SCRIPT); page += FPSTR(HTTP_STYLE); + page += _customHeadElement; page += FPSTR(HTTP_HEAD_END); page += F("
"); page += F("
Chip ID
"); @@ -569,6 +624,7 @@ void WiFiManager::handleReset() { page.replace("{v}", "Info"); page += FPSTR(HTTP_SCRIPT); page += FPSTR(HTTP_STYLE); + page += _customHeadElement; page += FPSTR(HTTP_HEAD_END); page += F("Module will reset in a few seconds."); page += FPSTR(HTTP_END); @@ -636,6 +692,12 @@ void WiFiManager::setSaveConfigCallback( void (*func)(void) ) { _savecallback = func; } +//sets a custom element to add to head, like a new style tag +void WiFiManager::setCustomHeadElement(const char* element) { + _customHeadElement = element; +} + + template @@ -679,5 +741,3 @@ String WiFiManager::toStringIp(IPAddress ip) { res += String(((ip >> 8 * 3)) & 0xFF); return res; } - - diff --git a/WiFiManager.h b/WiFiManager.h index 512d51f..0902e86 100644 --- a/WiFiManager.h +++ b/WiFiManager.h @@ -17,39 +17,49 @@ #include #include #include +#undef min +#undef max +#include +extern "C" { + #include "user_interface.h" +} - -const char HTTP_200[] PROGMEM = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"; -const char HTTP_HEAD[] PROGMEM = "{v}"; -const char HTTP_STYLE[] PROGMEM = ""; -const char HTTP_SCRIPT[] PROGMEM = ""; -const char HTTP_HEAD_END[] PROGMEM = "
"; -const char HTTP_PORTAL_OPTIONS[] PROGMEM = "



"; -const char HTTP_ITEM[] PROGMEM = "
{v} {r}%
"; +const char HTTP_200[] PROGMEM = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"; +const char HTTP_HEAD[] PROGMEM = "{v}"; +const char HTTP_STYLE[] PROGMEM = ""; +const char HTTP_SCRIPT[] PROGMEM = ""; +const char HTTP_HEAD_END[] PROGMEM = "
"; +const char HTTP_PORTAL_OPTIONS[] PROGMEM = "



"; +const char HTTP_ITEM[] PROGMEM = "
{v} {r}%
"; //const char HTTP_ITEM_PADLOCK[] PROGMEM = ""; -const char HTTP_FORM_START[] PROGMEM = "


"; -const char HTTP_FORM_PARAM[] PROGMEM = "
"; -const char HTTP_FORM_END[] PROGMEM = "
"; -const char HTTP_SCAN_LINK[] PROGMEM = "
"; - -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 = "
"; +const char HTTP_FORM_START[] PROGMEM = "


"; +const char HTTP_FORM_PARAM[] PROGMEM = "
"; +const char HTTP_FORM_END[] PROGMEM = "
"; +const char HTTP_SCAN_LINK[] PROGMEM = "
"; +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 = "
"; #define WIFI_MANAGER_MAX_PARAMS 10 class WiFiManagerParameter { public: + 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); const char *getID(); const char *getValue(); const char *getPlaceholder(); int getValueLength(); + const char *getCustomHTML(); private: const char *_id; const char *_placeholder; char *_value; int _length; + const char *_customHTML; + + void init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom); friend class WiFiManager; }; @@ -80,13 +90,13 @@ class WiFiManager //sets timeout for which to attempt connecting, usefull if you get a lot of failed connects void setConnectTimeout(unsigned long seconds); - + void setDebugOutput(boolean debug); //defaults to not showing anything under 8% signal quality if called void setMinimumSignalQuality(int quality = 8); //sets a custom ip /gateway /subnet configuration void setAPStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn); - //sets config for a static IP + //sets config for a static IP void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn); //called when AP mode and config portal is started void setAPCallback( void (*func)(WiFiManager*) ); @@ -97,6 +107,10 @@ class WiFiManager //if this is set, it will exit after config, even if connection is unsucessful. void setBreakAfterConfig(boolean shouldBreak); //if this is set, try WPS setup when starting (this will delay config portal for up to 2 mins) + //TODO + //if this is set, customise style + void setCustomHeadElement(const char* element); + private: std::unique_ptr dnsServer; @@ -117,19 +131,21 @@ class WiFiManager unsigned long _configPortalTimeout = 0; unsigned long _connectTimeout = 0; unsigned long _configPortalStart = 0; - + IPAddress _ap_static_ip; IPAddress _ap_static_gw; IPAddress _ap_static_sn; IPAddress _sta_static_ip; IPAddress _sta_static_gw; IPAddress _sta_static_sn; - + int _paramsCount = 0; int _minimumQuality = -1; boolean _shouldBreakAfterConfig = false; boolean _tryWPS = false; + const char* _customHeadElement = ""; + //String getEEPROMString(int start, int len); //void setEEPROMString(int start, int len, String string); @@ -145,7 +161,7 @@ class WiFiManager void handleNotFound(); void handle204(); boolean captivePortal(); - + // DNS server const byte DNS_PORT = 53; @@ -167,11 +183,11 @@ class WiFiManager template auto optionalIPFromString(T *obj, const char *s) -> decltype( obj->fromString(s) ) { - return obj->fromString(s); + return obj->fromString(s); } auto optionalIPFromString(...) -> bool { - DEBUG_WM("NO fromString METHOD ON IPAddress, you need ESP8266 core 2.1.0 or newer for Custom IP configuration to work."); - return false; + DEBUG_WM("NO fromString METHOD ON IPAddress, you need ESP8266 core 2.1.0 or newer for Custom IP configuration to work."); + return false; } };