Merge pull request #137 from Hieromon/Enhance/v110

Enhance/v110
pull/142/head v1.1.0
Hieromon Ikasamo 5 years ago committed by GitHub
commit b79028346e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      README.md
  2. 2
      docs/advancedusage.html
  3. 23
      docs/changelog.html
  4. 106
      docs/credit.html
  5. 44
      docs/faq.html
  6. 4
      docs/gettingstarted.html
  7. BIN
      docs/images/newap.png
  8. BIN
      docs/images/newap_static.png
  9. 291
      docs/images/process_begin.svg
  10. BIN
      docs/images/staticip.png
  11. 54
      docs/menu.html
  12. 2
      docs/search/search_index.json
  13. 58
      docs/sitemap.xml
  14. BIN
      docs/sitemap.xml.gz
  15. 8
      examples/ConfigIP/ConfigIP.ino
  16. 4
      examples/Credential/Credential.ino
  17. 13
      examples/CreditMigrate/CreditMigrate.ino
  18. 2
      library.json
  19. 2
      library.properties
  20. 2
      mkdocs/advancedusage.md
  21. 4
      mkdocs/changelog.md
  22. 70
      mkdocs/credit.md
  23. 23
      mkdocs/faq.md
  24. 3
      mkdocs/gettingstarted.md
  25. BIN
      mkdocs/images/newap.png
  26. BIN
      mkdocs/images/newap_static.png
  27. 291
      mkdocs/images/process_begin.svg
  28. BIN
      mkdocs/images/staticip.png
  29. 42
      mkdocs/menu.md
  30. 175
      src/AutoConnect.cpp
  31. 11
      src/AutoConnect.h
  32. 159
      src/AutoConnectCredential.cpp
  33. 57
      src/AutoConnectCredential.h
  34. 4
      src/AutoConnectDefs.h
  35. 209
      src/AutoConnectPage.cpp
  36. 10
      src/AutoConnectPage.h
  37. 2
      src/AutoConnectUpdate.cpp
  38. 2
      src/AutoConnectUpdatePage.h

@ -101,6 +101,10 @@ Full documentation is available on https://Hieromon.github.io/AutoConnect, some
## Change log ## Change log
### [1.1.0] Oct. 15, 2019
- Supports static IPs with the 'Configure new AP' menu. (issue #132)
- Fixed compilation error that no member named 'printTo' with ArduinoJson 5.
### [1.0.3] Sept. 30, 2019 ### [1.0.3] Sept. 30, 2019
- Fixed a return of AutoConnectCredential::entries(). (issue #133) - Fixed a return of AutoConnectCredential::entries(). (issue #133)

@ -1354,7 +1354,7 @@ Also, if you want to stop AutoConnect completely when the captive portal is time
<h3 id="casts-the-html-pages-to-be-add-on-into-the-menu"><i class="fa fa-caret-right"></i> Casts the HTML pages to be add-on into the menu<a class="headerlink" href="#casts-the-html-pages-to-be-add-on-into-the-menu" title="Permanent link">&para;</a></h3> <h3 id="casts-the-html-pages-to-be-add-on-into-the-menu"><i class="fa fa-caret-right"></i> Casts the HTML pages to be add-on into the menu<a class="headerlink" href="#casts-the-html-pages-to-be-add-on-into-the-menu" title="Permanent link">&para;</a></h3>
<p>If your sketch handles web pages, you can embed the pages into the AutoConnect menu in continuance enjoying the utility of the WiFi connection feature. Unlike the custom Web pages by <a href="acelements.html">AutoConnectElements</a>, this allows to legacy web pages registered by <em>ESP8266WebServer::on</em> or <em>WebServer::on</em> function.</p> <p>If your sketch handles web pages, you can embed the pages into the AutoConnect menu in continuance enjoying the utility of the WiFi connection feature. Unlike the custom Web pages by <a href="acelements.html">AutoConnectElements</a>, this allows to legacy web pages registered by <em>ESP8266WebServer::on</em> or <em>WebServer::on</em> function.</p>
<p>You can use AutoConnectAux only constructed with the URI of the page to be embedding. AutoConnectElements is not required. The basic procedure for this as follows:</p> <p>To implement embedding your legacy web pages to the AutoConnect menu, you can use AutoConnectAux only constructed with the URI of the page to be embedding. AutoConnectElements is not required. The basic procedure for this as follows:</p>
<ol> <ol>
<li>Declare AutoConnectAux for each legacy page. It includes the URI of the page and item string which will display in the AutoConnect menu.</li> <li>Declare AutoConnectAux for each legacy page. It includes the URI of the page and item string which will display in the AutoConnect menu.</li>
<li>Sketch the legacy page handlers.</li> <li>Sketch the legacy page handlers.</li>

@ -122,7 +122,7 @@
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> <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> <label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<a href="#103-sept-30-2019" tabindex="1" class="md-skip"> <a href="#110-oct-15-2019" tabindex="1" class="md-skip">
Skip to content Skip to content
</a> </a>
@ -725,6 +725,13 @@
<label class="md-nav__title" for="__toc">Table of contents</label> <label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix> <ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#110-oct-15-2019" title="[1.1.0] Oct. 15, 2019" class="md-nav__link">
[1.1.0] Oct. 15, 2019
</a>
</li>
<li class="md-nav__item"> <li class="md-nav__item">
<a href="#103-sept-30-2019" title="[1.0.3] Sept. 30, 2019" class="md-nav__link"> <a href="#103-sept-30-2019" title="[1.0.3] Sept. 30, 2019" class="md-nav__link">
[1.0.3] Sept. 30, 2019 [1.0.3] Sept. 30, 2019
@ -878,6 +885,13 @@
<label class="md-nav__title" for="__toc">Table of contents</label> <label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix> <ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#110-oct-15-2019" title="[1.1.0] Oct. 15, 2019" class="md-nav__link">
[1.1.0] Oct. 15, 2019
</a>
</li>
<li class="md-nav__item"> <li class="md-nav__item">
<a href="#103-sept-30-2019" title="[1.0.3] Sept. 30, 2019" class="md-nav__link"> <a href="#103-sept-30-2019" title="[1.0.3] Sept. 30, 2019" class="md-nav__link">
[1.0.3] Sept. 30, 2019 [1.0.3] Sept. 30, 2019
@ -1009,7 +1023,12 @@
<h1>Change log</h1> <h1>Change log</h1>
<h4 id="103-sept-30-2019">[1.0.3] Sept. 30, 2019<a class="headerlink" href="#103-sept-30-2019" title="Permanent link">&para;</a></h4> <h4 id="110-oct-15-2019">[1.1.0] Oct. 15, 2019<a class="headerlink" href="#110-oct-15-2019" title="Permanent link">&para;</a></h4>
<ul>
<li>Supports static IPs with the <a href="menu.html#configure-new-ap"><strong>Configure new AP</strong></a> menu.</li>
<li>Fixed compilation error that no member named 'printTo' with ArduinoJson 5.</li>
</ul>
<h4 id="103-sept-30-2019">[1.0.3] Sept. 30, 2019<a class="headerlink" href="#103-sept-30-2019" title="Permanent link">&para;</a></h4>
<ul> <ul>
<li>Fixed a return of AutoConnectCredential::entries().</li> <li>Fixed a return of AutoConnectCredential::entries().</li>
</ul> </ul>

@ -772,8 +772,8 @@
<ul class="md-nav__list"> <ul class="md-nav__list">
<li class="md-nav__item"> <li class="md-nav__item">
<a href="#station_config" title=" station_config" class="md-nav__link"> <a href="#station_config_t" title=" station_config_t" class="md-nav__link">
station_config station_config_t
</a> </a>
</li> </li>
@ -982,8 +982,8 @@
<ul class="md-nav__list"> <ul class="md-nav__list">
<li class="md-nav__item"> <li class="md-nav__item">
<a href="#station_config" title=" station_config" class="md-nav__link"> <a href="#station_config_t" title=" station_config_t" class="md-nav__link">
station_config station_config_t
</a> </a>
</li> </li>
@ -1075,37 +1075,37 @@
<dd>Number of entries as contained credentials.</dd> <dd>Number of entries as contained credentials.</dd>
</dl></p> </dl></p>
<h4 id="load"><i class="fa fa-caret-right"></i> load<a class="headerlink" href="#load" title="Permanent link">&para;</a></h4> <h4 id="load"><i class="fa fa-caret-right"></i> load<a class="headerlink" href="#load" title="Permanent link">&para;</a></h4>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">int8_t</span> <span style="color: #f8f8f2">load(</span><span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">ssid,</span> <span style="color: #66d9ef">struct</span> <span style="color: #f8f8f2">station_config</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">config)</span> <div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">int8_t</span> <span style="color: #f8f8f2">load(</span><span style="color: #66d9ef">const</span> <span style="color: #66d9ef">char</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">ssid,</span> <span style="color: #f8f8f2">station_config_t</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">config)</span>
</pre></div> </pre></div>
<p>Load a credential entry and store to <strong>config</strong>. <p>Load a credential entry and store to <strong>config</strong>.
<dl class="apidl"> <dl class="apidl">
<dt><strong>Parameters</strong></dt> <dt><strong>Parameters</strong></dt>
<dd><span class="apidef">ssid</span><span class="apidesc">SSID to be loaded.</span></dd> <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> <dd><span class="apidef">config</span><span class="apidesc">station_config_t</span></dd>
<dt><strong>Return value</strong></dt> <dt><strong>Return value</strong></dt>
<dd>Save the specified SSID's credential entry to station_config pointed to by the parameter as <strong>config</strong>. -1 is returned if the SSID is not saved. </dd> <dd>Save the specified SSID's credential entry to station_config_t pointed to by the parameter as <strong>config</strong>. -1 is returned if the SSID is not saved. </dd>
</dl></p> </dl></p>
<h4 id="load_1"><i class="fa fa-caret-right"></i> load<a class="headerlink" href="#load_1" title="Permanent link">&para;</a></h4> <h4 id="load_1"><i class="fa fa-caret-right"></i> load<a class="headerlink" href="#load_1" title="Permanent link">&para;</a></h4>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">bool</span> <span style="color: #f8f8f2">load(</span><span style="color: #66d9ef">int8_t</span> <span style="color: #f8f8f2">entry,</span> <span style="color: #66d9ef">struct</span> <span style="color: #f8f8f2">station_config</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">config)</span> <div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">bool</span> <span style="color: #f8f8f2">load(</span><span style="color: #66d9ef">int8_t</span> <span style="color: #f8f8f2">entry,</span> <span style="color: #f8f8f2">station_config_t</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">config)</span>
</pre></div> </pre></div>
<p>Load a credential entry and store to <strong>config</strong>. <p>Load a credential entry and store to <strong>config</strong>.
<dl class="apidl"> <dl class="apidl">
<dt><strong>Parameters</strong></dt> <dt><strong>Parameters</strong></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">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> <dd><span class="apidef">config</span><span class="apidesc">station_config_t</span></dd>
<dt><strong>Return value</strong></dt> <dt><strong>Return value</strong></dt>
<dd>Save the specified credential entry to station_config pointed to by the parameter as <strong>config</strong>. -1 is returned if specified number is not saved. </dd> <dd>Save the specified credential entry to station_config_t pointed to by the parameter as <strong>config</strong>. -1 is returned if specified number is not saved. </dd>
</dl></p> </dl></p>
<h4 id="save"><i class="fa fa-caret-right"></i> save<a class="headerlink" href="#save" title="Permanent link">&para;</a></h4> <h4 id="save"><i class="fa fa-caret-right"></i> save<a class="headerlink" href="#save" title="Permanent link">&para;</a></h4>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">bool</span> <span style="color: #f8f8f2">save(</span><span style="color: #66d9ef">const</span> <span style="color: #66d9ef">struct</span> <span style="color: #f8f8f2">station_config</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">config)</span> <div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">bool</span> <span style="color: #f8f8f2">save(</span><span style="color: #66d9ef">const</span> <span style="color: #f8f8f2">station_config_t</span><span style="color: #f92672">*</span> <span style="color: #f8f8f2">config)</span>
</pre></div> </pre></div>
<p>Save a credential entry. <p>Save a credential entry.
<dl class="apidl"> <dl class="apidl">
<dt><strong>Parameter</strong></dt> <dt><strong>Parameter</strong></dt>
<dd><span class="apidef">config</span><span class="apidesc">station_config to be saved.</span></dd> <dd><span class="apidef">config</span><span class="apidesc">station_config_t to be saved.</span></dd>
<dt><strong>Return value</strong></dt> <dt><strong>Return value</strong></dt>
<dd><span class="apidef">true</span><span class="apidesc">Successfully saved.</span></dd> <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> <dd><span class="apidef">false</span><span class="apidesc">Failed to save.</span></dd>
@ -1128,7 +1128,7 @@
The following function is an implementation example, and you can use it to achieve batch clearing. The following function is an implementation example, and you can use it to achieve batch clearing.
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">void</span> <span style="color: #a6e22e">deleteAllCredentials</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">)</span> <span style="color: #f8f8f2">{</span> <div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #66d9ef">void</span> <span style="color: #a6e22e">deleteAllCredentials</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">)</span> <span style="color: #f8f8f2">{</span>
<span style="color: #f8f8f2">AutoConnectCredential</span> <span style="color: #f8f8f2">credential;</span> <span style="color: #f8f8f2">AutoConnectCredential</span> <span style="color: #f8f8f2">credential;</span>
<span style="color: #66d9ef">struct</span> <span style="color: #f8f8f2">station_config</span> <span style="color: #f8f8f2">config;</span> <span style="color: #f8f8f2">station_config_t</span> <span style="color: #f8f8f2">config;</span>
<span style="color: #66d9ef">uint8_t</span> <span style="color: #f8f8f2">ent</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">credential.entries();</span> <span style="color: #66d9ef">uint8_t</span> <span style="color: #f8f8f2">ent</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">credential.entries();</span>
<span style="color: #66d9ef">while</span> <span style="color: #f8f8f2">(ent</span><span style="color: #f92672">--</span><span style="color: #f8f8f2">)</span> <span style="color: #f8f8f2">{</span> <span style="color: #66d9ef">while</span> <span style="color: #f8f8f2">(ent</span><span style="color: #f92672">--</span><span style="color: #f8f8f2">)</span> <span style="color: #f8f8f2">{</span>
@ -1139,27 +1139,36 @@ The following function is an implementation example, and you can use it to achie
</pre></div></p> </pre></div></p>
</div> </div>
<h2 id="the-data-structures">The data structures<a class="headerlink" href="#the-data-structures" title="Permanent link">&para;</a></h2> <h2 id="the-data-structures">The data structures<a class="headerlink" href="#the-data-structures" title="Permanent link">&para;</a></h2>
<h3 id="station_config"><i class="fa fa-code"></i> station_config<a class="headerlink" href="#station_config" title="Permanent link">&para;</a></h3> <h3 id="station_config_t"><i class="fa fa-code"></i> station_config_t<a class="headerlink" href="#station_config_t" title="Permanent link">&para;</a></h3>
<p>A structure is included in the ESP8266 SDK. You can use it in the sketch like as follows:</p> <p>The saved credential structure is defined as stato_config_t in the AcutoConnectCredential header file.</p>
<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> <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: #75715e">#include</span> <span style="color: #75715e">&lt;user_interface.h&gt;</span> <span style="color: #66d9ef">uint8_t</span> <span style="color: #f8f8f2">ssid[</span><span style="color: #ae81ff">32</span><span style="color: #f8f8f2">];</span>
<span style="color: #f8f8f2">}</span> <span style="color: #66d9ef">uint8_t</span> <span style="color: #f8f8f2">password[</span><span style="color: #ae81ff">64</span><span style="color: #f8f8f2">];</span>
</pre></div> <span style="color: #66d9ef">uint8_t</span> <span style="color: #f8f8f2">bssid[</span><span style="color: #ae81ff">6</span><span style="color: #f8f8f2">];</span>
<span style="color: #66d9ef">uint8_t</span> <span style="color: #f8f8f2">dhcp;</span> <span style="color: #75715e">/**&lt; 0:DHCP, 1:Static IP */</span>
<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: #66d9ef">union</span> <span style="color: #f8f8f2">_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: #66d9ef">uint32_t</span> <span style="color: #f8f8f2">addr[</span><span style="color: #ae81ff">5</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: #66d9ef">struct</span> <span style="color: #f8f8f2">_sta</span> <span style="color: #f8f8f2">{</span>
<span style="color: #f8f8f2">uint8</span> <span style="color: #f8f8f2">bssid_set;</span> <span style="color: #66d9ef">uint32_t</span> <span style="color: #f8f8f2">ip;</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: #66d9ef">uint32_t</span> <span style="color: #f8f8f2">gateway;</span>
<span style="color: #f8f8f2">};</span> <span style="color: #66d9ef">uint32_t</span> <span style="color: #f8f8f2">netmask;</span>
<span style="color: #66d9ef">uint32_t</span> <span style="color: #f8f8f2">dns1;</span>
<span style="color: #66d9ef">uint32_t</span> <span style="color: #f8f8f2">dns2;</span>
<span style="color: #f8f8f2">}</span> <span style="color: #f8f8f2">sta;</span>
<span style="color: #f8f8f2">}</span> <span style="color: #f8f8f2">config;</span>
<span style="color: #f8f8f2">}</span> <span style="color: #f8f8f2">station_config_t;</span>
</pre></div> </pre></div>
<div class="admonition note">
<p class="admonition-title">The byte size of station_config_t in program memory and stored credentials is different</p>
<p>There is a gap byte for boundary alignment between the <code>dhcp</code> member and the static IP members of the above station_config_t. Its gap byte will be removed with saved credentials on the flash.</p>
</div>
<h3 id="the-credential-entry"><i class="fa fa-code"></i> The credential entry<a class="headerlink" href="#the-credential-entry" title="Permanent link">&para;</a></h3> <h3 id="the-credential-entry"><i class="fa fa-code"></i> The credential entry<a class="headerlink" href="#the-credential-entry" title="Permanent link">&para;</a></h3>
<p>A data structure of the credential saving area in EEPROM as the below. <sup id="fnref:4"><a class="footnote-ref" href="#fn:4" rel="footnote">4</a></sup></p> <p>A data structure of the credential saving area in EEPROM as the below. <sup id="fnref:4"><a class="footnote-ref" href="#fn:4" rel="footnote">4</a></sup></p>
<table> <table>
<thead> <thead>
<tr> <tr>
<th>Byte offset</th> <th>byte offset</th>
<th>Length</th> <th>Length</th>
<th>Value</th> <th>Value</th>
</tr> </tr>
@ -1197,8 +1206,43 @@ The following function is an implementation example, and you can use it to achie
</tr> </tr>
<tr> <tr>
<td>variable</td> <td>variable</td>
<td>1</td>
<td>Flag for DHCP or Static IP (0:DHCP, 1:Static IP)</td>
</tr>
<tr>
<td><td colspan=3>The following IP address entries are stored only for static IPs.</td>
<td></td>
<td></td> <td></td>
<td>Contained the next entries. (Continuation SSID+Password+BSSID)</td> </tr>
<tr>
<td>variable(1)</td>
<td>4</td>
<td>Station IP address (uint32_t)</td>
</tr>
<tr>
<td>variable(5)</td>
<td>4</td>
<td>Gateway address (uint32_t)</td>
</tr>
<tr>
<td>variable(9)</td>
<td>4</td>
<td>Netmask (uint32_t)</td>
</tr>
<tr>
<td>variable(13)</td>
<td>4</td>
<td>Primary DNS address (uint32_t)</td>
</tr>
<tr>
<td>variable(17)</td>
<td>4</td>
<td>Secondary IP address (uint32_t)</td>
</tr>
<tr>
<td>variable</td>
<td>variable</td>
<td>Contained the next entries. (Continuation SSID+Password+BSSID+DHCP flag+Static IPs(if exists))</td>
</tr> </tr>
<tr> <tr>
<td>variable</td> <td>variable</td>
@ -1207,6 +1251,12 @@ The following function is an implementation example, and you can use it to achie
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div class="admonition note">
<p class="admonition-title">AutoConnectCredential has changed</p>
<p>It was lost AutoConnectCredential backward compatibility. Credentials saved by AutoConnect v1.0.3 (or earlier) will not work properly with AutoConnect v1.1.0. You need to erase the flash of the ESP module using the esptool before the sketch uploading.
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span>esptool -c esp8266 (or esp32) - p [COM_PORT] erase_flash
</pre></div></p>
</div>
<div class="footnote"> <div class="footnote">
<hr /> <hr />
<ol> <ol>

