Files
WiFiManager/WiFiManager.h
T
Chris Marrin 174bb615e6 Changed setAPCallback and setSaveConfigCallback to take std::function params
This allows Predicates and Lambdas to be passed. Still allows bare function pointers
so this patch is fully backward compatible. Tested on WiFiManager examples for
backward compatibility and on my own project (OfficeClock) for handling lambdas with
captured variables
2018-04-07 09:13:48 -07:00

435 lines
17 KiB
C++

/**
* WiFiManager.h
*
* WiFiManager, a library for the ESP8266/Arduino platform
* for configuration of WiFi credentials using a Captive Portal
*
* @author Creator tzapu
* @author tablatronix
* @version 0.0.0
* @license MIT
*/
#ifndef WiFiManager_h
#define WiFiManager_h
#include <vector>
// #define WM_MDNS // also set MDNS with sethostname
// #define WM_FIXERASECONFIG // use erase flash fix
// #define WM_ERASE_NVS // esp32 erase(true) will erase NVS
// #define WM_RTC // esp32 info page will include reset reasons
// #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.
#define WM_WEBSERVERSHIM // use webserver shim lib
#ifdef ESP8266
extern "C" {
#include "user_interface.h"
}
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#ifdef WM_MDNS
#include <ESP8266mDNS.h>
#endif
#define WIFI_getChipId() ESP.getChipId()
#define WM_WIFIOPEN ENC_TYPE_NONE
#elif defined(ESP32)
#include <WiFi.h>
#include <esp_wifi.h>
#define WIFI_getChipId() (uint32_t)ESP.getEfuseMac()
#define WM_WIFIOPEN WIFI_AUTH_OPEN
#ifndef WEBSERVER_H
#warning "WEBSERVER not implemented in espressif/esp32, see readme notes"
#ifdef WM_WEBSERVERSHIM
#include <WebServer.h>
#else
#include <ESP8266WebServer.h>
// Forthcoming official
// https://github.com/esp8266/ESPWebServer
#endif
#endif
#ifdef WM_ERASE_NVS
#include <nvs.h>
#include <nvs_flash.h>
#endif
#ifdef WM_MDNS
#include <ESPmDNS.h>
#endif
#ifdef WM_RTC
#include <rom/rtc.h>
#endif
#else
#endif
#include <DNSServer.h>
#include <memory>
#include "strings_en.h"
#ifndef WIFI_MANAGER_MAX_PARAMS
#define WIFI_MANAGER_MAX_PARAMS 5 // params will autoincrement and realloc by this amount when max is reached
#endif
#define WFM_LABEL_BEFORE 1
#define WFM_LABEL_AFTER 2
#define WFM_NO_LABEL 0
class WiFiManagerParameter {
public:
/**
Create custom parameters that can be added to the WiFiManager setup web page
@id is used for HTTP queries and must not contain spaces nor other special characters
*/
WiFiManagerParameter(const char *custom);
WiFiManagerParameter(const char *id, const char *placeholder);
WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length);
WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom);
WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom, int labelPlacement);
~WiFiManagerParameter();
const char *getID();
const char *getValue();
const char *getPlaceholder();
int getValueLength();
int getLabelPlacement();
const char *getCustomHTML();
void setValue(const char *defaultValue, int length);
private:
const char *_id;
const char *_placeholder;
char *_value;
int _length;
int _labelPlacement;
const char *_customHTML;
void init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom);
void init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom, int labelPlacement);
friend class WiFiManager;
};
class WiFiManager
{
public:
WiFiManager(Stream& consolePort);
WiFiManager();
~WiFiManager();
void WiFiManagerInit();
// auto connect to saved wifi, or custom, and start config portal on failures
boolean autoConnect();
boolean autoConnect(char const *apName, char const *apPassword = NULL);
//manually start the config portal, autoconnect does this automatically on connect failure
boolean startConfigPortal(); // auto generates apname
boolean startConfigPortal(char const *apName, char const *apPassword = NULL);
//manually start the web portal, autoconnect does this automatically on connect failure
void startWebPortal();
//manually stop the web portal if started manually
void stopWebPortal();
// Run webserver processing, if setConfigPortalBlocking(false)
boolean process();
// get the AP name of the config portal, so it can be used in the callback
String getConfigPortalSSID();
// erase wifi credentials
void resetSettings();
// reboot esp
void reboot();
// disconnect wifi, without persistent saving or erasing
bool disconnect();
// erase esp
bool erase();
bool erase(bool opt);
//sets timeout before AP,webserver loop ends and exits even if there has been no setup.
//useful for devices that failed to connect at some point and got stuck in a webserver loop
//in seconds setConfigPortalTimeout is a new name for setTimeout
void setConfigPortalTimeout(unsigned long seconds);
void setTimeout(unsigned long seconds); // @deprecated, alias
//sets timeout for which to attempt connecting, useful if you get a lot of failed connects
void setConnectTimeout(unsigned long seconds);
// toggle debug output
void setDebugOutput(boolean debug);
//defaults to not showing anything under 8% signal quality if called
void setMinimumSignalQuality(int quality = 8);
//sets a custom ip /gateway /subnet configuration
void setAPStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn);
//sets config for a static IP
void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn);
//sets config for a static IP with DNS
void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn, IPAddress dns);
//called when AP mode and config portal is started
void setAPCallback( std::function<void(WiFiManager*)> func );
//called when settings have been changed and connection was successful
void setSaveConfigCallback( std::function<void()> func );
//adds a custom parameter, returns false on failure
bool addParameter(WiFiManagerParameter *p);
//if this is set, it will exit after config, even if connection is unsuccessful.
void setBreakAfterConfig(boolean shouldBreak);
//if this is set, portal will be blocking and wait until save or exit, is false user must manually `process()` to handle config portal
void setConfigPortalBlocking(boolean shouldBlock);
//if this is set, customise style
void setCustomHeadElement(const char* element);
//if this is true, remove duplicated Access Points - defaut true
void setRemoveDuplicateAPs(boolean removeDuplicates);
//setter for ESP wifi.persistent so we can remember it and restore user preference, as WIFi._persistent is protected
void setRestorePersistent(boolean persistent);
//if true, always show static net inputs, IP, subnet, gateway, else only show if set via setSTAStaticIPConfig
void setShowStaticFields(boolean alwaysShow);
//if true, always show static dns, esle only show if set via setSTAStaticIPConfig
void setShowDnsFields(boolean alwaysShow);
//if false, disable captive portal redirection
void setCaptivePortalEnable(boolean enabled);
//if false, timeout captive portal even if a STA client connected (false), suggest disabling if captiveportal is open
void setCaptivePortalClientCheck(boolean enabled);
//if true, reset timeout when webclient connects (true), suggest disabling if captiveportal is open
void setWebPortalClientCheck(boolean enabled);
// if true, enable autoreconnecting
void setWiFiAutoReconnect(boolean enabled);
// if true, wifiscan will show percentage instead of quality icons, until we have better templating
void setScanDispPerc(boolean enabled);
// if true (default) then start the config portal from autoConnect if connection failed
void setEnableConfigPortal(boolean enable);
// set a custom hostname, sets sta and ap dhcp client id for esp32, and sta for esp8266
bool setHostname(const char * hostname);
// show erase wifi onfig button on info page, true
void setShowInfoErase(boolean enabled);
// set custom menu
// set custom menu items and order
void setMenu(std::vector<const char*>& menu);
void setMenu(const char* menu[], uint8_t size);
// get last connection result, includes autoconnect and wifisave
uint8_t getLastConxResult();
// get a status as string
String getWLStatusString(uint8_t status);
String getModeString(uint8_t mode);
// check if the module has a saved ap to connect to
bool getWiFiIsSaved();
// debug output the softap config
void debugSoftAPConfig();
// debug output platform info and versioning
void debugPlatformInfo();
String htmlEntities(String str);
private:
std::unique_ptr<DNSServer> dnsServer;
#if defined(ESP32) && defined(WM_WEBSERVERSHIM)
using WM_WebServer = WebServer;
#else
using WM_WebServer = ESP8266WebServer;
#endif
std::unique_ptr<WM_WebServer> server;
std::vector<uint8_t> _menuIds;
std::vector<const char *> _menuIdsDefault = {"wifi","info","exit"};
// ip configs @todo struct ?
IPAddress _ap_static_ip;
IPAddress _ap_static_gw;
IPAddress _ap_static_sn;
IPAddress _sta_static_ip;
IPAddress _sta_static_gw;
IPAddress _sta_static_sn;
IPAddress _sta_static_dns;
// defaults
const byte DNS_PORT = 53;
const byte HTTP_PORT = 80;
String _apName = "no-net";
String _apPassword = "";
String _ssid = "";
String _pass = "";
// options flags
unsigned long _configPortalTimeout = 0; // ms close config portal loop if set (depending on _cp/webClientCheck options)
unsigned long _connectTimeout = 0; // ms stop trying to connect to ap if set
unsigned long _saveTimeout = 5000; // ms stop trying to connect to ap on saves
unsigned long _configPortalStart = 0; // ms config portal start time (updated for timeouts)
unsigned long _webPortalAccessed = 0; // ms last web access time
WiFiMode_t _usermode = WIFI_OFF;
String _wifissidprefix = FPSTR(S_ssidpre); // auto apname prefix prefix+chipid
uint8_t _lastconxresult = WL_IDLE_STATUS;
int _numNetworks = 0;
unsigned long _lastscan = 0; // ms
int _cpclosedelay = 2000; // delay before wifisave, prevents captive portal from closing to fast.
#ifdef ESP32
static uint8_t _lastconxresulttmp; // tmp var for esp32 callback
#endif
#ifndef WL_STATION_WRONG_PASSWORD
uint8_t WL_STATION_WRONG_PASSWORD = 7; // @kludge define a WL status for wrong password
#endif
// parameter options
int _minimumQuality = -1; // filter wifiscan ap by this rssi
int _staShowStaticFields = 0; // ternary always show static ip fields, only if not set in code, never(cannot change ips via web!)
int _staShowDns = 0; // ternary always show dns, only if not set in code, never(cannot change dns via web!)
boolean _removeDuplicateAPs = true; // remove dup aps from wifiscan
boolean _shouldBreakAfterConfig = false; // stop configportal on save failure
boolean _tryWPS = false; // try WPS on save failure, unsupported
boolean _configPortalIsBlocking = true; // configportal enters blocking loop
boolean _enableCaptivePortal = true; // enable captive portal redirection
boolean _userpersistent = true; // users preffered persistence to restore
boolean _wifiAutoReconnect = true; // there is no platform getter for this, we must assume its true and make it so
boolean _cpClientCheck = false; // keep cp alive if cp have station
boolean _webClientCheck = true; // keep cp alive if web have client
boolean _scanDispOptions = false; // show percentage in scans not icons
boolean _paramsInWifi = true; // show custom parameters on wifi page
boolean _showInfoErase = true; // info page erase button
boolean _enableConfigPortal = true; // use config portal if autoconnect failed
const char * _hostname = "";
const char* _customHeadElement = ""; // store custom head element html from user
// internal options
boolean _preloadwifiscan = true; // preload wifiscan if true
boolean _disableIpFields = false; // edge case, if true, showxFields(false) forces ip fields off instead of default show when set
void setupConfigPortal();
void startWPS();
bool startAP();
uint8_t connectWifi(String ssid, String pass);
bool setSTAConfig();
bool wifiConnectDefault();
bool wifiConnectNew(String ssid, String pass);
uint8_t waitForConnectResult();
uint8_t waitForConnectResult(uint16_t timeout);
void updateConxResult(uint8_t status);
// webserver handlers
void handleRoot();
void handleWifi(boolean scan);
void handleWifiSave();
void handleInfo();
void handleReset();
void handleNotFound();
void handleExit();
void handleClose();
// void handleErase();
void handleErase(boolean opt);
void handleParam();
void handleWiFiStatus();
void handleRequest();
void handleParamSave();
void doParamSave();
boolean captivePortal();
boolean configPortalHasTimeout();
boolean stopConfigPortal();
uint8_t processConfigPortal();
void stopCaptivePortal();
// wifi platform abstractions
bool WiFi_Mode(WiFiMode_t m);
bool WiFi_Mode(WiFiMode_t m,bool persistent);
bool WiFi_Disconnect();
bool WiFi_enableSTA(bool enable);
bool WiFi_enableSTA(bool enable,bool persistent);
bool WiFi_eraseConfig();
uint8_t WiFi_softap_num_stations();
bool WiFi_hasAutoConnect();
void WiFi_autoReconnect();
String WiFi_SSID();
bool WiFi_scanNetworks();
bool WiFi_scanNetworks(bool force);
bool WiFi_scanNetworks(unsigned int cachetime);
#ifdef ESP32
static void WiFiEvent(WiFiEvent_t event, system_event_info_t info);
#endif
// output helpers
String getParamOut();
String getIpForm(String id, String title, String value);
String getScanItemOut();
String getStaticOut();
String getHTTPHead(String title);
String getMenuOut();
//helpers
int getRSSIasQuality(int RSSI);
boolean isIp(String str);
String toStringIp(IPAddress ip);
boolean validApPassword();
String encryptionTypeStr(uint8_t authmode);
void reportStatus(String &page);
String getInfoData(String id);
// flags
boolean connect;
boolean abort;
boolean reset = false;
boolean configPortalActive = false;
boolean webPortalActive = false;
boolean portalTimeoutResult = false;
boolean portalAbortResult = false;
boolean storeSTAmode = true; // option store persistent STA mode in connectwifi
int timer = 0;
// WiFiManagerParameter
int _paramsCount = 0;
int _max_params;
WiFiManagerParameter** _params = NULL;
// debugging
typedef enum {
DEBUG_ERROR = 0,
DEBUG_NOTIFY = 1, // default
DEBUG_VERBOSE = 2,
DEBUG_DEV = 3,
DEBUG_MAX = 4
} wm_debuglevel_t;
boolean _debug = true;
uint8_t _debugLevel = DEBUG_VERBOSE;
Stream& _debugPort; // debug output stream ref
template <typename Generic>
void DEBUG_WM(Generic text);
template <typename Generic>
void DEBUG_WM(wm_debuglevel_t level,Generic text);
template <typename Generic, typename Genericb>
void DEBUG_WM(Generic text,Genericb textb);
template <typename Generic, typename Genericb>
void DEBUG_WM(wm_debuglevel_t level, Generic text,Genericb textb);
// callbacks
std::function<void(WiFiManager*)> _apcallback;
std::function<void()> _savecallback;
template <class T>
auto optionalIPFromString(T *obj, const char *s) -> decltype( obj->fromString(s) ) {
return obj->fromString(s);
}
auto optionalIPFromString(...) -> bool {
// DEBUG_WM("NO fromString METHOD ON IPAddress, you need ESP8266 core 2.1.0 or newer for Custom IP configuration to work.");
return false;
}
};
#endif