diff --git a/README.md b/README.md index 6acf010..9405479 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ # WiFiManager +## DEVELOPMENT BRANCH + ESP8266 WiFi Connection manager with fallback web configuration portal +:warning: This Documentation is out of date for this branch, see notes below + [![Build Status](https://travis-ci.org/tzapu/WiFiManager.svg?branch=development)](https://travis-ci.org/tzapu/WiFiManager) ![ESP8266](https://img.shields.io/badge/ESP-8266-000000.svg?longCache=true&style=flat&colorA=CC101F) @@ -11,11 +15,11 @@ The configuration portal is of the captive variety, so on various devices it wil First attempt at a library. Lots more changes and fixes to do. Contributions are welcome. -**This works with the ESP8266 Arduino platform with a recent stable release(2.0.0 or newer)** +**This works with the ESP8266 Arduino platform** [https://github.com/esp8266/Arduino](https://github.com/esp8266/Arduino) -**This works with the ESP32 Arduino platform with staging** +**This works with the ESP32 Arduino platform** [https://github.com/espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) @@ -292,6 +296,8 @@ wifiManager.setSTAStaticIPConfig(IPAddress(192,168,0,99), IPAddress(192,168,0,1) ``` There are a couple of examples in the examples folder that show you how to set a static IP and even how to configure it through the web configuration portal. +NOTE: You should fill DNS server if you have HTTP requests with hostnames or syncronize time (NTP). It's the same as gateway ip or a popular (Google DNS: 8.8.8.8). + #### Custom HTML, CSS, Javascript There are various ways in which you can inject custom HTML, CSS or Javascript into the configuration portal. The options are: diff --git a/WiFiManager.cpp b/WiFiManager.cpp index abda41f..7b46c22 100644 --- a/WiFiManager.cpp +++ b/WiFiManager.cpp @@ -68,6 +68,12 @@ WiFiManagerParameter::~WiFiManagerParameter() { _length=0; // setting length 0, ideally the entire parameter should be removed, or added to wifimanager scope so it follows } +// WiFiManagerParameter& WiFiManagerParameter::operator=(const WiFiManagerParameter& rhs){ +// Serial.println("copy assignment op called"); +// (*this->_value) = (*rhs._value); +// return *this; +// } + // @note debug is not available in wmparameter class void WiFiManagerParameter::setValue(const char *defaultValue, int length) { if(!_id){ @@ -89,6 +95,7 @@ void WiFiManagerParameter::setValue(const char *defaultValue, int length) { } } const char* WiFiManagerParameter::getValue() const { + // Serial.println(printf("Address of _value is %p\n", (void *)_value)); return _value; } const char* WiFiManagerParameter::getID() const { @@ -206,9 +213,10 @@ WiFiManager::~WiFiManager() { } // @todo remove event - // #ifdef ESP32 - // WiFi.removeEvent(std::bind(&WiFiManager::WiFiEvent,this)); - // #endif + // WiFi.onEvent(std::bind(&WiFiManager::WiFiEvent,this,_1,_2)); + #ifdef ESP32 + WiFi.removeEvent(wm_event_id); + #endif DEBUG_WM(DEBUG_DEV,F("unloading")); } @@ -216,7 +224,7 @@ WiFiManager::~WiFiManager() { void WiFiManager::_begin(){ if(_hasBegun) return; _hasBegun = true; - _usermode = WiFi.getMode(); + // _usermode = WiFi.getMode(); #ifndef ESP32 WiFi.persistent(false); // disable persistent so scannetworks and mode switching do not cause overwrites @@ -245,97 +253,117 @@ boolean WiFiManager::autoConnect() { */ boolean WiFiManager::autoConnect(char const *apName, char const *apPassword) { DEBUG_WM(F("AutoConnect")); - _begin(); + if(getWiFiIsSaved()){ - // attempt to connect using saved settings, on fail fallback to AP config portal - if(!WiFi.enableSTA(true)){ - // handle failure mode Brownout detector etc. - DEBUG_WM(DEBUG_ERROR,"[FATAL] Unable to enable wifi!"); - return false; - } - - WiFiSetCountry(); + _begin(); - #ifdef ESP32 - if(esp32persistent) WiFi.persistent(false); // disable persistent for esp32 after esp_wifi_start or else saves wont work - #endif + // attempt to connect using saved settings, on fail fallback to AP config portal + if(!WiFi.enableSTA(true)){ + // handle failure mode Brownout detector etc. + DEBUG_WM(DEBUG_ERROR,"[FATAL] Unable to enable wifi!"); + return false; + } + + WiFiSetCountry(); - _usermode = WIFI_STA; - - // no getter for autoreconnectpolicy before this - // https://github.com/esp8266/Arduino/pull/4359 - // so we must force it on else, if not connectimeout then waitforconnectionresult gets stuck endless loop - WiFi_autoReconnect(); - - // set hostname before stating - if((String)_hostname != ""){ - DEBUG_WM(DEBUG_VERBOSE,"Setting hostname:",_hostname); - bool res = true; - #ifdef ESP8266 - res = WiFi.hostname(_hostname); - #ifdef ESP8266MDNS_H - DEBUG_WM(DEBUG_VERBOSE,"Setting MDNS hostname"); - if(MDNS.begin(_hostname)){ - MDNS.addService("http", "tcp", 80); - } - #endif - #elif defined(ESP32) - // @note hostname must be set after STA_START - delay(200); // do not remove, give time for STA_START - res = WiFi.setHostname(_hostname); - #ifdef ESP32MDNS_H - DEBUG_WM(DEBUG_VERBOSE,"Setting MDNS hostname"); - if(MDNS.begin(_hostname)){ - MDNS.addService("http", "tcp", 80); - } - #endif + #ifdef ESP32 + if(esp32persistent) WiFi.persistent(false); // disable persistent for esp32 after esp_wifi_start or else saves wont work #endif - - if(!res)DEBUG_WM(DEBUG_ERROR,F("[ERROR] hostname: set failed!")); - - if(WiFi.status() == WL_CONNECTED){ - DEBUG_WM(DEBUG_VERBOSE,F("reconnecting to set new hostname")); - // WiFi.reconnect(); // This does not reset dhcp - WiFi_Disconnect(); - delay(200); // do not remove, need a delay for disconnect to change status() - } - } - // if already connected, or try stored connect - // @note @todo ESP32 has no autoconnect, so connectwifi will always be called unless user called begin etc before - // @todo check if correct ssid == saved ssid when already connected - bool connected = false; - if (WiFi.status() == WL_CONNECTED){ - connected = true; - DEBUG_WM(F("AutoConnect: ESP Already Connected")); - setSTAConfig(); - } + _usermode = WIFI_STA; // When using autoconnect , assume the user wants sta mode on permanently. - if(connected || connectWifi("", "") == WL_CONNECTED){ - //connected - DEBUG_WM(F("AutoConnect: SUCCESS")); - DEBUG_WM(F("STA IP Address:"),WiFi.localIP()); - _lastconxresult = WL_CONNECTED; + // no getter for autoreconnectpolicy before this + // https://github.com/esp8266/Arduino/pull/4359 + // so we must force it on else, if not connectimeout then waitforconnectionresult gets stuck endless loop + WiFi_autoReconnect(); + // set hostname before stating if((String)_hostname != ""){ - #ifdef ESP8266 - DEBUG_WM(DEBUG_DEV,"hostname: STA",WiFi.hostname()); - #elif defined(ESP32) - DEBUG_WM(DEBUG_DEV,"hostname: STA",WiFi.getHostname()); - #endif + setupHostname(true); } - return true; - } - // possibly skip the config portal - if (!_enableConfigPortal) { - return false; - } + // if already connected, or try stored connect + // @note @todo ESP32 has no autoconnect, so connectwifi will always be called unless user called begin etc before + // @todo check if correct ssid == saved ssid when already connected + bool connected = false; + if (WiFi.status() == WL_CONNECTED){ + connected = true; + DEBUG_WM(F("AutoConnect: ESP Already Connected")); + setSTAConfig(); + // @todo not sure if this check makes sense, causes dup setSTAConfig in connectwifi, + // and we have no idea WHAT we are connected to + } - DEBUG_WM(F("AutoConnect: FAILED")); + if(connected || connectWifi("", "") == WL_CONNECTED){ + //connected + DEBUG_WM(F("AutoConnect: SUCCESS")); + DEBUG_WM(F("STA IP Address:"),WiFi.localIP()); + _lastconxresult = WL_CONNECTED; + + if((String)_hostname != ""){ + #ifdef ESP8266 + DEBUG_WM(DEBUG_DEV,"hostname: STA: ",WiFi.hostname()); + #elif defined(ESP32) + DEBUG_WM(DEBUG_DEV,"hostname: STA: ",WiFi.getHostname()); + #endif + } + + return true; // connected success + } + + // possibly skip the config portal + if (!_enableConfigPortal) { + return false; // not connected and not cp + } + + DEBUG_WM(F("AutoConnect: FAILED")); + } + else DEBUG_WM(F("No Credentials are Saved, skipping connect")); // not connected start configportal - return startConfigPortal(apName, apPassword); + bool res = startConfigPortal(apName, apPassword); + return res; +} + +bool WiFiManager::setupHostname(bool restart){ + if((String)_hostname == "") { + DEBUG_WM(DEBUG_DEV,"No Hostname to set"); + return false; + } else DEBUG_WM(DEBUG_DEV,"setupHostname: ",_hostname); + bool res = true; + #ifdef ESP8266 + DEBUG_WM(DEBUG_VERBOSE,"Setting WiFi hostname"); + res = WiFi.hostname(_hostname); + // #ifdef ESP8266MDNS_H + #ifdef WM_MDNS + DEBUG_WM(DEBUG_VERBOSE,"Setting MDNS hostname, tcp 80"); + if(MDNS.begin(_hostname)){ + MDNS.addService("http", "tcp", 80); + } + #endif + #elif defined(ESP32) + // @note hostname must be set after STA_START + delay(200); // do not remove, give time for STA_START + res = WiFi.setHostname(_hostname); + // #ifdef ESP32MDNS_H + #ifdef WM_MDNS + DEBUG_WM(DEBUG_VERBOSE,"Setting MDNS hostname, tcp 80"); + if(MDNS.begin(_hostname)){ + MDNS.addService("http", "tcp", 80); + } + #endif + #endif + + if(!res)DEBUG_WM(DEBUG_ERROR,F("[ERROR] hostname: set failed!")); + + if(restart && (WiFi.status() == WL_CONNECTED)){ + DEBUG_WM(DEBUG_VERBOSE,F("reconnecting to set new hostname")); + // WiFi.reconnect(); // This does not reset dhcp + WiFi_Disconnect(); + delay(200); // do not remove, need a delay for disconnect to change status() + } + + return res; } // CONFIG PORTAL @@ -404,7 +432,7 @@ bool WiFiManager::startAP(){ DEBUG_WM(DEBUG_VERBOSE,"setting softAP Hostname:",_hostname); bool res = WiFi.softAPsetHostname(_hostname); if(!res)DEBUG_WM(DEBUG_ERROR,F("[ERROR] hostname: AP set failed!")); - DEBUG_WM(DEBUG_DEV,F("hostname: AP"),WiFi.softAPgetHostname()); + DEBUG_WM(DEBUG_DEV,F("hostname: AP: "),WiFi.softAPgetHostname()); } #endif @@ -470,12 +498,14 @@ void WiFiManager::setupConfigPortal() { // setup dns and web servers dnsServer.reset(new DNSServer()); - server.reset(new WM_WebServer(80)); + server.reset(new WM_WebServer(_httpPort)); + + if(_httpPort != 80) DEBUG_WM(DEBUG_VERBOSE,"http server started with custom port: ",_httpPort); // @todo not showing ip /* Setup the DNS server redirecting all the domains to the apIP */ dnsServer->setErrorReplyCode(DNSReplyCode::NoError); // DEBUG_WM("dns server started port: ",DNS_PORT); - DEBUG_WM(DEBUG_DEV,"dns server started with ip: ",WiFi.softAPIP()); + DEBUG_WM(DEBUG_DEV,"dns server started with ip: ",WiFi.softAPIP()); // @todo not showing ip dnsServer->start(DNS_PORT, F("*"), WiFi.softAPIP()); // @todo new callback, webserver started, callback cannot override handlers, but can grab them first @@ -602,6 +632,11 @@ boolean WiFiManager::startConfigPortal(char const *apName, char const *apPasswo * @return {[type]} [description] */ boolean WiFiManager::process(){ + // process mdns, esp32 not required + #if defined(WM_MDNS) && defined(ESP8266) + MDNS.update(); + #endif + if(webPortalActive || (configPortalActive && !_configPortalIsBlocking)){ uint8_t state = processConfigPortal(); return state == WL_CONNECTED; @@ -619,7 +654,7 @@ uint8_t WiFiManager::processConfigPortal(){ // Waiting for save... if(connect) { connect = false; - DEBUG_WM(DEBUG_VERBOSE,F("process connect")); + DEBUG_WM(DEBUG_VERBOSE,F("processing save")); if(_enableCaptivePortal) delay(_cpclosedelay); // keeps the captiveportal from closing to fast. // skip wifi if no ssid @@ -644,10 +679,12 @@ uint8_t WiFiManager::processConfigPortal(){ } if (_shouldBreakAfterConfig) { + // do save callback // @todo this is more of an exiting callback than a save, clarify when this should actually occur // confirm or verify data was saved to make this more accurate callback if ( _savewificallback != NULL) { + DEBUG_WM(DEBUG_VERBOSE,F("WiFi/Param save callback")); _savewificallback(); } shutdownConfigPortal(); @@ -725,6 +762,7 @@ uint8_t WiFiManager::connectWifi(String ssid, String pass) { //@todo catch failures in set_config // make sure sta is on before `begin` so it does not call enablesta->mode while persistent is ON ( which would save WM AP state to eeprom !) + if(_cleanConnect) WiFi_Disconnect(); // disconnect before begin, in case anything is hung, this causes a 2 seconds delay for connect // @todo find out what status is when this is needed, can we detect it and handle it, say in between states or idle_status @@ -745,7 +783,7 @@ uint8_t WiFiManager::connectWifi(String ssid, String pass) { connRes = waitForConnectResult(); } else { - DEBUG_WM(F("No saved credentials, skipping wifi")); + DEBUG_WM(F("No wifi save required, skipping")); } } @@ -799,6 +837,8 @@ bool WiFiManager::wifiConnectDefault(){ DEBUG_WM(F("Connecting to SAVED AP:"),WiFi_SSID(true)); DEBUG_WM(DEBUG_DEV,F("Using Password:"),WiFi_psk(true)); ret = WiFi_enableSTA(true,storeSTAmode); + delay(500); // THIS DELAY ? + DEBUG_WM(DEBUG_DEV,"Mode after delay: "+getModeString(WiFi.getMode())); if(!ret) DEBUG_WM(DEBUG_ERROR,"[ERROR] wifi enableSta failed"); ret = WiFi.begin(); if(!ret) DEBUG_WM(DEBUG_ERROR,"[ERROR] wifi begin failed"); @@ -812,7 +852,7 @@ bool WiFiManager::wifiConnectDefault(){ * @return bool success */ bool WiFiManager::setSTAConfig(){ - DEBUG_WM(F("STA static IP:"),_sta_static_ip); + DEBUG_WM(DEBUG_DEV,F("STA static IP:"),_sta_static_ip); bool ret = true; if (_sta_static_ip) { DEBUG_WM(DEBUG_VERBOSE,F("Custom static IP/GW/Subnet/DNS")); @@ -828,7 +868,7 @@ bool WiFiManager::setSTAConfig(){ if(!ret) DEBUG_WM(DEBUG_ERROR,"[ERROR] wifi config failed"); else DEBUG_WM(F("STA IP set:"),WiFi.localIP()); } else { - DEBUG_WM(DEBUG_VERBOSE,F("setSTAConfig static ip not set")); + DEBUG_WM(DEBUG_VERBOSE,F("setSTAConfig static ip not set, skipping")); } return ret; } @@ -936,7 +976,7 @@ void WiFiManager::handleRoot() { DEBUG_WM(DEBUG_VERBOSE,F("<- HTTP Root")); if (captivePortal()) return; // If captive portal redirect instead of displaying the page handleRequest(); - String page = getHTTPHead(FPSTR(S_options)); // @token options + String page = getHTTPHead(FPSTR(S_options)); // @token options @todo replace options with title String str = FPSTR(HTTP_ROOT_MAIN); str.replace(FPSTR(T_v),configPortalActive ? _apName : WiFi.localIP().toString()); // use ip if ap is not active for heading page += str; @@ -991,6 +1031,7 @@ void WiFiManager::handleWifi(boolean scan) { } page += FPSTR(HTTP_FORM_END); page += FPSTR(HTTP_SCAN_LINK); + if(_showBack) page += FPSTR(HTTP_BACKBTN); reportStatus(page); page += FPSTR(HTTP_END); @@ -1017,6 +1058,7 @@ void WiFiManager::handleParam(){ page += getParamOut(); page += FPSTR(HTTP_FORM_END); + if(_showBack) page += FPSTR(HTTP_BACKBTN); reportStatus(page); page += FPSTR(HTTP_END); @@ -1311,7 +1353,7 @@ void WiFiManager::handleWiFiStatus(){ handleRequest(); String page; // String page = "{\"result\":true,\"count\":1}"; - #ifdef JSTEST + #ifdef WM_JSTEST page = FPSTR(HTTP_JS); #endif server->sendHeader(FPSTR(HTTP_HEAD_CL), String(page.length())); @@ -1366,7 +1408,7 @@ void WiFiManager::handleWifiSave() { page += FPSTR(HTTP_PARAMSAVED); } else { - String page = getHTTPHead(FPSTR(S_titlewifisaved)); // @token titlewifisaved + page = getHTTPHead(FPSTR(S_titlewifisaved)); // @token titlewifisaved page += FPSTR(HTTP_SAVED); } page += FPSTR(HTTP_END); @@ -1408,8 +1450,10 @@ void WiFiManager::doParamSave(){ if(_paramsCount > 0){ DEBUG_WM(DEBUG_VERBOSE,F("Parameters")); DEBUG_WM(DEBUG_VERBOSE,FPSTR(D_HR)); + for (int i = 0; i < _paramsCount; i++) { - if (_params[i] == NULL) { + if (_params[i] == NULL || _params[i]->_length == 0) { + DEBUG_WM(DEBUG_ERROR,"[ERROR] WiFiManagerParameter is out of scope"); break; // @todo might not be needed anymore } //read parameter from server @@ -1446,6 +1490,7 @@ void WiFiManager::handleInfo() { uint16_t infos = 0; //@todo convert to enum or refactor to strings + //@todo wrap in build flag to remove all info code for memory saving #ifdef ESP8266 infos = 27; String infoids[] = { @@ -1512,6 +1557,7 @@ void WiFiManager::handleInfo() { } page += F(""); if(_showInfoErase) page += FPSTR(HTTP_ERASEBTN); + if(_showBack) page += FPSTR(HTTP_BACKBTN); page += FPSTR(HTTP_HELP); page += FPSTR(HTTP_END); @@ -1524,7 +1570,7 @@ void WiFiManager::handleInfo() { String WiFiManager::getInfoData(String id){ String p; - // @todo add versioning + // @todo add WM versioning if(id==F("esphead"))p = FPSTR(HTTP_INFO_esphead); else if(id==F("wifihead"))p = FPSTR(HTTP_INFO_wifihead); else if(id==F("uptime")){ @@ -1806,11 +1852,16 @@ void WiFiManager::handleNotFound() { boolean WiFiManager::captivePortal() { DEBUG_WM(DEBUG_DEV,"-> " + server->hostHeader()); - if(!_enableCaptivePortal) return false; // skip redirections - - if (!isIp(server->hostHeader())) { + if(!_enableCaptivePortal) return false; // skip redirections, @todo maybe allow redirection even when no cp ? might be useful + + String serverLoc = toStringIp(server->client().localIP()); + if(_httpPort != 80) serverLoc += ":" + (String)_httpPort; // add port if not default + bool doredirect = serverLoc != server->hostHeader(); // redirect if hostheader not server ip, prevent redirect loops + // doredirect = !isIp(server->hostHeader()) // old check + + if (doredirect) { DEBUG_WM(DEBUG_VERBOSE,F("<- Request redirected to captive portal")); - server->sendHeader(F("Location"), (String)F("http://") + toStringIp(server->client().localIP()), true); + server->sendHeader(F("Location"), (String)F("http://") + serverLoc, true); server->send ( 302, FPSTR(HTTP_HEAD_CT2), ""); // 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; @@ -1931,7 +1982,6 @@ bool WiFiManager::erase(bool opt){ // if opt true, do nvs erase if(opt){ DEBUG_WM("Erasing NVS"); - int err; esp_err_t err; err = nvs_flash_init(); DEBUG_WM(DEBUG_VERBOSE,"nvs_flash_init: ",err!=ESP_OK ? (String)err : "Success"); @@ -1963,7 +2013,7 @@ bool WiFiManager::erase(bool opt){ * @access public */ void WiFiManager::resetSettings() { - DEBUG_WM(F("SETTINGS ERASED")); + DEBUG_WM(F("resetSettings")); WiFi_enableSTA(true,true); // must be sta to disconnect erase if (_resetcallback != NULL) @@ -1975,7 +2025,8 @@ void WiFiManager::resetSettings() { WiFi.persistent(true); WiFi.disconnect(true); WiFi.persistent(false); - #endif + #endif + DEBUG_WM(F("SETTINGS ERASED")); } // SETTERS @@ -2006,6 +2057,13 @@ void WiFiManager::setConfigPortalTimeout(unsigned long seconds) { void WiFiManager::setConnectTimeout(unsigned long seconds) { _connectTimeout = seconds * 1000; } +/** + * toggle _cleanconnect, always disconnect before connecting + * @param {[type]} bool enable [description] + */ +void WiFiManager::setCleanConnect(bool enable){ + _cleanConnect = enable; +} /** * [setConnectTimeout description @@ -2350,7 +2408,7 @@ void WiFiManager::setMenu(const char * menu[], uint8_t size){ } } } - DEBUG_WM(getMenuOut()); + // DEBUG_WM(getMenuOut()); } /** @@ -2373,13 +2431,14 @@ void WiFiManager::setMenu(std::vector& menu){ } } } - DEBUG_WM(getMenuOut()); + // DEBUG_WM(getMenuOut()); } /** * set params as sperate page not in wifi - * NOT COMPATIBLE WITH setMenu! @todo scan menuids and insert param after wifi or something + * NOT COMPATIBLE WITH setMenu! + * @todo scan menuids and insert param after wifi or something, same for ota * @param bool enable * @since $dev */ @@ -2447,6 +2506,10 @@ void WiFiManager::setClass(String str){ _bodyClass = str; } +void WiFiManager::setHttpPort(uint16_t port){ + _httpPort = port; +} + // HELPERS /** @@ -2495,8 +2558,8 @@ void WiFiManager::DEBUG_WM(wm_debuglevel_t level,Generic text,Genericb textb) { uint16_t max; uint8_t frag; #ifdef ESP8266 - ESP.getHeapStats(&free, &max, &frag); - _debugPort.printf("[MEM] free: %5d | max: %5d | frag: %3d%% \n", free, max, frag); + // ESP.getHeapStats(&free, &max, &frag);// @todo Does not exist in 2.3.0 + // _debugPort.printf("[MEM] free: %5d | max: %5d | frag: %3d%% \n", free, max, frag); #elif defined ESP32 // total_free_bytes; ///< Total free bytes in the heap. Equivalent to multi_free_heap_size(). // total_allocated_bytes; ///< Total bytes allocated to data in the heap. @@ -2529,13 +2592,16 @@ void WiFiManager::DEBUG_WM(wm_debuglevel_t level,Generic text,Genericb textb) { * @return {[type]} [description] */ void WiFiManager::debugSoftAPConfig(){ - wifi_country_t country; #ifdef ESP8266 softap_config config; wifi_softap_get_config(&config); - wifi_get_country(&country); + #if !defined(WM_NOCOUNTRY) + wifi_country_t country; + wifi_get_country(&country); + #endif #elif defined(ESP32) + wifi_country_t country; wifi_config_t conf_config; esp_wifi_get_config(WIFI_IF_AP, &conf_config); // == ESP_OK wifi_ap_config_t config = conf_config.ap; @@ -2551,7 +2617,9 @@ void WiFiManager::debugSoftAPConfig(){ DEBUG_WM(F("authmode: "),config.authmode); DEBUG_WM(F("ssid_hidden: "),config.ssid_hidden); DEBUG_WM(F("max_connection: "),config.max_connection); - DEBUG_WM(F("country: "),(String)country.cc); + #if !defined(WM_NOCOUNTRY) + DEBUG_WM(F("country: "),(String)country.cc); + #endif DEBUG_WM(F("beacon_interval: "),(String)config.beacon_interval + "(ms)"); DEBUG_WM(FPSTR(D_HR)); } @@ -2569,9 +2637,16 @@ void WiFiManager::debugPlatformInfo(){ DEBUG_WM(F("system_get_boot_version():"),system_get_boot_version()); DEBUG_WM(F("getFreeHeap(): "),(String)ESP.getFreeHeap()); #elif defined(ESP32) - size_t freeHeap = heap_caps_get_free_size(MALLOC_CAP_8BIT); - DEBUG_WM("Free heap: ", freeHeap); - DEBUG_WM("ESP-IDF version: ", esp_get_idf_version()); + DEBUG_WM("Free heap: ", ESP.getFreeHeap()); + DEBUG_WM("ESP SDK version: ", ESP.getSdkVersion()); + // esp_chip_info_t chipInfo; + // esp_chip_info(&chipInfo); + // DEBUG_WM("Chip Info: Model: ",chipInfo.model); + // DEBUG_WM("Chip Info: Cores: ",chipInfo.cores); + // DEBUG_WM("Chip Info: Rev: ",chipInfo.revision); + // DEBUG_WM(printf("Chip Info: Model: %d, cores: %d, revision: %d", chipInfo.model.c_str(), chipInfo.cores, chipInfo.revision)); + // DEBUG_WM("Chip Rev: ",(String)ESP.getChipRevision()); + // core version is not avail #endif } @@ -2674,7 +2749,7 @@ bool WiFiManager::WiFiSetCountry(){ else if(_wificountry == "CN") ret = esp_wifi_set_country(&WM_COUNTRY_CN) == ESP_OK; else DEBUG_WM(DEBUG_ERROR,"[ERROR] country code not found"); - #elif defined(ESP8266) + #elif defined(ESP8266) && !defined(WM_NOCOUNTRY) // if(WiFi.getMode() == WIFI_OFF); // exception if wifi not init! if(_wificountry == "US") ret = wifi_set_country((wifi_country_t*)&WM_COUNTRY_US); else if(_wificountry == "JP") ret = wifi_set_country((wifi_country_t*)&WM_COUNTRY_JP); @@ -2715,14 +2790,14 @@ bool WiFiManager::WiFi_Disconnect() { #ifdef ESP8266 if((WiFi.getMode() & WIFI_STA) != 0) { bool ret; - DEBUG_WM(DEBUG_DEV,F("WIFI station disconnect")); + DEBUG_WM(DEBUG_DEV,F("WiFi station disconnect")); ETS_UART_INTR_DISABLE(); // @todo probably not needed ret = wifi_station_disconnect(); ETS_UART_INTR_ENABLE(); return ret; } #elif defined(ESP32) - DEBUG_WM(DEBUG_DEV,F("WIFI station disconnect")); + DEBUG_WM(DEBUG_DEV,F("WiFi station disconnect")); return WiFi.disconnect(); // not persistent atm #endif return false; @@ -2730,7 +2805,7 @@ bool WiFiManager::WiFi_Disconnect() { // toggle STA without persistent bool WiFiManager::WiFi_enableSTA(bool enable,bool persistent) { - DEBUG_WM(DEBUG_DEV,F("WiFi station enable")); + DEBUG_WM(DEBUG_DEV,F("WiFi_enableSTA"),(String) enable? "enable" : "disable"); #ifdef ESP8266 WiFiMode_t newMode; WiFiMode_t currentMode = WiFi.getMode(); @@ -2858,8 +2933,9 @@ String WiFiManager::WiFi_psk(bool persistent) const { void WiFiManager::WiFiEvent(WiFiEvent_t event,system_event_info_t info){ if(!_hasBegun){ // DEBUG_WM(DEBUG_VERBOSE,"[ERROR] WiFiEvent, not ready"); + Serial.println("[ERROR] wm not ready"); return; - } + } // DEBUG_WM(DEBUG_VERBOSE,"[EVENT]",event); if(event == SYSTEM_EVENT_STA_DISCONNECTED){ DEBUG_WM(DEBUG_VERBOSE,"[EVENT] WIFI_REASON:",info.disconnected.reason); @@ -2887,7 +2963,7 @@ void WiFiManager::WiFi_autoReconnect(){ // @todo move to seperate method, used for event listener now DEBUG_WM(DEBUG_VERBOSE,"ESP32 event handler enabled"); using namespace std::placeholders; - WiFi.onEvent(std::bind(&WiFiManager::WiFiEvent,this,_1,_2)); + wm_event_id = WiFi.onEvent(std::bind(&WiFiManager::WiFiEvent,this,_1,_2)); // } #endif } diff --git a/WiFiManager.h b/WiFiManager.h index 0c23aa4..213c08a 100644 --- a/WiFiManager.h +++ b/WiFiManager.h @@ -22,14 +22,18 @@ #include -// #define WM_MDNS // also set MDNS with sethostname +// #define WM_MDNS // includes MDNS, also set MDNS with sethostname // #define WM_FIXERASECONFIG // use erase flash fix // #define WM_ERASE_NVS // esp32 erase(true) will erase NVS // #define WM_RTC // esp32 info page will include reset reasons +// #define WM_JSTEST // build flag for enabling js xhr tests +// #define WIFI_MANAGER_OVERRIDE_STRINGS // build flag for using own strings include + #ifdef ARDUINO_ESP8266_RELEASE_2_3_0 #warning "ARDUINO_ESP8266_RELEASE_2_3_0, some WM features disabled" #define WM_NOASYNC // esp8266 no async scan wifi +#define WM_NOCOUNTRY // esp8266 no country #endif // #include "soc/efuse_reg.h" // include to add efuse chip rev to info, getChipRevision() is almost always the same though, so not sure why it matters. @@ -67,7 +71,7 @@ #include #else #include - // Forthcoming official ? + // Forthcoming official ? probably never happening // https://github.com/esp8266/ESPWebServer #endif #endif @@ -85,7 +89,6 @@ #include #endif - #else #endif @@ -114,6 +117,7 @@ class WiFiManagerParameter { WiFiManagerParameter(const char *id, const char *label, const char *defaultValue, int length, const char *custom); WiFiManagerParameter(const char *id, const char *label, const char *defaultValue, int length, const char *custom, int labelPlacement); ~WiFiManagerParameter(); + // WiFiManagerParameter& operator=(const WiFiManagerParameter& rhs); const char *getID() const; const char *getValue() const; @@ -128,13 +132,13 @@ class WiFiManagerParameter { void init(const char *id, const char *label, const char *defaultValue, int length, const char *custom, int labelPlacement); private: + WiFiManagerParameter& operator=(const WiFiManagerParameter&); const char *_id; const char *_label; char *_value; int _length; int _labelPlacement; const char *_customHTML; - friend class WiFiManager; }; @@ -160,8 +164,10 @@ class WiFiManager //manually start the web portal, autoconnect does this automatically on connect failure void startWebPortal(); + //manually stop the web portal if started manually void stopWebPortal(); + // Run webserver processing, if setConfigPortalBlocking(false) boolean process(); @@ -171,34 +177,43 @@ class WiFiManager // erase wifi credentials void resetSettings(); + // reboot esp void reboot(); + // disconnect wifi, without persistent saving or erasing bool disconnect(); + // erase esp bool erase(); bool erase(bool opt); //adds a custom parameter, returns false on failure bool addParameter(WiFiManagerParameter *p); + //returns the list of Parameters WiFiManagerParameter** getParameters(); + // returns the Parameters Count int getParametersCount(); - // SET CALLBACKS //called after AP mode and config portal has started void setAPCallback( std::function func ); + //called after webserver has started void setWebServerCallback( std::function func ); + //called when settings reset have been triggered void setConfigResetCallback( std::function func ); + //called when wifi settings have been changed and connection was successful ( or setBreakAfterConfig(true) ) void setSaveConfigCallback( std::function func ); + //called when settings have been changed and connection was successful void setSaveParamsCallback( std::function func ); + //called when settings before have been changed and connection was successful void setPreSaveConfigCallback( std::function func ); @@ -211,59 +226,86 @@ class WiFiManager //sets timeout for which to attempt connecting, useful if you get a lot of failed connects void setConnectTimeout(unsigned long seconds); + //sets timeout for which to attempt connecting on saves, useful if there are bugs in esp waitforconnectloop void setSaveConnectTimeout(unsigned long seconds); + // toggle debug output void setDebugOutput(boolean debug); + //set min quality percentage to include in scan, defaults to 8% if not specified 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 void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn); + //sets config for a static IP with DNS void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn, IPAddress dns); + //if this is set, it will exit after config, even if connection is unsuccessful. void setBreakAfterConfig(boolean shouldBreak); + // if this is set, portal will be blocking and wait until save or exit, // is false user must manually `process()` to handle config portal, // setConfigPortalTimeout is ignored in this mode, user is responsible for closing configportal void setConfigPortalBlocking(boolean shouldBlock); + //if this is set, customise style void setCustomHeadElement(const char* element); + //if this is true, remove duplicated Access Points - defaut true void setRemoveDuplicateAPs(boolean removeDuplicates); + //setter for ESP wifi.persistent so we can remember it and restore user preference, as WIFi._persistent is protected void setRestorePersistent(boolean persistent); + //if true, always show static net inputs, IP, subnet, gateway, else only show if set via setSTAStaticIPConfig void setShowStaticFields(boolean alwaysShow); + //if true, always show static dns, esle only show if set via setSTAStaticIPConfig void setShowDnsFields(boolean alwaysShow); + // toggle showing the saved wifi password in wifi form, could be a security issue. void setShowPassword(boolean show); + //if false, disable captive portal redirection void setCaptivePortalEnable(boolean enabled); + //if false, timeout captive portal even if a STA client connected to softAP (false), suggest disabling if captiveportal is open void setAPClientCheck(boolean enabled); + //if true, reset timeout when webclient connects (true), suggest disabling if captiveportal is open void setWebPortalClientCheck(boolean enabled); + // if true, enable autoreconnecting void setWiFiAutoReconnect(boolean enabled); + // if true, wifiscan will show percentage instead of quality icons, until we have better templating void setScanDispPerc(boolean enabled); + // if true (default) then start the config portal from autoConnect if connection failed void setEnableConfigPortal(boolean enable); + // set a custom hostname, sets sta and ap dhcp client id for esp32, and sta for esp8266 bool setHostname(const char * hostname); + // show erase wifi onfig button on info page, true void setShowInfoErase(boolean enabled); + // set ap channel void setWiFiAPChannel(int32_t channel); + // set ap hidden void setWiFiAPHidden(bool hidden); // default false - // set custom menu + + // clean connect, always disconnect before connecting + void setCleanConnect(bool enable); // default false - // set custom menu items and order + // set custom menu items and order, vector or arr + // see _menutokens for ids void setMenu(std::vector& menu); void setMenu(const char* menu[], uint8_t size); @@ -272,29 +314,43 @@ class WiFiManager // get last connection result, includes autoconnect and wifisave uint8_t getLastConxResult(); + // get a status as string String getWLStatusString(uint8_t status); + + // get wifi mode as string String getModeString(uint8_t mode); + // check if the module has a saved ap to connect to bool getWiFiIsSaved(); - // helper to get saved ssid, if persistent get stored, else get current if connected + // helper to get saved password, if persistent get stored, else get current if connected String getWiFiPass(bool persistent = false); - // helper to get saved password, if persistent get stored, else get current if connected + + // helper to get saved ssid, if persistent get stored, else get current if connected String getWiFiSSID(bool persistent = false); // debug output the softap config void debugSoftAPConfig(); + // debug output platform info and versioning void debugPlatformInfo(); + + // helper for html String htmlEntities(String str); - // set the country code for wifi settings + // set the country code for wifi settings, CN void setCountry(String cc); - // set body class (invert) + + // set body class (invert), may be used for hacking in alt classes in the future void setClass(String str); + + // get default ap esp uses , esp_chipid etc String getDefaultAPName(); + // set port of webserver, 80 + void setHttpPort(uint16_t port); + std::unique_ptr dnsServer; #if defined(ESP32) && defined(WM_WEBSERVERSHIM) @@ -333,22 +389,24 @@ class WiFiManager unsigned long _saveTimeout = 0; // ms stop trying to connect to ap on saves, in case bugs in esp waitforconnectresult unsigned long _configPortalStart = 0; // ms config portal start time (updated for timeouts) unsigned long _webPortalAccessed = 0; // ms last web access time - WiFiMode_t _usermode = WIFI_OFF; + WiFiMode_t _usermode = WIFI_STA; // Default user mode String _wifissidprefix = FPSTR(S_ssidpre); // auto apname prefix prefix+chipid - uint8_t _lastconxresult = WL_IDLE_STATUS; - int _numNetworks = 0; + uint8_t _lastconxresult = WL_IDLE_STATUS; // store last result when doing connect operations + int _numNetworks = 0; // init index for numnetworks wifiscans unsigned long _lastscan = 0; // ms for timing wifi scans unsigned long _startscan = 0; // ms for timing wifi scans int _cpclosedelay = 2000; // delay before wifisave, prevents captive portal from closing to fast. - bool _cleanConnect = true; // disconnect before connect in connectwifi, increases stability on connects + bool _cleanConnect = false; // disconnect before connect in connectwifi, increases stability on connects bool _disableSTA = false; // disable sta when starting ap, always bool _disableSTAConn = true; // disable sta when starting ap, if sta is not connected ( stability ) bool _channelSync = false; // use same wifi sta channel when starting ap int32_t _apChannel = 0; // channel to use for ap bool _apHidden = false; // store softap hidden value + uint16_t _httpPort = 80; // port for webserver #ifdef ESP32 + wifi_event_id_t wm_event_id; static uint8_t _lastconxresulttmp; // tmp var for esp32 callback #endif @@ -372,29 +430,41 @@ class WiFiManager boolean _scanDispOptions = false; // show percentage in scans not icons boolean _paramsInWifi = true; // show custom parameters on wifi page boolean _showInfoErase = true; // info page erase button + boolean _showBack = false; // show back button boolean _enableConfigPortal = true; // use config portal if autoconnect failed - const char * _hostname = ""; + const char * _hostname = ""; // hostname for esp8266 for dhcp, and or MDNS const char* _customHeadElement = ""; // store custom head element html from user String _bodyClass = ""; // class to add to body // internal options + + // wifiscan notes + // The following are background wifi scanning optimizations + // experimental to make scans faster, preload scans after starting cp, and visiting home page, so when you click wifi its already has your list + // ideally we would add async and xhr here but I am holding off on js requirements atm + // might be slightly buggy since captive portals hammer the home page, @todo workaround this somehow. + // cache time helps throttle this + // async enables asyncronous scans, so they do not block anything + // the refresh button bypasses cache boolean _preloadwifiscan = true; // preload wifiscan if true - boolean _asyncScan = false; + boolean _asyncScan = false; // perform wifi network scan async unsigned int _scancachetime = 30000; // ms cache time for background scans + boolean _disableIpFields = false; // modify function of setShow_X_Fields(false), forces ip fields off instead of default show if set, eg. _staShowStaticFields=-1 String _wificountry = ""; // country code, @todo define in strings lang // wrapper functions for handling setting and unsetting persistent for now. bool esp32persistent = false; - bool _hasBegun = false; + bool _hasBegun = false; // flag wm loaded,unloaded void _begin(); void _end(); void setupConfigPortal(); bool shutdownConfigPortal(); - + bool setupHostname(bool restart); + #ifdef NO_EXTRA_4K_HEAP boolean _tryWPS = false; // try WPS on save failure, unsupported void startWPS(); @@ -544,4 +614,4 @@ class WiFiManager #endif -#endif \ No newline at end of file +#endif diff --git a/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino b/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino index 34c4d75..e86a39c 100644 --- a/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino +++ b/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino @@ -14,64 +14,21 @@ #include #endif -#define TRIGGER_PIN 0 const char* modes[] = { "NULL", "STA", "AP", "STA+AP" }; unsigned long mtime = 0; -// // #define MYOLED - -// #include -// #include -// #include -// #ifdef MYOLED - -// #define SCREEN_WIDTH 128 // OLED display width, in pixels -// #define SCREEN_HEIGHT 32 // OLED display height, in pixels - -// // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) -// #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) -// Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); - -// void init_oled(){ -// Wire.begin(SCL,SDA); // begin(sda, scl) SWAP! -// // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally -// if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32 -// Serial.println(F("SSD1306 allocation failed")); -// } - -// display.clearDisplay(); -// display.setTextSize(1); // Normal 1:1 pixepl scale -// display.setTextColor(WHITE); // Draw white text -// display.setCursor(0,0); // Start at top-left corner -// display.display(); -// } - -// void print_oled(String str,uint8_t size){ -// display.clearDisplay(); -// display.setTextSize(size); -// display.setTextColor(WHITE); -// display.setCursor(0,0); -// display.println(str); -// display.display(); -// } -// #else -// void print_oled(String str,uint8_t size){ -// (void)str; -// (void)size; -// } -// #endif - -void print_oled(String str,uint8_t size){ - (void)str; - (void)size; -} WiFiManager wm; -// OPTION FLAGS -bool TEST_CP = true; // always start the configportal, even if ap found -bool TEST_NET = true; // do a network test after connect, (gets ntp time) +// TEST OPTION FLAGS +bool TEST_CP = true; // always start the configportal, even if ap found +int TESP_CP_TIMEOUT = 90; // test cp timeout + +bool TEST_NET = true; // do a network test after connect, (gets ntp time) +bool ALLOWONDEMAND = true; // enable on demand +int ONDDEMANDPIN = 0; // gpio for button + // char ssid[] = "*************"; // your network SSID (name) // char pass[] = "********"; // your network password @@ -83,9 +40,6 @@ void saveWifiCallback(){ //gets called when WiFiManager enters configuration mode void configModeCallback (WiFiManager *myWiFiManager) { Serial.println("[CALLBACK] configModeCallback fired"); - #ifdef ESP8266 - print_oled("WiFiManager Waiting\nIP: " + WiFi.softAPIP().toString() + "\nSSID: " + WiFi.softAPSSID(),1); - #endif // myWiFiManager->setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); // Serial.println(WiFi.softAPIP()); //if you used auto generated SSID, print it @@ -99,7 +53,7 @@ void saveParamCallback(){ void bindServerCallback(){ wm.server->on("/custom",handleRoute); - // wm.server->on("/info",handleRoute); // can override wm! + // wm.server->on("/info",handleRoute); // you can override wm! } void handleRoute(){ @@ -109,37 +63,33 @@ void handleRoute(){ void setup() { WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP + // put your setup code here, to run once: Serial.begin(115200); // Serial1.begin(115200); // Serial.setDebugOutput(true); delay(1000); - // Serial1.println("TXD1 Enabled"); Serial.println("\n Starting"); // WiFi.setSleepMode(WIFI_NONE_SLEEP); // disable sleep, can improve ap stability - - #ifdef OLED - init_oled(); - #endif - print_oled(F("Starting..."),2); + + Serial.println("Error - TEST"); + Serial.println("Information- - TEST"); + + Serial.println("[ERROR] TEST"); + Serial.println("[INFORMATION] TEST"); + wm.debugPlatformInfo(); - //Local intialization. Once its business is done, there is no need to keep it around //reset settings - for testing // wm.resetSettings(); // wm.erase(); + // invert theme, dark wm.setClass("invert"); - //sets timeout until configuration portal gets turned off - //useful to make it all retry or go to sleep - //in seconds - // wm.setConfigPortalTimeout(600); - // wm.setConnectTimeout(5); - // wm.setShowStaticFields(true); - + // setup some parameters WiFiManagerParameter custom_html("