@ -857,6 +857,20 @@
I cannot see the custom Web page. I cannot see the custom Web page.
</a> </a>
</li>
<li class="md-nav__item">
<a href="#saved-credentials-are-wrong-or-lost" title=" Saved credentials are wrong or lost." class="md-nav__link">
Saved credentials are wrong or lost.
</a>
</li>
<li class="md-nav__item">
<a href="#some-autoconnect-page-is-cut-off" title=" Some AutoConnect page is cut off." class="md-nav__link">
Some AutoConnect page is cut off.
</a>
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
@ -1124,6 +1138,20 @@
I cannot see the custom Web page. I cannot see the custom Web page.
</a> </a>
</li>
<li class="md-nav__item">
<a href="#saved-credentials-are-wrong-or-lost" title=" Saved credentials are wrong or lost." class="md-nav__link">
Saved credentials are wrong or lost.
</a>
</li>
<li class="md-nav__item">
<a href="#some-autoconnect-page-is-cut-off" title=" Some AutoConnect page is cut off." class="md-nav__link">
Some AutoConnect page is cut off.
</a>
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
@ -1361,6 +1389,22 @@ wdt reset
<p>Because AutoConnect does not send a login success response to the captive portal requests from the smartphone. The login success response varies iOS, Android and Windows. By analyzing the request URL of different login success inquiries for each OS, the correct behavior can be implemented, but not yet. Please resets ESP8266 from the AutoConnect menu.</p> <p>Because AutoConnect does not send a login success response to the captive portal requests from the smartphone. The login success response varies iOS, Android and Windows. By analyzing the request URL of different login success inquiries for each OS, the correct behavior can be implemented, but not yet. Please resets ESP8266 from the AutoConnect menu.</p>
<h2 id="i-cannot-see-the-custom-web-page"><i class="fa fa-question-circle"></i> I cannot see the custom Web page.<a class="headerlink" href="#i-cannot-see-the-custom-web-page" title="Permanent link">&para;</a></h2> <h2 id="i-cannot-see-the-custom-web-page"><i class="fa fa-question-circle"></i> I cannot see the custom Web page.<a class="headerlink" href="#i-cannot-see-the-custom-web-page" title="Permanent link">&para;</a></h2>
<p>If the sketch is correct, a JSON syntax error may have occurred. In this case, activate the <a href="faq.html#3-turn-on-the-debug-log-options">AC_DEBUG</a> and rerun. If you take the message of JSON syntax error, the <a href="https://arduinojson.org/v5/assistant/">Json Assistant</a> helps syntax checking. This online tool is provided by the author of ArduinoJson and is most consistent for the AutoConnect. </p> <p>If the sketch is correct, a JSON syntax error may have occurred. In this case, activate the <a href="faq.html#3-turn-on-the-debug-log-options">AC_DEBUG</a> and rerun. If you take the message of JSON syntax error, the <a href="https://arduinojson.org/v5/assistant/">Json Assistant</a> helps syntax checking. This online tool is provided by the author of ArduinoJson and is most consistent for the AutoConnect. </p>
<h2 id="saved-credentials-are-wrong-or-lost"><i class="fa fa-question-circle"></i> Saved credentials are wrong or lost.<a class="headerlink" href="#saved-credentials-are-wrong-or-lost" title="Permanent link">&para;</a></h2>
<p>A structure of AutoConnect saved credentials has changed two times throughout enhancement with v1.0.3 and v1.1.0. In particular, due to enhancements in v1.1.0, AutoConnectCredential data structure has lost the backward compatibility with previous versions. You must erase the flash of the ESP module using the esptool completely to save the credentials correctly with v1.1.0.
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span>esptool -c esp8266 (or esp32) -p [COM_PORT] erase_flash
</pre></div></p>
<h2 id="some-autoconnect-page-is-cut-off"><i class="fa fa-question-circle"></i> Some AutoConnect page is cut off.<a class="headerlink" href="#some-autoconnect-page-is-cut-off" title="Permanent link">&para;</a></h2>
<p>It may be two possibilities as follows:</p>
<ol>
<li>Packet loss during transmission due to a too weak WiFi signal.</li>
<li>Heap is insufficient memory. AutoConnect entrusts HTML generation to PageBuilder that makes heavy use the String::concatenate function and causes memory fragmentation. This is a structural problem with PageBuilder, but it is difficult to solve immediately.</li>
</ol>
<p>If this issue produces with your sketch, Reloading the page may recover.<br />
Also, you can check the memory running out status by rebuilding the sketch with <a href="faq.html#fn:2">PageBuilder's debug log option</a> turned on.</p>
<p>If the heap memory is insufficient, the following message is displayed on the serial console.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span>[PB] Failed building, free heap:&lt;Size of free heap&gt;
</pre></div>
<h2 id="submit-element-in-a-custom-web-page-does-not-react"><i class="fa fa-question-circle"></i> Submit element in a custom Web page does not react.<a class="headerlink" href="#submit-element-in-a-custom-web-page-does-not-react" title="Permanent link">&para;</a></h2> <h2 id="submit-element-in-a-custom-web-page-does-not-react"><i class="fa fa-question-circle"></i> Submit element in a custom Web page does not react.<a class="headerlink" href="#submit-element-in-a-custom-web-page-does-not-react" title="Permanent link">&para;</a></h2>
<p>Is there the AutoConnectElements element named <strong>SUBMIT</strong> in the custom Web page? (case sensitive ignored) AutoConnect does not rely on the <code>input type=submit</code> element for the form submission and uses <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit">HTML form element submit</a> function instead. So, the submit function will fail if there is an element named 'submit' in the form. You can not use <strong>SUBMIT</strong> as the element name of AutoConnectElements in a custom Web page that declares the AutoConnectSubmit element.</p> <p>Is there the AutoConnectElements element named <strong>SUBMIT</strong> in the custom Web page? (case sensitive ignored) AutoConnect does not rely on the <code>input type=submit</code> element for the form submission and uses <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit">HTML form element submit</a> function instead. So, the submit function will fail if there is an element named 'submit' in the form. You can not use <strong>SUBMIT</strong> as the element name of AutoConnectElements in a custom Web page that declares the AutoConnectSubmit element.</p>
<h2 id="still-not-stable-with-my-sketch"><i class="fa fa-question-circle"></i> Still, not stable with my sketch.<a class="headerlink" href="#still-not-stable-with-my-sketch" title="Permanent link">&para;</a></h2> <h2 id="still-not-stable-with-my-sketch"><i class="fa fa-question-circle"></i> Still, not stable with my sketch.<a class="headerlink" href="#still-not-stable-with-my-sketch" title="Permanent link">&para;</a></h2>

@ -907,6 +907,10 @@
<h3 id="join-to-the-new-access-point"><i class="fa fa-cog"></i> Join to the new access point<a class="headerlink" href="#join-to-the-new-access-point" title="Permanent link">&para;</a></h3> <h3 id="join-to-the-new-access-point"><i class="fa fa-cog"></i> Join to the new access point<a class="headerlink" href="#join-to-the-new-access-point" title="Permanent link">&para;</a></h3>
<p>Here, tap <em>"Configure new AP"</em> to connect the new access point then the SSID configuration screen would be shown. Enter the <strong>SSID</strong> and <strong>Passphrase</strong> and tap <strong>apply</strong> to start connecting the access point.</p> <p>Here, tap <em>"Configure new AP"</em> to connect the new access point then the SSID configuration screen would be shown. Enter the <strong>SSID</strong> and <strong>Passphrase</strong> and tap <strong>apply</strong> to start connecting the access point.</p>
<p><img src="images/menu_login.png" style="border:1px solid lightgrey;width:280px;" /><img src="images/arrow_right.svg" style="vertical-align:top;padding-top:120px;width:48px;margin-left:30px;margin-right:30px;" /><img src="images/config_ssid.png" style="border:1px solid lightgrey;width:280px;" /></p> <p><img src="images/menu_login.png" style="border:1px solid lightgrey;width:280px;" /><img src="images/arrow_right.svg" style="vertical-align:top;padding-top:120px;width:48px;margin-left:30px;margin-right:30px;" /><img src="images/config_ssid.png" style="border:1px solid lightgrey;width:280px;" /></p>
<div class="admonition info">
<p class="admonition-title">Can be configured with static IP</p>
<p>Since v1.1.0, <a href="menu.html#configure-new-ap"><strong>Configure new AP</strong></a> menu can configure for WIFI_STA with static IP.</p>
</div>
<h3 id="connection-establishment"><i class="fa fa-rss"></i> Connection establishment<a class="headerlink" href="#connection-establishment" title="Permanent link">&para;</a></h3> <h3 id="connection-establishment"><i class="fa fa-rss"></i> Connection establishment<a class="headerlink" href="#connection-establishment" title="Permanent link">&para;</a></h3>
<p>After connection established, the current status screen will appear. It is already connected to WLAN with WiFi mode as WIFI_AP_STA and the IP connection status is displayed there including the SSID. Then at this screen, you have two options for the next step.</p> <p>After connection established, the current status screen will appear. It is already connected to WLAN with WiFi mode as WIFI_AP_STA and the IP connection status is displayed there including the SSID. Then at this screen, you have two options for the next step.</p>
<p>For one, continues execution of the sketch while keeping this connection. You can access ESP8266 via browser through the established IP address after cancel to "<strong>Log in</strong>" by upper right on the screen.<br /> <p>For one, continues execution of the sketch while keeping this connection. You can access ESP8266 via browser through the established IP address after cancel to "<strong>Log in</strong>" by upper right on the screen.<br />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

@ -9,9 +9,9 @@
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="99.56517mm" width="109mm"
height="304.07242mm" height="371.83472mm"
viewBox="0 0 99.56517 304.07241" viewBox="0 0 108.99999 371.83472"
version="1.1" version="1.1"
id="svg8776" id="svg8776"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)" inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
@ -224,6 +224,21 @@
style="stroke-width:2" style="stroke-width:2"
id="path2786" /> id="path2786" />
</symbol> </symbol>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0"
refX="0"
id="marker10923-1"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path10921-8"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(0.6)"
inkscape:connector-curvature="0" />
</marker>
</defs> </defs>
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
@ -233,12 +248,12 @@
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1.4142136" inkscape:zoom="1.4142136"
inkscape:cx="192.80115" inkscape:cx="259.43725"
inkscape:cy="364.94967" inkscape:cy="1200.0696"
inkscape:document-units="mm" inkscape:document-units="mm"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:snap-global="false" inkscape:snap-global="true"
inkscape:snap-bbox="true" inkscape:snap-bbox="true"
inkscape:snap-nodes="true" inkscape:snap-nodes="true"
inkscape:snap-others="true" inkscape:snap-others="true"
@ -249,11 +264,11 @@
inkscape:bbox-nodes="true" inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true" inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true" inkscape:snap-bbox-midpoints="true"
inkscape:window-width="1920" inkscape:window-width="1571"
inkscape:window-height="1029" inkscape:window-height="1013"
inkscape:window-x="1272" inkscape:window-x="1376"
inkscape:window-y="-8" inkscape:window-y="0"
inkscape:window-maximized="1" inkscape:window-maximized="0"
fit-margin-top="0" fit-margin-top="0"
fit-margin-left="0" fit-margin-left="0"
fit-margin-right="0" fit-margin-right="0"
@ -261,8 +276,8 @@
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid9104" id="grid9104"
originx="-23.598368" originx="-23.664512"
originy="15.544285" /> originy="15.544259" />
</sodipodi:namedview> </sodipodi:namedview>
<metadata <metadata
id="metadata8773"> id="metadata8773">
@ -280,7 +295,17 @@
inkscape:label="レイヤー 1" inkscape:label="レイヤー 1"
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="translate(-23.598368,-8.4718652)"> transform="translate(-23.664512,59.290411)">
<path
style="fill:none;stroke:#000000;stroke-width:0.26458341px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208337,-11.256129 v 3.8405916"
id="path9639-8-5-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208337,16.669816 v 3.840593"
id="path9639"
inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208334,32.416659 v 4.08568" d="m 58.208334,32.416659 v 4.08568"
@ -464,7 +489,7 @@
</g> </g>
<g <g
id="g9633" id="g9633"
transform="translate(-33.072919,2.6458338)"> transform="translate(-33.734378,-65.116439)">
<rect <rect
ry="0.26458257" ry="0.26458257"
rx="0.26458332" rx="0.26458332"
@ -486,11 +511,6 @@
id="tspan9136" id="tspan9136"
sodipodi:role="line">STA</tspan></text> sodipodi:role="line">STA</tspan></text>
</g> </g>
<path
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208334,16.669815 v 3.840593"
id="path9639"
inkscape:connector-curvature="0" />
<g <g
id="g9714" id="g9714"
transform="translate(-78.07551,36.012307)"> transform="translate(-78.07551,36.012307)">
@ -781,13 +801,13 @@
</g> </g>
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 105.83333,175.75504 V 297.54958 H 92.604167" d="M 105.83318,175.75505 V 297.53597 H 92.575102"
id="path9639-1-3-9" id="path9639-1-3-9"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" /> sodipodi:nodetypes="ccc" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:0.26458329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 75.563113,86.193127 30.107867,-0.06083 0.0306,81.420513" d="m 75.513505,86.193127 30.107915,-0.06083 0.0306,81.420513"
id="path10088" id="path10088"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" /> sodipodi:nodetypes="ccc" />
@ -838,13 +858,13 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:0.26458329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 40.845696,26.589892 23.730739,26.467079 23.812499,163.71219 H 58.208331" d="M 40.91184,26.461738 23.796883,26.338925 23.878643,163.58402 H 58.274475"
id="path10088-9" id="path10088-9"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /> sodipodi:nodetypes="cccc" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10923)" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10923)"
d="m 24.291915,102.06832 h 16.45392" d="m 24.374806,102.06831 h 16.52812"
id="path10088-92" id="path10088-92"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" /> sodipodi:nodetypes="cc" />
@ -870,7 +890,7 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart)" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart)"
d="m 57.679167,215.1778 -33.866667,0.13255 0.0073,40.48128 h 16.92604" d="m 57.676398,215.1778 -33.837442,0.13255 0.0074,40.48128 H 40.75779"
id="path10088-92-6" id="path10088-92-6"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /> sodipodi:nodetypes="cccc" />
@ -891,7 +911,7 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10931)" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10931)"
d="m 58.7375,265.97716 33.866674,-0.13255 -0.0073,-40.48128 H 75.670833" d="m 58.570889,265.97716 33.866674,-0.13255 -0.0073,-40.48128 H 75.504222"
id="path10088-92-6-8" id="path10088-92-6-8"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /> sodipodi:nodetypes="cccc" />
@ -912,7 +932,7 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10937)" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10937)"
d="m 58.7375,297.59504 33.734352,-0.0718 -0.007,-21.90474 H 75.538509" d="m 58.708562,297.61156 33.734352,-0.0718 -0.007,-21.90474 H 75.509571"
id="path10088-92-6-8-3" id="path10088-92-6-8-3"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /> sodipodi:nodetypes="cccc" />
@ -982,12 +1002,6 @@
x="60.844864" x="60.844864"
y="110.3716" y="110.3716"
style="stroke-width:0.26458332">YES</tspan></text> style="stroke-width:0.26458332">YES</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 75.257782,153.66218 30.310608,0.13228"
id="path10088-92-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
@ -1165,7 +1179,7 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 41.085466,42.413935 -10.12458,-0.0196 0.01766,22.036862 h 27.103849" d="m 41.054322,42.447007 -10.258285,-0.0196 0.01789,22.036862 H 58.27571"
id="path10088-9-7" id="path10088-9-7"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /> sodipodi:nodetypes="cccc" />
@ -1201,5 +1215,214 @@
x="60.844868" x="60.844868"
y="50.651817" y="50.651817"
style="stroke-width:0.26458332">Specified</tspan></text> style="stroke-width:0.26458332">Specified</tspan></text>
<g
id="g1109"
transform="translate(-37.739185,-61.587591)">
<g
id="g2292">
<rect
style="opacity:0.66000001;vector-effect:none;fill:#e7f3ff;fill-opacity:1;stroke:#000000;stroke-width:0.26458329;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
id="rect9134-4-7-4-7"
width="34.395828"
height="7.9375019"
x="78.749603"
y="14.472153"
rx="0.26458332"
ry="0.26458257" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="84.833466"
y="19.319145"
id="text9138-7-3-9-9"><tspan
y="19.319145"
x="84.833466"
sodipodi:role="line"
id="tspan1104">Set hostname</tspan></text>
</g>
</g>
<g
id="g1197"
transform="translate(-0.22278483,12.761983)">
<rect
ry="0.26458257"
rx="0.26458332"
y="-4.1619601"
x="41.233208"
height="7.9375019"
width="34.395828"
id="rect9134-4-7-4-7-5"
style="opacity:0.66000001;vector-effect:none;fill:#e7f3ff;fill-opacity:1;stroke:#000000;stroke-width:0.26458329;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill" />
<text
id="text9138-7-3-9-9-9"
y="0.68503231"
x="44.635841"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
y="0.68503231"
x="44.635841"
id="tspan1192"
sodipodi:role="line">WiFi.config (STA)</tspan></text>
</g>
<g
id="g1141">
<rect
ry="0.26458257"
rx="0.26458332"
y="-35.072762"
x="41.010418"
height="7.9375019"
width="34.395828"
id="rect9134-4-7-4-7-57"
style="opacity:0.66000001;vector-effect:none;fill:#e7f3ff;fill-opacity:1;stroke:#000000;stroke-width:0.26458329;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill" />
<text
id="text9138-7-3-9-9-90"
y="-30.225767"
x="42.740284"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
id="tspan1182"
sodipodi:role="line"
x="42.740284"
y="-30.225767">Load current config</tspan></text>
</g>
<path
style="fill:none;stroke:#000000;stroke-width:0.26458341px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208332,-27.002966 v 3.840593"
id="path9639-8-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26458341px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208332,-51.088322 v 3.840592"
id="path9639-8-5-3"
inkscape:connector-curvature="0" />
<g
id="g2166"
transform="translate(-30.682548,-13.096212)">
<rect
transform="matrix(0.94594599,0.32432418,-0.94594599,0.32432418,0,0)"
ry="3.6888673e-006"
rx="3.6888673e-006"
y="-62.503849"
x="31.466501"
height="18.355465"
width="18.355474"
id="rect9184-6-3-4-5"
style="opacity:0.66000001;vector-effect:none;fill:#e7f3ff;fill-opacity:1;stroke:#000000;stroke-width:0.33777279;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill" />
<text
id="text9188-6"
y="-2.9309402"
x="82.091293"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1em;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
y="-2.9309402"
x="82.091293"
id="tspan2161"
sodipodi:role="line">Static IP</tspan></text>
</g>
<path
style="fill:none;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 75.49653,153.66198 H 105.6468"
id="path10088-92-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26458338px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208337,4.6271392 v 3.840592"
id="path9639-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26458341px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 58.208337,0.78654773 V 4.6271395"
id="path9639-0-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26458341px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208332,-39.045645 v 3.840594"
id="path9639-8-5-6"
inkscape:connector-curvature="0" />
<g
id="g2200"
transform="translate(-37.753577,2.3026717)">
<rect
ry="0.26458257"
rx="0.26458332"
y="-9.5859175"
x="78.764"
height="7.9375019"
width="34.395828"
id="rect9134-4-7-4-7-57-3"
style="opacity:0.66000001;vector-effect:none;fill:#e7f3ff;fill-opacity:1;stroke:#000000;stroke-width:0.26458329;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill" />
<text
id="text9138-7-3-9-9-90-2"
y="-4.7389245"
x="79.303238"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
id="tspan2195"
sodipodi:role="line"
x="79.303238"
y="-4.7389245">Restore saved config</tspan></text>
</g>
<path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 40.84505,-17.209253 -10.258285,-0.0196 0.01789,22.0368617 h 27.461784"
id="path10088-9-7-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="35.828152"
y="-18.166817"
id="text10760-5-3"><tspan
sodipodi:role="line"
id="tspan10758-9-2"
x="35.828152"
y="-18.166817"
style="stroke-width:0.26458332">NO</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="60.096973"
y="-8.7963543"
id="text10760-57"><tspan
sodipodi:role="line"
id="tspan10758-6"
x="60.096973"
y="-8.7963543"
style="stroke-width:0.26458332">YES</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="79.585876"
y="-32.471371"
id="text9138-7-3-9-9-90-9"><tspan
sodipodi:role="line"
id="tspan1283"
x="79.585876"
y="-32.471371">Loads saved credentials from the flash</tspan><tspan
sodipodi:role="line"
id="tspan1285"
x="79.585876"
y="-28.502621">that matches the last SSID stored in</tspan><tspan
sodipodi:role="line"
id="tspan1287"
x="79.585876"
y="-24.533871">the ESP module. </tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:serif;-inkscape-font-specification:'serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="79.543159"
y="-14.876924"
id="text9138-7-3-9-9-90-9-7"><tspan
sodipodi:role="line"
id="tspan1289"
x="79.543159"
y="-14.876924">If that credential has a static IP,</tspan><tspan
sodipodi:role="line"
id="tspan1291"
x="79.543159"
y="-10.908174">restore it.</tspan></text>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

