WiFiManager.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. /**
  2. * WiFiManager.h
  3. *
  4. * WiFiManager, a library for the ESP8266/Arduino platform
  5. * for configuration of WiFi credentials using a Captive Portal
  6. *
  7. * @author Creator tzapu
  8. * @author tablatronix
  9. * @version 0.0.0
  10. * @license MIT
  11. */
  12. #ifndef WiFiManager_h
  13. #define WiFiManager_h
  14. #if defined(ESP8266) || defined(ESP32)
  15. #ifdef ESP8266
  16. #include <core_version.h>
  17. #endif
  18. #include <vector>
  19. // #define WM_MDNS // also set MDNS with sethostname
  20. // #define WM_FIXERASECONFIG // use erase flash fix
  21. // #define WM_ERASE_NVS // esp32 erase(true) will erase NVS
  22. // #define WM_RTC // esp32 info page will include reset reasons
  23. #ifdef ARDUINO_ESP8266_RELEASE_2_3_0
  24. #warning "ARDUINO_ESP8266_RELEASE_2_3_0, some WM features disabled"
  25. #define WM_NOASYNC // esp8266 no async scan wifi
  26. #endif
  27. // #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.
  28. // #define esp32autoreconnect // implement esp32 autoreconnect event listener kludge, @DEPRECATED
  29. // autoreconnect is WORKING https://github.com/espressif/arduino-esp32/issues/653#issuecomment-405604766
  30. #define WM_WEBSERVERSHIM // use webserver shim lib
  31. #ifdef ESP8266
  32. extern "C" {
  33. #include "user_interface.h"
  34. }
  35. #include <ESP8266WiFi.h>
  36. #include <ESP8266WebServer.h>
  37. #ifdef WM_MDNS
  38. #include <ESP8266mDNS.h>
  39. #endif
  40. #define WIFI_getChipId() ESP.getChipId()
  41. #define WM_WIFIOPEN ENC_TYPE_NONE
  42. #elif defined(ESP32)
  43. #include <WiFi.h>
  44. #include <esp_wifi.h>
  45. #define WIFI_getChipId() (uint32_t)ESP.getEfuseMac()
  46. #define WM_WIFIOPEN WIFI_AUTH_OPEN
  47. #ifndef WEBSERVER_H
  48. #ifdef WM_WEBSERVERSHIM
  49. #include <WebServer.h>
  50. #else
  51. #include <ESP8266WebServer.h>
  52. // Forthcoming official ?
  53. // https://github.com/esp8266/ESPWebServer
  54. #endif
  55. #endif
  56. #ifdef WM_ERASE_NVS
  57. #include <nvs.h>
  58. #include <nvs_flash.h>
  59. #endif
  60. #ifdef WM_MDNS
  61. #include <ESPmDNS.h>
  62. #endif
  63. #ifdef WM_RTC
  64. #include <rom/rtc.h>
  65. #endif
  66. #else
  67. #endif
  68. #include <DNSServer.h>
  69. #include <memory>
  70. #include "strings_en.h"
  71. #ifndef WIFI_MANAGER_MAX_PARAMS
  72. #define WIFI_MANAGER_MAX_PARAMS 5 // params will autoincrement and realloc by this amount when max is reached
  73. #endif
  74. #define WFM_LABEL_BEFORE 1
  75. #define WFM_LABEL_AFTER 2
  76. #define WFM_NO_LABEL 0
  77. class WiFiManagerParameter {
  78. public:
  79. /**
  80. Create custom parameters that can be added to the WiFiManager setup web page
  81. @id is used for HTTP queries and must not contain spaces nor other special characters
  82. */
  83. WiFiManagerParameter();
  84. WiFiManagerParameter(const char *custom);
  85. WiFiManagerParameter(const char *id, const char *label);
  86. WiFiManagerParameter(const char *id, const char *label, const char *defaultValue, int length);
  87. WiFiManagerParameter(const char *id, const char *label, const char *defaultValue, int length, const char *custom);
  88. WiFiManagerParameter(const char *id, const char *label, const char *defaultValue, int length, const char *custom, int labelPlacement);
  89. ~WiFiManagerParameter();
  90. const char *getID();
  91. const char *getValue();
  92. const char *getLabel();
  93. const char *getPlaceholder(); // @deprecated, use getLabel
  94. int getValueLength();
  95. int getLabelPlacement();
  96. const char *getCustomHTML();
  97. void setValue(const char *defaultValue, int length);
  98. protected:
  99. void init(const char *id, const char *label, const char *defaultValue, int length, const char *custom, int labelPlacement);
  100. private:
  101. const char *_id;
  102. const char *_label;
  103. char *_value;
  104. int _length;
  105. int _labelPlacement;
  106. const char *_customHTML;
  107. friend class WiFiManager;
  108. };
  109. class WiFiManager
  110. {
  111. public:
  112. WiFiManager(Stream& consolePort);
  113. WiFiManager();
  114. ~WiFiManager();
  115. void WiFiManagerInit();
  116. // auto connect to saved wifi, or custom, and start config portal on failures
  117. boolean autoConnect();
  118. boolean autoConnect(char const *apName, char const *apPassword = NULL);
  119. //manually start the config portal, autoconnect does this automatically on connect failure
  120. boolean startConfigPortal(); // auto generates apname
  121. boolean startConfigPortal(char const *apName, char const *apPassword = NULL);
  122. //manually stop the config portal if started manually, stop immediatly if non blocking, flag abort if blocking
  123. bool stopConfigPortal();
  124. //manually start the web portal, autoconnect does this automatically on connect failure
  125. void startWebPortal();
  126. //manually stop the web portal if started manually
  127. void stopWebPortal();
  128. // Run webserver processing, if setConfigPortalBlocking(false)
  129. boolean process();
  130. // get the AP name of the config portal, so it can be used in the callback
  131. String getConfigPortalSSID();
  132. int getRSSIasQuality(int RSSI);
  133. // erase wifi credentials
  134. void resetSettings();
  135. // reboot esp
  136. void reboot();
  137. // disconnect wifi, without persistent saving or erasing
  138. bool disconnect();
  139. // erase esp
  140. bool erase();
  141. bool erase(bool opt);
  142. //adds a custom parameter, returns false on failure
  143. bool addParameter(WiFiManagerParameter *p);
  144. //returns the list of Parameters
  145. WiFiManagerParameter** getParameters();
  146. // returns the Parameters Count
  147. int getParametersCount();
  148. // SET CALLBACKS
  149. //called after AP mode and config portal has started
  150. void setAPCallback( std::function<void(WiFiManager*)> func );
  151. //called after webserver has started
  152. void setWebServerCallback( std::function<void()> func );
  153. //called when settings reset have been triggered
  154. void setConfigResetCallback( std::function<void()> func );
  155. //called when wifi settings have been changed and connection was successful ( or setBreakAfterConfig(true) )
  156. void setSaveConfigCallback( std::function<void()> func );
  157. //called when settings have been changed and connection was successful
  158. void setSaveParamsCallback( std::function<void()> func );
  159. //called when settings before have been changed and connection was successful
  160. void setPreSaveConfigCallback( std::function<void()> func );
  161. //sets timeout before AP,webserver loop ends and exits even if there has been no setup.
  162. //useful for devices that failed to connect at some point and got stuck in a webserver loop
  163. //in seconds setConfigPortalTimeout is a new name for setTimeout, ! not used if setConfigPortalBlocking
  164. void setConfigPortalTimeout(unsigned long seconds);
  165. void setTimeout(unsigned long seconds); // @deprecated, alias
  166. //sets timeout for which to attempt connecting, useful if you get a lot of failed connects
  167. void setConnectTimeout(unsigned long seconds);
  168. //sets timeout for which to attempt connecting on saves, useful if there are bugs in esp waitforconnectloop
  169. void setSaveConnectTimeout(unsigned long seconds);
  170. // toggle debug output
  171. void setDebugOutput(boolean debug);
  172. //set min quality percentage to include in scan, defaults to 8% if not specified
  173. void setMinimumSignalQuality(int quality = 8);
  174. //sets a custom ip /gateway /subnet configuration
  175. void setAPStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn);
  176. //sets config for a static IP
  177. void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn);
  178. //sets config for a static IP with DNS
  179. void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn, IPAddress dns);
  180. //if this is set, it will exit after config, even if connection is unsuccessful.
  181. void setBreakAfterConfig(boolean shouldBreak);
  182. // if this is set, portal will be blocking and wait until save or exit,
  183. // is false user must manually `process()` to handle config portal,
  184. // setConfigPortalTimeout is ignored in this mode, user is responsible for closing configportal
  185. void setConfigPortalBlocking(boolean shouldBlock);
  186. //if this is set, customise style
  187. void setCustomHeadElement(const char* element);
  188. //if this is true, remove duplicated Access Points - defaut true
  189. void setRemoveDuplicateAPs(boolean removeDuplicates);
  190. //setter for ESP wifi.persistent so we can remember it and restore user preference, as WIFi._persistent is protected
  191. void setRestorePersistent(boolean persistent);
  192. //if true, always show static net inputs, IP, subnet, gateway, else only show if set via setSTAStaticIPConfig
  193. void setShowStaticFields(boolean alwaysShow);
  194. //if true, always show static dns, esle only show if set via setSTAStaticIPConfig
  195. void setShowDnsFields(boolean alwaysShow);
  196. // toggle showing the saved wifi password in wifi form, could be a security issue.
  197. void setShowPassword(boolean show);
  198. //if false, disable captive portal redirection
  199. void setCaptivePortalEnable(boolean enabled);
  200. //if false, timeout captive portal even if a STA client connected to softAP (false), suggest disabling if captiveportal is open
  201. void setAPClientCheck(boolean enabled);
  202. //if true, reset timeout when webclient connects (true), suggest disabling if captiveportal is open
  203. void setWebPortalClientCheck(boolean enabled);
  204. // if true, enable autoreconnecting
  205. void setWiFiAutoReconnect(boolean enabled);
  206. // if true, wifiscan will show percentage instead of quality icons, until we have better templating
  207. void setScanDispPerc(boolean enabled);
  208. // if true (default) then start the config portal from autoConnect if connection failed
  209. void setEnableConfigPortal(boolean enable);
  210. // set a custom hostname, sets sta and ap dhcp client id for esp32, and sta for esp8266
  211. bool setHostname(const char * hostname);
  212. // show erase wifi onfig button on info page, true
  213. void setShowInfoErase(boolean enabled);
  214. // set ap channel
  215. void setWiFiAPChannel(int32_t channel);
  216. // set ap hidden
  217. void setWiFiAPHidden(bool hidden); // default false
  218. // clean connect, always disconnect before connecting
  219. void setCleanConnect(bool enable); // default false
  220. // set custom menu
  221. // set custom menu items and order
  222. void setMenu(std::vector<const char*>& menu);
  223. void setMenu(const char* menu[], uint8_t size);
  224. // add params to its own menu page and remove from wifi, NOT TO BE COMBINED WITH setMenu!
  225. void setParamsPage(bool enable);
  226. // get last connection result, includes autoconnect and wifisave
  227. uint8_t getLastConxResult();
  228. // get a status as string
  229. String getWLStatusString(uint8_t status);
  230. String getModeString(uint8_t mode);
  231. // check if the module has a saved ap to connect to
  232. bool getWiFiIsSaved();
  233. // helper to get saved ssid, if persistent get stored, else get current if connected
  234. String getWiFiPass(bool persistent = false);
  235. // helper to get saved password, if persistent get stored, else get current if connected
  236. String getWiFiSSID(bool persistent = false);
  237. // debug output the softap config
  238. void debugSoftAPConfig();
  239. // debug output platform info and versioning
  240. void debugPlatformInfo();
  241. String htmlEntities(String str);
  242. // set the country code for wifi settings
  243. void setCountry(String cc);
  244. // set body class (invert)
  245. void setClass(String str);
  246. String getDefaultAPName();
  247. std::unique_ptr<DNSServer> dnsServer;
  248. #if defined(ESP32) && defined(WM_WEBSERVERSHIM)
  249. using WM_WebServer = WebServer;
  250. #else
  251. using WM_WebServer = ESP8266WebServer;
  252. #endif
  253. std::unique_ptr<WM_WebServer> server;
  254. private:
  255. std::vector<uint8_t> _menuIds;
  256. std::vector<const char *> _menuIdsParams = {"wifi","param","info","exit"};
  257. std::vector<const char *> _menuIdsDefault = {"wifi","info","exit"};
  258. // ip configs @todo struct ?
  259. IPAddress _ap_static_ip;
  260. IPAddress _ap_static_gw;
  261. IPAddress _ap_static_sn;
  262. IPAddress _sta_static_ip;
  263. IPAddress _sta_static_gw;
  264. IPAddress _sta_static_sn;
  265. IPAddress _sta_static_dns;
  266. // defaults
  267. const byte DNS_PORT = 53;
  268. const byte HTTP_PORT = 80;
  269. String _apName = "no-net";
  270. String _apPassword = "";
  271. String _ssid = "";
  272. String _pass = "";
  273. // options flags
  274. unsigned long _configPortalTimeout = 0; // ms close config portal loop if set (depending on _cp/webClientCheck options)
  275. unsigned long _connectTimeout = 0; // ms stop trying to connect to ap if set
  276. unsigned long _saveTimeout = 0; // ms stop trying to connect to ap on saves, in case bugs in esp waitforconnectresult
  277. unsigned long _configPortalStart = 0; // ms config portal start time (updated for timeouts)
  278. unsigned long _webPortalAccessed = 0; // ms last web access time
  279. WiFiMode_t _usermode = WIFI_OFF;
  280. String _wifissidprefix = FPSTR(S_ssidpre); // auto apname prefix prefix+chipid
  281. uint8_t _lastconxresult = WL_IDLE_STATUS;
  282. int _numNetworks = 0;
  283. unsigned long _lastscan = 0; // ms for timing wifi scans
  284. unsigned long _startscan = 0; // ms for timing wifi scans
  285. int _cpclosedelay = 2000; // delay before wifisave, prevents captive portal from closing to fast.
  286. bool _cleanConnect = false; // disconnect before connect in connectwifi, increases stability on connects
  287. bool _disableSTA = false; // disable sta when starting ap, always
  288. bool _disableSTAConn = true; // disable sta when starting ap, if sta is not connected ( stability )
  289. bool _channelSync = false; // use same wifi sta channel when starting ap
  290. int32_t _apChannel = 0; // channel to use for ap
  291. bool _apHidden = false; // store softap hidden value
  292. #ifdef ESP32
  293. static uint8_t _lastconxresulttmp; // tmp var for esp32 callback
  294. #endif
  295. #ifndef WL_STATION_WRONG_PASSWORD
  296. uint8_t WL_STATION_WRONG_PASSWORD = 7; // @kludge define a WL status for wrong password
  297. #endif
  298. // parameter options
  299. int _minimumQuality = -1; // filter wifiscan ap by this rssi
  300. int _staShowStaticFields = 0; // ternary 1=always show static ip fields, 0=only if set, -1=never(cannot change ips via web!)
  301. int _staShowDns = 0; // ternary 1=always show dns, 0=only if set, -1=never(cannot change dns via web!)
  302. boolean _removeDuplicateAPs = true; // remove dup aps from wifiscan
  303. boolean _showPassword = false; // show or hide saved password on wifi form, might be a security issue!
  304. boolean _shouldBreakAfterConfig = false; // stop configportal on save failure
  305. boolean _configPortalIsBlocking = true; // configportal enters blocking loop
  306. boolean _enableCaptivePortal = true; // enable captive portal redirection
  307. boolean _userpersistent = true; // users preffered persistence to restore
  308. boolean _wifiAutoReconnect = true; // there is no platform getter for this, we must assume its true and make it so
  309. boolean _apClientCheck = false; // keep cp alive if ap have station
  310. boolean _webClientCheck = true; // keep cp alive if web have client
  311. boolean _scanDispOptions = false; // show percentage in scans not icons
  312. boolean _paramsInWifi = true; // show custom parameters on wifi page
  313. boolean _showInfoErase = true; // info page erase button
  314. boolean _enableConfigPortal = true; // use config portal if autoconnect failed
  315. const char * _hostname = "";
  316. const char* _customHeadElement = ""; // store custom head element html from user
  317. String _bodyClass = ""; // class to add to body
  318. // internal options
  319. boolean _preloadwifiscan = true; // preload wifiscan if true
  320. boolean _asyncScan = false;
  321. unsigned int _scancachetime = 30000; // ms cache time for background scans
  322. boolean _disableIpFields = false; // modify function of setShow_X_Fields(false), forces ip fields off instead of default show if set, eg. _staShowStaticFields=-1
  323. String _wificountry = ""; // country code, @todo define in strings lang
  324. // wrapper functions for handling setting and unsetting persistent for now.
  325. bool esp32persistent = false;
  326. bool _hasBegun = false;
  327. void _begin();
  328. void _end();
  329. void setupConfigPortal();
  330. bool shutdownConfigPortal();
  331. #ifdef NO_EXTRA_4K_HEAP
  332. boolean _tryWPS = false; // try WPS on save failure, unsupported
  333. void startWPS();
  334. #endif
  335. bool startAP();
  336. uint8_t connectWifi(String ssid, String pass);
  337. bool setSTAConfig();
  338. bool wifiConnectDefault();
  339. bool wifiConnectNew(String ssid, String pass);
  340. uint8_t waitForConnectResult();
  341. uint8_t waitForConnectResult(uint16_t timeout);
  342. void updateConxResult(uint8_t status);
  343. // webserver handlers
  344. void handleRoot();
  345. void handleWifi(boolean scan);
  346. void handleWifiSave();
  347. void handleInfo();
  348. void handleReset();
  349. void handleNotFound();
  350. void handleExit();
  351. void handleClose();
  352. // void handleErase();
  353. void handleErase(boolean opt);
  354. void handleParam();
  355. void handleWiFiStatus();
  356. void handleRequest();
  357. void handleParamSave();
  358. void doParamSave();
  359. boolean captivePortal();
  360. boolean configPortalHasTimeout();
  361. uint8_t processConfigPortal();
  362. void stopCaptivePortal();
  363. // wifi platform abstractions
  364. bool WiFi_Mode(WiFiMode_t m);
  365. bool WiFi_Mode(WiFiMode_t m,bool persistent);
  366. bool WiFi_Disconnect();
  367. bool WiFi_enableSTA(bool enable);
  368. bool WiFi_enableSTA(bool enable,bool persistent);
  369. bool WiFi_eraseConfig();
  370. uint8_t WiFi_softap_num_stations();
  371. bool WiFi_hasAutoConnect();
  372. void WiFi_autoReconnect();
  373. String WiFi_SSID(bool persistent = false) const;
  374. String WiFi_psk(bool persistent = false) const;
  375. bool WiFi_scanNetworks();
  376. bool WiFi_scanNetworks(bool force,bool async);
  377. bool WiFi_scanNetworks(unsigned int cachetime,bool async);
  378. bool WiFi_scanNetworks(unsigned int cachetime);
  379. void WiFi_scanComplete(int networksFound);
  380. bool WiFiSetCountry();
  381. #ifdef ESP32
  382. void WiFiEvent(WiFiEvent_t event, system_event_info_t info);
  383. #endif
  384. // output helpers
  385. String getParamOut();
  386. String getIpForm(String id, String title, String value);
  387. String getScanItemOut();
  388. String getStaticOut();
  389. String getHTTPHead(String title);
  390. String getMenuOut();
  391. //helpers
  392. boolean isIp(String str);
  393. String toStringIp(IPAddress ip);
  394. boolean validApPassword();
  395. String encryptionTypeStr(uint8_t authmode);
  396. void reportStatus(String &page);
  397. String getInfoData(String id);
  398. // flags
  399. boolean connect;
  400. boolean abort;
  401. boolean reset = false;
  402. boolean configPortalActive = false;
  403. boolean webPortalActive = false;
  404. boolean portalTimeoutResult = false;
  405. boolean portalAbortResult = false;
  406. boolean storeSTAmode = true; // option store persistent STA mode in connectwifi
  407. int timer = 0;
  408. // WiFiManagerParameter
  409. int _paramsCount = 0;
  410. int _max_params;
  411. WiFiManagerParameter** _params = NULL;
  412. // debugging
  413. typedef enum {
  414. DEBUG_ERROR = 0,
  415. DEBUG_NOTIFY = 1, // default stable
  416. DEBUG_VERBOSE = 2,
  417. DEBUG_DEV = 3, // default dev
  418. DEBUG_MAX = 4
  419. } wm_debuglevel_t;
  420. boolean _debug = true;
  421. // build debuglevel support
  422. // @todo use DEBUG_ESP_x?
  423. #ifdef WM_DEBUG_LEVEL
  424. uint8_t _debugLevel = (uint8_t)WM_DEBUG_LEVEL;
  425. #else
  426. uint8_t _debugLevel = DEBUG_DEV; // default debug level
  427. #endif
  428. // @todo use DEBUG_ESP_PORT ?
  429. #ifdef WM_DEBUG_PORT
  430. Stream& _debugPort = WM_DEBUG_PORT;
  431. #else
  432. Stream& _debugPort = Serial; // debug output stream ref
  433. #endif
  434. template <typename Generic>
  435. void DEBUG_WM(Generic text);
  436. template <typename Generic>
  437. void DEBUG_WM(wm_debuglevel_t level,Generic text);
  438. template <typename Generic, typename Genericb>
  439. void DEBUG_WM(Generic text,Genericb textb);
  440. template <typename Generic, typename Genericb>
  441. void DEBUG_WM(wm_debuglevel_t level, Generic text,Genericb textb);
  442. // callbacks
  443. // @todo use cb list (vector) maybe event ids, allow no return value
  444. std::function<void(WiFiManager*)> _apcallback;
  445. std::function<void()> _webservercallback;
  446. std::function<void()> _savewificallback;
  447. std::function<void()> _presavecallback;
  448. std::function<void()> _saveparamscallback;
  449. std::function<void()> _resetcallback;
  450. template <class T>
  451. auto optionalIPFromString(T *obj, const char *s) -> decltype( obj->fromString(s) ) {
  452. return obj->fromString(s);
  453. }
  454. auto optionalIPFromString(...) -> bool {
  455. // DEBUG_WM("NO fromString METHOD ON IPAddress, you need ESP8266 core 2.1.0 or newer for Custom IP configuration to work.");
  456. return false;
  457. }
  458. };
  459. #endif
  460. #endif