diff --git a/.travis.yml b/.travis.yml index 7da81e4..cc63c55 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,9 @@ before_install: - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" - sleep 3 - export DISPLAY=:1.0 - - wget http://downloads.arduino.cc/arduino-1.8.8-linux64.tar.xz - - tar xf arduino-1.8.8-linux64.tar.xz - - sudo mv arduino-1.8.8 /usr/local/share/arduino + - wget http://downloads.arduino.cc/arduino-1.8.10-linux64.tar.xz + - tar xf arduino-1.8.10-linux64.tar.xz + - sudo mv arduino-1.8.10 /usr/local/share/arduino - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino install: diff --git a/README.md b/README.md index fb03403..e28d960 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ First attempt at a library. Lots more changes and fixes to do. Contributions are - Installing - [Arduino - Through Library Manager](#install-through-library-manager) - [Arduino - From Github](#checkout-from-github) - - [PlatformIO] + - [PlatformIO](#install-using-platformio) - [Using](#using) - [Documentation](#documentation) - [Access Point Password](#password-protect-the-configuration-access-point) @@ -147,6 +147,31 @@ While in AP mode, connect to it then open a browser to the gateway IP, default 1 Also see [examples](https://github.com/tzapu/WiFiManager/tree/master/examples). +#### Install Using PlatformIO + +[PlatformIO](https://platformio.org/) is an emerging ecosystem for IoT development, and +is an alternative to using the Arduino IDE. Install `WiFiManager` +using the platformio [library manager](https://docs.platformio.org/en/latest/librarymanager/index.htm) in your editor, +or using the [PlatformIO Core CLI](https://docs.platformio.org/en/latest/userguide/demo.html#library-manager), +or by adding it to your `platformio.ini` as shown below (recommended approach). + +The simplest way is to open the `platformio.ini` file at the root of your project, and `WifiManager` to the common top-level env +`lib_deps` key like so: + +``` +[env] +lib_deps = + WiFiManager +``` + +If you want to install the development branch, then you'll need to use the `repository#tag` format instead: + +``` +[env] +lib_deps = + https://github.com/tzapu/WiFiManager.git#development +``` + ## Documentation #### Password protect the configuration Access Point diff --git a/WiFiManager.cpp b/WiFiManager.cpp index 95d5496..4ba8d40 100644 --- a/WiFiManager.cpp +++ b/WiFiManager.cpp @@ -184,7 +184,8 @@ WiFiManager::WiFiManager(Stream& consolePort):_debugPort(consolePort){ WiFiManagerInit(); } -WiFiManager::WiFiManager():WiFiManager(Serial) { +WiFiManager::WiFiManager() { + WiFiManagerInit(); } void WiFiManager::WiFiManagerInit(){ @@ -371,20 +372,21 @@ bool WiFiManager::startAP(){ } // start soft AP with password or anonymous + // default channel is 1 here and in esplib, @todo just change to default remove conditionals if (_apPassword != "") { if(channel>0){ - ret = WiFi.softAP(_apName.c_str(), _apPassword.c_str(),channel); + ret = WiFi.softAP(_apName.c_str(), _apPassword.c_str(),channel,_apHidden); } else{ - ret = WiFi.softAP(_apName.c_str(), _apPassword.c_str());//password option + ret = WiFi.softAP(_apName.c_str(), _apPassword.c_str(),1,_apHidden);//password option } } else { DEBUG_WM(DEBUG_VERBOSE,F("AP has anonymous access!")); if(channel>0){ - ret = WiFi.softAP(_apName.c_str(),"",channel); + ret = WiFi.softAP(_apName.c_str(),"",channel,_apHidden); } else{ - ret = WiFi.softAP(_apName.c_str()); + ret = WiFi.softAP(_apName.c_str(),"",1,_apHidden); } } @@ -626,7 +628,7 @@ uint8_t WiFiManager::processConfigPortal(){ // skip wifi if no ssid if(_ssid == ""){ - DEBUG_WM(DEBUG_VERBOSE,F("No ssid, skipping wifi")); + DEBUG_WM(DEBUG_VERBOSE,F("No ssid, skipping wifi save")); } else{ // attempt sta connection to submitted _ssid, _pass @@ -976,6 +978,13 @@ void WiFiManager::handleWifi(boolean scan) { pitem = FPSTR(HTTP_FORM_WIFI); pitem.replace(FPSTR(T_v), WiFi_SSID()); + + if(_showPassword){ + pitem.replace(FPSTR(T_p), WiFi_psk()); + } + else { + pitem.replace(FPSTR(T_p),FPSTR(S_passph)); + } page += pitem; page += getStaticOut(); @@ -1026,7 +1035,7 @@ String WiFiManager::getMenuOut(){ String page; for(auto menuId :_menuIds ){ - if(((String)menuId == "param") && (_paramsCount == 0)) continue; // no params set, omit params + if(((String)menuId == "param") && (_paramsCount == 0)) continue; // no params set, omit params from menu, @todo this may be undesired by someone page += HTTP_PORTAL_MENU[menuId]; } @@ -1354,8 +1363,16 @@ void WiFiManager::handleWifiSave() { DEBUG_WM(DEBUG_DEV,F("static DNS:"),dns); } - String page = getHTTPHead(FPSTR(S_titlewifisaved)); // @token titlewifisaved - page += FPSTR(HTTP_SAVED); + String page; + + if(_ssid == ""){ + page = getHTTPHead(FPSTR(S_titlewifisettings)); // @token titleparamsaved + page += FPSTR(HTTP_PARAMSAVED); + } + else { + String page = getHTTPHead(FPSTR(S_titlewifisaved)); // @token titlewifisaved + page += FPSTR(HTTP_SAVED); + } page += FPSTR(HTTP_END); server->sendHeader(FPSTR(HTTP_HEAD_CL), String(page.length())); @@ -1926,10 +1943,21 @@ bool WiFiManager::erase(bool opt){ DEBUG_WM(DEBUG_VERBOSE,"nvs_flash_erase: ", err!=ESP_OK ? (String)err : "Success"); return err == ESP_OK; } + #elif defined(ESP8266) && defined(spiffs_api_h) + if(opt){ + bool ret = false; + if(SPIFFS.begin()){ + DEBUG_WM("Erasing SPIFFS"); + bool ret = SPIFFS.format(); + DEBUG_WM(DEBUG_VERBOSE,"spiffs erase: ",ret ? "Success" : "ERROR"); + } else DEBUG_WM("[ERROR] Could not start SPIFFS"); + return ret; + } #else (void)opt; #endif + DEBUG_WM("Erasing WiFi Config"); return WiFi_eraseConfig(); } @@ -2186,6 +2214,17 @@ void WiFiManager::setShowDnsFields(boolean alwaysShow){ _staShowDns = alwaysShow ? 1 : 0; } +/** + * toggle showing password in wifi password field + * if not enabled, placeholder will be S_passph + * @since $dev + * @access public + * @param boolean alwaysShow [false] + */ +void WiFiManager::setShowPassword(boolean show){ + _showPassword = show; +} + /** * toggle captive portal * if enabled, then devices that use captive portal checks will be redirected to root @@ -2278,6 +2317,15 @@ void WiFiManager::setWiFiAPChannel(int32_t channel){ _apChannel = channel; } +/** + * set the soft ap hidden + * @param bool wifi ap hidden, default is false + */ +void WiFiManager::setWiFiAPHidden(bool hidden){ + _apHidden = hidden; +} + + /** * toggle showing erase wifi config button on info page * @param boolean enabled @@ -2333,6 +2381,18 @@ void WiFiManager::setMenu(std::vector& menu){ } +/** + * set params as sperate page not in wifi + * NOT COMPATIBLE WITH setMenu! @todo scan menuids and insert param after wifi or something + * @param bool enable + * @since $dev + */ +void WiFiManager::setParamsPage(bool enable){ + _paramsInWifi= false; + _menuIdsDefault = {"wifi","param","info","exit"}; + setMenu(_menuIdsDefault); +} + // GETTERS /** @@ -2436,8 +2496,27 @@ void WiFiManager::DEBUG_WM(wm_debuglevel_t level,Generic text,Genericb textb) { if(!_debug || _debugLevel < level) return; if(_debugLevel >= DEBUG_MAX){ - _debugPort.print("MEM: "); - _debugPort.println((String)ESP.getFreeHeap()); + uint32_t free; + 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); + #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. + // largest_free_block; ///< Size of largest free block in the heap. This is the largest malloc-able size. + // minimum_free_bytes; ///< Lifetime minimum free heap size. Equivalent to multi_minimum_free_heap_size(). + // allocated_blocks; ///< Number of (variable size) blocks allocated in the heap. + // free_blocks; ///< Number of (variable size) free blocks in the heap. + // total_blocks; ///< Total number of (variable size) blocks in the heap. + multi_heap_info_t info; + heap_caps_get_info(&info, MALLOC_CAP_INTERNAL); + free = info.total_free_bytes; + max = info.largest_free_block; + frag = 100 - (max * 100) / free; + _debugPort.printf("[MEM] free: %5d | max: %5d | frag: %3d%% \n", free, max, frag); + #endif } _debugPort.print("*WM: "); if(_debugLevel == DEBUG_DEV) _debugPort.print("["+(String)level+"] "); @@ -2602,9 +2681,9 @@ bool WiFiManager::WiFiSetCountry(){ #elif defined(ESP8266) // if(WiFi.getMode() == WIFI_OFF); // exception if wifi not init! - if(_wificountry == "US") ret = wifi_set_country(&WM_COUNTRY_US); - else if(_wificountry == "JP") ret = wifi_set_country(&WM_COUNTRY_JP); - else if(_wificountry == "CN") ret = wifi_set_country(&WM_COUNTRY_CN); + 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); + else if(_wificountry == "CN") ret = wifi_set_country((wifi_country_t*)&WM_COUNTRY_CN); else DEBUG_WM(DEBUG_ERROR,"[ERROR] country code not found"); #endif diff --git a/WiFiManager.h b/WiFiManager.h index 2c2d664..7c894d3 100644 --- a/WiFiManager.h +++ b/WiFiManager.h @@ -240,6 +240,8 @@ class WiFiManager 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 @@ -258,12 +260,16 @@ class WiFiManager void setShowInfoErase(boolean enabled); // set ap channel void setWiFiAPChannel(int32_t channel); - + // set ap hidden + void setWiFiAPHidden(bool hidden); // default false // set custom menu // set custom menu items and order void setMenu(std::vector& menu); void setMenu(const char* menu[], uint8_t size); + + // add params to its own menu page and remove from wifi, NOT TO BE COMBINED WITH setMenu! + void setParamsPage(bool enable); // get last connection result, includes autoconnect and wifisave uint8_t getLastConxResult(); @@ -340,6 +346,7 @@ class WiFiManager 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 #ifdef ESP32 static uint8_t _lastconxresulttmp; // tmp var for esp32 callback @@ -354,6 +361,7 @@ class WiFiManager int _staShowStaticFields = 0; // ternary 1=always show static ip fields, 0=only if set, -1=never(cannot change ips via web!) int _staShowDns = 0; // ternary 1=always show dns, 0=only if set, -1=never(cannot change dns via web!) boolean _removeDuplicateAPs = true; // remove dup aps from wifiscan + boolean _showPassword = false; // show or hide saved password on wifi form, might be a security issue! boolean _shouldBreakAfterConfig = false; // stop configportal on save failure boolean _configPortalIsBlocking = true; // configportal enters blocking loop boolean _enableCaptivePortal = true; // enable captive portal redirection @@ -487,16 +495,29 @@ class WiFiManager // debugging typedef enum { DEBUG_ERROR = 0, - DEBUG_NOTIFY = 1, // default + DEBUG_NOTIFY = 1, // default stable DEBUG_VERBOSE = 2, - DEBUG_DEV = 3, + DEBUG_DEV = 3, // default dev DEBUG_MAX = 4 } wm_debuglevel_t; - boolean _debug = true; - uint8_t _debugLevel = DEBUG_DEV; - Stream& _debugPort; // debug output stream ref + boolean _debug = true; + // build debuglevel support + // @todo use DEBUG_ESP_x? + #ifdef WM_DEBUG_LEVEL + uint8_t _debugLevel = (uint8_t)WM_DEBUG_LEVEL; + #else + uint8_t _debugLevel = DEBUG_DEV; // default debug level + #endif + + // @todo use DEBUG_ESP_PORT ? + #ifdef WM_DEBUG_PORT + Stream& _debugPort = WM_DEBUG_PORT; + #else + Stream& _debugPort = Serial; // debug output stream ref + #endif + template void DEBUG_WM(Generic text); diff --git a/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino b/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino index 3b6419e..72f23eb 100644 --- a/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino +++ b/examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino @@ -5,6 +5,14 @@ */ #include // https://github.com/tzapu/WiFiManager #include +#include + +#define USEOTA +// enable OTA +#ifdef USEOTA +#include +#include +#endif #define TRIGGER_PIN 0 const char* modes[] = { "NULL", "STA", "AP", "STA+AP" }; @@ -60,10 +68,13 @@ void print_oled(String str,uint8_t size){ } WiFiManager wm; -bool TEST_CP = false; // always start the configportal -bool TEST_NET = true; // do a network test, get ntp time -char ssid[] = "*************"; // your network SSID (name) -char pass[] = "********"; // your network password + +// 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) + +// char ssid[] = "*************"; // your network SSID (name) +// char pass[] = "********"; // your network password void saveWifiCallback(){ Serial.println("[CALLBACK] saveCallback fired"); @@ -100,8 +111,12 @@ 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(3000); + delay(1000); + // Serial1.println("TXD1 Enabled"); + Serial.println("\n Starting"); // WiFi.setSleepMode(WIFI_NONE_SLEEP); // disable sleep, can improve ap stability @@ -160,6 +175,8 @@ void setup() { std::vector menu = {"wifi","info","param","update","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! + // set static sta ip // wm.setSTAStaticIPConfig(IPAddress(10,0,1,99), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); // wm.setShowStaticFields(false); @@ -173,19 +190,27 @@ void setup() { wm.setCountry("US"); // setting wifi country seems to improve OSX soft ap connectivity, may help others as well // set channel - wm.setWiFiAPChannel(13); + // wm.setWiFiAPChannel(13); + // set AP hidden + // wm.setAPHidden(true); + + // show password publicly! + // wm.setShowPassword(true); + // set configrportal timeout wm.setConfigPortalTimeout(120); // wm.startConfigPortal("AutoConnectAP", "password"); + // wm.setBreakAfterConfig(true); + //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("AutoConnectAP")) { + if(!wm.autoConnect("WM_AutoConnectAP")) { Serial.println("failed to connect and hit timeout"); print_oled("Not Connected",2); } @@ -194,7 +219,7 @@ void setup() { Serial.println("TEST_CP ENABLED"); // start configportal always wm.setConfigPortalTimeout(60); - wm.startConfigPortal(); + wm.startConfigPortal("WM_ConnectAP"); } else { //if you get here you have connected to the WiFi @@ -202,9 +227,17 @@ void setup() { print_oled("Connected\nIP: " + WiFi.localIP().toString() + "\nSSID: " + WiFi.SSID(),1); } pinMode(TRIGGER_PIN, INPUT); + + #ifdef USEOTA + ArduinoOTA.begin(); + #endif } void loop() { + + #ifdef USEOTA + ArduinoOTA.handle(); + #endif // is configuration portal requested? if ( digitalRead(TRIGGER_PIN) == LOW ) { delay(100); diff --git a/strings_en.h b/strings_en.h index 2936b2c..85cf298 100644 --- a/strings_en.h +++ b/strings_en.h @@ -48,7 +48,7 @@ const char HTTP_ITEM[] PROGMEM = "
{v} {R} {r}% {q} {e}
"; // test all tokens const char HTTP_FORM_START[] PROGMEM = "
"; -const char HTTP_FORM_WIFI[] PROGMEM = "
"; +const char HTTP_FORM_WIFI[] PROGMEM = "
"; const char HTTP_FORM_WIFI_END[] PROGMEM = ""; const char HTTP_FORM_STATIC_HEAD[] PROGMEM = "