@ -362,8 +362,8 @@
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
<a href="#by-attaching-autoconnect-menu" title=" by attaching AutoConnect menu" class="md-nav__link"> <a href="#attaching-to-autoconnect-menu" title=" Attaching to AutoConnect menu" class="md-nav__link">
by attaching AutoConnect menu Attaching to AutoConnect menu
</a> </a>
</li> </li>
@ -886,8 +886,8 @@
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
<a href="#by-attaching-autoconnect-menu" title=" by attaching AutoConnect menu" class="md-nav__link"> <a href="#attaching-to-autoconnect-menu" title=" Attaching to AutoConnect menu" class="md-nav__link">
by attaching AutoConnect menu Attaching to AutoConnect menu
</a> </a>
</li> </li>
@ -916,11 +916,11 @@
<p>The AutoConnect menu is developed using the <a href="https://github.com/balzss/luxbar">LuxBar</a> which is licensed under the MIT License. See the <a href="license.html">License</a>.</p> <p>The AutoConnect menu is developed using the <a href="https://github.com/balzss/luxbar">LuxBar</a> which is licensed under the MIT License. See the <a href="license.html">License</a>.</p>
</div> </div>
<h2 id="where-the-from"><i class="fa fa-external-link"></i> Where the from<a class="headerlink" href="#where-the-from" title="Permanent link">&para;</a></h2> <h2 id="where-the-from"><i class="fa fa-external-link"></i> Where the from<a class="headerlink" href="#where-the-from" title="Permanent link">&para;</a></h2>
<p>The AutoConnect menu appears when you access the <strong>AutoConnect root path</strong>. It is assigned "<strong>/_ac</strong>" located on the <em>local IP address</em> of ESP8266/ESP32 module by default. This location can be changed in the sketch. The following screen will appear at access to <code>http://{localIP}/_ac</code> as the root path. This is the statistics of the current WiFi connection. You can access the menu from the here, to invoke it tap <i class="fa fa-bars"></i> at right on top. (e.g. <code>http://172.217.28.1/_ac</code> for SoftAP mode.)</p> <p>The following screen will appear as the AutoConnect menu when you access to <strong>AutoConnect root URL</strong> via <code>http://{localIP}/_ac</code>. (eg. <code>http://172.217.28.1/_ac</code>) It is a top page of AutoConnect which shows the current WiFi connection statistics. To invoke the AutoConnect menu, you can t tap <i class="fa fa-bars"></i> at right on top.</p>
<p><img src="images/ac.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" /></p> <p><img src="images/ac.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" /></p>
<div class="admonition note"> <div class="admonition note">
<p class="admonition-title">What's the local IP?</p> <p class="admonition-title">AutoConnect root URL</p>
<p>A local IP means Local IP at connection established or SoftAP's IP.</p> <p>It is assigned "<strong>/_ac</strong>" located on the <em>local IP address</em> of ESP8266/ESP32 module by default and can be changed with the sketch. A local IP means Local IP at connection established or SoftAP's IP.</p>
</div> </div>
<h2 id="right-on-top"><i class="fa fa-bars"></i> Right on top<a class="headerlink" href="#right-on-top" title="Permanent link">&para;</a></h2> <h2 id="right-on-top"><i class="fa fa-bars"></i> Right on top<a class="headerlink" href="#right-on-top" title="Permanent link">&para;</a></h2>
<p>Currently, AutoConnect supports four menus. Undermost menu as "HOME" returns to the home path of its sketch.</p> <p>Currently, AutoConnect supports four menus. Undermost menu as "HOME" returns to the home path of its sketch.</p>
@ -933,36 +933,52 @@
</ul> </ul>
<p><img src="images/menu.png" style="width:280px;" /></p> <p><img src="images/menu.png" style="width:280px;" /></p>
<h2 id="configure-new-ap"><i class="fa fa-bars"></i> Configure new AP<a class="headerlink" href="#configure-new-ap" title="Permanent link">&para;</a></h2> <h2 id="configure-new-ap"><i class="fa fa-bars"></i> Configure new AP<a class="headerlink" href="#configure-new-ap" title="Permanent link">&para;</a></h2>
<p>Scan all available access point in the vicinity and display it. Strength and security of the detected AP are marked. The <i class="fa fa-lock"></i> is indicated for the SSID that needs a security key. "<strong>Hidden:</strong>" means the number of hidden SSIDs discovered.<br /> <p>It scans all available access points in the vicinity and display it further the WiFi signal strength and security indicator as <i class="fa fa-lock"></i> of the detected AP. Below that, the number of discovered hidden APs will be displayed.
Enter SSID and Passphrase and tap "<strong>apply</strong>" to starts WiFi connection. </p> Enter SSID and Passphrase and tap "<strong>Apply</strong>" to start a WiFi connection. </p>
<p><img src="images/newap.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" /></p> <p><img src="images/newap.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" /></p>
<p>If you want to configure with static IP, uncheck "<strong>Enable DHCP</strong>". Once the WiFi connection is established, the entered static IP<sup id="fnref:1"><a class="footnote-ref" href="#fn:1" rel="footnote">1</a></sup> configuration will be stored to the credentials in the flash and restored to the station configuration via the <a href="#open-ssids">Open SSIDs</a> menu.</p>
<p><img src="images/newap_static.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" /></p>
<h2 id="open-ssids"><i class="fa fa-bars"></i> Open SSIDs<a class="headerlink" href="#open-ssids" title="Permanent link">&para;</a></h2> <h2 id="open-ssids"><i class="fa fa-bars"></i> Open SSIDs<a class="headerlink" href="#open-ssids" title="Permanent link">&para;</a></h2>
<p>Once it was established WiFi connection, its SSID and password will be saved in the flash of ESP8266/ESP32 automatically. The <strong>Open SSIDs</strong> menu reads the saved SSID credentials from the flash. The stored credential data are listed by the SSID as shown below. Its label is a clickable button. Tap the SSID button, starts WiFi connection it.</p> <p>After WiFi connected, AutoConnect will automatically save the established SSID and password to the flash on the ESP module. <strong>Open SSIDs</strong> menu reads the saved SSID credentials and lists them as below. Listed items are clickable buttons and can initiate a connection to its access point.</p>
<p><img src="images/open.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" /></p> <p><img src="images/open.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" /></p>
<div class="admonition note">
<p class="admonition-title">Saved credentials data structure has changed</p>
<p>A structure of AutoConnect saved credentials has changed in v1.1.0 and was lost backward compatibility. Credentials saved by AutoConnect v1.0.3 (or earlier) will not display properly with AutoConnect v1.1.0. You need to erase the flash of the ESP module using the esptool before the sketch uploading.
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span>esptool -c esp8266 (or esp32) - p [COM_PORT] erase_flash
</pre></div></p>
</div>
<h2 id="disconnect"><i class="fa fa-bars"></i> Disconnect<a class="headerlink" href="#disconnect" title="Permanent link">&para;</a></h2> <h2 id="disconnect"><i class="fa fa-bars"></i> Disconnect<a class="headerlink" href="#disconnect" title="Permanent link">&para;</a></h2>
<p>Disconnect ESP8266/ESP32 from the current connection. It can also reset the ESP8266/ESP32 automatically after disconnection by instructing with using <a href="api.html#autoreset">API</a> in the sketch.</p> <p>It disconnects ESP8266/ESP32 from the current connection. Also, ESP8266/ESP32 can be automatically reset after WiFi cutting by instructing with the sketch using the <a href="api.html#autoreset">AutoConnect API</a>.</p>
<p>After tapping "Disconnect", you will not be able to reach the AutoConnect menu. Once disconnected, you will need to set the SSID again for connecting the WLAN. </p> <p>After tapping the <strong>Disconnect</strong>, you will not be able to reach the AutoConnect menu. Once disconnected, you will need to set the SSID again for connecting to the WLAN. </p>
<h2 id="reset"><i class="fa fa-bars"></i> Reset...<a class="headerlink" href="#reset" title="Permanent link">&para;</a></h2> <h2 id="reset"><i class="fa fa-bars"></i> Reset...<a class="headerlink" href="#reset" title="Permanent link">&para;</a></h2>
<p>Reset the ESP8266/ESP32 module, it will start rebooting. After rebooting complete, the ESP8266/ESP32 module begins establishing the previous connection with WIFI_STA mode, and <em>esp8266ap</em> or <em>esp32ap</em> of an access point will disappear from WLAN.</p> <p>Resetting the ESP8266/ESP32 module will initiate a reboot. When the module restarting, the <em>esp8266ap</em> or <em>esp32ap</em> access point will disappear from the WLAN and the ESP8266/ESP32 module will begin to reconnect a previous access point with WIFI_STA mode.</p>
<p><img src="images/resetting.png" style="width:280px;" /></p> <p><img src="images/resetting.png" style="width:280px;" /></p>
<div class="admonition warning"> <div class="admonition warning">
<p class="admonition-title">Not every ESP8266 module will be rebooted normally</p> <p class="admonition-title">Not every ESP8266 module will be rebooted normally</p>
<p>The Reset menu is using the <strong>ESP.reset()</strong> function for ESP8266. This is an almost hardware reset. In order to resume the sketch normally, the <a href="https://github.com/esp8266/esp8266-wiki/wiki/Boot-Process#esp-boot-modes">state of GPIO0</a> is important. Since this depends on the circuit implementation for each module, not every module will be rebooted normally. See also <a href="faq.html#hang-up-after-reset">FAQ</a>.</p> <p>The Reset menu is using the <strong>ESP.reset()</strong> function for ESP8266. This is an almost hardware reset. In order to resume the sketch normally, the <a href="https://github.com/esp8266/esp8266-wiki/wiki/Boot-Process#esp-boot-modes">state of GPIO0</a> is important. Since this depends on the circuit implementation for each module, not every module will be rebooted normally. See also <a href="faq.html#hang-up-after-reset">FAQ</a>.</p>
</div> </div>
<h2 id="custom-menu-items"><i class="fa fa-bars"></i> Custom menu items<a class="headerlink" href="#custom-menu-items" title="Permanent link">&para;</a></h2> <h2 id="custom-menu-items"><i class="fa fa-bars"></i> Custom menu items<a class="headerlink" href="#custom-menu-items" title="Permanent link">&para;</a></h2>
<p>The menu items of the custom Web page line up at the below in the AutoConnect menu if the custom Web pages are joined. Details for <a href="acintro.html#custom-web-pages-in-autoconnectmenu">Custom Web pages in AutoConnect menu</a>.</p> <p>If the sketch has custom Web pages, the AutoConnect menu lines them up with the AutoConnect's items. Details for <a href="acintro.html#custom-web-pages-in-autoconnectmenu">Custom Web pages in AutoConnect menu</a>.</p>
<h2 id="home"><i class="fa fa-bars"></i> HOME<a class="headerlink" href="#home" title="Permanent link">&para;</a></h2> <h2 id="home"><i class="fa fa-bars"></i> HOME<a class="headerlink" href="#home" title="Permanent link">&para;</a></h2>
<p>A <strong>HOME</strong> item located at the bottom of the menu list is a link to the home path. The URI as the home path is <code>/</code> by default, and it is defined by <code>AUTOCONNECT_HOMEURI</code> with <strong>AutoConnectDefs.h</strong> file.</p> <p>A <strong>HOME</strong> item at the bottom of the menu list is a link to the home path, and the default URI is <code>/</code> which is defined by <code>AUTOCONNECT_HOMEURI</code> in <strong>AutoConnectDefs.h</strong> header file.</p>
<div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #75715e">#define AUTOCONNECT_HOMEURI &quot;/&quot;</span> <div class="codehilite" style="background: #272822"><pre style="line-height: 125%"><span></span><span style="color: #75715e">#define AUTOCONNECT_HOMEURI &quot;/&quot;</span>
</pre></div> </pre></div>
<p>You can change the HOME path using the AutoConnect API. The <a href="api.html#home"><strong>AutoConnect::home</strong></a> function sets the URI as a link of the HOME item of the AutoConnect menu.</p> <p>Also, you can change the HOME path using the AutoConnect API. The <a href="api.html#home"><strong>AutoConnect::home</strong></a> function sets the URI as a link of the HOME item in the AutoConnect menu.</p>
<h2 id="by-attaching-autoconnect-menu"><i class="fa fa-bars"></i> by attaching AutoConnect menu<a class="headerlink" href="#by-attaching-autoconnect-menu" title="Permanent link">&para;</a></h2> <h2 id="attaching-to-autoconnect-menu"><i class="fa fa-bars"></i> Attaching to AutoConnect menu<a class="headerlink" href="#attaching-to-autoconnect-menu" title="Permanent link">&para;</a></h2>
<p>The AutoConnect menu can contain HTML pages of your owns sketch as custom items. It works for HTML pages implemented by <strong>ESP8266WebServer::on</strong> handler or <strong>WebServer::on</strong> handler for ESP32. That is, you can make it as menu items to invoke the legacy web page. The below screenshot is the result of adding an example sketch for the ESP8266WebServer library known as <a href="https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer/examples/FSBrowser">FSBrowser</a> to the AutoConnect menu item. It adds Edit and List items with little modification to the legacy sketch code.</p> <p>The AutoConnect menu can contain your sketch's web pages as extra items as a custom. It works for HTML pages implemented by the <strong>ESP8266WebServer::on</strong> handler or the <strong>WebServer::on</strong> handler for ESP32. That is, you can make them invoke the legacy web pages from the AutoConnect menu. The below screen-shot is the result of adding an example sketch for the ESP8266WebServer library known as <a href="https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer/examples/FSBrowser">FSBrowser</a> to the AutoConnect menu item. It can add Edit and List items with little modification to the legacy sketch code.</p>
<div style="float:left;width:auto;height:420px;"><img style="width:auto;height:420px;" src="images/fsbmenu.png"></div> <div style="float:left;width:auto;height:420px;"><img style="width:auto;height:420px;" src="images/fsbmenu.png"></div>
<p><img style="margin-left:70px;width:auto;height:420px;" src="images/fsbmenu_expand.png"></p> <p><img style="margin-left:70px;width:auto;height:420px;" src="images/fsbmenu_expand.png"></p>
<p>You can extend the AutoConnect menu to improve the original sketches and according to the procedure described in section <a href="advancedusage.html#casts-the-html-pages-to-be-add-on-into-the-menu"><em>Advanced Usage</em></a>.</p> <p>You can improve your sketches by extending the AutoConnect menu by adding the legacy web pages according to the procedure described in section <a href="advancedusage.html#casts-the-html-pages-to-be-add-on-into-the-menu"><em>Advanced Usage</em></a>.</p>
<div class="footnote">
<hr />
<ol>
<li id="fn:1">
<p>AutoConnect does not check the syntax and validity of the entered IP address. If the entered static IPs are incorrect, it cannot connect to the access point.&#160;<a class="footnote-backref" href="#fnref:1" rev="footnote" title="Jump back to footnote 1 in the text">&#8617;</a></p>
</li>
</ol>
</div>

File diff suppressed because one or more lines are too long

@ -2,147 +2,147 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/index.html</loc> <loc>https://Hieromon.github.io/AutoConnect/index.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/gettingstarted.html</loc> <loc>https://Hieromon.github.io/AutoConnect/gettingstarted.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/menu.html</loc> <loc>https://Hieromon.github.io/AutoConnect/menu.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/basicusage.html</loc> <loc>https://Hieromon.github.io/AutoConnect/basicusage.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/advancedusage.html</loc> <loc>https://Hieromon.github.io/AutoConnect/advancedusage.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/acintro.html</loc> <loc>https://Hieromon.github.io/AutoConnect/acintro.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/acelements.html</loc> <loc>https://Hieromon.github.io/AutoConnect/acelements.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/acjson.html</loc> <loc>https://Hieromon.github.io/AutoConnect/acjson.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/achandling.html</loc> <loc>https://Hieromon.github.io/AutoConnect/achandling.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/otaupdate.html</loc> <loc>https://Hieromon.github.io/AutoConnect/otaupdate.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/otabrowser.html</loc> <loc>https://Hieromon.github.io/AutoConnect/otabrowser.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/otaserver.html</loc> <loc>https://Hieromon.github.io/AutoConnect/otaserver.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/api.html</loc> <loc>https://Hieromon.github.io/AutoConnect/api.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/apiaux.html</loc> <loc>https://Hieromon.github.io/AutoConnect/apiaux.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/apiconfig.html</loc> <loc>https://Hieromon.github.io/AutoConnect/apiconfig.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/apielements.html</loc> <loc>https://Hieromon.github.io/AutoConnect/apielements.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/apiupdate.html</loc> <loc>https://Hieromon.github.io/AutoConnect/apiupdate.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/apiextra.html</loc> <loc>https://Hieromon.github.io/AutoConnect/apiextra.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/howtoembed.html</loc> <loc>https://Hieromon.github.io/AutoConnect/howtoembed.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/datatips.html</loc> <loc>https://Hieromon.github.io/AutoConnect/datatips.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/menuize.html</loc> <loc>https://Hieromon.github.io/AutoConnect/menuize.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/wojson.html</loc> <loc>https://Hieromon.github.io/AutoConnect/wojson.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/lsbegin.html</loc> <loc>https://Hieromon.github.io/AutoConnect/lsbegin.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/credit.html</loc> <loc>https://Hieromon.github.io/AutoConnect/credit.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/acupload.html</loc> <loc>https://Hieromon.github.io/AutoConnect/acupload.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/colorized.html</loc> <loc>https://Hieromon.github.io/AutoConnect/colorized.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/faq.html</loc> <loc>https://Hieromon.github.io/AutoConnect/faq.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/changelog.html</loc> <loc>https://Hieromon.github.io/AutoConnect/changelog.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://Hieromon.github.io/AutoConnect/license.html</loc> <loc>https://Hieromon.github.io/AutoConnect/license.html</loc>
<lastmod>2019-09-30</lastmod> <lastmod>2019-10-16</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
</urlset> </urlset>

Binary file not shown.

