/** * Declaration of AutoConnect class and accompanying AutoConnectConfig class. * @file AutoConnect.h * @author hieromon@gmail.com * @version 0.9.1 * @date 2018-02-13 * @copyright MIT license. */ #ifndef _AUTOCONNECT_H_ #define _AUTOCONNECT_H_ #include #include #include #include #include #include #include #include extern "C" { #include } #include "AutoConnectPage.h" // Uncomment the following AC_DEBUG to enable debug output. //#define AC_DEBUG // Debug output destination can be defined externally with AC_DEBUG_PORT #ifndef AC_DEBUG_PORT #define AC_DEBUG_PORT Serial #endif #ifdef AC_DEBUG #define AC_DBG(...) do {AC_DEBUG_PORT.print("[AC] "); AC_DEBUG_PORT.printf( __VA_ARGS__ );} while (0) #else #define AC_DBG(...) #endif #ifndef AUTOCONNECT_APID #define AUTOCONNECT_APID "esp8266ap" #endif #ifndef AUTOCONNECT_PSK #define AUTOCONNECT_PSK "12345678" #endif #ifndef AUTOCONNECT_AP_IP #define AUTOCONNECT_AP_IP 0x01F4A8C0 //*< 192.168.244.1 */ #endif // !AUTOCONNECT_AP_IP #ifndef AUTOCONNECT_AP_GW #define AUTOCONNECT_AP_GW 0x01F4A8C0 //*< 192.168.244.1 */ #endif // !AUTOCONNECT_AP_GW #ifndef AUTOCONNECT_AP_NM #define AUTOCONNECT_AP_NM 0x00FFFFFF //*< 255.255.255.0 */ #endif // !AUTOCONNECT_AP_NM #ifndef AUTOCONNECT_URI #define AUTOCONNECT_URI "/_ac" #endif #ifndef AUTOCONNECT_HOMEURI #define AUTOCONNECT_HOMEURI "/" #endif #ifndef AUTOCONNECT_MENU_TITLE #define AUTOCONNECT_MENU_TITLE "AutoConnect" #endif #define AUTOCONNECT_MENU_TITLE_CONNETED "Connected" #define AUTOCONNECT_URI_CONFIG AUTOCONNECT_URI "/config" #define AUTOCONNECT_URI_CONNECT AUTOCONNECT_URI "/connect" #define AUTOCONNECT_URI_RESULT AUTOCONNECT_URI "/result" #define AUTOCONNECT_URI_OPEN AUTOCONNECT_URI "/open" #define AUTOCONNECT_URI_DISCON AUTOCONNECT_URI "/disc" #define AUTOCONNECT_URI_RESET AUTOCONNECT_URI "/reset" #define AUTOCONNECT_URI_SUCCESS AUTOCONNECT_URI "/success" #define AUTOCONNECT_URI_FAIL AUTOCONNECT_URI "/fail" #ifndef AUTOCONNECT_TIMEOUT #define AUTOCONNECT_TIMEOUT 30000 #endif #ifndef AUTOCONNECT_STARTUPTIME #define AUTOCONNECT_STARTUPTIME 10 #endif #ifndef AUTOCONNECT_DNSPORT #define AUTOCONNECT_DNSPORT 53 #endif /**< A type to save established credential at WiFi.begin automatically. */ typedef enum AC_SAVECREDENTIAL { AC_SAVECREDENTIAL_NEVER, AC_SAVECREDENTIAL_AUTO } AC_SAVECREDENTIAL_t; class AutoConnectConfig { public: /** * AutoConnectConfig default constructor. * SSID for the captive portal access point assumes AUTOCONNECT_APID which * assigned from macro. Password is same as above too. */ AutoConnectConfig() : apip(AUTOCONNECT_AP_IP), gateway(AUTOCONNECT_AP_GW), netmask(AUTOCONNECT_AP_NM), apid(String(AUTOCONNECT_APID)), psk(String(AUTOCONNECT_PSK)), channel(1), hidden(0), autoSave(AC_SAVECREDENTIAL_AUTO), autoReset(true), uptime(AUTOCONNECT_STARTUPTIME), homeUri(AUTOCONNECT_HOMEURI) {} /** * Configure by SSID for the captive portal access point and password. */ AutoConnectConfig(const char* ap, const char* password) : apip(AUTOCONNECT_AP_IP), gateway(AUTOCONNECT_AP_GW), netmask(AUTOCONNECT_AP_NM), apid(String(ap)), psk(String(password)), channel(1), hidden(0), autoSave(AC_SAVECREDENTIAL_AUTO), autoReset(true), uptime(AUTOCONNECT_STARTUPTIME), homeUri(AUTOCONNECT_HOMEURI) {} ~AutoConnectConfig() {} AutoConnectConfig& operator=(const AutoConnectConfig& o) { apip = o.apip; gateway = o.gateway; netmask = o.netmask; apid = o.apid; psk = o.psk; channel = o.channel; hidden = o.hidden; autoSave = o.autoSave; autoReset = o.autoReset; uptime = o.uptime; homeUri = o.homeUri; return *this; } IPAddress apip; /**< SoftAP IP address */ IPAddress gateway; /**< SoftAP gateway address */ IPAddress netmask; /**< SoftAP subnet mask */ String apid; /**< SoftAP SSID */ String psk; /**< SoftAP password */ uint8_t channel; /**< SoftAP used wifi channel */ uint8_t hidden; /**< SoftAP SSID hidden */ AC_SAVECREDENTIAL_t autoSave; /**< Auto save credential */ bool autoReset; /**< Reset ESP8266 module automatically when WLAN disconnected. */ int uptime; /**< Length of start up time */ String homeUri; /**< A URI of user site */ }; class AutoConnect { public: AutoConnect(); AutoConnect(ESP8266WebServer& webServer); ~AutoConnect(); bool config(AutoConnectConfig& Config); bool config(const char* ap, const char* password = nullptr); void home(String uri); bool begin(); bool begin(const char* ssid, const char* passphrase); bool begin(const char* ssid, const char* passphrase, unsigned long timeout); void end(); void handleClient(); void handleRequest(); ESP8266WebServer& host(); typedef std::function DetectExit_ft; void onDetect(DetectExit_ft fn); void onNotFound(ESP8266WebServer::THandlerFunction fn); protected: enum _webServerAllocateType { AC_WEBSERVER_PARASITIC, AC_WEBSERVER_HOSTED }; typedef enum _webServerAllocateType AC_WEBSERVER_TYPE; void _initialize(); bool _config(); void _startWebServer(); void _startDNSServer(); void _handleNotFound(); void _stopPortal(); bool _classifyHandle(HTTPMethod mothod, String uri); PageElement* _setupPage(String uri); /** Request handlers implemented by Page Builder */ String _induceConnect(PageArgument& args); String _induceDisconnect(PageArgument& args); String _induceReset(PageArgument& args); String _invokeResult(PageArgument& args); /** For portal control */ bool _captivePortal(); bool _isIP(String ipStr); wl_status_t _waitForConnect(unsigned long timeout); /** Utilities */ static String _toMACAddressString(const uint8_t mac[]); static unsigned int _toWiFiQuality(int32_t rssi); DetectExit_ft _onDetectExit; ESP8266WebServer::THandlerFunction _notFoundHandler; std::unique_ptr _webServer; std::unique_ptr _dnsServer; AC_WEBSERVER_TYPE _webServerAlloc; PageBuilder* _responsePage; PageElement* _currentPageElement; /** configurations */ AutoConnectConfig _apConfig; struct station_config _credential; uint8_t _hiddenSSIDCount; unsigned long _portalTimeout; /** The control indicators */ bool _rfConnect; /**< URI /connect requested */ bool _rfDisconnect; /**< URI /disc requested */ bool _rfReset; /**< URI /reset requested */ String _uri; String _redirectURI; IPAddress _currentHostIP; String _menuTitle; /** PegeElements of AutoConnect site. */ static const char _CSS_BASE[] PROGMEM; static const char _CSS_UL[] PROGMEM; static const char _CSS_ICON_LOCK[] PROGMEM; static const char _CSS_INPUT_BUTTON[] PROGMEM; static const char _CSS_INPUT_TEXT[] PROGMEM; static const char _CSS_TABLE[] PROGMEM; static const char _CSS_LUXBAR[] PROGMEM; static const char _ELM_HTML_HEAD[] PROGMEM; static const char _ELM_MENU[] PROGMEM; static const char _PAGE_STAT[] PROGMEM; static const char _PAGE_CONFIGNEW[] PROGMEM; static const char _PAGE_OPENCREDT[] PROGMEM; static const char _PAGE_SUCCESS[] PROGMEM; static const char _PAGE_RESETTING[] PROGMEM; static const char _PAGE_DISCONN[] PROGMEM; static const char _PAGE_FAIL[] PROGMEM; static const char _PAGE_404[] PROGMEM; /** Token handlers for PageBuilder */ String _token_CSS_BASE(PageArgument& args); String _token_CSS_UL(PageArgument& args); String _token_CSS_ICON_LOCK(PageArgument& args); String _token_CSS_INPUT_BUTTON(PageArgument& args); String _token_CSS_INPUT_TEXT(PageArgument& args); String _token_CSS_TABLE(PageArgument& args); String _token_CSS_LUXBAR(PageArgument& args); String _token_HEAD(PageArgument& args); String _token_MENU(PageArgument& args); String _token_ESTAB_SSID(PageArgument& args); String _token_WIFI_MODE(PageArgument& args); String _token_WIFI_STATUS(PageArgument& args); String _token_STATION_STATUS(PageArgument& args); String _token_LOCAL_IP(PageArgument& args); String _token_SOFTAP_IP(PageArgument& args); String _token_GATEWAY(PageArgument& args); String _token_NETMASK(PageArgument& args); String _token_AP_MAC(PageArgument& args); String _token_STA_MAC(PageArgument& args); String _token_CHANNEL(PageArgument& args); String _token_DBM(PageArgument& args); String _token_CPU_FREQ(PageArgument& args); String _token_FLASH_SIZE(PageArgument& args); String _token_CHIP_ID(PageArgument& args); String _token_FREE_HEAP(PageArgument& args); String _token_LIST_SSID(PageArgument& args); String _token_HIDDEN_COUNT(PageArgument& args); String _token_OPEN_SSID(PageArgument& args); String _token_UPTIME(PageArgument& args); friend class ESP8266WebServer; }; #endif // _AUTOCONNECT_H_