├── .gitignore ├── LICENSE ├── PersWiFiManager.cpp ├── PersWiFiManager.h ├── README.md ├── data ├── wifi.htm ├── wifi.min.htm └── wifi.min.htm.gz ├── examples ├── basic_rest_api │ ├── basic_rest_api.ino │ └── data │ │ ├── index.htm │ │ └── wifi.min.htm.gz ├── spiffs_rest_api │ ├── data │ │ ├── index.htm │ │ └── wifi.min.htm.gz │ └── spiffs_rest_api.ino └── spiffs_rest_api_nonblocking │ ├── data │ ├── index.htm │ ├── wifi.htm │ ├── wifi.min.htm │ └── wifi.min.htm.gz │ └── spiffs_rest_api_nonblocking.ino ├── keywords.txt └── library.properties /.gitignore: -------------------------------------------------------------------------------- 1 | PersWiFiManager.ino 2 | data/* 3 | !data/wifi* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ryan Downing 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PersWiFiManager.cpp: -------------------------------------------------------------------------------- 1 | /* PersWiFiManager 2 | version 3.0.1 3 | https://r-downing.github.io/PersWiFiManager/ 4 | */ 5 | 6 | #include "PersWiFiManager.h" 7 | 8 | #if defined(ESP32) 9 | #include 10 | #endif 11 | 12 | #ifdef WIFI_HTM_PROGMEM 13 | const char wifi_htm[] PROGMEM = R"=====( 14 | 15 | 16 | 17 | 18 | ESP WiFi 19 | 58 | 82 | 83 | 84 |
85 | 86 |

87 |
88 | 89 |
90 | 91 |

92 | 93 |
94 |

95 | 96 |
97 | Back |Home 98 |
99 | 100 | 101 | )====="; 102 | #endif 103 | 104 | #if defined(ESP8266) 105 | PersWiFiManager::PersWiFiManager(ESP8266WebServer& s, DNSServer& d) { 106 | #elif defined(ESP32) 107 | PersWiFiManager::PersWiFiManager(WebServer& s, DNSServer& d) { 108 | #endif 109 | _server = &s; 110 | _dnsServer = &d; 111 | _apPass = ""; 112 | _freshConnectionAttempt = false; 113 | } //PersWiFiManager 114 | 115 | bool PersWiFiManager::attemptConnection(const String& ssid, const String& pass) { 116 | //attempt to connect to wifi 117 | WiFi.mode(WIFI_STA); 118 | if (ssid.length()) { 119 | resetSettings(); // To avoid issues (experience from WiFiManager) 120 | if (pass.length()) WiFi.begin(ssid.c_str(), pass.c_str()); 121 | else WiFi.begin(ssid.c_str()); 122 | } else { 123 | if((getSsid() == "") && (WiFi.status() != WL_CONNECTED)) { // No saved credentials, so skip trying to connect 124 | _connectStartTime = millis(); 125 | _freshConnectionAttempt = true; 126 | return false; 127 | } else { 128 | WiFi.begin(); 129 | } 130 | } 131 | 132 | //if in nonblock mode, skip this loop 133 | _connectStartTime = millis();// + 1; 134 | while (!_connectNonBlock && _connectStartTime) { 135 | handleWiFi(); 136 | delay(10); 137 | } 138 | 139 | return (WiFi.status() == WL_CONNECTED); 140 | 141 | } //attemptConnection 142 | 143 | void PersWiFiManager::handleWiFi() { 144 | if (!_connectStartTime) return; 145 | 146 | if (WiFi.status() == WL_CONNECTED) { 147 | _connectStartTime = 0; 148 | if (_connectHandler) _connectHandler(); 149 | return; 150 | } 151 | 152 | //if failed or no saved SSID or no WiFi credentials were found or not connected and time is up 153 | if ((WiFi.status() == WL_CONNECT_FAILED) || _freshConnectionAttempt || ((WiFi.status() != WL_CONNECTED) && ((millis() - _connectStartTime) > (1000 * WIFI_CONNECT_TIMEOUT)))) { 154 | startApMode(); 155 | _connectStartTime = 0; //reset connect start time 156 | _freshConnectionAttempt = false; 157 | } 158 | 159 | } //handleWiFi 160 | 161 | void PersWiFiManager::startApMode(){ 162 | //start AP mode 163 | IPAddress apIP(192, 168, 4, 1); 164 | WiFi.mode(WIFI_AP); 165 | WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); 166 | _apPass.length() ? WiFi.softAP(getApSsid().c_str(), _apPass.c_str()) : WiFi.softAP(getApSsid().c_str()); 167 | if (_apHandler) _apHandler(); 168 | }//startApMode 169 | 170 | void PersWiFiManager::setConnectNonBlock(bool b) { 171 | _connectNonBlock = b; 172 | } //setConnectNonBlock 173 | 174 | void PersWiFiManager::setupWiFiHandlers() { 175 | IPAddress apIP(192, 168, 4, 1); 176 | _dnsServer->setErrorReplyCode(DNSReplyCode::NoError); 177 | _dnsServer->start((byte)53, "*", apIP); //used for captive portal in AP mode 178 | 179 | _server->on("/wifi/list", [&] () { 180 | //scan for wifi networks 181 | int n = WiFi.scanNetworks(); 182 | 183 | //build array of indices 184 | int ix[n]; 185 | for (int i = 0; i < n; i++) ix[i] = i; 186 | 187 | //sort by signal strength 188 | for (int i = 0; i < n; i++) for (int j = 1; j < n - i; j++) if (WiFi.RSSI(ix[j]) > WiFi.RSSI(ix[j - 1])) std::swap(ix[j], ix[j - 1]); 189 | //remove duplicates 190 | for (int i = 0; i < n; i++) for (int j = i + 1; j < n; j++) if (WiFi.SSID(ix[i]).equals(WiFi.SSID(ix[j])) && WiFi.encryptionType(ix[i]) == WiFi.encryptionType(ix[j])) ix[j] = -1; 191 | 192 | //build plain text string of wifi info 193 | //format [signal%]:[encrypted 0 or 1]:SSID 194 | String s = ""; 195 | s.reserve(2050); 196 | for (int i = 0; i < n && s.length() < 2000; i++) { //check s.length to limit memory usage 197 | if (ix[i] != -1) { 198 | #if defined(ESP8266) 199 | s += String(i ? "\n" : "") + ((constrain(WiFi.RSSI(ix[i]), -100, -50) + 100) * 2) + "," 200 | + ((WiFi.encryptionType(ix[i]) == ENC_TYPE_NONE) ? 0 : 1) + "," + WiFi.SSID(ix[i]); 201 | #elif defined(ESP32) 202 | s += String(i ? "\n" : "") + ((constrain(WiFi.RSSI(ix[i]), -100, -50) + 100) * 2) + "," 203 | + ((WiFi.encryptionType(ix[i]) == WIFI_AUTH_OPEN) ? 0 : 1) + "," + WiFi.SSID(ix[i]); 204 | #endif 205 | } 206 | } 207 | 208 | //send string to client 209 | _server->send(200, "text/plain", s); 210 | }); //_server->on /wifi/list 211 | 212 | _server->on("/wifi/connect", [&]() { 213 | _server->send(200, "text/html", "connecting..."); 214 | attemptConnection(_server->arg("n"), _server->arg("p")); 215 | }); //_server->on /wifi/connect 216 | 217 | _server->on("/wifi/ap", [&](){ 218 | _server->send(200, "text/html", "access point: "+getApSsid()); 219 | startApMode(); 220 | }); //_server->on /wifi/ap 221 | 222 | _server->on("/wifi/rst", [&]() { 223 | _server->send(200, "text/html", "Rebooting..."); 224 | delay(100); 225 | //ESP.restart(); 226 | // Adding Safer Restart method 227 | #if defined(ESP8266) 228 | ESP.wdtDisable(); 229 | ESP.reset(); 230 | #elif defined(ESP32) 231 | ESP.restart(); 232 | #endif 233 | delay(2000); 234 | }); 235 | 236 | #ifdef WIFI_HTM_PROGMEM 237 | _server->on("/wifi.htm", [&]() { 238 | _server->sendHeader("Cache-Control", " no-cache, no-store, must-revalidate"); 239 | _server->sendHeader("Expires", " 0"); 240 | _server->send(200, "text/html", wifi_htm); 241 | }); 242 | #endif 243 | 244 | }//setupWiFiHandlers 245 | 246 | bool PersWiFiManager::begin(const String& ssid, const String& pass) { 247 | #if defined(ESP32) 248 | WiFi.mode(WIFI_STA); // ESP32 needs this before setupWiFiHandlers(). Might be good for ESP8266 too? 249 | #endif 250 | setupWiFiHandlers(); 251 | return attemptConnection(ssid, pass); //switched order of these two for return 252 | } //begin 253 | 254 | void PersWiFiManager::resetSettings() { 255 | #if defined(ESP8266) 256 | WiFi.disconnect(); 257 | #elif defined(ESP32) 258 | wifi_mode_t m = WiFi.getMode(); 259 | if(!(m & WIFI_MODE_STA)) WiFi.mode(WIFI_STA); 260 | WiFi.disconnect(false, true); 261 | if(!(m & WIFI_MODE_STA)) WiFi.mode(m); 262 | #endif 263 | } // resetSettings 264 | 265 | String PersWiFiManager::getApSsid() { 266 | #if defined(ESP8266) 267 | return _apSsid.length() ? _apSsid : "ESP8266"; 268 | #elif defined(ESP32) 269 | return _apSsid.length() ? _apSsid : "ESP32"; 270 | #endif 271 | } //getApSsid 272 | 273 | String PersWiFiManager::getSsid() { 274 | #if defined(ESP8266) 275 | return WiFi.SSID(); 276 | #elif defined(ESP32) 277 | wifi_config_t conf; 278 | esp_wifi_get_config(WIFI_IF_STA, &conf); // load wifi settings to struct comf 279 | const char *SSID = reinterpret_cast(conf.sta.ssid); 280 | return String(SSID); 281 | #endif 282 | } //getSsid 283 | 284 | void PersWiFiManager::setApCredentials(const String& apSsid, const String& apPass) { 285 | if (apSsid.length()) _apSsid = apSsid; 286 | if (apPass.length() >= 8) _apPass = apPass; 287 | } //setApCredentials 288 | 289 | void PersWiFiManager::onConnect(WiFiChangeHandlerFunction fn) { 290 | _connectHandler = fn; 291 | } 292 | 293 | void PersWiFiManager::onAp(WiFiChangeHandlerFunction fn) { 294 | _apHandler = fn; 295 | } 296 | 297 | 298 | -------------------------------------------------------------------------------- /PersWiFiManager.h: -------------------------------------------------------------------------------- 1 | #ifndef PERSWIFIMANAGER_H 2 | #define PERSWIFIMANAGER_H 3 | 4 | #if defined(ESP8266) 5 | #include 6 | #include 7 | #elif defined(ESP32) 8 | #include 9 | #include 10 | #else 11 | #error "Unknown board class" 12 | #endif 13 | #include 14 | 15 | #define WIFI_CONNECT_TIMEOUT 30 16 | 17 | class PersWiFiManager { 18 | 19 | public: 20 | 21 | typedef std::function WiFiChangeHandlerFunction; 22 | 23 | #if defined(ESP8266) 24 | PersWiFiManager(ESP8266WebServer& s, DNSServer& d); 25 | #elif defined(ESP32) 26 | PersWiFiManager(WebServer& s, DNSServer& d); 27 | #endif 28 | 29 | bool attemptConnection(const String& ssid = "", const String& pass = ""); 30 | 31 | void setupWiFiHandlers(); 32 | 33 | bool begin(const String& ssid = "", const String& pass = ""); 34 | 35 | void resetSettings(); 36 | 37 | String getApSsid(); 38 | 39 | String getSsid(); 40 | 41 | void setApCredentials(const String& apSsid, const String& apPass = ""); 42 | 43 | void setConnectNonBlock(bool b); 44 | 45 | void handleWiFi(); 46 | 47 | void startApMode(); 48 | 49 | void onConnect(WiFiChangeHandlerFunction fn); 50 | 51 | void onAp(WiFiChangeHandlerFunction fn); 52 | 53 | private: 54 | #if defined(ESP8266) 55 | ESP8266WebServer * _server; 56 | #elif defined(ESP32) 57 | WebServer * _server; 58 | #endif 59 | DNSServer * _dnsServer; 60 | String _apSsid, _apPass; 61 | 62 | bool _connectNonBlock; 63 | unsigned long _connectStartTime; 64 | bool _freshConnectionAttempt; 65 | 66 | WiFiChangeHandlerFunction _connectHandler; 67 | WiFiChangeHandlerFunction _apHandler; 68 | 69 | };//class 70 | 71 | #endif 72 | 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PersWiFiManager 2 | Persistent WiFiManager Arduino library for ESP8266-based microcontrollers 3 | 4 | This Persistent WiFi Manager provides a WiFi Settings web interface for ESP8266-based microcontrollers. It can autoconnect to the last used network, and then if unsuccessful, switch to AP mode with a captive DNS server. This action is non-blocking; the program will proceed to the main loop after, regardless of WiFi connection status. In AP mode, any device (phone, computer, etc) can connect to this network to configure the wifi connection, or access the device as a webserver. 5 | 6 | This library and UI was inspired by tzapu's [WiFiManager library](https://github.com/tzapu/WiFiManager). The main difference is that it allows the program to continue functioning normally, even in AP mode. It is also more memory efficient, as it does not have to dynamically build the page, and can serve it from SPIFFS rather than PROGMEM. 7 | 8 | [Full Documentation](http://ryandowning.net/PersWiFiManager) -------------------------------------------------------------------------------- /data/wifi.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ESP WiFi 7 | 36 | 81 | 82 | 83 | 84 |
85 | 86 |