@ -63,28 +63,28 @@ static const char AUX_CONFIGIP[] PROGMEM = R"(
"name": "staip", "name": "staip",
"type": "ACInput", "type": "ACInput",
"label": "IP", "label": "IP",
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", "pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
"global": true "global": true
}, },
{ {
"name": "gateway", "name": "gateway",
"type": "ACInput", "type": "ACInput",
"label": "Gateway", "label": "Gateway",
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", "pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
"global": true "global": true
}, },
{ {
"name": "netmask", "name": "netmask",
"type": "ACInput", "type": "ACInput",
"label": "Netmask", "label": "Netmask",
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", "pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
"global": true "global": true
}, },
{ {
"name": "dns1", "name": "dns1",
"type": "ACInput", "type": "ACInput",
"label": "DNS", "label": "DNS",
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", "pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
"global": true "global": true
}, },
{ {

@ -103,7 +103,7 @@ PageBuilder delPage("/del", { elmDel });
// with the <li> tag. // with the <li> tag.
String viewCredential(PageArgument& args) { String viewCredential(PageArgument& args) {
AutoConnectCredential ac(CREDENTIAL_OFFSET); AutoConnectCredential ac(CREDENTIAL_OFFSET);
struct station_config entry; station_config_t entry;
String content = ""; String content = "";
uint8_t count = ac.entries(); // Get number of entries. uint8_t count = ac.entries(); // Get number of entries.
@ -125,7 +125,7 @@ String delCredential(PageArgument& args) {
int8_t e = args.arg("num").toInt(); int8_t e = args.arg("num").toInt();
Serial.printf("Request deletion #%d\n", e); Serial.printf("Request deletion #%d\n", e);
if (e > 0) { if (e > 0) {
struct station_config entry; station_config_t entry;
// If the input number is valid, delete that entry. // If the input number is valid, delete that entry.
int8_t de = ac.load(e - 1, &entry); // A base of entry num is 0. int8_t de = ac.load(e - 1, &entry); // A base of entry num is 0.

@ -75,7 +75,7 @@ void convert(const uint8_t* eeprom, const size_t size) {
break; break;
// Obtain each entry and store to Preferences // Obtain each entry and store to Preferences
struct station_config config; station_config_t config;
Serial.printf("[%d] ", ec); Serial.printf("[%d] ", ec);
uint8_t ei = 0; uint8_t ei = 0;
do { do {
@ -91,6 +91,17 @@ void convert(const uint8_t* eeprom, const size_t size) {
config.bssid[ei] = *dp++; config.bssid[ei] = *dp++;
Serial.printf(":%02x", config.bssid[ei]); Serial.printf(":%02x", config.bssid[ei]);
} }
config.dhcp = *dp++;
if (config.dhcp == STA_STATIC) {
for (uint8_t e = 0; e < sizeof(station_config_t::_config::addr) / sizeof(uint32_t); e++) {
uint32_t* ip = &config.config.addr[e];
*ip = 0;
for (uint8_t b = 0; b < sizeof(uint32_t); b++) {
*ip <<= 8;
*ip += *dp++;
}
}
}
bool rc = credential.save(&config); bool rc = credential.save(&config);
Serial.println(rc ? " transferred" : " failed to save Preferences"); Serial.println(rc ? " transferred" : " failed to save Preferences");
} }

@ -25,6 +25,6 @@
"espressif8266", "espressif8266",
"espressif32" "espressif32"
], ],
"version": "1.0.3", "version": "1.1.0",
"license": "MIT" "license": "MIT"
} }

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

@ -190,7 +190,7 @@ void loop() {
If your sketch handles web pages, you can embed the pages into the AutoConnect menu in continuance enjoying the utility of the WiFi connection feature. Unlike the custom Web pages by [AutoConnectElements](acelements.md), this allows to legacy web pages registered by *ESP8266WebServer::on* or *WebServer::on* function. If your sketch handles web pages, you can embed the pages into the AutoConnect menu in continuance enjoying the utility of the WiFi connection feature. Unlike the custom Web pages by [AutoConnectElements](acelements.md), this allows to legacy web pages registered by *ESP8266WebServer::on* or *WebServer::on* function.
You can use AutoConnectAux only constructed with the URI of the page to be embedding. AutoConnectElements is not required. The basic procedure for this as follows: To implement embedding your legacy web pages to the AutoConnect menu, you can use AutoConnectAux only constructed with the URI of the page to be embedding. AutoConnectElements is not required. The basic procedure for this as follows:
1. Declare AutoConnectAux for each legacy page. It includes the URI of the page and item string which will display in the AutoConnect menu. 1. Declare AutoConnectAux for each legacy page. It includes the URI of the page and item string which will display in the AutoConnect menu.
2. Sketch the legacy page handlers. 2. Sketch the legacy page handlers.

@ -1,3 +1,7 @@
#### [1.1.0] Oct. 15, 2019
- Supports static IPs with the [**Configure new AP**](menu.md#configure-new-ap) menu.
- Fixed compilation error that no member named 'printTo' with ArduinoJson 5.
#### [1.0.3] Sept. 30, 2019 #### [1.0.3] Sept. 30, 2019
- Fixed a return of AutoConnectCredential::entries(). - Fixed a return of AutoConnectCredential::entries().

@ -79,43 +79,43 @@ Returns number of entries as contained credentials.
#### <i class="fa fa-caret-right"></i> load #### <i class="fa fa-caret-right"></i> load
```cpp ```cpp
int8_t load(const char* ssid, struct station_config* config) int8_t load(const char* ssid, station_config_t* config)
``` ```
Load a credential entry and store to **config**. Load a credential entry and store to **config**.
<dl class="apidl"> <dl class="apidl">
<dt>**Parameters**</dt> <dt>**Parameters**</dt>
<dd><span class="apidef">ssid</span><span class="apidesc">SSID to be loaded.</span></dd> <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> <dd><span class="apidef">config</span><span class="apidesc">station_config_t</span></dd>
<dt>**Return value**</dt> <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> <dd>Save the specified SSID's credential entry to station_config_t pointed to by the parameter as **config**. -1 is returned if the SSID is not saved. </dd>
</dl> </dl>
#### <i class="fa fa-caret-right"></i> load #### <i class="fa fa-caret-right"></i> load
```cpp ```cpp
bool load(int8_t entry, struct station_config* config) bool load(int8_t entry, station_config_t* config)
``` ```
Load a credential entry and store to **config**. Load a credential entry and store to **config**.
<dl class="apidl"> <dl class="apidl">
<dt>**Parameters**</dt> <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">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> <dd><span class="apidef">config</span><span class="apidesc">station_config_t</span></dd>
<dt>**Return value**</dt> <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> <dd>Save the specified credential entry to station_config_t pointed to by the parameter as **config**. -1 is returned if specified number is not saved. </dd>
</dl> </dl>
#### <i class="fa fa-caret-right"></i> save #### <i class="fa fa-caret-right"></i> save
```cpp ```cpp
bool save(const struct station_config* config) bool save(const station_config_t* config)
``` ```
Save a credential entry. Save a credential entry.
<dl class="apidl"> <dl class="apidl">
<dt>**Parameter**</dt> <dt>**Parameter**</dt>
<dd><span class="apidef">config</span><span class="apidesc">station_config to be saved.</span></dd> <dd><span class="apidef">config</span><span class="apidesc">station_config_t to be saved.</span></dd>
<dt>**Return value**</dt> <dt>**Return value**</dt>
<dd><span class="apidef">true</span><span class="apidesc">Successfully saved.</span></dd> <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> <dd><span class="apidef">false</span><span class="apidesc">Failed to save.</span></dd>
@ -142,7 +142,7 @@ Delete a credential the specified SSID.
```cpp ```cpp
void deleteAllCredentials(void) { void deleteAllCredentials(void) {
AutoConnectCredential credential; AutoConnectCredential credential;
struct station_config config; station_config_t config;
uint8_t ent = credential.entries(); uint8_t ent = credential.entries();
while (ent--) { while (ent--) {
@ -154,24 +154,31 @@ Delete a credential the specified SSID.
## The data structures ## The data structures
### <i class="fa fa-code"></i> station_config ### <i class="fa fa-code"></i> station_config_t
A structure is included in the ESP8266 SDK. You can use it in the sketch like as follows: The saved credential structure is defined as stato_config_t in the AcutoConnectCredential header file.
```cpp ```cpp
extern "C" { typedef struct {
#include <user_interface.h> uint8_t ssid[32];
} uint8_t password[64];
uint8_t bssid[6];
uint8_t dhcp; /**< 0:DHCP, 1:Static IP */
union _config {
uint32_t addr[5];
struct _sta {
uint32_t ip;
uint32_t gateway;
uint32_t netmask;
uint32_t dns1;
uint32_t dns2;
} sta;
} config;
} station_config_t;
``` ```
```cpp !!! note "The byte size of station_config_t in program memory and stored credentials is different"
struct station_config { There is a gap byte for boundary alignment between the `dhcp` member and the static IP members of the above station_config_t. Its gap byte will be removed with saved credentials on the flash.
uint8 ssid[32];
uint8 password[64];
uint8 bssid_set;
uint8 bssid[6];
};
```
### <i class="fa fa-code"></i> The credential entry ### <i class="fa fa-code"></i> The credential entry
@ -180,13 +187,26 @@ A data structure of the credential saving area in EEPROM as the below. [^4]
[^4]: [^4]:
There may be 0xff as an invalid data in the credential saving area. The 0xff area would be reused. There may be 0xff as an invalid data in the credential saving area. The 0xff area would be reused.
| Byte offset | Length | Value | | byte offset | Length | Value |
|-------------|----------|---------------------------------------------------------------------| |------------- |--------|-------|
| 0 | 8 | AC_CREDT | | 0 | 8 | AC_CREDT |
| 8 | 1 | Number of contained entries (uint8_t) | | 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). | | 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. | | 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 | variable | Password plain text terminated by 0x00. Max length is 64 bytes. |
| variable | 6 | BSSID | | variable | 6 | BSSID |
| variable | | Contained the next entries. (Continuation SSID+Password+BSSID) | | variable | 1 | Flag for DHCP or Static IP (0:DHCP, 1:Static IP) |
| <td colspan=3>The following IP address entries are stored only for static IPs.
| variable(1) | 4 | Station IP address (uint32_t) |
| variable(5) | 4 | Gateway address (uint32_t) |
| variable(9) | 4 | Netmask (uint32_t) |
| variable(13) | 4 | Primary DNS address (uint32_t) |
| variable(17) | 4 | Secondary IP address (uint32_t) |
| variable | variable | Contained the next entries. (Continuation SSID+Password+BSSID+DHCP flag+Static IPs(if exists)) |
| variable | 1 | 0x00. End of container. | | variable | 1 | 0x00. End of container. |
!!! note "AutoConnectCredential has changed"
It was lost AutoConnectCredential backward compatibility. Credentials saved by AutoConnect v1.0.3 (or earlier) will not work properly with AutoConnect v1.1.0. You need to erase the flash of the ESP module using the esptool before the sketch uploading.
```
esptool -c esp8266 (or esp32) - p [COM_PORT] erase_flash
```

@ -180,6 +180,29 @@ Because AutoConnect does not send a login success response to the captive portal
If the sketch is correct, a JSON syntax error may have occurred. In this case, activate the [AC_DEBUG](faq.md#3-turn-on-the-debug-log-options) and rerun. If you take the message of JSON syntax error, the [Json Assistant](https://arduinojson.org/v5/assistant/) helps syntax checking. This online tool is provided by the author of ArduinoJson and is most consistent for the AutoConnect. If the sketch is correct, a JSON syntax error may have occurred. In this case, activate the [AC_DEBUG](faq.md#3-turn-on-the-debug-log-options) and rerun. If you take the message of JSON syntax error, the [Json Assistant](https://arduinojson.org/v5/assistant/) helps syntax checking. This online tool is provided by the author of ArduinoJson and is most consistent for the AutoConnect.
## <i class="fa fa-question-circle"></i> Saved credentials are wrong or lost.
A structure of AutoConnect saved credentials has changed two times throughout enhancement with v1.0.3 and v1.1.0. In particular, due to enhancements in v1.1.0, AutoConnectCredential data structure has lost the backward compatibility with previous versions. You must erase the flash of the ESP module using the esptool completely to save the credentials correctly with v1.1.0.
```
esptool -c esp8266 (or esp32) -p [COM_PORT] erase_flash
```
## <i class="fa fa-question-circle"></i> Some AutoConnect page is cut off.
It may be two possibilities as follows:
1. Packet loss during transmission due to a too weak WiFi signal.
2. Heap is insufficient memory. AutoConnect entrusts HTML generation to PageBuilder that makes heavy use the String::concatenate function and causes memory fragmentation. This is a structural problem with PageBuilder, but it is difficult to solve immediately.
If this issue produces with your sketch, Reloading the page may recover.
Also, you can check the memory running out status by rebuilding the sketch with [PageBuilder's debug log option](faq.md#fn:2) turned on.
If the heap memory is insufficient, the following message is displayed on the serial console.
```
[PB] Failed building, free heap:<Size of free heap>
```
## <i class="fa fa-question-circle"></i> Submit element in a custom Web page does not react. ## <i class="fa fa-question-circle"></i> Submit element in a custom Web page does not react.
Is there the AutoConnectElements element named **SUBMIT** in the custom Web page? (case sensitive ignored) AutoConnect does not rely on the `input type=submit` element for the form submission and uses [HTML form element submit](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit) function instead. So, the submit function will fail if there is an element named 'submit' in the form. You can not use **SUBMIT** as the element name of AutoConnectElements in a custom Web page that declares the AutoConnectSubmit element. Is there the AutoConnectElements element named **SUBMIT** in the custom Web page? (case sensitive ignored) AutoConnect does not rely on the `input type=submit` element for the form submission and uses [HTML form element submit](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit) function instead. So, the submit function will fail if there is an element named 'submit' in the form. You can not use **SUBMIT** as the element name of AutoConnectElements in a custom Web page that declares the AutoConnectSubmit element.

@ -50,6 +50,9 @@ Here, tap *"Configure new AP"* to connect the new access point then the SSID con
<img src="images/menu_login.png" style="border:1px solid lightgrey;width:280px;" /><img src="images/arrow_right.svg" style="vertical-align:top;padding-top:120px;width:48px;margin-left:30px;margin-right:30px;" /><img src="images/config_ssid.png" style="border:1px solid lightgrey;width:280px;" /> <img src="images/menu_login.png" style="border:1px solid lightgrey;width:280px;" /><img src="images/arrow_right.svg" style="vertical-align:top;padding-top:120px;width:48px;margin-left:30px;margin-right:30px;" /><img src="images/config_ssid.png" style="border:1px solid lightgrey;width:280px;" />
!!! info "Can be configured with static IP"
Since v1.1.0, [**Configure new AP**](menu.md#configure-new-ap) menu can configure for WIFI_STA with static IP.
### <i class="fa fa-rss"></i> Connection establishment ### <i class="fa fa-rss"></i> Connection establishment
After connection established, the current status screen will appear. It is already connected to WLAN with WiFi mode as WIFI\_AP\_STA and the IP connection status is displayed there including the SSID. Then at this screen, you have two options for the next step. After connection established, the current status screen will appear. It is already connected to WLAN with WiFi mode as WIFI\_AP\_STA and the IP connection status is displayed there including the SSID. Then at this screen, you have two options for the next step.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

@ -9,9 +9,9 @@
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="99.56517mm" width="109mm"
height="304.07242mm" height="371.83472mm"
viewBox="0 0 99.56517 304.07241" viewBox="0 0 108.99999 371.83472"
version="1.1" version="1.1"
id="svg8776" id="svg8776"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)" inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
@ -224,6 +224,21 @@
style="stroke-width:2" style="stroke-width:2"
id="path2786" /> id="path2786" />
</symbol> </symbol>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0"
refX="0"
id="marker10923-1"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path10921-8"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(0.6)"
inkscape:connector-curvature="0" />
</marker>
</defs> </defs>
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
@ -233,12 +248,12 @@
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1.4142136" inkscape:zoom="1.4142136"
inkscape:cx="192.80115" inkscape:cx="259.43725"
inkscape:cy="364.94967" inkscape:cy="1200.0696"
inkscape:document-units="mm" inkscape:document-units="mm"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:snap-global="false" inkscape:snap-global="true"
inkscape:snap-bbox="true" inkscape:snap-bbox="true"
inkscape:snap-nodes="true" inkscape:snap-nodes="true"
inkscape:snap-others="true" inkscape:snap-others="true"
@ -249,11 +264,11 @@
inkscape:bbox-nodes="true" inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true" inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true" inkscape:snap-bbox-midpoints="true"
inkscape:window-width="1920" inkscape:window-width="1571"
inkscape:window-height="1029" inkscape:window-height="1013"
inkscape:window-x="1272" inkscape:window-x="1376"
inkscape:window-y="-8" inkscape:window-y="0"
inkscape:window-maximized="1" inkscape:window-maximized="0"
fit-margin-top="0" fit-margin-top="0"
fit-margin-left="0" fit-margin-left="0"
fit-margin-right="0" fit-margin-right="0"
@ -261,8 +276,8 @@
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid9104" id="grid9104"
originx="-23.598368" originx="-23.664512"
originy="15.544285" /> originy="15.544259" />
</sodipodi:namedview> </sodipodi:namedview>
<metadata <metadata
id="metadata8773"> id="metadata8773">
@ -280,7 +295,17 @@
inkscape:label="レイヤー 1" inkscape:label="レイヤー 1"
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="translate(-23.598368,-8.4718652)"> transform="translate(-23.664512,59.290411)">
<path
style="fill:none;stroke:#000000;stroke-width:0.26458341px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208337,-11.256129 v 3.8405916"
id="path9639-8-5-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208337,16.669816 v 3.840593"
id="path9639"
inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208334,32.416659 v 4.08568" d="m 58.208334,32.416659 v 4.08568"
@ -464,7 +489,7 @@
</g> </g>
<g <g
id="g9633" id="g9633"
transform="translate(-33.072919,2.6458338)"> transform="translate(-33.734378,-65.116439)">
<rect <rect
ry="0.26458257" ry="0.26458257"
rx="0.26458332" rx="0.26458332"
@ -486,11 +511,6 @@
id="tspan9136" id="tspan9136"
sodipodi:role="line">STA</tspan></text> sodipodi:role="line">STA</tspan></text>
</g> </g>
<path
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208334,16.669815 v 3.840593"
id="path9639"
inkscape:connector-curvature="0" />
<g <g
id="g9714" id="g9714"
transform="translate(-78.07551,36.012307)"> transform="translate(-78.07551,36.012307)">
@ -781,13 +801,13 @@
</g> </g>
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 105.83333,175.75504 V 297.54958 H 92.604167" d="M 105.83318,175.75505 V 297.53597 H 92.575102"
id="path9639-1-3-9" id="path9639-1-3-9"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" /> sodipodi:nodetypes="ccc" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:0.26458329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 75.563113,86.193127 30.107867,-0.06083 0.0306,81.420513" d="m 75.513505,86.193127 30.107915,-0.06083 0.0306,81.420513"
id="path10088" id="path10088"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" /> sodipodi:nodetypes="ccc" />
@ -838,13 +858,13 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:0.26458329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 40.845696,26.589892 23.730739,26.467079 23.812499,163.71219 H 58.208331" d="M 40.91184,26.461738 23.796883,26.338925 23.878643,163.58402 H 58.274475"
id="path10088-9" id="path10088-9"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /> sodipodi:nodetypes="cccc" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10923)" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10923)"
d="m 24.291915,102.06832 h 16.45392" d="m 24.374806,102.06831 h 16.52812"
id="path10088-92" id="path10088-92"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" /> sodipodi:nodetypes="cc" />
@ -870,7 +890,7 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart)" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart)"
d="m 57.679167,215.1778 -33.866667,0.13255 0.0073,40.48128 h 16.92604" d="m 57.676398,215.1778 -33.837442,0.13255 0.0074,40.48128 H 40.75779"
id="path10088-92-6" id="path10088-92-6"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /> sodipodi:nodetypes="cccc" />
@ -891,7 +911,7 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10931)" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10931)"
d="m 58.7375,265.97716 33.866674,-0.13255 -0.0073,-40.48128 H 75.670833" d="m 58.570889,265.97716 33.866674,-0.13255 -0.0073,-40.48128 H 75.504222"
id="path10088-92-6-8" id="path10088-92-6-8"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /> sodipodi:nodetypes="cccc" />
@ -912,7 +932,7 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10937)" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker10937)"
d="m 58.7375,297.59504 33.734352,-0.0718 -0.007,-21.90474 H 75.538509" d="m 58.708562,297.61156 33.734352,-0.0718 -0.007,-21.90474 H 75.509571"
id="path10088-92-6-8-3" id="path10088-92-6-8-3"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /> sodipodi:nodetypes="cccc" />
@ -982,12 +1002,6 @@
x="60.844864" x="60.844864"
y="110.3716" y="110.3716"
style="stroke-width:0.26458332">YES</tspan></text> style="stroke-width:0.26458332">YES</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 75.257782,153.66218 30.310608,0.13228"
id="path10088-92-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
@ -1165,7 +1179,7 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 41.085466,42.413935 -10.12458,-0.0196 0.01766,22.036862 h 27.103849" d="m 41.054322,42.447007 -10.258285,-0.0196 0.01789,22.036862 H 58.27571"
id="path10088-9-7" id="path10088-9-7"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /> sodipodi:nodetypes="cccc" />
@ -1201,5 +1215,214 @@
x="60.844868" x="60.844868"
y="50.651817" y="50.651817"
style="stroke-width:0.26458332">Specified</tspan></text> style="stroke-width:0.26458332">Specified</tspan></text>
<g
id="g1109"
transform="translate(-37.739185,-61.587591)">
<g
id="g2292">
<rect
style="opacity:0.66000001;vector-effect:none;fill:#e7f3ff;fill-opacity:1;stroke:#000000;stroke-width:0.26458329;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
id="rect9134-4-7-4-7"
width="34.395828"
height="7.9375019"
x="78.749603"
y="14.472153"
rx="0.26458332"
ry="0.26458257" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="84.833466"
y="19.319145"
id="text9138-7-3-9-9"><tspan
y="19.319145"
x="84.833466"
sodipodi:role="line"
id="tspan1104">Set hostname</tspan></text>
</g>
</g>
<g
id="g1197"
transform="translate(-0.22278483,12.761983)">
<rect
ry="0.26458257"
rx="0.26458332"
y="-4.1619601"
x="41.233208"
height="7.9375019"
width="34.395828"
id="rect9134-4-7-4-7-5"
style="opacity:0.66000001;vector-effect:none;fill:#e7f3ff;fill-opacity:1;stroke:#000000;stroke-width:0.26458329;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill" />
<text
id="text9138-7-3-9-9-9"
y="0.68503231"
x="44.635841"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
y="0.68503231"
x="44.635841"
id="tspan1192"
sodipodi:role="line">WiFi.config (STA)</tspan></text>
</g>
<g
id="g1141">
<rect
ry="0.26458257"
rx="0.26458332"
y="-35.072762"
x="41.010418"
height="7.9375019"
width="34.395828"
id="rect9134-4-7-4-7-57"
style="opacity:0.66000001;vector-effect:none;fill:#e7f3ff;fill-opacity:1;stroke:#000000;stroke-width:0.26458329;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill" />
<text
id="text9138-7-3-9-9-90"
y="-30.225767"
x="42.740284"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
id="tspan1182"
sodipodi:role="line"
x="42.740284"
y="-30.225767">Load current config</tspan></text>
</g>
<path
style="fill:none;stroke:#000000;stroke-width:0.26458341px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208332,-27.002966 v 3.840593"
id="path9639-8-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26458341px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208332,-51.088322 v 3.840592"
id="path9639-8-5-3"
inkscape:connector-curvature="0" />
<g
id="g2166"
transform="translate(-30.682548,-13.096212)">
<rect
transform="matrix(0.94594599,0.32432418,-0.94594599,0.32432418,0,0)"
ry="3.6888673e-006"
rx="3.6888673e-006"
y="-62.503849"
x="31.466501"
height="18.355465"
width="18.355474"
id="rect9184-6-3-4-5"
style="opacity:0.66000001;vector-effect:none;fill:#e7f3ff;fill-opacity:1;stroke:#000000;stroke-width:0.33777279;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill" />
<text
id="text9188-6"
y="-2.9309402"
x="82.091293"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1em;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
y="-2.9309402"
x="82.091293"
id="tspan2161"
sodipodi:role="line">Static IP</tspan></text>
</g>
<path
style="fill:none;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 75.49653,153.66198 H 105.6468"
id="path10088-92-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26458338px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208337,4.6271392 v 3.840592"
id="path9639-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26458341px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 58.208337,0.78654773 V 4.6271395"
id="path9639-0-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26458341px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 58.208332,-39.045645 v 3.840594"
id="path9639-8-5-6"
inkscape:connector-curvature="0" />
<g
id="g2200"
transform="translate(-37.753577,2.3026717)">
<rect
ry="0.26458257"
rx="0.26458332"
y="-9.5859175"
x="78.764"
height="7.9375019"
width="34.395828"
id="rect9134-4-7-4-7-57-3"
style="opacity:0.66000001;vector-effect:none;fill:#e7f3ff;fill-opacity:1;stroke:#000000;stroke-width:0.26458329;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill" />
<text
id="text9138-7-3-9-9-90-2"
y="-4.7389245"
x="79.303238"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
id="tspan2195"
sodipodi:role="line"
x="79.303238"
y="-4.7389245">Restore saved config</tspan></text>
</g>
<path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 40.84505,-17.209253 -10.258285,-0.0196 0.01789,22.0368617 h 27.461784"
id="path10088-9-7-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="35.828152"
y="-18.166817"
id="text10760-5-3"><tspan
sodipodi:role="line"
id="tspan10758-9-2"
x="35.828152"
y="-18.166817"
style="stroke-width:0.26458332">NO</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="60.096973"
y="-8.7963543"
id="text10760-57"><tspan
sodipodi:role="line"
id="tspan10758-6"
x="60.096973"
y="-8.7963543"
style="stroke-width:0.26458332">YES</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="79.585876"
y="-32.471371"
id="text9138-7-3-9-9-90-9"><tspan
sodipodi:role="line"
id="tspan1283"
x="79.585876"
y="-32.471371">Loads saved credentials from the flash</tspan><tspan
sodipodi:role="line"
id="tspan1285"
x="79.585876"
y="-28.502621">that matches the last SSID stored in</tspan><tspan
sodipodi:role="line"
id="tspan1287"
x="79.585876"
y="-24.533871">the ESP module. </tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;line-height:1.25;font-family:serif;-inkscape-font-specification:'serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="79.543159"
y="-14.876924"
id="text9138-7-3-9-9-90-9-7"><tspan
sodipodi:role="line"
id="tspan1289"
x="79.543159"
y="-14.876924">If that credential has a static IP,</tspan><tspan
sodipodi:role="line"
id="tspan1291"
x="79.543159"
y="-10.908174">restore it.</tspan></text>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

@ -3,12 +3,12 @@
## <i class="fa fa-external-link"></i> Where the from ## <i class="fa fa-external-link"></i> Where the from
The AutoConnect menu appears when you access the **AutoConnect root path**. It is assigned "**/_ac**" located on the *local IP address* of ESP8266/ESP32 module by default. This location can be changed in the sketch. The following screen will appear at access to `http://{localIP}/_ac` as the root path. This is the statistics of the current WiFi connection. You can access the menu from the here, to invoke it tap <i class="fa fa-bars"></i> at right on top. (e.g. `http://172.217.28.1/_ac` for SoftAP mode.) The following screen will appear as the AutoConnect menu when you access to **AutoConnect root URL** via `http://{localIP}/_ac`. (eg. `http://172.217.28.1/_ac`) It is a top page of AutoConnect which shows the current WiFi connection statistics. To invoke the AutoConnect menu, you can t tap <i class="fa fa-bars"></i> at right on top.
<img src="images/ac.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" /> <img src="images/ac.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" />
!!! note "What's the local IP?" !!! note "AutoConnect root URL"
A local IP means Local IP at connection established or SoftAP's IP. It is assigned "**/_ac**" located on the *local IP address* of ESP8266/ESP32 module by default and can be changed with the sketch. A local IP means Local IP at connection established or SoftAP's IP.
## <i class="fa fa-bars"></i> Right on top ## <i class="fa fa-bars"></i> Right on top
@ -24,26 +24,38 @@ Currently, AutoConnect supports four menus. Undermost menu as "HOME" returns to
## <i class="fa fa-bars"></i> Configure new AP ## <i class="fa fa-bars"></i> Configure new AP
Scan all available access point in the vicinity and display it. Strength and security of the detected AP are marked. The <i class="fa fa-lock"></i> is indicated for the SSID that needs a security key. "**Hidden:**" means the number of hidden SSIDs discovered. It scans all available access points in the vicinity and display it further the WiFi signal strength and security indicator as <i class="fa fa-lock"></i> of the detected AP. Below that, the number of discovered hidden APs will be displayed.
Enter SSID and Passphrase and tap "**apply**" to starts WiFi connection. Enter SSID and Passphrase and tap "**Apply**" to start a WiFi connection.
<img src="images/newap.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" /> <img src="images/newap.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" />
If you want to configure with static IP, uncheck "**Enable DHCP**". Once the WiFi connection is established, the entered static IP[^1] configuration will be stored to the credentials in the flash and restored to the station configuration via the [Open SSIDs](#open-ssids) menu.
[^1]: AutoConnect does not check the syntax and validity of the entered IP address. If the entered static IPs are incorrect, it cannot connect to the access point.
<img src="images/newap_static.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" />
## <i class="fa fa-bars"></i> Open SSIDs ## <i class="fa fa-bars"></i> Open SSIDs
Once it was established WiFi connection, its SSID and password will be saved in the flash of ESP8266/ESP32 automatically. The **Open SSIDs** menu reads the saved SSID credentials from the flash. The stored credential data are listed by the SSID as shown below. Its label is a clickable button. Tap the SSID button, starts WiFi connection it. After WiFi connected, AutoConnect will automatically save the established SSID and password to the flash on the ESP module. **Open SSIDs** menu reads the saved SSID credentials and lists them as below. Listed items are clickable buttons and can initiate a connection to its access point.
<img src="images/open.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" /> <img src="images/open.png" style="border-style:solid;border-width:1px;border-color:lightgrey;width:280px;" />
!!! note "Saved credentials data structure has changed"
A structure of AutoConnect saved credentials has changed in v1.1.0 and was lost backward compatibility. Credentials saved by AutoConnect v1.0.3 (or earlier) will not display properly with AutoConnect v1.1.0. You need to erase the flash of the ESP module using the esptool before the sketch uploading.
```
esptool -c esp8266 (or esp32) - p [COM_PORT] erase_flash
```
## <i class="fa fa-bars"></i> Disconnect ## <i class="fa fa-bars"></i> Disconnect
Disconnect ESP8266/ESP32 from the current connection. It can also reset the ESP8266/ESP32 automatically after disconnection by instructing with using [API](api.md#autoreset) in the sketch. It disconnects ESP8266/ESP32 from the current connection. Also, ESP8266/ESP32 can be automatically reset after WiFi cutting by instructing with the sketch using the [AutoConnect API](api.md#autoreset).
After tapping "Disconnect", you will not be able to reach the AutoConnect menu. Once disconnected, you will need to set the SSID again for connecting the WLAN. After tapping the **Disconnect**, you will not be able to reach the AutoConnect menu. Once disconnected, you will need to set the SSID again for connecting to the WLAN.
## <i class="fa fa-bars"></i> Reset... ## <i class="fa fa-bars"></i> Reset...
Reset the ESP8266/ESP32 module, it will start rebooting. After rebooting complete, the ESP8266/ESP32 module begins establishing the previous connection with WIFI_STA mode, and *esp8266ap* or *esp32ap* of an access point will disappear from WLAN. Resetting the ESP8266/ESP32 module will initiate a reboot. When the module restarting, the *esp8266ap* or *esp32ap* access point will disappear from the WLAN and the ESP8266/ESP32 module will begin to reconnect a previous access point with WIFI_STA mode.
<img src="images/resetting.png" style="width:280px;" /> <img src="images/resetting.png" style="width:280px;" />
@ -52,23 +64,23 @@ Reset the ESP8266/ESP32 module, it will start rebooting. After rebooting complet
## <i class="fa fa-bars"></i> Custom menu items ## <i class="fa fa-bars"></i> Custom menu items
The menu items of the custom Web page line up at the below in the AutoConnect menu if the custom Web pages are joined. Details for [Custom Web pages in AutoConnect menu](acintro.md#custom-web-pages-in-autoconnectmenu). If the sketch has custom Web pages, the AutoConnect menu lines them up with the AutoConnect's items. Details for [Custom Web pages in AutoConnect menu](acintro.md#custom-web-pages-in-autoconnectmenu).
## <i class="fa fa-bars"></i> HOME ## <i class="fa fa-bars"></i> HOME
A **HOME** item located at the bottom of the menu list is a link to the home path. The URI as the home path is `/` by default, and it is defined by `AUTOCONNECT_HOMEURI` with **AutoConnectDefs.h** file. A **HOME** item at the bottom of the menu list is a link to the home path, and the default URI is `/` which is defined by `AUTOCONNECT_HOMEURI` in **AutoConnectDefs.h** header file.
```cpp ```cpp
#define AUTOCONNECT_HOMEURI "/" #define AUTOCONNECT_HOMEURI "/"
``` ```
You can change the HOME path using the AutoConnect API. The [**AutoConnect::home**](api.md#home) function sets the URI as a link of the HOME item of the AutoConnect menu. Also, you can change the HOME path using the AutoConnect API. The [**AutoConnect::home**](api.md#home) function sets the URI as a link of the HOME item in the AutoConnect menu.
## <i class="fa fa-bars"></i> by attaching AutoConnect menu ## <i class="fa fa-bars"></i> Attaching to AutoConnect menu
The AutoConnect menu can contain HTML pages of your owns sketch as custom items. It works for HTML pages implemented by **ESP8266WebServer::on** handler or **WebServer::on** handler for ESP32. That is, you can make it as menu items to invoke the legacy web page. The below screenshot is the result of adding an example sketch for the ESP8266WebServer library known as [FSBrowser](https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer/examples/FSBrowser) to the AutoConnect menu item. It adds Edit and List items with little modification to the legacy sketch code. The AutoConnect menu can contain your sketch's web pages as extra items as a custom. It works for HTML pages implemented by the **ESP8266WebServer::on** handler or the **WebServer::on** handler for ESP32. That is, you can make them invoke the legacy web pages from the AutoConnect menu. The below screen-shot is the result of adding an example sketch for the ESP8266WebServer library known as [FSBrowser](https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer/examples/FSBrowser) to the AutoConnect menu item. It can add Edit and List items with little modification to the legacy sketch code.
<div style="float:left;width:auto;height:420px;"><img style="width:auto;height:420px;" src="images/fsbmenu.png"></div> <div style="float:left;width:auto;height:420px;"><img style="width:auto;height:420px;" src="images/fsbmenu.png"></div>
<img style="margin-left:70px;width:auto;height:420px;" src="images/fsbmenu_expand.png"> <img style="margin-left:70px;width:auto;height:420px;" src="images/fsbmenu_expand.png">
You can extend the AutoConnect menu to improve the original sketches and according to the procedure described in section [*Advanced Usage*](advancedusage.md#casts-the-html-pages-to-be-add-on-into-the-menu). You can improve your sketches by extending the AutoConnect menu by adding the legacy web pages according to the procedure described in section [*Advanced Usage*](advancedusage.md#casts-the-html-pages-to-be-add-on-into-the-menu).

@ -2,8 +2,8 @@
* AutoConnect class implementation. * AutoConnect class implementation.
* @file AutoConnect.cpp * @file AutoConnect.cpp
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 1.0.6 * @version 1.1.0
* @date 2019-09-17 * @date 2019-10-08
* @copyright MIT license. * @copyright MIT license.
*/ */
@ -53,7 +53,7 @@ void AutoConnect::_initialize(void) {
_menuTitle = _apConfig.title; _menuTitle = _apConfig.title;
_connectTimeout = AUTOCONNECT_TIMEOUT; _connectTimeout = AUTOCONNECT_TIMEOUT;
_scanCount = 0; _scanCount = 0;
memset(&_credential, 0x00, sizeof(struct station_config)); memset(&_credential, 0x00, sizeof(station_config_t));
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
_disconnectEventId = -1; // The member available for ESP32 only _disconnectEventId = -1; // The member available for ESP32 only
#endif #endif
@ -111,22 +111,14 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
_ticker->start(AUTOCONNECT_FLICKER_PERIODDC, (uint8_t)AUTOCONNECT_FLICKER_WIDTHDC); _ticker->start(AUTOCONNECT_FLICKER_PERIODDC, (uint8_t)AUTOCONNECT_FLICKER_WIDTHDC);
} }
// Advance configuration for STA mode. // Advance configuration for STA mode. Restore previous configuration of STA.
#ifdef AC_DEBUG station_config_t current;
String staip_s = _apConfig.staip.toString(); if (_getConfigSTA(&current)) {
String staGateway_s = _apConfig.staGateway.toString(); AC_DBG("Current:%.32s\n", current.ssid);
String staNetmask_s = _apConfig.staNetmask.toString(); _loadAvailCredential(reinterpret_cast<const char*>(current.ssid));
String dns1_s = _apConfig.dns1.toString();
String dns2_s = _apConfig.dns2.toString();
AC_DBG("WiFi.config(IP=%s, Gateway=%s, Subnetmask=%s, DNS1=%s, DNS2=%s)\n", staip_s.c_str(), staGateway_s.c_str(), staNetmask_s.c_str(), dns1_s.c_str(), dns2_s.c_str());
#endif
if (!WiFi.config(_apConfig.staip, _apConfig.staGateway, _apConfig.staNetmask, _apConfig.dns1, _apConfig.dns2)) {
AC_DBG("failed\n");
return false;
} }
#ifdef ARDUINO_ARCH_ESP8266 if (!_configSTA(_apConfig.staip, _apConfig.staGateway, _apConfig.staNetmask, _apConfig.dns1, _apConfig.dns2))
AC_DBG("DHCP client(%s)\n", wifi_station_dhcpc_status() == DHCP_STOPPED ? "STOPPED" : "STARTED"); return false;
#endif
// If the portal is requested promptly skip the first WiFi.begin and // If the portal is requested promptly skip the first WiFi.begin and
// immediately start the portal. // immediately start the portal.
@ -150,16 +142,17 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
// Reconnect with a valid credential as the autoReconnect option is enabled. // Reconnect with a valid credential as the autoReconnect option is enabled.
if (!cs && _apConfig.autoReconnect && (ssid == nullptr && passphrase == nullptr)) { if (!cs && _apConfig.autoReconnect && (ssid == nullptr && passphrase == nullptr)) {
// Load a valid credential. // Load a valid credential.
if (_loadAvailCredential()) { if (_loadAvailCredential(nullptr)) {
// Try to reconnect with a stored credential. // Try to reconnect with a stored credential.
char ssid_c[sizeof(station_config::ssid) + 1]; char ssid_c[sizeof(station_config_t::ssid) + sizeof('\0')];
char password_c[sizeof(station_config::password) + 1]; char password_c[sizeof(station_config_t::password) + sizeof('\0')];
*ssid_c = '\0'; *ssid_c = '\0';
strncat(ssid_c, reinterpret_cast<const char*>(_credential.ssid), sizeof(ssid_c) - 1); strncat(ssid_c, reinterpret_cast<const char*>(_credential.ssid), sizeof(ssid_c) - sizeof('\0'));
*password_c = '\0'; *password_c = '\0';
strncat(password_c, reinterpret_cast<const char*>(_credential.password), sizeof(password_c) - 1); strncat(password_c, reinterpret_cast<const char*>(_credential.password), sizeof(password_c) - sizeof('\0'));
AC_DBG("autoReconnect loaded SSID:%s\n", ssid_c); AC_DBG("autoReconnect loaded SSID:%s\n", ssid_c);
const char* psk = strlen(password_c) ? password_c : nullptr; const char* psk = strlen(password_c) ? password_c : nullptr;
_configSTA(IPAddress(_credential.config.sta.ip), IPAddress(_credential.config.sta.gateway), IPAddress(_credential.config.sta.netmask), IPAddress(_credential.config.sta.dns1), IPAddress(_credential.config.sta.dns2));
WiFi.begin(ssid_c, psk); WiFi.begin(ssid_c, psk);
AC_DBG("WiFi.begin(%s%s%s)\n", ssid_c, psk == nullptr ? "" : ",", psk == nullptr ? "" : psk); AC_DBG("WiFi.begin(%s%s%s)\n", ssid_c, psk == nullptr ? "" : ",", psk == nullptr ? "" : psk);
cs = _waitForConnect(_connectTimeout) == WL_CONNECTED; cs = _waitForConnect(_connectTimeout) == WL_CONNECTED;
@ -191,21 +184,17 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
// Connection unsuccessful, launch the captive portal. // Connection unsuccessful, launch the captive portal.
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
if (!(_apConfig.apip == IPAddress(0, 0, 0, 0) || _apConfig.gateway == IPAddress(0, 0, 0, 0) || _apConfig.netmask == IPAddress(0, 0, 0, 0))) {
_config(); _config();
}
#endif #endif
WiFi.softAP(_apConfig.apid.c_str(), _apConfig.psk.c_str(), _apConfig.channel, _apConfig.hidden); WiFi.softAP(_apConfig.apid.c_str(), _apConfig.psk.c_str(), _apConfig.channel, _apConfig.hidden);
do { do {
delay(100); delay(100);
yield(); yield();
} while (WiFi.softAPIP() == IPAddress(0, 0, 0, 0)); } while (!WiFi.softAPIP());
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
if (!(_apConfig.apip == IPAddress(0, 0, 0, 0) || _apConfig.gateway == IPAddress(0, 0, 0, 0) || _apConfig.netmask == IPAddress(0, 0, 0, 0))) {
_config(); _config();
}
#endif #endif
if (_apConfig.apip != IPAddress(0, 0, 0, 0)) { if (_apConfig.apip) {
do { do {
delay(100); delay(100);
yield(); yield();
@ -307,11 +296,70 @@ bool AutoConnect::config(AutoConnectConfig& Config) {
* by Config method. * by Config method.
*/ */
bool AutoConnect::_config(void) { bool AutoConnect::_config(void) {
if (static_cast<uint32_t>(_apConfig.apip) == 0U || static_cast<uint32_t>(_apConfig.gateway) == 0U || static_cast<uint32_t>(_apConfig.netmask) == 0U)
AC_DBG("Warning: Contains invalid SoftAPIP address(es).\n");
bool rc = WiFi.softAPConfig(_apConfig.apip, _apConfig.gateway, _apConfig.netmask); bool rc = WiFi.softAPConfig(_apConfig.apip, _apConfig.gateway, _apConfig.netmask);
AC_DBG("SoftAP configure %s, %s, %s %s\n", _apConfig.apip.toString().c_str(), _apConfig.gateway.toString().c_str(), _apConfig.netmask.toString().c_str(), rc ? "" : "failed"); AC_DBG("SoftAP configure %s, %s, %s %s\n", _apConfig.apip.toString().c_str(), _apConfig.gateway.toString().c_str(), _apConfig.netmask.toString().c_str(), rc ? "" : "failed");
return rc; return rc;
} }
/**
* Advance configuration for STA mode.
* @param ip IP address
* @param gateway Gateway address
* @param netmask Netmask
* @param dns1 Primary DNS address
* @param dns2 Secondary DNS address
* @return true Station successfully configured
* @return false WiFi.config failed
*/
bool AutoConnect::_configSTA(const IPAddress& ip, const IPAddress& gateway, const IPAddress& netmask, const IPAddress& dns1, const IPAddress& dns2) {
bool rc;
AC_DBG("WiFi.config(IP=%s, Gateway=%s, Subnetmask=%s, DNS1=%s, DNS2=%s)\n", ip.toString().c_str(), gateway.toString().c_str(), netmask.toString().c_str(), dns1.toString().c_str(), dns2.toString().c_str());
if (!(rc = WiFi.config(ip, gateway, netmask, dns1, dns2)))
AC_DBG("failed\n");
#ifdef ARDUINO_ARCH_ESP8266
AC_DBG("DHCP client(%s)\n", wifi_station_dhcpc_status() == DHCP_STOPPED ? "STOPPED" : "STARTED");
#endif
return rc;
}
/**
* Obtains the currently established AP connection to determine if the
* station configuration needs to run before the first WiFi.begin.
* Get the SSID of the currently connected AP stored in the ESP module
* by using the SDK API natively.
* AutoConnect::begin retrieves the IP configuration from the stored
* credentials of AutoConnectCredential based on that SSID and executes
* WiFi.config before WiFi.begin.
* @param config Station configuration stored in the ESP module.
* @return true The config parameter has obtained configuration.
* @return false Station configuration does not exist.
*/
bool AutoConnect::_getConfigSTA(station_config_t* config) {
bool rc;
uint8_t* ssid;
uint8_t* bssid;
#if defined(ARDUINO_ARCH_ESP8266)
struct station_config current;
ssid = current.ssid;
bssid = current.bssid;
rc = wifi_station_get_config(&current);
#elif defined(ARDUINO_ARCH_ESP32)
wifi_config_t current;
ssid = current.sta.ssid;
bssid = current.sta.bssid;
rc = (esp_wifi_get_config(WIFI_IF_STA, &current) == ESP_OK);
#endif
if (rc) {
memcpy(config->ssid, ssid, sizeof(station_config_t::ssid));
memcpy(config->bssid, bssid, sizeof(station_config_t::bssid));
}
return rc;
}
/** /**
* Put a user site's home URI. * Put a user site's home URI.
* The URI specified by home is linked from "HOME" in the AutoConnect * The URI specified by home is linked from "HOME" in the AutoConnect
@ -469,10 +517,13 @@ void AutoConnect::handleRequest(void) {
if (WiFi.status() == WL_CONNECTED) if (WiFi.status() == WL_CONNECTED)
_disconnectWiFi(true); _disconnectWiFi(true);
// Leave current AP, reconfigure station
_configSTA(_apConfig.staip, _apConfig.staGateway, _apConfig.staNetmask, _apConfig.dns1, _apConfig.dns2);
// An attempt to establish a new AP. // An attempt to establish a new AP.
int32_t ch = _connectCh == 0 ? _apConfig.channel : _connectCh; int32_t ch = _connectCh == 0 ? _apConfig.channel : _connectCh;
char ssid_c[sizeof(station_config::ssid) + 1]; char ssid_c[sizeof(station_config_t::ssid) + 1];
char password_c[sizeof(station_config::password) + 1]; char password_c[sizeof(station_config_t::password) + 1];
*ssid_c = '\0'; *ssid_c = '\0';
strncat(ssid_c, reinterpret_cast<const char*>(_credential.ssid), sizeof(ssid_c) - 1); strncat(ssid_c, reinterpret_cast<const char*>(_credential.ssid), sizeof(ssid_c) - 1);
*password_c = '\0'; *password_c = '\0';
@ -481,7 +532,7 @@ void AutoConnect::handleRequest(void) {
WiFi.begin(ssid_c, password_c, ch); WiFi.begin(ssid_c, password_c, ch);
if (_waitForConnect(_connectTimeout) == WL_CONNECTED) { if (_waitForConnect(_connectTimeout) == WL_CONNECTED) {
if (WiFi.BSSID() != NULL) { if (WiFi.BSSID() != NULL) {
memcpy(_credential.bssid, WiFi.BSSID(), sizeof(station_config::bssid)); memcpy(_credential.bssid, WiFi.BSSID(), sizeof(station_config_t::bssid));
_currentHostIP = WiFi.localIP(); _currentHostIP = WiFi.localIP();
_redirectURI = String(F(AUTOCONNECT_URI_SUCCESS)); _redirectURI = String(F(AUTOCONNECT_URI_SUCCESS));
@ -592,13 +643,15 @@ void AutoConnect::onNotFound(WebServerClass::THandlerFunction fn) {
/** /**
* Load stored credentials that match nearby WLANs. * Load stored credentials that match nearby WLANs.
* @param ssid SSID which should be loaded. If nullptr is assigned, search SSID with WiFi.scan.
* @return true A matched credential of BSSID was loaded. * @return true A matched credential of BSSID was loaded.
*/ */
bool AutoConnect::_loadAvailCredential(void) { bool AutoConnect::_loadAvailCredential(const char* ssid) {
AutoConnectCredential credential(_apConfig.boundaryOffset); AutoConnectCredential credential(_apConfig.boundaryOffset);
if (credential.entries() > 0) { if (credential.entries() > 0) {
// Scan the vicinity only when the saved credentials are existing. // Scan the vicinity only when the saved credentials are existing.
if (!ssid) {
WiFi.scanDelete(); WiFi.scanDelete();
int8_t nn = WiFi.scanNetworks(false, true); int8_t nn = WiFi.scanNetworks(false, true);
AC_DBG("%d network(s) found\n", (int)nn); AC_DBG("%d network(s) found\n", (int)nn);
@ -607,12 +660,24 @@ bool AutoConnect::_loadAvailCredential(void) {
for (uint8_t i = 0; i < credential.entries(); i++) { for (uint8_t i = 0; i < credential.entries(); i++) {
credential.load(i, &_credential); credential.load(i, &_credential);
for (uint8_t n = 0; n < nn; n++) { for (uint8_t n = 0; n < nn; n++) {
if (!memcmp(_credential.bssid, WiFi.BSSID(n), sizeof(station_config::bssid))) if (!memcmp(_credential.bssid, WiFi.BSSID(n), sizeof(station_config_t::bssid)))
return true; return true;
} }
} }
} }
} }
else if (strlen(ssid))
if (credential.load(ssid, &_credential) >= 0) {
if (_credential.dhcp == STA_STATIC) {
_apConfig.staip = static_cast<IPAddress>(_credential.config.sta.ip);
_apConfig.staGateway = static_cast<IPAddress>(_credential.config.sta.gateway);
_apConfig.staNetmask = static_cast<IPAddress>(_credential.config.sta.netmask);
_apConfig.dns1 = static_cast<IPAddress>(_credential.config.sta.dns1);
_apConfig.dns2 = static_cast<IPAddress>(_credential.config.sta.dns2);
}
return true;
}
}
return false; return false;
} }
@ -738,24 +803,53 @@ String AutoConnect::_induceConnect(PageArgument& args) {
if (args.hasArg(String(F(AUTOCONNECT_PARAMID_CRED)))) { if (args.hasArg(String(F(AUTOCONNECT_PARAMID_CRED)))) {
// Read from EEPROM // Read from EEPROM
AutoConnectCredential credential(_apConfig.boundaryOffset); AutoConnectCredential credential(_apConfig.boundaryOffset);
struct station_config entry; credential.load(args.arg(String(F(AUTOCONNECT_PARAMID_CRED))).c_str(), &_credential);
credential.load(args.arg(String(F(AUTOCONNECT_PARAMID_CRED))).c_str(), &entry); #ifdef AC_DEBUG
strncpy(reinterpret_cast<char*>(_credential.ssid), reinterpret_cast<const char*>(entry.ssid), sizeof(_credential.ssid)); IPAddress staip = IPAddress(_credential.config.sta.ip);
strncpy(reinterpret_cast<char*>(_credential.password), reinterpret_cast<const char*>(entry.password), sizeof(_credential.password)); AC_DBG("Credential loaded:%.*s(%s)\n", sizeof(station_config_t::ssid), reinterpret_cast<const char*>(_credential.ssid), _credential.dhcp == STA_DHCP ? "DHCP" : staip.toString().c_str());
AC_DBG("Credential loaded:%.*s\n", sizeof(station_config::ssid), _credential.ssid); #endif
} }
else { else {
AC_DBG("Queried SSID:%s\n", args.arg(AUTOCONNECT_PARAMID_SSID).c_str()); AC_DBG("Queried SSID:%s\n", args.arg(AUTOCONNECT_PARAMID_SSID).c_str());
// Credential had by the post parameter. // Credential had by the post parameter.
strncpy(reinterpret_cast<char*>(_credential.ssid), args.arg(String(F(AUTOCONNECT_PARAMID_SSID))).c_str(), sizeof(_credential.ssid)); strncpy(reinterpret_cast<char*>(_credential.ssid), args.arg(String(F(AUTOCONNECT_PARAMID_SSID))).c_str(), sizeof(_credential.ssid));
strncpy(reinterpret_cast<char*>(_credential.password), args.arg(String(F(AUTOCONNECT_PARAMID_PASS))).c_str(), sizeof(_credential.password)); strncpy(reinterpret_cast<char*>(_credential.password), args.arg(String(F(AUTOCONNECT_PARAMID_PASS))).c_str(), sizeof(_credential.password));
// Static IP detection
if (args.hasArg(String(F(AUTOCONNECT_PARAMID_DHCP)))) {
_credential.dhcp = STA_DHCP;
_credential.config.sta.ip = _credential.config.sta.gateway = _credential.config.sta.netmask = _credential.config.sta.dns1 = _credential.config.sta.dns2 = 0U;
} }
else {
_credential.dhcp = STA_STATIC;
const String paramId[] = {
String(F(AUTOCONNECT_PARAMID_STAIP)),
String(F(AUTOCONNECT_PARAMID_GTWAY)),
String(F(AUTOCONNECT_PARAMID_NTMSK)),
String(F(AUTOCONNECT_PARAMID_DNS1)),
String(F(AUTOCONNECT_PARAMID_DNS2))
};
for (uint8_t i = 0; i < sizeof(station_config_t::_config::addr) / sizeof(uint32_t); i++) {
if (args.hasArg(paramId[i])) {
IPAddress ip;
if (ip.fromString(args.arg(paramId[i])))
_credential.config.addr[i] = static_cast<uint32_t>(ip);
}
}
}
}
// Restore the configured IPs to STA configuration
_apConfig.staip = static_cast<IPAddress>(_credential.config.sta.ip);
_apConfig.staGateway = static_cast<IPAddress>(_credential.config.sta.gateway);
_apConfig.staNetmask = static_cast<IPAddress>(_credential.config.sta.netmask);
_apConfig.dns1 = static_cast<IPAddress>(_credential.config.sta.dns1);
_apConfig.dns2 = static_cast<IPAddress>(_credential.config.sta.dns2);
// Determine the connection channel based on the scan result. // Determine the connection channel based on the scan result.
_connectCh = 0; _connectCh = 0;
for (uint8_t nn = 0; nn < _scanCount; nn++) { for (uint8_t nn = 0; nn < _scanCount; nn++) {
String ssid = WiFi.SSID(nn); String ssid = WiFi.SSID(nn);
if (!strncmp(ssid.c_str(), reinterpret_cast<const char*>(_credential.ssid), sizeof(station_config::ssid))) { if (!strncmp(ssid.c_str(), reinterpret_cast<const char*>(_credential.ssid), sizeof(station_config_t::ssid))) {
_connectCh = WiFi.channel(nn); _connectCh = WiFi.channel(nn);
break; break;
} }
@ -811,6 +905,7 @@ String AutoConnect::_invokeResult(PageArgument& args) {
// This is the specification as before. // This is the specification as before.
redirect += _currentHostIP.toString(); redirect += _currentHostIP.toString();
#endif #endif
AC_DBG("Redirect to %s\n", redirect.c_str());
redirect += _redirectURI; redirect += _redirectURI;
_webServer->sendHeader(String(F("Location")), redirect, true); _webServer->sendHeader(String(F("Location")), redirect, true);
_webServer->send(302, String(F("text/plain")), _emptyString); _webServer->send(302, String(F("text/plain")), _emptyString);

@ -2,8 +2,8 @@
* Declaration of AutoConnect class and accompanying AutoConnectConfig class. * Declaration of AutoConnect class and accompanying AutoConnectConfig class.
* @file AutoConnect.h * @file AutoConnect.h
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 1.0.0 * @version 1.1.0
* @date 2019-08-15 * @date 2019-10-11
* @copyright MIT license. * @copyright MIT license.
*/ */
@ -229,10 +229,12 @@ class AutoConnect {
} AC_STARECONNECT_t; } AC_STARECONNECT_t;
void _initialize(void); void _initialize(void);
bool _config(void); bool _config(void);
bool _configSTA(const IPAddress& ip, const IPAddress& gateway, const IPAddress& netmask, const IPAddress& dns1, const IPAddress& dns2);
bool _getConfigSTA(station_config_t* config);
void _startWebServer(void); void _startWebServer(void);
void _startDNSServer(void); void _startDNSServer(void);
void _handleNotFound(void); void _handleNotFound(void);
bool _loadAvailCredential(void); bool _loadAvailCredential(const char* ssid);
void _stopPortal(void); void _stopPortal(void);
bool _classifyHandle(HTTPMethod mothod, String uri); bool _classifyHandle(HTTPMethod mothod, String uri);
void _handleUpload(const String& requestUri, const HTTPUpload& upload); void _handleUpload(const String& requestUri, const HTTPUpload& upload);
@ -290,7 +292,7 @@ class AutoConnect {
/** Saved configurations */ /** Saved configurations */
AutoConnectConfig _apConfig; AutoConnectConfig _apConfig;
struct station_config _credential; station_config_t _credential;
uint8_t _hiddenSSIDCount; uint8_t _hiddenSSIDCount;
int16_t _scanCount; int16_t _scanCount;
uint8_t _connectCh; uint8_t _connectCh;
@ -374,6 +376,7 @@ class AutoConnect {
String _token_LIST_SSID(PageArgument& args); String _token_LIST_SSID(PageArgument& args);
String _token_SSID_COUNT(PageArgument& args); String _token_SSID_COUNT(PageArgument& args);
String _token_HIDDEN_COUNT(PageArgument& args); String _token_HIDDEN_COUNT(PageArgument& args);
String _token_CONFIG_STAIP(PageArgument& args);
String _token_OPEN_SSID(PageArgument& args); String _token_OPEN_SSID(PageArgument& args);
String _token_UPTIME(PageArgument& args); String _token_UPTIME(PageArgument& args);
String _token_BOOTURI(PageArgument& args); String _token_BOOTURI(PageArgument& args);

@ -2,8 +2,8 @@
* AutoConnectCredential class dispatcher. * AutoConnectCredential class dispatcher.
* @file AutoConnectCredential.cpp * @file AutoConnectCredential.cpp
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 1.0.2 * @version 1.1.0
* @date 2019-09-16 * @date 2019-10-07
* @copyright MIT license. * @copyright MIT license.
*/ */
@ -16,16 +16,23 @@
* AutoConnectCredential constructor takes the available count of saved * AutoConnectCredential constructor takes the available count of saved
* entries. * entries.
* A stored credential data structure in EEPROM. * A stored credential data structure in EEPROM.
* 0 7 8 9a b (t) * 0 7 8 9a b (u) (u+16) (t)
* +--------+-+--+-----------------+-----------------+--+ * +--------+-+--+-----------------+-+--+--+--+----+----+-----------------+--+
* |AC_CREDT|e|ss|ssid\0pass\0bssid|ssid\0pass\0bssid|\0| * |AC_CREDT|e|ss|ssid\0pass\0bssid|d|ip|gw|nm|dns1|dns2|ssid\0pass\0bssid|\0|
* +--------+-+--+-----------------+-----------------+--+ * +--------+-+--+-----------------+-+--+--+--+----+----+-----------------+--+
* AC_CREDT : Identifier. 8 characters. * AC_CREDT : Identifier. 8 characters.
* e : Number of contained entries(uint8_t). * e : Number of contained entries(uint8_t).
* ss : Container size, excluding ID and number of entries(uint16_t). * ss : Container size, excluding ID and number of entries(uint16_t).
* ssid: SSID string with null termination. * ssid: SSID string with null termination.
* password : Password string with null termination. * password : Password string with null termination.
* bssid : BSSID 6 bytes. * bssid : BSSID 6 bytes.
* d : DHCP is in available. 0:DCHP 1:Static IP
* ip - dns2 : Optional fields for static IPs configuration, these fields are available when d=1.
* ip : Static IP (uint32_t)
* gw : Gateway address (uint32_t)
* nm : Netmask (uint32_t)
* dns1 : Primary DNS (uint32)
* dns2 : Secondary DNS (uint32_t)
* t : The end of the container is a continuous '\0'. * t : The end of the container is a continuous '\0'.
* The AC_CREDT identifier is at the beginning of the area. * The AC_CREDT identifier is at the beginning of the area.
* SSID and PASSWORD are terminated by '\ 0'. * SSID and PASSWORD are terminated by '\ 0'.
@ -81,7 +88,7 @@ AutoConnectCredential::~AutoConnectCredential() {
* false Could not deleted. * false Could not deleted.
*/ */
bool AutoConnectCredential::del(const char* ssid) { bool AutoConnectCredential::del(const char* ssid) {
struct station_config entry; station_config_t entry;
bool rc = false; bool rc = false;
if (load(ssid, &entry) >= 0) { if (load(ssid, &entry) >= 0) {
@ -100,9 +107,15 @@ bool AutoConnectCredential::del(const char* ssid) {
// Erase BSSID // Erase BSSID
_eeprom->write(_dp++, 0xff); _eeprom->write(_dp++, 0xff);
for (uint8_t i = 0; i < sizeof(station_config::bssid); i++) for (uint8_t i = 0; i < sizeof(station_config_t::bssid); i++)
_eeprom->write(_dp++, 0xff); _eeprom->write(_dp++, 0xff);
// Erase ip configuration extention
if (_eeprom->read(_dp) == STA_STATIC) {
for (uint8_t i = 0; i < sizeof(station_config_t::_config); i++)
_eeprom->write(_dp++, 0xff);
}
// End 0xff writing, update headers. // End 0xff writing, update headers.
_entries--; _entries--;
_eeprom->write(_offset + static_cast<int>(sizeof(AC_IDENTIFIER)) - 1, _entries); _eeprom->write(_offset + static_cast<int>(sizeof(AC_IDENTIFIER)) - 1, _entries);
@ -124,15 +137,15 @@ bool AutoConnectCredential::del(const char* ssid) {
* @retval The entry number of the SSID in EEPROM. If the number less than 0, * @retval The entry number of the SSID in EEPROM. If the number less than 0,
* the specified SSID was not found. * the specified SSID was not found.
*/ */
int8_t AutoConnectCredential::load(const char* ssid, struct station_config* config) { int8_t AutoConnectCredential::load(const char* ssid, station_config_t* config) {
int8_t entry = -1; int8_t entry = -1;
_dp = AC_HEADERSIZE; _dp = AC_HEADERSIZE;
if (_entries) { if (_entries) {
_eeprom->begin(AC_HEADERSIZE + _containSize); _eeprom->begin(AC_HEADERSIZE + _containSize);
for (uint8_t i = 0; i < _entries; i++) { for (uint8_t i = 0; i < _entries; i++) {
_retrieveEntry(reinterpret_cast<char*>(config->ssid), reinterpret_cast<char*>(config->password), config->bssid); _retrieveEntry(config);
if (!strcmp(ssid, (const char*)config->ssid)) { if (!strcmp(ssid, reinterpret_cast<const char*>(config->ssid))) {
entry = i; entry = i;
break; break;
} }
@ -151,12 +164,12 @@ int8_t AutoConnectCredential::load(const char* ssid, struct station_config* conf
* @retval true The entry number of the SSID in EEPROM. * @retval true The entry number of the SSID in EEPROM.
* false The number is not available. * false The number is not available.
*/ */
bool AutoConnectCredential::load(int8_t entry, struct station_config* config) { bool AutoConnectCredential::load(int8_t entry, station_config_t* config) {
_dp = AC_HEADERSIZE; _dp = AC_HEADERSIZE;
if (_entries && entry < _entries) { if (_entries && entry < _entries) {
_eeprom->begin(AC_HEADERSIZE + _containSize); _eeprom->begin(AC_HEADERSIZE + _containSize);
while (entry-- >= 0) while (entry-- >= 0)
_retrieveEntry(reinterpret_cast<char*>(config->ssid), reinterpret_cast<char*>(config->password), config->bssid); _retrieveEntry(config);
_eeprom->end(); _eeprom->end();
return true; return true;
} }
@ -174,18 +187,18 @@ bool AutoConnectCredential::load(int8_t entry, struct station_config* config) {
* @retval true Successfully saved. * @retval true Successfully saved.
* @retval false EEPROM commit failed. * @retval false EEPROM commit failed.
*/ */
bool AutoConnectCredential::save(const struct station_config* config) { bool AutoConnectCredential::save(const station_config_t* config) {
static const char _id[] = AC_IDENTIFIER; static const char _id[] = AC_IDENTIFIER;
struct station_config stage; station_config_t stage;
int8_t entry; int8_t entry;
bool rep = false; bool rep = false;
bool rc; bool rc;
// Detect same entry for replacement. // Detect same entry for replacement.
entry = load((const char*)(config->ssid), &stage); entry = load(reinterpret_cast<const char*>(config->ssid), &stage);
// Saving start. // Saving start.
_eeprom->begin(AC_HEADERSIZE + _containSize + sizeof(struct station_config)); _eeprom->begin(AC_HEADERSIZE + _containSize + sizeof(station_config_t));
// Determine insertion or replacement. // Determine insertion or replacement.
if (entry >= 0) { if (entry >= 0) {
@ -196,9 +209,15 @@ bool AutoConnectCredential::save(const struct station_config* config) {
dm--; dm--;
_eeprom->write(_dp, 0xff); // Clear SSID, Passphrase _eeprom->write(_dp, 0xff); // Clear SSID, Passphrase
} }
for (uint8_t i = 0; i < sizeof(station_config::bssid); i++) { for (uint8_t i = 0; i < sizeof(station_config_t::bssid); i++) {
_eeprom->write(_dp++, 0xff); // Clear BSSID _eeprom->write(_dp++, 0xff); // Clear BSSID
} }
uint8_t ss = _eeprom->read(_dp); // Read dhcp assignment flag
_eeprom->write(_dp++, 0xff); // Clear dhcp
if (ss == (uint8_t)STA_STATIC) {
for (uint8_t i = 0 ; i < sizeof(station_config_t::_config); i++)
_eeprom->write(_dp++, 0xff); // Clear static IPs
}
} }
else { else {
// Same entry not found. increase the entry. // Same entry not found. increase the entry.
@ -213,7 +232,11 @@ bool AutoConnectCredential::save(const struct station_config* config) {
delay(10); delay(10);
// Seek insertion point, evaluate capacity to insert the new entry. // Seek insertion point, evaluate capacity to insert the new entry.
uint16_t eSize = strlen((const char*)config->ssid) + strlen((const char*)config->password) + sizeof(station_config::bssid) + 2; uint16_t eSize = strlen(reinterpret_cast<const char*>(config->ssid)) + strlen(reinterpret_cast<const char*>(config->password)) + sizeof(station_config_t::bssid) + sizeof(station_config_t::dhcp);
if (config->dhcp == (uint8_t)STA_STATIC)
eSize += sizeof(station_config_t::_config);
eSize += sizeof('\0') + sizeof('\0');
for (_dp = AC_HEADERSIZE; _dp < _containSize + AC_HEADERSIZE; _dp++) { for (_dp = AC_HEADERSIZE; _dp < _containSize + AC_HEADERSIZE; _dp++) {
uint8_t c = _eeprom->read(_dp); uint8_t c = _eeprom->read(_dp);
if (c == 0xff) { if (c == 0xff) {
@ -241,9 +264,17 @@ bool AutoConnectCredential::save(const struct station_config* config) {
c = *dt++; c = *dt++;
_eeprom->write(_dp++, c); _eeprom->write(_dp++, c);
} while (c != '\0'); } while (c != '\0');
for (uint8_t i = 0; i < sizeof(station_config::bssid); i++) { for (uint8_t i = 0; i < sizeof(station_config_t::bssid); i++)
_eeprom->write(_dp++, config->bssid[i]); // write BSSID _eeprom->write(_dp++, config->bssid[i]); // write BSSID
_eeprom->write(_dp++, config->dhcp); // write dhcp flag
if (config->dhcp == (uint8_t)STA_STATIC) {
for (uint8_t e = 0; e < sizeof(station_config_t::_config::addr) / sizeof(uint32_t); e++) {
uint32_t ip = config->config.addr[e];
for (uint8_t b = 1; b <= sizeof(ip); b++)
_eeprom->write(_dp++, ((uint8_t*)&ip)[sizeof(ip) - b]);
}
} }
// Terminate container, mark to the end of credential area. // Terminate container, mark to the end of credential area.
// When the entry is replaced, not mark a terminator. // When the entry is replaced, not mark a terminator.
if (!rep) { if (!rep) {
@ -268,27 +299,41 @@ bool AutoConnectCredential::save(const struct station_config* config) {
* @param ssid A SSID storing address. * @param ssid A SSID storing address.
* @param password A password storing address. * @param password A password storing address.
*/ */
void AutoConnectCredential::_retrieveEntry(char* ssid, char* password, uint8_t* bssid) { void AutoConnectCredential::_retrieveEntry(station_config_t* config) {
uint8_t ec; uint8_t ec;
// Skip unavailable entry. // Skip unavailable entry.
while ((ec = _eeprom->read(_dp++)) == 0xff) {} while ((ec = _eeprom->read(_dp++)) == 0xff) {}
_ep = _dp - 1;
// Retrieve SSID // Retrieve SSID
_ep = _dp - 1; uint8_t* bp = config->ssid;
*ssid++ = ec; *bp++ = ec;
do { do {
ec = _eeprom->read(_dp++); ec = _eeprom->read(_dp++);
*ssid++ = ec; *bp++ = ec;
} while (ec != '\0'); } while (ec != '\0');
// Retrieve Password // Retrieve Password
bp = config->password;
do { do {
ec = _eeprom->read(_dp++); ec = _eeprom->read(_dp++);
*password++ = ec; *bp++ = ec;
} while (ec != '\0'); } while (ec != '\0');
// Retrieve BSSID // Retrieve BSSID
for (uint8_t i = 0; i < sizeof(station_config::bssid); i++) for (uint8_t i = 0; i < sizeof(station_config_t::bssid); i++)
bssid[i] = _eeprom->read(_dp++); config->bssid[i] = _eeprom->read(_dp++);
// Extended readout for static IP
config->dhcp = _eeprom->read(_dp++);
if (config->dhcp == (uint8_t)STA_STATIC) {
for (uint8_t e = 0; e < sizeof(station_config_t::_config::addr) / sizeof(uint32_t); e++) {
uint32_t* ip = &config->config.addr[e];
*ip = 0;
for (uint8_t b = 0; b < sizeof(uint32_t); b++) {
*ip <<= 8;
*ip += _eeprom->read(_dp++);
}
}
}
} }
#else #else
@ -299,19 +344,24 @@ void AutoConnectCredential::_retrieveEntry(char* ssid, char* password, uint8_t*
* The credential area in the flash used by AutoConnect was moved from * The credential area in the flash used by AutoConnect was moved from
* EEPROM to NVS with v.1.0.0. A stored credential data structure of * EEPROM to NVS with v.1.0.0. A stored credential data structure of
* Preferences is as follows. It has no identifier as AC_CREDT. * Preferences is as follows. It has no identifier as AC_CREDT.
* 0 12 3 (t) * 0 12 3 (u) (u+16) (t)
* +-+--+-----------------+-----------------+--+ * +-+--+-----------------+-+--+--+--+----+----+-----------------+--+
* |e|ss|ssid\0pass\0bssid|ssid\0pass\0bssid|\0| * |e|ss|ssid\0pass\0bssid|d|ip|gw|nm|dns1|dns2|ssid\0pass\0bssid|\0|
* +-+--+-----------------+-----------------+--+ * +-+--+-----------------+-+--+--+--+----+----+-----------------+--+
* e : Number of contained entries(uint8_t). * e : Number of contained entries(uint8_t).
* ss : Container size, excluding ID and number of entries(uint16_t). * ss : Container size, excluding ID and number of entries(uint16_t).
* ssid: SSID string with null termination. * ssid: SSID string with null termination.
* password : Password string with null termination. * password : Password string with null termination.
* bssid : BSSID 6 bytes. * bssid : BSSID 6 bytes.
* d : DHCP is in available. 0:DCHP 1:Static IP
* ip - dns2 : Optional fields for static IPs configuration, these fields are available when d=1.
* ip : Static IP (uint32_t)
* gw : Gateway address (uint32_t)
* nm : Netmask (uint32_t)
* dns1 : Primary DNS (uint32)
* dns2 : Secondary DNS (uint32_t)
* t : The end of the container is a continuous '\0'. * t : The end of the container is a continuous '\0'.
* The AC_CREDT identifier is at the beginning of the area.
* SSID and PASSWORD are terminated by '\ 0'. * SSID and PASSWORD are terminated by '\ 0'.
* Free area are filled with FF, which is reused as an area for insertion.
*/ */
AutoConnectCredential::AutoConnectCredential() { AutoConnectCredential::AutoConnectCredential() {
_allocateEntry(); _allocateEntry();
@ -362,7 +412,7 @@ inline uint8_t AutoConnectCredential::entries(void) {
* @retval The entry number of the SSID. If the number less than 0, * @retval The entry number of the SSID. If the number less than 0,
* the specified SSID was not found. * the specified SSID was not found.
*/ */
int8_t AutoConnectCredential::load(const char* ssid, struct station_config* config) { int8_t AutoConnectCredential::load(const char* ssid, station_config_t* config) {
// Determine the number in entries // Determine the number in entries
int8_t en = 0; int8_t en = 0;
_entries = _import(); // Reload the saved credentials _entries = _import(); // Reload the saved credentials
@ -386,7 +436,7 @@ int8_t AutoConnectCredential::load(const char* ssid, struct station_config* conf
* @retval true The entry number of the SSID. * @retval true The entry number of the SSID.
* false The number is not available. * false The number is not available.
*/ */
bool AutoConnectCredential::load(int8_t entry, struct station_config* config) { bool AutoConnectCredential::load(int8_t entry, station_config_t* config) {
_entries = _import(); _entries = _import();
for (decltype(_credit)::iterator it = _credit.begin(), e = _credit.end(); it != e; ++it) { for (decltype(_credit)::iterator it = _credit.begin(), e = _credit.end(); it != e; ++it) {
if (!entry--) { if (!entry--) {
@ -406,7 +456,7 @@ bool AutoConnectCredential::load(int8_t entry, struct station_config* config) {
* @retval true Successfully saved. * @retval true Successfully saved.
* @retval false Preferences commit failed. * @retval false Preferences commit failed.
*/ */
bool AutoConnectCredential::save(const struct station_config* config) { bool AutoConnectCredential::save(const station_config_t* config) {
if (_add(config)) { if (_add(config)) {
return _commit() > 0 ? true : false; return _commit() > 0 ? true : false;
} }
@ -432,6 +482,9 @@ bool AutoConnectCredential::_add(const station_config_t* config) {
AC_CREDTBODY_t credtBody; AC_CREDTBODY_t credtBody;
credtBody.password = String(reinterpret_cast<const char*>(config->password)); credtBody.password = String(reinterpret_cast<const char*>(config->password));
memcpy(credtBody.bssid, config->bssid, sizeof(AC_CREDTBODY_t::bssid)); memcpy(credtBody.bssid, config->bssid, sizeof(AC_CREDTBODY_t::bssid));
credtBody.dhcp = config->dhcp;
for (uint8_t e = 0; e < sizeof(AC_CREDTBODY_t::ip) / sizeof(uint32_t); e++)
credtBody.ip[e] = credtBody.dhcp == (uint8_t)STA_STATIC ? config->config.addr[e] : 0U;
std::pair<AC_CREDT_t::iterator, bool> rc = _credit.insert(std::make_pair(ssid, credtBody)); std::pair<AC_CREDT_t::iterator, bool> rc = _credit.insert(std::make_pair(ssid, credtBody));
_entries = _credit.size(); _entries = _credit.size();
#ifdef AC_DBG #ifdef AC_DBG
@ -455,7 +508,11 @@ size_t AutoConnectCredential::_commit(void) {
for (const auto& credt : _credit) { for (const auto& credt : _credit) {
ssid = credt.first; ssid = credt.first;
credtBody = credt.second; credtBody = credt.second;
sz += ssid.length() + sizeof('\0') + credtBody.password.length() + sizeof('\0') + sizeof(AC_CREDTBODY_t::bssid); sz += ssid.length() + sizeof('\0') + credtBody.password.length() + sizeof('\0') + sizeof(AC_CREDTBODY_t::bssid) + sizeof(AC_CREDTBODY_t::dhcp);
if (credtBody.dhcp == (uint32_t)STA_STATIC) {
for (uint8_t e = 0; e < sizeof(AC_CREDTBODY_t::ip) / sizeof(uint32_t); e++)
sz += sizeof(uint32_t);
}
} }
// When the entry is not empty, the size of container terminator as '\0' must be added. // When the entry is not empty, the size of container terminator as '\0' must be added.
_containSize = sz + (_entries ? sizeof('\0') : 0); _containSize = sz + (_entries ? sizeof('\0') : 0);
@ -484,6 +541,16 @@ size_t AutoConnectCredential::_commit(void) {
dp += itemLen; dp += itemLen;
memcpy(&credtPool[dp], credtBody.bssid, sizeof(station_config_t::bssid)); memcpy(&credtPool[dp], credtBody.bssid, sizeof(station_config_t::bssid));
dp += sizeof(station_config_t::bssid); dp += sizeof(station_config_t::bssid);
// DHCP/Static IP indicator
credtPool[dp++] = (uint8_t)credtBody.dhcp;
// Static IP configuration
if (credtBody.dhcp == STA_STATIC) {
for (uint8_t e = 0; e < sizeof(AC_CREDTBODY_t::ip) / sizeof(uint32_t); e++) {
// uint32_t ip = credtBody.ip[e];
for (uint8_t b = 1; b <= sizeof(credtBody.ip[e]); b++)
credtPool[dp++] = ((uint8_t*)&credtBody.ip[e])[sizeof(credtBody.ip[e]) - b];
}
}
} }
if (_credit.size() > 0) if (_credit.size() > 0)
credtPool[dp] = '\0'; // Terminates a container credtPool[dp] = '\0'; // Terminates a container
@ -552,9 +619,22 @@ uint8_t AutoConnectCredential::_import(void) {
// BSSID // BSSID
dp += credtBody.password.length() + sizeof('\0'); dp += credtBody.password.length() + sizeof('\0');
memcpy(credtBody.bssid, &credtPool[dp], sizeof(AC_CREDTBODY_t::bssid)); memcpy(credtBody.bssid, &credtPool[dp], sizeof(AC_CREDTBODY_t::bssid));
dp += sizeof(AC_CREDTBODY_t::bssid);
// DHCP/Static IP indicator
credtBody.dhcp = credtPool[dp++];
// Static IP configuration
for (uint8_t e = 0; e < sizeof(AC_CREDTBODY_t::ip) / sizeof(uint32_t); e++) {
uint32_t* ip = &credtBody.ip[e];
*ip = 0U;
if (credtBody.dhcp == (uint8_t)STA_STATIC) {
for (uint8_t b = 0; b < sizeof(uint32_t); b++) {
*ip <<= 8;
*ip += credtPool[dp++];
}
}
}
// Make an entry // Make an entry
_credit.insert(std::make_pair(ssid, credtBody)); _credit.insert(std::make_pair(ssid, credtBody));
dp += sizeof(AC_CREDTBODY_t::bssid);
} }
free(credtPool); free(credtPool);
} }
@ -585,6 +665,9 @@ void AutoConnectCredential::_obtain(AC_CREDT_t::iterator const& it, station_conf
ssid.toCharArray(reinterpret_cast<char*>(config->ssid), sizeof(station_config_t::ssid)); ssid.toCharArray(reinterpret_cast<char*>(config->ssid), sizeof(station_config_t::ssid));
credtBody.password.toCharArray(reinterpret_cast<char*>(config->password), sizeof(station_config_t::password)); credtBody.password.toCharArray(reinterpret_cast<char*>(config->password), sizeof(station_config_t::password));
memcpy(config->bssid, credtBody.bssid, sizeof(station_config_t::bssid)); memcpy(config->bssid, credtBody.bssid, sizeof(station_config_t::bssid));
config->dhcp = credtBody.dhcp;
for (uint8_t e = 0; e < sizeof(AC_CREDTBODY_t::ip) / sizeof(uint32_t); e++)
config->config.addr[e] = credtBody.dhcp == (uint8_t)STA_STATIC ? credtBody.ip[e] : 0U;
} }
#endif #endif

@ -2,8 +2,8 @@
* Declaration of AutoConnectCredential class. * Declaration of AutoConnectCredential class.
* @file AutoConnectCredential.h * @file AutoConnectCredential.h
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 1.0.2 * @version 1.1.0
* @date 2019-09-16 * @date 2019-10-07
* @copyright MIT license. * @copyright MIT license.
*/ */
@ -32,13 +32,6 @@ extern "C" {
#define AC_CREDENTIAL_PREFERENCES 0 #define AC_CREDENTIAL_PREFERENCES 0
#endif #endif
#include <esp_wifi.h> #include <esp_wifi.h>
struct station_config {
uint8_t ssid[32];
uint8_t password[64];
uint8_t bssid_set;
uint8_t bssid[6];
wifi_fast_scan_threshold_t threshold;
};
#endif #endif
#include "AutoConnectDefs.h" #include "AutoConnectDefs.h"
@ -59,15 +52,37 @@ wifi_fast_scan_threshold_t threshold;
#define AC_IDENTIFIER "AC_CREDT" #define AC_IDENTIFIER "AC_CREDT"
#endif #endif
typedef enum {
STA_DHCP = 0,
STA_STATIC
} station_config_dhcp;
typedef struct {
uint8_t ssid[32];
uint8_t password[64];
uint8_t bssid[6];
uint8_t dhcp; /**< 0:DHCP, 1:Static IP */
union _config {
uint32_t addr[5];
struct _sta {
uint32_t ip;
uint32_t gateway;
uint32_t netmask;
uint32_t dns1;
uint32_t dns2;
} sta;
} config;
} station_config_t;
class AutoConnectCredentialBase { class AutoConnectCredentialBase {
public: public:
explicit AutoConnectCredentialBase() : _entries(0), _containSize(0) {} explicit AutoConnectCredentialBase() : _entries(0), _containSize(0) {}
virtual ~AutoConnectCredentialBase() {} virtual ~AutoConnectCredentialBase() {}
virtual uint8_t entries(void) { return _entries; } virtual uint8_t entries(void) { return _entries; }
virtual bool del(const char* ssid) = 0; virtual bool del(const char* ssid) = 0;
virtual int8_t load(const char* ssid, struct station_config* config) = 0; virtual int8_t load(const char* ssid, station_config_t* config) = 0;
virtual bool load(int8_t entry, struct station_config* config) = 0; virtual bool load(int8_t entry, station_config_t* config) = 0;
virtual bool save(const struct station_config* config) = 0; virtual bool save(const station_config_t* config) = 0;
protected: protected:
virtual void _allocateEntry(void) = 0; /**< Initialize storage for credentials. */ virtual void _allocateEntry(void) = 0; /**< Initialize storage for credentials. */
@ -88,15 +103,15 @@ class AutoConnectCredential : public AutoConnectCredentialBase {
explicit AutoConnectCredential(uint16_t offset); explicit AutoConnectCredential(uint16_t offset);
~AutoConnectCredential(); ~AutoConnectCredential();
bool del(const char* ssid) override; bool del(const char* ssid) override;
int8_t load(const char* ssid, struct station_config* config) override; int8_t load(const char* ssid, station_config_t* config) override;
bool load(int8_t entry, struct station_config* config) override; bool load(int8_t entry, station_config_t* config) override;
bool save(const struct station_config* config) override; bool save(const station_config_t* config) override;
protected: protected:
void _allocateEntry(void) override; /**< Initialize storage for credentials. */ void _allocateEntry(void) override; /**< Initialize storage for credentials. */
private: private:
void _retrieveEntry(char* ssid, char* password, uint8_t* bssid); /**< Read an available entry. */ void _retrieveEntry(station_config_t* config); /**< Read an available entry. */
int _dp; /**< The current address in EEPROM */ int _dp; /**< The current address in EEPROM */
int _ep; /**< The current entry address in EEPROM */ int _ep; /**< The current entry address in EEPROM */
@ -127,9 +142,9 @@ class AutoConnectCredential : public AutoConnectCredentialBase {
~AutoConnectCredential(); ~AutoConnectCredential();
bool del(const char* ssid) override; bool del(const char* ssid) override;
uint8_t entries(void) override; uint8_t entries(void) override;
int8_t load(const char* ssid, struct station_config* config) override; int8_t load(const char* ssid, station_config_t* config) override;
bool load(int8_t entry, struct station_config* config) override; bool load(int8_t entry, station_config_t* config) override;
bool save(const struct station_config* config) override; bool save(const station_config_t* config) override;
protected: protected:
void _allocateEntry(void) override; /**< Initialize storage for credentials. */ void _allocateEntry(void) override; /**< Initialize storage for credentials. */
@ -138,9 +153,11 @@ class AutoConnectCredential : public AutoConnectCredentialBase {
typedef struct { typedef struct {
String password; String password;
uint8_t bssid[6]; uint8_t bssid[6];
uint8_t dhcp; /**< 1:DHCP, 2:Static IP */
uint32_t ip[5];
} AC_CREDTBODY_t; /**< Credential entry */ } AC_CREDTBODY_t; /**< Credential entry */
typedef std::map<String, AC_CREDTBODY_t> AC_CREDT_t; typedef std::map<String, AC_CREDTBODY_t> AC_CREDT_t;
typedef station_config station_config_t; // typedef station_config station_config_t;
bool _add(const station_config_t* config); /**< Add an entry */ bool _add(const station_config_t* config); /**< Add an entry */
size_t _commit(void); /**< Write back to the nvs */ size_t _commit(void); /**< Write back to the nvs */

@ -2,8 +2,8 @@
* Predefined AutoConnect configuration parameters. * Predefined AutoConnect configuration parameters.
* @file AutoConnectDefs.h * @file AutoConnectDefs.h
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 1.0.0 * @version 1.1.0
* @date 2019-08-15 * @date 2019-10-11
* @copyright MIT license. * @copyright MIT license.
*/ */

@ -2,8 +2,8 @@
* AutoConnect portal site web page implementation. * AutoConnect portal site web page implementation.
* @file AutoConnectPage.h * @file AutoConnectPage.h
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 1.0.2 * @version 1.1.0
* @date 2019-09-17 * @date 2019-10-15
* @copyright MIT license. * @copyright MIT license.
*/ */
@ -38,12 +38,12 @@ const char AutoConnect::_CSS_BASE[] PROGMEM = {
".base-panel{" ".base-panel{"
"margin:0 22px 0 22px" "margin:0 22px 0 22px"
"}" "}"
".base-panel>*>label{" ".base-panel * label :not(.bins){"
"display:inline-block;" "display:inline-block;"
"width:3.0em;" "width:3.0em;"
"text-align:right" "text-align:right"
"}" "}"
".base-panel>*>label.slist{" ".base-panel * .slist{"
"width:auto;" "width:auto;"
"font-size:0.9em;" "font-size:0.9em;"
"margin-left:10px;" "margin-left:10px;"
@ -100,34 +100,33 @@ const char AutoConnect::_CSS_BASE[] PROGMEM = {
/**< non-marked list for UL */ /**< non-marked list for UL */
const char AutoConnect::_CSS_UL[] PROGMEM = { const char AutoConnect::_CSS_UL[] PROGMEM = {
"ul.noorder{" ".noorder,.exp{"
"padding:0;" "padding:0;"
"list-style:none;" "list-style:none;"
"display:table" "display:table"
"}" "}"
"ul.noorder li{" ".noorder li,.exp{"
"display:table-row" "display:table-row-group"
"}" "}"
"ul.noorder>*>label{" ".noorder li label, .exp li *{"
"display:table-cell;" "display:table-cell;"
"width:auto;" "width:auto;"
"margin-right:10px;"
"text-align:right;" "text-align:right;"
"padding:10px 0.5em" "padding:10px 0.5em"
"}" "}"
"ul.noorder input[type=\"checkbox\"]{" ".noorder input[type=\"checkbox\"]{"
"-moz-appearance:checkbox;" "-moz-appearance:checkbox;"
"-webkit-appearance:checkbox" "-webkit-appearance:checkbox"
"}" "}"
"ul.noorder input[type=\"radio\"]{" ".noorder input[type=\"radio\"]{"
"margin-right:0.5em;" "margin-right:0.5em;"
"-moz-appearance:radio;" "-moz-appearance:radio;"
"-webkit-appearance:radio" "-webkit-appearance:radio"
"}" "}"
"ul.noorder input[type=\"text\"]{" ".noorder input[type=\"text\"]{"
"width:auto" "width:auto"
"}" "}"
"ul.noorder input[type=\"text\"]:invalid{" ".noorder input[type=\"text\"]:invalid{"
"background:#fce4d6" "background:#fce4d6"
"}" "}"
}; };
@ -223,7 +222,8 @@ const char AutoConnect::_CSS_INPUT_TEXT[] PROGMEM = {
"color:#D9434E" "color:#D9434E"
"}" "}"
".aux-page label{" ".aux-page label{"
"padding:10px 0.5em" "display:inline;"
"padding:10px 0.5em;"
"}" "}"
}; };
@ -289,7 +289,7 @@ const char AutoConnect::_CSS_SPINNER[] PROGMEM = {
"position:relative;" "position:relative;"
"margin:100px auto" "margin:100px auto"
"}" "}"
".double-bounce1, .double-bounce2{" ".dbl-bounce1, .dbl-bounce2{"
"width:100%;" "width:100%;"
"height:100%;" "height:100%;"
"border-radius:50%;" "border-radius:50%;"
@ -301,7 +301,7 @@ const char AutoConnect::_CSS_SPINNER[] PROGMEM = {
"-webkit-animation:sk-bounce 2.0s infinite ease-in-out;" "-webkit-animation:sk-bounce 2.0s infinite ease-in-out;"
"animation:sk-bounce 2.0s infinite ease-in-out" "animation:sk-bounce 2.0s infinite ease-in-out"
"}" "}"
".double-bounce2{" ".dbl-bounce2{"
"-webkit-animation-delay:-1.0s;" "-webkit-animation-delay:-1.0s;"
"animation-delay:-1.0s" "animation-delay:-1.0s"
"}" "}"
@ -487,10 +487,10 @@ const char AutoConnect::_CSS_LUXBAR[] PROGMEM = {
"white-space:nowrap;" "white-space:nowrap;"
"}" "}"
"}" "}"
".lb-cb:checked+.lb-menu .lb-burger-doublespin span::before{" ".lb-cb:checked+.lb-menu .lb-burger-dblspin span::before{"
"transform:rotate(225deg)" "transform:rotate(225deg)"
"}" "}"
".lb-cb:checked+.lb-menu .lb-burger-doublespin span::after{" ".lb-cb:checked+.lb-menu .lb-burger-dblspin span::after{"
"transform:rotate(-225deg)" "transform:rotate(-225deg)"
"}" "}"
".lb-menu-material," ".lb-menu-material,"
@ -525,7 +525,7 @@ const char AutoConnect::_ELM_MENU_PRE[] PROGMEM = {
"<ul class=\"lb-navigation\">" "<ul class=\"lb-navigation\">"
"<li class=\"lb-header\">" "<li class=\"lb-header\">"
"<a href=\"" AUTOCONNECT_URI "\" class=\"lb-brand\">MENU_TITLE</a>" "<a href=\"" AUTOCONNECT_URI "\" class=\"lb-brand\">MENU_TITLE</a>"
"<label class=\"lb-burger lb-burger-doublespin\" id=\"lb-burger\" for=\"lb-cb\"><span></span></label>" "<label class=\"lb-burger lb-burger-dblspin\" id=\"lb-burger\" for=\"lb-cb\"><span></span></label>"
"</li>" "</li>"
"<li class=\"lb-item\"><a href=\"" AUTOCONNECT_URI_CONFIG "\">" AUTOCONNECT_MENULABEL_CONFIGNEW "</a></li>" "<li class=\"lb-item\"><a href=\"" AUTOCONNECT_URI_CONFIG "\">" AUTOCONNECT_MENULABEL_CONFIGNEW "</a></li>"
"<li class=\"lb-item\"><a href=\"" AUTOCONNECT_URI_OPEN "\">" AUTOCONNECT_MENULABEL_OPENSSIDS "</a></li>" "<li class=\"lb-item\"><a href=\"" AUTOCONNECT_URI_OPEN "\">" AUTOCONNECT_MENULABEL_OPENSSIDS "</a></li>"
@ -683,18 +683,29 @@ const char AutoConnect::_PAGE_CONFIGNEW[] PROGMEM = {
"<label for=\"passphrase\">Passphrase</label>" "<label for=\"passphrase\">Passphrase</label>"
"<input id=\"passphrase\" type=\"password\" name=\"" AUTOCONNECT_PARAMID_PASS "\" placeholder=\"Passphrase\">" "<input id=\"passphrase\" type=\"password\" name=\"" AUTOCONNECT_PARAMID_PASS "\" placeholder=\"Passphrase\">"
"</li>" "</li>"
"<br><li><input type=\"submit\" value=\"Apply\"></li>" "<li>"
"<label for=\"dhcp\">Enable DHCP</label>"
"<input id=\"dhcp\" type=\"checkbox\" name=\"dhcp\" value=\"en\" checked onclick=\"vsw(this.checked);\">"
"</li>"
"{{CONFIG_IP}}"
"<li><input type=\"submit\" value=\"Apply\"></li>"
"</ul>" "</ul>"
"</form>" "</form>"
"</div>" "</div>"
"</div>" "</div>"
"</body>"
"<script type=\"text/javascript\">" "<script type=\"text/javascript\">"
"function onFocus(value){" "window.onload=function(){"
"document.getElementById('ssid').value=value;" "['" AUTOCONNECT_PARAMID_STAIP "','" AUTOCONNECT_PARAMID_GTWAY "','" AUTOCONNECT_PARAMID_NTMSK "','" AUTOCONNECT_PARAMID_DNS1 "','" AUTOCONNECT_PARAMID_DNS2 "'].forEach(function(n,o,t){"
"document.getElementById('passphrase').focus();" "io=document.getElementById(n),io.placeholder='0.0.0.0',io.pattern='^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'});"
"vsw(true)};"
"function onFocus(e){"
"document.getElementById('ssid').value=e,document.getElementById('passphrase').focus()"
"}"
"function vsw(e){"
"var t;t=e?'none':'table-row';for(const e of document.getElementsByClassName('exp'))e.style.display=t;e||document.getElementById('sip').focus()"
"}" "}"
"</script>" "</script>"
"</body>"
"</html>" "</html>"
}; };
@ -740,8 +751,8 @@ const char AutoConnect::_PAGE_CONNECTING[] PROGMEM = {
"{{MENU_PRE}}" "{{MENU_PRE}}"
"{{MENU_POST}}" "{{MENU_POST}}"
"<div class=\"spinner\">" "<div class=\"spinner\">"
"<div class=\"double-bounce1\"></div>" "<div class=\"dbl-bounce1\"></div>"
"<div class=\"double-bounce2\"></div>" "<div class=\"dbl-bounce2\"></div>"
"<div style=\"position:absolute;left:-100%;right:-100%;text-align:center;margin:10px auto;font-weight:bold;color:#0b0b33;\">{{CUR_SSID}}</div>" "<div style=\"position:absolute;left:-100%;right:-100%;text-align:center;margin:10px auto;font-weight:bold;color:#0b0b33;\">{{CUR_SSID}}</div>"
"</div>" "</div>"
"</div>" "</div>"
@ -995,15 +1006,17 @@ String AutoConnect::_token_WIFI_STATUS(PageArgument& args) {
String AutoConnect::_token_STATION_STATUS(PageArgument& args) { String AutoConnect::_token_STATION_STATUS(PageArgument& args) {
AC_UNUSED(args); AC_UNUSED(args);
const char* wlStatusSymbol =""; PGM_P wlStatusSymbol = PSTR("");
static const char* wlStatusSymbols[] = { // const char* wlStatusSymbol ="";
PGM_P wlStatusSymbols[] = {
// static const char* wlStatusSymbols[] = {
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
"IDLE", PSTR("IDLE"),
"CONNECTING", PSTR("CONNECTING"),
"WRONG_PASSWORD", PSTR("WRONG_PASSWORD"),
"NO_AP_FOUND", PSTR("NO_AP_FOUND"),
"CONNECT_FAIL", PSTR("CONNECT_FAIL"),
"GOT_IP" PSTR("GOT_IP")
}; };
switch (wifi_station_get_connect_status()) { switch (wifi_station_get_connect_status()) {
case STATION_IDLE: case STATION_IDLE:
@ -1025,14 +1038,14 @@ String AutoConnect::_token_STATION_STATUS(PageArgument& args) {
wlStatusSymbol = wlStatusSymbols[5]; wlStatusSymbol = wlStatusSymbols[5];
break; break;
#elif defined(ARDUINO_ARCH_ESP32) #elif defined(ARDUINO_ARCH_ESP32)
"IDLE", PSTR("IDLE"),
"NO_SSID_AVAIL", PSTR("NO_SSID_AVAIL"),
"SCAN_COMPLETED", PSTR("SCAN_COMPLETED"),
"CONNECTED", PSTR("CONNECTED"),
"CONNECT_FAILED", PSTR("CONNECT_FAILED"),
"CONNECTION_LOST", PSTR("CONNECTION_LOST"),
"DISCONNECTED", PSTR("DISCONNECTED"),
"NO_SHIELD" PSTR("NO_SHIELD")
}; };
switch (_rsConnect) { switch (_rsConnect) {
case WL_IDLE_STATUS: case WL_IDLE_STATUS:
@ -1061,7 +1074,7 @@ String AutoConnect::_token_STATION_STATUS(PageArgument& args) {
break; break;
#endif #endif
} }
return String("(") + String(_rsConnect) + String(") ") + String(wlStatusSymbol); return String("(") + String(_rsConnect) + String(") ") + String(FPSTR(wlStatusSymbol));
} }
String AutoConnect::_token_LOCAL_IP(PageArgument& args) { String AutoConnect::_token_LOCAL_IP(PageArgument& args) {
@ -1143,11 +1156,27 @@ String AutoConnect::_token_LIST_SSID(PageArgument& args) {
_scanCount = WiFi.scanNetworks(false, true); _scanCount = WiFi.scanNetworks(false, true);
AC_DBG("%d network(s) found\n", (int)_scanCount); AC_DBG("%d network(s) found\n", (int)_scanCount);
} }
// Preapre SSID list content building buffer
size_t bufSize = 192 * (_scanCount > AUTOCONNECT_SSIDPAGEUNIT_LINES ? AUTOCONNECT_SSIDPAGEUNIT_LINES : _scanCount);
bufSize += 88 * (_scanCount > AUTOCONNECT_SSIDPAGEUNIT_LINES ? (_scanCount > (AUTOCONNECT_SSIDPAGEUNIT_LINES * 2) ? 2 : 1) : 0);
char* ssidList = (char*)malloc(bufSize);
if (!ssidList) {
AC_DBG("ssidList buffer(%d) allocation failed\n", (int)bufSize);
return _emptyString;
}
AC_DBG_DUMB("\n");
// Locate to the page and build SSD list content. // Locate to the page and build SSD list content.
String ssidList = String(""); static const char _ssidList[] PROGMEM =
"<input type=\"button\" onClick=\"onFocus(this.getAttribute('value'))\" value=\"%s\">"
"<label class=\"slist\">%d&#037;&ensp;Ch.%d</label>%s<br>";
static const char _ssidEnc[] PROGMEM =
"<span class=\"img-lock\"></span>";
static const char _ssidPage[] PROGMEM =
"<button type=\"submit\" name=\"page\" value=\"%d\" formaction=\"/_ac/config\">%s</button>&emsp;";
_hiddenSSIDCount = 0; _hiddenSSIDCount = 0;
uint8_t validCount = 0; uint8_t validCount = 0;
uint8_t dispCount = 0; uint8_t dispCount = 0;
char* slBuf = ssidList;
for (uint8_t i = 0; i < _scanCount; i++) { for (uint8_t i = 0; i < _scanCount; i++) {
String ssid = WiFi.SSID(i); String ssid = WiFi.SSID(i);
if (ssid.length() > 0) { if (ssid.length() > 0) {
@ -1156,11 +1185,8 @@ String AutoConnect::_token_LIST_SSID(PageArgument& args) {
// per page in the available SSID list. // per page in the available SSID list.
if (validCount >= page * AUTOCONNECT_SSIDPAGEUNIT_LINES && validCount <= (page + 1) * AUTOCONNECT_SSIDPAGEUNIT_LINES - 1) { if (validCount >= page * AUTOCONNECT_SSIDPAGEUNIT_LINES && validCount <= (page + 1) * AUTOCONNECT_SSIDPAGEUNIT_LINES - 1) {
if (++dispCount <= AUTOCONNECT_SSIDPAGEUNIT_LINES) { if (++dispCount <= AUTOCONNECT_SSIDPAGEUNIT_LINES) {
ssidList += String(F("<input type=\"button\" onClick=\"onFocus(this.getAttribute('value'))\" value=\"")) + ssid + String("\">"); snprintf_P(slBuf, bufSize - (slBuf - ssidList), (PGM_P)_ssidList, ssid.c_str(), AutoConnect::_toWiFiQuality(WiFi.RSSI(i)), WiFi.channel(i), WiFi.encryptionType(i) != ENC_TYPE_NONE ? (PGM_P)_ssidEnc : "");
ssidList += String(F("<label class=\"slist\">")) + String(AutoConnect::_toWiFiQuality(WiFi.RSSI(i))) + String(F("&#037;&ensp;Ch.")) + String(WiFi.channel(i)) + String(F("</label>")); slBuf += strlen(slBuf);
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 // The validCount counts the found SSIDs that is not the Hidden
@ -1171,12 +1197,18 @@ String AutoConnect::_token_LIST_SSID(PageArgument& args) {
_hiddenSSIDCount++; _hiddenSSIDCount++;
} }
// Prepare perv. button // Prepare perv. button
if (page >= 1) 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;")); snprintf_P(slBuf, bufSize - (slBuf - ssidList), (PGM_P)_ssidPage, page - 1, PSTR("Prev."));
slBuf = ssidList + strlen(ssidList);
}
// Prepare next button // Prepare next button
if (validCount > (page + 1) * AUTOCONNECT_SSIDPAGEUNIT_LINES) 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;")); snprintf_P(slBuf, bufSize - (slBuf - ssidList), (PGM_P)_ssidPage, page + 1, PSTR("Next"));
return ssidList; }
// return ssidList;
String ssidListStr = String(ssidList);
free(ssidList);
return ssidListStr;
} }
String AutoConnect::_token_SSID_COUNT(PageArgument& args) { String AutoConnect::_token_SSID_COUNT(PageArgument& args) {
@ -1189,12 +1221,57 @@ String AutoConnect::_token_HIDDEN_COUNT(PageArgument& args) {
return String(_hiddenSSIDCount); return String(_hiddenSSIDCount);
} }
String AutoConnect::_token_CONFIG_STAIP(PageArgument& args) {
AC_UNUSED(args);
static const char _configIPList[] PROGMEM =
"<li class=\"exp\">"
"<label for=\"%s\">%s</label>"
"<input id=\"%s\" type=\"text\" name=\"%s\" value=\"%s\">"
"</li>";
struct _reps {
PGM_P lid;
PGM_P lbl;
} static const reps[] = {
{ PSTR(AUTOCONNECT_PARAMID_STAIP), PSTR("IP Address") },
{ PSTR(AUTOCONNECT_PARAMID_GTWAY), PSTR("Gateway") },
{ PSTR(AUTOCONNECT_PARAMID_NTMSK), PSTR("Netmask") },
{ PSTR(AUTOCONNECT_PARAMID_DNS1), PSTR("DNS1") },
{ PSTR(AUTOCONNECT_PARAMID_DNS2), PSTR("DNS2") }
};
char liCont[600];
char* liBuf = liCont;
for (uint8_t i = 0; i < 5; i++) {
IPAddress* ip;
if (i == 0)
ip = &_apConfig.staip;
else if (i == 1)
ip = &_apConfig.staGateway;
else if (i == 2)
ip = &_apConfig.staNetmask;
else if (i == 3)
ip = &_apConfig.dns1;
else if (i == 4)
ip = &_apConfig.dns2;
String ipStr = *ip ? ip->toString() : String(F("0.0.0.0"));
snprintf_P(liBuf, sizeof(liCont) - (liBuf - liCont), (PGM_P)_configIPList, reps[i].lid, reps[i].lbl, reps[i].lid, reps[i].lid, ipStr.c_str());
liBuf += strlen(liBuf);
}
return String(liCont);
}
String AutoConnect::_token_OPEN_SSID(PageArgument& args) { String AutoConnect::_token_OPEN_SSID(PageArgument& args) {
AC_UNUSED(args); AC_UNUSED(args);
AutoConnectCredential credit(_apConfig.boundaryOffset); static const char _ssidList[] PROGMEM = "<input id=\"sb\" type=\"submit\" name=\"%s\" value=\"%s\"><label class=\"slist\">%s</label>%s<br>";
struct station_config entry; static const char _ssidRssi[] PROGMEM = "%d&#037;&ensp;Ch.%d";
static const char _ssidNA[] PROGMEM = "N/A";
static const char _ssidLock[] PROGMEM = "<span class=\"img-lock\"></span>";
static const char _ssidNull[] PROGMEM = "";
String ssidList; String ssidList;
String rssiSym; station_config_t entry;
char slCont[176];
char rssiCont[32];
AutoConnectCredential credit(_apConfig.boundaryOffset);
uint8_t creEntries = credit.entries(); uint8_t creEntries = credit.entries();
if (creEntries > 0) { if (creEntries > 0) {
@ -1205,20 +1282,23 @@ String AutoConnect::_token_OPEN_SSID(PageArgument& args) {
ssidList = String(F("<p><b>No saved credentials.</b></p>")); ssidList = String(F("<p><b>No saved credentials.</b></p>"));
for (uint8_t i = 0; i < creEntries; i++) { for (uint8_t i = 0; i < creEntries; i++) {
rssiCont[0] = '\0';
PGM_P rssiSym = _ssidNA;
PGM_P ssidLock = _ssidNull;
credit.load(i, &entry); credit.load(i, &entry);
AC_DBG("A credential #%d loaded\n", (int)i); AC_DBG("A credential #%d loaded\n", (int)i);
ssidList += String(F("<input id=\"sb\" type=\"submit\" name=\"" AUTOCONNECT_PARAMID_CRED "\" value=\"")) + String(reinterpret_cast<char*>(entry.ssid)) + String(F("\"><label class=\"slist\">"));
rssiSym = String(F("N/A</label>"));
for (int8_t sc = 0; sc < (int8_t)_scanCount; sc++) { for (int8_t sc = 0; sc < (int8_t)_scanCount; sc++) {
if (!memcmp(entry.bssid, WiFi.BSSID(sc), sizeof(station_config::bssid))) { if (!memcmp(entry.bssid, WiFi.BSSID(sc), sizeof(station_config_t::bssid))) {
_connectCh = WiFi.channel(sc); _connectCh = WiFi.channel(sc);
rssiSym = String(AutoConnect::_toWiFiQuality(WiFi.RSSI(sc))) + String(F("&#037;&ensp;Ch.")) + String(_connectCh) + String(F("</label>")); snprintf_P(rssiCont, sizeof(rssiCont), (PGM_P)_ssidRssi, AutoConnect::_toWiFiQuality(WiFi.RSSI(sc)), _connectCh);
rssiSym = rssiCont;
if (WiFi.encryptionType(sc) != ENC_TYPE_NONE) if (WiFi.encryptionType(sc) != ENC_TYPE_NONE)
rssiSym += String(F("<span class=\"img-lock\"></span>")); ssidLock = _ssidLock;
break; break;
} }
} }
ssidList += rssiSym + String(F("<br>")); snprintf_P(slCont, sizeof(slCont), (PGM_P)_ssidList, AUTOCONNECT_PARAMID_CRED, reinterpret_cast<char*>(entry.ssid), rssiSym, ssidLock);
ssidList += String(slCont);
} }
return ssidList; return ssidList;
} }
@ -1240,7 +1320,7 @@ String AutoConnect::_token_BOOTURI(PageArgument& args) {
String AutoConnect::_token_CURRENT_SSID(PageArgument& args) { String AutoConnect::_token_CURRENT_SSID(PageArgument& args) {
AC_UNUSED(args); AC_UNUSED(args);
char ssid_c[sizeof(station_config::ssid) + 1]; char ssid_c[sizeof(station_config_t::ssid) + 1];
*ssid_c = '\0'; *ssid_c = '\0';
strncat(ssid_c, reinterpret_cast<char*>(_credential.ssid), sizeof(ssid_c) - 1); strncat(ssid_c, reinterpret_cast<char*>(_credential.ssid), sizeof(ssid_c) - 1);
String ssid = String(ssid_c); String ssid = String(ssid_c);
@ -1307,6 +1387,7 @@ PageElement* AutoConnect::_setupPage(String uri) {
elm->addToken(String(FPSTR("LIST_SSID")), std::bind(&AutoConnect::_token_LIST_SSID, 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("SSID_COUNT")), std::bind(&AutoConnect::_token_SSID_COUNT, this, std::placeholders::_1));
elm->addToken(String(FPSTR("HIDDEN_COUNT")), std::bind(&AutoConnect::_token_HIDDEN_COUNT, this, std::placeholders::_1)); elm->addToken(String(FPSTR("HIDDEN_COUNT")), std::bind(&AutoConnect::_token_HIDDEN_COUNT, this, std::placeholders::_1));
elm->addToken(String(FPSTR("CONFIG_IP")), std::bind(&AutoConnect::_token_CONFIG_STAIP, this, std::placeholders::_1));
} }
else if (uri == String(AUTOCONNECT_URI_CONNECT)) { else if (uri == String(AUTOCONNECT_URI_CONNECT)) {

@ -2,8 +2,8 @@
* AutoConnect portal site web page declaration. * AutoConnect portal site web page declaration.
* @file AutoConnectPage.h * @file AutoConnectPage.h
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 1.0.0 * @version 1.1.0
* @date 2019-08-15 * @date 2019-10-11
* @copyright MIT license. * @copyright MIT license.
*/ */
@ -15,6 +15,12 @@
#define AUTOCONNECT_PARAMID_SSID "SSID" #define AUTOCONNECT_PARAMID_SSID "SSID"
#define AUTOCONNECT_PARAMID_PASS "Passphrase" #define AUTOCONNECT_PARAMID_PASS "Passphrase"
#define AUTOCONNECT_PARAMID_CRED "Credential" #define AUTOCONNECT_PARAMID_CRED "Credential"
#define AUTOCONNECT_PARAMID_DHCP "dhcp"
#define AUTOCONNECT_PARAMID_STAIP "sip"
#define AUTOCONNECT_PARAMID_GTWAY "gw"
#define AUTOCONNECT_PARAMID_NTMSK "nm"
#define AUTOCONNECT_PARAMID_DNS1 "ns1"
#define AUTOCONNECT_PARAMID_DNS2 "ns2"
// AutoConnect menu hyper-link as image // AutoConnect menu hyper-link as image
#define AUTOCONNECT_GLYPH_COG_16 "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAA" \ #define AUTOCONNECT_GLYPH_COG_16 "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAA" \

@ -405,7 +405,7 @@ String AutoConnectUpdateAct::_onCatalog(AutoConnectAux& catalog, PageArgument& a
if (parse) { if (parse) {
#ifdef AC_DEBUG #ifdef AC_DEBUG
AC_DBG_DUMB("\n"); AC_DBG_DUMB("\n");
ARDUINOJSON_PRINT(jb, AC_DEBUG_PORT); ARDUINOJSON_PRINT(json, AC_DEBUG_PORT);
#endif #endif
// Register only bin type file name as available sketch binary to // Register only bin type file name as available sketch binary to
// AutoConnectRadio value based on the response from the update server. // AutoConnectRadio value based on the response from the update server.

@ -14,7 +14,7 @@
// Define the AUTOCONNECT_URI_UPDATE page to select the sketch binary // Define the AUTOCONNECT_URI_UPDATE page to select the sketch binary
// for update and order update execution. // for update and order update execution.
const AutoConnectUpdateAct::ACElementProp_t AutoConnectUpdateAct::_elmCatalog[] PROGMEM = { const AutoConnectUpdateAct::ACElementProp_t AutoConnectUpdateAct::_elmCatalog[] PROGMEM = {
{ AC_Element, "binSty", "<style type=\"text/css\">.bins{display:grid;font-size:14px;grid-gap:10px 0;grid-template-columns:1em repeat(4,max-content);overflow-x:auto}.bins input[type=radio]{-moz-appearance:radio;-webkit-appearance:radio;margin:0;vertical-align:middle}.noorder .bins label,span{margin:0 .5em 0 .5em;padding:0;text-align:left}</style>", nullptr }, { AC_Element, "binSty", "<style type=\"text/css\">.bins{display:grid;font-size:14px;grid-gap:10px 0;grid-template-columns:1em repeat(4,max-content);overflow-x:auto}.bins input[type=radio]{-moz-appearance:radio;-webkit-appearance:radio;margin:0;vertical-align:middle}.noorder .bins label,.bins span{margin:0 .5em 0 .5em;padding:0;text-align:left}</style>", nullptr },
{ AC_Text, "caption", nullptr, nullptr }, { AC_Text, "caption", nullptr, nullptr },
{ AC_Element, "c1", "<div class=\"bins\">", nullptr }, { AC_Element, "c1", "<div class=\"bins\">", nullptr },
{ AC_Radio, "firmwares", nullptr, nullptr }, { AC_Radio, "firmwares", nullptr, nullptr },

Loading…
Cancel
Save