This Is Custom HTML

"); // only custom html WiFiManagerParameter custom_mqtt_server("server", "mqtt server", "", 40); WiFiManagerParameter custom_mqtt_port("port", "mqtt port", "", 6); @@ -156,7 +106,7 @@ void setup() { wm.setSaveConfigCallback(saveWifiCallback); wm.setSaveParamsCallback(saveParamCallback); - //add all your parameters here + // add all your parameters here wm.addParameter(&custom_html); wm.addParameter(&custom_mqtt_server); wm.addParameter(&custom_mqtt_port); @@ -165,72 +115,104 @@ void setup() { wm.addParameter(&custom_ipaddress); wm.addParameter(&custom_checkbox); + // set values later if you want custom_html.setValue("test",4); custom_token.setValue("test",4); - // Set cutom menu via menu[] or vector - // const char* menu[] = {"wifi","wifinoscan","info","param","close","sep","erase","restart","exit"}; - // wm.setMenu(menu,9); // custom menu array must provide length +/* + Set cutom menu via menu[] or vector + const char* menu[] = {"wifi","wifinoscan","info","param","close","sep","erase","restart","exit"}; + wm.setMenu(menu,9); // custom menu array must provide length +*/ std::vector menu = {"wifi","wifinoscan","info","param","close","sep","erase","restart","exit"}; // wm.setMenu(menu); // custom menu, pass vector - wm.setParamsPage(true); // move params to seperate page, not wifi, do not combine with setmenu! + // wm.setParamsPage(true); // move params to seperate page, not wifi, do not combine with setmenu! - // set static sta ip + // set STA static ip // wm.setSTAStaticIPConfig(IPAddress(10,0,1,99), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); // wm.setShowStaticFields(false); // wm.setShowDnsFields(false); - // set static ip + // set AP static ip // wm.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); // wm.setAPStaticIPConfig(IPAddress(10,0,1,99), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); // set country - wm.setCountry("US"); // setting wifi country seems to improve OSX soft ap connectivity, may help others as well - - // set channel + // setting wifi country seems to improve OSX soft ap connectivity, + // may help others as well, default is CN which has different channels + wm.setCountry("US"); + + // set Hostname + wm.setHostname("WIFIMANAGERTESTING"); + + // set custom channel // wm.setWiFiAPChannel(13); // set AP hidden // wm.setAPHidden(true); - // show password publicly! + // show password publicly in form // wm.setShowPassword(true); - // set configrportal timeout + //sets timeout until configuration portal gets turned off + //useful to make it all retry or go to sleep in seconds wm.setConfigPortalTimeout(120); + + // set connection timeout + // wm.setConnectTimeout(20); + + // show static ip fields + // wm.setShowStaticFields(true); + // wm.startConfigPortal("AutoConnectAP", "password"); + + // This is sometimes necessary, it is still unknown when and why this is needed but it may solve some race condition or bug in esp SDK/lib + // wm.setCleanConnect(true); // disconnect before connect, clean connect + + // + wm.setBreakAfterConfig(true); - // wm.setBreakAfterConfig(true); + // set custom webserver port, automatic captive portal does not work with custom ports! + // wm.setHttpPort(8080); //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 - print_oled(F("Connecting..."),2); - if(!wm.autoConnect("WM_AutoConnectAP")) { + wifiInfo(); + + if(!wm.autoConnect("WM_AutoConnectAP","12345678")) { Serial.println("failed to connect and hit timeout"); - print_oled("Not Connected",2); } else if(TEST_CP) { + // start configportal always delay(1000); Serial.println("TEST_CP ENABLED"); - // start configportal always - wm.setConfigPortalTimeout(60); + wm.setConfigPortalTimeout(TESP_CP_TIMEOUT); wm.startConfigPortal("WM_ConnectAP"); } else { //if you get here you have connected to the WiFi Serial.println("connected...yeey :)"); - print_oled("Connected\nIP: " + WiFi.localIP().toString() + "\nSSID: " + WiFi.SSID(),1); } - pinMode(TRIGGER_PIN, INPUT); + + wifiInfo(); + pinMode(ONDDEMANDPIN, INPUT_PULLUP); #ifdef USEOTA ArduinoOTA.begin(); #endif + +} + +void wifiInfo(){ + WiFi.printDiag(Serial); + Serial.println("SAVED: " + (String)wm.getWiFiIsSaved() ? "YES" : "NO"); + Serial.println("SSID: " + (String)wm.getWiFiSSID()); + Serial.println("PASS: " + (String)wm.getWiFiPass()); } void loop() { @@ -239,9 +221,9 @@ void loop() { ArduinoOTA.handle(); #endif // is configuration portal requested? - if ( digitalRead(TRIGGER_PIN) == LOW ) { + if (ALLOWONDEMAND && digitalRead(ONDDEMANDPIN) == LOW ) { delay(100); - if ( digitalRead(TRIGGER_PIN) == LOW ){ + if ( digitalRead(ONDDEMANDPIN) == LOW ){ Serial.println("BUTTON PRESSED"); wm.setConfigPortalTimeout(140); wm.setParamsPage(false); // move params to seperate page, not wifi, do not combine with setmenu! @@ -257,7 +239,6 @@ void loop() { else { //if you get here you have connected to the WiFi Serial.println("connected...yeey :)"); - print_oled("Connected\nIP: " + WiFi.localIP().toString() + "\nSSID: " + WiFi.SSID(),1); getTime(); } } @@ -283,13 +264,13 @@ void getTime() { Serial.print("."); now = time(nullptr); if((millis() - start) > timeout){ - Serial.println("[ERROR] Failed to get NTP time."); + Serial.println("\n[ERROR] Failed to get NTP time."); return; } } Serial.println(""); struct tm timeinfo; - gmtime_r(&now, &timeinfo); + gmtime_r(&now, &timeinfo); // @NOTE doesnt work in esp2.3.0 Serial.print("Current time: "); Serial.print(asctime(&timeinfo)); } @@ -315,4 +296,4 @@ void debugchipid(){ // AP esp_267751 // 507726A4AE30 // ESP32 Chip ID = 507726A4AE30 -} \ No newline at end of file +} diff --git a/examples/NonBlocking/OnDemandNonBlocking/onDemandNonBlocking.ino b/examples/NonBlocking/OnDemandNonBlocking/onDemandNonBlocking.ino index 7ebd8d5..3813356 100644 --- a/examples/NonBlocking/OnDemandNonBlocking/onDemandNonBlocking.ino +++ b/examples/NonBlocking/OnDemandNonBlocking/onDemandNonBlocking.ino @@ -6,6 +6,13 @@ */ #include // https://github.com/tzapu/WiFiManager +// include MDNS +#ifdef ESP8266 +#include +#elif defined(ESP32) +#include +#endif + // select which pin will trigger the configuration portal when set to LOW #define TRIGGER_PIN 0 @@ -20,11 +27,23 @@ void setup() { WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP // put your setup code here, to run once Serial.begin(115200); + Serial.setDebugOutput(true); + delay(1000); Serial.println("\n Starting"); + pinMode(TRIGGER_PIN, INPUT_PULLUP); + + // wm.resetSettings(); + wm.setHostname("MDNSEXAMPLE"); + // wm.setEnableConfigPortal(false); + // wm.setConfigPortalBlocking(false); + wm.autoConnect(); } void loop() { + #ifdef ESP8266 + MDNS.update(); + #endif doWiFiManager(); // put your main code here, to run repeatedly: } diff --git a/examples/Tests/AnonymousCB.ino b/examples/Tests/AnonymousCB.ino new file mode 100644 index 0000000..f34d80f --- /dev/null +++ b/examples/Tests/AnonymousCB.ino @@ -0,0 +1,26 @@ +#include // https://github.com/tzapu/WiFiManager + +bool _enteredConfigMode = false; + +void setup(){ + Serial.begin(115200); + WiFiManager wifiManager; + + // wifiManager.setAPCallback([this](WiFiManager* wifiManager) { + wifiManager.setAPCallback([&](WiFiManager* wifiManager) { + Serial.printf("Entered config mode:ip=%s, ssid='%s'\n", + WiFi.softAPIP().toString().c_str(), + wifiManager->getConfigPortalSSID().c_str()); + _enteredConfigMode = true; + }); + wifiManager.resetSettings(); + if (!wifiManager.autoConnect()) { + Serial.printf("*** Failed to connect and hit timeout\n"); + ESP.restart(); + delay(1000); + } +} + +void loop(){ + +} diff --git a/extras/WiFiManager.template.html b/extras/WiFiManager.template.html index 74480ee..d2c2c39 100644 --- a/extras/WiFiManager.template.html +++ b/extras/WiFiManager.template.html @@ -139,12 +139,12 @@ a:hover { .msg.P h4 { color: var(--primarycolor); } -/*.msg.S { +.msg.S { border-left-color: #5cb85c; } .msg.S h4 { color: #5cb85c; -}*/ +} .msg.D { border-left-color: #dc3630; } @@ -201,6 +201,7 @@ input:disabled {



