|
| 1 | +/************************************************************** |
| 2 | + WiFiManager is a library for the ESP8266/Arduino platform |
| 3 | + (https://github.com/esp8266/Arduino) to enable easy |
| 4 | + configuration and reconfiguration of WiFi credentials using a Captive Portal |
| 5 | + inspired by: |
| 6 | + http://www.esp8266.com/viewtopic.php?f=29&t=2520 |
| 7 | + https://github.com/chriscook8/esp-arduino-apboot |
| 8 | + https://github.com/esp8266/Arduino/tree/esp8266/hardware/esp8266com/esp8266/libraries/DNSServer/examples/CaptivePortalAdvanced |
| 9 | + Built by AlexT https://github.com/tzapu |
| 10 | + Licensed under MIT license |
| 11 | + **************************************************************/ |
| 12 | + |
| 13 | +#ifndef ESPAsyncWiFiManager_h |
| 14 | +#define ESPAsyncWiFiManager_h |
| 15 | + |
| 16 | +#include <ESP8266WiFi.h> |
| 17 | +#include <ESPAsyncWebServer.h> |
| 18 | +#include <DNSServer.h> |
| 19 | +#include <memory> |
| 20 | + |
| 21 | +extern "C" { |
| 22 | + #include "user_interface.h" |
| 23 | +} |
| 24 | + |
| 25 | +const char WFM_HTTP_HEAD[] PROGMEM = "<!DOCTYPE html><html lang=\"en\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/><title>{v}</title>"; |
| 26 | +const char HTTP_STYLE[] PROGMEM = "<style>.c{text-align: center;} div,input{padding:5px;font-size:1em;} input{width:95%;} body{text-align: center;font-family:verdana;} button{border:0;border-radius:0.3rem;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%;} .q{float: right;width: 64px;text-align: right;} .l{background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAALVBMVEX///8EBwfBwsLw8PAzNjaCg4NTVVUjJiZDRUUUFxdiZGSho6OSk5Pg4eFydHTCjaf3AAAAZElEQVQ4je2NSw7AIAhEBamKn97/uMXEGBvozkWb9C2Zx4xzWykBhFAeYp9gkLyZE0zIMno9n4g19hmdY39scwqVkOXaxph0ZCXQcqxSpgQpONa59wkRDOL93eAXvimwlbPbwwVAegLS1HGfZAAAAABJRU5ErkJggg==\") no-repeat left center;background-size: 1em;}</style>"; |
| 27 | +const char HTTP_SCRIPT[] PROGMEM = "<script>function c(l){document.getElementById('s').value=l.innerText||l.textContent;document.getElementById('p').focus();}</script>"; |
| 28 | +const char HTTP_HEAD_END[] PROGMEM = "</head><body><div style='text-align:left;display:inline-block;min-width:260px;'>"; |
| 29 | +const char HTTP_PORTAL_OPTIONS[] PROGMEM = "<form action=\"/wifi\" method=\"get\"><button>Configure WiFi</button></form><br/><form action=\"/0wifi\" method=\"get\"><button>Configure WiFi (No Scan)</button></form><br/><form action=\"/i\" method=\"get\"><button>Info</button></form><br/><form action=\"/r\" method=\"post\"><button>Reset</button></form>"; |
| 30 | +const char HTTP_ITEM[] PROGMEM = "<div><a href='#p' onclick='c(this)'>{v}</a> <span class='q {i}'>{r}%</span></div>"; |
| 31 | +const char HTTP_FORM_START[] PROGMEM = "<form method='get' action='wifisave'><input id='s' name='s' length=32 placeholder='SSID'><br/><input id='p' name='p' length=64 type='password' placeholder='password'><br/>"; |
| 32 | +const char HTTP_FORM_PARAM[] PROGMEM = "<br/><input id='{i}' name='{n}' length={l} placeholder='{p}' value='{v}' {c}>"; |
| 33 | +const char HTTP_FORM_END[] PROGMEM = "<br/><button type='submit'>save</button></form>"; |
| 34 | +const char HTTP_SCAN_LINK[] PROGMEM = "<br/><div class=\"c\"><a href=\"/wifi\">Scan</a></div>"; |
| 35 | +const char HTTP_SAVED[] PROGMEM = "<div>Credentials Saved<br />Trying to connect ESP to network.<br />If it fails reconnect to AP to try again</div>"; |
| 36 | +const char HTTP_END[] PROGMEM = "</div></body></html>"; |
| 37 | + |
| 38 | +#define WIFI_MANAGER_MAX_PARAMS 10 |
| 39 | + |
| 40 | +class AsyncWiFiManagerParameter { |
| 41 | + public: |
| 42 | + AsyncWiFiManagerParameter(const char *custom); |
| 43 | + AsyncWiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length); |
| 44 | + AsyncWiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom); |
| 45 | + |
| 46 | + const char *getID(); |
| 47 | + const char *getValue(); |
| 48 | + const char *getPlaceholder(); |
| 49 | + int getValueLength(); |
| 50 | + const char *getCustomHTML(); |
| 51 | + private: |
| 52 | + const char *_id; |
| 53 | + const char *_placeholder; |
| 54 | + char *_value; |
| 55 | + int _length; |
| 56 | + const char *_customHTML; |
| 57 | + |
| 58 | + void init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom); |
| 59 | + |
| 60 | + friend class AsyncWiFiManager; |
| 61 | +}; |
| 62 | + |
| 63 | + |
| 64 | +class WiFiResult |
| 65 | +{ |
| 66 | +public: |
| 67 | + bool duplicate; |
| 68 | + String SSID; |
| 69 | + uint8_t encryptionType; |
| 70 | + int32_t RSSI; |
| 71 | + uint8_t* BSSID; |
| 72 | + int32_t channel; |
| 73 | + bool isHidden; |
| 74 | + |
| 75 | + WiFiResult() |
| 76 | + { |
| 77 | + } |
| 78 | + |
| 79 | + |
| 80 | +}; |
| 81 | + |
| 82 | +class AsyncWiFiManager |
| 83 | +{ |
| 84 | + public: |
| 85 | + AsyncWiFiManager(AsyncWebServer * server, DNSServer *dns); |
| 86 | + |
| 87 | + void scan(); |
| 88 | + |
| 89 | + boolean autoConnect(); |
| 90 | + boolean autoConnect(char const *apName, char const *apPassword = NULL); |
| 91 | + |
| 92 | + //if you want to always start the config portal, without trying to connect first |
| 93 | + boolean startConfigPortal(char const *apName, char const *apPassword = NULL); |
| 94 | + |
| 95 | + // get the AP name of the config portal, so it can be used in the callback |
| 96 | + String getConfigPortalSSID(); |
| 97 | + |
| 98 | + void resetSettings(); |
| 99 | + |
| 100 | + //sets timeout before webserver loop ends and exits even if there has been no setup. |
| 101 | + //usefully for devices that failed to connect at some point and got stuck in a webserver loop |
| 102 | + //in seconds setConfigPortalTimeout is a new name for setTimeout |
| 103 | + void setConfigPortalTimeout(unsigned long seconds); |
| 104 | + void setTimeout(unsigned long seconds); |
| 105 | + |
| 106 | + //sets timeout for which to attempt connecting, usefull if you get a lot of failed connects |
| 107 | + void setConnectTimeout(unsigned long seconds); |
| 108 | + |
| 109 | + |
| 110 | + void setDebugOutput(boolean debug); |
| 111 | + //defaults to not showing anything under 8% signal quality if called |
| 112 | + void setMinimumSignalQuality(int quality = 8); |
| 113 | + //sets a custom ip /gateway /subnet configuration |
| 114 | + void setAPStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn); |
| 115 | + //sets config for a static IP |
| 116 | + void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn); |
| 117 | + //called when AP mode and config portal is started |
| 118 | + void setAPCallback( void (*func)(AsyncWiFiManager*) ); |
| 119 | + //called when settings have been changed and connection was successful |
| 120 | + void setSaveConfigCallback( void (*func)(void) ); |
| 121 | + //adds a custom parameter |
| 122 | + void addParameter(AsyncWiFiManagerParameter *p); |
| 123 | + //if this is set, it will exit after config, even if connection is unsucessful. |
| 124 | + void setBreakAfterConfig(boolean shouldBreak); |
| 125 | + //if this is set, try WPS setup when starting (this will delay config portal for up to 2 mins) |
| 126 | + //TODO |
| 127 | + //if this is set, customise style |
| 128 | + void setCustomHeadElement(const char* element); |
| 129 | + //if this is true, remove duplicated Access Points - defaut true |
| 130 | + void setRemoveDuplicateAPs(boolean removeDuplicates); |
| 131 | + |
| 132 | + private: |
| 133 | + DNSServer *dnsServer; |
| 134 | + AsyncWebServer *server; |
| 135 | + |
| 136 | + //const int WM_DONE = 0; |
| 137 | + //const int WM_WAIT = 10; |
| 138 | + |
| 139 | + //const String HTTP_HEAD = "<!DOCTYPE html><html lang=\"en\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/><title>{v}</title>"; |
| 140 | + |
| 141 | + void setupConfigPortal(); |
| 142 | + void startWPS(); |
| 143 | + |
| 144 | + const char* _apName = "no-net"; |
| 145 | + const char* _apPassword = NULL; |
| 146 | + String _ssid = ""; |
| 147 | + String _pass = ""; |
| 148 | + unsigned long _configPortalTimeout = 0; |
| 149 | + unsigned long _connectTimeout = 0; |
| 150 | + unsigned long _configPortalStart = 0; |
| 151 | + |
| 152 | + IPAddress _ap_static_ip; |
| 153 | + IPAddress _ap_static_gw; |
| 154 | + IPAddress _ap_static_sn; |
| 155 | + IPAddress _sta_static_ip; |
| 156 | + IPAddress _sta_static_gw; |
| 157 | + IPAddress _sta_static_sn; |
| 158 | + |
| 159 | + int _paramsCount = 0; |
| 160 | + int _minimumQuality = -1; |
| 161 | + boolean _removeDuplicateAPs = true; |
| 162 | + boolean _shouldBreakAfterConfig = false; |
| 163 | + boolean _tryWPS = false; |
| 164 | + |
| 165 | + const char* _customHeadElement = ""; |
| 166 | + |
| 167 | + //String getEEPROMString(int start, int len); |
| 168 | + //void setEEPROMString(int start, int len, String string); |
| 169 | + |
| 170 | + int status = WL_IDLE_STATUS; |
| 171 | + int connectWifi(String ssid, String pass); |
| 172 | + uint8_t waitForConnectResult(); |
| 173 | + |
| 174 | + void handleRoot(AsyncWebServerRequest *); |
| 175 | + void handleWifi(AsyncWebServerRequest*,boolean scan); |
| 176 | + void handleWifiSave(AsyncWebServerRequest*); |
| 177 | + void handleInfo(AsyncWebServerRequest*); |
| 178 | + void handleReset(AsyncWebServerRequest*); |
| 179 | + void handleNotFound(AsyncWebServerRequest*); |
| 180 | + void handle204(AsyncWebServerRequest*); |
| 181 | + boolean captivePortal(AsyncWebServerRequest*); |
| 182 | + |
| 183 | + // DNS server |
| 184 | + const byte DNS_PORT = 53; |
| 185 | + |
| 186 | + //helpers |
| 187 | + int getRSSIasQuality(int RSSI); |
| 188 | + boolean isIp(String str); |
| 189 | + String toStringIp(IPAddress ip); |
| 190 | + |
| 191 | + boolean connect; |
| 192 | + boolean _debug = true; |
| 193 | + |
| 194 | + WiFiResult *wifiSSIDs; |
| 195 | + int wifiSSIDCount; |
| 196 | + boolean wifiSSIDscan; |
| 197 | + |
| 198 | + void (*_apcallback)(AsyncWiFiManager*) = NULL; |
| 199 | + void (*_savecallback)(void) = NULL; |
| 200 | + |
| 201 | + AsyncWiFiManagerParameter* _params[WIFI_MANAGER_MAX_PARAMS]; |
| 202 | + |
| 203 | + template <typename Generic> |
| 204 | + void DEBUG_WM(Generic text); |
| 205 | + |
| 206 | + template <class T> |
| 207 | + auto optionalIPFromString(T *obj, const char *s) -> decltype( obj->fromString(s) ) { |
| 208 | + return obj->fromString(s); |
| 209 | + } |
| 210 | + auto optionalIPFromString(...) -> bool { |
| 211 | + DEBUG_WM("NO fromString METHOD ON IPAddress, you need ESP8266 core 2.1.0 or newer for Custom IP configuration to work."); |
| 212 | + return false; |
| 213 | + } |
| 214 | +}; |
| 215 | + |
| 216 | +#endif |
0 commit comments