/** * AutoConnect portal site web page implementation. * @file AutoConnectPage.h * @author hieromon@gmail.com * @version 1.1.7 * @date 2020-04-19 * @copyright MIT license. */ #if defined(ARDUINO_ARCH_ESP8266) #include extern "C" { #include } #elif defined(ARDUINO_ARCH_ESP32) #include #include #define ENC_TYPE_NONE WIFI_AUTH_OPEN #endif #include "AutoConnect.h" #include "AutoConnectPage.h" #include "AutoConnectCredential.h" /**< Basic CSS common to all pages */ const char AutoConnect::_CSS_BASE[] PROGMEM = { "html{" "font-family:Helvetica,Arial,sans-serif;" "font-size:16px;" "-ms-text-size-adjust:100%;" "-webkit-text-size-adjust:100%;" "-moz-osx-font-smoothing:grayscale;" "-webkit-font-smoothing:antialiased" "}" "body{" "margin:0;" "padding:0" "}" ".base-panel{" "margin:0 22px 0 22px" "}" ".base-panel * label :not(.bins){" "display:inline-block;" "width:3.0em;" "text-align:right" "}" ".base-panel * .slist{" "width:auto;" "font-size:0.9em;" "margin-left:10px;" "text-align:left" "}" "input{" "-moz-appearance:none;" "-webkit-appearance:none;" "font-size:0.9em;" "margin:8px 0 auto" "}" ".lap{" "visibility:collapse" "}" ".lap:target{" "visibility:visible" "}" ".lap:target .overlap{" "opacity:0.7;" "transition:0.3s" "}" ".lap:target .modal_button{" "opacity:1;" "transition:0.3s" "}" ".overlap{" "top:0;" "left:0;" "width:100%;" "height:100%;" "position:fixed;" "opacity:0;" "background:#000;" "z-index:1000" "}" ".modal_button{" "border-radius:13px;" "background:#660033;" "color:#ffffcc;" "padding:20px 30px;" "text-align:center;" "text-decoration:none;" "letter-spacing:1px;" "font-weight:bold;" "display:inline-block;" "top:40%;" "left:40%;" "width:20%;" "position:fixed;" "opacity:0;" "z-index:1001" "}" }; /**< non-marked list for UL */ const char AutoConnect::_CSS_UL[] PROGMEM = { ".noorder,.exp{" "padding:0;" "list-style:none;" "display:table" "}" ".noorder li,.exp{" "display:table-row-group" "}" ".noorder li label, .exp li *{" "display:table-cell;" "width:auto;" "text-align:right;" "padding:10px 0.5em" "}" ".noorder input[type=\"checkbox\"]{" "-moz-appearance:checkbox;" "-webkit-appearance:checkbox" "}" ".noorder input[type=\"radio\"]{" "margin-right:0.5em;" "-moz-appearance:radio;" "-webkit-appearance:radio" "}" ".noorder input[type=\"text\"]{" "width:auto" "}" ".noorder input[type=\"text\"]:invalid{" "background:#fce4d6" "}" }; /**< Image icon for inline expansion, the lock mark. */ const char AutoConnect::_CSS_ICON_LOCK[] PROGMEM = { ".img-lock{" "display:inline-block;" "width:22px;" "height:22px;" "margin-top:14px;" "float:right;" "background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB1ElEQVRIibWVu0scURTGf3d2drBQFAWbbRQVCwuVLIZdi2gnWIiF/4GtKyuJGAJh8mgTcU0T8T8ICC6kiIVu44gvtFEQQWwsbExQJGHXmZtiZsOyzCN3Vz+4cDjfvec7j7l3QAF95onRZ54YKmdE1IbnS0c9mnAyAjkBxDy3LRHrjtRyu7OD52HntTAyvbw/HxP2hkCearrRb2WSCSuTTGi60S+QpzFhbwznDl/VVMHw0sF7hEjFbW2qkB38lfp8nNDipWcATil+uDM3cDWyeNRSijnfkHJnezb5Vkkgvbg3IOXD2e1ts93S+icnkZOAVaalZK3YQMa4L+pC6L1WduhYSeCf0PLBdxzOjZ93Lwvm6APAiLmlF1ubPiHotmaS41ExQjH0ZbfNM1NAFpgD0lVcICIrANqAVaAd+AFIYAy4BqaBG+Wsq5AH3vgk8xpYrzf4KLAZwhe8PYEIvQe4vc6H8Hnc2dQs0AFchvAXQGdEDF8s4A5TZS34BQqqQNaS1WMI3KD4WUbNoBJfce9CO7BSr4BfBe8A21vmUwh0VdjdTyHwscL+UK+AHxoD7FDoAX6/Cnpxn4ay/egCjcCL/w1chkqLakLQ/6ABhT57uAd+Vzv/Ara3iY6fK4WxAAAAAElFTkSuQmCC) no-repeat" "}" }; /**< INPUT button and submit style */ const char AutoConnect::_CSS_INPUT_BUTTON[] PROGMEM = { "input[type=\"button\"],input[type=\"submit\"],button[type=\"submit\"],button[type=\"button\"]{" "padding:8px 0.5em;" "font-weight:bold;" "letter-spacing:0.8px;" "color:#fff;" "border:1px solid;" "border-radius:2px;" "margin-top:12px" "}" "input[type=\"button\"],button[type=\"button\"]{" "background-color:#1b5e20;" "border-color:#1b5e20;" "width:15em" "}" ".aux-page input[type=\"button\"],button[type=\"button\"]{" "font-weight:normal;" "padding:8px 14px;" "margin:12px;" "width:auto" "}" "input#sb[type=\"submit\"]{" "width:15em" "}" "input[type=\"submit\"],button[type=\"submit\"]{" "padding:8px 30px;" "background-color:#006064;" "border-color:#006064" "}" "input[type=\"button\"],input[type=\"submit\"],button[type=\"submit\"]:focus," "input[type=\"button\"],input[type=\"submit\"],button[type=\"submit\"]:active{" "outline:none;" "text-decoration:none" "}" }; /**< INPUT text style */ const char AutoConnect::_CSS_INPUT_TEXT[] PROGMEM = { "input[type=\"text\"],input[type=\"password\"], .aux-page select{" "background-color:#fff;" "border:1px solid #ccc;" "border-radius:2px;" "color:#444;" "margin:8px 0 8px 0;" "padding:10px" "}" "input[type=\"text\"],input[type=\"password\"]{" "font-weight:300;" "width:auto;" "-webkit-transition:all 0.20s ease-in;" "-moz-transition:all 0.20s ease-in;" "-o-transition:all 0.20s ease-in;" "-ms-transition:all 0.20s ease-in;" "transition:all 0.20s ease-in" "}" "input[type=\"text\"]:focus,input[type=\"password\"]:focus{" "outline:none;" "border-color:#5C9DED;" "box-shadow:0 0 3px #4B8CDC" "}" "input.error,input.error:focus{" "border-color:#ED5564;" "color:#D9434E;" "box-shadow:0 0 3px #D9434E" "}" "input:disabled{" "opacity:0.6;" "background-color:#f7f7f7" "}" "input:disabled:hover{" "cursor:not-allowed" "}" "input.error::-webkit-input-placeholder," "input.error::-moz-placeholder," "input.error::-ms-input-placeholder{" "color:#D9434E" "}" ".aux-page label{" "display:inline;" "padding:10px 0.5em;" "}" }; /**< TABLE style */ const char AutoConnect::_CSS_TABLE[] PROGMEM = { "table{" "border-collapse:collapse;" "border-spacing:0;" "border:1px solid #ddd;" "color:#444;" "background-color:#fff;" "margin-bottom:20px" "}" "table.info," "table.info>tfoot," "table.info>thead{" "width:100%;" "border-color:#5C9DED" "}" "table.info>thead{" "background-color:#5C9DED" "}" "table.info>thead>tr>th{" "color:#fff" "}" "td," "th{" "padding:10px 22px" "}" "thead{" "background-color:#f3f3f3;" "border-bottom:1px solid #ddd" "}" "thead>tr>th{" "font-weight:400;" "text-align:left" "}" "tfoot{" "border-top:1px solid #ddd" "}" "tbody," "tbody>tr:nth-child(odd){" "background-color:#fff" "}" "tbody>tr>td," "tfoot>tr>td{" "font-weight:300;" "font-size:.88em" "}" "tbody>tr:nth-child(even){" "background-color:#f7f7f7" "}" "table.info tbody>tr:nth-child(even){" "background-color:#EFF5FD" "}" }; /**< SVG animation for spinner */ const char AutoConnect::_CSS_SPINNER[] PROGMEM = { ".spinner{" "width:40px;" "height:40px;" "position:relative;" "margin:100px auto" "}" ".dbl-bounce1, .dbl-bounce2{" "width:100%;" "height:100%;" "border-radius:50%;" "background-color:#a3cccc;" "opacity:0.6;" "position:absolute;" "top:0;" "left:0;" "-webkit-animation:sk-bounce 2.0s infinite ease-in-out;" "animation:sk-bounce 2.0s infinite ease-in-out" "}" ".dbl-bounce2{" "-webkit-animation-delay:-1.0s;" "animation-delay:-1.0s" "}" "@-webkit-keyframes sk-bounce{" "0%, 100%{-webkit-transform:scale(0.0)}" "50%{-webkit-transform:scale(1.0)}" "}" "@keyframes sk-bounce{" "0%,100%{" "transform:scale(0.0);" "-webkit-transform:scale(0.0);" "}50%{" "transform:scale(1.0);" "-webkit-transform:scale(1.0);" "}" "}" }; /**< Common menu bar. This style quotes LuxBar. */ /**< balzss/luxbar is licensed under the MIT License https://github.com/balzss/luxbar */ const char AutoConnect::_CSS_LUXBAR[] PROGMEM = { ".lb-fixed{" "width:100%;" "position:fixed;" "top:0;" "left:0;" "z-index:1000;" "box-shadow:0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24)" "}" ".lb-burger span," ".lb-burger span::before," ".lb-burger span::after{" "display:block;" "height:2px;" "width:26px;" "transition:0.6s ease" "}" ".lb-cb:checked~.lb-menu li .lb-burger span{" "background-color:transparent" "}" ".lb-cb:checked~.lb-menu li .lb-burger span::before," ".lb-cb:checked~.lb-menu li .lb-burger span::after{" "margin-top:0" "}" ".lb-header{" "display:flex;" "flex-direction:row;" "justify-content:space-between;" "align-items:center;" "height:58px" "}" ".lb-menu-right .lb-burger{" "margin-left:auto" "}" ".lb-brand{" "font-size:1.6em;" "padding:18px 24px 18px 24px" "}" ".lb-menu{" "min-height:58px;" "transition:0.6s ease;" "width:100%" "}" ".lb-navigation{" "display:flex;" "flex-direction:column;" "list-style:none;" "padding-left:0;" "margin:0" "}" ".lb-menu a," ".lb-item a{" "text-decoration:none;" "color:inherit;" "cursor:pointer" "}" ".lb-item{" "height:58px" "}" ".lb-item a{" "padding:18px 24px 18px 24px;" "display:block" "}" ".lb-burger{" "padding:18px 24px 18px 24px;" "position:relative;" "cursor:pointer" "}" ".lb-burger span::before," ".lb-burger span::after{" "content:'';" "position:absolute" "}" ".lb-burger span::before{" "margin-top:-8px" "}" ".lb-burger span::after{" "margin-top:8px" "}" ".lb-cb{" "display:none" "}" ".lb-cb:not(:checked)~.lb-menu{" "overflow:hidden;" "height:58px" "}" ".lb-cb:checked~.lb-menu{" "transition:height 0.6s ease;" "height:100vh;" "overflow:auto" "}" ".dropdown{" "position:relative;" "height:auto;" "min-height:58px" "}" ".dropdown:hover>ul{" "position:relative;" "display:block;" "min-width:100%" "}" ".dropdown>a::after{" "position:absolute;" "content:'';" "right:10px;" "top:25px;" "border-width:5px 5px 0;" "border-color:transparent;" "border-style:solid" "}" ".dropdown>ul{" "display:block;" "overflow-x:hidden;" "list-style:none;" "padding:0" "}" ".dropdown>ul .lb-item{" "min-width:100%;" "height:29px;" "padding:5px 10px 5px 40px" "}" ".dropdown>ul .lb-item a{" "min-height:29px;" "line-height:29px;" "padding:0" "}" "@media screen and (min-width:768px){" ".lb-navigation{" "flex-flow:row;" "justify-content:flex-end;" "}" ".lb-burger{" "display:none;" "}" ".lb-cb:not(:checked)~.lb-menu{" "overflow:visible;" "}" ".lb-cb:checked~.lb-menu{" "height:58px;" "}" ".lb-menu .lb-item{" "border-top:0;" "}" ".lb-menu-right .lb-header{" "margin-right:auto;" "}" ".dropdown{" "height:58px;" "}" ".dropdown:hover>ul{" "position:absolute;" "left:0;" "top:58px;" "padding:0;" "}" ".dropdown>ul{" "display:none;" "}" ".dropdown>ul .lb-item{" "padding:5px 10px;" "}" ".dropdown>ul .lb-item a{" "white-space:nowrap;" "}" "}" ".lb-cb:checked+.lb-menu .lb-burger-dblspin span::before{" "transform:rotate(225deg)" "}" ".lb-cb:checked+.lb-menu .lb-burger-dblspin span::after{" "transform:rotate(-225deg)" "}" ".lb-menu-material," ".lb-menu-material .dropdown ul{" "background-color:" AUTOCONNECT_MENUCOLOR_BACKGROUND ";" "color:" AUTOCONNECT_MENUCOLOR_TEXT "}" ".lb-menu-material .active," ".lb-menu-material .lb-item:hover{" "background-color:" AUTOCONNECT_MENUCOLOR_ACTIVE "}" ".lb-menu-material .lb-burger span," ".lb-menu-material .lb-burger span::before," ".lb-menu-material .lb-burger span::after{" "background-color:" AUTOCONNECT_MENUCOLOR_TEXT "}" }; /**< Common html document header. */ const char AutoConnect::_ELM_HTML_HEAD[] PROGMEM = { "" "" "" "" }; /**< LuxBar menu element. */ const char AutoConnect::_ELM_MENU_PRE[] PROGMEM = { "
" "" "
" "
    " "
  • " "MENU_TITLE" "" "
  • " "MENU_LIST" }; const char AutoConnect::_ELM_MENU_AUX[] PROGMEM = { "{{AUX_MENU}}" }; const char AutoConnect::_ELM_MENU_POST[] PROGMEM = { "MENU_HOME" "MENU_DEVINFO" "