87 |
88 | 89 |
90 | 91 |
92 |
93 | 94 |
95 |
96 |
97 | 98 |
99 | 100 |
101 | 102 |
103 | Back | 104 | Home 105 |
106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /data/wifi.min.htm: -------------------------------------------------------------------------------- 1 | ESP WiFi









Back | Home
-------------------------------------------------------------------------------- /data/wifi.min.htm.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-downing/PersWiFiManager/6808d3f254c1eade1f53b2cc16e757f99f4dce96/data/wifi.min.htm.gz -------------------------------------------------------------------------------- /examples/basic_rest_api/basic_rest_api.ino: -------------------------------------------------------------------------------- 1 | #define DEBUG_SERIAL //uncomment for Serial debugging statements 2 | 3 | #ifdef DEBUG_SERIAL 4 | #define DEBUG_BEGIN Serial.begin(115200) 5 | #define DEBUG_PRINT(x) Serial.println(x) 6 | #else 7 | #define DEBUG_PRINT(x) 8 | #define DEBUG_BEGIN 9 | #endif 10 | 11 | //includes 12 | #include 13 | #include 14 | #if defined(ESP8266) 15 | #include 16 | #include 17 | #include 18 | #include 19 | #elif defined(ESP32) 20 | #include 21 | #include 22 | #include 23 | #include 24 | #else 25 | #error "Unsupported board class" 26 | #endif 27 | #include 28 | 29 | #if defined(ESP8266) 30 | #define DEVICE_NAME "ESP8266 DEVICE" 31 | #elif defined(ESP32) 32 | #define DEVICE_NAME "ESP32 DEVICE" 33 | #endif 34 | 35 | //const char *metaRefreshStr = "redirecting..."; 36 | const char *metaRefreshStr = "redirecting..."; 37 | 38 | //server objects 39 | #if defined(ESP8266) 40 | ESP8266WebServer server(80); 41 | #elif defined(ESP32) 42 | WebServer server(80); 43 | #endif 44 | DNSServer dnsServer; 45 | PersWiFiManager persWM(server, dnsServer); 46 | 47 | ////// Sample program data 48 | int x; 49 | String y; 50 | 51 | 52 | //code from fsbrowser example, consolidated. 53 | bool handleFileRead(String path) { 54 | DEBUG_PRINT("handlefileread" + path); 55 | if (path.endsWith("/")) path += "index.htm"; 56 | String contentType; 57 | if (path.endsWith(".htm") || path.endsWith(".html")) contentType = "text/html"; 58 | else if (path.endsWith(".css")) contentType = "text/css"; 59 | else if (path.endsWith(".js")) contentType = "application/javascript"; 60 | else if (path.endsWith(".png")) contentType = "image/png"; 61 | else if (path.endsWith(".gif")) contentType = "image/gif"; 62 | else if (path.endsWith(".jpg")) contentType = "image/jpeg"; 63 | else if (path.endsWith(".ico")) contentType = "image/x-icon"; 64 | else if (path.endsWith(".xml")) contentType = "text/xml"; 65 | else if (path.endsWith(".pdf")) contentType = "application/x-pdf"; 66 | else if (path.endsWith(".zip")) contentType = "application/x-zip"; 67 | else if (path.endsWith(".gz")) contentType = "application/x-gzip"; 68 | else if (path.endsWith(".json")) contentType = "application/json"; 69 | else contentType = "text/plain"; 70 | 71 | //split filepath and extension 72 | String prefix = path, ext = ""; 73 | int lastPeriod = path.lastIndexOf('.'); 74 | if (lastPeriod >= 0) { 75 | prefix = path.substring(0, lastPeriod); 76 | ext = path.substring(lastPeriod); 77 | } 78 | 79 | //look for smaller versions of file 80 | //minified file, good (myscript.min.js) 81 | if (SPIFFS.exists(prefix + ".min" + ext)) path = prefix + ".min" + ext; 82 | //gzipped file, better (myscript.js.gz) 83 | if (SPIFFS.exists(prefix + ext + ".gz")) path = prefix + ext + ".gz"; 84 | //min and gzipped file, best (myscript.min.js.gz) 85 | if (SPIFFS.exists(prefix + ".min" + ext + ".gz")) path = prefix + ".min" + ext + ".gz"; 86 | 87 | if (SPIFFS.exists(path)) { 88 | DEBUG_PRINT("sending file " + path); 89 | File file = SPIFFS.open(path, "r"); 90 | if (server.hasArg("download")) 91 | server.sendHeader("Content-Disposition", " attachment;"); 92 | if (server.uri().indexOf("nocache") < 0) 93 | server.sendHeader("Cache-Control", " max-age=172800"); 94 | 95 | //optional alt arg (encoded url), server sends redirect to file on the web 96 | if (WiFi.status() == WL_CONNECTED && server.hasArg("alt")) { 97 | server.sendHeader("Location", server.arg("alt"), true); 98 | server.send ( 302, "text/plain", ""); 99 | } else { 100 | //server sends file 101 | size_t sent = server.streamFile(file, contentType); 102 | } 103 | file.close(); 104 | return true; 105 | } //if SPIFFS.exists 106 | return false; 107 | } //bool handleFileRead 108 | 109 | void setup() { 110 | DEBUG_BEGIN; //for terminal debugging 111 | DEBUG_PRINT(); 112 | 113 | //allows serving of files from SPIFFS 114 | SPIFFS.begin(); 115 | persWM.begin(); 116 | //reset saved settings, clears WiFi credentials e.g. for testing 117 | //persWM.resetSettings(); 118 | 119 | 120 | //serve files from SPIFFS 121 | server.onNotFound([]() { 122 | if (!handleFileRead(server.uri())) { 123 | server.sendHeader("Cache-Control", " max-age=172800"); 124 | server.send(302, "text/html", metaRefreshStr); 125 | } 126 | }); //server.onNotFound 127 | 128 | //handles commands from webpage, sends live data in JSON format 129 | server.on("/api", []() { 130 | DEBUG_PRINT("server.on /api"); 131 | if (server.hasArg("x")) { 132 | x = server.arg("x").toInt(); 133 | DEBUG_PRINT(String("x: ")+x); 134 | } //if 135 | if (server.hasArg("y")) { 136 | y = server.arg("y"); 137 | DEBUG_PRINT("y: "+y); 138 | } //if 139 | 140 | //build json object of program data 141 | StaticJsonBuffer<200> jsonBuffer; 142 | JsonObject &json = jsonBuffer.createObject(); 143 | json["x"] = x; 144 | json["y"] = y; 145 | 146 | char jsonchar[200]; 147 | json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece 148 | server.send(200, "application/json", jsonchar); 149 | 150 | }); //server.on api 151 | 152 | 153 | //SSDP makes device visible on windows network 154 | server.on("/description.xml", HTTP_GET, []() { 155 | SSDP.schema(server.client()); 156 | }); 157 | SSDP.setSchemaURL("description.xml"); 158 | SSDP.setHTTPPort(80); 159 | SSDP.setName(DEVICE_NAME); 160 | SSDP.setURL("/"); 161 | SSDP.setDeviceType("upnp:rootdevice"); 162 | SSDP.begin(); 163 | 164 | server.begin(); 165 | DEBUG_PRINT("setup complete."); 166 | } //void setup 167 | 168 | void loop() { 169 | dnsServer.processNextRequest(); 170 | server.handleClient(); 171 | 172 | // do stuff with x and y 173 | 174 | } //void loop 175 | -------------------------------------------------------------------------------- /examples/basic_rest_api/data/index.htm: -------------------------------------------------------------------------------- 1 |