"; const char HTTP_FORM_END[] PROGMEM = "

"; @@ -196,8 +196,9 @@ const char S_disable[] PROGMEM = "Disabled"; const char S_GET[] PROGMEM = "GET"; const char S_POST[] PROGMEM = "POST"; const char S_NA[] PROGMEM = "Unknown"; - +const char S_passph[] PROGMEM = "********"; const char S_titlewifisaved[] PROGMEM = "Credentials Saved"; +const char S_titlewifisettings[] PROGMEM = "Settings Saved"; const char S_titlewifi[] PROGMEM = "Config ESP"; const char S_titleinfo[] PROGMEM = "Info"; const char S_titleparam[] PROGMEM = "Setup"; @@ -363,9 +364,9 @@ const wifi_country_t WM_COUNTRY_JP{"JP",1,14,CONFIG_ESP32_PHY_MAX_TX_POWER,WIFI_ // uint8_t nchan; /**< total channel number */ // uint8_t policy; /**< country policy */ // } wifi_country_t; -static wifi_country_t WM_COUNTRY_US{"US",1,11,WIFI_COUNTRY_POLICY_AUTO}; -static wifi_country_t WM_COUNTRY_CN{"CN",1,13,WIFI_COUNTRY_POLICY_AUTO}; -static wifi_country_t WM_COUNTRY_JP{"JP",1,14,WIFI_COUNTRY_POLICY_AUTO}; +const wifi_country_t WM_COUNTRY_US{"US",1,11,WIFI_COUNTRY_POLICY_AUTO}; +const wifi_country_t WM_COUNTRY_CN{"CN",1,13,WIFI_COUNTRY_POLICY_AUTO}; +const wifi_country_t WM_COUNTRY_JP{"JP",1,14,WIFI_COUNTRY_POLICY_AUTO}; #endif #endif \ No newline at end of file