" "
" "" "
" }; /**< The 404 page content. */ const char AutoConnect::_PAGE_404[] PROGMEM = { "{{HEAD}}" "" AUTOCONNECT_PAGETITLE_NOTFOUND "" "" "" "404 Not found" "" "" }; /**< The page that started the reset. */ const char AutoConnect::_PAGE_RESETTING[] PROGMEM = { "{{HEAD}}" "" "" AUTOCONNECT_PAGETITLE_RESETTING "" "" "" "

{{RESET}}

" "" "" "" }; /**< AutoConnect portal page. */ const char AutoConnect::_PAGE_STAT[] PROGMEM = { "{{HEAD}}" "" AUTOCONNECT_PAGETITLE_STATISTICS "" "" "" "" "
" "{{MENU_PRE}}" "{{MENU_AUX}}" "{{MENU_POST}}" "
" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
" AUTOCONNECT_PAGESTATS_ESTABLISHEDCONNECTION "{{ESTAB_SSID}}
" AUTOCONNECT_PAGESTATS_MODE "{{WIFI_MODE}}({{WIFI_STATUS}})
" AUTOCONNECT_PAGESTATS_IP "{{LOCAL_IP}}
" AUTOCONNECT_PAGESTATS_GATEWAY "{{GATEWAY}}
" AUTOCONNECT_PAGESTATS_SUBNETMASK "{{NETMASK}}
" AUTOCONNECT_PAGESTATS_SOFTAPIP "{{SOFTAP_IP}}
" AUTOCONNECT_PAGESTATS_APMAC "{{AP_MAC}}
" AUTOCONNECT_PAGESTATS_STAMAC "{{STA_MAC}}
" AUTOCONNECT_PAGESTATS_CHANNEL "{{CHANNEL}}
" AUTOCONNECT_PAGESTATS_DBM "{{DBM}}
" AUTOCONNECT_PAGESTATS_CHIPID "{{CHIP_ID}}
" AUTOCONNECT_PAGESTATS_CPUFREQ "{{CPU_FREQ}}MHz
" AUTOCONNECT_PAGESTATS_FLASHSIZE "{{FLASH_SIZE}}
" AUTOCONNECT_PAGESTATS_FREEMEM "{{FREE_HEAP}}
" "
" "
" "" "" }; /**< A page that specifies the new configuration. */ const char AutoConnect::_PAGE_CONFIGNEW[] PROGMEM = { "{{HEAD}}" "" AUTOCONNECT_PAGETITLE_CONFIG "" "" "" "" "
" "{{MENU_PRE}}" "{{MENU_AUX}}" "{{MENU_POST}}" "
" "
" "" "{{LIST_SSID}}" "
" AUTOCONNECT_PAGECONFIG_TOTAL "{{SSID_COUNT}} " AUTOCONNECT_PAGECONFIG_HIDDEN "{{HIDDEN_COUNT}}
" "
    " "
  • " "" "" "
  • " "
  • " "" "" "
  • " "
  • " "" "" "
  • " "{{CONFIG_IP}}" "
  • " "
