Commit 80a71660 authored by Eric Duminil's avatar Eric Duminil
Browse files

Trying to add autoconnect libraries

parent a5807d86
This diff is collapsed.
/**
* Declaration of AutoConnect class and accompanying AutoConnectConfig class.
* @file AutoConnect.h
* @author hieromon@gmail.com
* @version 1.2.0
* @date 2020-11-15
* @copyright MIT license.
*/
#ifndef _AUTOCONNECT_H_
#define _AUTOCONNECT_H_
#include <vector>
#include <memory>
#include <functional>
#include <DNSServer.h>
#if defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
extern "C" {
#include <user_interface.h>
}
using WebServerClass = ESP8266WebServer;
#elif defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h>
#include <WebServer.h>
using WebServerClass = WebServer;
#endif
#include <EEPROM.h>
#include <PageBuilder.h>
#include "AutoConnectDefs.h"
#include "AutoConnectPage.h"
#include "AutoConnectCredential.h"
#include "AutoConnectTicker.h"
#include "AutoConnectAux.h"
#include "AutoConnectTypes.h"
// The realization of AutoConnectOTA is effective only by the explicit
#include "AutoConnectOTA.h"
class AutoConnectOTA; // Reference to avoid circular
// The realization of AutoConnectUpdate is effective only by the explicit
// definition of AUTOCONNECT_USE_UPDATE
#include "AutoConnectUpdate.h"
class AutoConnectUpdate; // Reference to avoid circular
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(F(AUTOCONNECT_APID))),
psk(String(F(AUTOCONNECT_PSK))),
channel(AUTOCONNECT_AP_CH),
hidden(0),
minRSSI(AUTOCONNECT_MIN_RSSI),
autoSave(AC_SAVECREDENTIAL_AUTO),
bootUri(AC_ONBOOTURI_ROOT),
principle(AC_PRINCIPLE_RECENT),
boundaryOffset(AC_IDENTIFIER_OFFSET),
uptime(AUTOCONNECT_STARTUPTIME),
autoRise(true),
autoReset(true),
autoReconnect(false),
immediateStart(false),
retainPortal(false),
preserveAPMode(false),
beginTimeout(AUTOCONNECT_TIMEOUT),
portalTimeout(AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT),
menuItems(AC_MENUITEM_CONFIGNEW | AC_MENUITEM_OPENSSIDS | AC_MENUITEM_DISCONNECT | AC_MENUITEM_RESET | AC_MENUITEM_UPDATE | AC_MENUITEM_HOME),
reconnectInterval(0),
ticker(false),
tickerPort(AUTOCONNECT_TICKER_PORT),
tickerOn(LOW),
ota(AC_OTA_EXTRA),
auth(AC_AUTH_NONE),
authScope(AC_AUTHSCOPE_AUX),
username(String("")),
password(String("")),
hostName(String("")),
homeUri(AUTOCONNECT_HOMEURI),
title(AUTOCONNECT_MENU_TITLE),
staip(0U),
staGateway(0U),
staNetmask(0U),
dns1(0U),
dns2(0U) {}
/**
* Configure by SSID for the captive portal access point and password.
*/
AutoConnectConfig(const char* ap, const char* password, const unsigned long portalTimeout = 0, const uint8_t channel = AUTOCONNECT_AP_CH) :
apip(AUTOCONNECT_AP_IP),
gateway(AUTOCONNECT_AP_GW),
netmask(AUTOCONNECT_AP_NM),
apid(String(ap)),
psk(String(password)),
channel(channel),
hidden(0),
minRSSI(AUTOCONNECT_MIN_RSSI),
autoSave(AC_SAVECREDENTIAL_AUTO),
bootUri(AC_ONBOOTURI_ROOT),
principle(AC_PRINCIPLE_RECENT),
boundaryOffset(AC_IDENTIFIER_OFFSET),
uptime(AUTOCONNECT_STARTUPTIME),
autoRise(true),
autoReset(true),
autoReconnect(false),
immediateStart(false),
retainPortal(false),
preserveAPMode(false),
beginTimeout(AUTOCONNECT_TIMEOUT),
portalTimeout(portalTimeout),
menuItems(AC_MENUITEM_CONFIGNEW | AC_MENUITEM_OPENSSIDS | AC_MENUITEM_DISCONNECT | AC_MENUITEM_RESET | AC_MENUITEM_UPDATE | AC_MENUITEM_HOME),
reconnectInterval(0),
ticker(false),
tickerPort(AUTOCONNECT_TICKER_PORT),
tickerOn(LOW),
ota(AC_OTA_EXTRA),
auth(AC_AUTH_NONE),
authScope(AC_AUTHSCOPE_AUX),
username(String("")),
password(String("")),
hostName(String("")),
homeUri(AUTOCONNECT_HOMEURI),
title(AUTOCONNECT_MENU_TITLE),
staip(0U),
staGateway(0U),
staNetmask(0U),
dns1(0U),
dns2(0U) {}
~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;
minRSSI=o.minRSSI;
autoSave = o.autoSave;
bootUri = o.bootUri;
principle = o.principle;
boundaryOffset = o.boundaryOffset;
uptime = o.uptime;
autoRise = o.autoRise;
autoReset = o.autoReset;
autoReconnect = o.autoReconnect;
immediateStart = o.immediateStart;
retainPortal = o.retainPortal;
preserveAPMode = o.preserveAPMode;
beginTimeout = o.beginTimeout;
portalTimeout = o.portalTimeout;
menuItems = o.menuItems;
reconnectInterval = o.reconnectInterval;
ticker = o.ticker;
tickerPort = o.tickerPort;
tickerOn = o.tickerOn;
ota = o.ota;
auth = o.auth;
authScope = o.authScope;
username = o.username;
password = o.password;
hostName = o.hostName;
homeUri = o.homeUri;
title = o.title;
staip = o.staip;
staGateway = o.staGateway;
staNetmask = o.staNetmask;
dns1 = o.dns1;
dns2 = o.dns2;
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 */
int16_t minRSSI; /**< Lowest WiFi signal strength (RSSI) that can be connected. */
AC_SAVECREDENTIAL_t autoSave; /**< Auto save credential */
AC_ONBOOTURI_t bootUri; /**< An uri invoking after reset */
AC_PRINCIPLE_t principle; /**< WiFi connection principle */
uint16_t boundaryOffset; /**< The save storage offset of EEPROM */
int uptime; /**< Length of start up time */
bool autoRise; /**< Automatic starting the captive portal */
bool autoReset; /**< Reset ESP8266 module automatically when WLAN disconnected. */
bool autoReconnect; /**< Automatic reconnect with past SSID */
bool immediateStart; /**< Skips WiFi.begin(), start portal immediately */
bool retainPortal; /**< Even if the captive portal times out, it maintains the portal state. */
bool preserveAPMode; /**< Keep existing AP WiFi mode if captive portal won't be started. */
unsigned long beginTimeout; /**< Timeout value for WiFi.begin */
unsigned long portalTimeout; /**< Timeout value for stay in the captive portal */
uint16_t menuItems; /**< A compound value of the menu items to be attached */
uint8_t reconnectInterval; /**< Auto-reconnect attempt interval uint */
bool ticker; /**< Drives LED flicker according to WiFi connection status. */
uint8_t tickerPort; /**< GPIO for flicker */
uint8_t tickerOn; /**< A signal for flicker turn on */
AC_OTA_t ota; /**< Attach built-in OTA */
AC_AUTH_t auth; /**< Enable authentication */
uint16_t authScope; /**< Authetication scope */
String username; /**< User name for authentication */
String password; /**< Authentication password */
String hostName; /**< host name */
String homeUri; /**< A URI of user site */
String title; /**< Menu title */
IPAddress staip; /**< Station static IP address */
IPAddress staGateway; /**< Station gateway address */
IPAddress staNetmask; /**< Station subnet mask */
IPAddress dns1; /**< Primary DNS server */
IPAddress dns2; /**< Secondary DNS server */
};
typedef std::vector<std::reference_wrapper<AutoConnectAux>> AutoConnectAuxVT;
class AutoConnect {
public:
AutoConnect();
AutoConnect(WebServerClass& webServer);
virtual ~AutoConnect();
bool begin(void);
bool begin(const char* ssid, const char* passphrase = nullptr, unsigned long timeout = 0);
bool config(AutoConnectConfig& Config);
bool config(const char* ap, const char* password = nullptr);
void end(void);
uint16_t getEEPROMUsedSize(void);
void handleClient(void);
void handleRequest(void);
void home(const String& uri);
WebServerClass& host(void);
String where(void) const { return _auxUri; }
AutoConnectAux* aux(const String& uri) const;
AutoConnectAux* append(const String& uri, const String& title);
AutoConnectAux* append(const String& uri, const String& title, WebServerClass::THandlerFunction handler);
bool detach(const String& uri);
inline void disableMenu(const uint16_t items) { _apConfig.menuItems &= (0xffff ^ items); }
inline void enableMenu(const uint16_t items) { _apConfig.menuItems |= items; }
void join(AutoConnectAux& aux);
void join(AutoConnectAuxVT auxVector);
bool on(const String& uri, const AuxHandlerFunctionT handler, AutoConnectExitOrder_t order = AC_EXIT_AHEAD);
/** For AutoConnectAux described in JSON */
#ifdef AUTOCONNECT_USE_JSON
bool load(PGM_P aux);
bool load(const __FlashStringHelper* aux);
bool load(const String& aux);
bool load(Stream& aux);
#endif // !AUTOCONNECT_USE_JSON
typedef std::function<bool(IPAddress&)> DetectExit_ft;
typedef std::function<void(IPAddress&)> ConnectExit_ft;
typedef std::function<bool(void)> WhileCaptivePortalExit_ft;
void onDetect(DetectExit_ft fn);
void onConnect(ConnectExit_ft fn);
void onNotFound(WebServerClass::THandlerFunction fn);
void whileCaptivePortal(WhileCaptivePortalExit_ft fn);
protected:
typedef enum {
AC_RECONNECT_SET,
AC_RECONNECT_RESET
} AC_STARECONNECT_t;
typedef enum {
AC_SEEKMODE_ANY,
AC_SEEKMODE_NEWONE,
AC_SEEKMODE_CURRENT
} AC_SEEKMODE_t;
void _authentication(bool allow);
void _authentication(bool allow, const HTTPAuthMethod method);
bool _configAP(void);
bool _configSTA(const IPAddress& ip, const IPAddress& gateway, const IPAddress& netmask, const IPAddress& dns1, const IPAddress& dns2);
String _getBootUri(void);
bool _getConfigSTA(station_config_t* config);
bool _loadAvailCredential(const char* ssid, const AC_PRINCIPLE_t principle = AC_PRINCIPLE_RECENT, const bool excludeCurrent = false);
bool _loadCurrentCredential(char* ssid, char* password, const AC_PRINCIPLE_t principle, const bool excludeCurrent);
bool _seekCredential(const AC_PRINCIPLE_t principle, const AC_SEEKMODE_t mode);
void _startWebServer(void);
void _startDNSServer(void);
void _stopDNSServer(void);
void _stopPortal(void);
bool _classifyHandle(HTTPMethod mothod, String uri);
void _handleUpload(const String& requestUri, const HTTPUpload& upload);
void _handleNotFound(void);
void _purgePages(void);
virtual PageElement* _setupPage(String& uri);
#ifdef AUTOCONNECT_USE_JSON
template<typename T>
bool _parseJson(T in);
bool _load(JsonVariant& aux);
#endif // !AUTOCONNECT_USE_JSON
/** 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(void);
bool _hasTimeout(unsigned long timeout);
bool _isIP(String ipStr);
void _softAP(void);
wl_status_t _waitForConnect(unsigned long timeout);
void _waitForEndTransmission(void);
void _disconnectWiFi(bool wifiOff);
void _setReconnect(const AC_STARECONNECT_t order);
/** Utilities */
String _attachMenuItem(const AC_MENUITEM_t item);
static uint32_t _getChipId(void);
static uint32_t _getFlashChipRealSize(void);
static String _toMACAddressString(const uint8_t mac[]);
static unsigned int _toWiFiQuality(int32_t rssi);
ConnectExit_ft _onConnectExit;
DetectExit_ft _onDetectExit;
WhileCaptivePortalExit_ft _whileCaptivePortal;
WebServerClass::THandlerFunction _notFoundHandler;
size_t _freeHeapSize;
/** Servers which works in concert. */
typedef std::unique_ptr<WebServerClass, std::function<void(WebServerClass *)> > WebserverUP;
WebserverUP _webServer = WebserverUP(nullptr, std::default_delete<WebServerClass>());
std::unique_ptr<DNSServer> _dnsServer;
/**
* Dynamically hold one page of AutoConnect menu.
* Every time a GET/POST HTTP request occurs, an AutoConnect
* menu page corresponding to the URI is generated.
*/
std::unique_ptr<PageBuilder> _responsePage;
std::unique_ptr<PageElement> _currentPageElement;
/** Extended pages made up with AutoConnectAux */
AutoConnectAux* _aux = nullptr; /**< A top of registered AutoConnectAux */
String _auxUri; /**< Last accessed AutoConnectAux */
String _prevUri; /**< Previous generated page uri */
/** Available updater, only reset by AutoConnectUpdate::attach is valid */
std::unique_ptr<AutoConnectUpdate> _update;
/** OTA updater */
std::unique_ptr<AutoConnectOTA> _ota;
/** Saved configurations */
AutoConnectConfig _apConfig;
station_config_t _credential;
uint8_t _hiddenSSIDCount;
int16_t _scanCount;
uint8_t _connectCh;
unsigned long _portalAccessPeriod;
unsigned long _attemptPeriod;
/** The control indicators */
bool _rfAdHocBegin = false; /**< Specified with AutoConnect::begin */
bool _rfConnect = false; /**< URI /connect requested */
bool _rfDisconnect = false; /**< URI /disc requested */
bool _rfReset = false; /**< URI /reset requested */
wl_status_t _rsConnect; /**< connection result */
#ifdef ARDUINO_ARCH_ESP32
WiFiEventId_t _disconnectEventId = -1; /**< STA disconnection event handler registered id */
#endif
/** Only available with ticker enabled */
std::unique_ptr<AutoConnectTicker> _ticker;
/** HTTP header information of the currently requested page. */
IPAddress _currentHostIP; /**< host IP address */
String _uri; /**< Requested URI */
String _redirectURI; /**< Redirect destination */
String _menuTitle; /**< Title string of the page */
/** PageElements of AutoConnect site. */
static const char _CSS_BASE[] PROGMEM;
static const char _CSS_LUXBAR[] 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_SPINNER[] PROGMEM;
static const char _ELM_HTML_HEAD[] PROGMEM;
static const char _ELM_MENU_PRE[] PROGMEM;
static const char _ELM_MENU_AUX[] PROGMEM;
static const char _ELM_MENU_POST[] PROGMEM;
static const char _PAGE_STAT[] PROGMEM;
static const char _PAGE_CONFIGNEW[] PROGMEM;
static const char _PAGE_CONNECTING[] 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;
static const struct PageTranserModeST {
const char* uri;
const TransferEncoding_t transMode;
const size_t rSize;
} _pageBuildMode[];
/** Token handlers for PageBuilder */
String _token_CSS_BASE(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_LUXBAR(PageArgument& args);
String _token_CSS_SPINNER(PageArgument& args);
String _token_CSS_TABLE(PageArgument& args);
String _token_CSS_UL(PageArgument& args);
String _token_MENU_AUX(PageArgument& args);
String _token_MENU_POST(PageArgument& args);
String _token_MENU_PRE(PageArgument& args);
String _token_AP_MAC(PageArgument& args);
String _token_BOOTURI(PageArgument& args);
String _token_CHANNEL(PageArgument& args);
String _token_CHIP_ID(PageArgument& args);
String _token_CONFIG_STAIP(PageArgument& args);
String _token_CPU_FREQ(PageArgument& args);
String _token_CURRENT_SSID(PageArgument& args);
String _token_DBM(PageArgument& args);
String _token_ESTAB_SSID(PageArgument& args);
String _token_FLASH_SIZE(PageArgument& args);
String _token_FREE_HEAP(PageArgument& args);
String _token_GATEWAY(PageArgument& args);
String _token_HEAD(PageArgument& args);
String _token_HIDDEN_COUNT(PageArgument& args);
String _token_LIST_SSID(PageArgument& args);
String _token_LOCAL_IP(PageArgument& args);
String _token_NETMASK(PageArgument& args);
String _token_OPEN_SSID(PageArgument& args);
String _token_SOFTAP_IP(PageArgument& args);
String _token_SSID_COUNT(PageArgument& args);
String _token_STA_MAC(PageArgument& args);
String _token_STATION_STATUS(PageArgument& args);
String _token_UPTIME(PageArgument& args);
String _token_WIFI_MODE(PageArgument& args);
String _token_WIFI_STATUS(PageArgument& args);
private:
// The access point collation key is determined at compile time
// according to the AUTOCONNECT_APKEY_SSID definition, which is
inline bool _isValidAP(const station_config_t& config, const uint8_t item) const {
#if defined(AUTOCONNECT_APKEY_SSID)
return !strcmp(reinterpret_cast<const char*>(config.ssid), WiFi.SSID(item).c_str());
#else
return !memcmp(config.bssid, WiFi.BSSID(item), sizeof(station_config_t::bssid));
#endif
}
static const String _emptyString; /**< An empty string allocation **/
#if defined(ARDUINO_ARCH_ESP8266)
friend ESP8266WebServer;
#elif defined(ARDUINO_ARCH_ESP32)
friend class WebServer;
#endif
friend class AutoConnectAux;
friend class AutoConnectUpdate;
};
#endif // _AUTOCONNECT_H_
This diff is collapsed.
/**
* Declaration of AutoConnectAux basic class.
* @file AutoConnectAux.h
* @author hieromon@gmail.com
* @version 1.2.0
* @date 2029-04-17
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTAUX_H_
#define _AUTOCONNECTAUX_H_
#include "AutoConnectDefs.h"
#include <vector>
#include <memory>
#include <functional>
#include <type_traits>
#ifdef AUTOCONNECT_USE_JSON
#include <Stream.h>
#endif // !AUTOCONNECT_USE_JSON
#include <PageBuilder.h>
#include "AutoConnectElement.h"
#include "AutoConnectTypes.h"
class AutoConnect; // Reference to avoid circular
class AutoConnectAux; // Reference to avoid circular
// Manage placed AutoConnectElement with a vector
typedef std::vector<std::reference_wrapper<AutoConnectElement>> AutoConnectElementVT;
// A type of callback function when AutoConnectAux page requested.
typedef std::function<String(AutoConnectAux&, PageArgument&)> AuxHandlerFunctionT;
// A type for the order in which callback functions are called.
typedef enum {
AC_EXIT_AHEAD = 1, /**< Callback before building HTML */
AC_EXIT_LATER = 2, /**< Callback after building HTML */
AC_EXIT_BOTH = 3 /**< Callback twice before and after building HTML */
} AutoConnectExitOrder_t;
/**
* A class that handles an auxiliary page with AutoConnectElement
* that placed on it by binding it to the AutoConnect menu.
* @param uri An uri string of this page.
* @param title A title string of this page.
* @param addons A set of AutoConnectElement vector.
* @param menu A switch for item displaying in AutoConnect menu.
*/
class AutoConnectAux : public PageBuilder {
public:
explicit AutoConnectAux(const String& uri = String(""), const String& title = String(""), const bool menu = true, const AutoConnectElementVT addons = AutoConnectElementVT()) :
chunk(PB_Chunk), _title(title), _menu(menu), _uriStr(String(uri)), _addonElm(addons), _handler(nullptr), _order(AC_EXIT_AHEAD), _uploadHandler(nullptr) { _uri = _uriStr.c_str(); }
~AutoConnectAux();
AutoConnectElement& operator[](const String& name) { return *getElement(name); }
void add(AutoConnectElement& addon); /**< Add an element to the auxiliary page */
void add(AutoConnectElementVT addons); /**< Add the element set to the auxiliary page */
void authentication(const AC_AUTH_t auth) { _httpAuth = auth; } /**< Set certain page authentication */
void fetchElement(void); /**< Fetch AutoConnectElements values from http query parameters */
template<typename T>
T& getElement(const String& name);
AutoConnectElement* getElement(const String& name); /**< Get registered AutoConnectElement as specified name */
AutoConnectElementVT& getElements(void) { return _addonElm; } /**< Get vector of all elements */
void menu(const bool post) { _menu = post; } /**< Set or reset the display as menu item for this aux */
bool isMenu(void) { return _menu; } /**< Return whether embedded in the menu or not */
bool isValid(void) const; /**< Validate all AutoConnectInput value */
bool release(const String& name); /**< Release an AutoConnectElement */
bool setElementValue(const String& name, const String value); /**< Set value to specified element */
bool setElementValue(const String& name, std::vector<String> const& values); /**< Set values collection to specified element */
void setTitle(const String& title) { _title = title; } /**< Set a title of the auxiliary page */
void on(const AuxHandlerFunctionT handler, const AutoConnectExitOrder_t order = AC_EXIT_AHEAD) { _handler = handler; _order = order; } /**< Set user handler */
void onUpload(PageBuilder::UploadFuncT uploadFunc) override { _uploadHandler = uploadFunc; }
template<typename T>
void onUpload(T& uploadClass) {
static_assert(std::is_base_of<AutoConnectUploadHandler, T>::value, "onUpload type must be inherited AutoConnectUploadHandler");
_uploadHandler = std::bind(&T::upload, &uploadClass, std::placeholders::_1, std::placeholders::_2);
}
#ifdef AUTOCONNECT_USE_JSON
bool load(PGM_P in); /**< Load whole elements to AutoConnectAux Page */
bool load(const __FlashStringHelper* in); /**< Load whole elements to AutoConnectAux Page */
bool load(const String& in); /**< Load whole elements to AutoConnectAux Page */
bool load(Stream& in); /**< Load whole elements to AutoConnectAux Page */
bool loadElement(PGM_P in, const String& name = String("")); /**< Load specified element */
bool loadElement(PGM_P in, std::vector<String> const& names); /**< Load any specified elements */
bool loadElement(const __FlashStringHelper* in, const String& name = String("")); /**< Load specified element */
bool loadElement(const __FlashStringHelper* in, std::vector<String> const& names); /**< Load any specified elements */
bool loadElement(const String& in, const String& name = String("")); /**< Load specified element */
bool loadElement(const String& in, std::vector<String> const& names);/**< Load any specified elements */
bool loadElement(Stream& in, const String& name = String("")); /**< Load specified element */
bool loadElement(Stream& in, std::vector<String> const& names); /**< Load any specified elements */
size_t saveElement(Stream& out, std::vector<String> const& names = {}); /**< Write elements of AutoConnectAux to the stream */
#endif // !AUTOCONNECT_USE_JSON
TransferEncoding_t chunk; /**< Chunked transfer specified */
protected:
void upload(const String& requestUri, const HTTPUpload& upload); /**< Uploader wrapper */
void _concat(AutoConnectAux& aux); /**< Make up chain of AutoConnectAux */
void _join(AutoConnect& ac); /**< Make a link to AutoConnect */
PageElement* _setupPage(const String& uri); /**< AutoConnectAux page builder */
const String _insertElement(PageArgument& args); /**< Insert a generated HTML to the page built by PageBuilder */
const String _insertStyle(PageArgument& args); /**< Insert CSS style */
const String _injectTitle(PageArgument& args) const { (void)(args); return _title; } /**< Returns title of this page to PageBuilder */
const String _injectMenu(PageArgument& args); /**< Inject menu title of this page to PageBuilder */
const String _indicateUri(PageArgument& args); /**< Inject the uri that caused the request */
const String _indicateEncType(PageArgument& args); /**< Inject the ENCTYPE attribute */
void _storeElements(WebServerClass* webServer); /**< Store element values from contained in request arguments */
static AutoConnectElement& _nullElement(void); /**< A static returning value as invalid */
#ifdef AUTOCONNECT_USE_JSON
template<typename T>
bool _parseJson(T in);
bool _load(JsonObject& in); /**< Load all elements from JSON object */
bool _loadElement(JsonVariant& in, const String& name); /**< Load an element as specified name from JSON object */
bool _loadElement(JsonVariant& in, std::vector<String> const& names); /**< Load any elements as specified name from JSON object */
AutoConnectElement& _loadElement(JsonObject& in, const String& name); /**< Load an element as specified name from JSON object */
AutoConnectElement* _createElement(const JsonObject& json); /**< Create an AutoConnectElement instance from JSON object */
static ACElement_t _asElementType(const String& type); /**< Convert a string of element type to the enumeration value */
/**
* Parse and load a JSON document which declares one of the AutoConnectElement.
* The compiler instantiates this template according to the stored data type that contains the JSON document.
* This template also generates different parsing function calls depending on the ArduinoJson version.
* @param T An object type of the JSON document which must be a passable object to ArduinoJson.
* @param U An instance of a source name to load.
*/
template<typename T, typename U,
typename std::enable_if<std::is_same<U, const String&>::value || std::is_same<U, std::vector<String> const&>::value>::type* = nullptr>
bool _parseElement(T in, U name) {
ArduinoJsonBuffer jsonBuffer(AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE);
JsonVariant jb;
#if ARDUINOJSON_VERSION_MAJOR<=5
jb = jsonBuffer.parse(in);
if (!jb.success()) {
AC_DBG("JSON parse error\n");
return false;
}
#else
DeserializationError err = deserializeJson(jsonBuffer, in);
if (err) {
AC_DBG("Deserialize:%s\n", err.c_str());
return false;
}
jb = jsonBuffer.as<JsonVariant>();
#endif
return _loadElement(jb, name);
}
#endif // !AUTOCONNECT_USE_JSON
String _title; /**< A title of the page */
bool _menu; /**< Switch for menu displaying */
bool _deletable = false; /**< Allow deleting itself. */
AC_AUTH_t _httpAuth = AC_AUTH_NONE; /**< Applying HTTP authentication */
String _uriStr; /**< uri as String */
AutoConnectElementVT _addonElm; /**< A vector set of AutoConnectElements placed on this auxiliary page */
AutoConnectAux* _next = nullptr; /**< Auxiliary pages chain list */
AutoConnect* _ac = nullptr; /**< Hosted AutoConnect instance */
AuxHandlerFunctionT _handler; /**< User sketch callback function when AutoConnectAux page requested. */
AutoConnectExitOrder_t _order; /**< The order in which callback functions are called. */
PageBuilder::UploadFuncT _uploadHandler; /**< The AutoConnectFile corresponding to current upload */
AutoConnectFile* _currentUpload; /**< AutoConnectFile handling the current upload */
static const char _PAGE_AUX[] PROGMEM; /**< Auxiliary page template */
// Protected members can be used from AutoConnect which handles AutoConnectAux pages.
friend class AutoConnect;
};
#endif // !_AUTOCONNECTAUX_H_
/**
* Implementation of template functions of AutoConnect and AutoConnectAux.
* This implementation instantiates completely the void AutoConnectElement
* as each type and also absorbs interface differences due to ArduinoJson
* version differences.
* @file AutoConnectAuxImpl.h
* @author hieromon@gmail.com
* @version 0.9.8
* @date 2019-03-21
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTAUXIMPL_H_
#define _AUTOCONNECTAUXIMPL_H_
#include "AutoConnectDefs.h"
#ifndef AUTOCONNECT_USE_JSON
/**
* Get AutoConnectElementBasis element.
* @param name an element name.
* @return A reference of AutoConnectElement class.
*/
template<>
AutoConnectElementBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
return *(reinterpret_cast<AutoConnectElementBasis*>(elm));
}
return reinterpret_cast<AutoConnectElementBasis&>(_nullElement());
}
/**
* Get AutoConnectButtonBasis element.
* @param name An element name.
* @return A reference of AutoConnectButton class.
*/
template<>
AutoConnectButtonBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Button)
return *(reinterpret_cast<AutoConnectButtonBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectButtonBasis&>(_nullElement());
}
/**
* Get AutoConnectCheckboxBasis element.
* @param name An element name.
* @return A reference of AutoConnectCheckbox class.
*/
template<>
AutoConnectCheckboxBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Checkbox)
return *(reinterpret_cast<AutoConnectCheckboxBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectCheckboxBasis&>(_nullElement());
}
/**
* Get AutoConnectFileBasis element.
* @param name An element name.
* @return A reference of AutoConnectFile class.
*/
template<>
AutoConnectFileBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_File)
return *(reinterpret_cast<AutoConnectFileBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectFileBasis&>(_nullElement());
}
/**
* Get AutoConnectInputBasis element.
* @param name An element name.
* @return A reference of AutoConnectInput class.
*/
template<>
AutoConnectInputBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Input)
return *(reinterpret_cast<AutoConnectInputBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectInputBasis&>(_nullElement());
}
/**
* Get AutoConnectRadioBasis element.
* @param name An element name.
* @return A reference of AutoConnectRadio class.
*/
template<>
AutoConnectRadioBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Radio)
return *(reinterpret_cast<AutoConnectRadioBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectRadioBasis&>(_nullElement());
}
/**
* Get AutoConnectSelectBasis element.
* @param name An element name.
* @return A reference of AutoConnectSelect class.
*/
template<>
AutoConnectSelectBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Select)
return *(reinterpret_cast<AutoConnectSelectBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectSelectBasis&>(_nullElement());
}
/**
* Get AutoConnectStyleBasis element.
* @param name An element name.
* @return A reference of AutoConnectStyle class.
*/
template<>
AutoConnectStyleBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Style)
return *(reinterpret_cast<AutoConnectStyleBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectStyleBasis&>(_nullElement());
}
/**
* Get AutoConnectSubmitBasis element.
* @param name An element name.
* @return A reference of AutoConnectSubmit class.
*/
template<>
AutoConnectSubmitBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Submit)
return *(reinterpret_cast<AutoConnectSubmitBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectSubmitBasis&>(_nullElement());
}
/**
* Get AutoConnectTextBasis element.
* @param name An element name.
* @return A reference of AutoConnectText class.
*/
template<>
AutoConnectTextBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Text)
return *(reinterpret_cast<AutoConnectTextBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectTextBasis&>(_nullElement());
}
#else
/**
* Parse and load a JSON document which marks up multiple custom web
* pages. The compiler instantiates this template according to the stored
* data type that contains the JSON document.
* This template also generates different parsing function calls
* depending on the ArduinoJson version.
* @param T An object type of the JSON document which must be a
* passable object to ArduinoJson.
* @param in An instance of a source JSON document to load.
*/
template<typename T>
bool AutoConnect::_parseJson(T in) {
ArduinoJsonBuffer jsonBuffer(AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE);
JsonVariant jv;
#if ARDUINOJSON_VERSION_MAJOR<=5
jv = jsonBuffer.parse(in);
if (!jv.success()) {
AC_DBG("JSON parse error\n");
return false;
}
#else
DeserializationError err = deserializeJson(jsonBuffer, in);
if (err) {
AC_DBG("Deserialize error:%s\n", err.c_str());
return false;
}
jv = jsonBuffer.as<JsonVariant>();
#endif
return _load(jv);
}
/**
* Parse and load a JSON document which marks up a custom web page.
* The compiler instantiates this template according to the stored data
* type that contains the JSON document.
* This template also generates different parsing function calls
* depending on the ArduinoJson version.
* @param T An object type of the JSON document which must be a
* passable object to ArduinoJson.
* @param in An instance of a source JSON document to load.
*/
template<typename T>
bool AutoConnectAux::_parseJson(T in) {
ArduinoJsonBuffer jsonBuffer(AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE);
#if ARDUINOJSON_VERSION_MAJOR<=5
JsonObject& jb = jsonBuffer.parseObject(in);
if (!jb.success()) {
AC_DBG("JSON parse error\n");
return false;
}
#else
DeserializationError err = deserializeJson(jsonBuffer, in);
if (err) {
AC_DBG("Deserialize:%s\n", err.c_str());
return false;
}
JsonObject jb = jsonBuffer.as<JsonObject>();
#endif
return _load(jb);
}
/**
* Get AutoConnectElementJson element.
* @param name an element name.
* @return A reference of AutoConnectElement class.
*/
template<>
AutoConnectElementJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
return *(reinterpret_cast<AutoConnectElementJson*>(elm));
}
return reinterpret_cast<AutoConnectElementJson&>(_nullElement());
}
/**
* Get AutoConnectButtonJson element.
* @param name An element name.
* @return A reference of AutoConnectButton class.
*/
template<>
AutoConnectButtonJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Button)
return *(reinterpret_cast<AutoConnectButtonJson*>(elm));
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectButtonJson&>(_nullElement());
}
/**
* Get AutoConnectCheckboxJson element.
* @param name An element name.
* @return A reference of AutoConnectCheckbox class.
*/
template<>
AutoConnectCheckboxJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Checkbox)
return *(reinterpret_cast<AutoConnectCheckboxJson*>(elm));
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectCheckboxJson&>(_nullElement());
}
/**
* Get AutoConnectFile element.
* @param name An element name.
* @return A reference of AutoConnectFile class.
*/
template<>
AutoConnectFileJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_File)
return *(reinterpret_cast<AutoConnectFileJson*>(elm));
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectFileJson&>(_nullElement());
}
/**
* Get AutoConnectInputJson element.
* @param name An element name.
* @return A reference of AutoConnectInput class.
*/
template<>
AutoConnectInputJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Input)
return *(reinterpret_cast<AutoConnectInputJson*>(elm));
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectInputJson&>(_nullElement());
}
/**
* Get AutoConnectRadioJson element.
* @param name An element name.
* @return A reference of AutoConnectRadio class.
*/
template<>
AutoConnectRadioJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Radio)
return *(reinterpret_cast<AutoConnectRadioJson*>(elm));
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectRadioJson&>(_nullElement());
}
/**
* Get AutoConnectSelectJson element.
* @param name An element name.
* @return A reference of AutoConnectSelect class.
*/
template<>
AutoConnectSelectJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Select)
return *(reinterpret_cast<AutoConnectSelectJson*>(elm));
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectSelectJson&>(_nullElement());
}
/**
* Get AutoConnectSubmitJson element.
* @param name An element name.
* @return A reference of AutoConnectSubmit class.
*/
template<>
AutoConnectSubmitJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Submit)
return *(reinterpret_cast<AutoConnectSubmitJson*>(elm));
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectSubmitJson&>(_nullElement());
}
/**
* Get AutoConnectTextJson element.
* @param name An element name.
* @return A reference of AutoConnectText class.
*/
template<>
AutoConnectTextJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Text)
return *(reinterpret_cast<AutoConnectTextJson*>(elm));
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectTextJson&>(_nullElement());
}
#endif // !AUTOCONNECT_USE_JSON
#endif // !_AUTOCONNECTAUXIMPL_H_
This diff is collapsed.
/**
* Declaration of AutoConnectCredential class.
* @file AutoConnectCredential.h
* @author hieromon@gmail.com
* @version 1.2.0
* @date 2020-04-22
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTCREDENTIAL_H_
#define _AUTOCONNECTCREDENTIAL_H_
// The AUTOCONNECT_USE_PREFERENCES macro indicates which classes apply
// to the credentials storage structure either EEPROM or Preferences.
// It is a valid indicator only for ESP32.
// Undefine this macro, it maintains backward compatibility by applying
// EEPROM to the credentials storage class in the arduino-esp32 core
// v1.0.2 and earlier.
#define AUTOCONNECT_USE_PREFERENCES
#include <Arduino.h>
#include <memory>
#if defined(ARDUINO_ARCH_ESP8266)
#define AC_CREDENTIAL_PREFERENCES 0
extern "C" {
#include <user_interface.h>
}
#elif defined(ARDUINO_ARCH_ESP32)
#ifdef AUTOCONNECT_USE_PREFERENCES
#define AC_CREDENTIAL_PREFERENCES 1
#else
#define AC_CREDENTIAL_PREFERENCES 0
#endif
#include <esp_wifi.h>
#endif
#include "AutoConnectDefs.h"
/**
* Credential storage area offset specifier in EEPROM.
* By defining AC_IDENTIFIER_OFFSET macro in the user sketch, the credential
* storage area can be shifted in EEPROM.
*/
#ifndef AC_IDENTIFIER_OFFSET
#define AC_IDENTIFIER_OFFSET 0
#endif
/**
* Storage identifier for AutoConnect credentials. It is global constant
* and reserved.
*/
#ifndef AC_IDENTIFIER
#define AC_IDENTIFIER "AC_CREDT"
#endif
typedef enum {
STA_DHCP = 0,
STA_STATIC
} station_config_dhcp;
typedef struct {
uint8_t ssid[32];
uint8_t password[64];
uint8_t bssid[6];
uint8_t dhcp; /**< 0:DHCP, 1:Static IP */
union _config {
uint32_t addr[5];
struct _sta {
uint32_t ip;
uint32_t gateway;
uint32_t netmask;
uint32_t dns1;
uint32_t dns2;
} sta;
} config;
} station_config_t;
class AutoConnectCredentialBase {
public:
explicit AutoConnectCredentialBase() : _entries(0), _containSize(0) {}
virtual ~AutoConnectCredentialBase() {}
virtual uint8_t entries(void) { return _entries; }
virtual uint16_t dataSize(void) const { return sizeof(AC_IDENTIFIER) - 1 + sizeof(uint8_t) + sizeof(uint16_t) + _containSize; }
virtual bool del(const char* ssid) = 0;
virtual int8_t load(const char* ssid, station_config_t* config) = 0;
virtual bool load(int8_t entry, station_config_t* config) = 0;
virtual bool save(const station_config_t* config) = 0;
protected:
virtual void _allocateEntry(void) = 0; /**< Initialize storage for credentials. */
uint8_t _entries; /**< Count of the available entry */
uint16_t _containSize; /**< Container size */
};
#if AC_CREDENTIAL_PREFERENCES == 0
// #pragma message "AutoConnectCredential applies the EEPROM"
#define NO_GLOBAL_EEPROM
#include <EEPROM.h>
/** AutoConnectCredential class using EEPROM for ESP8266 */
class AutoConnectCredential : public AutoConnectCredentialBase {
public:
AutoConnectCredential();
explicit AutoConnectCredential(uint16_t offset);
~AutoConnectCredential();
bool del(const char* ssid) override;
int8_t load(const char* ssid, station_config_t* config) override;
bool load(int8_t entry, station_config_t* config) override;
bool save(const station_config_t* config) override;
protected:
void _allocateEntry(void) override; /**< Initialize storage for credentials. */
private:
void _retrieveEntry(station_config_t* config); /**< Read an available entry. */
int _dp; /**< The current address in EEPROM */
int _ep; /**< The current entry address in EEPROM */
uint16_t _offset; /**< The offset for the saved area of credentials in EEPROM. */
std::unique_ptr<EEPROMClass> _eeprom; /**< shared EEPROM class */
};
#else
// #pragma message "AutoConnectCredential applies the Preferences"
#include <type_traits>
#include <map>
#include <Preferences.h>
#include <nvs.h>
#define AC_CREDENTIAL_NVSNAME AC_IDENTIFIER
#define AC_CREDENTIAL_NVSKEY AC_CREDENTIAL_NVSNAME
/** Declare the member function existence determination */
namespace AutoConnectUtil {
AC_HAS_FUNC(getBytesLength);
}
/** AutoConnectCredential class using Preferences for ESP32 */
class AutoConnectCredential : public AutoConnectCredentialBase {
public:
AutoConnectCredential();
explicit AutoConnectCredential(uint16_t offset);
~AutoConnectCredential();
bool del(const char* ssid) override;
uint8_t entries(void) override;
int8_t load(const char* ssid, station_config_t* config) override;
bool load(int8_t entry, station_config_t* config) override;
bool save(const station_config_t* config) override;
protected:
void _allocateEntry(void) override; /**< Initialize storage for credentials. */
private:
typedef struct {
String password;
uint8_t bssid[6];
uint8_t dhcp; /**< 1:DHCP, 2:Static IP */
uint32_t ip[5];
} AC_CREDTBODY_t; /**< Credential entry */
typedef std::map<String, AC_CREDTBODY_t> AC_CREDT_t;
bool _add(const station_config_t* config); /**< Add an entry */
size_t _commit(void); /**< Write back to the nvs */
bool _del(const char* ssid, const bool commit); /**< Deletes an entry */
uint8_t _import(void); /**< Import from the nvs */
void _obtain(AC_CREDT_t::iterator const& it, station_config_t* config); /**< Obtain an entry from iterator */
template<typename T>
typename std::enable_if<AutoConnectUtil::has_func_getBytesLength<T>::value, size_t>::type _getPrefBytesLength(T* pref, const char* key) {
return pref->getBytesLength(key);
}
template<typename T>
typename std::enable_if<!AutoConnectUtil::has_func_getBytesLength<T>::value, size_t>::type _getPrefBytesLength(T* pref, const char* key) {
AC_UNUSED(pref);
uint32_t handle;
size_t len;
esp_err_t err = nvs_open(AC_CREDENTIAL_NVSNAME, NVS_READONLY, &handle);
if (err)
len = 0;
else {
(void)nvs_get_blob(handle, key, NULL, &len);
nvs_close(handle);
}
return len;
}
AC_CREDT_t _credit; /**< Dictionary to maintain the credentials */
std::unique_ptr<Preferences> _pref; /**< Preferences class instance to access the nvs */
};
#endif
#endif // _AUTOCONNECTCREDENTIAL_H_
/**
* Predefined AutoConnect configuration parameters.
* @file AutoConnectDefs.h
* @author hieromon@gmail.com
* @version 1.2.2
* @date 2020-12-11
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTDEFS_H_
#define _AUTOCONNECTDEFS_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 // !AC_DEBUG_PORT
#ifdef AC_DEBUG
#define AC_DBG_DUMB(fmt, ...) do {AC_DEBUG_PORT.printf_P((PGM_P)PSTR(fmt), ## __VA_ARGS__ );} while (0)
#define AC_DBG(fmt, ...) do {AC_DEBUG_PORT.printf_P((PGM_P)PSTR("[AC] " fmt), ## __VA_ARGS__ );} while (0)
#else
#define AC_DBG(...) do {(void)0;} while(0)
#define AC_DBG_DUMB(...) do {(void)0;} while(0)
#endif // !AC_DEBUG
// Indicator to specify that AutoConnectAux handles elements with JSON.
// Comment out the AUTOCONNECT_USE_JSON macro to detach the ArduinoJson.
#ifndef AUTOCONNECT_NOUSE_JSON
#define AUTOCONNECT_USE_JSON
// Indicator of whether to use the AutoConnectUpdate feature.
#define AUTOCONNECT_USE_UPDATE
#endif
// SPIFFS has deprecated on EP8266 core. This flag indicates that
// the migration to LittleFS has not completed.
//#define AC_USE_SPIFFS
// Deploys SPIFFS usage flag to the global.
#if defined(ARDUINO_ARCH_ESP8266)
#ifdef AC_USE_SPIFFS
#define AUTOCONNECT_USE_SPIFFS
#endif
#elif defined(ARDUINO_ARCH_ESP32)
#define AUTOCONNECT_USE_SPIFFS
#endif
// Whether or not it points to the target access point is determined by
// matching the SSID or BSSID. The default key to collate is BSSID.
// The BSSID is usually fixed to the MAC address unique to its AP,
// but when using some mobile hotspots, the BSSID may change even for
// the same access point.
// If you operate inconvenience in aiming at the access point by BSSID,
// you can change the collation key to SSID by uncommenting the below.
// If the AUTOCONNECT_APKEY_SSID is defined at compile-time, the access
// point will be collated by the SSID.
//#define AUTOCONNECT_APKEY_SSID
// Predefined parameters
// SSID that Captive portal started.
#ifndef AUTOCONNECT_APID
#if defined(ARDUINO_ARCH_ESP8266)
#define AUTOCONNECT_APID "esp8266ap"
#elif defined(ARDUINO_ARCH_ESP32)
#define AUTOCONNECT_APID "esp32ap"
#endif // !ARDUINO_ARCH_ESP8266
#endif // !AUTOCONNECT_APID
// Password that Captive portal started.
#ifndef AUTOCONNECT_PSK
#define AUTOCONNECT_PSK "12345678"
#endif // !AUTOCONNECT_PSK
#ifndef AUTOCONNECT_AP_IP
// #define AUTOCONNECT_AP_IP 0x01F4A8C0 //*< 192.168.244.1 */
#define AUTOCONNECT_AP_IP 0x011CD9AC //*< 172.217.28.1 */
#endif // !AUTOCONNECT_AP_IP
#ifndef AUTOCONNECT_AP_GW
// #define AUTOCONNECT_AP_GW 0x01F4A8C0 //*< 192.168.244.1 */
#define AUTOCONNECT_AP_GW 0x011CD9AC //*< 172.217.28.1 */
#endif // !AUTOCONNECT_AP_GW
#ifndef AUTOCONNECT_AP_NM
#define AUTOCONNECT_AP_NM 0x00FFFFFF //*< 255.255.255.0 */
#endif // !AUTOCONNECT_AP_NM
#ifndef AUTOCONNECT_AP_CH
#define AUTOCONNECT_AP_CH 1
#endif // !AUTOCONNECT_AP_CH
// AutoConnect menu root path
#ifndef AUTOCONNECT_URI
#define AUTOCONNECT_URI "/_ac"
#endif // !AUTOCONNECT_URI
// Root URI of home path prepared by user sketch
#ifndef AUTOCONNECT_HOMEURI
#define AUTOCONNECT_HOMEURI "/"
#endif // !AUTOCONNECT_HOMEURI
// AutoConnectAux form argument name
#ifndef AUTOCONNECT_AUXURI_PARAM
#define AUTOCONNECT_AUXURI_PARAM "_acuri"
#endif // !AUTOCONNECT_AUXURI_PARAM
// AutoConnect menu title
#ifndef AUTOCONNECT_MENU_TITLE
#define AUTOCONNECT_MENU_TITLE "AutoConnect"
#endif // !AUTOCONNECT_MENU_TITLE
// URIs of AutoConnect menu collection
#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"
#define AUTOCONNECT_URI_UPDATE AUTOCONNECT_URI "/update"
#define AUTOCONNECT_URI_UPDATE_ACT AUTOCONNECT_URI "/update_act"
#define AUTOCONNECT_URI_UPDATE_PROGRESS AUTOCONNECT_URI "/update_progress"
#define AUTOCONNECT_URI_UPDATE_RESULT AUTOCONNECT_URI "/update_result"
// Number of seconds in uint time [s]
#ifndef AUTOCONNECT_UNITTIME
#define AUTOCONNECT_UNITTIME 30
#endif
// Time-out limitation when AutoConnect::begin [ms]
#ifndef AUTOCONNECT_TIMEOUT
#define AUTOCONNECT_TIMEOUT 30000
#endif // !AUTOCONNECT_TIMEOUT
// Captive portal timeout value [ms]
#ifndef AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT
#define AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT 0
#endif // !AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT
// Advance wait time [s]
#ifndef AUTOCONNECT_STARTUPTIME
#define AUTOCONNECT_STARTUPTIME (AUTOCONNECT_TIMEOUT/1000)
#endif // !AUTOCONNECT_STARTUPTIME
// Response wait time until requesting a result of connection attempt, uint:[ms]
#ifndef AUTOCONNECT_RESPONSE_WAITTIME
#define AUTOCONNECT_RESPONSE_WAITTIME 2000
#endif // !AUTOCONNECT_RESPONSE_WAITTIME
// Default HTTP port
#ifndef AUTOCONNECT_HTTPPORT
#define AUTOCONNECT_HTTPPORT 80
#endif // !AUTOCONNECT_HTTPPORT
// DNS port
#ifndef AUTOCONNECT_DNSPORT
#define AUTOCONNECT_DNSPORT 53
#endif // !AUTOCONNECT_DNSPORT
// http response transfer method
#ifndef AUTOCONNECT_HTTP_TRANSFER
#define AUTOCONNECT_HTTP_TRANSFER PB_ByteStream
#endif // !AUTOCONNECT_HTTP_TRANSFER
// Reserved buffer size to build content
#ifndef AUTOCONNECT_CONTENTBUFFER_SIZE
#define AUTOCONNECT_CONTENTBUFFER_SIZE (13 * 1024)
#endif // !AUTOCONNECT_CONTENTBUFFER_SIZE
// Number of unit lines in the page that lists available SSIDs
#ifndef AUTOCONNECT_SSIDPAGEUNIT_LINES
#define AUTOCONNECT_SSIDPAGEUNIT_LINES 5
#endif // !AUTOCONNECT_SSIDPAGEUNIT_LINES
// SPI transfer speed for SD [Hz]
#ifndef AUTOCONNECT_SD_SPEED
#define AUTOCONNECT_SD_SPEED 4000000
#endif // !AUTOCONNECT_SD_SPEED
// Flicker signal related factors
// Flicker cycle during AP operation [ms]
#ifndef AUTOCONNECT_FLICKER_PERIODAP
#define AUTOCONNECT_FLICKER_PERIODAP 1000
#endif // !AUTOCONNECT_FLICKER_PERIODAP
// Flicker cycle while WiFi is not connected [ms]
#ifndef AUTOCONNECT_FLICKER_PERIODDC
#define AUTOCONNECT_FLICKER_PERIODDC (AUTOCONNECT_FLICKER_PERIODAP << 1)
#endif // !AUTOCONNECT_FLICKER_PERIODDC
// Flicker pulse width during AP operation (8bit resolution)
#ifndef AUTOCONNECT_FLICKER_WIDTHAP
#define AUTOCONNECT_FLICKER_WIDTHAP 96
#endif // !AUTOCONNECT_FLICKER_WIDTHAP
// Flicker pulse width while WiFi is not connected (8bit resolution)
#ifndef AUTOCONNECT_FLICKER_WIDTHDC
#define AUTOCONNECT_FLICKER_WIDTHDC 16
#endif // !AUTOCONNECT_FLICKER_WIDTHDISCON
// Ticker port
#ifndef AUTOCONNECT_TICKER_PORT
#if defined(BUILTIN_LED) || defined(LED_BUILTIN)
#define AUTOCONNECT_TICKER_PORT LED_BUILTIN
#else // Native pin for the arduino
#define AUTOCONNECT_TICKER_PORT 2
#endif
#endif
// Lowest WiFi signal strength (RSSI) that can be connected.
#ifndef AUTOCONNECT_MIN_RSSI
#define AUTOCONNECT_MIN_RSSI -120 // No limit
#endif // !AUTOCONNECT_MIN_RSSI
// ArduinoJson buffer size
#ifndef AUTOCONNECT_JSONBUFFER_SIZE
#define AUTOCONNECT_JSONBUFFER_SIZE 256
#endif // !AUTOCONNECT_JSONBUFFER_SIZE
#ifndef AUTOCONNECT_JSONDOCUMENT_SIZE
#define AUTOCONNECT_JSONDOCUMENT_SIZE (8 * 1024)
#endif // !AUTOCONNECT_JSONDOCUMENT_SIZE
#ifndef AUTOCONNECT_JSONPSRAM_SIZE
#define AUTOCONNECT_JSONPSRAM_SIZE (16* 1024)
#endif // !AUTOCONNECT_JSONPSRAM_SIZE
// Available HTTP port number for the update
#ifndef AUTOCONNECT_UPDATE_PORT
#define AUTOCONNECT_UPDATE_PORT 8000
#endif // !AUTOCONNECT_UPDATE_PORT
// HTTP client timeout limitation for the update [ms]
#ifndef AUTOCONNECT_UPDATE_TIMEOUT
#define AUTOCONNECT_UPDATE_TIMEOUT 8000
#endif // !AUTOCONNECT_UPDATE_TIMEOUT
// Maximum wait time until transitioning AutoConnectUpdate dialog page [ms]
#ifndef AUTOCONNECT_UPDATE_DURATION
#define AUTOCONNECT_UPDATE_DURATION 180000
#endif // !AUTOCONNECT_UPDATE_DURATION
// Interval time of progress status periodical inquiry [ms]
#ifndef AUTOCONNECT_UPDATE_INTERVAL
#define AUTOCONNECT_UPDATE_INTERVAL 400
#endif // !AUTOCONNECT_UPDATE_INTERVAL
// Wait timer for rebooting after updated
#ifndef AUTOCONNECT_UPDATE_WAITFORREBOOT
#define AUTOCONNECT_UPDATE_WAITFORREBOOT 15000
#endif // !AUTOCONNECT_UPDATE_WAITFORREBOOT
// A signal value that the board dependent LED turns on.
// As a typical example, the ON signal of built-in LED such as the
// NodeMCU is LOW and the HIGH for the NodeMCU-32S as another example.
#ifndef AUTOCONNECT_UPDATE_LEDON
// #define AUTOCONNECT_UPDATE_LEDON HIGH
#define AUTOCONNECT_UPDATE_LEDON LOW
#endif // !AUTOCONNECT_UPDATE_LEDON
// URIs of the behaviors owned by the update server
#ifndef AUTOCONNECT_UPDATE_CATALOG
#define AUTOCONNECT_UPDATE_CATALOG "/_catalog"
#endif // !AUTOCONNECT_UPDATE_CATALOG
#ifndef AUTOCONNECT_UPDATE_DOWNLOAD
#define AUTOCONNECT_UPDATE_DOWNLOAD "/"
#endif // !AUTOCONNECT_UPDATE_DOWNLOAD
#ifndef AUTOCONNECT_UPDATE_CATALOG_JSONBUFFER_SIZE
#define AUTOCONNECT_UPDATE_CATALOG_JSONBUFFER_SIZE 256
#endif // !AUTOCONNECT_UPDATE_CATALOG_JSONBUFFER_SIZE
// HTTP authentication default realm
#ifndef AUTOCONNECT_AUTH_REALM
#define AUTOCONNECT_AUTH_REALM "AUTOCONNECT"
#endif // !AUTOCONNECT_AUTH_REALM
// Flename pattern that AutoConnectOTA considers to be firmware.
// The extension used as the criterion for uploading destination is
// fixed.
// AUTOCONNECT_UPLOAD_ASFIRMWARE_USE_REGEXP allows you to use regular
// expressions with the extension to determine the uploading destination.
#ifndef AUTOCONNECT_UPLOAD_ASFIRMWARE
#ifdef AUTOCONNECT_UPLOAD_ASFIRMWARE_USE_REGEXP
#define AUTOCONNECT_UPLOAD_ASFIRMWARE "^.+\\.bin$"
#else
#define AUTOCONNECT_UPLOAD_ASFIRMWARE ".bin"
#endif
#endif
// Explicitly avoiding unused warning with token handler of PageBuilder
#define AC_UNUSED(expr) do { (void)(expr); } while (0)
// Numeric to string deployment
#define AUTOCONNECT_STRING_DEPLOY(n) _AUTOCONNECT_STRING_DEPLOY(n)
#define _AUTOCONNECT_STRING_DEPLOY(s) #s
// Generates a template that determines whether the class owns the
// specified member function.
// The purpose of this macro is to avoid the use of invalid member
// functions due to differences in the version of the library which
// AutoConnect depends on.
#define AC_HAS_FUNC(func) \
template<typename T> \
struct has_func_##func { \
private: \
typedef char one; \
typedef long two; \
template<typename U> static one test(decltype(&U::func)); \
template<typename U> static two test(...); \
public: \
enum { value = sizeof(test<T>(0)) == sizeof(char) }; \
}
#endif // _AUTOCONNECTDEFS_H_
/**
* Alias declarations for an accessible the AutoConnectElement class.
* @file AutoConnectElement.h
* @author hieromon@gmail.com
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTELEMENT_H_
#define _AUTOCONNECTELEMENT_H_
#include "AutoConnectElementBasis.h"
#ifdef AUTOCONNECT_USE_JSON
#include <ArduinoJson.h>
#include "AutoConnectElementJson.h"
using AutoConnectElement = AutoConnectElementJson;
using AutoConnectButton = AutoConnectButtonJson;
using AutoConnectCheckbox = AutoConnectCheckboxJson;
using AutoConnectFile = AutoConnectFileJson;
using AutoConnectInput = AutoConnectInputJson;
using AutoConnectRadio = AutoConnectRadioJson;
using AutoConnectSelect = AutoConnectSelectJson;
using AutoConnectStyle = AutoConnectStyleJson;
using AutoConnectSubmit = AutoConnectSubmitJson;
using AutoConnectText = AutoConnectTextJson;
#define AUTOCONNECT_JSON_BUFFER_SIZE 256
#else
using AutoConnectElement = AutoConnectElementBasis;
using AutoConnectButton = AutoConnectButtonBasis;
using AutoConnectCheckbox = AutoConnectCheckboxBasis;
using AutoConnectFile = AutoConnectFileBasis;
using AutoConnectInput = AutoConnectInputBasis;
using AutoConnectRadio = AutoConnectRadioBasis;
using AutoConnectSelect = AutoConnectSelectBasis;
using AutoConnectStyle = AutoConnectStyleBasis;
using AutoConnectSubmit = AutoConnectSubmitBasis;
using AutoConnectText = AutoConnectTextBasis;
#endif // !AUTOCONNECT_USE_JSON
/**
* Support declare the AutoConnectElement variable with reducing the
* arguments. These macros declare the AutoConnectElement variable
* with the same name as a "name" argument.
*/
#define ACElement(n, v) AutoConnectElement n(#n, v)
#define ACButton(n, ...) AutoConnectButton n(#n, ##__VA_ARGS__)
#define ACCheckbox(n, ...) AutoConnectCheckbox n(#n, ##__VA_ARGS__)
#define ACFile(n, ...) AutoConnectFile n(#n, ##__VA_ARGS__)
#define ACInput(n, ...) AutoConnectInput n(#n, ##__VA_ARGS__)
#define ACRadio(n, ...) AutoConnectRadio n(#n, ##__VA_ARGS__)
#define ACSelect(n, ...) AutoConnectSelect n(#n, ##__VA_ARGS__)
#define ACSubmit(n, ...) AutoConnectSubmit n(#n, ##__VA_ARGS__)
#define ACStyle(n, ...) AutoConnectStyle n(#n, ##__VA_ARGS__)
#define ACText(n, ...) AutoConnectText n(#n, ##__VA_ARGS__)
#endif // _AUTOCONNECTELEMENT_H_
This diff is collapsed.
This diff is collapsed.
/**
* Wrapping definition to ensure version compatibility of ArduinoJson.
* @file AutoConnectJsonDefs.h
* @author hieromon@gmail.com
* @version 1.0.0
* @date 2019-04-25
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTJSONDEFS_H_
#define _AUTOCONNECTJSONDEFS_H_
#include <ArduinoJson.h>
/**
* Make the Json types and functions consistent with the ArduinoJson
* version. These declarations share the following type definitions:
* - Difference between reference and proxy of JsonObject and JsonArray.
* - Difference of check whether the parsing succeeded or not.
* - The print function name difference.
* - The buffer class difference.
* - When PSRAM present, enables the buffer allocation it with ESP32 and
* supported version.
*/
#if ARDUINOJSON_VERSION_MAJOR<=5
#define ArduinoJsonStaticBuffer StaticJsonBuffer
#define ARDUINOJSON_CREATEOBJECT(doc) doc.createObject()
#define ARDUINOJSON_CREATEARRAY(doc) doc.createArray()
#define ARDUINOJSON_PRETTYPRINT(doc, out) ({ size_t s = doc.prettyPrintTo(out); s; })
#define ARDUINOJSON_PRINT(doc, out) ({ size_t s = doc.printTo(out); s; })
using ArduinoJsonObject = JsonObject&;
using ArduinoJsonArray = JsonArray&;
using ArduinoJsonBuffer = DynamicJsonBuffer;
#define AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE AUTOCONNECT_JSONBUFFER_SIZE
#else
#define ArduinoJsonStaticBuffer StaticJsonDocument
#define ARDUINOJSON_CREATEOBJECT(doc) doc.to<JsonObject>()
#define ARDUINOJSON_CREATEARRAY(doc) doc.to<JsonArray>()
#define ARDUINOJSON_PRETTYPRINT(doc, out) ({ size_t s = serializeJsonPretty(doc, out); s; })
#define ARDUINOJSON_PRINT(doc, out) ({ size_t s = serializeJson(doc, out); s; })
using ArduinoJsonObject = JsonObject;
using ArduinoJsonArray = JsonArray;
#if defined(BOARD_HAS_PSRAM) && ((ARDUINOJSON_VERSION_MAJOR==6 && ARDUINOJSON_VERSION_MINOR>=10) || ARDUINOJSON_VERSION_MAJOR>6)
// JsonDocument is assigned to PSRAM by ArduinoJson's custom allocator.
struct SpiRamAllocatorST {
void* allocate(size_t size) {
uint32_t caps;
if (psramFound())
caps = MALLOC_CAP_SPIRAM;
else {
caps = MALLOC_CAP_8BIT;
AC_DBG("PSRAM not found, JSON buffer allocates to the heap.\n");
}
return heap_caps_malloc(size, caps);
}
void deallocate(void* pointer) {
heap_caps_free(pointer);
}
};
#define AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE AUTOCONNECT_JSONPSRAM_SIZE
using ArduinoJsonBuffer = BasicJsonDocument<SpiRamAllocatorST>;
#else
#define AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE AUTOCONNECT_JSONDOCUMENT_SIZE
using ArduinoJsonBuffer = DynamicJsonDocument;
#endif
#endif
#endif // _AUTOCONNECTJSONDEFS_H_
This diff is collapsed.
This diff is collapsed.
/**
* Declaration of AutoConnectOTA class.
* The AutoConnecOTA class is a class for web updating a Sketch binary
* via OTA and implements with an AutoConnectAux page handler that
* inherits from AutoConnectUploadHandler.
* By overriding the _write function of AutoConnectUploadHandler to
* write the executable binary using the Update class, it can update
* the module firmware in synchronization with the upload of the sketch
* binary file.
* @file AutoConnectOTA.h
* @author hieromon@gmail.com
* @version 1.2.2
* @date 2020-12-11
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTOTA_H_
#define _AUTOCONNECTOTA_H_
#include <memory>
#include "AutoConnect.h"
#include "AutoConnectUpload.h"
#include <FS.h>
#if defined(ARDUINO_ARCH_ESP8266)
#ifndef AUTOCONNECT_USE_SPIFFS
#include <LittleFS.h>
#endif
typedef fs::FS SPIFFST;
#elif defined(ARDUINO_ARCH_ESP32)
#include <SPIFFS.h>
typedef fs::SPIFFSFS SPIFFST;
#endif
class AutoConnectOTA : public AutoConnectUploadHandler {
public:
// Updating process status
typedef enum {
OTA_IDLE, /**< Update process has not started */
OTA_START, /**< Update process has started */
OTA_PROGRESS, /**< Update process in progress */
OTA_SUCCESS, /**< A binary updater has uploaded fine */
OTA_RIP, /**< Ready for module restart */
OTA_FAIL /**< Failed to save binary updater by Update class */
} AC_OTAStatus_t;
// The treating destination of OTA transferred data
typedef enum {
OTA_DEST_FILE, /**< To be upload the file */
OTA_DEST_FIRM /**< To update the firmware */
} AC_OTADest_t;
AutoConnectOTA() : _dest(OTA_DEST_FIRM), _status(OTA_IDLE), _tickerPort(-1), _tickerOn(LOW) {};
~AutoConnectOTA();
void attach(AutoConnect& portal); /**< Attach itself to AutoConnect */
void authentication(const AC_AUTH_t auth); /**< Set certain page authentication */
String error(void) const { return _err; } /**< Returns current error string */
void menu(const bool post) { _auxUpdate->menu(post); } /**< Enabel or disable arranging a created AutoConnectOTA page in the menu. */
void reset(void) { _status = OTA_IDLE; } /**< Reset the status */
AC_OTAStatus_t status(void) const { return _status; } /**< Return a current error status of the Update class */
AC_OTADest_t dest(void) const { return _dest; } /**< Return a current uploading destination */
void setTicker(int8_t pin, uint8_t on) { _tickerPort = pin, _tickerOn = on; } /**< Set ticker LED port */
protected:
// Attribute definition of the element to be placed on the update page.
typedef struct {
const ACElement_t type;
const char* name; /**< Name to assign to AutoConnectElement */
const char* value; /**< Value owned by an element */
const char* peculiar; /**< Specific ornamentation for the element */
} ACElementProp_t;
// Attributes to treat included update pages as AutoConnectAux.
typedef struct {
const char* uri; /**< URI for the page */
const char* title; /**< Menu title of update page */
const bool menu; /**< Whether to display in menu */
const ACElementProp_t* element;
} ACPage_t;
template <typename T, size_t N> constexpr size_t lengthOf(T (&)[N]) noexcept {
return N;
}
void _buildAux(AutoConnectAux* aux, const AutoConnectOTA::ACPage_t* page, const size_t elementNum);
bool _open(const char* filename, const char* mode) override;
size_t _write(const uint8_t *buf, const size_t size) override;
void _close(const HTTPUploadStatus status) override;
String _updated(AutoConnectAux& result, PageArgument& args);
std::unique_ptr<AutoConnectAux> _auxUpdate; /**< An update operation page */
std::unique_ptr<AutoConnectAux> _auxResult; /**< An update result page */
private:
void _setError(void);
void _setError(const char* err);
AC_OTADest_t _dest; /**< Destination of OTA transferred data */
AC_OTAStatus_t _status; /**< Status for update progress */
int8_t _tickerPort; /**< GPIO for flicker */
uint8_t _tickerOn; /**< A signal for flicker turn on */
String _binName; /**< An updater file name */
String _err; /**< Occurred error stamp */
SPIFFST* _fs; /**< Filesystem for the native file uploading */
fs::File _file; /**< File handler for the native file uploading */
static const ACPage_t _pageUpdate PROGMEM;
static const ACElementProp_t _elmUpdate[] PROGMEM;
static const ACPage_t _pageResult PROGMEM;
static const ACElementProp_t _elmResult[] PROGMEM;
};
#endif // !_AUTOCONNECTOTA_H_
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment