Merge pull request #57 from Hieromon/enhance/v098

Release v0.9.8
pull/60/head
Hieromon Ikasamo 6 years ago committed by GitHub
commit b13c5e8788
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      .travis.yml
  2. 14
      README.md
  3. 135
      docs/404.html
  4. 385
      docs/acelements.html
  5. 173
      docs/achandling.html
  6. 137
      docs/acintro.html
  7. 293
      docs/acjson.html
  8. 1322
      docs/acupload.html
  9. 177
      docs/advancedusage.html
  10. 163
      docs/api.html
  11. 206
      docs/apiaux.html
  12. 137
      docs/apiconfig.html
  13. 650
      docs/apielements.html
  14. 137
      docs/apiextra.html
  15. 8
      docs/assets/javascripts/application.dc02f8ce.js
  16. 2
      docs/assets/javascripts/lunr/lunr.du.js
  17. 1
      docs/assets/javascripts/lunr/lunr.ja.js
  18. 2
      docs/assets/javascripts/lunr/lunr.jp.js
  19. 1
      docs/assets/javascripts/lunr/lunr.nl.js
  20. 1
      docs/assets/javascripts/lunr/lunr.th.js
  21. 1
      docs/assets/javascripts/lunr/wordcut.js
  22. 1
      docs/assets/javascripts/modernizr.01ccdecf.js
  23. 1
      docs/assets/javascripts/modernizr.1f0bcf2b.js
  24. 1
      docs/assets/stylesheets/application.3020aac5.css
  25. 1
      docs/assets/stylesheets/application.982221ab.css
  26. 135
      docs/basicusage.html
  27. 164
      docs/changelog.html
  28. 1185
      docs/credit.html
  29. 159
      docs/datatips.html
  30. 330
      docs/faq.html
  31. 135
      docs/gettingstarted.html
  32. 137
      docs/howtoembed.html
  33. 973
      docs/images/ac_upload_flow.svg
  34. BIN
      docs/images/acfile.png
  35. BIN
      docs/images/upload.gif
  36. 145
      docs/index.html
  37. 135
      docs/license.html
  38. 157
      docs/lsbegin.html
  39. 135
      docs/menu.html
  40. 137
      docs/menuize.html
  41. 2
      docs/search/search_index.json
  42. 54
      docs/sitemap.xml
  43. BIN
      docs/sitemap.xml.gz
  44. 141
      docs/wojson.html
  45. 162
      examples/FileUpload/FileUpload.ino
  46. 2
      examples/Simple/Simple.ino
  47. 92
      examples/mqttRSSI/mqttRSSI.ino
  48. 9
      examples/mqttRSSI_FS/mqttRSSI_FS.ino
  49. 4
      keywords.txt
  50. 4
      library.json
  51. 2
      library.properties
  52. 7
      mkdocs.yml
  53. 66
      mkdocs/acelements.md
  54. 40
      mkdocs/achandling.md
  55. 38
      mkdocs/acjson.md
  56. 384
      mkdocs/acupload.md
  57. 19
      mkdocs/advancedusage.md
  58. 26
      mkdocs/api.md
  59. 50
      mkdocs/apiaux.md
  60. 122
      mkdocs/apielements.md
  61. 12
      mkdocs/changelog.md
  62. 142
      mkdocs/credit.md
  63. 18
      mkdocs/datatips.md
  64. 78
      mkdocs/faq.md
  65. 973
      mkdocs/images/ac_upload_flow.svg
  66. BIN
      mkdocs/images/acfile.png
  67. BIN
      mkdocs/images/upload.gif
  68. 9
      mkdocs/index.md
  69. 9
      mkdocs/lsbegin.md
  70. 35
      src/AutoConnect.cpp
  71. 13
      src/AutoConnect.h
  72. 525
      src/AutoConnectAux.cpp
  73. 35
      src/AutoConnectAux.h
  74. 416
      src/AutoConnectAuxImpl.h
  75. 38
      src/AutoConnectDefs.h
  76. 7
      src/AutoConnectElement.h
  77. 113
      src/AutoConnectElementBasis.h
  78. 68
      src/AutoConnectElementBasisImpl.h
  79. 192
      src/AutoConnectElementJson.h
  80. 224
      src/AutoConnectElementJsonImpl.h
  81. 65
      src/AutoConnectLabels.h
  82. 119
      src/AutoConnectPage.cpp
  83. 2
      src/AutoConnectPage.h
  84. 38
      src/AutoConnectUpload.h
  85. 145
      src/AutoConnectUploadImpl.h

@ -4,7 +4,7 @@ banches:
language: generic
env:
global:
- IDE_VERSION=1.8.6
- IDE_VERSION=1.8.8
matrix:
- BOARD="esp8266:esp8266:generic:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled,FlashMode=qio,FlashFreq=80"
- BOARD="esp32:esp32:esp32:FlashFreq=80,FlashSize=4M"
@ -23,7 +23,10 @@ before_install:
- if [[ "$BOARD" =~ "esp32:esp32:" ]]; then
arduino --install-boards esp32:esp32;
fi
- arduino --install-library PubSubClient,ArduinoJson:5.13.3,PageBuilder:1.3.2
- arduino --install-library PubSubClient,PageBuilder:1.3.3
- arduino --install-library ArduinoJson:5.13.5
- buildExampleSketch() { arduino --verify --board $BOARD $PWD/examples/$1/$1.ino; }
- arduino --install-library ArduinoJson:6.10.0
- buildExampleSketch() { arduino --verify --board $BOARD $PWD/examples/$1/$1.ino; }
install:
- mkdir -p ~/Arduino/libraries
@ -39,3 +42,4 @@ script:
- buildExampleSketch mqttRSSI
- buildExampleSketch mqttRSSI_FS
- buildExampleSketch mqttRSSI_NA
- buildExampleSketch FileUpload

@ -1,8 +1,8 @@
# AutoConnect for ESP8266/ESP32
[![Build Status](https://travis-ci.org/Hieromon/AutoConnect.svg?branch=master)](https://travis-ci.org/Hieromon/AutoConnect)
[![GitHub release](https://img.shields.io/github/release/Hieromon/AutoConnect.svg)](https://github.com/Hieromon/AutoConnect/releases)
[![arduino-library-badge](https://www.ardu-badge.com/badge/AutoConnect.svg)](https://www.ardu-badge.com/AutoConnect)
[![GitHub release](https://img.shields.io/github/release/Hieromon/AutoConnect.svg)](https://github.com/Hieromon/AutoConnect/releases)
[![Build Status](https://travis-ci.org/Hieromon/AutoConnect.svg?branch=master)](https://travis-ci.org/Hieromon/AutoConnect)
An Arduino library for ESP8266/ESP32 WLAN configuration at run time with web interface.
@ -96,6 +96,16 @@ Full documentation is available on https://Hieromon.github.io/AutoConnect, some
## Change log
### [0.9.8] Apr. 25, 2019
- Supports ArduinoJson 6.9.1 or later.
- Supports allocating JsonDocument buffer to PSRAM on ESP32 with ArduinoJson 6.10.0 or later.
- Supports **operator`[]`** as a shortcut for AutoConnectAux::getElement function.
- Supports **AutoConnectElement::as<T\>** function to easily coding for conversion from an AutoConnectElement to an actual type.
- Supports new element type **AutoConnectFile** and built-in file uploader.
- Supports a **format attribute** with the AutoConnectText element.
- Fixed blank page responds with Configure new.
- Changed menu labels placement in source files structure.
### [0.9.7] Feb. 25, 2019
- Fixed crash in some environments. Thank you @ageurtse
- Supports AutoConnect menu extension by user sketch with **AutoConnectAux**.

@ -36,7 +36,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="/AutoConnect/assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -44,7 +44,7 @@
<link rel="stylesheet" href="/AutoConnect/assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="/AutoConnect/assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="/AutoConnect/assets/stylesheets/application-palette.224b79ff.css">
@ -55,7 +55,7 @@
<script src="/AutoConnect/assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="/AutoConnect/assets/javascripts/modernizr.01ccdecf.js"></script>
@ -223,81 +223,6 @@
<nav class="md-tabs" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="/AutoConnect/index.html" title="Overview" class="md-tabs__link md-tabs__link--active">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="/AutoConnect/acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="/AutoConnect/api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="/AutoConnect/howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -630,12 +555,60 @@
<li class="md-nav__item">
<a href="/AutoConnect/lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="/AutoConnect/lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="/AutoConnect/credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="/AutoConnect/acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -729,7 +702,7 @@
</div>
<script src="/AutoConnect/assets/javascripts/application.b806dc00.js"></script>
<script src="/AutoConnect/assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"/AutoConnect/"}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link md-tabs__link--active">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -618,8 +541,8 @@
</li>
<li class="md-nav__item">
<a href="#autoconnectinput" title="AutoConnectInput" class="md-nav__link">
AutoConnectInput
<a href="#autoconnectfile" title="AutoConnectFile" class="md-nav__link">
AutoConnectFile
</a>
<nav class="md-nav">
@ -651,6 +574,54 @@
label
</a>
</li>
<li class="md-nav__item">
<a href="#store" title=" store" class="md-nav__link">
store
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#autoconnectinput" title="AutoConnectInput" class="md-nav__link">
AutoConnectInput
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#constructor_4" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#name_4" title=" name" class="md-nav__link">
name
</a>
</li>
<li class="md-nav__item">
<a href="#value_4" title=" value" class="md-nav__link">
value
</a>
</li>
<li class="md-nav__item">
<a href="#label_2" title=" label" class="md-nav__link">
label
</a>
</li>
<li class="md-nav__item">
@ -681,14 +652,14 @@
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#constructor_4" title=" Constructor" class="md-nav__link">
<a href="#constructor_5" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#name_4" title=" name" class="md-nav__link">
<a href="#name_5" title=" name" class="md-nav__link">
name
</a>
@ -702,7 +673,7 @@
</li>
<li class="md-nav__item">
<a href="#label_2" title=" label" class="md-nav__link">
<a href="#label_3" title=" label" class="md-nav__link">
label
</a>
@ -736,14 +707,14 @@
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#constructor_5" title=" Constructor" class="md-nav__link">
<a href="#constructor_6" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#name_5" title=" name" class="md-nav__link">
<a href="#name_6" title=" name" class="md-nav__link">
name
</a>
@ -757,7 +728,7 @@
</li>
<li class="md-nav__item">
<a href="#label_3" title=" label" class="md-nav__link">
<a href="#label_4" title=" label" class="md-nav__link">
label
</a>
@ -777,21 +748,21 @@
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#constructor_6" title=" Constructor" class="md-nav__link">
<a href="#constructor_7" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#name_6" title=" name" class="md-nav__link">
<a href="#name_7" title=" name" class="md-nav__link">
name
</a>
</li>
<li class="md-nav__item">
<a href="#value_4" title=" value" class="md-nav__link">
<a href="#value_5" title=" value" class="md-nav__link">
value
</a>
@ -818,21 +789,21 @@
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#constructor_7" title=" Constructor" class="md-nav__link">
<a href="#constructor_8" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#name_7" title=" name" class="md-nav__link">
<a href="#name_8" title=" name" class="md-nav__link">
name
</a>
</li>
<li class="md-nav__item">
<a href="#value_5" title=" value" class="md-nav__link">
<a href="#value_6" title=" value" class="md-nav__link">
value
</a>
@ -843,6 +814,13 @@
style
</a>
</li>
<li class="md-nav__item">
<a href="#format" title=" format" class="md-nav__link">
format
</a>
</li>
</ul>
@ -1078,12 +1056,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -1291,8 +1317,8 @@
</li>
<li class="md-nav__item">
<a href="#autoconnectinput" title="AutoConnectInput" class="md-nav__link">
AutoConnectInput
<a href="#autoconnectfile" title="AutoConnectFile" class="md-nav__link">
AutoConnectFile
</a>
<nav class="md-nav">
@ -1324,6 +1350,54 @@
label
</a>
</li>
<li class="md-nav__item">
<a href="#store" title=" store" class="md-nav__link">
store
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#autoconnectinput" title="AutoConnectInput" class="md-nav__link">
AutoConnectInput
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#constructor_4" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#name_4" title=" name" class="md-nav__link">
name
</a>
</li>
<li class="md-nav__item">
<a href="#value_4" title=" value" class="md-nav__link">
value
</a>
</li>
<li class="md-nav__item">
<a href="#label_2" title=" label" class="md-nav__link">
label
</a>
</li>
<li class="md-nav__item">
@ -1354,14 +1428,14 @@
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#constructor_4" title=" Constructor" class="md-nav__link">
<a href="#constructor_5" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#name_4" title=" name" class="md-nav__link">
<a href="#name_5" title=" name" class="md-nav__link">
name
</a>
@ -1375,7 +1449,7 @@
</li>
<li class="md-nav__item">
<a href="#label_2" title=" label" class="md-nav__link">
<a href="#label_3" title=" label" class="md-nav__link">
label
</a>
@ -1409,14 +1483,14 @@
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#constructor_5" title=" Constructor" class="md-nav__link">
<a href="#constructor_6" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#name_5" title=" name" class="md-nav__link">
<a href="#name_6" title=" name" class="md-nav__link">
name
</a>
@ -1430,7 +1504,7 @@
</li>
<li class="md-nav__item">
<a href="#label_3" title=" label" class="md-nav__link">
<a href="#label_4" title=" label" class="md-nav__link">
label
</a>
@ -1450,21 +1524,21 @@
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#constructor_6" title=" Constructor" class="md-nav__link">
<a href="#constructor_7" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#name_6" title=" name" class="md-nav__link">
<a href="#name_7" title=" name" class="md-nav__link">
name
</a>
</li>
<li class="md-nav__item">
<a href="#value_4" title=" value" class="md-nav__link">
<a href="#value_5" title=" value" class="md-nav__link">
value
</a>
@ -1491,21 +1565,21 @@
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#constructor_7" title=" Constructor" class="md-nav__link">
<a href="#constructor_8" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#name_7" title=" name" class="md-nav__link">
<a href="#name_8" title=" name" class="md-nav__link">
name
</a>
</li>
<li class="md-nav__item">
<a href="#value_5" title=" value" class="md-nav__link">
<a href="#value_6" title=" value" class="md-nav__link">
value
</a>
@ -1516,6 +1590,13 @@
style
</a>
</li>
<li class="md-nav__item">
<a href="#format" title=" format" class="md-nav__link">
format
</a>
</li>
</ul>
@ -1575,6 +1656,7 @@
<li><a href="#autoconnectbutton">AutoConnectButton</a>: Labeled action button</li>
<li><a href="#autoconnectcheckbox">AutoConnectCheckbox</a>: Labeled checkbox</li>
<li><a href="#autoconnectelement-a-basic-class-of-elements">AutoConnectElement</a>: General tag</li>
<li><a href="#autoconnectfile">AutoConnectFile</a>: File uploader</li>
<li><a href="#autoconnectinput">AutoConnectInput</a>: Labeled text input box</li>
<li><a href="#autoconnectradio">AutoConnectRadio</a>: Labeled radio button</li>
<li><a href="#autoconnectselect">AutoConnectSelect</a>: Selection list</li>
@ -1616,6 +1698,7 @@
<li>AutoConnectButton: <strong>AC_Button</strong></li>
<li>AutoConnectCheckbox: <strong>AC_Checkbox</strong> </li>
<li>AutoConnectElement: <strong>AC_Element</strong></li>
<li>AutoConnectFile: <strong>AC_File</strong></li>
<li>AutoConnectInput: <strong>AC_Input</strong></li>
<li>AutoConnectRadio: <strong>AC_Radio</strong></li>
<li>AutoConnectSelect: <strong>AC_Select</strong></li>
@ -1623,7 +1706,20 @@
<li>AutoConnectText: <strong>AC_Text</strong></li>
<li>Uninitialized element: <strong>AC_Unknown</strong></li>
</ul>
<p>Furthermore, to convert an entity that is not an AutoConnectElement to its native type, you must <a href="https://en.cppreference.com/w/cpp/language/reinterpret_cast">re-interpret</a> that type with c++.</p>
<p>Furthermore, to convert an entity that is not an AutoConnectElement to its native type, you must <a href="https://en.cppreference.com/w/cpp/language/reinterpret_cast">re-interpret</a> that type with c++. Or, you can be coding the sketch more easily with using the <a href="apielements.html#ast62"><strong>as&lt;T></strong></a> function.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectAux</span> <span style="color: #f8f8f2">customPage;</span>
<span style="color: #f8f8f2">AutoConnectElementVT</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">elements</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">customPage.getElements();</span>
<span style="color: #66d9ef">for</span> <span style="color: #f8f8f2">(AutoConnectElement</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">elm</span> <span style="color: #f8f8f2">:</span> <span style="color: #f8f8f2">elements)</span> <span style="color: #f8f8f2">{</span>
<span style="color: #66d9ef">if</span> <span style="color: #f8f8f2">(elm.type()</span> <span style="color: #f92672">==</span> <span style="color: #f8f8f2">AC_Text)</span> <span style="color: #f8f8f2">{</span>
<span style="background-color: #49483e"> <span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">text</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">customPage[elm.name].as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">();</span>
</span> <span style="color: #f8f8f2">text.style</span> <span style="color: #f92672">=</span> <span style="color: #e6db74">&quot;color:gray;&quot;</span><span style="color: #f8f8f2">;</span>
<span style="color: #75715e">// Or, it is also possible to write the code further reduced as follows.</span>
<span style="color: #75715e">// customPage[elm.name].as&lt;AutoConnectText&gt;().style = &quot;color:gray;&quot;;</span>
<span style="color: #f8f8f2">}</span>
<span style="color: #f8f8f2">}</span>
</pre></div>
<h2 id="autoconnectbutton">AutoConnectButton<a class="headerlink" href="#autoconnectbutton" title="Permanent link">&para;</a></h2>
<p>AutoConnectButton generates an HTML <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">button</span> <span style="color: #a6e22e">type</span><span style="color: #f92672">=</span><span style="color: #e6db74">&quot;button&quot;</span><span style="color: #f8f8f2">&gt;</span></code> tag and locates a clickable button to a custom Web page. Currently AutoConnectButton corresponds only to name, value, an <em>onclick</em> attribute of HTML button tag. An <em>onclick</em> attribute is generated from an <code>action</code> member variable of the AutoConnectButton, which is mostly used with a JavaScript to activate a script.</p>
<p><i class="fa fa-eye"></i> <strong>Sample</strong><br>
@ -1670,20 +1766,46 @@
Only <i class="far fa-square"></i> will be displayed if a label is not specified.</p>
<h3 id="checked"><i class="fa fa-caret-right"></i> checked<a class="headerlink" href="#checked" title="Permanent link">&para;</a></h3>
<p>A checked is a Boolean value and indicates the checked status of the checkbox. The value of the checked checkbox element is packed in the query string and sent.</p>
<h2 id="autoconnectfile">AutoConnectFile<a class="headerlink" href="#autoconnectfile" title="Permanent link">&para;</a></h2>
<p>AutoConnectFile generates asn HTML <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">input</span> <span style="color: #a6e22e">type</span><span style="color: #f92672">=</span><span style="color: #e6db74">&quot;file&quot;</span><span style="color: #f8f8f2">&gt;</span></code> tag and a <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">label</span><span style="color: #f8f8f2">&gt;</span></code> tag. AutoConnectFile enables file upload from the client through the web browser to ESP8266/ESP32 module. You can select the flash in the module, external SD device or any output destination as the storage of the uploaded file.</p>
<p><i class="fa fa-eye"></i> <strong>Sample</strong><br>
<small><strong><code>AutoConnectFile file("file", "", "Upload:", AC_File_FS)</code></strong></small></p>
<p><small>On the page:</small><br><img src="images/acfile.png"></p>
<h3 id="constructor_3"><i class="fa fa-edit"></i> Constructor<a class="headerlink" href="#constructor_3" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectFile(</span><span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">name,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">value,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">label,</span> <span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">ACFile_t</span> <span style="color: #f8f8f2">store)</span>
</pre></div>
<h3 id="name_3"><i class="fa fa-caret-right"></i> name<a class="headerlink" href="#name_3" title="Permanent link">&para;</a></h3>
<p>It is the <code>name</code> of the AutoConnectFile element and matches the name attribute of the input tag. It also becomes the parameter name of the query string when submitted.</p>
<h3 id="value_3"><i class="fa fa-caret-right"></i> value<a class="headerlink" href="#value_3" title="Permanent link">&para;</a></h3>
<p>File name to be upload. The value contains the value entered by the client browser to the <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">input</span> <span style="color: #a6e22e">type</span><span style="color: #f92672">=</span><span style="color: #e6db74">&quot;file&quot;</span><span style="color: #f8f8f2">&gt;</span></code> tag and is read-only. Even If you give a value to the constructor, it does not affect as an initial value like a default file name.</p>
<h3 id="label_1"><i class="fa fa-caret-right"></i> label<a class="headerlink" href="#label_1" title="Permanent link">&para;</a></h3>
<p>A <code>label</code> is an optional string. A label is always arranged on the left side of the input box. Specification of a label will generate an HTML <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">label</span><span style="color: #f8f8f2">&gt;</span></code> tag with an id attribute. The input box and the label are connected by the id attribute.</p>
<h3 id="store"><i class="fa fa-caret-right"></i> store<a class="headerlink" href="#store" title="Permanent link">&para;</a></h3>
<p>Specifies the destination to save the uploaded file. The destination can be specified the following values in the <em>ACFile_t</em> enumeration type.</p>
<ul>
<li><strong><code>AC_File_FS</code></strong> : Save as the SPIFFS file in flash of ESP8266/ESP32 module.</li>
<li><strong><code>AC_File_SD</code></strong> : Save to an external SD device connected to ESP8266/ESP32 module.</li>
<li><strong><code>AC_File_Extern</code></strong> : Pass the content of the uploaded file to the uploader which is declared by the sketch individually. Its uploader must inherit <a href="acupload.html#to-upload-to-a-device-other-than-flash-or-sd"><strong>AutoConnectUploadHandler</strong></a> class and implements <em>_open</em>, <em>_write</em> and <em>_close</em> function.</li>
</ul>
<div class="admonition note">
<p class="admonition-title">Built-in uploader is ready.</p>
<p>AutoConnect already equips the built-in uploader for saving to the SPIFFS as AC_File_FS and the external SD as AC_File_SD. It is already implemented inside AutoConnect and will store uploaded file automatically.</p>
</div>
<h2 id="autoconnectinput">AutoConnectInput<a class="headerlink" href="#autoconnectinput" title="Permanent link">&para;</a></h2>
<p>AutoConnectInput generates an HTML <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">input</span> <span style="color: #a6e22e">type</span><span style="color: #f92672">=</span><span style="color: #e6db74">&quot;text&quot;</span><span style="color: #f8f8f2">&gt;</span></code> tag and a <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">label</span><span style="color: #f8f8f2">&gt;</span></code> tag. It can also have a placeholder. The value of the input box is passed to the destination in the query string and can be retrieved programmatically. You can also update from the sketches.</p>
<p><i class="fa fa-eye"></i> <strong>Sample</strong><br>
<small><strong><code>AutoConnectInput input("input", "", "Server", "MQTT broker server");</code></strong></small></p>
<p><small>On the page:</small><br><img src="images/acinput.png"></p>
<h3 id="constructor_3"><i class="fa fa-edit"></i> Constructor<a class="headerlink" href="#constructor_3" title="Permanent link">&para;</a></h3>
<h3 id="constructor_4"><i class="fa fa-edit"></i> Constructor<a class="headerlink" href="#constructor_4" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectInput(</span><span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">name,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">value,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">label,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">pattern,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">placeholder)</span>
</pre></div>
<h3 id="name_3"><i class="fa fa-caret-right"></i> name<a class="headerlink" href="#name_3" title="Permanent link">&para;</a></h3>
<h3 id="name_4"><i class="fa fa-caret-right"></i> name<a class="headerlink" href="#name_4" title="Permanent link">&para;</a></h3>
<p>It is the <code>name</code> of the AutoConnectInput element and matches the name attribute, the id attribute of the input tag. It also becomes the parameter name of the query string when submitted.</p>
<h3 id="value_3"><i class="fa fa-caret-right"></i> value<a class="headerlink" href="#value_3" title="Permanent link">&para;</a></h3>
<h3 id="value_4"><i class="fa fa-caret-right"></i> value<a class="headerlink" href="#value_4" title="Permanent link">&para;</a></h3>
<p>It becomes a string value of the <code>value</code> attribute of an HTML <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">input</span> <span style="color: #a6e22e">type</span><span style="color: #f92672">=</span><span style="color: #e6db74">&quot;text&quot;</span><span style="color: #f8f8f2">&gt;</span></code> tag. The text entered from the custom Web page will be grouped in the query string of the form submission and the string set before accessing the page will be displayed as the initial value.</p>
<h3 id="label_1"><i class="fa fa-caret-right"></i> label<a class="headerlink" href="#label_1" title="Permanent link">&para;</a></h3>
<h3 id="label_2"><i class="fa fa-caret-right"></i> label<a class="headerlink" href="#label_2" title="Permanent link">&para;</a></h3>
<p>A <code>label</code> is an optional string. A label is always arranged on the left side of the input box. Specification of a label will generate an HTML <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">label</span><span style="color: #f8f8f2">&gt;</span></code> tag with an id attribute. The input box and the label are connected by the id attribute.</p>
<h3 id="pattern"><i class="fa fa-caret-right"></i> pattern<a class="headerlink" href="#pattern" title="Permanent link">&para;</a></h3>
<p>A <code>pattern</code> specifies a <a href="https://www.w3schools.com/js/js_regexp.asp">regular expression</a> that the AutoConnectInput element's value is checked against on form submission. If it is invalid, the background color will change, but it will be sent even if the data format does not match. To check whether the entered value matches the pattern, use the <a href="apielements.html#isvalid">isValid</a> function.</p>
@ -1712,15 +1834,15 @@ Only <i class="far fa-square"></i> will be displayed if a label is not specified
<p><i class="fa fa-eye"></i> <strong>Sample</strong><br>
<small><strong><code>AutoConnectRadio radio("radio", { "30 sec.", "60 sec.", "180 sec." }, "Update period", AC_Vertical, 1);</code></strong></small></p>
<p><small>On the page:</small><br><img src="images/acradio.png"></p>
<h3 id="constructor_4"><i class="fa fa-edit"></i> Constructor<a class="headerlink" href="#constructor_4" title="Permanent link">&para;</a></h3>
<h3 id="constructor_5"><i class="fa fa-edit"></i> Constructor<a class="headerlink" href="#constructor_5" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectRadio(</span><span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">name,</span> <span style="color: #f8f8f2">std</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">vector</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">String</span><span style="color: #f92672">&gt;</span> <span style="color: #66d9ef">const</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">values,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">label,</span> <span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">ACArrange_t</span> <span style="color: #f8f8f2">order,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">uint8_t</span> <span style="color: #f8f8f2">checked)</span>
</pre></div>
<h3 id="name_4"><i class="fa fa-caret-right"></i> name<a class="headerlink" href="#name_4" title="Permanent link">&para;</a></h3>
<h3 id="name_5"><i class="fa fa-caret-right"></i> name<a class="headerlink" href="#name_5" title="Permanent link">&para;</a></h3>
<p>It is the <code>name</code> of the AutoConnectRadio element and matches the name attribute of the input tags. It also becomes the parameter name of the query string when submitted.</p>
<h3 id="values"><i class="fa fa-caret-right"></i> values<a class="headerlink" href="#values" title="Permanent link">&para;</a></h3>
<p>A <code>values</code> is an array of String type for the radio button options which as actually <a href="https://en.cppreference.com/w/cpp/container/vector">std::vector</a>. It is an initialization list can be used. The input tags will be generated from each entry in the values, the amount of which is the same as the number of items in <code>values</code>.</p>
<h3 id="label_2"><i class="fa fa-caret-right"></i> label<a class="headerlink" href="#label_2" title="Permanent link">&para;</a></h3>
<h3 id="label_3"><i class="fa fa-caret-right"></i> label<a class="headerlink" href="#label_3" title="Permanent link">&para;</a></h3>
<p>A label is an optional string. A label will be arranged in the left or top of the radio buttons according to the <strong>order</strong>. Specification of a label will generate an HTML <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">label</span><span style="color: #f8f8f2">&gt;</span></code> tag with an <code>id</code> attribute. The radio buttons and the label are connected by the id attribute.</p>
<h3 id="order"><i class="fa fa-caret-right"></i> order<a class="headerlink" href="#order" title="Permanent link">&para;</a></h3>
<p>A <code>order</code> specifies the direction to arrange the radio buttons. It is a value of type <code>ACArrange_t</code> and accepts one of the following:</p>
@ -1736,28 +1858,28 @@ Only <i class="far fa-square"></i> will be displayed if a label is not specified
<p><i class="fa fa-eye"></i> <strong>Sample</strong><br>
<small><strong><code>AutoConnectSelect select("select", { String("Europe/London"), String("Europe/Berlin"), String("Europe/Helsinki"), String("Europe/Moscow"), String("Asia/Dubai") }, "Select TZ name");</code></strong></small></p>
<p><small>On the page:</small><br><img src="images/acselect.png"></p>
<h3 id="constructor_5"><i class="fa fa-edit"></i> Constructor<a class="headerlink" href="#constructor_5" title="Permanent link">&para;</a></h3>
<h3 id="constructor_6"><i class="fa fa-edit"></i> Constructor<a class="headerlink" href="#constructor_6" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectSelect(</span><span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">name,</span> <span style="color: #f8f8f2">std</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">vector</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">String</span><span style="color: #f92672">&gt;</span> <span style="color: #66d9ef">const</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">options,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">label)</span>
</pre></div>
<h3 id="name_5"><i class="fa fa-caret-right"></i> name<a class="headerlink" href="#name_5" title="Permanent link">&para;</a></h3>
<h3 id="name_6"><i class="fa fa-caret-right"></i> name<a class="headerlink" href="#name_6" title="Permanent link">&para;</a></h3>
<p>It is the <code>name</code> of the AutoConnectSelect element and matches the name attribute of the select tags.</p>
<h3 id="options"><i class="fa fa-caret-right"></i> options<a class="headerlink" href="#options" title="Permanent link">&para;</a></h3>
<p>An <code>options</code> is an array of String type for the options which as actually <a href="https://en.cppreference.com/w/cpp/container/vector">std::vector</a> for an HTML <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">option</span><span style="color: #f8f8f2">&gt;</span></code> tag. It is an initialization list can be used. The option tags will be generated from each entry in the options, the amount of which is the same as the number of items in an <code>options</code>.</p>
<h3 id="label_3"><i class="fa fa-caret-right"></i> label<a class="headerlink" href="#label_3" title="Permanent link">&para;</a></h3>
<h3 id="label_4"><i class="fa fa-caret-right"></i> label<a class="headerlink" href="#label_4" title="Permanent link">&para;</a></h3>
<p>A <code>label</code> is an optional string. A label is always arranged on the left side of the drop-down list. Specification of a label will generate an HTML <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">label</span><span style="color: #f8f8f2">&gt;</span></code> tag with an id attribute. The select tag and the label are connected by the id attribute.</p>
<h2 id="autoconnectsubmit">AutoConnectSubmit<a class="headerlink" href="#autoconnectsubmit" title="Permanent link">&para;</a></h2>
<p>AutoConnectSubmit generates an HTML <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">input</span> <span style="color: #a6e22e">type</span><span style="color: #f92672">=</span><span style="color: #e6db74">&quot;button&quot;</span><span style="color: #f8f8f2">&gt;</span></code> tag attached <code class="codehilite">onclick</code> attribute. The native code of the <code class="codehilite">onclick</code> attribute is the submission of the form with the <strong>POST</strong> method.</p>
<p><i class="fa fa-eye"></i> <strong>Sample</strong><br>
<small><strong><code>AutoConnectSubmit submit("submit", "Save", "/mqtt_save");</code></strong></small></p>
<p><small>On the page:</small><br><img src="images/acsubmit.png"></p>
<h3 id="constructor_6"><i class="fa fa-edit"></i> Constructor<a class="headerlink" href="#constructor_6" title="Permanent link">&para;</a></h3>
<h3 id="constructor_7"><i class="fa fa-edit"></i> Constructor<a class="headerlink" href="#constructor_7" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectSubmit(</span><span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">name,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">value,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">uri)</span>
</pre></div>
<h3 id="name_6"><i class="fa fa-caret-right"></i> name<a class="headerlink" href="#name_6" title="Permanent link">&para;</a></h3>
<h3 id="name_7"><i class="fa fa-caret-right"></i> name<a class="headerlink" href="#name_7" title="Permanent link">&para;</a></h3>
<p>It is the <code>name</code> of the AutoConnectSubmit element and matches the name attribute of the input tag.</p>
<h3 id="value_4"><i class="fa fa-caret-right"></i> value<a class="headerlink" href="#value_4" title="Permanent link">&para;</a></h3>
<h3 id="value_5"><i class="fa fa-caret-right"></i> value<a class="headerlink" href="#value_5" title="Permanent link">&para;</a></h3>
<p>It becomes a string of the <code>value</code> attribute of an HTML <code class="codehilite"><span style="color: #f8f8f2">&lt;</span><span style="color: #f92672">input</span> <span style="color: #a6e22e">type</span><span style="color: #f92672">=</span><span style="color: #e6db74">&quot;button&quot;</span><span style="color: #f8f8f2">&gt;</span></code> tag. The <code>value</code> will be displayed as a label of the button.</p>
<h3 id="uri"><i class="fa fa-caret-right"></i> uri<a class="headerlink" href="#uri" title="Permanent link">&para;</a></h3>
<p>A <code>uri</code> specifies the URI to send form data when the button declared by AutoConnectSubmit is clicked.</p>
@ -1768,27 +1890,30 @@ Only <i class="far fa-square"></i> will be displayed if a label is not specified
<p><i class="fa fa-eye"></i> <strong>Sample</strong><br>
<small><strong><code>AutoConnectText text("text", "Publishing the WiFi signal strength to MQTT channel. RSSI value of ESP8266 to the channel created on ThingSpeak", "font-family:serif;color:#4682b4;");</code></strong></small></p>
<p><small>On the page:</small><br><img src="images/actext.png"></p>
<h3 id="constructor_7"><i class="fa fa-edit"></i> Constructor<a class="headerlink" href="#constructor_7" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectText(</span><span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">name,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">value,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">style)</span>
<h3 id="constructor_8"><i class="fa fa-edit"></i> Constructor<a class="headerlink" href="#constructor_8" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectText(</span><span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">name,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">value,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">style,</span> <span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">format)</span>
</pre></div>
<h3 id="name_7"><i class="fa fa-caret-right"></i> name<a class="headerlink" href="#name_7" title="Permanent link">&para;</a></h3>
<h3 id="name_8"><i class="fa fa-caret-right"></i> name<a class="headerlink" href="#name_8" title="Permanent link">&para;</a></h3>
<p>A <code>name</code> does not exist in the generated HTML. It provides only a means of accessing elements with the sketches.</p>
<h3 id="value_5"><i class="fa fa-caret-right"></i> value<a class="headerlink" href="#value_5" title="Permanent link">&para;</a></h3>
<h3 id="value_6"><i class="fa fa-caret-right"></i> value<a class="headerlink" href="#value_6" title="Permanent link">&para;</a></h3>
<p>It becomes content and also can contain the native HTML code, but remember that your written code is enclosed by the div tag.</p>
<h3 id="style"><i class="fa fa-caret-right"></i> style<a class="headerlink" href="#style" title="Permanent link">&para;</a></h3>
<p>A <code>style</code> specifies the qualification style to give to the content and can use the style attribute format as it is.</p>
<h3 id="format"><i class="fa fa-caret-right"></i> format<a class="headerlink" href="#format" title="Permanent link">&para;</a></h3>
<p>A <code>format</code> is a pointer to a null-terminated multibyte string specifying how to interpret the value. It specifies the conversion format when outputting values. The format string conforms to C-style printf library functions, but depends on the espressif sdk implementation. The conversion specification is valid only in <strong>%s</strong> format. (Left and Right justification, width are also valid.)</p>
<h2 id="how-to-coding-for-the-elements">How to coding for the elements<a class="headerlink" href="#how-to-coding-for-the-elements" title="Permanent link">&para;</a></h2>
<h3 id="declaration-for-the-elements-in-sketches"><i class="fa fa-edit"></i> Declaration for the elements in Sketches<a class="headerlink" href="#declaration-for-the-elements-in-sketches" title="Permanent link">&para;</a></h3>
<p>Variables of each AutoConnetElement can be declared with macros. By using the macros, you can treat element name that is String type as variable in sketches.<sup id="fnref:2"><a class="footnote-ref" href="#fn:2" rel="footnote">2</a></sup></p>
<p>ACElement ( <em>name</em> <small>[</small> , <em>value</em> <small>]</small> )</p>
<p>ACButton ( <em>name</em> <small>[</small> , <em>value</em> <small>]</small> <small>[</small> , <em>action</em> <small>]</small> )</p>
<p>ACCheckbox ( <em>name</em> <small>[</small> , <em>value</em> <small>]</small> <small>[</small> , <em>label</em> <small>]</small> <small>[</small> , <strong>true</strong> | <strong>false</strong> <small>]</small> )</p>
<p>ACFile ( <em>name</em> <small>[</small> , <em>value</em> <small>]</small> <small>[</small> , <em>label</em> <small>]</small> <small>[</small> , <strong>AC_File_FS</strong> | <strong>AC_File_SD</strong> | <strong>AC_File_Extern</strong> <small>]</small> )</p>
<p>ACInput ( <em>name</em> <small>[</small> , <em>value</em> <small>]</small> <small>[</small> , <em>label</em> <small>]</small> <small>[</small> , <em>pattern</em> <small>]</small> <small>[</small> , <em>placeholder</em> <small>]</small> )</p>
<p>ACRadio ( <em>name</em> <small>[</small> , <em>values</em> <small>]</small> <small>[</small> , <em>label</em> <small>]</small> <small>[</small> , <strong>AC_Horizontal</strong> | <strong>AC_Vertical</strong> <small>]</small> <small>[</small> , <em>checked</em> <small>]</small> )</p>
<p>ACSelect ( <em>name</em> <small>[</small> , <em>options</em> <small>]</small> <small>[</small> , <em>label</em> <small>]</small> )</p>
<p>ACSubmit ( <em>name</em> <small>[</small> , <em>value</em> <small>]</small> <small>[</small> , <em>uri</em> <small>]</small> )</p>
<p>ACText ( <em>name</em> <small>[</small> , <em>value</em> <small>]</small> <small>[</small> , <em>style</em> <small>]</small> )</p>
<p>ACText ( <em>name</em> <small>[</small> , <em>value</em> <small>]</small> <small>[</small> , <em>style</em> <small>]</small> <small>[</small> , <em>format</em> <small>]</small> )</p>
<div class="admonition memo">
<p class="admonition-title">Declaration macro usage</p>
<p>For example, <em>AutoConnectText</em> can be declared using macros.
@ -1900,7 +2025,7 @@ equals by using <em>ACText</em> macro.<br>
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link md-tabs__link--active">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -824,12 +747,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -1118,7 +1089,19 @@ AutoConnectElements contained in AutoConnectAux object are uniquely identified b
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectElementVT</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">getElements(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">)</span>
</pre></div>
<p>The <a href="apiaux.html#getelement"><strong>getElement</strong></a> function returns an AutoConnectElement with the specified name as a key. When you use this function, you need to know the type of AutoConnectElement in advance. To retrieve an AutoConnectElement by specifying its type, use the following method.</p>
<p>The <a href="apiaux.html#getelement"><strong>getElement</strong></a> function returns an AutoConnectElement with the specified name as a key. When you use this function, you need to know the type of AutoConnectElement in advance and specify its type &lt;T> to an argument of the getElement. A type of &lt;T> can be specified as follows.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectButton</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectButton</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">String</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">name)</span>
<span style="color: #f8f8f2">AutoConnectCheckbox</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectCheckbox</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">String</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">name)</span>
<span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">String</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">name)</span>
<span style="color: #f8f8f2">AutoConnectFile</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectFile</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">String</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">name)</span>
<span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">String</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">name)</span>
<span style="color: #f8f8f2">AutoConnectRadio</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectRadio</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">String</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">name)</span>
<span style="color: #f8f8f2">AutoConnectSelect</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectSelect</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">String</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">name)</span>
<span style="color: #f8f8f2">AutoConnectSubmit</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectSubmit</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">String</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">name)</span>
<span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">String</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">name)</span>
</pre></div>
<p>To retrieve an AutoConnectElement by specifying its type, use the following method.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectAux</span> <span style="color: #f8f8f2">aux;</span>
<span style="color: #f8f8f2">aux.load(</span><span style="color: #e6db74">&quot;SOME_JSON_DOCUMENT&quot;</span><span style="color: #f8f8f2">);</span>
@ -1138,6 +1121,28 @@ AutoConnectElements contained in AutoConnectAux object are uniquely identified b
<span style="color: #f8f8f2">Serial.println(text.value);</span>
</pre></div>
<p>You can also use the <a href="apiaux.html#operator">operator <strong><code>[]</code></strong> of AutoConnectAux</a> as another way to get the desired element. An operator <strong><code>[]</code></strong> is a shortcut for <a href="apiaux.html#getelement">getElement</a> function with the reference casting and makes simplify the sketch code and treats like an array with the elements placed on a custom Web page. Its argument is the name of the element to be acquired similarly to getElement function. In the sketch, by combining the <a href="apielements.html#ast62"><strong>AutoConnectElement::as&lt;T></strong></a> function with the operator <code>[]</code>, you can access the AutoConnectElements reference according to its actual type. For example, the following sketch code returns the same as a reference of AutoConnectText element as the <code>caption</code>.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnect</span> <span style="color: #f8f8f2">portal;</span>
<span style="color: #f8f8f2">portal.load(auxJson);</span>
<span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">aux</span> <span style="color: #f92672">=</span> <span style="color: #f92672">*</span><span style="color: #f8f8f2">portal.aux(</span><span style="color: #e6db74">&quot;/page1&quot;</span><span style="color: #f8f8f2">);</span>
<span style="background-color: #49483e"><span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">text1</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux.getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #e6db74">&quot;caption&quot;</span><span style="color: #f8f8f2">);</span>
</span><span style="background-color: #49483e"><span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">text2</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux[</span><span style="color: #e6db74">&quot;caption&quot;</span><span style="color: #f8f8f2">].as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">();</span>
</span></pre></div>
<div class="admonition note">
<p class="admonition-title">Need cast to convert to the actual type</p>
<p>An operator <code>[]</code> returns a referene of an AutoConnectElement. It is necessary to convert the type according to the actual element type with <a href="apielements.html#ast62">AutoConnectElement::as&lt;T></a> functon.
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectButton</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectButton</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">()</span>
<span style="color: #f8f8f2">AutoConnectCheckbox</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectCheckbox</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">()</span>
<span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">()</span>
<span style="color: #f8f8f2">AutoConnectFile</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectFile</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">()</span>
<span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">()</span>
<span style="color: #f8f8f2">AutoConnectRadio</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectRadio</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">()</span>
<span style="color: #f8f8f2">AutoConnectSelect</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectSelect</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">()</span>
<span style="color: #f8f8f2">AutoConnectSubmit</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectSubmit</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">()</span>
<span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">()</span>
</pre></div></p>
</div>
<p>To get all the AutoConnectElements in an AutoConnectAux object use the <a href="apiaux.html#getelements"><strong>getElements</strong></a> function. This function returns the vector of the reference wrapper as <strong>AutoConnectElementVT</strong> to all AutoConnectElements registered in the AutoConnectAux.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectElementVT</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">getElements(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">)</span>
</pre></div>
@ -1726,7 +1731,7 @@ ESP8266WebServer class will parse the query string and rebuilds its arguments wh
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link md-tabs__link--active">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -716,12 +639,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -1089,7 +1060,7 @@ The following JSON code and sketch will execute the custom Web page as an exampl
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link md-tabs__link--active">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -582,6 +505,13 @@
ACElement
</a>
</li>
<li class="md-nav__item">
<a href="#acfile" title=" ACFile" class="md-nav__link">
ACFile
</a>
</li>
<li class="md-nav__item">
@ -634,6 +564,53 @@
Loading JSON document
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#loading-from-the-streamed-file" title=" Loading from the streamed file" class="md-nav__link">
Loading from the streamed file
</a>
</li>
<li class="md-nav__item">
<a href="#adjust-the-json-document-buffer-size" title=" Adjust the JSON document buffer size" class="md-nav__link">
Adjust the JSON document buffer size
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#autoconnect_jsonbuffer_size" title="AUTOCONNECT_JSONBUFFER_SIZE" class="md-nav__link">
AUTOCONNECT_JSONBUFFER_SIZE
</a>
</li>
<li class="md-nav__item">
<a href="#autoconnect_jsondocument_size" title="AUTOCONNECT_JSONDOCUMENT_SIZE" class="md-nav__link">
AUTOCONNECT_JSONDOCUMENT_SIZE
</a>
</li>
<li class="md-nav__item">
<a href="#autoconnect_jsonpsram_size" title="AUTOCONNECT_JSONPSRAM_SIZE" class="md-nav__link">
AUTOCONNECT_JSONPSRAM_SIZE
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
@ -832,12 +809,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -997,6 +1022,13 @@
ACElement
</a>
</li>
<li class="md-nav__item">
<a href="#acfile" title=" ACFile" class="md-nav__link">
ACFile
</a>
</li>
<li class="md-nav__item">
@ -1049,6 +1081,53 @@
Loading JSON document
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#loading-from-the-streamed-file" title=" Loading from the streamed file" class="md-nav__link">
Loading from the streamed file
</a>
</li>
<li class="md-nav__item">
<a href="#adjust-the-json-document-buffer-size" title=" Adjust the JSON document buffer size" class="md-nav__link">
Adjust the JSON document buffer size
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#autoconnect_jsonbuffer_size" title="AUTOCONNECT_JSONBUFFER_SIZE" class="md-nav__link">
AUTOCONNECT_JSONBUFFER_SIZE
</a>
</li>
<li class="md-nav__item">
<a href="#autoconnect_jsondocument_size" title="AUTOCONNECT_JSONDOCUMENT_SIZE" class="md-nav__link">
AUTOCONNECT_JSONDOCUMENT_SIZE
</a>
</li>
<li class="md-nav__item">
<a href="#autoconnect_jsonpsram_size" title="AUTOCONNECT_JSONPSRAM_SIZE" class="md-nav__link">
AUTOCONNECT_JSONPSRAM_SIZE
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
@ -1204,6 +1283,11 @@
</dd>
<dd>
<ul>
<li>AutoConnectFile: <a href="#acfile"><strong>ACFile</strong></a></li>
</ul>
</dd>
<dd>
<ul>
<li>AutoConnectInput: <a href="#acinput"><strong>ACInput</strong></a></li>
</ul>
</dd>
@ -1269,6 +1353,27 @@
</ul>
</dd>
</dl>
<h4 id="acfile"><i class="fa fa-caret-right"></i> ACFile<a class="headerlink" href="#acfile" title="Permanent link">&para;</a></h4>
<dl>
<dd>
<ul>
<li><strong>value</strong> : The file name of the upload file will be stored. The <code>value</code> is read-only and will be ignored if specified.</li>
</ul>
</dd>
<dd>
<ul>
<li><strong>label</strong> : Specifies a label of the file selection box. Its placement is always to the left of the file selection box.</li>
</ul>
</dd>
<dd>
<ul>
<li><strong>store</strong> : Specifies the destination to save the uploaded file. Its value accepts one of the following:<p>
<b>fs</b>&nbsp;: Save as the SPIFFS file in flash of ESP8266/ESP32 module.<br>
<b>sd</b>&nbsp;: Save to an external SD device connected to ESP8266/ESP32 module.<br>
<b>extern</b>&nbsp;: Pass the content of the uploaded file to the uploader which is declared by the sketch individually. Its uploader must inherit <a href="acupload.html#to-upload-to-a-device-other-than-flash-or-sd"><strong>AutoConnectUploadHandler</strong></a> class and implements <em>_open</em>, <em>_write</em> and <em>_close</em> function.</p></li>
</ul>
</dd>
</dl>
<h4 id="acinput"><i class="fa fa-caret-right"></i> ACInput<a class="headerlink" href="#acinput" title="Permanent link">&para;</a></h4>
<dl>
<dd>
@ -1350,12 +1455,18 @@
<li><strong>style</strong> : Specifies the qualification style to give to the content and can use the style attribute format as it is.</li>
</ul>
</dd>
<dd>
<ul>
<li><strong>format</strong> : Specifies how to interpret the value. It specifies the conversion format when outputting values. The format string conforms to the C-style printf library functions, but depends on the espressif sdk implementation. The conversion specification is valid only for <strong>%s</strong> format. (Left and Right justification, width are also valid.)</li>
</ul>
</dd>
</dl>
<div class="admonition caution">
<p class="admonition-title">AutoConnect's JSON parsing process is not perfect</p>
<p>It is based on ArduinoJson, but the process is simplified to save memory. As a result, even if there is an unnecessary key, it will not be an error. It is ignored.</p>
<p>It is based on analysis by ArduinoJson, but the semantic analysis is simplified to save memory. Consequently, it is not an error that a custom Web page JSON document to have unnecessary keys. It will be ignored.</p>
</div>
<h2 id="loading-json-document">Loading JSON document<a class="headerlink" href="#loading-json-document" title="Permanent link">&para;</a></h2>
<h3 id="loading-from-the-streamed-file"><i class="fa fa-caret-right"></i> Loading from the streamed file<a class="headerlink" href="#loading-from-the-streamed-file" title="Permanent link">&para;</a></h3>
<p>AutoConnect supports loading of JSON document from the following instances:</p>
<ul>
<li>String</li>
@ -1399,6 +1510,20 @@ An example of using each function is as follows.
<span style="color: #f8f8f2">aux.close();</span>
</pre></div></p>
<p>AutoConnect passes the given JSON document directly to the <a href="https://arduinojson.org/v5/api/jsonbuffer/parseobject/"><strong>parseObject()</strong></a> function of the ArduinoJson library for parsing. Therefore, the constraint of the parseObject() function is applied as it is in the parsing of the JSON document for the AutoConnect. That is, if the JSON string is read-only, duplicating the input string occurs and consumes more memory.</p>
<h3 id="adjust-the-json-document-buffer-size"><i class="fa fa-caret-right"></i> Adjust the JSON document buffer size<a class="headerlink" href="#adjust-the-json-document-buffer-size" title="Permanent link">&para;</a></h3>
<p>AutoConnect uses ArduinoJson library's dynamic buffer to parse JSON documents. Its dynamic buffer allocation scheme depends on the version 5 or version 6 of ArduinoJson library. Either version must have enough buffer to parse the custom web page's JSON document successfully. AutoConnect has the following three constants internally to complete the parsing as much as possible in both ArduinoJson version. These constants are macro defined in <a href="https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDefs.h">AutoConnectDefs.h</a>.</p>
<p>If memory insufficiency occurs during JSON document parsing, you can adjust these constants to avoid insufficiency by using the <a href="https://arduinojson.org/v6/assistant/">JsonAssistant</a> with deriving the required buffer size in advance.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #75715e">#define AUTOCONNECT_JSONBUFFER_SIZE 256</span>
<span style="color: #75715e">#define AUTOCONNECT_JSONDOCUMENT_SIZE (8 * 1024)</span>
<span style="color: #75715e">#define AUTOCONNECT_JSONPSRAM_SIZE (16* 1024)</span>
</pre></div>
<h4 id="autoconnect_jsonbuffer_size">AUTOCONNECT_JSONBUFFER_SIZE<a class="headerlink" href="#autoconnect_jsonbuffer_size" title="Permanent link">&para;</a></h4>
<p>This is a unit size constant of <a href="https://arduinojson.org/v5/faq/what-are-the-differences-between-staticjsonbuffer-and-dynamicjsonbuffer/">DynamicJsonBuffer</a> and works when the library used is ArduinoJson version 5. A buffer size of the JSON document increases with this unit. This value relates to the impact of the fragmented heap area. If it is too large, may occur run-out of memory.</p>
<h4 id="autoconnect_jsondocument_size">AUTOCONNECT_JSONDOCUMENT_SIZE<a class="headerlink" href="#autoconnect_jsondocument_size" title="Permanent link">&para;</a></h4>
<p>This is a size of <a href="https://arduinojson.org/v6/api/dynamicjsondocument/">DynamicJsonDocument</a> for ArduinoJson version 6. This buffer is not automatically expanding, and the size determines the limit.</p>
<h4 id="autoconnect_jsonpsram_size">AUTOCONNECT_JSONPSRAM_SIZE<a class="headerlink" href="#autoconnect_jsonpsram_size" title="Permanent link">&para;</a></h4>
<p>For ESP32 module equips with PSRAM, you can allocate the JSON document buffer to PSRAM. Buffer allocation to PSRAM will enable when <strong>PSRAM:Enabled</strong> option selected in the Arduino IDE's Board Manager menu. It is available since ArduinoJson 6.10.0.</p>
<h2 id="saving-json-document">Saving JSON document<a class="headerlink" href="#saving-json-document" title="Permanent link">&para;</a></h2>
<p>The sketch can persist AutoConnectElements as a JSON document and also uses <a href="achandling.html#saving-autoconnectelements-with-json">this function</a> to save the values entered on the custom Web page. And you can reload the saved JSON document into AutoConnectElements as the field in a custom Web page using the <a href="achandling.html#loading-autoconnectaux-autoconnectelements-with-json">load function</a>. </p>
<div class="footnote">
@ -1491,7 +1616,7 @@ An example of using each function is as follows.
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

File diff suppressed because it is too large Load Diff

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,81 +229,6 @@
<nav class="md-tabs" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link md-tabs__link--active">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -432,6 +357,13 @@
404 handler
</a>
</li>
<li class="md-nav__item">
<a href="#access-to-saved-credentials" title=" Access to saved credentials" class="md-nav__link">
Access to saved credentials
</a>
</li>
<li class="md-nav__item">
@ -474,6 +406,13 @@
Change menu title
</a>
</li>
<li class="md-nav__item">
<a href="#change-the-menu-labels" title=" Change the menu labels" class="md-nav__link">
Change the menu labels
</a>
</li>
<li class="md-nav__item">
@ -843,12 +782,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -917,6 +904,13 @@
404 handler
</a>
</li>
<li class="md-nav__item">
<a href="#access-to-saved-credentials" title=" Access to saved credentials" class="md-nav__link">
Access to saved credentials
</a>
</li>
<li class="md-nav__item">
@ -959,6 +953,13 @@
Change menu title
</a>
</li>
<li class="md-nav__item">
<a href="#change-the-menu-labels" title=" Change the menu labels" class="md-nav__link">
Change the menu labels
</a>
</li>
<li class="md-nav__item">
@ -1105,7 +1106,9 @@
<h2 id="advanced-usage">Advanced usage<a class="headerlink" href="#advanced-usage" title="Permanent link">&para;</a></h2>
<h3 id="404-handler"><i class="fa fa-caret-right"></i> 404 handler<a class="headerlink" href="#404-handler" title="Permanent link">&para;</a></h3>
<p>Registering the "not found" handler is a different way than ESP8266WebServer/WebServer. The <em>onNotFound</em> of ESP8266WebServer/WebServer does not work with AutoConnect. AutoConnect overrides <em>ESP8266WebServer::onNotFound</em>/<em>WebServer::onNotFound</em> to handle a captive portal. To register "not found" handler, use <a href="api.html#onnotfound"><em>AutoConnect::onNotFound</em></a>.</p>
<p>Registering the "not found" handler is a different way than ESP8266WebServer (WebServer as ESP32). The <em>onNotFound</em> of ESP8266WebServer/WebServer does not work with AutoConnect. AutoConnect overrides <em>ESP8266WebServer::onNotFound</em>/<em>WebServer::onNotFound</em> to handle a captive portal. To register "not found" handler, use <a href="api.html#onnotfound"><em>AutoConnect::onNotFound</em></a>.</p>
<h3 id="access-to-saved-credentials"><i class="fa fa-caret-right"></i> Access to saved credentials<a class="headerlink" href="#access-to-saved-credentials" title="Permanent link">&para;</a></h3>
<p>AutoConnect stores the established WiFi connection in the EEPROM of the ESP8266/ESP32 module and equips the class to access it from the sketch. You can read, write or erase the credentials using this class individually. It's <a href="credit.html#autoconnectcredential">AutoConnectCredential</a> class which provides the access method to the saved credentials in EEPROM. Refer to section <a href="credit.html">Saved credentail access</a> for details.</p>
<h3 id="automatic-reconnect"><i class="fa fa-caret-right"></i> Automatic reconnect<a class="headerlink" href="#automatic-reconnect" title="Permanent link">&para;</a></h3>
<p>When the captive portal is started, SoftAP starts and the STA is disconnected. The current SSID setting memorized in ESP8266 will be lost but then the reconnect behavior of ESP32 is somewhat different from this.</p>
<p>The <a href="https://github.com/espressif/arduino-esp32/blob/a0f0bd930cfd2d607bf3d3288f46e2d265dd2e11/libraries/WiFi/src/WiFiSTA.h#L46"><em>WiFiSTAClass::disconnect</em></a> function implemented in the arduino-esp32 has extended parameters than the ESP8266's arduino-core. The second parameter of WiFi.disconnect on the arduino-esp32 core that does not exist in the <a href="https://github.com/esp8266/Arduino/blob/7e1bdb225da8ab337373517e6a86a99432921a86/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp#L296">ESP8266WiFiSTAClass</a> has the effect of deleting the currently connected WiFi configuration and its default value is "false". On the ESP32 platform, even if WiFi.disconnect is executed, WiFi.begin() without the parameters in the next turn will try to connect to that AP. That is, automatic reconnection is implemented in arduino-esp32 already. Although this behavior appears seemingly competent, it is rather a disadvantage in scenes where you want to change the access point each time. When explicitly disconnecting WiFi from the Disconnect menu, AutoConnect will erase the AP connection settings saved by arduino-esp32 core. AutoConnect's automatic reconnection is a mechanism independent from the automatic reconnection of the arduino-esp32 core.</p>
@ -1267,6 +1270,16 @@ Also, if you want to stop AutoConnect completely when the captive portal is time
<div style="float:left;width:40%;height:470px;overflow:hidden;"><img src="images/fsbmenu.png"></div>
<p><img style="margin-left:70px;width:40%;height:470px;" src="images/fsbmenu_expand.png"></p>
<h3 id="change-the-menu-labels"><i class="fa fa-caret-right"></i> Change the menu labels<a class="headerlink" href="#change-the-menu-labels" title="Permanent link">&para;</a></h3>
<p>You can change the label of the AutoConnect menu item by rewriting the default label letter in <a href="https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectLabels.h">AutoConnectLabels.h</a> macros. However, changing menu items letter influences all the sketch's build scenes.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #75715e">#define AUTOCONNECT_MENULABEL_CONFIGNEW &quot;Configure new AP&quot;</span>
<span style="color: #75715e">#define AUTOCONNECT_MENULABEL_OPENSSIDS &quot;Open SSIDs&quot;</span>
<span style="color: #75715e">#define AUTOCONNECT_MENULABEL_DISCONNECT &quot;Disconnect&quot;</span>
<span style="color: #75715e">#define AUTOCONNECT_MENULABEL_RESET &quot;Reset...&quot;</span>
<span style="color: #75715e">#define AUTOCONNECT_MENULABEL_HOME &quot;HOME&quot;</span>
<span style="color: #75715e">#define AUTOCONNECT_BUTTONLABEL_RESET &quot;RESET&quot;</span>
</pre></div>
<h3 id="combination-with-mdns"><i class="fa fa-caret-right"></i> Combination with mDNS<a class="headerlink" href="#combination-with-mdns" title="Permanent link">&para;</a></h3>
<p>With <a href="https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266mDNS">mDNS library</a>, you can access to ESP8266 by name instead of IP address after connection. The sketch can start the MDNS responder after <a href="api.html#begin"><em>AutoConnect::begin</em></a>.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #75715e">#include</span> <span style="color: #75715e">&lt;ESP8266WiFi.h&gt;</span>
@ -1596,7 +1609,7 @@ The above example does not connect to WiFi until TRIGGER_PIN goes LOW. When TRIG
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link md-tabs__link--active">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -825,12 +748,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -1111,7 +1082,7 @@
<p>Run the AutoConnect site using the externally ensured ESP8266WebServer for ESP8266 or WebServer for ESP32.</p>
<p>The <a href="api.html#handleclient"><strong>handleClient</strong></a> function of AutoConnect can include the response of the URI handler added by the user using the "<em>on</em>" function of ESP8266WebServer/WebServer. If ESP8266WebServer/WebServer is assigned internally by AutoConnect, the sketch can obtain that reference with the <a href="api.html#host"><strong>host</strong></a> function.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">webServer</span><span class="apidesc">A reference of ESP8266WebServer or WebServer instance.</span></dd>
</dl></p>
<h2 id="public-member-functions"><i class="fa fa-code"></i> Public member functions<a class="headerlink" href="#public-member-functions" title="Permanent link">&para;</a></h2>
@ -1120,7 +1091,7 @@
</pre></div>
Returns a pointer to AutoConnectAux with the URI specified by <em>uri</em>. If AutoConnectAux with that URI is not bound, it returns <strong>nullptr</strong>.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">uri</span><span class="apidesc">A string of the URI.</span></dd>
<dt><strong>Return value</strong></dt>
<dd>A Pointer of the AutoConnectAux instance.</dd>
@ -1160,7 +1131,7 @@ The captive portal will not be started if the connection has been established wi
<dd><span class="apidef">false</span><span class="aidesc">Configuration parameter is invalid, some values out of range.</span></dd>
</dl></p>
<h3 id="end"><i class="fa fa-caret-right"></i> end<a class="headerlink" href="#end" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">void</span> <span style="color: #f8f8f2">end()</span>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">void</span> <span style="color: #f8f8f2">end(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">)</span>
</pre></div>
<p>Stops AutoConnect captive portal service. Release ESP8266WebServer/WebServer and DNSServer. </p>
@ -1169,12 +1140,12 @@ The captive portal will not be started if the connection has been established wi
<p>The end function releases the instance of ESP8266WebServer/WebServer and DNSServer. It can not process them after the end function.</p>
</div>
<h3 id="handleclient"><i class="fa fa-caret-right"></i> handleClient<a class="headerlink" href="#handleclient" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">void</span> <span style="color: #f8f8f2">handleClient()</span>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">void</span> <span style="color: #f8f8f2">handleClient(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">)</span>
</pre></div>
<p>Process the AutoConnect menu interface. The handleClient() function of the ESP8266WebServer/WebServer hosted by AutoConnect is also called from within AutoConnect, and the client request handlers contained in the user sketch are also handled.</p>
<h3 id="handlerequest"><i class="fa fa-caret-right"></i> handleRequest<a class="headerlink" href="#handlerequest" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">void</span> <span style="color: #f8f8f2">handleRequest()</span>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">void</span> <span style="color: #f8f8f2">handleRequest(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">)</span>
</pre></div>
<p>Handling for the AutoConnect menu request.</p>
@ -1188,20 +1159,20 @@ The captive portal will not be started if the connection has been established wi
<p>Put a user site's home URI. The URI specified by home is linked from "HOME" in the AutoConnect menu.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">uri</span><span class="aidesc">A URI string of user site's home path.</span></dd>
</dl></p>
<h3 id="host"><i class="fa fa-caret-right"></i> host<a class="headerlink" href="#host" title="Permanent link">&para;</a></h3>
<ul>
<li>For ESP8266</li>
</ul>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">ESP8266WebServer</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">host()</span>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">ESP8266WebServer</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">host(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">)</span>
</pre></div>
<ul>
<li>For ESP32</li>
</ul>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">WebServer</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">host()</span>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">WebServer</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">host(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">)</span>
</pre></div>
<p>Returns the reference of the ESP8266WebServer/WebServer which is allocated in AutoConnect automatically.
@ -1226,7 +1197,7 @@ or<br />
</pre></div>
Join the AutoConnectAux object to AutoConnect. AutoConnectAux objects can be joined one by one, or joined altogether. The AutoConnectAux object joined by the join function can be handled from the AutoConnect menu.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">aux</span><span class="apidesc">Reference to AutoConnectAux. It can be std::vector of std::reference_wrapper of AutoConnectAux with <a href="https://en.cppreference.com/w/cpp/language/list_initialization">list initialization</a>.</span></dd>
</dl></p>
<h3 id="load"><i class="fa fa-caret-right"></i> load<a class="headerlink" href="#load" title="Permanent link">&para;</a></h3>
@ -1238,7 +1209,7 @@ Join the AutoConnectAux object to AutoConnect. AutoConnectAux objects can be joi
</pre></div>
Load JSON document of AutoConnectAux which contains AutoConnectElements. If there is a syntax error in the JSON document, false is returned.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">aux</span><span class="apidesc">The input string to be loaded.</span></dd>
<dt><strong>Return value</strong></dt>
<dd><span class="apidef">true</span><span class="apidesc">The JSON document as AutoConnectAux successfully loaded.</span></dd>
@ -1284,7 +1255,7 @@ Called even before generating HTML and after generated.</li>
</pre></div>
Register the function which will call from AutoConnect at the start of the captive portal.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">fn</span><span class="apidesc">Function called at the captive portal start.</span></dd></p>
</dl>
@ -1292,7 +1263,7 @@ Register the function which will call from AutoConnect at the start of the capti
<p><div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">typedef</span> <span style="color: #f8f8f2">std</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">function</span><span style="color: #f92672">&lt;</span><span style="color: #66d9ef">bool</span><span style="color: #f8f8f2">(IPAddress</span> <span style="color: #f8f8f2">softapIP)</span><span style="color: #f92672">&gt;</span> <span style="color: #f8f8f2">DetectExit_ft</span>
</pre></div>
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">softapIP</span><span class="apidesc">An IP address of SoftAP for the captive portal.</span></dd>
<dt><strong>Return value</strong></dt>
<dd><span class="apidef">true</span><span class="apidesc">Continues captive portal handling.</span></dd>
@ -1312,7 +1283,7 @@ Register the function which will call from AutoConnect at the start of the capti
</pre></div>
Register the handler function for undefined URL request detected.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">fn</span><span class="apidesc">A function of the "not found" handler.</span></dd>
</dl></p>
<h3 id="where"><i class="fa fa-caret-right"></i> where<a class="headerlink" href="#where" title="Permanent link">&para;</a></h3>
@ -1408,7 +1379,7 @@ This function is provided to access the fields (ie. the AutoConnectElements) wit
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link md-tabs__link--active">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -566,6 +489,13 @@
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#operator" title=" operator [ ]" class="md-nav__link">
operator [ ]
</a>
</li>
<li class="md-nav__item">
<a href="#add" title=" add" class="md-nav__link">
add
@ -613,6 +543,13 @@
on
</a>
</li>
<li class="md-nav__item">
<a href="#onupload" title=" onUpload" class="md-nav__link">
onUpload
</a>
</li>
<li class="md-nav__item">
@ -777,12 +714,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -866,6 +851,13 @@
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#operator" title=" operator [ ]" class="md-nav__link">
operator [ ]
</a>
</li>
<li class="md-nav__item">
<a href="#add" title=" add" class="md-nav__link">
add
@ -913,6 +905,13 @@
on
</a>
</li>
<li class="md-nav__item">
<a href="#onupload" title=" onUpload" class="md-nav__link">
onUpload
</a>
</li>
<li class="md-nav__item">
@ -979,6 +978,15 @@
<dd><span class="apidef">addons</span><span class="apidesc">Reference to AutoConnectElement collection.</span></dt>
</dl></p>
<h2 id="public-member-functions"><i class="fa fa-code"></i> Public member functions<a class="headerlink" href="#public-member-functions" title="Permanent link">&para;</a></h2>
<h3 id="operator"><i class="fa fa-caret-right"></i> operator [ ]<a class="headerlink" href="#operator" title="Permanent link">&para;</a></h3>
<p><div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectElement</span><span style="color: #f92672">&amp;</span> <span style="color: #66d9ef">operator</span><span style="color: #f8f8f2">[](</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">String</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">name)</span>
</pre></div>
Returns a reference to the element specified by <strong>name</strong>. An operator <code>[]</code> is a shortcut for <a href="apiaux.html#getelement">getElement</a> function with the reference casting. Unlike getElement, which returns a pointer to that element, an operator <code>[]</code> returns a reference to that element. You also need to cast the return value to the actual type, just like the getElement function.
<dl class="apidl">
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">name</span><span class="apidesc">Name of the AutoConnectElements to be retrieved.</span></dd>
<dt><strong>Return value</strong></dt><dd>A reference to AutoConnectElement. It is different from the actual element type.</dd>
</dl></p>
<h3 id="add"><i class="fa fa-caret-right"></i> add<a class="headerlink" href="#add" title="Permanent link">&para;</a></h3>
<p><div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">void</span> <span style="color: #f8f8f2">add(AutoConnectElement</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">addon)</span>
</pre></div>
@ -998,7 +1006,7 @@ Add an element to the AutoConnectAux. An added element is displayed on the custo
Get a registered AutoConnectElement as specified name. If <strong>T</strong> is specified as an actual type of AutoConnectElements, it returns a reference to that instance.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dd><span class="apidef">T</span><span class="apidesc">Actual type name of AutoConnectElements as <a href="apielements.html#autoconnectbutton">AutoConnectButton</a>, <a href="apielements.html#autoconnectcheckbox">AutoConnectCheckbox</a>, <a href="apielements.html#autoconnectelement">AutoConnectElement</a>, <a href="apielements.html#autoconnectinput">AutoConnectInput</a>, <a href="apielements.html#autoconnectradio">AutoConnectRadio</a>, <a href="apielements.html#autoconnectselect">AutoConnectSelect</a>, <a href="apielements.html#autoconnectsubmit">AutoConnectSubmit</a>, <a href="apielements.html#autoconnecttext">AutoConnectText</a>.</span></dd>
<dd><span class="apidef">T</span><span class="apidesc">Actual type name of AutoConnectElements as <a href="apielements.html#autoconnectbutton">AutoConnectButton</a>, <a href="apielements.html#autoconnectcheckbox">AutoConnectCheckbox</a>, <a href="apielements.html#autoconnectelement">AutoConnectElement</a>, <a href="apielements.html#autoconnectfile">AutoConnectFile</a>, <a href="apielements.html#autoconnectinput">AutoConnectInput</a>, <a href="apielements.html#autoconnectradio">AutoConnectRadio</a>, <a href="apielements.html#autoconnectselect">AutoConnectSelect</a>, <a href="apielements.html#autoconnectsubmit">AutoConnectSubmit</a>, <a href="apielements.html#autoconnecttext">AutoConnectText</a>.</span></dd>
<dd><span class="apidef">name</span><span class="apidesc">Name of the AutoConnectElements to be retrieved.</span></dd>
<dt><strong>Return value</strong></dt><dd>A reference of the AutoConnectElements. If a type is not specified returns a pointer.</dd>
</dl></p>
@ -1029,7 +1037,7 @@ Get vector of reference of all elements.
</pre></div>
Load all AutoConnectElements elements from JSON document into AutoConnectAux as custom Web pages. The JSON document specified by the load function must be the <a href="acjson.html#json-objects-elements-for-the-custom-web-page">document structure</a> of AutoConnectAux. Its JSON document can describe multiple pages as an array.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">in</span><span class="apidesc">Specifies the JSON document to be load. The load function can input the following objects.</p>
<ul>
<li>String : Read-only String</li>
@ -1088,7 +1096,7 @@ The outermost <code>[</code>, <code>]</code> is missing.</p>
</pre></div>
Set or reset the display as menu item for this AutoConnectAux. This function programmatically manipulates the menu parameter of the <a href="apiaux.html#autoconnectaux">AutoConenctAux constructor</a>.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">true</span><span class="apidesc">Show on the menu.</span></dd>
<dd><span class="apidef">false</span><span class="apidesc">Hidden on the menu.</span></dd>
</dl></p>
@ -1122,12 +1130,36 @@ Called even before generating HTML and after generated.</dd></li>
</dl>
</dl>
<h3 id="onupload"><i class="fa fa-caret-right"></i> onUpload<a class="headerlink" href="#onupload" title="Permanent link">&para;</a></h3>
<p><div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">void</span> <span style="color: #f8f8f2">onUpload</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">T</span><span style="color: #f92672">&amp;&gt;</span><span style="color: #f8f8f2">(T</span> <span style="color: #f8f8f2">handler)</span>
</pre></div>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">void</span> <span style="color: #f8f8f2">onUpload(PageBuilder</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">UploadFuncT</span> <span style="color: #f8f8f2">uploadFunc)</span>
</pre></div>
Register the upload handler of the AutoConnectAux.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dd><span class="apidef">T</span><span class="apidesc">Specifies a class name of the custom uploader inherited from <a href="acupload.html#upload-handler-base-class">AutoConnectUploadHandler</a> class. Refer to the <a href="acupload.html#to-upload-to-a-device-other-than-flash-or-sd">appendix</a> for details.</span></dd>
<dd><span class="apidef">handler</span><span class="apidesc">Specifies the custom uploader inherited from <a href="acupload.html#upload-handler-base-class">AutoConnectUploadHandler</a> class. Refer to the <a href="acupload.html#to-upload-to-a-device-other-than-flash-or-sd">appendix</a> for details.</span></dd>
<dd><span class="apidef">uploadFunc</span><span class="apidesc">A function that behaves when request to upload with the AutoConnectAux page. UploadFuncT type is defined by the following declaration.<p class="apidesc"><code>void(const String&amp;, const HTTPUpload&amp;)</code></p><p>A data structure of the upload file as HTTPUpload. It is defined in the ESP8266WebServer (the WebServer for ESP32) library as follows:</p>
<p><div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">typedef</span> <span style="color: #66d9ef">struct</span> <span style="color: #f8f8f2">{</span>
<span style="color: #f8f8f2">HTTPUploadStatus</span> <span style="color: #f8f8f2">status;</span>
<span style="color: #f8f8f2">String</span> <span style="color: #f8f8f2">filename;</span>
<span style="color: #f8f8f2">String</span> <span style="color: #f8f8f2">name;</span>
<span style="color: #f8f8f2">String</span> <span style="color: #f8f8f2">type;</span>
<span style="color: #66d9ef">size_t</span> <span style="color: #f8f8f2">totalSize;</span>
<span style="color: #66d9ef">size_t</span> <span style="color: #f8f8f2">currentSize;</span>
<span style="color: #66d9ef">size_t</span> <span style="color: #f8f8f2">contentLength;</span>
<span style="color: #66d9ef">uint8_t</span> <span style="color: #f8f8f2">buf[HTTP_UPLOAD_BUFLEN];</span>
<span style="color: #f8f8f2">}</span> <span style="color: #f8f8f2">HTTPUpload;</span>
</pre></div>
</p>Refer to '<a href="acupload.html#to-upload-to-a-device-other-than-flash-or-sd">To upload to a device other than Flash or SD</a>' in section <a href="acupload.html">appendix</a> for details.</span></dd>
</dl></p>
<h3 id="release"><i class="fa fa-caret-right"></i> release<a class="headerlink" href="#release" title="Permanent link">&para;</a></h3>
<p><div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">bool</span> <span style="color: #f8f8f2">release(</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">String</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">name)</span>
</pre></div>
Release a specified AutoConnectElement from AutoConenctAux. The release function is provided to dynamically change the structure of the custom Web pages with the sketch. By combining the release function and the <a href="apiaux.html#add">add</a> function or the <a href="apiaux.html#loadelement">loadElement</a> function, the sketch can change the style of the custom Web page according to its behavior.
<dl class="apidl">
<dt><strong>Parameters</strong></dt>
<dt><strong>Parameter</strong></dt>
<dd><span class="apidef">name</span><span class="apidesc">Specifies the name of AutoConnectElements to be released.</span></dd>
<dt><strong>Return value</strong></dt>
<dd><span class="apidef">true</span><span class="apidesc">The AutoConnectElement successfully released.</span></dd>
@ -1271,7 +1303,7 @@ Set the title string of the custom Web page. This title will be displayed as the
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link md-tabs__link--active">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -875,12 +798,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -1477,7 +1448,7 @@ The default value is 0.
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

File diff suppressed because it is too large Load Diff

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link md-tabs__link--active">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -674,12 +597,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -867,7 +838,7 @@
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(m){if(void 0===m)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===m.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var l="2"==m.version[0];m.ja=function(){this.pipeline.reset(),this.pipeline.add(m.ja.trimmer,m.ja.stopWordFilter,m.ja.stemmer),l?this.tokenizer=m.ja.tokenizer:(m.tokenizer&&(m.tokenizer=m.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=m.ja.tokenizer))};var j=new m.TinySegmenter;m.ja.tokenizer=function(e){var r,t,i,n,o,s,p,a,u;if(!arguments.length||null==e||null==e)return[];if(Array.isArray(e))return e.map(function(e){return l?new m.Token(e.toLowerCase()):e.toLowerCase()});for(r=(t=e.toString().toLowerCase().replace(/^\s+/,"")).length-1;0<=r;r--)if(/\S/.test(t.charAt(r))){t=t.substring(0,r+1);break}for(o=[],i=t.length,p=a=0;a<=i;a++)if(s=a-p,t.charAt(a).match(/\s/)||a==i){if(0<s)for(n=j.segment(t.slice(p,a)).filter(function(e){return!!e}),u=p,r=0;r<n.length;r++)l?o.push(new m.Token(n[r],{position:[u,n[r].length],index:o.length})):o.push(n[r]),u+=n[r].length;p=a+1}return o},m.ja.stemmer=function(e){return e},m.Pipeline.registerFunction(m.ja.stemmer,"stemmer-ja"),m.ja.wordCharacters="一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Za-zA-Z0-90-9",m.ja.trimmer=m.trimmerSupport.generateTrimmer(m.ja.wordCharacters),m.Pipeline.registerFunction(m.ja.trimmer,"trimmer-ja"),m.ja.stopWordFilter=m.generateStopWordFilter("これ それ あれ この その あの ここ そこ あそこ こちら どこ だれ なに なん 何 私 貴方 貴方方 我々 私達 あの人 あのかた 彼女 彼 です あります おります います は が の に を で え から まで より も どの と し それで しかし".split(" ")),m.Pipeline.registerFunction(m.ja.stopWordFilter,"stopWordFilter-ja"),m.jp=m.ja,m.Pipeline.registerFunction(m.jp.stemmer,"stemmer-jp"),m.Pipeline.registerFunction(m.jp.trimmer,"trimmer-jp"),m.Pipeline.registerFunction(m.jp.stopWordFilter,"stopWordFilter-jp")}});

@ -1 +1 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(n){if(void 0===n)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===n.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==n.version[0];n.jp=function(){this.pipeline.reset(),this.pipeline.add(n.jp.stopWordFilter,n.jp.stemmer),i?this.tokenizer=n.jp.tokenizer:(n.tokenizer&&(n.tokenizer=n.jp.tokenizer),this.tokenizerFn&&(this.tokenizerFn=n.jp.tokenizer))};var o=new n.TinySegmenter;n.jp.tokenizer=function(e){if(!arguments.length||null==e||null==e)return[];if(Array.isArray(e))return e.map(function(e){return i?new n.Token(e.toLowerCase()):e.toLowerCase()});for(var r=e.toString().toLowerCase().replace(/^\s+/,""),t=r.length-1;0<=t;t--)if(/\S/.test(r.charAt(t))){r=r.substring(0,t+1);break}return o.segment(r).filter(function(e){return!!e}).map(function(e){return i?new n.Token(e):e})},n.jp.stemmer=function(e){return e},n.Pipeline.registerFunction(n.jp.stemmer,"stemmer-jp"),n.jp.wordCharacters="一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Za-zA-Z0-90-9",n.jp.stopWordFilter=function(e){if(-1===n.jp.stopWordFilter.stopWords.indexOf(i?e.toString():e))return e},n.jp.stopWordFilter=n.generateStopWordFilter("これ それ あれ この その あの ここ そこ あそこ こちら どこ だれ なに なん 何 私 貴方 貴方方 我々 私達 あの人 あのかた 彼女 彼 です あります おります います は が の に を で え から まで より も どの と し それで しかし".split(" ")),n.Pipeline.registerFunction(n.jp.stopWordFilter,"stopWordFilter-jp")}});
module.exports=require("./lunr.ja");

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(t){if(void 0===t)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===t.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==t.version[0];t.th=function(){this.pipeline.reset(),this.pipeline.add(t.th.trimmer),i?this.tokenizer=t.th.tokenizer:(t.tokenizer&&(t.tokenizer=t.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=t.th.tokenizer))},t.th.wordCharacters="[฀-๿]",t.th.trimmer=t.trimmerSupport.generateTrimmer(t.th.wordCharacters),t.Pipeline.registerFunction(t.th.trimmer,"trimmer-th");var n=t.wordcut;n.init(),t.th.tokenizer=function(e){if(!arguments.length||null==e||null==e)return[];if(Array.isArray(e))return e.map(function(e){return i?new t.Token(e):e});var r=e.toString().replace(/^\s+/,"");return n.cut(r).split("|")}}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,81 +229,6 @@
<nav class="md-tabs" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link md-tabs__link--active">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -765,12 +690,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -1147,7 +1120,7 @@ or</p>
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -139,7 +139,7 @@
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<a href="#097-jan-25-2019" tabindex="1" class="md-skip">
<a href="#098-apr-25-2019" tabindex="1" class="md-skip">
Skip to content
</a>
@ -229,81 +229,6 @@
<nav class="md-tabs" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link md-tabs__link--active">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -636,12 +561,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -683,6 +656,13 @@
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#098-apr-25-2019" title="[0.9.8] Apr. 25, 2019" class="md-nav__link">
[0.9.8] Apr. 25, 2019
</a>
</li>
<li class="md-nav__item">
<a href="#097-jan-25-2019" title="[0.9.7] Jan. 25, 2019" class="md-nav__link">
[0.9.7] Jan. 25, 2019
@ -773,6 +753,13 @@
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#098-apr-25-2019" title="[0.9.8] Apr. 25, 2019" class="md-nav__link">
[0.9.8] Apr. 25, 2019
</a>
</li>
<li class="md-nav__item">
<a href="#097-jan-25-2019" title="[0.9.7] Jan. 25, 2019" class="md-nav__link">
[0.9.7] Jan. 25, 2019
@ -841,7 +828,18 @@
<h1>Change log</h1>
<h4 id="097-jan-25-2019">[0.9.7] Jan. 25, 2019<a class="headerlink" href="#097-jan-25-2019" title="Permanent link">&para;</a></h4>
<h4 id="098-apr-25-2019">[0.9.8] Apr. 25, 2019<a class="headerlink" href="#098-apr-25-2019" title="Permanent link">&para;</a></h4>
<ul>
<li>Supports ArduinoJson 6.9.1 or later.</li>
<li>Supports allocating JsonDocument buffer to PSRAM on ESP32 with ArduinoJson 6.10.0 or later.</li>
<li>Supports <a href="apiaux.html#operator"><strong>operator<code>[]</code></strong></a> as a shortcut for AutoConnectAux::getElement function.</li>
<li>Supports <a href="apielements.html#ast62"><strong>AutoConnectElement::as&lt;T></strong></a> function to easily coding for conversion from an AutoConnectElement to an actual type.</li>
<li>Supports new element type <a href="acelements.html#autoconnectfile"><strong>AutoConnectFile</strong></a> and built-in file uploader.</li>
<li>Supports a <a href="acelements.html#format"><strong>format attribute</strong></a> with the AutoConnectText element.</li>
<li>Fixed blank page responds with Configure new.</li>
<li>Changed menu labels placement in source files structure.</li>
</ul>
<h4 id="097-jan-25-2019">[0.9.7] Jan. 25, 2019<a class="headerlink" href="#097-jan-25-2019" title="Permanent link">&para;</a></h4>
<ul>
<li>Fixed crash in some environments. Thank you @ageurtse</li>
<li>Supports AutoConnect menu extention by user sketch with <a href="acintro.html"><strong>AutoConnectAux</strong></a>.</li>
@ -962,7 +960,7 @@
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

File diff suppressed because it is too large Load Diff

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link md-tabs__link--active">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -756,12 +679,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -931,16 +902,20 @@
<p>Here, represent examples the typical method for the data type conversion for the AutoConnectElements value of custom Web pages.</p>
<h3 id="integer"><i class="fa fa-exchange"></i> Integer<a class="headerlink" href="#integer" title="Permanent link">&para;</a></h3>
<p>Use <a href="https://www.arduino.cc/reference/en/language/variables/conversion/intcast/">int()</a> or <a href="https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/toint/">toInt() of String</a>.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">input</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux.getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #e6db74">&quot;INPUT&quot;</span><span style="color: #f8f8f2">);</span>
<p><div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">input</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux.getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #e6db74">&quot;INPUT&quot;</span><span style="color: #f8f8f2">);</span>
<span style="color: #66d9ef">int</span> <span style="color: #f8f8f2">value</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">input.value.toInt();</span>
</pre></div>
You can shorten it and write as like:
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">int</span> <span style="color: #f8f8f2">value</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux[</span><span style="color: #e6db74">&quot;INPUT&quot;</span><span style="color: #f8f8f2">].value.toInt();</span>
</pre></div></p>
<h3 id="float"><i class="fa fa-exchange"></i> Float<a class="headerlink" href="#float" title="Permanent link">&para;</a></h3>
<p>Use <a href="https://www.arduino.cc/reference/en/language/variables/conversion/floatcast/">float()</a> or <a href="https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/tofloat/">toFloat() of String</a>.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">input</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux.getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #e6db74">&quot;INPUT&quot;</span><span style="color: #f8f8f2">);</span>
<p><div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">input</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux.getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #e6db74">&quot;INPUT&quot;</span><span style="color: #f8f8f2">);</span>
<span style="color: #66d9ef">float</span> <span style="color: #f8f8f2">value</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">input.value.toFloat();</span>
</pre></div>
You can shorten it and write as like:
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">float</span> <span style="color: #f8f8f2">value</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux[</span><span style="color: #e6db74">&quot;INPUT&quot;</span><span style="color: #f8f8f2">].value.toFloat();</span>
</pre></div></p>
<h3 id="date-time"><i class="fa fa-exchange"></i> Date &amp; Time<a class="headerlink" href="#date-time" title="Permanent link">&para;</a></h3>
<p>The easiest way is to use the <a href="https://www.pjrc.com/teensy/td_libs_Time.html">Arduino Time Library</a>. Sketches must accommodate differences in date and time formats depending on the time zone. You can absorb the difference in DateTime format by using <code>sscanf</code> function.<sup id="fnref:1"><a class="footnote-ref" href="#fn:1" rel="footnote">1</a></sup></p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #75715e">#include</span> <span style="color: #75715e">&lt;TimeLib.h&gt;</span>
@ -948,7 +923,7 @@
<span style="color: #66d9ef">time_t</span> <span style="color: #f8f8f2">tm;</span>
<span style="color: #66d9ef">int</span> <span style="color: #f8f8f2">Year,</span> <span style="color: #f8f8f2">Month,</span> <span style="color: #f8f8f2">Day,</span> <span style="color: #f8f8f2">Hour,</span> <span style="color: #f8f8f2">Minute,</span> <span style="color: #f8f8f2">Second;</span>
<span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">input</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux.getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #e6db74">&quot;INPUT&quot;</span><span style="color: #f8f8f2">);</span>
<span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">input</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux.[</span><span style="color: #e6db74">&quot;INPUT&quot;</span><span style="color: #f8f8f2">].as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">();</span>
<span style="color: #f8f8f2">sscanf(input.value.c_str(),</span> <span style="color: #e6db74">&quot;%d-%d-%d %d:%d:%d&quot;</span><span style="color: #f8f8f2">,</span> <span style="color: #f92672">&amp;</span><span style="color: #f8f8f2">Year,</span> <span style="color: #f92672">&amp;</span><span style="color: #f8f8f2">Month,</span> <span style="color: #f92672">&amp;</span><span style="color: #f8f8f2">Day,</span> <span style="color: #f92672">&amp;</span><span style="color: #f8f8f2">Hour,</span> <span style="color: #f92672">&amp;</span><span style="color: #f8f8f2">Minute,</span> <span style="color: #f92672">&amp;</span><span style="color: #f8f8f2">Second);</span>
<span style="color: #f8f8f2">tm.Year</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">CalendarYrToTm(Year);</span>
<span style="color: #f8f8f2">tm.Month</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">Month;</span>
@ -961,7 +936,7 @@
<h3 id="ip-address"><i class="fa fa-exchange"></i> IP address<a class="headerlink" href="#ip-address" title="Permanent link">&para;</a></h3>
<p>To convert a String to an IP address, use <strong>IPAddress::fromString</strong>. To stringize an instance of an IP address, use <strong>IPAddress::toString</strong>.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">IPAddress</span> <span style="color: #f8f8f2">ip;</span>
<span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">input</span> <span style="color: #f8f8f2">aux.getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #e6db74">&quot;INPUT&quot;</span><span style="color: #f8f8f2">);</span>
<span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">input</span> <span style="color: #f8f8f2">aux[</span><span style="color: #e6db74">&quot;INPUT&quot;</span><span style="color: #f8f8f2">].as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">();</span>
<span style="color: #f8f8f2">ip.fromString(input.value);</span>
<span style="color: #f8f8f2">input.value</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">ip.toString();</span>
</pre></div>
@ -1012,9 +987,9 @@
<span style="color: #f8f8f2">AutoConnect</span> <span style="color: #f8f8f2">portal;</span>
<span style="color: #f8f8f2">String</span> <span style="color: #a6e22e">checkIPAddress</span><span style="color: #f8f8f2">(AutoConnectAux</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">aux,</span> <span style="color: #f8f8f2">PageArgument</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">args)</span> <span style="color: #f8f8f2">{</span>
<span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">input_page</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">portal.aux(</span><span style="color: #e6db74">&quot;/&quot;</span><span style="color: #f8f8f2">);</span>
<span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">ipaddress</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">input_page</span><span style="color: #f92672">-&gt;</span><span style="color: #f8f8f2">getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #e6db74">&quot;ipaddress&quot;</span><span style="color: #f8f8f2">);</span>
<span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">result</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux.getElement</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(</span><span style="color: #e6db74">&quot;result&quot;</span><span style="color: #f8f8f2">);</span>
<span style="color: #f8f8f2">AutoConnectAux</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">input_page</span> <span style="color: #f92672">=</span> <span style="color: #f92672">*</span><span style="color: #f8f8f2">portal.aux(</span><span style="color: #e6db74">&quot;/&quot;</span><span style="color: #f8f8f2">);</span>
<span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">ipaddress</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">input_page[</span><span style="color: #e6db74">&quot;ipaddress&quot;</span><span style="color: #f8f8f2">].as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectInput</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">();</span>
<span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&amp;</span> <span style="color: #f8f8f2">result</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">aux[</span><span style="color: #e6db74">&quot;result&quot;</span><span style="color: #f8f8f2">].as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">();</span>
<span style="background-color: #49483e"> <span style="color: #66d9ef">if</span> <span style="color: #f8f8f2">(ipaddress.isValid())</span> <span style="color: #f8f8f2">{</span>
</span> <span style="color: #f8f8f2">result.value</span> <span style="color: #f92672">=</span> <span style="color: #e6db74">&quot;IP Address &quot;</span> <span style="color: #f92672">+</span> <span style="color: #f8f8f2">ipaddress.value</span> <span style="color: #f92672">+</span> <span style="color: #e6db74">&quot; is OK.&quot;</span><span style="color: #f8f8f2">;</span>
@ -1163,7 +1138,7 @@
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,81 +229,6 @@
<nav class="md-tabs" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link md-tabs__link--active">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -636,12 +561,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -732,40 +705,6 @@
How erase the credentials saved in EEPROM?
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#include-header" title=" Include header" class="md-nav__link">
Include header
</a>
</li>
<li class="md-nav__item">
<a href="#constructor" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#public-member-functions" title=" Public member functions" class="md-nav__link">
Public member functions
</a>
</li>
<li class="md-nav__item">
<a href="#data-structures" title=" Data structures" class="md-nav__link">
Data structures
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
@ -998,40 +937,6 @@
How erase the credentials saved in EEPROM?
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#include-header" title=" Include header" class="md-nav__link">
Include header
</a>
</li>
<li class="md-nav__item">
<a href="#constructor" title=" Constructor" class="md-nav__link">
Constructor
</a>
</li>
<li class="md-nav__item">
<a href="#public-member-functions" title=" Public member functions" class="md-nav__link">
Public member functions
</a>
</li>
<li class="md-nav__item">
<a href="#data-structures" title=" Data structures" class="md-nav__link">
Data structures
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
@ -1257,117 +1162,7 @@ wdt reset
</table>
</div>
<h2 id="how-erase-the-credentials-saved-in-eeprom"><i class="fa fa-question-circle"></i> How erase the credentials saved in EEPROM?<a class="headerlink" href="#how-erase-the-credentials-saved-in-eeprom" title="Permanent link">&para;</a></h2>
<p>Make some sketches for erasing the EEPROM area, or some erasing utility is needed. You can prepare the sketch to erase the saved credential with <em>AutoConnectCredential</em>. The <em>AutoConnectCrendential</em> class provides the access method to the saved credential in EEPROM and library source file is including it.</p>
<p>A class description of AutoConnectCredential is follows.</p>
<h3 id="include-header"><i class="fa fa-code"></i> Include header<a class="headerlink" href="#include-header" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #75715e">#include</span> <span style="color: #75715e">&lt;AutoConnectCredential.h&gt;</span>
</pre></div>
<h3 id="constructor"><i class="fa fa-code"></i> Constructor<a class="headerlink" href="#constructor" title="Permanent link">&para;</a></h3>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectCredential();</span>
</pre></div>
<p>AutoConnectCredential default constructor. The default offset value is 0. If the offset value is 0, the credential storage area starts from the top of the EEPROM. AutoConnect sometimes overwrites data when using this area with user sketch.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #f8f8f2">AutoConnectCredential(</span><span style="color: #66d9ef">uint16_t</span> <span style="color: #f8f8f2">offset);</span>
</pre></div>
<p>Specify offset from the top of the EEPROM for the credential storage area together. The offset value is from 0 to the flash sector size.</p>
<h3 id="public-member-functions"><i class="fa fa-code"></i> Public member functions<a class="headerlink" href="#public-member-functions" title="Permanent link">&para;</a></h3>
<ul>
<li>
<p>uint8_t <strong>entries()</strong><br />
Returns number of entries as contained credentials.</p>
</li>
<li>
<p>int8_t <strong>load(const char* <em>ssid</em>, struct station_config* <em>config</em>)</strong><br />
Load a credential entry specified <em>ssid</em> to <em>config</em>. Returns -1 as unsuccessfully loaded.</p>
</li>
<li>
<p>bool <strong>load(int8_t <em>entry</em>, struct station_config* <em>config</em>)</strong><br />
Load a credential entry to <em>config</em>. The <em>entry</em> parameter specify to index of the entry.</p>
</li>
<li>
<p>bool <strong>save(const struct station_config* <em>config</em>)</strong><br />
Save a credential entry stored in <em>config</em> to EEPROM. Returns the true as succeeded.</p>
</li>
<li>
<p>bool <strong>del(const char* <em>ssid</em>)</strong><br />
Delete a credential entry specified <em>ssid</em>. Returns the true as successfully deleted.</p>
</li>
</ul>
<h3 id="data-structures"><i class="fa fa-code"></i> Data structures<a class="headerlink" href="#data-structures" title="Permanent link">&para;</a></h3>
<ul>
<li>station_config<br />
A structure is included in the ESP8266 SDK. You can use it in the sketch like as follows.</li>
</ul>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">extern</span> <span style="color: #e6db74">&quot;C&quot;</span> <span style="color: #f8f8f2">{</span>
<span style="color: #75715e">#include</span> <span style="color: #75715e">&lt;user_interface.h&gt;</span>
<span style="color: #f8f8f2">}</span>
</pre></div>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">struct</span> <span style="color: #f8f8f2">station_config</span> <span style="color: #f8f8f2">{</span>
<span style="color: #f8f8f2">uint8</span> <span style="color: #f8f8f2">ssid[</span><span style="color: #ae81ff">32</span><span style="color: #f8f8f2">];</span>
<span style="color: #f8f8f2">uint8</span> <span style="color: #f8f8f2">password[</span><span style="color: #ae81ff">64</span><span style="color: #f8f8f2">];</span>
<span style="color: #f8f8f2">uint8</span> <span style="color: #f8f8f2">bssid_set;</span>
<span style="color: #f8f8f2">uint8</span> <span style="color: #f8f8f2">bssid[</span><span style="color: #ae81ff">6</span><span style="color: #f8f8f2">];</span>
<span style="color: #f8f8f2">};</span>
</pre></div>
<ul>
<li>EEPROM data structure<br />
A data structure of the credential saving area in EEPROM as the below. <sup id="fnref:1"><a class="footnote-ref" href="#fn:1" rel="footnote">1</a></sup></li>
</ul>
<table>
<thead>
<tr>
<th>Byte offset</th>
<th>Length</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>8</td>
<td>AC_CREDT</td>
</tr>
<tr>
<td>8</td>
<td>1</td>
<td>Number of contained entries (uint8_t)</td>
</tr>
<tr>
<td>9</td>
<td>2</td>
<td>Container size, excluding size of AC_CREDT and size of the number of entries(width for uint16_t type).</td>
</tr>
<tr>
<td>11</td>
<td>variable</td>
<td>SSID terminated by 0x00. Max length is 32 bytes.</td>
</tr>
<tr>
<td>variable</td>
<td>variable</td>
<td>Password plain text terminated by 0x00. Max length is 64 bytes.</td>
</tr>
<tr>
<td>variable</td>
<td>6</td>
<td>BSSID</td>
</tr>
<tr>
<td>variable</td>
<td></td>
<td>Contained the next entries. (Continuation SSID+Password+BSSID)</td>
</tr>
<tr>
<td>variable</td>
<td>1</td>
<td>0x00. End of container.</td>
</tr>
</tbody>
</table>
<p>Make some sketches for erasing the EEPROM area, or some erasing utility is needed. You can prepare the sketch to erase the saved credential with <em>AutoConnectCredential</em>. The <em>AutoConnectCrendential</em> class provides the access method to the saved credential in EEPROM and library source file is including it. Refer to '<a href="credit.html#saved-credential-in-eeprom">Saved credential access</a>' on section <a href="credit.html">Appendix</a> for details.</p>
<div class="admonition hint">
<p class="admonition-title">Hint</p>
<p>With the <a href="https://github.com/Hieromon/ESPShaker"><strong>ESPShaker</strong></a>, you can access EEPROM interactively from the serial monitor, and of course you can erase saved credentials.</p>
@ -1417,12 +1212,12 @@ wdt reset
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #75715e">#define AC_DEBUG</span>
</pre></div>
<p><i class="fas fa-angle-right"></i> PageBuilder.h <sup id="fnref:2"><a class="footnote-ref" href="#fn:2" rel="footnote">2</a></sup></p>
<p><i class="fas fa-angle-right"></i> PageBuilder.h <sup id="fnref:2"><a class="footnote-ref" href="#fn:2" rel="footnote">1</a></sup></p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #75715e">#define PB_DEBUG</span>
</pre></div>
<h3 id="4-reports-the-issue-to-autoconnect-github-repository">4. Reports the issue to AutoConnect Github repository<a class="headerlink" href="#4-reports-the-issue-to-autoconnect-github-repository" title="Permanent link">&para;</a></h3>
<p>If you can not solve AutoConnect problems please report to <a href="https://github.com/Hieromon/AutoConnect/issues">Issues</a>. And please make your question comprehensively, not a statement. Include all relevant information to start the problem diagnostics as follows:<sup id="fnref:3"><a class="footnote-ref" href="#fn:3" rel="footnote">3</a></sup></p>
<p>If you can not solve AutoConnect problems please report to <a href="https://github.com/Hieromon/AutoConnect/issues">Issues</a>. And please make your question comprehensively, not a statement. Include all relevant information to start the problem diagnostics as follows:<sup id="fnref:3"><a class="footnote-ref" href="#fn:3" rel="footnote">2</a></sup></p>
<ul class="task-list">
<li class="task-list-item"><input type="checkbox" disabled/> Hardware module</li>
<li class="task-list-item"><input type="checkbox" disabled/> Arduino core version Including the upstream commit ID if necessary</li>
@ -1440,14 +1235,11 @@ wdt reset
<div class="footnote">
<hr />
<ol>
<li id="fn:1">
<p>There may be 0xff as an invalid data in the credential saving area. The 0xff area would be reused.&#160;<a class="footnote-backref" href="#fnref:1" rev="footnote" title="Jump back to footnote 1 in the text">&#8617;</a></p>
</li>
<li id="fn:2">
<p><code>PageBuilder.h</code> exists in the <code>libraries/PageBuilder/src</code> directory under your sketch folder.&#160;<a class="footnote-backref" href="#fnref:2" rev="footnote" title="Jump back to footnote 2 in the text">&#8617;</a></p>
<p><code>PageBuilder.h</code> exists in the <code>libraries/PageBuilder/src</code> directory under your sketch folder.&#160;<a class="footnote-backref" href="#fnref:2" rev="footnote" title="Jump back to footnote 1 in the text">&#8617;</a></p>
</li>
<li id="fn:3">
<p>Without this information, the reproducibility of the problem is reduced, making diagnosis and analysis difficult.&#160;<a class="footnote-backref" href="#fnref:3" rev="footnote" title="Jump back to footnote 3 in the text">&#8617;</a></p>
<p>Without this information, the reproducibility of the problem is reduced, making diagnosis and analysis difficult.&#160;<a class="footnote-backref" href="#fnref:3" rev="footnote" title="Jump back to footnote 2 in the text">&#8617;</a></p>
</li>
</ol>
</div>
@ -1471,7 +1263,7 @@ wdt reset
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="lsbegin.html" title="Appendix" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<a href="acupload.html" title="File upload handler" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
@ -1480,7 +1272,7 @@ wdt reset
<span class="md-footer-nav__direction">
Previous
</span>
Appendix
File upload handler
</span>
</div>
</a>
@ -1533,7 +1325,7 @@ wdt reset
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,81 +229,6 @@
<nav class="md-tabs" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link md-tabs__link--active">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -704,12 +629,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -969,7 +942,7 @@ Or, "<strong>RESET</strong>" can be selected. The ESP8266 resets and reboots. Af
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link md-tabs__link--active">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -769,12 +692,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -1135,7 +1106,7 @@
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,81 +229,6 @@
<nav class="md-tabs" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link md-tabs__link--active">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -769,12 +694,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -1011,14 +984,10 @@ Install third-party platform using the <em>Boards Manager</em> of Arduino IDE. P
Install third-party platform using the <em>Boards Manager</em> of Arduino IDE. You can add multiple URLs into <em>Additional Board Manager URLs</em> field, separating them with commas. Package URL is <a href="https://dl.espressif.com/dl/package_esp32_index.json">https://dl.espressif.com/dl/package_esp32_index.json</a> for ESP32.</p>
<p><i class="fa fa-download"></i> <strong>Additional library (Required)</strong></p>
<p>The <a href="https://github.com/Hieromon/PageBuilder">PageBuilder</a> library to build HTML for ESP8266WebServer is needed.<br />
To install the PageBuilder library into your Arduino IDE, you can use the <em>Library Manager</em>. Select the board of ESP8266 series in the Arduino IDE, open the library manager and search keyword '<strong>PageBuilder</strong>' with the topic '<strong>Communication</strong>', then you can see the <em>PageBuilder</em>. The latest version is required <strong>1.3.2</strong> <strong>later</strong>.<sup id="fnref:1"><a class="footnote-ref" href="#fn:1" rel="footnote">1</a></sup></p>
To install the PageBuilder library into your Arduino IDE, you can use the <em>Library Manager</em>. Select the board of ESP8266 series in the Arduino IDE, open the library manager and search keyword '<strong>PageBuilder</strong>' with the topic '<strong>Communication</strong>', then you can see the <em>PageBuilder</em>. The latest version is required <strong>1.3.3</strong> <strong>later</strong>.<sup id="fnref:1"><a class="footnote-ref" href="#fn:1" rel="footnote">1</a></sup></p>
<p><img src="images/lm.png" width="640"/></p>
<p><i class="fa fa-download"></i> <strong>Additional library (Optional)</strong></p>
<p>By adding the <a href="https://github.com/bblanchon/ArduinoJson">ArduinoJson</a> library, AutoConnect will be able to handle the <a href="acintro.html"><strong>custom Web pages</strong></a> described with JSON. With AutoConnect v0.9.7 you can insert user-owned web pages that can consist of representative HTML elements as styled TEXT, INPUT, BUTTON, CHECKBOX, SELECT, SUBMIT and invoke them from the AutoConnect menu. These HTML elements can be added by sketches using the AutoConnect API. Further it possible importing the custom Web pages declarations described with JSON which stored in PROGMEM, SPIFFS, or SD. <a href="https://arduinojson.org/v5/doc/">ArduinoJson version 5</a> is required to use this feature.<sup id="fnref:2"><a class="footnote-ref" href="#fn:2" rel="footnote">2</a></sup></p>
<div class="admonition info">
<p class="admonition-title">AutoConnect supports ArduinoJson version 5 only</p>
<p>ArduinoJson version 6 is just released, Arduino Library Manager installs the ArduinoJson version 6 by default. Open the Arduino Library Manager and make sure that ArduinoJson version 5 is installed.</p>
</div>
<p>By adding the <a href="https://github.com/bblanchon/ArduinoJson">ArduinoJson</a> library, AutoConnect will be able to handle the <a href="acintro.html"><strong>custom Web pages</strong></a> described with JSON. Since AutoConnect v0.9.7 you can insert user-owned web pages that can consist of representative HTML elements as styled TEXT, INPUT, BUTTON, CHECKBOX, SELECT, SUBMIT and invoke them from the AutoConnect menu. These HTML elements can be added by sketches using the AutoConnect API. Further it possible importing the custom Web pages declarations described with JSON which stored in PROGMEM, SPIFFS, or SD. <a href="https://arduinojson.org/">ArduinoJson</a> is required to use this feature.<sup id="fnref:2"><a class="footnote-ref" href="#fn:2" rel="footnote">2</a></sup> AutoConnect can work with ArduinoJson both <a href="https://arduinojson.org/v5/doc/">version 5</a> and <a href="https://arduinojson.org/v6/doc/">version 6</a>.</p>
<h3 id="install-the-autoconnect">Install the AutoConnect<a class="headerlink" href="#install-the-autoconnect" title="Permanent link">&para;</a></h3>
<p>Clone or download from the <a href="https://github.com/Hieromon/AutoConnect">AutoConnect GitHub repository</a>.</p>
<p><img src="images/gitrepo.png" width="640"/></p>
@ -1038,7 +1007,7 @@ To install the PageBuilder library into your Arduino IDE, you can use the <em>Li
<hr />
<ol>
<li id="fn:1">
<p>Since AutoConnect v0.9.7, PageBuilder v1.3.2 later is required.&#160;<a class="footnote-backref" href="#fnref:1" rev="footnote" title="Jump back to footnote 1 in the text">&#8617;</a></p>
<p>Since AutoConnect v0.9.8, PageBuilder v1.3.3 later is required.&#160;<a class="footnote-backref" href="#fnref:1" rev="footnote" title="Jump back to footnote 1 in the text">&#8617;</a></p>
</li>
<li id="fn:2">
<p>Using the AutoConnect API natively allows you to sketch custom Web pages without JSON.&#160;<a class="footnote-backref" href="#fnref:2" rev="footnote" title="Jump back to footnote 2 in the text">&#8617;</a></p>
@ -1113,7 +1082,7 @@ To install the PageBuilder library into your Arduino IDE, you can use the <em>Li
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -225,81 +225,6 @@
<nav class="md-tabs" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link md-tabs__link--active">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -632,12 +557,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -777,7 +750,7 @@ IN THE SOFTWARE.</p>
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,15 +38,15 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
<title>Appendix - AutoConnect for ESP8266/ESP32</title>
<title>Inside AutoConnect::begin - AutoConnect for ESP8266/ESP32</title>
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -164,7 +164,7 @@
AutoConnect for ESP8266/ESP32
</span>
<span class="md-header-nav__topic">
Appendix
Inside AutoConnect::begin
</span>
</div>
@ -229,81 +229,6 @@
<nav class="md-tabs" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link md-tabs__link--active">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -638,17 +563,38 @@
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9" checked>
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
Appendix
Inside AutoConnect::begin
</label>
<a href="lsbegin.html" title="Appendix" class="md-nav__link md-nav__link--active">
Appendix
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link md-nav__link--active">
Inside AutoConnect::begin
</a>
@ -676,6 +622,35 @@
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -755,10 +730,10 @@
<h1>Appendix</h1>
<h1>Inside AutoConnect::begin</h1>
<h2 id="autoconnectbegin-logic-sequence">AutoConnect::begin logic sequence<a class="headerlink" href="#autoconnectbegin-logic-sequence" title="Permanent link">&para;</a></h2>
<p>Several parameters as follows of <a href="apiconfig.html">AutoConnectConfig</a> affect the behavior of <a href="api.html#begin">AutoConnect::begin</a> function. Each parameter affects the behaves in interacted order with the priority and apply to the logic sequence of AutoConnect::begin.</p>
<p>Several parameters as follows of <a href="apiconfig.html">AutoConnectConfig</a> affect the behavior of <a href="api.html#begin">AutoConnect::begin</a> function. Each parameter affects the behaves in interacted order with the priority and apply to the logic sequence of <a href="api.html#begin">AutoConnect::begin</a>.</p>
<ul>
<li><a href="apiconfig.html#immediatestart">immediateStart</a> : The captive portal start immediately, without first WiFi.begin.</li>
<li><a href="apiconfig.html#autoreconnect">autoReconenct</a> : Attempt re-connect with past SSID by saved credential.</li>
@ -767,9 +742,9 @@
</ul>
<p>You can use these parameters in combination with sketch requirements and need to understand correctly the behavior caused by the parameters. The following chart shows the AutoConnect::begin logic sequence including the effect of these parameters.</p>
<p><img align="center" src="images/process_begin.svg"></p>
<p>For example, AutoConnect::begin will not exits without the <strong>portalTimeout</strong> while the connection not establishes, but WebServer will start to work. A DNS server that detects the probe of the captive portal is also effective. So, your sketch may work seemingly, but it will close with inside a loop of the AutoConnect::begin function. Especially when invoking AutoConnect::begin in the <strong>setup()</strong>, execution control does not pass to the <strong>loop()</strong>.</p>
<p>As different scenes, you may use the <strong>immediateStart</strong> effectively. Equipped the external switch to activate the captive portal with the ESP module, combined with the <strong>portalTime</strong> and the <strong>retainPortal</strong> it will become WiFi active connection feature. You can start AutoConnect::begin at any point in the <strong>loop()</strong>, which allows your sketch can behave both the offline mode and the online mode.</p>
<p>The <strong>retainPortal</strong> option allows the DNS server to continue operation after exiting from AutoConnect::begin. AutoConnect traps captive portal detection from the client and redirects it to the AutoConnect menu. That trap will answer all unresolved addresses with SoftAP's IP address. If the URI handler for the source request is undefined, it returns a 302 response with <code>SoftAPIP/_ac</code> to the client. This is the mechanism of AutoConnect's captive portal. Captive portal probes will frequently occur while you are attempting on the client device's WiFi connection Apps and these implementations are varied each OS, so it not realistic to identify all probing URIs. Therefore, while retainPortal is enabled, it is not preferable to executing the sketch under the WiFi connection Apps on the client device. (Probably not work correctly) You need to exit from the WiFi connection Apps once.</p>
<p>For example, <a href="api.html#begin">AutoConnect::begin</a> will not exits without the <a href="apiconfig.html#portaltimeout"><strong>portalTimeout</strong></a> while the connection not establishes, but WebServer will start to work. A DNS server that detects the probe of the captive portal is also effective. So, your sketch may work seemingly, but it will close with inside a loop of the <a href="api.html#begin">AutoConnect::begin</a> function. Especially when invoking <a href="api.html#begin">AutoConnect::begin</a> in the <strong>setup()</strong>, execution control does not pass to the <strong>loop()</strong>.</p>
<p>As different scenes, you may use the <a href="apiconfig.html#immediatestart"><strong>immediateStart</strong></a> effectively. Equipped the external switch to activate the captive portal with the ESP module, combined with the <a href="apiconfig.html#portaltimeout"><strong>portalTime</strong></a> and the <a href="apiconfig.html#retainportal"><strong>retainPortal</strong></a> it will become WiFi active connection feature. You can start <a href="api.html#begin">AutoConnect::begin</a> at any point in the <strong>loop()</strong>, which allows your sketch can behave both the offline mode and the online mode.</p>
<p>The <a href="apiconfig.html#retainportal"><strong>retainPortal</strong></a> option allows the DNS server to continue operation after exiting from <a href="api.html#begin">AutoConnect::begin</a>. AutoConnect traps captive portal detection from the client and redirects it to the AutoConnect menu. That trap will answer all unresolved addresses with SoftAP's IP address. If the URI handler for the source request is undefined, it returns a 302 response with <code>SoftAPIP/_ac</code> to the client. This is the mechanism of AutoConnect's captive portal. Captive portal probes will frequently occur while you are attempting on the client device's WiFi connection Apps and these implementations are varied each OS, so it not realistic to identify all probing URIs. Therefore, while retainPortal is enabled, it is not preferable to executing the sketch under the WiFi connection Apps on the client device. (Probably not work correctly) You need to exit from the WiFi connection Apps once.</p>
<p>Please consider these kinds of influence when you make sketches.</p>
<div class="admonition info">
<p class="admonition-title">The AutoConnect::begin 3<sup>rd</sup> parameter</p>
@ -810,13 +785,13 @@
</a>
<a href="faq.html" title="FAQ" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<a href="credit.html" title="Saved credentail access" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
FAQ
Saved credentail access
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
@ -857,7 +832,7 @@
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,81 +229,6 @@
<nav class="md-tabs" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link md-tabs__link--active">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -726,12 +651,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -1003,7 +976,7 @@ Enter SSID and Passphrase and tap "<strong>apply</strong>" to starts WiFi connec
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link md-tabs__link--active">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -688,12 +611,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -911,7 +882,7 @@
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

File diff suppressed because one or more lines are too long

@ -2,112 +2,122 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://Hieromon.github.io/AutoConnect/index.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/gettingstarted.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/menu.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/basicusage.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/advancedusage.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/acintro.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/acelements.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/acjson.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/achandling.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/api.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/apiaux.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/apiconfig.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/apielements.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/apiextra.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/howtoembed.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/datatips.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/menuize.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/wojson.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/lsbegin.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/credit.html</loc>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/acupload.html</loc>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/faq.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/changelog.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://Hieromon.github.io/AutoConnect/license.html</loc>
<lastmod>2019-03-12</lastmod>
<lastmod>2019-04-14</lastmod>
<changefreq>daily</changefreq>
</url>
</urlset>

Binary file not shown.

@ -38,7 +38,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.0.1">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.1.1">
@ -46,7 +46,7 @@
<link rel="stylesheet" href="assets/stylesheets/application.982221ab.css">
<link rel="stylesheet" href="assets/stylesheets/application.3020aac5.css">
<link rel="stylesheet" href="assets/stylesheets/application-palette.224b79ff.css">
@ -57,7 +57,7 @@
<script src="assets/javascripts/modernizr.1f0bcf2b.js"></script>
<script src="assets/javascripts/modernizr.01ccdecf.js"></script>
@ -229,83 +229,6 @@
<nav class="md-tabs md-tabs--active" data-md-component="tabs">
<div class="md-tabs__inner md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="index.html" title="Overview" class="md-tabs__link">
Overview
</a>
</li>
<li class="md-tabs__item">
<a href="acintro.html" title="Custom Web pages" class="md-tabs__link">
Custom Web pages
</a>
</li>
<li class="md-tabs__item">
<a href="api.html" title="Library APIs" class="md-tabs__link">
Library APIs
</a>
</li>
<li class="md-tabs__item">
<a href="howtoembed.html" title="Examples" class="md-tabs__link md-tabs__link--active">
Examples
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
@ -688,12 +611,60 @@
<li class="md-nav__item">
<a href="lsbegin.html" title="Appendix" class="md-nav__link">
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Appendix
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
Appendix
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link">
Inside AutoConnect::begin
</a>
</li>
<li class="md-nav__item">
<a href="credit.html" title="Saved credentail access" class="md-nav__link">
Saved credentail access
</a>
</li>
<li class="md-nav__item">
<a href="acupload.html" title="File upload handler" class="md-nav__link">
File upload handler
</a>
</li>
</ul>
</nav>
</li>
@ -1024,13 +995,13 @@
</a>
<a href="lsbegin.html" title="Appendix" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Appendix
Inside AutoConnect::begin
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
@ -1071,7 +1042,7 @@
</div>
<script src="assets/javascripts/application.b806dc00.js"></script>
<script src="assets/javascripts/application.dc02f8ce.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

@ -0,0 +1,162 @@
/*
FileUpload.ino, Example for the AutoConnect library.
Copyright (c) 2019, Hieromon Ikasamo
https://github.com/Hieromon/AutoConnect
This software is released under the MIT License.
https://opensource.org/licenses/MIT
FileUpload.ino writes the file uploaded from the HTTP client to SPIFFS
with its file name. To run this example successfully, you need the
SPIFFS area setting with Arduino IDE Tool menu which is larger than
the size of the upload file.
This example leverages the AutoConnectFile element to upload files to
the flash on the ESP8266/ESP32 module. The necessary basic process
for uploading and storing to flash is already embedded in the
AutoConnectFile element. By the sketch, just place the AutoConnectFile
element on a custom web page.
*/
#if defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#elif defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h>
#include <WebServer.h>
#include <SPIFFS.h>
#endif
#include <FS.h>
#include <AutoConnect.h>
// Upload request custom Web page
static const char PAGE_UPLOAD[] PROGMEM = R"(
{
"uri": "/",
"title": "Upload",
"menu": true,
"element": [
{
"name": "caption",
"type": "ACText",
"value": "<h2>File uploading platform<h2>"
},
{
"name": "upload_file",
"type": "ACFile",
"label": "Select file: ",
"store": "fs"
},
{
"name": "upload",
"type": "ACSubmit",
"value": "UPLOAD",
"uri": "/upload"
}
]
}
)";
// Upload result display
static const char PAGE_BROWSE[] PROGMEM = R"(
{
"uri": "/upload",
"title": "Upload",
"menu": false,
"element": [
{
"name": "caption",
"type": "ACText",
"value": "<h2>Uploading ended<h2>"
},
{
"name": "filename",
"type": "ACText"
},
{
"name": "size",
"type": "ACText",
"format": "%s bytes uploaded"
},
{
"name": "content_type",
"type": "ACText",
"format": "Content: %s"
}
]
}
)";
#if defined(ARDUINO_ARCH_ESP8266)
#define FILE_MODE_R "r"
typedef ESP8266WebServer WiFiWebServer;
#elif defined(ARDUINO_ARCH_ESP32)
#define FILE_MODE_R FILE_READ
typedef WebServer WiFiWebServer;
#endif
WiFiWebServer server;
AutoConnect portal(server);
// Declare AutoConnectAux separately as a custom web page to access
// easily for each page in the post-upload handler.
AutoConnectAux auxUpload;
AutoConnectAux auxBrowse;
/**
* Post uploading, AutoConnectFile's built-in upload handler reads the
* file saved in SPIFFS and displays the file contents on /upload custom
* web page. However, only files with mime type uploaded as text are
* displayed. A custom web page handler is called after upload.
* @param aux AutoConnectAux(/upload)
* @param args PageArgument
* @return Uploaded text content
*/
String postUpload(AutoConnectAux& aux, PageArgument& args) {
String content;
// Explicitly cast to the desired element to correctly extract
// the element using the operator [].
AutoConnectFile& upload = auxUpload["upload_file"].as<AutoConnectFile>();
AutoConnectText& aux_filename = aux["filename"].as<AutoConnectText>();
AutoConnectText& aux_size = aux["size"].as<AutoConnectText>();
AutoConnectText& aux_contentType = aux["content_type"].as<AutoConnectText>();
// Assignment operator can be used for the element attribute.
aux_filename.value = upload.value;
aux_size.value = String(upload.size);
aux_contentType.value = upload.mimeType;
// The file saved by the AutoConnect upload handler is read from
// the EEPROM and echoed to a custom web page.
if (upload.mimeType.indexOf("text/") >= 0) {
SPIFFS.begin();
File uploadFile = SPIFFS.open(String("/" + upload.value).c_str(), FILE_MODE_R);
if (uploadFile) {
while (uploadFile.available()) {
char c = uploadFile.read();
if (c == '\n')
content += "<br>";
else
content += c;
}
uploadFile.close();
}
else
content = "Not saved";
SPIFFS.end();
}
return content;
}
void setup() {
delay(1000);
Serial.begin(115200);
Serial.println();
auxUpload.load(PAGE_UPLOAD);
auxBrowse.load(PAGE_BROWSE);
portal.join({ auxUpload, auxBrowse });
auxBrowse.on(postUpload);
portal.begin();
}
void loop() {
portal.handleClient();
}

