diff --git a/WiFiManager.cpp b/WiFiManager.cpp index fc79a72..a8edd42 100644 --- a/WiFiManager.cpp +++ b/WiFiManager.cpp @@ -1,33 +1,67 @@ /************************************************************** - * WiFiManager is a library for the ESP8266/Arduino platform - * (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 - * 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 + WiFiManager is a library for the ESP8266/Arduino platform + (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 + 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" +WiFiManagerParameter::WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length) { + _id = id; + _placeholder = placeholder; + _length = length; + _value = new char[length]; + for (int i = 0; i < length; i++) { + _value[i] = 0; + } + if (defaultValue != NULL) { + strncpy(_value, defaultValue, length); + } +} + +const char* WiFiManagerParameter::getValue() { + return _value; +} +const char* WiFiManagerParameter::getID() { + return _id; +} +const char* WiFiManagerParameter::getPlaceholder() { + return _placeholder; +} +int WiFiManagerParameter::getValueLength() { + return _length; +} + WiFiManager::WiFiManager() { } +void WiFiManager::addParameter(WiFiManagerParameter *p) { + _params[_paramsCount] = p; + _paramsCount++; + DEBUG_PRINT("Adding parameter"); + DEBUG_PRINT(p->getID()); +} + + void WiFiManager::begin() { begin("NoNetESP"); } void WiFiManager::begin(char const *apName) { - begin(apName,NULL); + begin(apName, NULL); } void WiFiManager::begin(char const *apName, char const *apPasswd) { dnsServer.reset(new DNSServer()); server.reset(new ESP8266WebServer(80)); - + DEBUG_PRINT(F("")); _apName = apName; _apPasswd = apPasswd; @@ -36,9 +70,9 @@ void WiFiManager::begin(char const *apName, char const *apPasswd) { 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")); + if (strlen(_apPasswd) < 8 || strlen(_apPasswd) > 63) { + // fail passphrase to short or long! + DEBUG_PRINT(F("Invalid AccessPoint password")); } DEBUG_PRINT(_apPasswd); } @@ -59,7 +93,7 @@ void WiFiManager::begin(char const *apName, char const *apPasswd) { DEBUG_PRINT(F("AP IP address: ")); DEBUG_PRINT(WiFi.softAPIP()); - /* Setup the DNS server redirecting all the domains to the apIP */ + /* Setup the DNS server redirecting all the domains to the apIP */ dnsServer->setErrorReplyCode(DNSReplyCode::NoError); dnsServer->start(DNS_PORT, "*", WiFi.softAPIP()); @@ -77,24 +111,24 @@ void WiFiManager::begin(char const *apName, char const *apPasswd) { boolean WiFiManager::autoConnect() { String ssid = "ESP" + String(ESP.getChipId()); - return autoConnect(ssid.c_str(),NULL); + return autoConnect(ssid.c_str(), NULL); } boolean WiFiManager::autoConnect(char const *apName) { - return autoConnect(apName,NULL); + 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(); String pass = getPassword(); //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(); @@ -104,26 +138,26 @@ boolean WiFiManager::autoConnect(char const *apName, char const *apPasswd) { //connected return true; } - + //not connected //setup AP WiFi.mode(WIFI_AP); //notify we entered AP mode - if( _apcallback != NULL) { + if ( _apcallback != NULL) { _apcallback(); } connect = false; - begin(apName,apPasswd); + begin(apName, apPasswd); bool looping = true; - while(timeout == 0 || millis() < start + timeout) { + while (timeout == 0 || millis() < start + timeout) { //DNS dnsServer->processNextRequest(); //HTTP server->handleClient(); - - if(connect) { + + if (connect) { delay(2000); DEBUG_PRINT(F("Connecting to new AP")); connect = false; @@ -138,13 +172,18 @@ boolean WiFiManager::autoConnect(char const *apName, char const *apPasswd) { //delay(1000); //return false; } else { - //connected + //connected WiFi.mode(WIFI_STA); + //notify that configuration has changed and any optional parameters should be saved + if ( _savecallback != NULL) { + //todo: check if any custom parameters actually exist, and check if they really changed maybe + _savecallback(); + } break; } - + } - yield(); + yield(); } server.reset(); @@ -184,7 +223,7 @@ String WiFiManager::getPassword() { } /* -String WiFiManager::getEEPROMString(int start, int len) { + String WiFiManager::getEEPROMString(int start, int len) { EEPROM.begin(512); delay(10); String string = ""; @@ -194,10 +233,10 @@ String WiFiManager::getEEPROMString(int start, int len) { } EEPROM.end(); return string; -} + } */ /* -void WiFiManager::setEEPROMString(int start, int len, String string) { + void WiFiManager::setEEPROMString(int start, int len, String string) { EEPROM.begin(512); delay(10); int si = 0; @@ -215,7 +254,7 @@ void WiFiManager::setEEPROMString(int start, int len, String string) { } EEPROM.end(); DEBUG_PRINT(F("Wrote " + string); -}*/ + }*/ String WiFiManager::urldecode(const char *src) { @@ -301,7 +340,7 @@ void WiFiManager::handleRoot() { server->sendContent(title); server->sendContent(F("

WiFiManager

")); - + server->sendContent_P(HTTP_PORTAL_OPTIONS); server->sendContent_P(HTTP_END); @@ -340,7 +379,7 @@ void WiFiManager::handleWifi(bool scan) { rssiQ += getRSSIasQuality(WiFi.RSSI(i)); item.replace("{v}", WiFi.SSID(i)); item.replace("{r}", rssiQ); - if(WiFi.encryptionType(i) != ENC_TYPE_NONE) { + if (WiFi.encryptionType(i) != ENC_TYPE_NONE) { item.replace("{i}", FPSTR(HTTP_ITEM_PADLOCK)); } else { item.replace("{i}", ""); @@ -352,12 +391,34 @@ void WiFiManager::handleWifi(bool scan) { server->sendContent("
"); } } - - server->sendContent_P(HTTP_FORM); + + server->sendContent_P(HTTP_FORM_START); + char parLength[2]; + // add the extra parameters to the form + for (int i = 0; i < _paramsCount; i++) { + if (_params[i] == NULL) { + break; + } + + 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()); + + server->sendContent(pitem); + } + if (_params[0] != NULL) { + server->sendContent_P("
"); + } + + server->sendContent_P(HTTP_FORM_END); server->sendContent_P(HTTP_END); server->client().stop(); - - DEBUG_PRINT(F("Sent config page")); + + DEBUG_PRINT(F("Sent config page")); } /** Handle the WLAN save form and redirect to WLAN config page again */ @@ -368,6 +429,20 @@ void WiFiManager::handleWifiSave() { _ssid = urldecode(server->arg("s").c_str()); _pass = urldecode(server->arg("p").c_str()); + //parameters + for (int i = 0; i < _paramsCount; i++) { + if (_params[i] == NULL) { + break; + } + //read parameter + String value = urldecode(server->arg(_params[i]->getID()).c_str()); + //store it in array + value.toCharArray(_params[i]->_value, _params[i]->_length); + DEBUG_PRINT(F("Parameter")); + DEBUG_PRINT(_params[i]->getID()); + DEBUG_PRINT(value); + } + server->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); server->sendHeader("Pragma", "no-cache"); server->sendHeader("Expires", "-1"); @@ -379,19 +454,19 @@ void WiFiManager::handleWifiSave() { server->sendContent_P(HTTP_SCRIPT); server->sendContent_P(HTTP_STYLE); server->sendContent_P(HTTP_HEAD_END); - + server->sendContent_P(HTTP_SAVED); server->sendContent_P(HTTP_END); server->client().stop(); - - DEBUG_PRINT(F("Sent wifi save page")); - + + DEBUG_PRINT(F("Sent wifi save page")); + connect = true; //signal ready to connect/reset } void WiFiManager::handle204() { - DEBUG_PRINT(F("204 No Response")); + 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"); @@ -438,12 +513,18 @@ void WiFiManager::setAPCallback( void (*func)(void) ) { _apcallback = func; } +//start up save config callback +void WiFiManager::setSaveConfigCallback( void (*func)(void) ) { + _savecallback = func; +} + + template void WiFiManager::DEBUG_PRINT(Generic text) { - if(_debug) { + if (_debug) { Serial.print("*WM: "); - Serial.println(text); + Serial.println(text); } } @@ -451,12 +532,12 @@ 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; + if (RSSI <= -100) { + quality = 0; + } else if (RSSI >= -50) { + quality = 100; } else { - quality = 2 * (RSSI + 100); + quality = 2 * (RSSI + 100); } return quality; } diff --git a/WiFiManager.h b/WiFiManager.h index 27deed9..b209215 100644 --- a/WiFiManager.h +++ b/WiFiManager.h @@ -14,7 +14,7 @@ #include -//#include +#include //#include #include #include @@ -29,10 +29,32 @@ const char HTTP_HEAD_END[] PROGMEM = "
{v} {r}% {i}
"; const char HTTP_ITEM_PADLOCK[] PROGMEM = ""; -const char HTTP_FORM[] PROGMEM = "



"; +const char HTTP_FORM_START[] PROGMEM = "


"; +const char HTTP_FORM_PARAM[] PROGMEM = "
"; +const char HTTP_FORM_END[] 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 *id, const char *placeholder, const char *defaultValue, int length); + + const char* getID(); + const char* getValue(); + const char* getPlaceholder(); + int getValueLength(); +private: + const char* _id; + const char* _placeholder; + char* _value; + int _length; + +friend class WiFiManager; +}; + class WiFiManager { @@ -58,8 +80,14 @@ public: //sets a custom ip /gateway /subnet configuration void setAPConfig(IPAddress ip, IPAddress gw, IPAddress sn); + //called when AP mode and config portal is started void setAPCallback( void (*func)(void) ); - + //called when settings have been changed and connection was successful + void setSaveConfigCallback( void (*func)(void) ); + + //adds a custom parameter + void addParameter(WiFiManagerParameter *p); + private: std::unique_ptr dnsServer; std::unique_ptr server; @@ -95,6 +123,7 @@ private: IPAddress _ip; IPAddress _gw; IPAddress _sn; + int _paramsCount = 0; String getEEPROMString(int start, int len); void setEEPROMString(int start, int len, String string); @@ -122,6 +151,10 @@ private: boolean _debug = true; void (*_apcallback)(void) = NULL; + void (*_savecallback)(void) = NULL; + + WiFiManagerParameter* _params[WIFI_MANAGER_MAX_PARAMS]; + //int _eepromLength; template void DEBUG_PRINT(Generic text); diff --git a/examples/AutoConnectWithFSParameters/AutoConnectWithFSParameters.ino b/examples/AutoConnectWithFSParameters/AutoConnectWithFSParameters.ino new file mode 100644 index 0000000..5e69973 --- /dev/null +++ b/examples/AutoConnectWithFSParameters/AutoConnectWithFSParameters.ino @@ -0,0 +1,144 @@ +#include //this needs to be first, or it all crashes and burns... + +#include //https://github.com/esp8266/Arduino + +//needed for library +#include +#include +#include //https://github.com/tzapu/WiFiManager + +#include //https://github.com/bblanchon/ArduinoJson + +//define your default values here, if there are different values in config.json, they are overwritten. +const char *mqtt_server = NULL; +const char *mqtt_port = "8080"; +const char *blynk_token = "YOUR_BLYNK_TOKEN"; + + //flag for saving data + bool shouldSaveConfig = false; + +//callback notifying us of the need to save config +void saveConfigCallback () { + Serial.println("Should save config"); + shouldSaveConfig = true; +} + + +void setup() { + // put your setup code here, to run once: + Serial.begin(115200); + Serial.println(); + + //clean FS, for testing + //SPIFFS.format(); + + //read configuration from FS json + Serial.println("mounting FS..."); + + if (SPIFFS.begin()) { + Serial.println("mounted file system"); + if (SPIFFS.exists("/config.json")) { + //file exists, reading and loading + Serial.println("reading config file"); + File configFile = SPIFFS.open("/config.json", "r"); + if (configFile) { + Serial.println("opened config file"); + size_t size = configFile.size(); + // Allocate a buffer to store contents of the file. + std::unique_ptr buf(new char[size]); + + configFile.readBytes(buf.get(), size); + StaticJsonBuffer<200> jsonBuffer; + JsonObject& json = jsonBuffer.parseObject(buf.get()); + json.printTo(Serial); + if (json.success()) { + Serial.println("\nparsed json"); + + mqtt_server = json["mqtt_server"]; + mqtt_port = json["mqtt_port"]; + blynk_token = json["blynk_token"]; + } else { + Serial.println("failed to load json config"); + } + } + } + } else { + Serial.println("failed to mount FS"); + } + //end read + + + + // The extra parameters to be configured (can be either global or just in the setup) + // After connecting, parameter.getValue() will get you the configured value + // id/name placeholder/prompt default length + WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40); + WiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 8); + WiFiManagerParameter custom_blynk_token("blynk", "blynk token", blynk_token, 32); + + //WiFiManager + //Local intialization. Once its business is done, there is no need to keep it around + WiFiManager wifiManager; + + //set config save notify callback + wifiManager.setSaveConfigCallback(saveConfigCallback); + + //add all your parameters here + wifiManager.addParameter(&custom_mqtt_server); + wifiManager.addParameter(&custom_mqtt_port); + wifiManager.addParameter(&custom_blynk_token); + + //reset settings - for testing + //wifiManager.resetSettings(); + + //sets timeout until configuration portal gets turned off + //useful to make it all retry or go to sleep + //in seconds + //wifiManager.setTimeout(120); + + //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"); + delay(3000); + //reset and try again, or maybe put it to deep sleep + ESP.reset(); + delay(5000); + } + + //if you get here you have connected to the WiFi + Serial.println("connected...yeey :)"); + + //read updated parameters + mqtt_server = custom_mqtt_server.getValue(); + mqtt_port = custom_mqtt_port.getValue(); + blynk_token = custom_blynk_token.getValue(); + + //save the custom parameters to FS + if (shouldSaveConfig) { + Serial.println("saving config"); + StaticJsonBuffer<200> jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + json["mqtt_server"] = mqtt_server; + json["mqtt_port"] = mqtt_port; + json["blynk_token"] = blynk_token; + + File configFile = SPIFFS.open("/config.json", "w"); + if (!configFile) { + Serial.println("failed to open config file for writing"); + } + + json.printTo(Serial); + json.printTo(configFile); + configFile.close(); + //end save + } +} + +void loop() { + // put your main code here, to run repeatedly: + + +} diff --git a/extras/WiFiManager.template.html b/extras/WiFiManager.template.html new file mode 100644 index 0000000..4d005b2 --- /dev/null +++ b/extras/WiFiManager.template.html @@ -0,0 +1,17 @@ +{v} + + +
+
{v} {r}% {i}
+
{v} 100%
+
Vila17 95%
+ +
Marcelica 100%
+
PMica 110%
+
+


+
+

+
+
+ \ No newline at end of file