Current Data

2 | x: 3 | 4 |
y: 5 | 6 | 7 |
Last updated 8 | seconds ago. 9 | 10 |
11 | 12 |

Update Data

13 |
14 | x: 15 | 16 | 17 |
18 |
19 | y: 20 | 21 | 22 |
23 | 24 | WiFi settings 25 | 26 | 53 | -------------------------------------------------------------------------------- /examples/basic_rest_api/data/wifi.min.htm.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-downing/PersWiFiManager/6808d3f254c1eade1f53b2cc16e757f99f4dce96/examples/basic_rest_api/data/wifi.min.htm.gz -------------------------------------------------------------------------------- /examples/spiffs_rest_api/data/index.htm: -------------------------------------------------------------------------------- 1 |

Current Data

2 | x: 3 | 4 |
y: 5 | 6 | 7 |
Last updated 8 | seconds ago. 9 | 10 |
11 | 12 |

Update Data

13 |
14 | x: 15 | 16 | 17 |
18 |
19 | y: 20 | 21 | 22 |
23 | 24 | WiFi settings 25 | 26 | 53 | -------------------------------------------------------------------------------- /examples/spiffs_rest_api/data/wifi.min.htm.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-downing/PersWiFiManager/6808d3f254c1eade1f53b2cc16e757f99f4dce96/examples/spiffs_rest_api/data/wifi.min.htm.gz -------------------------------------------------------------------------------- /examples/spiffs_rest_api/spiffs_rest_api.ino: -------------------------------------------------------------------------------- 1 | #define DEBUG_SERIAL //uncomment for Serial debugging statements 2 | 3 | #ifdef DEBUG_SERIAL 4 | #define DEBUG_BEGIN Serial.begin(115200) 5 | #define DEBUG_PRINT(x) Serial.println(x) 6 | #else 7 | #define DEBUG_PRINT(x) 8 | #define DEBUG_BEGIN 9 | #endif 10 | 11 | //includes 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | //extension of ESP8266WebServer with SPIFFS handlers built in 18 | #include // https://github.com/r-downing/SPIFFSReadServer 19 | // upload data folder to chip with Arduino ESP8266 filesystem uploader 20 | // https://github.com/esp8266/arduino-esp8266fs-plugin 21 | 22 | #include 23 | #include 24 | 25 | #define DEVICE_NAME "ESP8266 DEVICE" 26 | 27 | 28 | //server objects 29 | SPIFFSReadServer server(80); 30 | DNSServer dnsServer; 31 | PersWiFiManager persWM(server, dnsServer); 32 | 33 | ////// Sample program data 34 | int x; 35 | String y; 36 | 37 | void setup() { 38 | DEBUG_BEGIN; //for terminal debugging 39 | DEBUG_PRINT(); 40 | 41 | //allows serving of files from SPIFFS 42 | SPIFFS.begin(); 43 | //sets network name for AP mode 44 | persWM.setApCredentials(DEVICE_NAME); 45 | //persWM.setApCredentials(DEVICE_NAME, "password"); optional password 46 | persWM.begin(); 47 | 48 | //handles commands from webpage, sends live data in JSON format 49 | server.on("/api", []() { 50 | DEBUG_PRINT("server.on /api"); 51 | if (server.hasArg("x")) { 52 | x = server.arg("x").toInt(); 53 | DEBUG_PRINT(String("x: ")+x); 54 | } //if 55 | if (server.hasArg("y")) { 56 | y = server.arg("y"); 57 | DEBUG_PRINT("y: "+y); 58 | } //if 59 | 60 | //build json object of program data 61 | StaticJsonBuffer<200> jsonBuffer; 62 | JsonObject &json = jsonBuffer.createObject(); 63 | json["x"] = x; 64 | json["y"] = y; 65 | 66 | char jsonchar[200]; 67 | json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece 68 | server.send(200, "application/json", jsonchar); 69 | 70 | }); //server.on api 71 | 72 | 73 | //SSDP makes device visible on windows network 74 | server.on("/description.xml", HTTP_GET, []() { 75 | SSDP.schema(server.client()); 76 | }); 77 | SSDP.setSchemaURL("description.xml"); 78 | SSDP.setHTTPPort(80); 79 | SSDP.setName(DEVICE_NAME); 80 | SSDP.setURL("/"); 81 | SSDP.begin(); 82 | SSDP.setDeviceType("upnp:rootdevice"); 83 | 84 | server.begin(); 85 | DEBUG_PRINT("setup complete."); 86 | } //void setup 87 | 88 | void loop() { 89 | dnsServer.processNextRequest(); 90 | server.handleClient(); 91 | 92 | // do stuff with x and y 93 | 94 | } //void loop 95 | -------------------------------------------------------------------------------- /examples/spiffs_rest_api_nonblocking/data/index.htm: -------------------------------------------------------------------------------- 1 |