+

/wifi


@@ -269,9 +270,12 @@ input:disabled {
No AP set
-

H4 Color Header

content
+

H4 Color Header P

content
+

H4 Color Header S

content
+ +

/info


Chip ID
123456
diff --git a/library.json b/library.json index 0ceb4c8..96c4164 100644 --- a/library.json +++ b/library.json @@ -25,5 +25,5 @@ "espressif8266", "espressif32" ], - "version": "1.0.0" + "version": "2.0.3-alpha" } diff --git a/library.properties b/library.properties index 5ee6e46..9ac084b 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=WiFiManager -version=1.0.0 +version=2.0.3-alpha author=tzapu,tablatronix maintainer=tablatronix sentence=WiFi Configuration manager with web configuration portal for ESP boards diff --git a/strings_en.h b/strings_en.h index bce2ebd..903efe6 100644 --- a/strings_en.h +++ b/strings_en.h @@ -20,12 +20,12 @@ const char HTTP_HEAD_START[] PROGMEM = ""; const char HTTP_HEAD_END[] PROGMEM = "
"; - +// example of embedded logo, base64 encoded inline, No styling here +// const char HTTP_ROOT_MAIN[] PROGMEM = "

{v}

WiFiManager

"; const char HTTP_ROOT_MAIN[] PROGMEM = "

{v}

WiFiManager

"; const char * const HTTP_PORTAL_MENU[] PROGMEM = { "

\n", // MENU_WIFI @@ -57,11 +57,12 @@ const char HTTP_FORM_PARAM[] PROGMEM = "
More information about WiFiManager at https://github.com/tzapu/WiFiManager."; -#ifdef JSTEST +#ifdef WM_JSTEST const char HTTP_JS[] PROGMEM = "