diff --git a/README.md b/README.md index 6acf010..34f19cb 100644 --- a/README.md +++ b/README.md @@ -292,6 +292,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 bb5af87..993726e 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() { + // Serial.println(printf("Address of _value is %p\n", (void *)_value)); return _value; } const char* WiFiManagerParameter::getID() { @@ -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")); } @@ -282,6 +290,8 @@ boolean WiFiManager::autoConnect(char const *apName, char const *apPassword) { 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 } if(connected || connectWifi("", "") == WL_CONNECTED){ @@ -297,12 +307,13 @@ boolean WiFiManager::autoConnect(char const *apName, char const *apPassword) { DEBUG_WM(DEBUG_DEV,"hostname: STA",WiFi.getHostname()); #endif } - return true; + + return true; // connected success } // possibly skip the config portal if (!_enableConfigPortal) { - return false; + return false; // not connected and not cp } DEBUG_WM(F("AutoConnect: FAILED")); @@ -486,7 +497,9 @@ 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); @@ -1832,11 +1845,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; @@ -2383,7 +2401,7 @@ void WiFiManager::setMenu(const char * menu[], uint8_t size){ } } } - DEBUG_WM(getMenuOut()); + // DEBUG_WM(getMenuOut()); } /** @@ -2406,7 +2424,7 @@ void WiFiManager::setMenu(std::vector& menu){ } } } - DEBUG_WM(getMenuOut()); + // DEBUG_WM(getMenuOut()); } @@ -2480,6 +2498,10 @@ void WiFiManager::setClass(String str){ _bodyClass = str; } +void WiFiManager::setHttpPort(uint16_t port){ + _httpPort = port; +} + // HELPERS /** @@ -2603,8 +2625,16 @@ void WiFiManager::debugPlatformInfo(){ 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 } @@ -2891,8 +2921,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); @@ -2920,7 +2951,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 02032f2..2ed854b 100644 --- a/WiFiManager.h +++ b/WiFiManager.h @@ -115,6 +115,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 char *getValue(); @@ -129,13 +130,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; }; @@ -298,6 +299,9 @@ class WiFiManager void setClass(String str); String getDefaultAPName(); + // set port of webserver + void setHttpPort(uint16_t port); + std::unique_ptr dnsServer; #if defined(ESP32) && defined(WM_WEBSERVERSHIM) @@ -350,8 +354,10 @@ class WiFiManager 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 diff --git a/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino b/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino index f78546e..e779dc3 100644 --- a/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino +++ b/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino @@ -14,11 +14,11 @@ #include #endif -#define TRIGGER_PIN 0 const char* modes[] = { "NULL", "STA", "AP", "STA+AP" }; unsigned long mtime = 0; +// OLED TEST , untested // // #define MYOLED // #include @@ -69,11 +69,14 @@ void print_oled(String str,uint8_t size){ WiFiManager wm; -// OPTION FLAGS -bool TEST_CP = false; // always start the configportal, even if ap found -bool TEST_NET = true; // do a network test after connect, (gets ntp time) -bool AUTOSTARTCP = false; // automatically start config portal is no wifi found -bool ALLOWONDEMAND = true; + +// 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 @@ -195,7 +198,7 @@ void setup() { //sets timeout until configuration portal gets turned off //useful to make it all retry or go to sleep in seconds - wm.setConfigPortalTimeout(120); + wm.setConfigPortalTimeout(120); // wm.setConnectTimeout(20); // wm.setShowStaticFields(true); @@ -206,6 +209,9 @@ void setup() { 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" @@ -220,7 +226,7 @@ void setup() { delay(1000); Serial.println("TEST_CP ENABLED"); // start configportal always - wm.setConfigPortalTimeout(60); + wm.setConfigPortalTimeout(TESP_CP_TIMEOUT); wm.startConfigPortal("WM_ConnectAP"); } else { @@ -230,7 +236,7 @@ void setup() { } wifiInfo(); - pinMode(TRIGGER_PIN, INPUT_PULLUP); + pinMode(ONDDEMANDPIN, INPUT_PULLUP); #ifdef USEOTA ArduinoOTA.begin(); @@ -252,9 +258,9 @@ void loop() { ArduinoOTA.handle(); #endif // is configuration portal requested? - if (ALLOWONDEMAND && 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!