@ -158,7 +158,7 @@ void setup() {
Timezone.load(AUX_TIMEZONE);
// Retrieve the select element that holds the time zone code and
// register the zone mnemonic in advance.
AutoConnectSelect& tz = Timezone.getElement<AutoConnectSelect>("timezone");
AutoConnectSelect& tz = Timezone["timezone"].as<AutoConnectSelect>();
for (uint8_t n = 0; n < sizeof(TZ) / sizeof(Timezone_t); n++) {
tz.add(String(TZ[n].zone));
}

@ -173,6 +173,7 @@ String userKey;
String apiKey;
String apid;
String hostName;
bool uniqueid;
unsigned int updateInterval = 0;
unsigned long lastPub = 0;
@ -227,14 +228,32 @@ int getStrength(uint8_t points) {
return points ? static_cast<int>(rssi / points) : 0;
}
void getParams(AutoConnectAux& aux) {
serverName = aux["mqttserver"].value;
serverName.trim();
channelId = aux["channelid"].value;
channelId.trim();
userKey = aux["userkey"].value;
userKey.trim();
apiKey = aux["apikey"].value;
apiKey.trim();
AutoConnectRadio& period = aux["period"].as<AutoConnectRadio>();
updateInterval = period.value().substring(0, 2).toInt() * 1000;
uniqueid = aux["uniqueid"].as<AutoConnectCheckbox>().checked;
hostName = aux["hostname"].value;
hostName.trim();
}
// Load parameters saved with saveParams from SPIFFS into the
// elements defined in /mqtt_setting JSON.
String loadParams(AutoConnectAux& aux, PageArgument& args) {
(void)(args);
File param = SPIFFS.open(PARAM_FILE, "r");
if (param) {
if (aux.loadElement(param))
if (aux.loadElement(param)) {
getParams(aux);
Serial.println(PARAM_FILE " loaded");
}
else
Serial.println(PARAM_FILE " failed to load");
param.close();
@ -256,42 +275,19 @@ String loadParams(AutoConnectAux& aux, PageArgument& args) {
String saveParams(AutoConnectAux& aux, PageArgument& args) {
// The 'where()' function returns the AutoConnectAux that caused
// the transition to this page.
AutoConnectAux* mqtt_setting = portal.where();
AutoConnectInput& mqttserver = mqtt_setting->getElement<AutoConnectInput>("mqttserver");
serverName = mqttserver.value;
serverName.trim();
AutoConnectInput& channelid = mqtt_setting->getElement<AutoConnectInput>("channelid");
channelId = channelid.value;
channelId.trim();
AutoConnectInput& userkey = mqtt_setting->getElement<AutoConnectInput>("userkey");
userKey = userkey.value;
userKey.trim();
AutoConnectInput& apikey = mqtt_setting->getElement<AutoConnectInput>("apikey");
apiKey = apikey.value;
apiKey.trim();
AutoConnectRadio& period = mqtt_setting->getElement<AutoConnectRadio>("period");
updateInterval = period.value().substring(0, 2).toInt() * 1000;
bool uniqueid = mqtt_setting->getElement<AutoConnectCheckbox>("uniqueid").checked;
AutoConnectInput& hostname = mqtt_setting->getElement<AutoConnectInput>("hostname");
hostName = hostname.value;
hostName.trim();
AutoConnectAux& mqtt_setting = portal.where();
getParams(mqtt_setting);
AutoConnectInput& mqttserver = mqtt_setting["mqttserver"].as<AutoConnectInput>();
// The entered value is owned by AutoConnectAux of /mqtt_setting.
// To retrieve the elements of /mqtt_setting, it is necessary to get
// the AutoConnectAux object of /mqtt_setting.
File param = SPIFFS.open(PARAM_FILE, "w");
mqtt_setting->saveElement(param, { "mqttserver", "channelid", "userkey", "apikey", "uniqueid", "hostname" });
mqtt_setting.saveElement(param, { "mqttserver", "channelid", "userkey", "apikey", "uniqueid", "period", "hostname" });
param.close();
// Echo back saved parameters to AutoConnectAux page.
AutoConnectText& echo = aux.getElement<AutoConnectText>("parameters");
AutoConnectText& echo = aux["parameters"].as<AutoConnectText>();
echo.value = "Server: " + serverName;
echo.value += mqttserver.isValid() ? String(" (OK)") : String(" (ERR)");
echo.value += "<br>Channel ID: " + channelId + "<br>";
@ -354,15 +350,15 @@ void setup() {
SPIFFS.begin();
if (portal.load(FPSTR(AUX_mqtt_setting))) {
AutoConnectAux* mqtt_setting = portal.aux(AUX_SETTING_URI);
AutoConnectCheckbox& uniqueidElm = mqtt_setting->getElement<AutoConnectCheckbox>("uniqueid");
AutoConnectInput& hostnameElm = mqtt_setting->getElement<AutoConnectInput>("hostname");
if (uniqueidElm.checked) {
AutoConnectAux& mqtt_setting = *portal.aux(AUX_SETTING_URI);
PageArgument args;
loadParams(mqtt_setting, args);
if (uniqueid) {
config.apid = String("ESP") + "-" + String(GET_CHIPID(), HEX);
Serial.println("apid set to " + config.apid);
}
if (hostnameElm.value.length()) {
config.hostName = hostnameElm.value;
if (hostName.length()) {
config.hostName = hostName;
Serial.println("hostname set to " + config.hostName);
}
config.bootUri = AC_ONBOOTURI_HOME;
@ -382,10 +378,7 @@ void setup() {
}
else {
Serial.println("connection failed:" + String(WiFi.status()));
while (1) {
delay(100);
yield();
}
Serial.println("Needs WiFi connection to start publishing messages");
}
WiFiWebServer& webServer = portal.host();
@ -394,16 +387,19 @@ void setup() {
}
void loop() {
portal.handleClient();
if (updateInterval > 0) {
if (millis() - lastPub > updateInterval) {
if (!mqttClient.connected()) {
mqttConnect();
if (WiFi.status() == WL_CONNECTED) {
// MQTT publish control
if (updateInterval > 0) {
if (millis() - lastPub > updateInterval) {
if (!mqttClient.connected()) {
mqttConnect();
}
String item = String("field1=") + String(getStrength(7));
mqttPublish(item);
mqttClient.loop();
lastPub = millis();
}
String item = String("field1=") + String(getStrength(7));
mqttPublish(item);
mqttClient.loop();
lastPub = millis();
}
}
portal.handleClient();
}

@ -149,7 +149,7 @@ String saveParams(AutoConnectAux& aux, PageArgument& args) {
param.close();
// Echo back saved parameters to AutoConnectAux page.
AutoConnectText& echo = aux.getElement<AutoConnectText>("parameters");
AutoConnectText& echo = aux["parameters"].as<AutoConnectText>();
echo.value = "Server: " + serverName + "<br>";
echo.value += "Channel ID: " + channelId + "<br>";
echo.value += "User Key: " + userKey + "<br>";
@ -231,9 +231,10 @@ void setup() {
AutoConnectAux* setting = portal.aux(AUX_MQTTSETTING);
if (setting) {
PageArgument args;
loadParams(*setting, args);
AutoConnectCheckbox& uniqueidElm = setting->getElement<AutoConnectCheckbox>("uniqueid");
AutoConnectInput& hostnameElm = setting->getElement<AutoConnectInput>("hostname");
AutoConnectAux& mqtt_setting = *setting;
loadParams(mqtt_setting, args);
AutoConnectCheckbox& uniqueidElm = mqtt_setting["uniqueid"].as<AutoConnectCheckbox>();
AutoConnectInput& hostnameElm = mqtt_setting["hostname"].as<AutoConnectInput>();
if (uniqueidElm.checked) {
config.apid = String("ESP") + "-" + String(GET_CHIPID(), HEX);
Serial.println("apid set to " + config.apid);

@ -8,6 +8,7 @@ AutoConnectAux KEYWORD1
AutoConnectButton KEYWORD1
AutoConnectCheckbox KEYWORD1
AutoConnectElement KEYWORD1
AutoConnectFile KEYWORD1
AutoConnectInput KEYWORD1
AutoConnectRadio KEYWORD1
AutoConnectSelect KEYWORD1
@ -39,6 +40,7 @@ name KEYWORD2
on KEYWORD2
onDetect KEYWORD2
onNotFound KEYWORD2
onUpload KEYWORD2
release KEYWORD2
save KEYWORD2
saveElement KEYWORD2
@ -64,6 +66,7 @@ AC_EXIT_BOTH LITERAL1
AC_Button LITERAL1
AC_Checkbox LITERAL1
AC_Element LITERAL1
AC_File LITERAL1
AC_Input LITERAL1
AC_Radio LITERAL1
AC_Select LITERAL1
@ -76,6 +79,7 @@ AC_Text LITERAL1
ACButton PREPROCESSOR
ACCheckbox PREPROCESSOR
ACElement PREPROCESSOR
ACFile PREPROCESSOR
ACInput PREPROCESSOR
ACRadio PREPROCESSOR
ACSelect PREPROCESSOR

@ -12,7 +12,7 @@
[
{
"name": "PageBuilder",
"version": ">=1.3.2"
"version": ">=1.3.3"
},
{
"name": "ArduinoJson",
@ -25,6 +25,6 @@
"espressif8266",
"espressif32"
],
"version": "0.9.7",
"version": "0.9.8",
"license": "MIT"
}

@ -1,5 +1,5 @@
name=AutoConnect
version=0.9.7
version=0.9.8
author=Hieromon Ikasamo <hieromon@gmail.com>
maintainer=Hieromon Ikasamo <hieromon@gmail.com>
sentence=ESP8266/ESP32 WLAN configuration at runtime with web interface.

@ -30,7 +30,10 @@ nav:
- 'Tips for data conversion': datatips.md
- 'Attach the menu': menuize.md
- 'Custom Web pages w/o JSON': wojson.md
- 'Appendix': lsbegin.md
- 'Appendix':
- 'Inside AutoConnect::begin': lsbegin.md
- 'Saved credentail access': credit.md
- 'File upload handler': acupload.md
- 'FAQ' : faq.md
- 'Change log' : changelog.md
- 'License' : license.md
@ -48,7 +51,7 @@ use_directory_urls: false
theme:
name: 'material'
feature:
tabs: true
tabs: false
language: 'en'
logo: 'images/arduino-logo.svg'
palette:

@ -5,6 +5,7 @@ Representative HTML elements for making the custom Web page are provided as Auto
- [AutoConnectButton](#autoconnectbutton): Labeled action button
- [AutoConnectCheckbox](#autoconnectcheckbox): Labeled checkbox
- [AutoConnectElement](#autoconnectelement-a-basic-class-of-elements): General tag
- [AutoConnectFile](#autoconnectfile): File uploader
- [AutoConnectInput](#autoconnectinput): Labeled text input box
- [AutoConnectRadio](#autoconnectradio): Labeled radio button
- [AutoConnectSelect](#autoconnectselect): Selection list
@ -63,6 +64,7 @@ The enumerators for *ACElement_t* are as follows:
- AutoConnectButton: **AC_Button**
- AutoConnectCheckbox: **AC_Checkbox**
- AutoConnectElement: **AC_Element**
- AutoConnectFile: **AC_File**
- AutoConnectInput: **AC_Input**
- AutoConnectRadio: **AC_Radio**
- AutoConnectSelect: **AC_Select**
@ -70,7 +72,21 @@ The enumerators for *ACElement_t* are as follows:
- AutoConnectText: **AC_Text**
- Uninitialized element: **AC_Unknown**
Furthermore, to convert an entity that is not an AutoConnectElement to its native type, you must [re-interpret](https://en.cppreference.com/w/cpp/language/reinterpret_cast) that type with c++.
Furthermore, to convert an entity that is not an AutoConnectElement to its native type, you must [re-interpret](https://en.cppreference.com/w/cpp/language/reinterpret_cast) that type with c++. Or, you can be coding the sketch more easily with using the [**as<T\>**](apielements.md#ast62) function.
```cpp hl_lines="6"
AutoConnectAux customPage;
AutoConnectElementVT& elements = customPage.getElements();
for (AutoConnectElement& elm : elements) {
if (elm.type() == AC_Text) {
AutoConnectText& text = customPage[elm.name].as<AutoConnectText>();
text.style = "color:gray;";
// Or, it is also possible to write the code further reduced as follows.
// customPage[elm.name].as<AutoConnectText>().style = "color:gray;";
}
}
```
## AutoConnectButton
@ -147,6 +163,44 @@ Only <i class="far fa-square"></i> will be displayed if a label is not specified
A checked is a Boolean value and indicates the checked status of the checkbox. The value of the checked checkbox element is packed in the query string and sent.
## AutoConnectFile
AutoConnectFile generates asn HTML `#!html <input type="file">` tag and a `#!html <label>` tag. AutoConnectFile enables file upload from the client through the web browser to ESP8266/ESP32 module. You can select the flash in the module, external SD device or any output destination as the storage of the uploaded file.
<i class="fa fa-eye"></i> **Sample**<br>
<small>**`AutoConnectFile file("file", "", "Upload:", AC_File_FS)`**</small>
<small>On the page:</small><br><img src="images/acfile.png">
### <i class="fa fa-edit"></i> Constructor
```cpp
AutoConnectFile(const char* name, const char* value, const char* label, const ACFile_t store)
```
### <i class="fa fa-caret-right"></i> name
It is the `name` of the AutoConnectFile element and matches the name attribute of the input tag. It also becomes the parameter name of the query string when submitted.
### <i class="fa fa-caret-right"></i> value
File name to be upload. The value contains the value entered by the client browser to the `#!html <input type="file">` tag and is read-only. Even If you give a value to the constructor, it does not affect as an initial value like a default file name.
### <i class="fa fa-caret-right"></i> label
A `label` is an optional string. A label is always arranged on the left side of the input box. Specification of a label will generate an HTML `#!html <label>` tag with an id attribute. The input box and the label are connected by the id attribute.
### <i class="fa fa-caret-right"></i> store
Specifies the destination to save the uploaded file. The destination can be specified the following values in the *ACFile_t* enumeration type.
- **`AC_File_FS`** : Save as the SPIFFS file in flash of ESP8266/ESP32 module.
- **`AC_File_SD`** : Save to an external SD device connected to ESP8266/ESP32 module.
- **`AC_File_Extern`** : Pass the content of the uploaded file to the uploader which is declared by the sketch individually. Its uploader must inherit [**AutoConnectUploadHandler**](acupload.md#to-upload-to-a-device-other-than-flash-or-sd) class and implements *_open*, *_write* and *_close* function.
!!! note "Built-in uploader is ready."
AutoConnect already equips the built-in uploader for saving to the SPIFFS as AC_File_FS and the external SD as AC_File_SD. It is already implemented inside AutoConnect and will store uploaded file automatically.
## AutoConnectInput
AutoConnectInput generates an HTML `#!html <input type="text">` tag and a `#!html <label>` tag. It can also have a placeholder. The value of the input box is passed to the destination in the query string and can be retrieved programmatically. You can also update from the sketches.
@ -303,7 +357,7 @@ AutoConnectText generates an HTML `#!html <div>` tag. A `#!html style` attribute
### <i class="fa fa-edit"></i> Constructor
```cpp
AutoConnectText(const char* name, const char* value, const char* style)
AutoConnectText(const char* name, const char* value, const char* style, const char* format)
```
### <i class="fa fa-caret-right"></i> name
@ -318,6 +372,10 @@ It becomes content and also can contain the native HTML code, but remember that
A `style` specifies the qualification style to give to the content and can use the style attribute format as it is.
### <i class="fa fa-caret-right"></i> format
A `format` is a pointer to a null-terminated multibyte string specifying how to interpret the value. It specifies the conversion format when outputting values. The format string conforms to C-style printf library functions, but depends on the espressif sdk implementation. The conversion specification is valid only in **%s** format. (Left and Right justification, width are also valid.)
## How to coding for the elements
### <i class="fa fa-edit"></i> Declaration for the elements in Sketches
@ -332,6 +390,8 @@ ACButton ( *name* <small>\[</small> , *value* <small>\]</small> <small>\[</small
ACCheckbox ( *name* <small>\[</small> , *value* <small>\]</small> <small>\[</small> , *label* <small>\]</small> <small>\[</small> , **true** | **false** <small>\]</small> )
ACFile ( *name* <small>\[</small> , *value* <small>\]</small> <small>\[</small> , *label* <small>\]</small> <small>\[</small> , **AC\_File\_FS** | **AC\_File\_SD** | **AC\_File\_Extern** <small>\]</small> )
ACInput ( *name* <small>\[</small> , *value* <small>\]</small> <small>\[</small> , *label* <small>\]</small> <small>\[</small> , *pattern* <small>\]</small> <small>\[</small> , *placeholder* <small>\]</small> )
ACRadio ( *name* <small>\[</small> , *values* <small>\]</small> <small>\[</small> , *label* <small>\]</small> <small>\[</small> , **AC\_Horizontal** | **AC\_Vertical** <small>\]</small> <small>\[</small> , *checked* <small>\]</small> )
@ -340,7 +400,7 @@ ACSelect ( *name* <small>\[</small> , *options* <small>\]</small> <small>\[</sma
ACSubmit ( *name* <small>\[</small> , *value* <small>\]</small> <small>\[</small> , *uri* <small>\]</small> )
ACText ( *name* <small>\[</small> , *value* <small>\]</small> <small>\[</small> , *style* <small>\]</small> )
ACText ( *name* <small>\[</small> , *value* <small>\]</small> <small>\[</small> , *style* <small>\]</small> <small>\[</small> , *format* <small>\]</small> )
!!! memo "Declaration macro usage"
For example, *AutoConnectText* can be declared using macros.

@ -77,7 +77,21 @@ T& AutoConenctAux::getElement<T>(const String& name)
AutoConnectElementVT* AutoConnectAux::getElements(void)
```
The [**getElement**](apiaux.md#getelement) function returns an AutoConnectElement with the specified name as a key. When you use this function, you need to know the type of AutoConnectElement in advance. To retrieve an AutoConnectElement by specifying its type, use the following method.
The [**getElement**](apiaux.md#getelement) function returns an AutoConnectElement with the specified name as a key. When you use this function, you need to know the type of AutoConnectElement in advance and specify its type <T\> to an argument of the getElement. A type of <T\> can be specified as follows.
```cpp
AutoConnectButton& AutoConnectAux::getElement<AutoConnectButton>(const String& name)
AutoConnectCheckbox& AutoConnectAux::getElement<AutoConnectCheckbox>(const String& name)
AutoConnectElement& AutoConnectAux::getElement<AutoConnectElement>(const String& name)
AutoConnectFile& AutoConnectAux::getElement<AutoConnectFile>(const String& name)
AutoConnectInput& AutoConnectAux::getElement<AutoConnectInput>(const String& name)
AutoConnectRadio& AutoConnectAux::getElement<AutoConnectRadio>(const String& name)
AutoConnectSelect& AutoConnectAux::getElement<AutoConnectSelect>(const String& name)
AutoConnectSubmit& AutoConnectAux::getElement<AutoConnectSubmit>(const String& name)
AutoConnectText& AutoConnectAux::getElement<AutoConnectText>(const String& name)
```
To retrieve an AutoConnectElement by specifying its type, use the following method.
```cpp
AutoConnectAux aux;
@ -101,6 +115,30 @@ AutoConenctText& text = aux->getElement<AutoConnectText>("caption"); // Cast to
Serial.println(text.value);
```
You can also use the [operator **`[]`** of AutoConnectAux](apiaux.md#operator) as another way to get the desired element. An operator **`[]`** is a shortcut for [getElement](apiaux.md#getelement) function with the reference casting and makes simplify the sketch code and treats like an array with the elements placed on a custom Web page. Its argument is the name of the element to be acquired similarly to getElement function. In the sketch, by combining the [**AutoConnectElement::as<T\>**](apielements.md#ast62) function with the operator `[]`, you can access the AutoConnectElements reference according to its actual type. For example, the following sketch code returns the same as a reference of AutoConnectText element as the `caption`.
```cpp hl_lines="4 5"
AutoConnect portal;
portal.load(auxJson);
AutoConnectAux& aux = *portal.aux("/page1");
AutoConnectText& text1 = aux.getElement<AutoConnectElement>("caption");
AutoConnectText& text2 = aux["caption"].as<AutoConnectText>();
```
!!! note "Need cast to convert to the actual type"
An operator `[]` returns a referene of an AutoConnectElement. It is necessary to convert the type according to the actual element type with [AutoConnectElement::as<T\>](apielements.md#ast62) functon.
```cpp
AutoConnectButton& AutoConnectElement::as<AutoConnectButton>()
AutoConnectCheckbox& AutoConnectElement::as<AutoConnectCheckbox>()
AutoConnectElement& AutoConnectElement::as<AutoConnectElement>()
AutoConnectFile& AutoConnectElement::as<AutoConnectFile>()
AutoConnectInput& AutoConnectElement::as<AutoConnectInput>()
AutoConnectRadio& AutoConnectElement::as<AutoConnectRadio>()
AutoConnectSelect& AutoConnectElement::as<AutoConnectSelect>()
AutoConnectSubmit& AutoConnectElement::as<AutoConnectSubmit>()
AutoConnectText& AutoConnectElement::as<AutoConnectText>()
```
To get all the AutoConnectElements in an AutoConnectAux object use the [**getElements**](apiaux.md#getelements) function. This function returns the vector of the reference wrapper as **AutoConnectElementVT** to all AutoConnectElements registered in the AutoConnectAux.
```cpp

@ -120,6 +120,7 @@ JSON description for AutoConnectElements describes as an array in the *element*
: - AutoConnectButton: [**ACButton**](#acbutton)
: - AutoConnectCheckbox: [**ACCheckbox** ](#accheckbox)
: - AutoConnectElement: [**ACElement**](#acelement)
: - AutoConnectFile: [**ACFile**](#acfile)
: - AutoConnectInput: [**ACInput**](#acinput)
: - AutoConnectRadio: [**ACRadio**](#acradio)
: - AutoConnectSelect: [**ACSelect**](#acselect)
@ -142,6 +143,14 @@ This is different for each AutoConnectElements, and the key that can be specifie
#### <i class="fa fa-caret-right"></i> ACElement
: - **value** : Specifies the source code of generating HTML. The value is native HTML code and is output as HTML as it is.
#### <i class="fa fa-caret-right"></i> ACFile
: - **value** : The file name of the upload file will be stored. The `value` is read-only and will be ignored if specified.
: - **label** : Specifies a label of the file selection box. Its placement is always to the left of the file selection box.
: - **store** : Specifies the destination to save the uploaded file. Its value accepts one of the following:<p>
<b>fs</b>&nbsp;: Save as the SPIFFS file in flash of ESP8266/ESP32 module.<br>
<b>sd</b>&nbsp;: Save to an external SD device connected to ESP8266/ESP32 module.<br>
<b>extern</b>&nbsp;: Pass the content of the uploaded file to the uploader which is declared by the sketch individually. Its uploader must inherit [**AutoConnectUploadHandler**](acupload.md#to-upload-to-a-device-other-than-flash-or-sd) class and implements *_open*, *_write* and *_close* function.</p>
#### <i class="fa fa-caret-right"></i> ACInput
: - **value** : Specifies the initial text string of the input box. If this value is omitted, placeholder is displayed as the initial string.
: - **label** : Specifies a label of the input box. Its placement is always to the left of the input box.
@ -167,12 +176,15 @@ This is different for each AutoConnectElements, and the key that can be specifie
#### <i class="fa fa-caret-right"></i> ACText
: - **value** : Specifies a content and also can contain the native HTML code, but remember that your written code is enclosed by the div tag.
: - **style** : Specifies the qualification style to give to the content and can use the style attribute format as it is.
: - **format** : Specifies how to interpret the value. It specifies the conversion format when outputting values. The format string conforms to the C-style printf library functions, but depends on the espressif sdk implementation. The conversion specification is valid only for **%s** format. (Left and Right justification, width are also valid.)
!!! caution "AutoConnect's JSON parsing process is not perfect"
It is based on ArduinoJson, but the process is simplified to save memory. As a result, even if there is an unnecessary key, it will not be an error. It is ignored.
It is based on analysis by ArduinoJson, but the semantic analysis is simplified to save memory. Consequently, it is not an error that a custom Web page JSON document to have unnecessary keys. It will be ignored.
## Loading JSON document
### <i class="fa fa-caret-right"></i> Loading from the streamed file
AutoConnect supports loading of JSON document from the following instances:
- String
@ -223,6 +235,30 @@ aux.close();
AutoConnect passes the given JSON document directly to the [**parseObject()**](https://arduinojson.org/v5/api/jsonbuffer/parseobject/) function of the ArduinoJson library for parsing. Therefore, the constraint of the parseObject() function is applied as it is in the parsing of the JSON document for the AutoConnect. That is, if the JSON string is read-only, duplicating the input string occurs and consumes more memory.
### <i class="fa fa-caret-right"></i> Adjust the JSON document buffer size
AutoConnect uses ArduinoJson library's dynamic buffer to parse JSON documents. Its dynamic buffer allocation scheme depends on the version 5 or version 6 of ArduinoJson library. Either version must have enough buffer to parse the custom web page's JSON document successfully. AutoConnect has the following three constants internally to complete the parsing as much as possible in both ArduinoJson version. These constants are macro defined in [AutoConnectDefs.h](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDefs.h).
If memory insufficiency occurs during JSON document parsing, you can adjust these constants to avoid insufficiency by using the [JsonAssistant](https://arduinojson.org/v6/assistant/) with deriving the required buffer size in advance.
```cpp
#define AUTOCONNECT_JSONBUFFER_SIZE 256
#define AUTOCONNECT_JSONDOCUMENT_SIZE (8 * 1024)
#define AUTOCONNECT_JSONPSRAM_SIZE (16* 1024)
```
#### AUTOCONNECT_JSONBUFFER_SIZE
This is a unit size constant of [DynamicJsonBuffer](https://arduinojson.org/v5/faq/what-are-the-differences-between-staticjsonbuffer-and-dynamicjsonbuffer/) and works when the library used is ArduinoJson version 5. A buffer size of the JSON document increases with this unit. This value relates to the impact of the fragmented heap area. If it is too large, may occur run-out of memory.
#### AUTOCONNECT_JSONDOCUMENT_SIZE
This is a size of [DynamicJsonDocument](https://arduinojson.org/v6/api/dynamicjsondocument/) for ArduinoJson version 6. This buffer is not automatically expanding, and the size determines the limit.
#### AUTOCONNECT_JSONPSRAM_SIZE
For ESP32 module equips with PSRAM, you can allocate the JSON document buffer to PSRAM. Buffer allocation to PSRAM will enable when **PSRAM:Enabled** option selected in the Arduino IDE's Board Manager menu. It is available since ArduinoJson 6.10.0.
## Saving JSON document
The sketch can persist AutoConnectElements as a JSON document and also uses [this function](achandling.md#saving-autoconnectelements-with-json) to save the values entered on the custom Web page. And you can reload the saved JSON document into AutoConnectElements as the field in a custom Web page using the [load function](achandling.md#loading-autoconnectaux-autoconnectelements-with-json).

@ -0,0 +1,384 @@
## Uploading file from Web Browser
If you have to write some data individually to the ESP8266/ESP32 module for the sketch behavior, the [AutoConnectFile](acelements.md#autoconnectfile) element will assist with your wants implementation. The AutoConnectFile element produces an HTML `<input type="file">` tag and can save uploaded file to the flash or external SD of the ESP8266/ESP32 module. The handler for saving is built into AutoConnect. You can use it to inject any sketch data such as the initial values for the custom Web page into the ESP module via OTA without using the sketch data upload tool of Arduino-IDE.
<p style="display:block;margin-left:auto;margin-right:auto;width:603px;height:368px;border:1px solid lightgray;"><img data-gifffer="images/upload.gif" data-gifffer-width="601" data-gifffer-height="366""/></p>
## Basic steps of the file upload sketch
Here is the basic procedure of the sketch which can upload files from the client browser using AutoConnectFile:[^1]
[^1]:The AutoConnectFile element can be used with other AutoConnectElements on the same page.
1. Place AutoConnectFile on a custom Web page by writing JSON or constructor code directly with the sketch.
2. Place other AutoConnectElements as needed.
3. Place AutoConnectSubmit on the same custom Web page.
4. Perform the following process in the on-handler of submitting destination:
- Retrieve the [AutoConnectFile instance](apielements.md#autoconnectfile) from the custom Web page where you placed the AutoConnectFile element using the [AutoConnectAux::getElement](apiaux.md#getelement) function or the [operator \[\]](apiaux.md#operator).
- Start access to the device specified as the upload destination. In usually, it depends on the file system's begin function. For example, if you specified Flash's SPIFFS as the upload destination, invokes *SPIFFS.begin()*.
- The [value member](acelements.md#value_3) of AutoConnectFile contains the file name of the upload file. Use its file name to access the uploaded file on the device.
- Invokes the end function associated with the begin to close the device. It is the *SPIFFS.end()** if the flash on the ESP module has been begun for SPIFFS.
The following sketch is an example that implements the above basic steps. The *postUpload* function is the on-handler and retrieves the AutoConnectFile as named `upload_file`. You should note that this handler is **not** for a custom Web page placed with its AutoConnectFile element. The uploaded file should be processed by the handler for the transition destination page from the AutoConnectFile element placed page. AutoConnect built-in upload handler will save the uploaded file to the specified device before invoking the *postUpload* function.
However, If you use uploaded files in different situations, it may be more appropriate to place the actual handling process outside the handler. It applies for the parameter file, etc. The important thing is that you do not have to sketch file reception and storing logic by using the AutoConnectFile element and the upload handler built into the AutoConnect.
```cpp hl_lines="14 53 64 67 70 86"
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <FS.h>
#include <AutoConnect.h>
// Upload request custom Web page
static const char PAGE_UPLOAD[] PROGMEM = R"(
{
"uri": "/",
"title": "Upload",
"menu": true,
"element": [
{ "name":"caption", "type":"ACText", "value":"<h2>File uploading platform<h2>" },
{ "name":"upload_file", "type":"ACFile", "label":"Select file: ", "store":"fs" },
{ "name":"upload", "type":"ACSubmit", "value":"UPLOAD", "uri":"/upload" }
]
}
)";
// Upload result display
static const char PAGE_BROWSE[] PROGMEM = R"(
{
"uri": "/upload",
"title": "Upload",
"menu": false,
"element": [
{ "name":"caption", "type":"ACText", "value":"<h2>Uploading ended<h2>" },
{ "name":"filename", "type":"ACText" },
{ "name":"size", "type":"ACText", "format":"%s bytes uploaded" },
{ "name":"content_type", "type":"ACText", "format":"Content: %s" }
]
}
)";
ESP8266WebServer server;
AutoConnect portal(server);
// Declare AutoConnectAux separately as a custom web page to access
// easily for each page in the post-upload handler.
AutoConnectAux auxUpload;
AutoConnectAux auxBrowse;
/**
* Post uploading, AutoConnectFile's built-in upload handler reads the
* file saved in SPIFFS and displays the file contents on /upload custom
* web page. However, only files with mime type uploaded as text are
* displayed. A custom web page handler is called after upload.
* @param aux AutoConnectAux(/upload)
* @param args PageArgument
* @return Uploaded text content
*/
String postUpload(AutoConnectAux& aux, PageArgument& args) {
String content;
AutoConnectFile& upload = auxUpload["upload_file"].as<AutoConnectFile>();
AutoConnectText& aux_filename = aux["filename"].as<AutoConnectText>();
AutoConnectText& aux_size = aux["size"].as<AutoConnectText>();
AutoConnectText& aux_contentType = aux["content_type"].as<AutoConnectText>();
// Assignment operator can be used for the element attribute.
aux_filename.value = upload.value;
aux_size.value = String(upload.size);
aux_contentType.value = upload.mimeType;
// The file saved by the AutoConnect upload handler is read from
// the EEPROM and echoed to a custom web page.
SPIFFS.begin();
File uploadFile = SPIFFS.open(String("/" + upload.value).c_str(), "r");
if (uploadFile) {
while (uploadFile.available()) {
char c = uploadFile.read();
Serial.print(c);
}
uploadFile.close();
}
else
content = "Not saved";
SPIFFS.end();
return String();
}
void setup() {
delay(1000);
Serial.begin(115200);
Serial.println();
auxUpload.load(PAGE_UPLOAD);
auxBrowse.load(PAGE_BROWSE);
portal.join({ auxUpload, auxBrowse });
auxBrowse.on(postUpload);
portal.begin();
}
void loop() {
portal.handleClient();
}
```
## Where will the file upload
The AutoConnect built-in upload handler can save the upload file to three locations:
1. Flash memory embedded in the ESP8266/ESP32 module
2. SD device externally connected to the ESP8266/ESP32 module
3. Other character devices
You can specify the device type to save with the [**store**](acelements.md#store) attribute of AutoConenctFile, and it accepts the following values:
- Flash : `AC_File_FS` for the API parameter or `fs` for the JSON document
- SD : `AC_File_SD` for the API parameter or `sd` for the JSON document
- Other : `AC_File_Extern` for the API parameter or `extern` for the JSON document
The substance of AC_File_FS (fs) is a SPIFFS file system implemented by the ESP8266/ESP32 core, and then AutoConnect uses the Global Instance **SPIFFS** to access SPIFFS.
Also, the substance of AC_File_SD (sd) is a FAT file of Arduino SD library ported to the ESP8266/ESP32 core, and then AutoConnect uses the Global Instance **SD** to access SD. When saving to an external SD device, there are additional required parameters for the connection interface and is defined as the macro in AutoConnectDefs.h.
```cpp
#define AUTOCONNECT_SD_CS SS
#define AUTOCONNECT_SD_SPEED 4000000
```
`AUTOCONNECT_SD_CS` defines which GPIO for the CS (Chip Select, or SS as Slave Select) pin. This definition is derived from pins_arduino.h, which is included in the Arduino core distribution. If you want to assign the CS pin to another GPIO, you need to change the macro definition of AutoConnectDefs.h.
`AUTOCONNECT_SD_SPEED` defines SPI clock speed depending on the connected device.
!!! info "Involves both the begin() and the end()"
The built-in uploader executes the begin and end functions regardless of the sketch whence the file system of the device will terminate with the uploader termination. Therefore, to use the device in the sketch after uploading, you need to **restart it with the begin** function.
## When it will be uploaded
Upload handler will be launched by ESP8266WebServer/WebServer(as ESP32) library which is triggered by receiving an HTTP stream of POST BODY including file content. Its launching occurs before invoking the page handler.
The following diagram illustrates the file uploading sequence:
<img src="images/ac_upload_flow.svg">
At the time of the page handler behaves, the uploaded file already saved to the device, and the [member variables](acelements.md#name_3) of AutoConnectFile reflects the file name and transfer size.
## The file name for the uploaded file
AutoConnetFile saves the uploaded file with the file name you selected by `<input type="file">` tag on the browser. The file name used for uploading is stored in the AutoConnetFile's value member, which you can access after uploading. (i.e. In the handler of the destination page by the AutoConnectSubmit element.) You can not save it with a different name. It can be renamed after upload if you need to change the name.
## Upload to a device other than Flash or SD
You can output the file to any device using a custom uploader by specifying [**extern**](acjson.md#acfile) with the [store](acjson.md#acfile) attribute of [AutoConnectFile (or specifying [**AC_File_Extern**](acelements.md#store) for the store member variable) and can customize the uploader according to the need to upload files to other than Flash or SD. Implements your own uploader with inheriting the [**AutoConnectUploadHandler**](#upload-handler-base-class) class which is the base class of the upload handler.
!!! note "It's not so difficult"
Implementing the custom uploader requires a little knowledge of the c++ language. If you are less attuned to programming c++, you may find it difficult. But don't worry. You can make it in various situations by just modifying the sketch skeleton that appears at the end of this page.
### <i class="fa fa-code"></i> Upload handler base class
AutoConnectUploadHandler is a base class of upload handler and It has one public member function and three protected functions.
#### <i class="fa fa-caret-right"></i> Constructor
```cpp
AutoConnectUploadHandler()
```
#### <i class="fa fa-caret-right"></i> Member functions
The **upload** public function is an entry point, the ESP8266WebServer (WebServer as ESP32) library will invoke the upload with each time of uploading content divided into chunks.
Also, the **\_open**, **\_write** and **\_close** protected functions are actually responsible for saving files and are declared as pure virtual functions. A custom uploader class that inherits from the AutoConnectUploadHandler class need to implement these functions.
The actual upload process is handled by the three private functions above, and then upload only invokes three functions according to the upload situation. In usually, there is no need to override the upload function in an inherited class.
```cpp
public virtual void upload(const String& requestUri, const HTTPUpload& upload)
```
<dl class="apidl">
<dt>**Parameters**</dt>
<dd><span class="apidef">requestUri</span><span class="apidesc">URI of upload request source.</span></dd>
<dd><span class="apidef">upload</span><span class="apidesc">A data structure of the upload file as <b>HTTPUpload</b>. It is defined in the ESP8266WebServer (WebServer as ESP32) library as follows:
```cpp
typedef struct {
HTTPUploadStatus status;
String filename;
String name;
String type;
size_t totalSize;
size_t currentSize;
size_t contentLength;
uint8_t buf[HTTP_UPLOAD_BUFLEN];
} HTTPUpload;
```
</span></dd>
</dl>
The upload handler needs to implement processing based on the enumeration value of HTTPUpload.status as **HTTPUploadStatus** enum type. HTTPUploadStatus enumeration is as follows:
- **`UPLOAD_FILE_START`** : Invokes to the \_open.
- **`UPLOAD_FILE_WRITE`** : Invokes to the \_write.
- **`UPLOAD_FILE_END`** : Invokes to the \_close.
- **`UPLOAD_FILE_ABORTED`** : Invokes to the \_close.
The \_open function will be invoked when HTTPUploadStatus is **UPLOAD_FILE_START**. Usually, the implementation of an inherited class will open the file.
```cpp
protected virtual bool _open(const char* filename, const char* mode) = 0
```
<dl class="apidl">
<dt>**Parameters**</dt>
<dd><span class="apidef">filename</span><span class="apidesc">Uploading file name.</span></dd>
<dd><span class="apidef">mode</span><span class="apidesc">An indicator for the file access mode, a "w" for writing.</span></dd>
<dt>**Return value**</dt>
<dd><span class="apidef">true</span><span class="apidesc">File open successful.</span></dd>
<dd><span class="apidef">false</span><span class="apidesc">Failed to open.</span></dd>
</dl>
The \_write function will be invoked when HTTPUploadStatus is **UPLOAD_FILE_WRITE**. The content of the upload file is divided and the \_write will be invoked in multiple times. Usually, the implementation of an inherited class will write data.
```cpp
protected virtual size_t _write(const uint8_t *buf, const size_t size))= 0
```
<dl class="apidl">
<dt>**Parameters**</dt>
<dd><span class="apidef">buf</span><span class="apidesc">File content block.</span></dd>
<dd><span class="apidef">size</span><span class="apidesc">File block size to write.</span></dd>
<dt>**Return value**</dt>
<dd>Size written.</dd>
</dl>
The \_close function will be invoked when HTTPUploadStatus is **UPLOAD_FILE_END** or **UPLOAD_FILE_ABORTED**. Usually, the implementation of an inherited class will close the file.
```cpp
protected virtual void _close(void) = 0
```
For reference, the following AutoConnectUploadFS class is an implementation of AutoConnect built-in uploader and inherits from AutoConnectUploadHandler.
```cpp
class AutoConnectUploadFS : public AutoConnectUploadHandler {
public:
explicit AutoConnectUploadFS(SPIFFST& media) : _media(&media) {}
~AutoConnectUploadFS() { _close(); }
protected:
bool _open(const char* filename, const char* mode) override {
if (_media->begin()) {
_file = _media->open(filename, mode);
return _file != false;
}
return false;
}
size_t _write(const uint8_t* buf, const size_t size) override {
if (_file)
return _file.write(buf, size);
else
return -1;
}
void _close(void) override {
if (_file)
_file.close();
_media->end();
}
private:
SPIFFST* _media;
SPIFileT _file;
};
```
### <i class="fa fa-code"></i> Register custom upload handler
In order to upload a file by the custom uploader, it is necessary to register it to the custom Web page beforehand. To register a custom uploader, specify the custom uploader class name in the template argument of the [AutoConnectAux::onUpload](apiaux.md#onupload) function and invokes it.
```cpp
void AutoConnectAux::onUpload<T>(T& uploadClass)
```
<dl class="apidl">
<dt>**Parameters**</dt>
<dd><span class="apidef">T</span><span class="apidesc">Specifies a class name of the custom uploader. This class name is a class that you implemented by inheriting AutoConnectUploadHandler for custom upload.</span></dd>
<dd><span class="apidef">uploadClass</span><span class="apidesc">Specifies the custom upload class instance.</span></dd>
</dl>
The rough structure of the sketches that completed these implementations will be as follows:
```cpp
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <AutoConnect.h>
static const char PAGE_UPLOAD[] PROGMEM = R"(
{
"uri": "/",
"title": "Upload",
"menu": true,
"element": [
{ "name":"caption", "type":"ACText", "value":"<h2>File uploading platform<h2>" },
{ "name":"upload_file", "type":"ACFile", "label":"Select file: ", "store":"extern" },
{ "name":"upload", "type":"ACSubmit", "value":"UPLOAD", "uri":"/upload" }
]
}
)";
static const char PAGE_RECEIVED[] PROGMEM = R"(
{
"uri": "/upload",
"title": "Upload ended",
"menu": false,
"element": [
{ "name":"caption", "type":"ACText", "value":"<h2>File uploading ended<h2>" }
]
}
)";
// Custom upload handler class
class CustomUploader : public AutoConnectUploadHandler {
public:
CustomUploader() {}
~CustomUploader() {}
protected:
bool _open(const char* filename, const char* mode) override;
size_t _write(const uint8_t *buf, const size_t size) override;
void _close(void) override;
};
// _open for custom open
bool CustomUploader::_open(const char* filename, const char* mode) {
// Here, an implementation for the open file.
}
// _open for custom write
size_t CustomUploader::_write(const uint8_t *buf, const size_t size) {
// Here, an implementation for the writing the file data.
}
// _open for custom close
void CustomUploader::_close(void) {
// Here, an implementation for the close file.
}
AutoConnect portal;
AutoConnectAux uploadPage;
AutoConnectAux receivePage;
CustomUploader uploader; // Declare the custom uploader
void setup() {
uploadPage.load(PAGE_UPLOAD);
receivePage.load(PAGE_RECEIVED);
portal.join({ uploadPage, receivePage });
receivePage.onUpload<CustomUploader>(uploader); // Register the custom uploader
portal.begin();
}
void loop() {
portal.handleClient();
}
```
!!! note "Don't forget to specify the store"
When using a custom uploader, remember to specify the **extern** for the store attribute of AutoConnectFile.
<script>
window.onload = function() {
Gifffer();
};
</script>

@ -2,7 +2,11 @@
### <i class="fa fa-caret-right"></i> 404 handler
Registering the "not found" handler is a different way than ESP8266WebServer/WebServer. The *onNotFound* of ESP8266WebServer/WebServer does not work with AutoConnect. AutoConnect overrides *ESP8266WebServer::onNotFound*/*WebServer::onNotFound* to handle a captive portal. To register "not found" handler, use [*AutoConnect::onNotFound*](api.md#onnotfound).
Registering the "not found" handler is a different way than ESP8266WebServer (WebServer as ESP32). The *onNotFound* of ESP8266WebServer/WebServer does not work with AutoConnect. AutoConnect overrides *ESP8266WebServer::onNotFound*/*WebServer::onNotFound* to handle a captive portal. To register "not found" handler, use [*AutoConnect::onNotFound*](api.md#onnotfound).
### <i class="fa fa-caret-right"></i> Access to saved credentials
AutoConnect stores the established WiFi connection in the EEPROM of the ESP8266/ESP32 module and equips the class to access it from the sketch. You can read, write or erase the credentials using this class individually. It's [AutoConnectCredential](credit.md#autoconnectcredential) class which provides the access method to the saved credentials in EEPROM. Refer to section [Saved credentail access](credit.md) for details.
### <i class="fa fa-caret-right"></i> Automatic reconnect
@ -191,6 +195,19 @@ Executing the above sketch will rewrite the menu title for the **FSBrowser** as
<div style="float:left;width:40%;height:470px;overflow:hidden;"><img src="images/fsbmenu.png"></div>
<img style="margin-left:70px;width:40%;height:470px;" src="images/fsbmenu_expand.png">
### <i class="fa fa-caret-right"></i> Change the menu labels
You can change the label of the AutoConnect menu item by rewriting the default label letter in [AutoConnectLabels.h](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectLabels.h) macros. However, changing menu items letter influences all the sketch's build scenes.
```cpp
#define AUTOCONNECT_MENULABEL_CONFIGNEW "Configure new AP"
#define AUTOCONNECT_MENULABEL_OPENSSIDS "Open SSIDs"
#define AUTOCONNECT_MENULABEL_DISCONNECT "Disconnect"
#define AUTOCONNECT_MENULABEL_RESET "Reset..."
#define AUTOCONNECT_MENULABEL_HOME "HOME"
#define AUTOCONNECT_BUTTONLABEL_RESET "RESET"
```
### <i class="fa fa-caret-right"></i> Combination with mDNS
With [mDNS library](https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266mDNS), you can access to ESP8266 by name instead of IP address after connection. The sketch can start the MDNS responder after [*AutoConnect::begin*](api.md#begin).

@ -57,7 +57,7 @@ Run the AutoConnect site using the externally ensured ESP8266WebServer for ESP82
The [**handleClient**](api.md#handleclient) function of AutoConnect can include the response of the URI handler added by the user using the "*on*" function of ESP8266WebServer/WebServer. If ESP8266WebServer/WebServer is assigned internally by AutoConnect, the sketch can obtain that reference with the [**host**](api.md#host) function.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">webServer</span><span class="apidesc">A reference of ESP8266WebServer or WebServer instance.</span></dd>
</dl>
@ -70,7 +70,7 @@ AutoConnectAux* aux(const String& uri) const
```
Returns a pointer to AutoConnectAux with the URI specified by *uri*. If AutoConnectAux with that URI is not bound, it returns **nullptr**.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">uri</span><span class="apidesc">A string of the URI.</span></dd>
<dt>**Return value**</dt>
<dd>A Pointer of the AutoConnectAux instance.</dd>
@ -124,7 +124,7 @@ Set SoftAP's WiFi configuration and static IP configuration.
### <i class="fa fa-caret-right"></i> end
```cpp
void end()
void end(void)
```
Stops AutoConnect captive portal service. Release ESP8266WebServer/WebServer and DNSServer.
@ -135,7 +135,7 @@ Stops AutoConnect captive portal service. Release ESP8266WebServer/WebServer and
### <i class="fa fa-caret-right"></i> handleClient
```cpp
void handleClient()
void handleClient(void)
```
Process the AutoConnect menu interface. The handleClient() function of the ESP8266WebServer/WebServer hosted by AutoConnect is also called from within AutoConnect, and the client request handlers contained in the user sketch are also handled.
@ -143,7 +143,7 @@ Process the AutoConnect menu interface. The handleClient() function of the ESP82
### <i class="fa fa-caret-right"></i> handleRequest
```cpp
void handleRequest()
void handleRequest(void)
```
Handling for the AutoConnect menu request.
@ -159,7 +159,7 @@ void home(String& uri)
Put a user site's home URI. The URI specified by home is linked from "HOME" in the AutoConnect menu.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">uri</span><span class="aidesc">A URI string of user site's home path.</span></dd>
</dl>
@ -168,13 +168,13 @@ Put a user site's home URI. The URI specified by home is linked from "HOME" in t
- For ESP8266
```cpp
ESP8266WebServer& host()
ESP8266WebServer& host(void)
```
- For ESP32
```cpp
WebServer& host()
WebServer& host(void)
```
Returns the reference of the ESP8266WebServer/WebServer which is allocated in AutoConnect automatically.
@ -204,7 +204,7 @@ void join(std::vector<std::reference_wrapper<AutoConnectAux>> aux)
```
Join the AutoConnectAux object to AutoConnect. AutoConnectAux objects can be joined one by one, or joined altogether. The AutoConnectAux object joined by the join function can be handled from the AutoConnect menu.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">aux</span><span class="apidesc">Reference to AutoConnectAux. It can be std::vector of std::reference_wrapper of AutoConnectAux with [list initialization](https://en.cppreference.com/w/cpp/language/list_initialization).</span></dd>
</dl>
@ -221,7 +221,7 @@ bool load(Stream& aux)
```
Load JSON document of AutoConnectAux which contains AutoConnectElements. If there is a syntax error in the JSON document, false is returned.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">aux</span><span class="apidesc">The input string to be loaded.</span></dd>
<dt>**Return value**</dt>
<dd><span class="apidef">true</span><span class="apidesc">The JSON document as AutoConnectAux successfully loaded.</span></dd>
@ -257,7 +257,7 @@ void onDetect(DetectExit_ft fn)
```
Register the function which will call from AutoConnect at the start of the captive portal.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">fn</span><span class="apidesc">Function called at the captive portal start.</span></dd>
</dl>
@ -268,7 +268,7 @@ An *fn* specifies the function called when the captive portal starts. Its protot
typedef std::function<bool(IPAddress softapIP)> DetectExit_ft
```
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">softapIP</span><span class="apidesc">An IP address of SoftAP for the captive portal.</span></dd>
<dt>**Return value**</dt>
<dd><span class="apidef">true</span><span class="apidesc">Continues captive portal handling.</span></dd>
@ -290,7 +290,7 @@ void onNotFound(WebServer::THandlerFunction fn)
```
Register the handler function for undefined URL request detected.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">fn</span><span class="apidesc">A function of the "not found" handler.</span></dd>
</dl>

@ -15,6 +15,18 @@ AutoConnectAux(const String& uri = String(""), const String& title = String(""),
## <i class="fa fa-code"></i> Public member functions
### <i class="fa fa-caret-right"></i> operator [ ]
```cpp
AutoConnectElement& operator[](const String& name)
```
Returns a reference to the element specified by **name**. An operator `[]` is a shortcut for [getElement](apiaux.md#getelement) function with the reference casting. Unlike getElement, which returns a pointer to that element, an operator `[]` returns a reference to that element. You also need to cast the return value to the actual type, just like the getElement function.
<dl class="apidl">
<dt>**Parameter**</dt>
<dd><span class="apidef">name</span><span class="apidesc">Name of the AutoConnectElements to be retrieved.</span></dd>
<dt>**Return value**</dt><dd>A reference to AutoConnectElement. It is different from the actual element type.</dd>
</dl>
### <i class="fa fa-caret-right"></i> add
```cpp
@ -41,7 +53,7 @@ AutoConnectElement* getElement(const String& name)
Get a registered AutoConnectElement as specified name. If **T** is specified as an actual type of AutoConnectElements, it returns a reference to that instance.
<dl class="apidl">
<dt>**Parameters**</dt>
<dd><span class="apidef">T</span><span class="apidesc">Actual type name of AutoConnectElements as [AutoConnectButton](apielements.md#autoconnectbutton), [AutoConnectCheckbox](apielements.md#autoconnectcheckbox), [AutoConnectElement](apielements.md#autoconnectelement), [AutoConnectInput](apielements.md#autoconnectinput), [AutoConnectRadio](apielements.md#autoconnectradio), [AutoConnectSelect](apielements.md#autoconnectselect), [AutoConnectSubmit](apielements.md#autoconnectsubmit), [AutoConnectText](apielements.md#autoconnecttext).</span></dd>
<dd><span class="apidef">T</span><span class="apidesc">Actual type name of AutoConnectElements as [AutoConnectButton](apielements.md#autoconnectbutton), [AutoConnectCheckbox](apielements.md#autoconnectcheckbox), [AutoConnectElement](apielements.md#autoconnectelement), [AutoConnectFile](apielements.md#autoconnectfile), [AutoConnectInput](apielements.md#autoconnectinput), [AutoConnectRadio](apielements.md#autoconnectradio), [AutoConnectSelect](apielements.md#autoconnectselect), [AutoConnectSubmit](apielements.md#autoconnectsubmit), [AutoConnectText](apielements.md#autoconnecttext).</span></dd>
<dd><span class="apidef">name</span><span class="apidesc">Name of the AutoConnectElements to be retrieved.</span></dd>
<dt>**Return value**</dt><dd>A reference of the AutoConnectElements. If a type is not specified returns a pointer.</dd>
</dl>
@ -82,7 +94,7 @@ bool load(Stream& in)
```
Load all AutoConnectElements elements from JSON document into AutoConnectAux as custom Web pages. The JSON document specified by the load function must be the [document structure](acjson.md#json-objects-elements-for-the-custom-web-page) of AutoConnectAux. Its JSON document can describe multiple pages as an array.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">in</span><span class="apidesc">Specifies the JSON document to be load. The load function can input the following objects.
- String : Read-only String
@ -147,7 +159,7 @@ void menu(const bool post)
```
Set or reset the display as menu item for this AutoConnectAux. This function programmatically manipulates the menu parameter of the [AutoConenctAux constructor](apiaux.md#autoconnectaux).
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">true</span><span class="apidesc">Show on the menu.</span></dd>
<dd><span class="apidef">false</span><span class="apidesc">Hidden on the menu.</span></dd>
</dl>
@ -170,6 +182,36 @@ Register the handler function of the AutoConnectAux.
Called even before generating HTML and after generated.</dd>
</dl>
### <i class="fa fa-caret-right"></i> onUpload
```cpp
void onUpload<T&>(T handler)
```
```cpp
void onUpload(PageBuilder::UploadFuncT uploadFunc)
```
Register the upload handler of the AutoConnectAux.
<dl class="apidl">
<dt>**Parameters**</dt>
<dd><span class="apidef">T</span><span class="apidesc">Specifies a class name of the custom uploader inherited from [AutoConnectUploadHandler](acupload.md#upload-handler-base-class) class. Refer to the [appendix](acupload.md#to-upload-to-a-device-other-than-flash-or-sd) for details.</span></dd>
<dd><span class="apidef">handler</span><span class="apidesc">Specifies the custom uploader inherited from [AutoConnectUploadHandler](acupload.md#upload-handler-base-class) class. Refer to the [appendix](acupload.md#to-upload-to-a-device-other-than-flash-or-sd) for details.</span></dd>
<dd><span class="apidef">uploadFunc</span><span class="apidesc">A function that behaves when request to upload with the AutoConnectAux page. UploadFuncT type is defined by the following declaration.<p class="apidesc">`void(const String&, const HTTPUpload&)`</p><p>A data structure of the upload file as HTTPUpload. It is defined in the ESP8266WebServer (the WebServer for ESP32) library as follows:
```cpp
typedef struct {
HTTPUploadStatus status;
String filename;
String name;
String type;
size_t totalSize;
size_t currentSize;
size_t contentLength;
uint8_t buf[HTTP_UPLOAD_BUFLEN];
} HTTPUpload;
```
</p>Refer to '[To upload to a device other than Flash or SD](acupload.md#to-upload-to-a-device-other-than-flash-or-sd)' in section [appendix](acupload.md) for details.</span></dd>
</dl>
### <i class="fa fa-caret-right"></i> release
```cpp
@ -177,7 +219,7 @@ bool release(const String& name)
```
Release a specified AutoConnectElement from AutoConenctAux. The release function is provided to dynamically change the structure of the custom Web pages with the sketch. By combining the release function and the [add](apiaux.md#add) function or the [loadElement](apiaux.md#loadelement) function, the sketch can change the style of the custom Web page according to its behavior.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">name</span><span class="apidesc">Specifies the name of AutoConnectElements to be released.</span></dd>
<dt>**Return value**</dt>
<dd><span class="apidef">true</span><span class="apidesc">The AutoConnectElement successfully released.</span></dd>

@ -159,6 +159,103 @@ Returns type of AutoConnectElement.
<dd>AC_Element</dd>
</dl>
#### <i class="fa fa-caret-right"></i> as<T\>
```cpp
AutoConnectElement& as<T>(void)
```
Casts the reference to the AutoConnectElement the specified type.
<dl class="apidl">
<dt>**Parameter**</dt>
<dd><span class="apidef">T</span><span class="apidesc">The element type. AutoConnectElements type such as [AutoConnectButton](apielements.md#autoconnectbutton), [AutoConnectCheckbox](apielements.md#autoconnectcheckbox), [AutoConnectFile](apielements.md#autoconnectfile), [AutoConnectInput](apielements.md#autoconnectinput), [AutoConnectRadio](apielements.md#autoconnectradio), [AutoConnectSelect](apielements.md#autoconnectselect), [AutoConnectSubmit](apielements.md#autoconnectsubmit), [AutoConnectText](apielements.md#autoconnecttext).</span></dd>
<dt>**Return value**</dt>
<dd>A reference to the AutoConnectElement with actual type.</dd>
</dl>
## AutoConnectFile
### <i class="fa fa-code"></i> Constructor
```cpp
AutoConnectFile(const char* name = "", const char* value = "", const char* label = "", const ACFile_t store = AC_File_FS)
```
<dl class="apidl">
<dt>**Parameters**</dt>
<dd><span class="apidef">name</span><span class="apidesc">The element name.</span></dd>
<dd><span class="apidef">value</span><span class="apidesc">File name to be upload.</span></dd>
<dd><span class="apidef">label</span><span class="apidesc">Label string.</span></dd>
<dd><span class="apidef">store</span><span class="apidesc">The **ACFile_t** enumerator that represents the media to save the uploaded file.</span></dd>
</dl>
### <i class="fa fa-code"></i> Public member variables
#### <i class="fa fa-caret-right"></i> name
The element name.
<dl class="apidl">
<dt>**Type**</dt>
<dd><span class="apidef">String</span><span class="apidesc"></span></dd>
</dl>
#### <i class="fa fa-caret-right"></i> value
File name to be upload. The value contains the value entered by the client browser to the `#!html <input type="file">` tag and is read-only.
<dl class="apidl">
<dt>**Type**</dt>
<dd><span class="apidef">String</span><span class="apidesc"></span></dd>
</dl>
#### <i class="fa fa-caret-right"></i> label
A label is an optional string. A label is always arranged on the left side of the file input box. Specification of a label will generate an HTML `#!html <label>` tag with an id attribute. The file input box and the label are connected by the id attribute.
<dl class="apidl">
<dt>**Type**</dt>
<dd><span class="apidef">String</span><span class="apidesc"></span></dd>
</dl>
#### <i class="fa fa-caret-right"></i> store
Specifies the save destination of the uploaded file. You can use the built-in uploader to save uploaded file to the flash of the ESP8266/ESP32 module or external SD media without writing a dedicated sketch code. It also supports saving to any destination using a custom uploader that inherits from the AutoConnectUploadHandler class.
<dl class="apidl">
<dt>**Type**</dt>
<dd><span class="apidef">ACFile_t</span><span class="apidesc">
- **`AC_File_FS`** : Save the uploaded file to SPIFFS in the flash.
- **`AC_File_SD`** : Save the uploaded file to SD.
- **`AC_File_Extern`** : Save the file using your own upload handler.
</span></dd>
</dl>
#### <i class="fa fa-caret-right"></i> mimeType
The mime type of the upload file which included as Media type in the http post request. Set by the client (usually the browser) that requested the upload. It is determined by the file type as `application/octet-stream`, `text` etc. which is described in [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml).
<dl class="apidl">
<dt>**Type**</dt>
<dd><span class="apidef">String</span><span class="apidesc"></span></dd>
</dl>
#### <i class="fa fa-caret-right"></i> size
Size of the uploading file.
<dl class="apidl">
<dt>**Type**</dt>
<dd><span class="apidef">size_t</span><span class="apidesc"></span></dd>
</dl>
### <i class="fa fa-code"></i> Public member functions
#### <i class="fa fa-caret-right"></i> typeOf
```cpp
ACElement_t typeOf(void)
```
Returns type of AutoConnectFile.
<dl class="apidl">
<dt>**Return value**</dt>
<dd>AC_File</dd>
</dl>
## AutoConnectInput
### <i class="fa fa-code"></i> Constructor
@ -324,7 +421,7 @@ void add(const String& value)
```
Adds an option for the radio button.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">value</span><span class="apidesc">An option string to add to the radio button.</span></dd>
</dl>
@ -335,7 +432,7 @@ void check(const String& value)
```
Indicates the check of the specified option for the radio buttons. You can use the **check** function for checking dynamically with arbitrary of the radio button.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">value</span><span class="apidesc">An option string to be checked.</span></dd>
</dl>
@ -346,7 +443,7 @@ void empty(const size_t reserve = 0)
```
Clear the array of option strings that AutoConnectRadio has in the values. When a **_reserve_** parameter is specified, a vector container of that size is reserved.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">reserve</span><span class="apidesc">Reserved size of a container for the radio button option strings.</span></dd>
</dl>
@ -357,7 +454,7 @@ const String& operator[] (const std::size_t n)
```
Returns a value string of the index specified by **_n_**.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">n</span><span class="apidesc">Index of values array to return. Its base number is 0.</span></dd>
<dt>**Return value**</dt>
<dd>A reference of a value string indexed by the specified the **n**.</dd>
@ -445,7 +542,7 @@ void add(const String& option)
```
Adds a selectable option string for the selection list.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">option</span><span class="apidesc">A string of selectable item to be contained in the select element.</span></dd>
</dl>
@ -456,7 +553,7 @@ void empty(const size_t reserve = 0)
```
Clear the array of options list that AutoConnectSelect has in the options. When a **_reserve_** parameter is specified, a vector container of that size is reserved.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">reserve</span><span class="apidesc">Reserved size of a container for the options.</span></dd>
</dl>
@ -467,7 +564,7 @@ const String& operator[] (const std::size_t n)
```
Returns an option string of the index specified by **_n_**.
<dl class="apidl">
<dt>**Parameters**</dt>
<dt>**Parameter**</dt>
<dd><span class="apidef">n</span><span class="apidesc">Index of options array to return. Its base number is 0.</span></dd>
<dt>**Return value**</dt>
<dd>A reference of a option string indexed by the specified the **n**.</dd>
@ -543,13 +640,14 @@ Returns type of AutoConnectElement.
### <i class="fa fa-code"></i> Constructor
```cpp
AutoConnectText(const char* name = "", const char* value = "", const char* style = "")
AutoConnectText(const char* name = "", const char* value = "", const char* style = "", const char* format = "")
```
<dl class="apidl">
<dt>**Parameters**</dt>
<dd><span class="apidef">name</span><span class="apidesc">The element name.</span></dd>
<dd><span class="apidef">value</span><span class="apidesc">String of content for the text element.</span></dd>
<dd><span class="apidef">style</span><span class="apidesc">A style code with CSS format that qualifiers the text.</span></dd>
<dd><span class="apidef">format</span><span class="apidesc">A pointer to a null-terminated multibyte string specifying how to interpret the value. It specifies the conversion format when outputting values. The format string conforms to C-style printf library functions</span></dd>
</dl>
### <i class="fa fa-code"></i> Public member variables
@ -578,6 +676,14 @@ A style code with CSS format that qualifiers the text.
<dd><span class="apidef">String</span><span class="apidesc"></span></dd>
</dl>
#### <i class="fa fa-caret-right"></i> format
The conversion format when outputting values. The format string conforms to C-style printf library functions.
<dl class="apidl">
<dt>**Type**</dt>
<dd><span class="apidef">String</span><span class="apidesc"></span></dd>
</dl>
### <i class="fa fa-code"></i> Public member functions
#### <i class="fa fa-caret-right"></i> typeOf

@ -1,3 +1,13 @@
#### [0.9.8] Apr. 25, 2019
- Supports ArduinoJson 6.9.1 or later.
- Supports allocating JsonDocument buffer to PSRAM on ESP32 with ArduinoJson 6.10.0 or later.
- Supports [**operator`[]`**](apiaux.md#operator) as a shortcut for AutoConnectAux::getElement function.
- Supports [**AutoConnectElement::as<T\>**](apielements.md#ast62) function to easily coding for conversion from an AutoConnectElement to an actual type.
- Supports new element type [**AutoConnectFile**](acelements.md#autoconnectfile) and built-in file uploader.
- Supports a [**format attribute**](acelements.md#format) with the AutoConnectText element.
- Fixed blank page responds with Configure new.
- Changed menu labels placement in source files structure.
#### [0.9.7] Jan. 25, 2019
- Fixed crash in some environments. Thank you @ageurtse
@ -35,4 +45,4 @@
#### [0.9.1] March 13, 2018.
- A release of the stable.
- A release of the stable.

@ -0,0 +1,142 @@
## Saved credential in EEPROM
AutoConnect stores the established WiFi connection in the EEPROM of the ESP8266/ESP32 module and equips the class to access it from the sketch. You can read, write or erase the credentials using this class individually. It's [**AutoConnectCredential**](#autoconnectcredential) class which provides the access method to the saved credentials in EEPROM.[^1]
[^1]:An example using AutoConnectCredential is provided as [an example](https://github.com/Hieromon/AutoConnect/blob/master/examples/Credential/Credential.ino) of a library sketch to delete saved credentials.
## AutoConnectCredential
### <i class="fa fa-code"></i> Include header
```cpp
#include <AutoConnectCredential.h>
```
### <i class="fa fa-code"></i> Constructors
```cpp
AutoConnectCredential();
```
AutoConnectCredential default constructor. The default offset value is 0. If the offset value is 0, the credential area starts from the top of the EEPROM. AutoConnect sometimes overwrites data when using this area with user sketch.
```cpp
AutoConnectCredential(uint16_t offset);
```
<dl class="apidl">
<dt>**Parameter**</dt>
<dd><span class="apidef">offset</span><span class="apidesc">Species offset from the top of the EEPROM for the credential area together. The offset value is from 0 to the flash sector size.</span></dd>
</dl>
### <i class="fa fa-code"></i> Public member functions
#### <i class="fa fa-caret-right"></i> entries
```cpp
uint8_t entries(void)
```
Returns number of entries as contained credentials.
<dl class="apidl">
<dt>**Return value**</dt>
<dd>Number of entries as contained credentials.</dd>
</dl>
#### <i class="fa fa-caret-right"></i> load
```cpp
int8_t load(const char* ssid, struct station_config* config)
```
Load a credential entry and store to **config**.
<dl class="apidl">
<dt>**Parameters**</dt>
<dd><span class="apidef">ssid</span><span class="apidesc">SSID to be loaded.</span></dd>
<dd><span class="apidef">config</span><span class="apidesc">station_config</span></dd>
<dt>**Return value**</dt>
<dd>Save the specified SSID's credential entry to station_config pointed to by the parameter as **config**. -1 is returned if the SSID is not saved. </dd>
</dl>
#### <i class="fa fa-caret-right"></i> load
```cpp
bool load(int8_t entry, struct station_config* config)
```
Load a credential entry and store to **config**.
<dl class="apidl">
<dt>**Parameters**</dt>
<dd><span class="apidef">entry</span><span class="apidesc">Specifies the index number based 0 to be loaded.</span></dd>
<dd><span class="apidef">config</span><span class="apidesc">station_config</span></dd>
<dt>**Return value**</dt>
<dd>Save the specified credential entry to station_config pointed to by the parameter as **config**. -1 is returned if specified number is not saved. </dd>
</dl>
#### <i class="fa fa-caret-right"></i> save
```cpp
bool save(const struct station_config* config)
```
Save a credentail entry.
<dl class="apidl">
<dt>**Parameter**</dt>
<dd><span class="apidef">config</span><span class="apidesc">station_config to be saved.</span></dd>
<dt>**Return value**</dt>
<dd><span class="apidef">true</span><span class="apidesc">Successfully saved.</span></dd>
<dd><span class="apidef">false</span><span class="apidesc">Failed to save.</span></dd>
</dl>
#### <i class="fa fa-caret-right"></i> del
```cpp
bool del(const char* ssid)
```
Delete a credential the specified SSID.
<dl class="apidl">
<dt>**Parameter**</dt>
<dd><span class="apidef">ssid</span><span class="apidesc">SSID to be deleted.</span></dd>
<dt>**Return value**</dt>
<dd><span class="apidef">true</span><span class="apidesc">Successfully deleted.</span></dd>
<dd><span class="apidef">false</span><span class="apidesc">Failed to delete.</span></dd>
</dl>
## The data structures
### <i class="fa fa-code"></i> station_config
A structure is included in the ESP8266 SDK. You can use it in the sketch like as follows:
```cpp
extern "C" {
#include <user_interface.h>
}
```
```cpp
struct station_config {
uint8 ssid[32];
uint8 password[64];
uint8 bssid_set;
uint8 bssid[6];
};
```
### <i class="fa fa-code"></i> The credential entry
A data structure of the credential saving area in EEPROM as the below. [^2]
[^2]:
There may be 0xff as an invalid data in the credential saving area. The 0xff area would be reused.
| Byte offset | Length | Value |
|-------------|----------|---------------------------------------------------------------------|
| 0 | 8 | AC_CREDT |
| 8 | 1 | Number of contained entries (uint8_t) |
| 9 | 2 | Container size, excluding size of AC_CREDT and size of the number of entries(width for uint16_t type). |
| 11 | variable | SSID terminated by 0x00. Max length is 32 bytes. |
| variable | variable | Password plain text terminated by 0x00. Max length is 64 bytes. |
| variable | 6 | BSSID |
| variable | | Contained the next entries. (Continuation SSID+Password+BSSID) |
| variable | 1 | 0x00. End of container. |

@ -14,6 +14,10 @@ Use [int()](https://www.arduino.cc/reference/en/language/variables/conversion/in
AutoConnectInput& input = aux.getElement<AutoConnectInput>("INPUT");
int value = input.value.toInt();
```
You can shorten it and write as like:
```cpp
int value = aux["INPUT"].value.toInt();
```
### <i class="fa fa-exchange"></i> Float
@ -23,6 +27,10 @@ Use [float()](https://www.arduino.cc/reference/en/language/variables/conversion/
AutoConnectInput& input = aux.getElement<AutoConnectInput>("INPUT");
float value = input.value.toFloat();
```
You can shorten it and write as like:
```cpp
float value = aux["INPUT"].value.toFloat();
```
### <i class="fa fa-exchange"></i> Date &amp; Time
@ -36,7 +44,7 @@ The easiest way is to use the [Arduino Time Library](https://www.pjrc.com/teensy
time_t tm;
int Year, Month, Day, Hour, Minute, Second;
AutoConnectInput& input = aux.getElement<AutoConnectInput>("INPUT");
AutoConnectInput& input = aux.["INPUT"].as<AutoConnectInput>();
sscanf(input.value.c_str(), "%d-%d-%d %d:%d:%d", &Year, &Month, &Day, &Hour, &Minute, &Second);
tm.Year = CalendarYrToTm(Year);
tm.Month = Month;
@ -52,7 +60,7 @@ To convert a String to an IP address, use **IPAddress::fromString**. To stringiz
```cpp
IPAddress ip;
AutoConnectInput& input aux.getElement<AutoConnectInput>("INPUT");
AutoConnectInput& input aux["INPUT"].as<AutoConnectInput>();
ip.fromString(input.value);
input.value = ip.toString();
```
@ -108,9 +116,9 @@ static const char input_page[] PROGMEM = R"raw(
AutoConnect portal;
String checkIPAddress(AutoConnectAux& aux, PageArgument& args) {
AutoConnectAux* input_page = portal.aux("/");
AutoConnectInput& ipaddress = input_page->getElement<AutoConnectInput>("ipaddress");
AutoConnectText& result = aux.getElement<AutoConnectText>("result");
AutoConnectAux& input_page = *portal.aux("/");
AutoConnectInput& ipaddress = input_page["ipaddress"].as<AutoConnectInput>();
AutoConnectText& result = aux["result"].as<AutoConnectText>();
if (ipaddress.isValid()) {
result.value = "IP Address " + ipaddress.value + " is OK.";

@ -98,83 +98,7 @@ The correct boot mode for starting the sketch is **(3, x)**.
## <i class="fa fa-question-circle"></i> How erase the credentials saved in EEPROM?
Make some sketches for erasing the EEPROM area, or some erasing utility is needed. You can prepare the sketch to erase the saved credential with *AutoConnectCredential*. The *AutoConnectCrendential* class provides the access method to the saved credential in EEPROM and library source file is including it.
A class description of AutoConnectCredential is follows.
### <i class="fa fa-code"></i> Include header
```cpp
#include <AutoConnectCredential.h>
```
### <i class="fa fa-code"></i> Constructor
```cpp
AutoConnectCredential();
```
AutoConnectCredential default constructor. The default offset value is 0. If the offset value is 0, the credential storage area starts from the top of the EEPROM. AutoConnect sometimes overwrites data when using this area with user sketch.
```cpp
AutoConnectCredential(uint16_t offset);
```
Specify offset from the top of the EEPROM for the credential storage area together. The offset value is from 0 to the flash sector size.
### <i class="fa fa-code"></i> Public member functions
- uint8_t **entries()**
Returns number of entries as contained credentials.
- int8_t **load(const char\* _ssid_, struct station_config\* _config_)**
Load a credential entry specified *ssid* to *config*. Returns -1 as unsuccessfully loaded.
- bool **load(int8_t _entry_, struct station_config\* _config_)**
Load a credential entry to *config*. The *entry* parameter specify to index of the entry.
- bool **save(const struct station_config\* _config_)**
Save a credential entry stored in *config* to EEPROM. Returns the true as succeeded.
- bool **del(const char\* _ssid_)**
Delete a credential entry specified *ssid*. Returns the true as successfully deleted.
### <i class="fa fa-code"></i> Data structures
- station_config
A structure is included in the ESP8266 SDK. You can use it in the sketch like as follows.
```cpp
extern "C" {
#include <user_interface.h>
}
```
```cpp
struct station_config {
uint8 ssid[32];
uint8 password[64];
uint8 bssid_set;
uint8 bssid[6];
};
```
- EEPROM data structure
A data structure of the credential saving area in EEPROM as the below. [^1]
[^1]:
There may be 0xff as an invalid data in the credential saving area. The 0xff area would be reused.
| Byte offset | Length | Value |
|-------------|----------|---------------------------------------------------------------------|
| 0 | 8 | AC_CREDT |
| 8 | 1 | Number of contained entries (uint8_t) |
| 9 | 2 | Container size, excluding size of AC_CREDT and size of the number of entries(width for uint16_t type). |
| 11 | variable | SSID terminated by 0x00. Max length is 32 bytes. |
| variable | variable | Password plain text terminated by 0x00. Max length is 64 bytes. |
| variable | 6 | BSSID |
| variable | | Contained the next entries. (Continuation SSID+Password+BSSID) |
| variable | 1 | 0x00. End of container. |
Make some sketches for erasing the EEPROM area, or some erasing utility is needed. You can prepare the sketch to erase the saved credential with *AutoConnectCredential*. The *AutoConnectCrendential* class provides the access method to the saved credential in EEPROM and library source file is including it. Refer to '[Saved credential access](credit.md#saved-credential-in-eeprom)' on section [Appendix](credit.md) for details.
!!! hint
With the [**ESPShaker**](https://github.com/Hieromon/ESPShaker), you can access EEPROM interactively from the serial monitor, and of course you can erase saved credentials.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

@ -85,19 +85,16 @@ Install third-party platform using the *Boards Manager* of Arduino IDE. You can
<i class="fa fa-download"></i> <strong>Additional library (Required)</strong>
The [PageBuilder](https://github.com/Hieromon/PageBuilder) library to build HTML for ESP8266WebServer is needed.
To install the PageBuilder library into your Arduino IDE, you can use the *Library Manager*. Select the board of ESP8266 series in the Arduino IDE, open the library manager and search keyword '**PageBuilder**' with the topic '**Communication**', then you can see the *PageBuilder*. The latest version is required **1.3.2** **later**.[^1]
[^1]:Since AutoConnect v0.9.7, PageBuilder v1.3.2 later is required.
To install the PageBuilder library into your Arduino IDE, you can use the *Library Manager*. Select the board of ESP8266 series in the Arduino IDE, open the library manager and search keyword '**PageBuilder**' with the topic '**Communication**', then you can see the *PageBuilder*. The latest version is required **1.3.3** **later**.[^1]
[^1]:Since AutoConnect v0.9.8, PageBuilder v1.3.3 later is required.
<img src="images/lm.png" width="640"/>
<i class="fa fa-download"></i> <strong>Additional library (Optional)</strong>
By adding the [ArduinoJson](https://github.com/bblanchon/ArduinoJson) library, AutoConnect will be able to handle the [**custom Web pages**](acintro.md) described with JSON. With AutoConnect v0.9.7 you can insert user-owned web pages that can consist of representative HTML elements as styled TEXT, INPUT, BUTTON, CHECKBOX, SELECT, SUBMIT and invoke them from the AutoConnect menu. These HTML elements can be added by sketches using the AutoConnect API. Further it possible importing the custom Web pages declarations described with JSON which stored in PROGMEM, SPIFFS, or SD. [ArduinoJson version 5](https://arduinojson.org/v5/doc/) is required to use this feature.[^2]
By adding the [ArduinoJson](https://github.com/bblanchon/ArduinoJson) library, AutoConnect will be able to handle the [**custom Web pages**](acintro.md) described with JSON. Since AutoConnect v0.9.7 you can insert user-owned web pages that can consist of representative HTML elements as styled TEXT, INPUT, BUTTON, CHECKBOX, SELECT, SUBMIT and invoke them from the AutoConnect menu. These HTML elements can be added by sketches using the AutoConnect API. Further it possible importing the custom Web pages declarations described with JSON which stored in PROGMEM, SPIFFS, or SD. [ArduinoJson](https://arduinojson.org/) is required to use this feature.[^2] AutoConnect can work with ArduinoJson both [version 5](https://arduinojson.org/v5/doc/) and [version 6](https://arduinojson.org/v6/doc/).
[^2]:Using the AutoConnect API natively allows you to sketch custom Web pages without JSON.
!!! info "AutoConnect supports ArduinoJson version 5 only"
ArduinoJson version 6 is just released, Arduino Library Manager installs the ArduinoJson version 6 by default. Open the Arduino Library Manager and make sure that ArduinoJson version 5 is installed.
### Install the AutoConnect
Clone or download from the [AutoConnect GitHub repository](https://github.com/Hieromon/AutoConnect).

@ -1,6 +1,6 @@
## AutoConnect::begin logic sequence
Several parameters as follows of [AutoConnectConfig](apiconfig.md) affect the behavior of [AutoConnect::begin](api.md#begin) function. Each parameter affects the behaves in interacted order with the priority and apply to the logic sequence of AutoConnect::begin.
Several parameters as follows of [AutoConnectConfig](apiconfig.md) affect the behavior of [AutoConnect::begin](api.md#begin) function. Each parameter affects the behaves in interacted order with the priority and apply to the logic sequence of [AutoConnect::begin](api.md#begin).
- [immediateStart](apiconfig.md#immediatestart) : The captive portal start immediately, without first WiFi.begin.
- [autoReconenct](apiconfig.md#autoreconnect) : Attempt re-connect with past SSID by saved credential.
@ -11,14 +11,13 @@ You can use these parameters in combination with sketch requirements and need to
<img align="center" src="images/process_begin.svg">
For example, AutoConnect::begin will not exits without the **portalTimeout** while the connection not establishes, but WebServer will start to work. A DNS server that detects the probe of the captive portal is also effective. So, your sketch may work seemingly, but it will close with inside a loop of the AutoConnect::begin function. Especially when invoking AutoConnect::begin in the **setup()**, execution control does not pass to the **loop()**.
For example, [AutoConnect::begin](api.md#begin) will not exits without the [**portalTimeout**](apiconfig.md#portaltimeout) while the connection not establishes, but WebServer will start to work. A DNS server that detects the probe of the captive portal is also effective. So, your sketch may work seemingly, but it will close with inside a loop of the [AutoConnect::begin](api.md#begin) function. Especially when invoking [AutoConnect::begin](api.md#begin) in the **setup()**, execution control does not pass to the **loop()**.
As different scenes, you may use the **immediateStart** effectively. Equipped the external switch to activate the captive portal with the ESP module, combined with the **portalTime** and the **retainPortal** it will become WiFi active connection feature. You can start AutoConnect::begin at any point in the **loop()**, which allows your sketch can behave both the offline mode and the online mode.
As different scenes, you may use the [**immediateStart**](apiconfig.md#immediatestart) effectively. Equipped the external switch to activate the captive portal with the ESP module, combined with the [**portalTime**](apiconfig.md#portaltimeout) and the [**retainPortal**](apiconfig.md#retainportal) it will become WiFi active connection feature. You can start [AutoConnect::begin](api.md#begin) at any point in the **loop()**, which allows your sketch can behave both the offline mode and the online mode.
The **retainPortal** option allows the DNS server to continue operation after exiting from AutoConnect::begin. AutoConnect traps captive portal detection from the client and redirects it to the AutoConnect menu. That trap will answer all unresolved addresses with SoftAP's IP address. If the URI handler for the source request is undefined, it returns a 302 response with `SoftAPIP/_ac` to the client. This is the mechanism of AutoConnect's captive portal. Captive portal probes will frequently occur while you are attempting on the client device's WiFi connection Apps and these implementations are varied each OS, so it not realistic to identify all probing URIs. Therefore, while retainPortal is enabled, it is not preferable to executing the sketch under the WiFi connection Apps on the client device. (Probably not work correctly) You need to exit from the WiFi connection Apps once.
The [**retainPortal**](apiconfig.md#retainportal) option allows the DNS server to continue operation after exiting from [AutoConnect::begin](api.md#begin). AutoConnect traps captive portal detection from the client and redirects it to the AutoConnect menu. That trap will answer all unresolved addresses with SoftAP's IP address. If the URI handler for the source request is undefined, it returns a 302 response with `SoftAPIP/_ac` to the client. This is the mechanism of AutoConnect's captive portal. Captive portal probes will frequently occur while you are attempting on the client device's WiFi connection Apps and these implementations are varied each OS, so it not realistic to identify all probing URIs. Therefore, while retainPortal is enabled, it is not preferable to executing the sketch under the WiFi connection Apps on the client device. (Probably not work correctly) You need to exit from the WiFi connection Apps once.
Please consider these kinds of influence when you make sketches.
!!! info "The AutoConnect::begin 3rd parameter"
Another parameter as the [3rd parameter](api.md#begin) of AutoConnect::begin related to timeout constrains the connection wait time after WiFi.begin. It is the **CONNECTED** judgment of the above chart that it has an effect.

@ -389,9 +389,8 @@ void AutoConnect::_startWebServer(void) {
// here, Prepare PageBuilders for captive portal
if (!_responsePage) {
_responsePage = new PageBuilder();
_responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER);
_responsePage->reserve(AUTOCONNECT_CONTENTBUFFER_SIZE);
_responsePage->exitCanHandle(std::bind(&AutoConnect::_classifyHandle, this, std::placeholders::_1, std::placeholders::_2));
_responsePage->onUpload(std::bind(&AutoConnect::_handleUpload, this, std::placeholders::_1, std::placeholders::_2));
_responsePage->insert(*_webServer);
_webServer->begin();
@ -598,7 +597,7 @@ void AutoConnect::_stopPortal(void) {
bool AutoConnect::_captivePortal(void) {
String hostHeader = _webServer->hostHeader();
if (!_isIP(hostHeader) && (hostHeader != WiFi.localIP().toString()) && (!hostHeader.endsWith(F(".local")))) {
AC_DBG("Detected appliaction, %s, %s\n", hostHeader.c_str(), WiFi.localIP().toString().c_str());
AC_DBG("Detected application, %s, %s\n", hostHeader.c_str(), WiFi.localIP().toString().c_str());
String location = String(F("http://")) + _webServer->client().localIP().toString() + String(AUTOCONNECT_URI);
_webServer->sendHeader(String(F("Location")), location, true);
_webServer->send(302, String(F("text/plain")), _emptyString);
@ -668,7 +667,7 @@ void AutoConnect::_handleNotFound(void) {
String AutoConnect::_induceReset(PageArgument& args) {
AC_UNUSED(args);
_rfReset = true;
return String(F("Reset in progress..."));
return String(F(AUTOCONNECT_BUTTONLABEL_RESET " in progress..."));
}
/**
@ -788,7 +787,7 @@ String AutoConnect::_invokeResult(PageArgument& args) {
bool AutoConnect::_classifyHandle(HTTPMethod method, String uri) {
AC_UNUSED(method);
_portalAccessPeriod = millis();
AC_DBG("Host:%s, URI:%s", _webServer->hostHeader().c_str(), uri.c_str());
AC_DBG("Host:%s,URI:%s", _webServer->hostHeader().c_str(), uri.c_str());
// When handleClient calls RequestHandler, the parsed http argument
// remains the previous request.
@ -801,6 +800,8 @@ bool AutoConnect::_classifyHandle(HTTPMethod method, String uri) {
AutoConnectAux* aux = _aux.get();
while (aux) {
if (aux->_uriStr == _auxUri) {
// Save the value owned by each element contained in the POST body
// of a current HTTP request to AutoConnectElements.
aux->_storeElements(_webServer.get());
break;
}
@ -810,11 +811,12 @@ bool AutoConnect::_classifyHandle(HTTPMethod method, String uri) {
// Here, classify requested uri
if (uri == _uri) {
AC_DBG_DUMB(", already allocated\n");
AC_DBG_DUMB(",already allocated\n");
return true; // The response page already exists.
}
// Dispose decrepit page
_prevUri = _uri; // Save current uri for the upload request
_purgePages();
// Create the page dynamically
@ -824,15 +826,30 @@ bool AutoConnect::_classifyHandle(HTTPMethod method, String uri) {
_currentPageElement = _aux->_setupPage(uri);
}
if (_currentPageElement != nullptr) {
AC_DBG_DUMB(", generated:%s", uri.c_str());
AC_DBG_DUMB(",generated:%s", uri.c_str());
_uri = uri;
_responsePage->addElement(*_currentPageElement);
_responsePage->setUri(_uri.c_str());
}
AC_DBG_DUMB(", %s\n", _currentPageElement != nullptr ? "allocated" : "ignored");
AC_DBG_DUMB(",%s\n", _currentPageElement != nullptr ? " allocated" : "ignored");
return _currentPageElement != nullptr ? true : false;
}
/**
* A wrapper of the upload function for the WebServerClass. Invokes the
* upload function of the AutoConnectAux which has a destination URI.
*/
void AutoConnect::_handleUpload(const String& requestUri, const HTTPUpload& upload) {
AutoConnectAux* aux = _aux.get();
while (aux) {
if (aux->_uriStr == requestUri) {
aux->upload(_prevUri, upload);
break;
}
aux = aux->_next.get();
}
}
/**
* Purge allocated pages.
*/
@ -841,8 +858,8 @@ void AutoConnect::_purgePages(void) {
if (_currentPageElement != nullptr) {
delete _currentPageElement;
_currentPageElement = nullptr;
_uri = String("");
}
_uri = String("");
}
/**

@ -185,7 +185,7 @@ class AutoConnect {
void join(AutoConnectAux& aux);
void join(AutoConnectAuxVT auxVector);
bool on(const String& uri, const AuxHandlerFunctionT handler, AutoConnectExitOrder_t order = AC_EXIT_AHEAD);
AutoConnectAux* where(void) const { return aux(_auxUri); }
AutoConnectAux& where(void) const { return *aux(_auxUri); }
/** For AutoConnectAux described in JSON */
#ifdef AUTOCONNECT_USE_JSON
@ -216,9 +216,12 @@ class AutoConnect {
bool _loadAvailCredential(void);
void _stopPortal(void);
bool _classifyHandle(HTTPMethod mothod, String uri);
void _handleUpload(const String& requestUri, const HTTPUpload& upload);
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
@ -262,6 +265,7 @@ class AutoConnect {
/** Extended pages made up with AutoConnectAux */
std::unique_ptr<AutoConnectAux> _aux;
String _auxUri; /**< Last accessed AutoConnectAux */
String _prevUri; /**< Previous generated page uri */
/** Saved configurations */
AutoConnectConfig _apConfig;
@ -310,6 +314,12 @@ class AutoConnect {
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_UL(PageArgument& args);
@ -340,6 +350,7 @@ class AutoConnect {
String _token_CHIP_ID(PageArgument& args);
String _token_FREE_HEAP(PageArgument& args);
String _token_LIST_SSID(PageArgument& args);
String _token_SSID_COUNT(PageArgument& args);
String _token_HIDDEN_COUNT(PageArgument& args);
String _token_OPEN_SSID(PageArgument& args);
String _token_UPTIME(PageArgument& args);

@ -2,14 +2,15 @@
* Implementation of AutoConnectAux class.
* @file AutoConnectAuxBasisImpl.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
#include <algorithm>
#include "AutoConnect.h"
#include "AutoConnectAux.h"
#include "AutoConnectElement.h"
#include "AutoConnectAuxImpl.h"
#include "AutoConnectUploadImpl.h"
#include "AutoConnectElementBasisImpl.h"
#ifdef AUTOCONNECT_USE_JSON
#include "AutoConnectElementJsonImpl.h"
@ -43,7 +44,7 @@ const char AutoConnectAux::_PAGE_AUX[] PROGMEM = {
"{{MENU_AUX}}"
"{{MENU_POST}}"
"<div class=\"base-panel\"><div class=\"aux-page\">"
"<form id='_aux' method=\"post\" onsubmit=\"return false;\">"
"<form id='_aux' method=\"post\" onsubmit=\"return false;\" {{ENC_TYPE}}>"
"<ul class=\"noorder\">"
"{{AUX_ELEMENT}}"
"</ul>"
@ -204,6 +205,84 @@ bool AutoConnectAux::setElementValue(const String& name, std::vector<String> con
return rc;
}
/**
* The upload function that overrides the RequestHandler class
* attached with ESP8266WebServer.
* This function invokes the upload handler registered by the onUpload
* function which will be implemented by the user sketch.
*/
void AutoConnectAux::upload(const String& requestUri, const HTTPUpload& upload) {
if (upload.status == UPLOAD_FILE_START) {
AC_DBG("%s requests upload to %s\n", requestUri.c_str(), _uriStr.c_str());
// Selects a valid upload handler before uploading starts.
// Identify AutoConnectFile with the current upload request and
// save the value and mimeType attributes.
AC_DBG("ACFile %s ", upload.name.c_str());
String logContext = "missing";
AutoConnectElementVT addons;
AutoConnectAux* aux = _ac->_aux.get();
while (aux) {
if (aux->_uriStr == requestUri) {
addons = aux->_addonElm;
break;
}
aux = aux->_next.get();
}
_currentUpload = nullptr;
for (AutoConnectElement& elm : addons) {
if (elm.typeOf() == AC_File) {
_currentUpload = reinterpret_cast<AutoConnectFile*>(&elm);
// Reset previous value
_currentUpload->value = String("");
_currentUpload->mimeType = String("");
_currentUpload->size = 0;
// Overwrite with current upload request
if (upload.name.equalsIgnoreCase(_currentUpload->name)) {
_currentUpload->value = upload.filename;
_currentUpload->mimeType = upload.type;
logContext = "accepted " + _currentUpload->value;
break;
}
}
}
AC_DBG_DUMB("%s, handler ", logContext.c_str());
// If the current upload request is AutoConnectFile without default
// AutoConnectUpload (i.e. the store attribute is AC_File_Ex),
// enable the user-owned upload handler activated by the onUpload.
_upload = nullptr;
if (_currentUpload)
if (_currentUpload->attach(_currentUpload->store)) {
_upload = std::bind(&AutoConnectUploadHandler::upload, _currentUpload->upload(), std::placeholders::_1, std::placeholders::_2);
AC_DBG_DUMB("attached(%d)\n", (int)_currentUpload->store);
}
if (!_upload) {
if (_uploadHandler) {
_upload = _uploadHandler;
AC_DBG_DUMB("enabled\n");
}
else
AC_DBG_DUMB("missing\n");
}
}
// Invokes upload handler
if (_upload) {
_upload(requestUri, upload);
if (_currentUpload)
_currentUpload->size = upload.totalSize;
// Upload ended, purge handler
if (upload.status == UPLOAD_FILE_END || upload.status == UPLOAD_FILE_ABORTED) {
if (_currentUpload)
_currentUpload->detach();
AC_DBG("%ld bytes uploaded\n", upload.totalSize);
}
}
}
/**
* Concatenates subsequent AutoConnectAux pages starting from oneself
* to the chain list.
@ -263,6 +342,23 @@ const String AutoConnectAux::_indicateUri(PageArgument& args) {
return lastUri;
}
/**
* Modifying the form of attribute depending on the type of `input` tag
* contained. If the custom web page contains `input type=file` then
* allows multipart as ENCTYPE attribute.
* @param args A reference of PageArgument but unused.
* @return HTML string that should be inserted.
*/
const String AutoConnectAux::_indicateEncType(PageArgument& args) {
AC_UNUSED(args);
String encType = String("");
for (AutoConnectElement& elm : _addonElm)
if (elm.typeOf() == AC_File) {
return String(F("enctype='multipart/form-data'"));
}
return AutoConnect::_emptyString;
}
/**
* Insert the token handler of PageBuilder. This handler inserts HTML
* elements generated by the whole AutoConnectElements to the auxiliary page.
@ -328,6 +424,7 @@ PageElement* AutoConnectAux::_setupPage(const String& uri) {
elm->addToken(String(FPSTR("MENU_AUX")), std::bind(&AutoConnect::_token_MENU_AUX, mother, std::placeholders::_1));
elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, mother, std::placeholders::_1));
elm->addToken(String(FPSTR("AUX_URI")), std::bind(&AutoConnectAux::_indicateUri, this, std::placeholders::_1));
elm->addToken(String(FPSTR("ENC_TYPE")), std::bind(&AutoConnectAux::_indicateEncType, this, std::placeholders::_1));
elm->addToken(String(FPSTR("AUX_ELEMENT")), std::bind(&AutoConnectAux::_insertElement, this, std::placeholders::_1));
}
}
@ -341,9 +438,17 @@ PageElement* AutoConnectAux::_setupPage(const String& uri) {
* @param webServer A pointer to the class object of WebServerClass
*/
void AutoConnectAux::_storeElements(WebServerClass* webServer) {
// Retrieve each element value, Overwrites the value of all cataloged
// AutoConnectElements with arguments inherited from last http request.
for (AutoConnectElement& elm : _addonElm) {
// Overwrite the value of all cataloged AutoConnectElements with
// arguments inherited from the last http request.
// The POST body does not contain the value of the AutoConnectFile,
// so it can not be obtained with the WebServerClass::arg function.
// The AutoConnectFile value will be restored from least recent
// upload request.
if (elm.typeOf() == AC_File)
continue;
// Relies on AutoConnectRadio, it restores to false at the being
// because the checkbox argument will not pass if it is not checked.
if (elm.typeOf() == AC_Checkbox)
@ -361,247 +466,7 @@ void AutoConnectAux::_storeElements(WebServerClass* webServer) {
}
}
#ifndef AUTOCONNECT_USE_JSON
/**
* 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 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 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
/**
* 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 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());
}
#ifdef AUTOCONNECT_USE_JSON
/**
* Load AutoConnectAux page from JSON description stored in the sketch.
@ -611,35 +476,29 @@ AutoConnectTextJson& AutoConnectAux::getElement(const String& name) {
* @return true Successfully loaded.
*/
bool AutoConnect::load(const String& aux) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
return _parseJson<const String&>(aux);
}
/**
* Load AutoConnectAux page from JSON description stored in PROGMEM.
* This function can load AutoConnectAux for multiple AUX pages written
* in JSON and is registered in AutoConnect.
* @param aux JSON description to be load.
* @return true Successfully loaded.
*/
* Load AutoConnectAux page from JSON description stored in PROGMEM.
* This function can load AutoConnectAux for multiple AUX pages written
* in JSON and is registered in AutoConnect.
* @param aux JSON description to be load.
* @return true Successfully loaded.
*/
bool AutoConnect::load(const __FlashStringHelper* aux) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
return _parseJson<const __FlashStringHelper*>(aux);
}
/**
* Load AutoConnectAux page from JSON description from the stream.
* This function can load AutoConnectAux for multiple AUX pages written
* in JSON and is registered in AutoConnect.
* @param aux Stream for read AutoConnectAux elements.
* @return true Successfully loaded.
*/
* Load AutoConnectAux page from JSON description from the stream.
* This function can load AutoConnectAux for multiple AUX pages written
* in JSON and is registered in AutoConnect.
* @param aux Stream for read AutoConnectAux elements.
* @return true Successfully loaded.
*/
bool AutoConnect::load(Stream& aux) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
return _parseJson<Stream&>(aux);
}
/**
@ -648,34 +507,29 @@ bool AutoConnect::load(Stream& aux) {
* @return true Successfully loaded.
*/
bool AutoConnect::_load(JsonVariant& auxJson) {
bool rc = auxJson.success();
if (rc) {
if (auxJson.is<JsonArray>()) {
JsonArray& jb = auxJson.as<JsonArray>();
for (JsonObject& auxJson : jb) {
AutoConnectAux* newAux = new AutoConnectAux;
if (newAux->_load(auxJson))
join(*newAux);
else {
delete newAux;
rc = false;
break;
}
}
}
else {
JsonObject& jb = auxJson.as<JsonObject>();
bool rc = true;
if (auxJson.is<JsonArray>()) {
ArduinoJsonArray jb = auxJson.as<JsonArray>();
for (ArduinoJsonObject auxJson : jb) {
AutoConnectAux* newAux = new AutoConnectAux;
if (newAux->_load(jb))
if (newAux->_load(auxJson))
join(*newAux);
else {
delete newAux;
rc = false;
break;
}
}
}
else {
AC_DBG("JSON parse error\n");
ArduinoJsonObject jb = auxJson.as<JsonObject>();
AutoConnectAux* newAux = new AutoConnectAux;
if (newAux->_load(jb))
join(*newAux);
else {
delete newAux;
rc = false;
}
}
return rc;
}
@ -687,7 +541,7 @@ bool AutoConnect::_load(JsonVariant& auxJson) {
*/
AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) {
AutoConnectElement* elm = nullptr;
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
switch (_asElementType(type)) {
case AC_Element:
@ -702,6 +556,10 @@ AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) {
AutoConnectCheckbox* cert_elm = new AutoConnectCheckbox;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
}
case AC_File: {
AutoConnectFile* cert_elm = new AutoConnectFile;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
}
case AC_Input: {
AutoConnectInput* cert_elm = new AutoConnectInput;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
@ -735,9 +593,7 @@ AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) {
* @return false Invalid JSON data occurred.
*/
bool AutoConnectAux::load(const String& in) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb);
return _parseJson<const String&>(in);
}
/**
@ -749,9 +605,7 @@ bool AutoConnectAux::load(const String& in) {
* @return false Invalid JSON data occurred.
*/
bool AutoConnectAux::load(const __FlashStringHelper* in) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb);
return _parseJson<const __FlashStringHelper*>(in);
}
/**
@ -763,9 +617,7 @@ bool AutoConnectAux::load(const __FlashStringHelper* in) {
* @return false Invalid JSON data occurred.
*/
bool AutoConnectAux::load(Stream& in) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb);
return _parseJson<Stream&>(in);
}
/**
@ -775,15 +627,10 @@ bool AutoConnectAux::load(Stream& in) {
* @return false loading unsuccessful, JSON parsing error occurred.
*/
bool AutoConnectAux::_load(JsonObject& jb) {
if (!jb.success()) {
AC_DBG("json parse error\n");
return false;
}
_title = jb.get<String>(F(AUTOCONNECT_JSON_KEY_TITLE));
_uriStr = jb.get<String>(F(AUTOCONNECT_JSON_KEY_URI));
_title = jb[F(AUTOCONNECT_JSON_KEY_TITLE)].as<String>();
_uriStr = jb[F(AUTOCONNECT_JSON_KEY_URI)].as<String>();
_uri = _uriStr.c_str();
_menu = jb.get<bool>(F(AUTOCONNECT_JSON_KEY_MENU));
_menu = jb[F(AUTOCONNECT_JSON_KEY_MENU)].as<bool>();
JsonVariant elements = jb[F(AUTOCONNECT_JSON_KEY_ELEMENT)];
(void)_loadElement(elements, "");
return true;
@ -800,49 +647,41 @@ bool AutoConnectAux::_load(JsonObject& jb) {
* @return A reference of loaded AutoConnectElement instance.
*/
bool AutoConnectAux::loadElement(const String& in, const String& name) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name);
return _parseElement<const String&>(in, name);
}
bool AutoConnectAux::loadElement(const __FlashStringHelper* in, const String& name) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name);
return _parseElement<const __FlashStringHelper*>(in, name);
}
bool AutoConnectAux::loadElement(Stream& in, const String& name) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name);
return _parseElement<Stream&>(in, name);
}
bool AutoConnectAux::_loadElement(JsonVariant& jb, const String& name) {
bool rc = jb.success();
if (rc) {
if (jb.is<JsonArray>()) {
JsonArray& elements = jb.as<JsonArray>();
for (JsonObject& element : elements) {
AutoConnectElement& elm = _loadElement(element, name);
if (!elm.name.length()) {
rc = false;
break;
}
}
}
else {
JsonObject& element = jb.as<JsonObject>();
bool rc = true;
if (jb.is<JsonArray>()) {
ArduinoJsonArray elements = jb.as<JsonArray>();
for (ArduinoJsonObject element : elements) {
AutoConnectElement& elm = _loadElement(element, name);
if (!elm.name.length())
if (!elm.name.length()) {
rc = false;
break;
}
}
}
else {
ArduinoJsonObject element = jb.as<JsonObject>();
AutoConnectElement& elm = _loadElement(element, name);
if (!elm.name.length())
rc = false;
}
return rc;
}
AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& element, const String& name) {
AutoConnectElement* auxElm = nullptr;
String elmName = element.get<String>(F(AUTOCONNECT_JSON_KEY_NAME));
String elmName = element[F(AUTOCONNECT_JSON_KEY_NAME)].as<String>();
if (!name.length() || name.equalsIgnoreCase(elmName)) {
// The specified element is defined in the JSON stream.
// Loads from JSON object.
@ -896,40 +735,43 @@ size_t AutoConnectAux::saveElement(Stream& out, std::vector<String> const& names
bufferSize += elm.getObjectSize();
break;
}
// Round up to 16 boundary
bufferSize = bufferSize > 0 ? ((bufferSize + 16) & (~0xf)) : bufferSize;
// Serialization
if (bufferSize > 0) {
DynamicJsonBuffer jb(bufferSize);
ArduinoJsonBuffer jb(bufferSize);
if (amount == 1) {
JsonObject& element = jb.createObject();
ArduinoJsonObject element = ARDUINOJSON_CREATEOBJECT(jb);
for (AutoConnectElement& elm : _addonElm)
if (elm.name.equalsIgnoreCase(names[0])) {
elm.serialize(element);
break;
}
size_n = element.printTo(out);
size_n = ARDUINOJSON_PRINT(element, out);
}
else if (amount == 0) {
JsonObject& json = jb.createObject();
ArduinoJsonObject json = ARDUINOJSON_CREATEOBJECT(jb);
json[F(AUTOCONNECT_JSON_KEY_TITLE)] = _title;
json[F(AUTOCONNECT_JSON_KEY_URI)] = _uriStr;
json[F(AUTOCONNECT_JSON_KEY_MENU)] = _menu;
JsonArray& elements = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_ELEMENT));
ArduinoJsonArray elements = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_ELEMENT));
for (AutoConnectElement& elm : _addonElm) {
JsonObject& element = elements.createNestedObject();
ArduinoJsonObject element = elements.createNestedObject();
elm.serialize(element);
}
size_n = json.prettyPrintTo(out);
size_n = ARDUINOJSON_PRETTYPRINT(json, out);
}
else if (amount >= 2) {
JsonArray& elements = jb.createArray();
ArduinoJsonArray elements = ARDUINOJSON_CREATEARRAY(jb);
for (String name : names)
for (AutoConnectElement& elm : _addonElm)
if (elm.name.equalsIgnoreCase(name)) {
JsonObject& element = elements.createNestedObject();
ArduinoJsonObject element = elements.createNestedObject();
elm.serialize(element);
break;
}
size_n = elements.prettyPrintTo(out);
size_n = ARDUINOJSON_PRETTYPRINT(elements, out);
}
}
return size_n;
@ -949,6 +791,7 @@ ACElement_t AutoConnectAux::_asElementType(const String& type) {
{ AUTOCONNECT_JSON_TYPE_ACBUTTON, AC_Button },
{ AUTOCONNECT_JSON_TYPE_ACCHECKBOX, AC_Checkbox },
{ AUTOCONNECT_JSON_TYPE_ACELEMENT, AC_Element },
{ AUTOCONNECT_JSON_TYPE_ACFILE, AC_File },
{ AUTOCONNECT_JSON_TYPE_ACINPUT, AC_Input },
{ AUTOCONNECT_JSON_TYPE_ACRADIO, AC_Radio },
{ AUTOCONNECT_JSON_TYPE_ACSELECT, AC_Select },
@ -964,4 +807,4 @@ ACElement_t AutoConnectAux::_asElementType(const String& type) {
return t;
}
#endif // AUTOCONNECT_USE_JSON
#endif // !AUTOCONNECT_USE_JSON

@ -14,6 +14,7 @@
#include <vector>
#include <memory>
#include <functional>
#include <type_traits>
#ifdef AUTOCONNECT_USE_JSON
#include <Stream.h>
#endif // !AUTOCONNECT_USE_JSON
@ -47,8 +48,9 @@ typedef enum {
class AutoConnectAux : public PageBuilder {
public:
explicit AutoConnectAux(const String& uri = String(""), const String& title = String(""), const bool menu = true, const AutoConnectElementVT addons = AutoConnectElementVT()) :
_title(title), _menu(menu), _uriStr(String(uri)), _addonElm(addons) { _uri = _uriStr.c_str(); _next.release(); _ac.release(); }
_title(title), _menu(menu), _uriStr(String(uri)), _addonElm(addons), _handler(nullptr), _order(AC_EXIT_AHEAD), _uploadHandler(nullptr) { _uri = _uriStr.c_str(); _next.release(); _ac.release(); }
~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 */
template<typename T>
@ -59,20 +61,27 @@ class AutoConnectAux : public PageBuilder {
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 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(const String& in); /**< Load whole elements to AutoConnectAux Page */
bool load(const __FlashStringHelper* in); /**< Load whole elements to AutoConnectAux Page */
bool load(Stream& in); /**< Load whole elements to AutoConnectAux Page */
bool loadElement(const String& in, const String& name = String("")); /**< Load specified element */
bool loadElement(const __FlashStringHelper* in, const String& name = String("")); /**< Load specified element */
bool loadElement(Stream& in, const String& name = String("")); /**< Load specified element */
bool load(const String& in); /**< Load whole elements to AutoConnectAux Page */
bool load(const __FlashStringHelper* in); /**< Load whole elements to AutoConnectAux Page */
bool load(Stream& in); /**< Load whole elements to AutoConnectAux Page */
bool loadElement(const String& in, const String& name = String("")); /**< Load specified element */
bool loadElement(const __FlashStringHelper* in, const String& name = String("")); /**< Load specified element */
bool loadElement(Stream& in, const String& name = String("")); /**< Load specified element */
size_t saveElement(Stream& out, std::vector<String> const& names = {}); /**< Write elements of AutoConnectAux to the stream */
#endif // !AUTOCONNECT_USE_JSON
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 */
@ -80,15 +89,20 @@ class AutoConnectAux : public PageBuilder {
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 */
template<typename T>
bool _parseElement(T in, const String& name);
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 */
static ACElement_t _asElementType(const String& type); /**< Convert a string of element type to the enumeration value */
#endif // !AUTOCONNECT_USE_JSON
String _title; /**< A title of the page */
@ -99,7 +113,8 @@ class AutoConnectAux : public PageBuilder {
std::unique_ptr<AutoConnect> _ac; /**< 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.

@ -0,0 +1,416 @@
/**
* 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 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);
}
/**
* 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 in An instance of a source JSON document to load.
*/
template<typename T>
bool AutoConnectAux::_parseElement(T in, const String& 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);
}
/**
* 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_

@ -124,10 +124,44 @@
// Reserved buffer size to build content
#ifndef AUTOCONNECT_CONTENTBUFFER_SIZE
#define AUTOCONNECT_CONTENTBUFFER_SIZE 0
#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
// SD pin assignment for AutoConnectFile
#ifndef AUTOCONNECT_SD_CS
#if defined(ARDUINO_ARCH_ESP8266)
#define AUTOCONNECT_SD_CS SD_CHIP_SELECT_PIN
#elif defined(ARDUINO_ARCH_ESP32)
#define AUTOCONNECT_SD_CS SS
#endif
#endif // !AUTOCONNECT_SD_CS
// SPI transfer speed for SD
#ifndef AUTOCONNECT_SD_SPEED
#if defined(ARDUINO_ARCH_ESP8266)
#define AUTOCONNECT_SD_SPEED SPI_HALF_SPEED
#elif defined(ARDUINO_ARCH_ESP32)
#define AUTOCONNECT_SD_SPEED 4000000
#endif
#endif // !AUTOCONNECT_SD_SPEED
// 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
// Explicitly avoiding unused warning with token handler of PageBuilder
#define AC_UNUSED(expr) do { (void)(expr); } while (0)
#endif // _AUTOCONNECTDEFS_H_
#endif // _AUTOCONNECTDEFS_H_

@ -2,8 +2,8 @@
* Alias declarations for an accessible the AutoConnectElement class.
* @file AutoConnectAux.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @version 0.9.8
* @date 2018-03-11
* @copyright MIT license.
*/
@ -17,6 +17,7 @@
using AutoConnectElement = AutoConnectElementJson;
using AutoConnectButton = AutoConnectButtonJson;
using AutoConnectCheckbox = AutoConnectCheckboxJson;
using AutoConnectFile = AutoConnectFileJson;
using AutoConnectInput = AutoConnectInputJson;
using AutoConnectRadio = AutoConnectRadioJson;
using AutoConnectSelect = AutoConnectSelectJson;
@ -27,6 +28,7 @@ using AutoConnectText = AutoConnectTextJson;
using AutoConnectElement = AutoConnectElementBasis;
using AutoConnectButton = AutoConnectButtonBasis;
using AutoConnectCheckbox = AutoConnectCheckboxBasis;
using AutoConnectFile = AutoConnectFileBasis;
using AutoConnectInput = AutoConnectInputBasis;
using AutoConnectRadio = AutoConnectRadioBasis;
using AutoConnectSelect = AutoConnectSelectBasis;
@ -42,6 +44,7 @@ using AutoConnectText = AutoConnectTextBasis;
#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__)

@ -2,8 +2,8 @@
* Declaration of AutoConnectElement basic class.
* @file AutoConnectElementBasis.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-12-29
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
@ -12,17 +12,19 @@
#include <vector>
#include <memory>
#include "AutoConnectUpload.h"
typedef enum {
AC_Button,
AC_Checkbox,
AC_Element,
AC_File,
AC_Input,
AC_Radio,
AC_Select,
AC_Submit,
AC_Text,
AC_Unknown
AC_Unknown = -1
} ACElement_t; /**< AutoConnectElement class type */
typedef enum {
@ -30,6 +32,12 @@ typedef enum {
AC_Vertical
} ACArrange_t; /**< The element arrange order */
typedef enum {
AC_File_FS = 0,
AC_File_SD,
AC_File_Extern
} ACFile_t; /**< AutoConnectFile media type */
/**
* AutoConnectAux element base.
* Placed a raw text that can be added by user sketch.
@ -44,6 +52,10 @@ class AutoConnectElementBasis {
virtual ~AutoConnectElementBasis() {}
virtual const String toHTML(void) const { return value; }
ACElement_t typeOf(void) const { return _type; }
#ifndef AUTOCONNECT_USE_JSON
template<typename T>
T& as(void);
#endif
String name; /**< Element name */
String value; /**< Element value */
@ -90,6 +102,35 @@ class AutoConnectCheckboxBasis : virtual public AutoConnectElementBasis {
bool checked; /**< The element should be pre-selected */
};
/**
* File-select input arrangement class, a part of AutoConnectAux element.
* Place a optionally labeled file-select input box that can be added by user sketch.
* @param name File-select input box name string.
* @param value A string value entered by the selected file name.
* @param label A label string that follows file-select box, optionally.
* The label is placed in front of file-select box.
*/
class AutoConnectFileBasis : virtual public AutoConnectElementBasis {
public:
explicit AutoConnectFileBasis(const char* name = "", const char* value = "", const char* label = "", const ACFile_t store = AC_File_FS) : AutoConnectElementBasis(name, value), label(String(label)), store(store) {
_type = AC_File;
_upload.reset();
}
virtual ~AutoConnectFileBasis() {}
const String toHTML(void) const override;
bool attach(const ACFile_t store);
void detach(void) { _upload.reset(); }
AutoConnectUploadHandler* upload(void) const { return _upload.get(); }
String label; /**< A label for a subsequent input box */
ACFile_t store; /**< Type of file store */
String mimeType; /**< Uploading file mime type string */
size_t size; /**< Total uploaded bytes */
protected:
std::unique_ptr<AutoConnectUploadHandler> _upload;
};
/**
* Input-box arrangement class, a part of AutoConnectAux element.
* Place a optionally labeled input-box that can be added by user sketch.
@ -196,18 +237,82 @@ class AutoConnectSubmitBasis : virtual public AutoConnectElementBasis {
* @param name Text name string.
* @param value Text value string.
* @param style A string of style-code for decoration, optionally.
* @param format C string that contains the value to be formatted.
* An arrangement text would be placed with <div> contains. A string
* of style-codes are given for '<div style=>'.
*/
class AutoConnectTextBasis : virtual public AutoConnectElementBasis {
public:
explicit AutoConnectTextBasis(const char* name = "", const char* value = "", const char* style = "") : AutoConnectElementBasis(name, value), style(String(style)) {
explicit AutoConnectTextBasis(const char* name = "", const char* value = "", const char* style = "", const char* format = "") : AutoConnectElementBasis(name, value), style(String(style)), format(String(format)) {
_type = AC_Text;
}
virtual ~AutoConnectTextBasis() {}
const String toHTML(void) const override;
String style; /**< CSS style modifier native code */
String format; /**< C string that contains the text to be written */
};
#ifndef AUTOCONNECT_USE_JSON
/**
* Casts only a class derived from the AutoConnectElement class to the
* actual element class.
*/
template<>
inline AutoConnectButtonBasis& AutoConnectElementBasis::as<AutoConnectButtonBasis>(void) {
if (typeOf() != AC_Button)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectButtonBasis*>(this));
}
template<>
inline AutoConnectCheckboxBasis& AutoConnectElementBasis::as<AutoConnectCheckboxBasis>(void) {
if (typeOf() != AC_Checkbox)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectCheckboxBasis*>(this));
}
template<>
inline AutoConnectFileBasis& AutoConnectElementBasis::as<AutoConnectFileBasis>(void) {
if (typeOf() != AC_File)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectFileBasis*>(this));
}
template<>
inline AutoConnectInputBasis& AutoConnectElementBasis::as<AutoConnectInputBasis>(void) {
if (typeOf() != AC_Input)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectInputBasis*>(this));
}
template<>
inline AutoConnectRadioBasis& AutoConnectElementBasis::as<AutoConnectRadioBasis>(void) {
if (typeOf() != AC_Radio)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectRadioBasis*>(this));
}
template<>
inline AutoConnectSelectBasis& AutoConnectElementBasis::as<AutoConnectSelectBasis>(void) {
if (typeOf() != AC_Select)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectSelectBasis*>(this));
}
template<>
inline AutoConnectSubmitBasis& AutoConnectElementBasis::as<AutoConnectSubmitBasis>(void) {
if (typeOf() != AC_Submit)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectSubmitBasis*>(this));
}
template<>
inline AutoConnectTextBasis& AutoConnectElementBasis::as<AutoConnectTextBasis>(void) {
if (typeOf() != AC_Text)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectTextBasis*>(this));
}
#endif
#endif // _AUTOCONNECTELEMENTBASIS_H_

@ -2,20 +2,22 @@
* Implementation of AutoConnectElementBasis classes.
* @file AutoConnectElementImpl.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-12-29
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTELEMENTBASISIMPL_H_
#define _AUTOCONNECTELEMENTBASISIMPL_H_
#include "AutoConnectElementBasis.h"
#include <stdlib.h>
#include <stdio.h>
#if defined(ARDUINO_ARCH_ESP8266)
#include <regex.h>
#elif defined(ARDUINO_ARCH_ESP32)
#include <regex>
#endif
#include "AutoConnectElementBasis.h"
/**
* Generate an HTML <button> element. The onclick behavior depends on
@ -46,6 +48,48 @@ const String AutoConnectCheckboxBasis::toHTML(void) const {
return html;
}
/**
* Generate an HTML <input type=file> element.
* The entered value can be obtained using the user callback function
* registered by AutoConnectAux::on after the form is sent in
* combination with AutoConnectSubmit.
* @return String an HTML string.
*/
const String AutoConnectFileBasis::toHTML(void) const {
String html = String("");
if (label.length())
html = String(F("<label for=\"")) + name + String(F("\">")) + label + String(F("</label>"));
html += String(F("<input type=\"file\" id=\"")) + name + String(F("\" name=\"")) + name + String(F("\"><br>"));
return html;
}
/**
* Instantiate the upload handler with the specified store type.
* @param store An enumuration value of ACFile_t
*/
bool AutoConnectFileBasis::attach(const ACFile_t store) {
AutoConnectUploadFS* handlerFS;
AutoConnectUploadSD* handlerSD;
// Release previous handler
detach();
// Classify a handler type and create the corresponding handler
switch (store) {
case AC_File_FS:
handlerFS = new AutoConnectUploadFS(SPIFFS);
_upload.reset(reinterpret_cast<AutoConnectUploadHandler*>(handlerFS));
break;
case AC_File_SD:
handlerSD = new AutoConnectUploadSD(SD);
_upload.reset(reinterpret_cast<AutoConnectUploadHandler*>(handlerSD));
break;
case AC_File_Extern:
break;
}
return _upload != false;
}
/**
* Generate an HTML <input type=text> element.
* If the value member is contained, it is reflected in the placeholder
@ -208,7 +252,23 @@ const String AutoConnectSubmitBasis::toHTML(void) const {
* @return String an HTML string.
*/
const String AutoConnectTextBasis::toHTML(void) const {
return String(F("<div style=\"")) + style + String("\">") + value + String(F("</div>"));
String html = String("<div");
String value_f = value;
if (style.length())
html += String(F(" style=\"")) + style + String("\"");
html += String(">");
if (format.length()) {
int buflen = (value.length() + format.length() + 16 + 1) & (~0xf);
char* buffer;
if ((buffer = (char*)malloc(buflen))) {
snprintf(buffer, buflen, format.c_str(), value.c_str());
value_f = String(buffer);
free(buffer);
}
}
html += value_f + String(F("</div>"));
return html;
}
#endif // _AUTOCONNECTELEMENTBASISIMPL_H_

@ -2,8 +2,8 @@
* Declaration of AutoConnectElement extended classes using JSON.
* @file AutoConnectElementJson.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
@ -13,31 +13,81 @@
#include "AutoConnectElementBasis.h"
#include <ArduinoJson.h>
#define AUTOCONNECT_JSON_KEY_ACTION "action"
#define AUTOCONNECT_JSON_KEY_ARRANGE "arrange"
#define AUTOCONNECT_JSON_KEY_CHECKED "checked"
#define AUTOCONNECT_JSON_KEY_ELEMENT "element"
#define AUTOCONNECT_JSON_KEY_HORIZONTAL "horizontal"
#define AUTOCONNECT_JSON_KEY_LABEL "label"
#define AUTOCONNECT_JSON_KEY_MENU "menu"
#define AUTOCONNECT_JSON_KEY_NAME "name"
#define AUTOCONNECT_JSON_KEY_OPTION "option"
#define AUTOCONNECT_JSON_KEY_PATTERN "pattern"
#define AUTOCONNECT_JSON_KEY_PLACEHOLDER "placeholder"
#define AUTOCONNECT_JSON_KEY_STYLE "style"
#define AUTOCONNECT_JSON_KEY_TITLE "title"
#define AUTOCONNECT_JSON_KEY_TYPE "type"
#define AUTOCONNECT_JSON_KEY_URI "uri"
#define AUTOCONNECT_JSON_KEY_VALUE "value"
#define AUTOCONNECT_JSON_KEY_VERTICAL "vertical"
#define AUTOCONNECT_JSON_TYPE_ACBUTTON "ACButton"
#define AUTOCONNECT_JSON_TYPE_ACCHECKBOX "ACCheckBox"
#define AUTOCONNECT_JSON_TYPE_ACELEMENT "ACElement"
#define AUTOCONNECT_JSON_TYPE_ACINPUT "ACInput"
#define AUTOCONNECT_JSON_TYPE_ACRADIO "ACRadio"
#define AUTOCONNECT_JSON_TYPE_ACSELECT "ACSelect"
#define AUTOCONNECT_JSON_TYPE_ACSUBMIT "ACSubmit"
#define AUTOCONNECT_JSON_TYPE_ACTEXT "ACText"
#define AUTOCONNECT_JSON_KEY_ACTION "action"
#define AUTOCONNECT_JSON_KEY_ARRANGE "arrange"
#define AUTOCONNECT_JSON_KEY_CHECKED "checked"
#define AUTOCONNECT_JSON_KEY_ELEMENT "element"
#define AUTOCONNECT_JSON_KEY_FORMAT "format"
#define AUTOCONNECT_JSON_KEY_LABEL "label"
#define AUTOCONNECT_JSON_KEY_MENU "menu"
#define AUTOCONNECT_JSON_KEY_NAME "name"
#define AUTOCONNECT_JSON_KEY_OPTION "option"
#define AUTOCONNECT_JSON_KEY_PATTERN "pattern"
#define AUTOCONNECT_JSON_KEY_PLACEHOLDER "placeholder"
#define AUTOCONNECT_JSON_KEY_STORE "store"
#define AUTOCONNECT_JSON_KEY_STYLE "style"
#define AUTOCONNECT_JSON_KEY_TITLE "title"
#define AUTOCONNECT_JSON_KEY_TYPE "type"
#define AUTOCONNECT_JSON_KEY_URI "uri"
#define AUTOCONNECT_JSON_KEY_VALUE "value"
#define AUTOCONNECT_JSON_TYPE_ACBUTTON "ACButton"
#define AUTOCONNECT_JSON_TYPE_ACCHECKBOX "ACCheckBox"
#define AUTOCONNECT_JSON_TYPE_ACELEMENT "ACElement"
#define AUTOCONNECT_JSON_TYPE_ACFILE "ACFile"
#define AUTOCONNECT_JSON_TYPE_ACINPUT "ACInput"
#define AUTOCONNECT_JSON_TYPE_ACRADIO "ACRadio"
#define AUTOCONNECT_JSON_TYPE_ACSELECT "ACSelect"
#define AUTOCONNECT_JSON_TYPE_ACSUBMIT "ACSubmit"
#define AUTOCONNECT_JSON_TYPE_ACTEXT "ACText"
#define AUTOCONNECT_JSON_VALUE_EXTERNAL "extern"
#define AUTOCONNECT_JSON_VALUE_FS "fs"
#define AUTOCONNECT_JSON_VALUE_HORIZONTAL "horizontal"
#define AUTOCONNECT_JSON_VALUE_SD "sd"
#define AUTOCONNECT_JSON_VALUE_VERTICAL "vertical"
/**
* 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 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 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) {
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
}
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
/**
* AutoConnectAux element base with handling with JSON object.
@ -55,6 +105,8 @@ class AutoConnectElementJson : virtual public AutoConnectElementBasis {
virtual size_t getObjectSize(void) const;
virtual bool loadMember(const JsonObject& json);
virtual void serialize(JsonObject& json);
template<typename T>
T& as(void);
protected:
void _setMember(const JsonObject& json);
@ -105,6 +157,29 @@ class AutoConnectCheckboxJson : public AutoConnectElementJson, public AutoConnec
void serialize(JsonObject& json) override;
};
/**
* File-select input arrangement class, a part of AutoConnectAux element.
* Place a optionally labeled file-select input box that can be added by user sketch.
* @param name File-select input box name string.
* @param value A string value entered by the selected file name.
* @param label A label string that follows file-select box, optionally.
* The label is placed in front of file-select box.
* @param store An enumuration value of store type.
*/
class AutoConnectFileJson : public AutoConnectElementJson, public AutoConnectFileBasis {
public:
explicit AutoConnectFileJson(const char* name = "", const char* value= "", const char* label = "", const ACFile_t store = AC_File_FS) {
AutoConnectFileBasis::name = String(name);
AutoConnectFileBasis::value = String(value);
AutoConnectFileBasis::label = String(label);
AutoConnectFileBasis::store = store;
}
~AutoConnectFileJson() {}
size_t getObjectSize(void) const override;
bool loadMember(const JsonObject& json) override;
void serialize(JsonObject& json) override;
};
/**
* Input-box arrangement class, a part of AutoConnectAux element with
* handling JSON object.
@ -206,10 +281,11 @@ class AutoConnectSubmitJson : public AutoConnectElementJson, public AutoConnectS
*/
class AutoConnectTextJson : public AutoConnectElementJson, public AutoConnectTextBasis {
public:
explicit AutoConnectTextJson(const char* name = "", const char* value = "", const char* style = "") {
explicit AutoConnectTextJson(const char* name = "", const char* value = "", const char* style = "", const char* format = "") {
AutoConnectTextBasis::name = String(name);
AutoConnectTextBasis::value = String(value);
AutoConnectTextBasis::style = String(style);
AutoConnectTextBasis::format = String(format);
}
~AutoConnectTextJson() {}
size_t getObjectSize(void) const override;
@ -217,4 +293,64 @@ class AutoConnectTextJson : public AutoConnectElementJson, public AutoConnectTex
void serialize(JsonObject& json) override;
};
/**
* Casts only a class derived from the AutoConnectElement class to the
* actual element class.
*/
template<>
inline AutoConnectButtonJson& AutoConnectElementJson::as<AutoConnectButtonJson>(void) {
if (typeOf() != AC_Button)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectButtonJson*>(this));
}
template<>
inline AutoConnectCheckboxJson& AutoConnectElementJson::as<AutoConnectCheckboxJson>(void) {
if (typeOf() != AC_Checkbox)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectCheckboxJson*>(this));
}
template<>
inline AutoConnectFileJson& AutoConnectElementJson::as<AutoConnectFileJson>(void) {
if (typeOf() != AC_File)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectFileJson*>(this));
}
template<>
inline AutoConnectInputJson& AutoConnectElementJson::as<AutoConnectInputJson>(void) {
if (typeOf() != AC_Input)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectInputJson*>(this));
}
template<>
inline AutoConnectRadioJson& AutoConnectElementJson::as<AutoConnectRadioJson>(void) {
if (typeOf() != AC_Radio)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectRadioJson*>(this));
}
template<>
inline AutoConnectSelectJson& AutoConnectElementJson::as<AutoConnectSelectJson>(void) {
if (typeOf() != AC_Select)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectSelectJson*>(this));
}
template<>
inline AutoConnectSubmitJson& AutoConnectElementJson::as<AutoConnectSubmitJson>(void) {
if (typeOf() != AC_Submit)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectSubmitJson*>(this));
}
template<>
inline AutoConnectTextJson& AutoConnectElementJson::as<AutoConnectTextJson>(void) {
if (typeOf() != AC_Text)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectTextJson*>(this));
}
#endif // _AUTOCONNECTELEMENTJSON_H_

@ -2,8 +2,8 @@
* Implementation of AutoConnectElementJson classes.
* @file AutoConnectElementImpl.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
@ -17,7 +17,9 @@
* @return An object size for JsonBuffer.
*/
size_t AutoConnectElementJson::getObjectSize() const {
return JSON_OBJECT_SIZE(3);
size_t size = JSON_OBJECT_SIZE(3) + sizeof(AUTOCONNECT_JSON_KEY_TYPE) + sizeof(AUTOCONNECT_JSON_KEY_NAME) + sizeof(AUTOCONNECT_JSON_KEY_VALUE) + 10;
size += name.length() + value.length();
return size;
}
/**
@ -27,7 +29,7 @@ size_t AutoConnectElementJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectElementJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACELEMENT))) {
_setMember(json);
return true;
@ -41,8 +43,8 @@ bool AutoConnectElementJson::loadMember(const JsonObject& json) {
*/
void AutoConnectElementJson::serialize(JsonObject& json) {
_serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACELEMENT));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value);
json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACELEMENT));
json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
}
/**
@ -51,7 +53,7 @@ void AutoConnectElementJson::serialize(JsonObject& json) {
* @param json JSON object to be serialized.
*/
void AutoConnectElementJson::_serialize(JsonObject& json) {
json.set(F(AUTOCONNECT_JSON_KEY_NAME), name);
json[F(AUTOCONNECT_JSON_KEY_NAME)] = name;
}
/**
@ -59,9 +61,9 @@ void AutoConnectElementJson::_serialize(JsonObject& json) {
* @param json JSON object with the definition of AutoConnectElement.
*/
void AutoConnectElementJson::_setMember(const JsonObject& json) {
name = json.get<String>(F(AUTOCONNECT_JSON_KEY_NAME));
name = json[F(AUTOCONNECT_JSON_KEY_NAME)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_VALUE)))
value = json.get<String>(F(AUTOCONNECT_JSON_KEY_VALUE));
value = json[F(AUTOCONNECT_JSON_KEY_VALUE)].as<String>();
}
/**
@ -69,7 +71,9 @@ void AutoConnectElementJson::_setMember(const JsonObject& json) {
* @return An object size for JsonBuffer.
*/
size_t AutoConnectButtonJson::getObjectSize() const {
return AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(1);
size_t size = AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(1);
size += sizeof(AUTOCONNECT_JSON_KEY_ACTION) + action.length();
return size;
}
/**
@ -79,11 +83,11 @@ size_t AutoConnectButtonJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectButtonJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACBUTTON))) {
_setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_ACTION)))
action = json.get<String>(F(AUTOCONNECT_JSON_KEY_ACTION));
action = json[F(AUTOCONNECT_JSON_KEY_ACTION)].as<String>();
return true;
}
return false;
@ -95,9 +99,9 @@ bool AutoConnectButtonJson::loadMember(const JsonObject& json) {
*/
void AutoConnectButtonJson::serialize(JsonObject& json) {
_serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACBUTTON));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value);
json.set(F(AUTOCONNECT_JSON_KEY_ACTION), action);
json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACBUTTON));
json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json[F(AUTOCONNECT_JSON_KEY_ACTION)] = action;
}
/**
@ -105,7 +109,9 @@ void AutoConnectButtonJson::serialize(JsonObject& json) {
* @return An object size for JsonBuffer.
*/
size_t AutoConnectCheckboxJson::getObjectSize() const {
return AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(2);
size_t size = AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(2);
size += sizeof(AUTOCONNECT_JSON_KEY_LABEL) + label.length() + sizeof(AUTOCONNECT_JSON_KEY_CHECKED);
return size;
}
/**
@ -115,13 +121,13 @@ size_t AutoConnectCheckboxJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectCheckboxJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACCHECKBOX))) {
_setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL)))
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL));
label = json[F(AUTOCONNECT_JSON_KEY_LABEL)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_CHECKED)))
checked = json.get<bool>(F(AUTOCONNECT_JSON_KEY_CHECKED));
checked = json[F(AUTOCONNECT_JSON_KEY_CHECKED)].as<bool>();
return true;
}
return false;
@ -133,11 +139,73 @@ bool AutoConnectCheckboxJson::loadMember(const JsonObject& json) {
*/
void AutoConnectCheckboxJson::serialize(JsonObject& json) {
_serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACCHECKBOX));
json.set(F(AUTOCONNECT_JSON_KEY_NAME), name);
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value);
json.set(F(AUTOCONNECT_JSON_KEY_LABEL), label);
json.set(F(AUTOCONNECT_JSON_KEY_CHECKED), checked);
json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACCHECKBOX));
json[F(AUTOCONNECT_JSON_KEY_NAME)] = name;
json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json[F(AUTOCONNECT_JSON_KEY_LABEL)] = label;
json[F(AUTOCONNECT_JSON_KEY_CHECKED)] = checked;
}
/**
* Returns JSON object size.
* @return An object size for JsonBuffer.
*/
size_t AutoConnectFileJson::getObjectSize() const {
size_t size = AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(2);
size += sizeof(AUTOCONNECT_JSON_KEY_LABEL) + label.length() + sizeof(AUTOCONNECT_JSON_KEY_STORE) + sizeof(AUTOCONNECT_JSON_VALUE_FS);
return size;
}
/**
* Load a file-select element attribute member from the JSON object.
* @param json JSON object with the definition of AutoConnectElement.
* @return true AutoConnectElement loaded
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectFileJson::loadMember(const JsonObject& json) {
String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACFILE))) {
_setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL)))
label = json[F(AUTOCONNECT_JSON_KEY_LABEL)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_STORE))) {
String media = json[F(AUTOCONNECT_JSON_KEY_STORE)].as<String>();
if (media.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_FS)))
store = AC_File_FS;
else if (media.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_SD)))
store = AC_File_SD;
else if (media.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_EXTERNAL)))
store = AC_File_Extern;
else {
AC_DBG("Failed to load %s element, unknown %s\n", name.c_str(), media.c_str());
return false;
}
}
return true;
}
return false;
}
/**
* Serialize AutoConnectFile to JSON.
* @param json JSON object to be serialized.
*/
void AutoConnectFileJson::serialize(JsonObject& json) {
_serialize(json);
json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACFILE));
json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json[F(AUTOCONNECT_JSON_KEY_LABEL)] = label;
switch (store) {
case AC_File_FS:
json[F(AUTOCONNECT_JSON_KEY_STORE)] = AUTOCONNECT_JSON_VALUE_FS;
break;
case AC_File_SD:
json[F(AUTOCONNECT_JSON_KEY_STORE)] = AUTOCONNECT_JSON_VALUE_SD;
break;
case AC_File_Extern:
json[F(AUTOCONNECT_JSON_KEY_STORE)] = AUTOCONNECT_JSON_VALUE_EXTERNAL;
break;
}
}
/**
@ -145,7 +213,9 @@ void AutoConnectCheckboxJson::serialize(JsonObject& json) {
* @return An object size for JsonBuffer.
*/
size_t AutoConnectInputJson::getObjectSize() const {
return AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(3);
size_t size = AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(3);
size += sizeof(AUTOCONNECT_JSON_KEY_LABEL) + label.length() + sizeof(AUTOCONNECT_JSON_KEY_PATTERN) + pattern.length() + sizeof(AUTOCONNECT_JSON_KEY_PLACEHOLDER) + placeholder.length();
return size;
}
/**
@ -155,15 +225,15 @@ size_t AutoConnectInputJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectInputJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACINPUT))) {
_setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL)))
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL));
label = json[F(AUTOCONNECT_JSON_KEY_LABEL)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_PATTERN)))
pattern = json.get<String>(F(AUTOCONNECT_JSON_KEY_PATTERN));
pattern = json[F(AUTOCONNECT_JSON_KEY_PATTERN)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_PLACEHOLDER)))
placeholder = json.get<String>(F(AUTOCONNECT_JSON_KEY_PLACEHOLDER));
placeholder = json[F(AUTOCONNECT_JSON_KEY_PLACEHOLDER)].as<String>();
return true;
}
return false;
@ -175,11 +245,11 @@ bool AutoConnectInputJson::loadMember(const JsonObject& json) {
*/
void AutoConnectInputJson::serialize(JsonObject& json) {
_serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACINPUT));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value);
json.set(F(AUTOCONNECT_JSON_KEY_LABEL), label);
json.set(F(AUTOCONNECT_JSON_KEY_PATTERN), pattern);
json.set(F(AUTOCONNECT_JSON_KEY_PLACEHOLDER), placeholder);
json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACINPUT));
json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json[F(AUTOCONNECT_JSON_KEY_LABEL)] = label;
json[F(AUTOCONNECT_JSON_KEY_PATTERN)] = pattern;
json[F(AUTOCONNECT_JSON_KEY_PLACEHOLDER)] = placeholder;
}
/**
@ -187,7 +257,11 @@ void AutoConnectInputJson::serialize(JsonObject& json) {
* @return An object size for JsonBuffer.
*/
size_t AutoConnectRadioJson::getObjectSize() const {
return AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(3) + _values.size() * JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(1);
size_t size =AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(3) + _values.size() * JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(1);
size += sizeof(AUTOCONNECT_JSON_KEY_LABEL) + label.length() + sizeof(AUTOCONNECT_JSON_KEY_ARRANGE) + sizeof(AUTOCONNECT_JSON_VALUE_HORIZONTAL) + sizeof(AUTOCONNECT_JSON_KEY_CHECKED);
for (String _value : _values)
size += _value.length();
return size;
}
/**
@ -197,23 +271,28 @@ size_t AutoConnectRadioJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectRadioJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACRADIO))) {
_setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL)))
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL));
label = json[F(AUTOCONNECT_JSON_KEY_LABEL)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_CHECKED)))
checked = static_cast<uint8_t>(json.get<int>(F(AUTOCONNECT_JSON_KEY_CHECKED)));
checked = static_cast<uint8_t>(json[F(AUTOCONNECT_JSON_KEY_CHECKED)].as<int>());
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_ARRANGE))) {
String arrange = json.get<String>(F(AUTOCONNECT_JSON_KEY_ARRANGE));
if (arrange.equalsIgnoreCase(F(AUTOCONNECT_JSON_KEY_VERTICAL)))
String arrange = json[F(AUTOCONNECT_JSON_KEY_ARRANGE)].as<String>();
if (arrange.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_VERTICAL)))
order = AC_Vertical;
else if (arrange.equalsIgnoreCase(F(AUTOCONNECT_JSON_KEY_HORIZONTAL)))
else if (arrange.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_HORIZONTAL)))
order = AC_Horizontal;
else {
AC_DBG("Failed to load %s element, unknown %s\n", name.c_str(), arrange.c_str());
return false;
}
}
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_VALUE))) {
empty();
JsonArray& optionArray = json[AUTOCONNECT_JSON_KEY_VALUE];
// JsonArray& optionArray = json[AUTOCONNECT_JSON_KEY_VALUE];
ArduinoJsonArray optionArray = json[AUTOCONNECT_JSON_KEY_VALUE];
for (auto value : optionArray)
add(value.as<String>());
}
@ -228,20 +307,20 @@ bool AutoConnectRadioJson::loadMember(const JsonObject& json) {
*/
void AutoConnectRadioJson::serialize(JsonObject& json) {
_serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACRADIO));
json.set(F(AUTOCONNECT_JSON_KEY_LABEL), label);
JsonArray& values = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_VALUE));
json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACRADIO));
json[F(AUTOCONNECT_JSON_KEY_LABEL)] = label;
ArduinoJsonArray values = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_VALUE));
for (String v : _values)
values.add(v);
switch (order) {
case AC_Horizontal:
json.set(F(AUTOCONNECT_JSON_KEY_ARRANGE), AUTOCONNECT_JSON_KEY_HORIZONTAL);
json[F(AUTOCONNECT_JSON_KEY_ARRANGE)] = String(F(AUTOCONNECT_JSON_VALUE_HORIZONTAL));
break;
case AC_Vertical:
json.set(F(AUTOCONNECT_JSON_KEY_ARRANGE), AUTOCONNECT_JSON_KEY_VERTICAL);
json[F(AUTOCONNECT_JSON_KEY_ARRANGE)] = String(F(AUTOCONNECT_JSON_VALUE_VERTICAL));
break;
}
json.set(F(AUTOCONNECT_JSON_KEY_CHECKED), checked);
json[F(AUTOCONNECT_JSON_KEY_CHECKED)] = checked;
}
/**
@ -249,7 +328,11 @@ void AutoConnectRadioJson::serialize(JsonObject& json) {
* @return An object size for JsonBuffer.
*/
size_t AutoConnectSelectJson::getObjectSize() const {
return AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(3) + _options.size() * JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(1);
size_t size = AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(3) + _options.size() * JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(1);
size += sizeof(AUTOCONNECT_JSON_KEY_LABEL) + label.length();
for (String _option : _options)
size += _option.length();
return size;
}
/**
@ -259,15 +342,15 @@ size_t AutoConnectSelectJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectSelectJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACSELECT))) {
_setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL))) {
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL));
label = json[F(AUTOCONNECT_JSON_KEY_LABEL)].as<String>();
}
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_OPTION))) {
empty();
JsonArray& optionArray = json[AUTOCONNECT_JSON_KEY_OPTION];
ArduinoJsonArray optionArray = json[AUTOCONNECT_JSON_KEY_OPTION];
for (auto value : optionArray)
add(value.as<String>());
return true;
@ -282,11 +365,11 @@ bool AutoConnectSelectJson::loadMember(const JsonObject& json) {
*/
void AutoConnectSelectJson::serialize(JsonObject& json) {
_serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACSELECT));
JsonArray& options = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_OPTION));
json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACSELECT));
ArduinoJsonArray options = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_OPTION));
for (String o : _options)
options.add(o);
json.set(F(AUTOCONNECT_JSON_KEY_LABEL), label);
json[F(AUTOCONNECT_JSON_KEY_LABEL)] = label;
}
/**
@ -294,7 +377,9 @@ void AutoConnectSelectJson::serialize(JsonObject& json) {
* @return An object size for JsonBuffer.
*/
size_t AutoConnectSubmitJson::getObjectSize() const {
return AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(1);
size_t size = AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(1);
size += sizeof(AUTOCONNECT_JSON_KEY_URI) + uri.length();
return size;
}
/**
@ -304,11 +389,11 @@ size_t AutoConnectSubmitJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectSubmitJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACSUBMIT))) {
_setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_URI)))
uri = json.get<String>(F(AUTOCONNECT_JSON_KEY_URI));
uri = json[F(AUTOCONNECT_JSON_KEY_URI)].as<String>();
return true;
}
return false;
@ -320,9 +405,9 @@ bool AutoConnectSubmitJson::loadMember(const JsonObject& json) {
*/
void AutoConnectSubmitJson::serialize(JsonObject& json) {
_serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACSUBMIT));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value);
json.set(F(AUTOCONNECT_JSON_KEY_URI), uri);
json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACSUBMIT));
json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json[F(AUTOCONNECT_JSON_KEY_URI)] = uri;
}
/**
@ -330,7 +415,9 @@ void AutoConnectSubmitJson::serialize(JsonObject& json) {
* @return An object size for JsonBuffer.
*/
size_t AutoConnectTextJson::getObjectSize() const {
return AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(1);
size_t size = AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(2);
size += sizeof(AUTOCONNECT_JSON_KEY_STYLE) + style.length() + sizeof(AUTOCONNECT_JSON_KEY_FORMAT) + format.length();
return size;
}
/**
@ -340,11 +427,13 @@ size_t AutoConnectTextJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectTextJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACTEXT))) {
_setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_STYLE)))
style = json.get<String>(F(AUTOCONNECT_JSON_KEY_STYLE));
style = json[F(AUTOCONNECT_JSON_KEY_STYLE)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_FORMAT)))
format = json[F(AUTOCONNECT_JSON_KEY_FORMAT)].as<String>();
return true;
}
return false;
@ -356,9 +445,10 @@ bool AutoConnectTextJson::loadMember(const JsonObject& json) {
*/
void AutoConnectTextJson::serialize(JsonObject& json) {
_serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACTEXT));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value);
json.set(F(AUTOCONNECT_JSON_KEY_STYLE), style);
json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACTEXT));
json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json[F(AUTOCONNECT_JSON_KEY_STYLE)] = style;
json[F(AUTOCONNECT_JSON_KEY_FORMAT)] = format;
}
#endif // _AUTOCONNECTELEMENTJSONIMPL_H_

@ -0,0 +1,65 @@
/**
* AutoConnect proper menu label constant definition.
* @file AutoConnectLabels.h
* @author hieromon@gmail.com
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTLABELS_H_
#define _AUTOCONNECTLABELS_H_
/**
* The upper row of each of the following definition items is the
* default value. The lower row is an alternative label string as
* a sample and can be changed you wish.
*
* Notes:
* You can find some tokens for the PageBuilder if you parse
* AutoConnectPage.cpp. Some of the tokens are valid at the time
* the AutoConnect menu will generate. For example, the token
* `{{CUR_SSID}}` returns the SSID of the currently participating
* AP by AutoConnect::_token_CURRENT_SSID function.
* You can use these tokens to display dynamic menus showing the
* current situation, but you need to know the internal structure
* of AutoConnect in order to display the appropriate menu.
*/
// Menu item: Configure new AP
#ifndef AUTOCONNECT_MENULABEL_CONFIGNEW
#define AUTOCONNECT_MENULABEL_CONFIGNEW "Configure new AP"
//#define AUTOCONNECT_MENULABEL_CONFIGNEW "Establish a new AP"
#endif // !AUTOCONNECT_MENULABEL_CONFIGNEW
// Menu item: Open SSIDs
#ifndef AUTOCONNECT_MENULABEL_OPENSSIDS
#define AUTOCONNECT_MENULABEL_OPENSSIDS "Open SSIDs"
//#define AUTOCONNECT_MENULABEL_OPENSSIDS "Open credentials"
#endif // !AUTOCONNECT_MENULABEL_OPENSSIDS
// Menu item: Disconnect
#ifndef AUTOCONNECT_MENULABEL_DISCONNECT
#define AUTOCONNECT_MENULABEL_DISCONNECT "Disconnect"
//#define AUTOCONNECT_MENULABEL_DISCONNECT "Leave {{CUR_SSID}}"
#endif // !AUTOCONNECT_MENULABEL_DISCONNECT
// Menu item: Reset...
#ifndef AUTOCONNECT_MENULABEL_RESET
#define AUTOCONNECT_MENULABEL_RESET "Reset..."
//#define AUTOCONNECT_MENULABEL_RESET "Reboot..."
#endif // !AUTOCONNECT_MENULABEL_RESET
// Menu item: HOME
#ifndef AUTOCONNECT_MENULABEL_HOME
#define AUTOCONNECT_MENULABEL_HOME "HOME"
//#define AUTOCONNECT_MENULABEL_HOME "Main"
#endif // !AUTOCONNECT_MENULABEL_HOME
// Button label: RESET
#ifndef AUTOCONNECT_BUTTONLABEL_RESET
#define AUTOCONNECT_BUTTONLABEL_RESET "RESET"
//#define AUTOCONNECT_BUTTONLABEL_RESET "Reboot"
#endif // !AUTOCONNECT_BUTTONLABEL_RESET
#endif

@ -138,8 +138,8 @@ const char AutoConnect::_CSS_ICON_LOCK[] PROGMEM = {
/**< INPUT button and submit style */
const char AutoConnect::_CSS_INPUT_BUTTON[] PROGMEM = {
"input[type=\"button\"],input[type=\"submit\"]{"
"padding:8px 30px;"
"input[type=\"button\"],input[type=\"submit\"],button[type=\"submit\"]{"
"padding:8px 0.5em;"
"font-weight:bold;"
"letter-spacing:0.8px;"
"color:#fff;"
@ -161,12 +161,13 @@ const char AutoConnect::_CSS_INPUT_BUTTON[] PROGMEM = {
"input#sb[type=\"submit\"]{"
"width:15em;"
"}"
"input[type=\"submit\"]{"
"input[type=\"submit\"],button[type=\"submit\"]{"
"padding:8px 30px;"
"background-color:#006064;"
"border-color:#006064;"
"}"
"input[type=\"button\"],input[type=\"submit\"]:focus,"
"input[type=\"button\"],input[type=\"submit\"]:active{"
"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;"
"}"
@ -525,10 +526,10 @@ const char AutoConnect::_ELM_MENU_PRE[] PROGMEM = {
"<a href=\"" AUTOCONNECT_URI "\" class=\"luxbar-brand\">MENU_TITLE</a>"
"<label class=\"luxbar-hamburger luxbar-hamburger-doublespin\" id=\"luxbar-hamburger\" for=\"luxbar-checkbox\"><span></span></label>"
"</li>"
"<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_CONFIG "\">Configure new AP</a></li>"
"<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_OPEN "\">Open SSIDs</a></li>"
"<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_DISCON "\">Disconnect</a></li>"
"<li class=\"luxbar-item\" id=\"reset\"><a href=\"#rdlg\">Reset...</a></li>"
"<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_CONFIG "\">" AUTOCONNECT_MENULABEL_CONFIGNEW "</a></li>"
"<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_OPEN "\">" AUTOCONNECT_MENULABEL_OPENSSIDS "</a></li>"
"<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_DISCON "\">" AUTOCONNECT_MENULABEL_DISCONNECT "</a></li>"
"<li class=\"luxbar-item\" id=\"reset\"><a href=\"#rdlg\">" AUTOCONNECT_MENULABEL_RESET "</a></li>"
};
const char AutoConnect::_ELM_MENU_AUX[] PROGMEM = {
@ -536,11 +537,11 @@ const char AutoConnect::_ELM_MENU_AUX[] PROGMEM = {
};
const char AutoConnect::_ELM_MENU_POST[] PROGMEM = {
"<li class=\"luxbar-item\"><a href=\"HOME_URI\">HOME</a></li>"
"<li class=\"luxbar-item\"><a href=\"HOME_URI\">" AUTOCONNECT_MENULABEL_HOME "</a></li>"
"</ul>"
"</div>"
"<div class=\"lap\" id=\"rdlg\"><a href=\"#reset\" class=\"overlap\"></a>"
"<div class=\"modal_button\"><h2><a href=\"" AUTOCONNECT_URI_RESET "\" class=\"modal_button\">RESET</a></h2></div>"
"<div class=\"modal_button\"><h2><a href=\"" AUTOCONNECT_URI_RESET "\" class=\"modal_button\">" AUTOCONNECT_BUTTONLABEL_RESET "</a></h2></div>"
"</div>"
"</header>"
};
@ -671,7 +672,7 @@ const char AutoConnect::_PAGE_CONFIGNEW[] PROGMEM = {
"<div class=\"base-panel\">"
"<form action=\"" AUTOCONNECT_URI_CONNECT "\" method=\"post\">"
"{{LIST_SSID}}"
"<div style=\"margin:16px 0 8px 0;border-bottom:solid 1px #263238;\">Hidden:{{HIDDEN_COUNT}}</div>"
"<div style=\"margin:16px 0 8px 0;border-bottom:solid 1px #263238;\">Total:{{SSID_COUNT}} Hidden:{{HIDDEN_COUNT}}</div>"
"<ul class=\"noorder\">"
"<li>"
"<label for=\"ssid\">SSID</label>"
@ -687,6 +688,12 @@ const char AutoConnect::_PAGE_CONFIGNEW[] PROGMEM = {
"</div>"
"</div>"
"</body>"
"<script type=\"text/javascript\">"
"function onFocus(value){"
"document.getElementById('ssid').value=value;"
"document.getElementById('passphrase').focus();"
"}"
"</script>"
"</html>"
};
@ -847,6 +854,25 @@ const char AutoConnect::_PAGE_DISCONN[] PROGMEM = {
"</html>"
};
// 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();
@ -906,10 +932,9 @@ String AutoConnect::_token_HEAD(PageArgument& args) {
}
String AutoConnect::_token_MENU_PRE(PageArgument& args) {
AC_UNUSED(args);
String currentMenu = FPSTR(_ELM_MENU_PRE);
currentMenu.replace(String(F("MENU_TITLE")), _menuTitle);
// currentMenu.replace(String(F("HOME_URI")), _apConfig.homeUri);
currentMenu.replace(String(F("{{CUR_SSID}}")), _token_ESTAB_SSID(args));
return currentMenu;
}
@ -1104,27 +1129,60 @@ String AutoConnect::_token_FREE_HEAP(PageArgument& args) {
}
String AutoConnect::_token_LIST_SSID(PageArgument& args) {
AC_UNUSED(args);
String ssidList = String("");
// 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);
}
// Locate to the page and build SSD list content.
String ssidList = String("");
_hiddenSSIDCount = 0;
WiFi.scanDelete();
_scanCount = WiFi.scanNetworks(false, true);
AC_DBG("%d network(s) found\n", (int)_scanCount);
uint8_t validCount = 0;
uint8_t dispCount = 0;
for (uint8_t i = 0; i < _scanCount; i++) {
String ssid = WiFi.SSID(i);
if (ssid.length() > 0) {
ssidList += String(F("<input type=\"button\" onClick=\"document.getElementById('ssid').value=this.getAttribute('value');document.getElementById('passphrase').focus()\" value=\"")) + ssid + String("\">");
ssidList += String(F("<label class=\"slist\">")) + String(AutoConnect::_toWiFiQuality(WiFi.RSSI(i))) + String(F("&#037;&ensp;Ch.")) + String(WiFi.channel(i)) + String(F("</label>"));
if (WiFi.encryptionType(i) != ENC_TYPE_NONE)
ssidList += String(F("<span class=\"img-lock\"></span>"));
ssidList += String(F("<br>"));
// 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) {
ssidList += String(F("<input type=\"button\" onClick=\"onFocus(this.getAttribute('value'))\" value=\"")) + ssid + String("\">");
ssidList += String(F("<label class=\"slist\">")) + String(AutoConnect::_toWiFiQuality(WiFi.RSSI(i))) + String(F("&#037;&ensp;Ch.")) + String(WiFi.channel(i)) + String(F("</label>"));
if (WiFi.encryptionType(i) != ENC_TYPE_NONE)
ssidList += String(F("<span class=\"img-lock\"></span>"));
ssidList += String(F("<br>"));
}
}
// 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)
ssidList += String(F("<button type=\"submit\" name=\"page\" value=\"")) + String(page - 1) + String(F("\" formaction=\"")) + String(F(AUTOCONNECT_URI_CONFIG)) + String(F("\">Prev.</button>&emsp;"));
// Prepare next button
if (validCount > (page + 1) * AUTOCONNECT_SSIDPAGEUNIT_LINES)
ssidList += String(F("<button type=\"submit\" name=\"page\" value=\"")) + String(page + 1) + String(F("\" formaction=\"")) + String(F(AUTOCONNECT_URI_CONFIG)) + String(F("\">Next</button>&emsp;"));
return ssidList;
}
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);
@ -1243,6 +1301,7 @@ PageElement* AutoConnect::_setupPage(String uri) {
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));
}
else if (uri == String(AUTOCONNECT_URI_CONNECT)) {
@ -1339,5 +1398,17 @@ PageElement* AutoConnect::_setupPage(String uri) {
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;
}

@ -10,6 +10,8 @@
#ifndef _AUTOCONNECTPAGE_H_
#define _AUTOCONNECTPAGE_H_
#include "AutoConnectLabels.h"
#define AUTOCONNECT_PARAMID_SSID "SSID"
#define AUTOCONNECT_PARAMID_PASS "Passphrase"
#define AUTOCONNECT_PARAMID_CRED "Credential"

@ -0,0 +1,38 @@
/**
* The upload wrapper base class definition and the default up-loader
* class declarations.
* @file AutoConnectUpload.h
* @author hieromon@gmail.com
* @version 0.9.8
* @date 2019-03-19
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTUPLOAD_H_
#define _AUTOCONNECTUPLOAD_H_
#if defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#elif defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h>
#include <WebServer.h>
#endif
/**
* Uploader base class. This class is a wrapper for the AutoConnectUpload
* class, and only the upload member function is implemented.
*/
class AutoConnectUploadHandler {
public:
explicit AutoConnectUploadHandler() {}
virtual ~AutoConnectUploadHandler() {}
virtual void upload(const String& requestUri, const HTTPUpload& upload);
protected:
virtual bool _open(const char* filename, const char* mode) = 0;
virtual size_t _write(const uint8_t *buf, const size_t size) = 0;
virtual void _close(void) = 0;
};
#endif // !_AUTOCONNECTUPLOAD_H_

@ -0,0 +1,145 @@
/**
* The default upload handler implementation.
* @file AutoConnectUploadImpl.h
* @author hieromon@gmail.com
* @version 0.9.8
* @date 2019-03-19
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTUPLOADIMPL_H_
#define _AUTOCONNECTUPLOADIMPL_H_
#if defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>
#elif defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h>
#include <SPIFFS.h>
#endif
#include <SPI.h>
#include <SD.h>
#define FS_NO_GLOBALS
#include <FS.h>
// Types branching to be code commonly for the file system classes with
// ESP8266 and ESP32.
#if defined(ARDUINO_ARCH_ESP8266)
typedef fs::FS SPIFFST; // SPIFFS:File system class
typedef fs::File SPIFileT; // SPIFFS:File class
typedef SDClass SDClassT; // SD:File system class
typedef File SDFileT; // SD:File class
#elif defined(ARDUINO_ARCH_ESP32)
typedef fs::SPIFFSFS SPIFFST;
typedef fs::File SPIFileT;
typedef fs::SDFS SDClassT;
typedef SDFile SDFileT;
#endif
#include "AutoConnectDefs.h"
#include "AutoConnectUpload.h"
/**
* Handles the default upload process depending on the upload status.
* This handler function supports the status of UPLOAD_FILE_START,
* UPLOAD_FILE_WRITE, UPLOAD_FILE_END and calls open, write and
* close processing respectively.
* @param requestUri A reference to the upload request uri.
* @param upload A reference of HTTPUpload entity.
*/
void AutoConnectUploadHandler::upload(const String& requestUri, const HTTPUpload& upload) {
AC_UNUSED(requestUri);
switch (upload.status) {
case UPLOAD_FILE_START: {
String absFilename = "/" + upload.filename;
(void)_open(absFilename.c_str(), "w");
break;
}
case UPLOAD_FILE_WRITE:
(void)_write(upload.buf, (const size_t)upload.currentSize);
break;
case UPLOAD_FILE_ABORTED:
case UPLOAD_FILE_END:
_close();
break;
}
}
// Default handler for uploading to the standard SPIFFS class embedded in the core.
class AutoConnectUploadFS : public AutoConnectUploadHandler {
public:
explicit AutoConnectUploadFS(SPIFFST& media) : _media(&media) {}
~AutoConnectUploadFS() { _close(); }
protected:
bool _open(const char* filename, const char* mode) override {
#if defined(ARDUINO_ARCH_ESP8266)
if (_media->begin()) {
#elif defined(ARDUINO_ARCH_ESP32)
if (_media->begin(true)) {
#endif
_file = _media->open(filename, mode);
return _file != false;
}
return false;
}
size_t _write(const uint8_t* buf, const size_t size) override {
if (_file)
return _file.write(buf, size);
else
return -1;
}
void _close(void) override {
if (_file)
_file.close();
_media->end();
}
private:
SPIFFST* _media;
SPIFileT _file;
};
// Default handler for uploading to the standard SD class embedded in the core.
class AutoConnectUploadSD : public AutoConnectUploadHandler {
public:
explicit AutoConnectUploadSD(SDClassT& media, const uint8_t cs = AUTOCONNECT_SD_CS, const uint32_t speed = AUTOCONNECT_SD_SPEED) : _media(&media), _cs(cs), _speed(speed) {}
~AutoConnectUploadSD() { _close(); }
protected:
bool _open(const char* filename, const char* mode) override {
#if defined(ARDUINO_ARCH_ESP8266)
if (_media->begin(_cs, _speed)) {
uint8_t oflag = *mode == 'w' ? FILE_WRITE : FILE_READ;
#elif defined(ARDUINO_ARCH_ESP32)
if (_media->begin(_cs, SPI, _speed)) {
const char* oflag = mode;
#endif
_file = _media->open(filename, oflag);
return _file != false;
}
return false;
}
size_t _write(const uint8_t* buf, const size_t size) override {
if (_file)
return _file.write(buf, size);
else
return -1;
}
void _close(void) override {
if (_file)
_file.close();
_media->end();
}
private:
SDClassT* _media;
SDFileT _file;
uint8_t _cs;
uint8_t _speed;
};
#endif // !_AUTOCONNECTUPLOADIMPL_H_
Loading…
Cancel
Save