" "
" "
" "
" "" "" "" }; /**< A page that reads stored authentication information and starts connection. */ const char AutoConnect::_PAGE_OPENCREDT[] PROGMEM = { "{{HEAD}}" "" AUTOCONNECT_PAGETITLE_CREDENTIALS "" "" "" "" "
" "{{MENU_PRE}}" "{{MENU_AUX}}" "{{MENU_POST}}" "
" "
" "{{OPEN_SSID}}" "
" "
" "
" "" "" }; /**< A page that informs during a connection attempting. */ const char AutoConnect::_PAGE_CONNECTING[] PROGMEM = { "{{REQ}}" "{{HEAD}}" "" AUTOCONNECT_PAGETITLE_CONNECTING "" "" "" "" "
" "{{MENU_PRE}}" "{{MENU_POST}}" "
" "
" "
" "
{{CUR_SSID}}
" "
" "
" "" "" "" }; /**< A page announcing that a connection has been established. */ const char AutoConnect::_PAGE_SUCCESS[] PROGMEM = { "{{HEAD}}" "" AUTOCONNECT_PAGETITLE_STATISTICS "" "" "" "" "
" "{{MENU_PRE}}" "{{MENU_AUX}}" "{{MENU_POST}}" "
" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
" AUTOCONNECT_PAGESTATS_ESTABLISHEDCONNECTION "{{ESTAB_SSID}}
" AUTOCONNECT_PAGESTATS_MODE "{{WIFI_MODE}}({{WIFI_STATUS}})
" AUTOCONNECT_PAGESTATS_IP "{{LOCAL_IP}}
" AUTOCONNECT_PAGESTATS_GATEWAY "{{GATEWAY}}
" AUTOCONNECT_PAGESTATS_SUBNETMASK "{{NETMASK}}
" AUTOCONNECT_PAGESTATS_CHANNEL "{{CHANNEL}}
" AUTOCONNECT_PAGESTATS_DBM "{{DBM}}
" "
" "
" "" "" }; /**< A response page for connection failed. */ const char AutoConnect::_PAGE_FAIL[] PROGMEM = { "{{HEAD}}" "" AUTOCONNECT_PAGETITLE_CONNECTIONFAILED "" "" "" "" "
" "{{MENU_PRE}}" "{{MENU_AUX}}" "{{MENU_POST}}" "
" "" "" "" "" "" "" "" "
" AUTOCONNECT_PAGECONNECTIONFAILED_CONNECTIONFAILED "{{STATION_STATUS}}
" "
" "
" "" "" }; /**< A response page for disconnected from the AP. */ const char AutoConnect::_PAGE_DISCONN[] PROGMEM = { "{{DISCONNECT}}" "{{HEAD}}" "" AUTOCONNECT_PAGETITLE_DISCONNECTED "" "" "" "" "
" "{{MENU_PRE}}" "{{MENU_POST}}" "
" "" "" }; // Each page of AutoConnect is http transferred by the content transfer // mode of Page Builder. The default transfer mode is // AUTOCONNECT_HTTP_TRANSFER defined in AutoConnectDefs.h. The page to // which default transfer mode is not applied, specifies the enumeration // value of PageBuilder::TransferEncoding_t. The content construction // buffer can be reserved with the chunked transfer, and its size is // macro defined by AUTOCONNECT_CONTENTBUFFER_SIZE. const AutoConnect::PageTranserModeST AutoConnect::_pageBuildMode[] = { { AUTOCONNECT_URI, AUTOCONNECT_HTTP_TRANSFER, 0 }, { AUTOCONNECT_URI_CONFIG, PB_Chunk, AUTOCONNECT_CONTENTBUFFER_SIZE }, { AUTOCONNECT_URI_CONNECT, AUTOCONNECT_HTTP_TRANSFER, 0 }, { AUTOCONNECT_URI_RESULT, AUTOCONNECT_HTTP_TRANSFER, 0 }, { AUTOCONNECT_URI_OPEN, AUTOCONNECT_HTTP_TRANSFER, 0 }, { AUTOCONNECT_URI_DISCON, AUTOCONNECT_HTTP_TRANSFER, 0 }, { AUTOCONNECT_URI_RESET, AUTOCONNECT_HTTP_TRANSFER, 0 }, { AUTOCONNECT_URI_SUCCESS, AUTOCONNECT_HTTP_TRANSFER, 0 }, { AUTOCONNECT_URI_FAIL, AUTOCONNECT_HTTP_TRANSFER, 0 } }; uint32_t AutoConnect::_getChipId() { #if defined(ARDUINO_ARCH_ESP8266) return ESP.getChipId(); #elif defined(ARDUINO_ARCH_ESP32) uint64_t chipId; chipId = ESP.getEfuseMac(); return (uint32_t)(chipId >> 32); #endif } uint32_t AutoConnect::_getFlashChipRealSize() { #if defined(ARDUINO_ARCH_ESP8266) return ESP.getFlashChipRealSize(); #elif defined(ARDUINO_ARCH_ESP32) return (uint32_t)spi_flash_get_chip_size(); #endif } String AutoConnect::_token_CSS_BASE(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_CSS_BASE)); } String AutoConnect::_token_CSS_UL(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_CSS_UL)); } String AutoConnect::_token_CSS_ICON_LOCK(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_CSS_ICON_LOCK)); } String AutoConnect::_token_CSS_INPUT_BUTTON(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_CSS_INPUT_BUTTON)); } String AutoConnect::_token_CSS_INPUT_TEXT(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_CSS_INPUT_TEXT)); } String AutoConnect::_token_CSS_TABLE(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_CSS_TABLE)); } String AutoConnect::_token_CSS_SPINNER(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_CSS_SPINNER)); } String AutoConnect::_token_HEAD(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_ELM_HTML_HEAD)); } String AutoConnect::_token_MENU_PRE(PageArgument& args) { String currentMenu = FPSTR(_ELM_MENU_PRE); String menuItem = _attachMenuItem(AC_MENUITEM_CONFIGNEW) + _attachMenuItem(AC_MENUITEM_OPENSSIDS) + _attachMenuItem(AC_MENUITEM_DISCONNECT) + _attachMenuItem(AC_MENUITEM_RESET); currentMenu.replace(String(F("MENU_LIST")), menuItem); currentMenu.replace(String(F("BOOT_URI")), _getBootUri()); currentMenu.replace(String(F("MENU_TITLE")), _menuTitle); currentMenu.replace(String(F("{{CUR_SSID}}")), _token_ESTAB_SSID(args)); return currentMenu; } String AutoConnect::_token_MENU_AUX(PageArgument& args) { String menuItem = String(""); if (_aux) menuItem = _aux->_injectMenu(args); return menuItem; } String AutoConnect::_token_MENU_POST(PageArgument& args) { AC_UNUSED(args); String postMenu = FPSTR(_ELM_MENU_POST); postMenu.replace(String(F("MENU_HOME")), _attachMenuItem(AC_MENUITEM_HOME)); postMenu.replace(String(F("HOME_URI")), _apConfig.homeUri); postMenu.replace(String(F("MENU_DEVINFO")), _attachMenuItem(AC_MENUITEM_DEVINFO)); return postMenu; } String AutoConnect::_token_CSS_LUXBAR(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_CSS_LUXBAR)); } String AutoConnect::_token_ESTAB_SSID(PageArgument& args) { AC_UNUSED(args); return (WiFi.status() == WL_CONNECTED ? WiFi.SSID() : String(F("N/A"))); } String AutoConnect::_token_WIFI_MODE(PageArgument& args) { AC_UNUSED(args); PGM_P wifiMode; switch (WiFi.getMode()) { case WIFI_OFF: wifiMode = PSTR("OFF"); break; case WIFI_STA: wifiMode = PSTR("STA"); break; case WIFI_AP: wifiMode = PSTR("AP"); break; case WIFI_AP_STA: wifiMode = PSTR("AP_STA"); break; #ifdef ARDUINO_ARCH_ESP32 case WIFI_MODE_MAX: wifiMode = PSTR("MAX"); break; #endif default: wifiMode = PSTR("experiment"); } return String(FPSTR(wifiMode)); } String AutoConnect::_token_WIFI_STATUS(PageArgument& args) { AC_UNUSED(args); return String(WiFi.status()); } String AutoConnect::_token_STATION_STATUS(PageArgument& args) { AC_UNUSED(args); PGM_P wlStatusSymbol = PSTR(""); // const char* wlStatusSymbol =""; PGM_P wlStatusSymbols[] = { // static const char* wlStatusSymbols[] = { #if defined(ARDUINO_ARCH_ESP8266) PSTR("IDLE"), PSTR("CONNECTING"), PSTR("WRONG_PASSWORD"), PSTR("NO_AP_FOUND"), PSTR("CONNECT_FAIL"), PSTR("GOT_IP") }; switch (wifi_station_get_connect_status()) { case STATION_IDLE: wlStatusSymbol = wlStatusSymbols[0]; break; case STATION_CONNECTING: wlStatusSymbol = wlStatusSymbols[1]; break; case STATION_WRONG_PASSWORD: wlStatusSymbol = wlStatusSymbols[2]; break; case STATION_NO_AP_FOUND: wlStatusSymbol = wlStatusSymbols[3]; break; case STATION_CONNECT_FAIL: wlStatusSymbol = wlStatusSymbols[4]; break; case STATION_GOT_IP: wlStatusSymbol = wlStatusSymbols[5]; break; #elif defined(ARDUINO_ARCH_ESP32) PSTR("IDLE"), PSTR("NO_SSID_AVAIL"), PSTR("SCAN_COMPLETED"), PSTR("CONNECTED"), PSTR("CONNECT_FAILED"), PSTR("CONNECTION_LOST"), PSTR("DISCONNECTED"), PSTR("NO_SHIELD") }; switch (_rsConnect) { case WL_IDLE_STATUS: wlStatusSymbol = wlStatusSymbols[0]; break; case WL_NO_SSID_AVAIL: wlStatusSymbol = wlStatusSymbols[1]; break; case WL_SCAN_COMPLETED: wlStatusSymbol = wlStatusSymbols[2]; break; case WL_CONNECTED: wlStatusSymbol = wlStatusSymbols[3]; break; case WL_CONNECT_FAILED: wlStatusSymbol = wlStatusSymbols[4]; break; case WL_CONNECTION_LOST: wlStatusSymbol = wlStatusSymbols[5]; break; case WL_DISCONNECTED: wlStatusSymbol = wlStatusSymbols[6]; break; case WL_NO_SHIELD: wlStatusSymbol = wlStatusSymbols[7]; break; #endif } return String("(") + String(_rsConnect) + String(") ") + String(FPSTR(wlStatusSymbol)); } String AutoConnect::_token_LOCAL_IP(PageArgument& args) { AC_UNUSED(args); return WiFi.localIP().toString(); } String AutoConnect::_token_SOFTAP_IP(PageArgument& args) { AC_UNUSED(args); return WiFi.softAPIP().toString(); } String AutoConnect::_token_GATEWAY(PageArgument& args) { AC_UNUSED(args); return WiFi.gatewayIP().toString(); } String AutoConnect::_token_NETMASK(PageArgument& args) { AC_UNUSED(args); return WiFi.subnetMask().toString(); } String AutoConnect::_token_AP_MAC(PageArgument& args) { AC_UNUSED(args); uint8_t macAddress[6]; WiFi.softAPmacAddress(macAddress); return AutoConnect::_toMACAddressString(macAddress); } String AutoConnect::_token_STA_MAC(PageArgument& args) { AC_UNUSED(args); uint8_t macAddress[6]; WiFi.macAddress(macAddress); return AutoConnect::_toMACAddressString(macAddress); } String AutoConnect::_token_CHANNEL(PageArgument& args) { AC_UNUSED(args); return String(WiFi.channel()); } String AutoConnect::_token_DBM(PageArgument& args) { AC_UNUSED(args); int32_t dBm = WiFi.RSSI(); return (dBm == 31 ? String(F("N/A")) : String(dBm)); } String AutoConnect::_token_CPU_FREQ(PageArgument& args) { AC_UNUSED(args); return String(ESP.getCpuFreqMHz()); } String AutoConnect::_token_FLASH_SIZE(PageArgument& args) { AC_UNUSED(args); return String(_getFlashChipRealSize()); } String AutoConnect::_token_CHIP_ID(PageArgument& args) { AC_UNUSED(args); return String(_getChipId()); } String AutoConnect::_token_FREE_HEAP(PageArgument& args) { AC_UNUSED(args); return String(_freeHeapSize); } String AutoConnect::_token_LIST_SSID(PageArgument& args) { // Obtain the page number to display. // When the display request is the first page, it will be obtained // from the scan results of the WiFiScan class if it has already been // scanned. uint8_t page = 0; if (args.hasArg(String(F("page")))) page = args.arg("page").toInt(); else { // Scan at a first time WiFi.scanDelete(); _scanCount = WiFi.scanNetworks(false, true); AC_DBG("%d network(s) found\n", (int)_scanCount); } // Prepare SSID list content building buffer size_t bufSize = sizeof('\0') + 192 * (_scanCount > AUTOCONNECT_SSIDPAGEUNIT_LINES ? AUTOCONNECT_SSIDPAGEUNIT_LINES : _scanCount); bufSize += 88 * (_scanCount > AUTOCONNECT_SSIDPAGEUNIT_LINES ? (_scanCount > (AUTOCONNECT_SSIDPAGEUNIT_LINES * 2) ? 2 : 1) : 0); char* ssidList = (char*)malloc(bufSize); if (!ssidList) { AC_DBG("ssidList buffer(%d) allocation failed\n", (int)bufSize); return _emptyString; } AC_DBG_DUMB("\n"); // Locate to the page and build SSD list content. static const char _ssidList[] PROGMEM = "" "%s
"; static const char _ssidEnc[] PROGMEM = ""; static const char _ssidPage[] PROGMEM = " "; _hiddenSSIDCount = 0; uint8_t validCount = 0; uint8_t dispCount = 0; char* slBuf = ssidList; *slBuf = '\0'; for (uint8_t i = 0; i < _scanCount; i++) { String ssid = WiFi.SSID(i); if (ssid.length() > 0) { // An available SSID may be listed. // AUTOCONNECT_SSIDPAGEUNIT_LINES determines the number of lines // per page in the available SSID list. if (validCount >= page * AUTOCONNECT_SSIDPAGEUNIT_LINES && validCount <= (page + 1) * AUTOCONNECT_SSIDPAGEUNIT_LINES - 1) { if (++dispCount <= AUTOCONNECT_SSIDPAGEUNIT_LINES) { snprintf_P(slBuf, bufSize - (slBuf - ssidList), (PGM_P)_ssidList, ssid.c_str(), AutoConnect::_toWiFiQuality(WiFi.RSSI(i)), WiFi.channel(i), WiFi.encryptionType(i) != ENC_TYPE_NONE ? (PGM_P)_ssidEnc : ""); slBuf += strlen(slBuf); } } // The validCount counts the found SSIDs that is not the Hidden // attribute to determines the next button should be displayed. validCount++; } else _hiddenSSIDCount++; } // Prepare perv. button if (page >= 1) { snprintf_P(slBuf, bufSize - (slBuf - ssidList), (PGM_P)_ssidPage, page - 1, PSTR("Prev.")); slBuf = ssidList + strlen(ssidList); } // Prepare next button if (validCount > (page + 1) * AUTOCONNECT_SSIDPAGEUNIT_LINES) { snprintf_P(slBuf, bufSize - (slBuf - ssidList), (PGM_P)_ssidPage, page + 1, PSTR("Next")); } // return ssidList; String ssidListStr = String(ssidList); free(ssidList); return ssidListStr; } String AutoConnect::_token_SSID_COUNT(PageArgument& args) { AC_UNUSED(args); return String(_scanCount); } String AutoConnect::_token_HIDDEN_COUNT(PageArgument& args) { AC_UNUSED(args); return String(_hiddenSSIDCount); } String AutoConnect::_token_CONFIG_STAIP(PageArgument& args) { AC_UNUSED(args); static const char _configIPList[] PROGMEM = "
  • " "" "" "
  • "; struct _reps { PGM_P lid; PGM_P lbl; } static const reps[] = { { PSTR(AUTOCONNECT_PARAMID_STAIP), PSTR("IP Address") }, { PSTR(AUTOCONNECT_PARAMID_GTWAY), PSTR("Gateway") }, { PSTR(AUTOCONNECT_PARAMID_NTMSK), PSTR("Netmask") }, { PSTR(AUTOCONNECT_PARAMID_DNS1), PSTR("DNS1") }, { PSTR(AUTOCONNECT_PARAMID_DNS2), PSTR("DNS2") } }; char liCont[600]; char* liBuf = liCont; for (uint8_t i = 0; i < 5; i++) { IPAddress* ip = nullptr; if (i == 0) ip = &_apConfig.staip; else if (i == 1) ip = &_apConfig.staGateway; else if (i == 2) ip = &_apConfig.staNetmask; else if (i == 3) ip = &_apConfig.dns1; else if (i == 4) ip = &_apConfig.dns2; String ipStr = ip != nullptr ? ip->toString() : String(F("0.0.0.0")); snprintf_P(liBuf, sizeof(liCont) - (liBuf - liCont), (PGM_P)_configIPList, reps[i].lid, reps[i].lbl, reps[i].lid, reps[i].lid, ipStr.c_str()); liBuf += strlen(liBuf); } return String(liCont); } String AutoConnect::_token_OPEN_SSID(PageArgument& args) { AC_UNUSED(args); static const char _ssidList[] PROGMEM = "%s
    "; static const char _ssidRssi[] PROGMEM = "%d% Ch.%d"; static const char _ssidNA[] PROGMEM = "N/A"; static const char _ssidLock[] PROGMEM = ""; static const char _ssidNull[] PROGMEM = ""; String ssidList; station_config_t entry; char slCont[176]; char rssiCont[32]; AutoConnectCredential credit(_apConfig.boundaryOffset); uint8_t creEntries = credit.entries(); if (creEntries > 0) { ssidList = String(""); _scanCount = WiFi.scanNetworks(false, true); } else ssidList = String(F("

    " AUTOCONNECT_TEXT_NOSAVEDCREDENTIALS "

    ")); for (uint8_t i = 0; i < creEntries; i++) { rssiCont[0] = '\0'; PGM_P rssiSym = _ssidNA; PGM_P ssidLock = _ssidNull; credit.load(i, &entry); AC_DBG("A credential #%d loaded\n", (int)i); for (int8_t sc = 0; sc < (int8_t)_scanCount; sc++) { if (!memcmp(entry.bssid, WiFi.BSSID(sc), sizeof(station_config_t::bssid))) { _connectCh = WiFi.channel(sc); snprintf_P(rssiCont, sizeof(rssiCont), (PGM_P)_ssidRssi, AutoConnect::_toWiFiQuality(WiFi.RSSI(sc)), _connectCh); rssiSym = rssiCont; if (WiFi.encryptionType(sc) != ENC_TYPE_NONE) ssidLock = _ssidLock; break; } } snprintf_P(slCont, sizeof(slCont), (PGM_P)_ssidList, AUTOCONNECT_PARAMID_CRED, reinterpret_cast(entry.ssid), rssiSym, ssidLock); ssidList += String(slCont); } return ssidList; } String AutoConnect::_token_UPTIME(PageArgument& args) { AC_UNUSED(args); return String(_apConfig.uptime); } String AutoConnect::_token_BOOTURI(PageArgument& args) { AC_UNUSED(args); return _getBootUri(); } String AutoConnect::_token_CURRENT_SSID(PageArgument& args) { AC_UNUSED(args); char ssid_c[sizeof(station_config_t::ssid) + 1]; *ssid_c = '\0'; strncat(ssid_c, reinterpret_cast(_credential.ssid), sizeof(ssid_c) - 1); String ssid = String(ssid_c); return ssid; } /** * Generate AutoConnect menu item configured by AutoConnectConfig::attachMenu. * @param item An enumerated value for the generating item configured in AutoConnectConfig. * @return HTML string of a li tag with the menu item. */ String AutoConnect::_attachMenuItem(const AC_MENUITEM_t item) { static const char _liTempl[] PROGMEM = "
  • %s
  • "; PGM_P id; PGM_P link; PGM_P label; switch (static_cast(_apConfig.menuItems & static_cast(item))) { case AC_MENUITEM_CONFIGNEW: id = PSTR(""); link = PSTR(AUTOCONNECT_URI_CONFIG); label = PSTR(AUTOCONNECT_MENULABEL_CONFIGNEW); break; case AC_MENUITEM_OPENSSIDS: id = PSTR(""); link = PSTR(AUTOCONNECT_URI_OPEN); label = PSTR(AUTOCONNECT_MENULABEL_OPENSSIDS); break; case AC_MENUITEM_DISCONNECT: id = PSTR(""); link = PSTR(AUTOCONNECT_URI_DISCON); label = PSTR(AUTOCONNECT_MENULABEL_DISCONNECT); break; case AC_MENUITEM_RESET: id = PSTR(" id=\"reset\""); link = PSTR("#rdlg"); label = PSTR(AUTOCONNECT_MENULABEL_RESET); break; case AC_MENUITEM_HOME: id = PSTR(""); link = PSTR("HOME_URI"); label = PSTR(AUTOCONNECT_MENULABEL_HOME); break; case AC_MENUITEM_DEVINFO: id = PSTR(""); link = PSTR(AUTOCONNECT_URI); label = PSTR(AUTOCONNECT_MENULABEL_DEVINFO); break; default: id = nullptr; link = nullptr; label = nullptr; break; } char li[128] = { '\0' }; if (!!id && !!link && !!label) snprintf(li, sizeof(li), (PGM_P)_liTempl, id, link, label); return String(li); } /** * This function dynamically build up the response pages that conform to * the requested URI. A PageBuilder instance is stored in _responsePage * as the response page. * @param Requested URI. * @retval true A response page generated. * @retval false Requested uri is not defined. */ PageElement* AutoConnect::_setupPage(String& uri) { PageElement *elm = new PageElement(); // Restore menu title _menuTitle = _apConfig.title; // Build the elements of current requested page. if (uri == String(AUTOCONNECT_URI)) { // Setup /auto _freeHeapSize = ESP.getFreeHeap(); elm->setMold(_PAGE_STAT); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_TABLE")), std::bind(&AutoConnect::_token_CSS_TABLE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_LUXBAR")), std::bind(&AutoConnect::_token_CSS_LUXBAR, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_AUX")), std::bind(&AutoConnect::_token_MENU_AUX, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); elm->addToken(String(FPSTR("ESTAB_SSID")), std::bind(&AutoConnect::_token_ESTAB_SSID, this, std::placeholders::_1)); elm->addToken(String(FPSTR("WIFI_MODE")), std::bind(&AutoConnect::_token_WIFI_MODE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("WIFI_STATUS")), std::bind(&AutoConnect::_token_WIFI_STATUS, this, std::placeholders::_1)); elm->addToken(String(FPSTR("LOCAL_IP")), std::bind(&AutoConnect::_token_LOCAL_IP, this, std::placeholders::_1)); elm->addToken(String(FPSTR("SOFTAP_IP")), std::bind(&AutoConnect::_token_SOFTAP_IP, this, std::placeholders::_1)); elm->addToken(String(FPSTR("GATEWAY")), std::bind(&AutoConnect::_token_GATEWAY, this, std::placeholders::_1)); elm->addToken(String(FPSTR("NETMASK")), std::bind(&AutoConnect::_token_NETMASK, this, std::placeholders::_1)); elm->addToken(String(FPSTR("AP_MAC")), std::bind(&AutoConnect::_token_AP_MAC, this, std::placeholders::_1)); elm->addToken(String(FPSTR("STA_MAC")), std::bind(&AutoConnect::_token_STA_MAC, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CHANNEL")), std::bind(&AutoConnect::_token_CHANNEL, this, std::placeholders::_1)); elm->addToken(String(FPSTR("DBM")), std::bind(&AutoConnect::_token_DBM, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CPU_FREQ")), std::bind(&AutoConnect::_token_CPU_FREQ, this, std::placeholders::_1)); elm->addToken(String(FPSTR("FLASH_SIZE")), std::bind(&AutoConnect::_token_FLASH_SIZE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CHIP_ID")), std::bind(&AutoConnect::_token_CHIP_ID, this, std::placeholders::_1)); elm->addToken(String(FPSTR("FREE_HEAP")), std::bind(&AutoConnect::_token_FREE_HEAP, this, std::placeholders::_1)); } else if (uri == String(AUTOCONNECT_URI_CONFIG) && (_apConfig.menuItems & AC_MENUITEM_CONFIGNEW)) { // Setup /auto/config elm->setMold(_PAGE_CONFIGNEW); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_UL")), std::bind(&AutoConnect::_token_CSS_UL, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_ICON_LOCK")), std::bind(&AutoConnect::_token_CSS_ICON_LOCK, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_INPUT_BUTTON")), std::bind(&AutoConnect::_token_CSS_INPUT_BUTTON, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_INPUT_TEXT")), std::bind(&AutoConnect::_token_CSS_INPUT_TEXT, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_LUXBAR")), std::bind(&AutoConnect::_token_CSS_LUXBAR, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_AUX")), std::bind(&AutoConnect::_token_MENU_AUX, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); elm->addToken(String(FPSTR("LIST_SSID")), std::bind(&AutoConnect::_token_LIST_SSID, this, std::placeholders::_1)); elm->addToken(String(FPSTR("SSID_COUNT")), std::bind(&AutoConnect::_token_SSID_COUNT, this, std::placeholders::_1)); elm->addToken(String(FPSTR("HIDDEN_COUNT")), std::bind(&AutoConnect::_token_HIDDEN_COUNT, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CONFIG_IP")), std::bind(&AutoConnect::_token_CONFIG_STAIP, this, std::placeholders::_1)); } else if (uri == String(AUTOCONNECT_URI_CONNECT) && (_apConfig.menuItems & AC_MENUITEM_CONFIGNEW || _apConfig.menuItems & AC_MENUITEM_OPENSSIDS)) { // Setup /auto/connect _menuTitle = FPSTR(AUTOCONNECT_MENUTEXT_CONNECTING); elm->setMold(_PAGE_CONNECTING); elm->addToken(String(FPSTR("REQ")), std::bind(&AutoConnect::_induceConnect, this, std::placeholders::_1)); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_SPINNER")), std::bind(&AutoConnect::_token_CSS_SPINNER, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_LUXBAR")), std::bind(&AutoConnect::_token_CSS_LUXBAR, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CUR_SSID")), std::bind(&AutoConnect::_token_CURRENT_SSID, this, std::placeholders::_1)); } else if (uri == String(AUTOCONNECT_URI_OPEN) && (_apConfig.menuItems & AC_MENUITEM_OPENSSIDS)) { // Setup /auto/open elm->setMold(_PAGE_OPENCREDT); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_ICON_LOCK")), std::bind(&AutoConnect::_token_CSS_ICON_LOCK, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_INPUT_BUTTON")), std::bind(&AutoConnect::_token_CSS_INPUT_BUTTON, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_LUXBAR")), std::bind(&AutoConnect::_token_CSS_LUXBAR, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_AUX")), std::bind(&AutoConnect::_token_MENU_AUX, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); elm->addToken(String(FPSTR("OPEN_SSID")), std::bind(&AutoConnect::_token_OPEN_SSID, this, std::placeholders::_1)); } else if (uri == String(AUTOCONNECT_URI_DISCON) && (_apConfig.menuItems & AC_MENUITEM_DISCONNECT)) { // Setup /auto/disc _menuTitle = FPSTR(AUTOCONNECT_MENUTEXT_DISCONNECT); elm->setMold(_PAGE_DISCONN); elm->addToken(String(FPSTR("DISCONNECT")), std::bind(&AutoConnect::_induceDisconnect, this, std::placeholders::_1)); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_LUXBAR")), std::bind(&AutoConnect::_token_CSS_LUXBAR, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); } else if (uri == String(AUTOCONNECT_URI_RESET) && (_apConfig.menuItems & AC_MENUITEM_RESET)) { // Setup /auto/reset elm->setMold(_PAGE_RESETTING); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("BOOTURI")), std::bind(&AutoConnect::_token_BOOTURI, this, std::placeholders::_1)); elm->addToken(String(FPSTR("UPTIME")), std::bind(&AutoConnect::_token_UPTIME, this, std::placeholders::_1)); elm->addToken(String(FPSTR("RESET")), std::bind(&AutoConnect::_induceReset, this, std::placeholders::_1)); } else if (uri == String(AUTOCONNECT_URI_RESULT)) { // Setup /auto/result elm->setMold("{{RESULT}}"); elm->addToken(String(FPSTR("RESULT")), std::bind(&AutoConnect::_invokeResult, this, std::placeholders::_1)); } else if (uri == String(AUTOCONNECT_URI_SUCCESS)) { // Setup /auto/success elm->setMold(_PAGE_SUCCESS); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_TABLE")), std::bind(&AutoConnect::_token_CSS_TABLE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_LUXBAR")), std::bind(&AutoConnect::_token_CSS_LUXBAR, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_AUX")), std::bind(&AutoConnect::_token_MENU_AUX, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); elm->addToken(String(FPSTR("ESTAB_SSID")), std::bind(&AutoConnect::_token_ESTAB_SSID, this, std::placeholders::_1)); elm->addToken(String(FPSTR("WIFI_MODE")), std::bind(&AutoConnect::_token_WIFI_MODE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("WIFI_STATUS")), std::bind(&AutoConnect::_token_WIFI_STATUS, this, std::placeholders::_1)); elm->addToken(String(FPSTR("LOCAL_IP")), std::bind(&AutoConnect::_token_LOCAL_IP, this, std::placeholders::_1)); elm->addToken(String(FPSTR("GATEWAY")), std::bind(&AutoConnect::_token_GATEWAY, this, std::placeholders::_1)); elm->addToken(String(FPSTR("NETMASK")), std::bind(&AutoConnect::_token_NETMASK, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CHANNEL")), std::bind(&AutoConnect::_token_CHANNEL, this, std::placeholders::_1)); elm->addToken(String(FPSTR("DBM")), std::bind(&AutoConnect::_token_DBM, this, std::placeholders::_1)); } else if (uri == String(AUTOCONNECT_URI_FAIL)) { // Setup /auto/fail _menuTitle = FPSTR(AUTOCONNECT_MENUTEXT_FAILED); elm->setMold(_PAGE_FAIL); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_TABLE")), std::bind(&AutoConnect::_token_CSS_TABLE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_LUXBAR")), std::bind(&AutoConnect::_token_CSS_LUXBAR, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_AUX")), std::bind(&AutoConnect::_token_MENU_AUX, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); elm->addToken(String(FPSTR("STATION_STATUS")), std::bind(&AutoConnect::_token_STATION_STATUS, this, std::placeholders::_1)); } else { delete elm; elm = nullptr; } // Restore the page transfer mode and the content build buffer // reserved size corresponding to each URI defined in structure // _pageBuildMode. if (elm) { for (uint8_t n = 0; n < sizeof(_pageBuildMode) / sizeof(PageTranserModeST); n++) if (!strcmp(_pageBuildMode[n].uri, uri.c_str())) { _responsePage->reserve(_pageBuildMode[n].rSize); _responsePage->chunked(_pageBuildMode[n].transMode); break; } } return elm; }