Current Data

2 | x: 3 | 4 |
y: 5 | 6 | 7 |
Last updated 8 | seconds ago. 9 | 10 |
11 | 12 |

Update Data

13 |
14 | x: 15 | 16 | 17 |
18 |
19 | y: 20 | 21 | 22 |
23 | 24 | WiFi settings 25 | 26 | 53 | -------------------------------------------------------------------------------- /examples/spiffs_rest_api_nonblocking/data/wifi.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ESP WiFi 7 | 36 | 81 | 82 | 83 | 84 |
85 | 86 |

87 |
88 | 89 |
90 | 91 |
92 |
93 | 94 |
95 |
96 |
97 | 98 |
99 | 100 |
101 | 102 |
103 | Back | 104 | Home 105 |
106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /examples/spiffs_rest_api_nonblocking/data/wifi.min.htm: -------------------------------------------------------------------------------- 1 | ESP WiFi









Back | Home
-------------------------------------------------------------------------------- /examples/spiffs_rest_api_nonblocking/data/wifi.min.htm.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-downing/PersWiFiManager/6808d3f254c1eade1f53b2cc16e757f99f4dce96/examples/spiffs_rest_api_nonblocking/data/wifi.min.htm.gz -------------------------------------------------------------------------------- /examples/spiffs_rest_api_nonblocking/spiffs_rest_api_nonblocking.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SPIFFS-served REST API example for PersWiFiManager v3.0 3 | */ 4 | 5 | #define DEBUG_SERIAL //uncomment for Serial debugging statements 6 | 7 | #ifdef DEBUG_SERIAL 8 | #define DEBUG_BEGIN Serial.begin(115200) 9 | #define DEBUG_PRINT(x) Serial.println(x) 10 | #else 11 | #define DEBUG_PRINT(x) 12 | #define DEBUG_BEGIN 13 | #endif 14 | 15 | //includes 16 | #include 17 | #include 18 | #include 19 | 20 | #include // http://ryandowning.net/EasySSDP/ 21 | 22 | //extension of ESP8266WebServer with SPIFFS handlers built in 23 | #include // http://ryandowning.net/SPIFFSReadServer/ 24 | // upload data folder to chip with Arduino ESP8266 filesystem uploader 25 | // https://github.com/esp8266/arduino-esp8266fs-plugin 26 | 27 | #include 28 | #include 29 | 30 | #define DEVICE_NAME "ESP8266 DEVICE" 31 | 32 | 33 | //server objects 34 | SPIFFSReadServer server(80); 35 | DNSServer dnsServer; 36 | PersWiFiManager persWM(server, dnsServer); 37 | 38 | ////// Sample program data 39 | int x; 40 | String y; 41 | 42 | void setup() { 43 | DEBUG_BEGIN; //for terminal debugging 44 | DEBUG_PRINT(); 45 | 46 | //optional code handlers to run everytime wifi is connected... 47 | persWM.onConnect([]() { 48 | DEBUG_PRINT("wifi connected"); 49 | DEBUG_PRINT(WiFi.localIP()); 50 | EasySSDP::begin(server); 51 | }); 52 | //...or AP mode is started 53 | persWM.onAp([](){ 54 | DEBUG_PRINT("AP MODE"); 55 | DEBUG_PRINT(persWM.getApSsid()); 56 | }); 57 | 58 | //allows serving of files from SPIFFS 59 | SPIFFS.begin(); 60 | //sets network name for AP mode 61 | persWM.setApCredentials(DEVICE_NAME); 62 | //persWM.setApCredentials(DEVICE_NAME, "password"); optional password 63 | 64 | //make connecting/disconnecting non-blocking 65 | persWM.setConnectNonBlock(true); 66 | 67 | //in non-blocking mode, program will continue past this point without waiting 68 | persWM.begin(); 69 | 70 | //handles commands from webpage, sends live data in JSON format 71 | server.on("/api", []() { 72 | DEBUG_PRINT("server.on /api"); 73 | if (server.hasArg("x")) { 74 | x = server.arg("x").toInt(); 75 | DEBUG_PRINT(String("x: ") + x); 76 | } //if 77 | if (server.hasArg("y")) { 78 | y = server.arg("y"); 79 | DEBUG_PRINT("y: " + y); 80 | } //if 81 | 82 | //build json object of program data 83 | StaticJsonBuffer<200> jsonBuffer; 84 | JsonObject &json = jsonBuffer.createObject(); 85 | json["x"] = x; 86 | json["y"] = y; 87 | 88 | char jsonchar[200]; 89 | json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece 90 | server.send(200, "application/json", jsonchar); 91 | 92 | }); //server.on api 93 | 94 | 95 | server.begin(); 96 | DEBUG_PRINT("setup complete."); 97 | } //void setup 98 | 99 | void loop() { 100 | //in non-blocking mode, handleWiFi must be called in the main loop 101 | persWM.handleWiFi(); 102 | 103 | dnsServer.processNextRequest(); 104 | server.handleClient(); 105 | 106 | //DEBUG_PRINT(millis()); 107 | 108 | // do stuff with x and y 109 | 110 | } //void loop 111 | 112 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For PersWiFiManager Library 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | PersWiFiManager KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | attemptConnection KEYWORD2 16 | setupWiFiHandlers KEYWORD2 17 | begin KEYWORD2 18 | getApSsid KEYWORD2 19 | setApCredentials KEYWORD2 20 | handleWiFi KEYWORD2 21 | setConnectNonBlock KEYWORD2 22 | startApMode KEYWORD2 23 | onConnect KEYWORD2 24 | onAp KEYWORD2 25 | 26 | ####################################### 27 | # Constants (LITERAL1) 28 | ####################################### 29 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=PersWiFiManager 2 | version=5.0.0 3 | author=Ryan Downing 4 | maintainer=Ryan Downing 5 | sentence=Persistent WiFi Manager 6 | paragraph=A non-blocking, persistant wifi manager for ESP8266 that allows network changes at any time 7 | category=Communication 8 | url=http://ryandowning.net/PersWiFiManager/ 9 | architectures=esp8266,esp32 10 | --------------------------------------------------------------------------------