diff --git a/README.md b/README.md index 4c006bf..83779c3 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,10 @@ Full documentation is available on https://Hieromon.github.io/AutoConnect, some ## Change log +### [1.1.5] Apr. 1, 2020 +- Supports AutoConnect menu configuration. +- Changed the bootUri behavior to be an automatic pop-up at the captive portal. (PR #181) + ### [1.1.4] Feb. 14, 2020 - Supports for overriding text of the menu items with user-defined labels. - Fixed the compiler warning with experimental WiFi mode of ESP8266. diff --git a/examples/MyLabels/mylabels.h b/examples/MyLabels/mylabels.h index 1327d75..cbfbf8d 100644 --- a/examples/MyLabels/mylabels.h +++ b/examples/MyLabels/mylabels.h @@ -62,6 +62,11 @@ //#define AUTOCONNECT_BUTTONLABEL_RESET "NEW_STRING_YOU_WISH" //#endif // !AUTOCONNECT_BUTTONLABEL_RESET +// Button label: UPDATE +//#ifndef AUTOCONNECT_BUTTONLABEL_UPDATE +//#define AUTOCONNECT_BUTTONLABEL_UPDATE "NEW_STRING_YOU_WISH" +//#endif // !AUTOCONNECT_BUTTONLABEL_UPDATE + // Page title: Page not found //#ifdef AUTOCONNECT_PAGETITLE_NOTFOUND //#undef AUTOCONNECT_PAGETITLE_NOTFOUND @@ -212,6 +217,26 @@ //#define AUTOCONNECT_PAGETITLE_CREDENTIALS "NEW_STRING_YOU_WISH" //#endif // !AUTOCONNECT_PAGETITLE_CREDENTIALS +// Text: The update page caption +//#ifndef AUTOCONNECT_TEXT_UPDATINGFIRMWARE +//#define AUTOCONNECT_TEXT_UPDATINGFIRMWARE "NEW_STRING_YOU_WISH" +//#endif // !AUTOCONNECT_TEXT_UPDATINGFIRMWARE + +// Text: The update page's file selection button label +//#ifndef AUTOCONNECT_TEXT_SELECTFIRMWARE +//#define AUTOCONNECT_TEXT_SELECTFIRMWARE "NEW_STRING_YOU_WISH" +//#endif // !AUTOCONNECT_TEXT_SELECTFIRMWARE + +// Text: OTA success +//#ifndef AUTOCONNECT_TEXT_OTASUCCESS +//#define AUTOCONNECT_TEXT_OTASUCCESS "NEW_STRING_YOU_WISH" +//#endif // !AUTOCONNECT_TEXT_OTASUCCESS + +// Text: OTA failure +//#ifndef AUTOCONNECT_TEXT_OTAFAILURE +//#define AUTOCONNECT_TEXT_OTAFAILURE "NEW_STRING_YOU_WISH" +//#endif // !AUTOCONNECT_TEXT_OTAFAILURE + // Page title: AutoConnect connecting //#ifdef AUTOCONNECT_PAGETITLE_CONNECTING //#undef AUTOCONNECT_PAGETITLE_CONNECTING diff --git a/keywords.txt b/keywords.txt index e5a0e2b..51b3709 100644 --- a/keywords.txt +++ b/keywords.txt @@ -10,6 +10,7 @@ AutoConnectCheckbox KEYWORD1 AutoConnectElement KEYWORD1 AutoConnectFile KEYWORD1 AutoConnectInput KEYWORD1 +AutoConnectOTA KEYWORD1 AutoConnectRadio KEYWORD1 AutoConnectSelect KEYWORD1 AutoConnectStyle KEYWORD1 @@ -26,10 +27,12 @@ attach KEYWORD2 aux KEYWORD2 config KEYWORD2 begin KEYWORD2 -disable KEYWORD2 +disable KEYWORD2 +disableMenu KEYWORD2 del KEYWORD2 end KEYWORD2 -enable KEYWORD2 +enable KEYWORD2 +enableMenu KEYWORD2 entries KEYWORD2 fetchElement KEYWORD2 getElement KEYWORD2 @@ -68,8 +71,18 @@ AC_Behind LITERAL1 AC_EXIT_AHEAD LITERAL1 AC_EXIT_LATER LITERAL1 AC_EXIT_BOTH LITERAL1 +AC_MENUITEM_NONE LITERAL1 +AC_MENUITEM_CONFIGNEW LITERAL1 +AC_MENUITEM_OPENSSIDS LITERAL1 +AC_MENUITEM_DISCONNECT LITERAL1 +AC_MENUITEM_RESET LITERAL1 +AC_MENUITEM_HOME LITERAL1 +AC_MENUITEM_UPDATE LITERAL1 +AC_MENUITEM_DEVINFO LITERAL1 AC_ONBOOTURI_ROOT LITERAL1 AC_ONBOOTURI_HOME LITERAL1 +AC_OTA_BUILTIN LITERAL1 +AC_OTA_EXTRA LITERAL1 AC_SAVECREDENTIAL_NEVER LITERAL1 AC_SAVECREDENTIAL_AUTO LITERAL1 AC_Button LITERAL1 diff --git a/library.json b/library.json index 90b150c..281a516 100644 --- a/library.json +++ b/library.json @@ -25,6 +25,6 @@ "espressif8266", "espressif32" ], - "version": "1.1.4", + "version": "1.1.5", "license": "MIT" } diff --git a/library.properties b/library.properties index 2ac38c4..0403fc1 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AutoConnect -version=1.1.4 +version=1.1.5 author=Hieromon Ikasamo maintainer=Hieromon Ikasamo sentence=ESP8266/ESP32 WLAN configuration at runtime with web interface. diff --git a/mkdocs.yml b/mkdocs.yml index 878efc5..7114289 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -72,7 +72,7 @@ theme: extra_css: - 'css/paragraph.css' - 'css/extra.css' - - 'https://use.fontawesome.com/releases/v5.6.1/css/all.css' + - 'https://use.fontawesome.com/releases/v5.6.3/css/all.css' extra_javascript: - 'js/gifffer.min.js' extra: diff --git a/mkdocs/achandling.md b/mkdocs/achandling.md index a557e2d..3e7cf21 100644 --- a/mkdocs/achandling.md +++ b/mkdocs/achandling.md @@ -543,7 +543,7 @@ String append(AutoConnectAux& aux, PageArgument& args) { ### How you can reach the values AutoConnectSubmit uses the POST method to send HTTP requests. A value of AutoConnectInput sent to the ESP8266 or ESP32 with POST is stored in the request body of the HTTP request: -``` +```powershell POST /feels HTTP/1.1 Host: ESP8266_IP_ADDRESS name1=value1&name2=value2&name3=value3 diff --git a/mkdocs/acupload.md b/mkdocs/acupload.md index 434ff12..3cb0d08 100644 --- a/mkdocs/acupload.md +++ b/mkdocs/acupload.md @@ -209,7 +209,7 @@ typedef struct { -The upload handler needs to implement processing based on the enumeration value of HTTPUpload.status as **HTTPUploadStatus** enum type. HTTPUploadStatus enumeration is as follows: +An upload handler needs to implement a procedure corresponding with **HTTPUploadStatus** enum value indicated by the uploading process of ESP8266WebServer class, which contained in HTTPUpload.status as following values: - **`UPLOAD_FILE_START`** : Invokes to the \_open. - **`UPLOAD_FILE_WRITE`** : Invokes to the \_write. diff --git a/mkdocs/advancedusage.md b/mkdocs/advancedusage.md index efd9561..e3fb4c2 100644 --- a/mkdocs/advancedusage.md +++ b/mkdocs/advancedusage.md @@ -199,7 +199,50 @@ To implement embedding your legacy web pages to the AutoConnect menu, you can us 5. [Begin](api.md#begin) the portal. 6. Performs [*AutoConnect::handleClient*](api.md#handleClient) in the **loop** function. -For details, see section [Constructing the menu](menuize.md) of Examples page. +```cpp hl_lines="10 28 32" +#include +#include +#include + +ESP8266WebServer server; + +// Declaration for casting legacy page to AutoConnect menu. +// Specifies an uri and the menu label. +AutoConnect portal(server); +AutoConnectAux hello("/hello", "Hello"); // Step #1 as the above procedure + +// Step #2 as the above procedure +// A conventional web page driven by the ESP8266WebServer::on handler. +// This is a legacy. +void handleHello() { + server.send(200, "text/html", String(F( +"" +"" +"Hello, world" +"" + ))); +} + +void setup() { + // Step #3 as the above procedure + // Register the "on" handler as usual to ESP8266WebServer. + // Match this URI with the URI of AutoConnectAux to cast. + server.on("/hello", handleHello); + + // Step #4 as the above procedure + // Joins AutoConnectAux to cast the page via the handleRoot to AutoConnect. + portal.join({ hello }); + portal.begin(); // Step #5 as the above procedure +} + +void loop() { + portal.handleClient(); // Step #6 as the above procedure +} +``` + + + +For more details, see section [Constructing the menu](menuize.md) of Examples page. ### Change menu title @@ -224,7 +267,7 @@ Executing the above sketch will rewrite the menu title for the **FSBrowser** as ### Change the menu labels -You can change the label of the AutoConnect menu item by rewriting the default label letter in [AutoConnectLabels.h](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectLabels.h) macros. However, changing menu items letter influences all the sketch's build scenes. +You can change the label of the AutoConnect menu item by rewriting the default label letter in [AutoConnectLabels.h](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectLabels.h) macros. However, changing menu items letter influences all build scenes for the Sketch. ```cpp #define AUTOCONNECT_MENULABEL_CONFIGNEW "Configure new AP" @@ -234,6 +277,7 @@ You can change the label of the AutoConnect menu item by rewriting the default l #define AUTOCONNECT_MENULABEL_HOME "HOME" #define AUTOCONNECT_BUTTONLABEL_RESET "RESET" ``` +See also: [*Change label text*](changelabel.md) ### Combination with mDNS @@ -307,7 +351,7 @@ By default, the credentials saving area is occupied from the beginning of EEPROM > The following diagram illustrates flash layout used in Arduino environment: -> ``` +> ```powershell > |--------------|-------|---------------|--|--|--|--|--| > ^ ^ ^ ^ ^ > Sketch OTA update File system EEPROM WiFi config (SDK) @@ -443,6 +487,7 @@ AutoConnect will activate SoftAP at failed the first *WiFi.begin*. It SoftAP set - Home URL of the user sketch application. - Menu title. - Ticker signal output. +- Built-in OTA update. !!! note "AutoConnect::config before AutoConnect::begin" *AutoConnect::config* must be executed before *AutoConnect::begin*. @@ -453,6 +498,22 @@ AutoConnect will activate SoftAP at failed the first *WiFi.begin*. It SoftAP set +The sketch HOME path is closely related to the [bootUri](apiconfig.md#booturi) that specifies the access path on module restart. AutoConnect has the following three parameters concerning control the URIs: + +- **AUTOCONNECT_URI** + The **ROOT** of AutoConnect. It is defined in `AutoConnectDefs.h` and is assigned an [AutoConnect statistics screen](menu.md#where-the-from) by default. +- [**AutoConnectConfig::homeUri**](apiconfig.md#homeuri) + It is the hyperlink of listed on the AutoConnect menu list as **HOME**. +- [**AutoConnectConfig::bootUri**](apiconfig.md#booturi) + Which page appears at the captive portal, AUTOCONNECT_URI or the homeUri. Its page will pop up automatically when you visit the captive portal. + +| The definition of **HOME** | Behavior | Specified by | Default value | Possible value | +|---|---|---|---|---| +| **ROOT** of AutoConnect | Default for AC_ONBOOTURI_ROOT | `#define AUTOCONNECT_URI` in `AutoConnectDefs.h` | `/_ac` | URI string | +| **HOME** for Application-specific | Listed on the **menu list** as **HOME**
Also, It may be linked from the **menu title** and is **redundant** with the HOME menu item.
eg. Case of bootURI = AC_ONBOOTURI_HOME | AutoConnectConfig::homeURI | `/` | URI string | +| Which page **loads** at the boot time, ROOT or HOME | Appears after module reboot by **RESET** button with AutoConnect menu | AutoConnectConfig::bootURI | AC_ONBOOTURI_ROOT | AC_ONBOOTURI_HOME | +| Which page **appears** at the captive portal, ROOT or HOME | Auto pop-up | AutoConnectConfig::bootURI | AC_ONBOOTURI_ROOT | AC_ONBOOTURI_HOME | + ### Change SSID and Password for SoftAP An **esp8266ap** is default SSID name for SoftAP of captive portal and password is **12345678** for ESP8266. Similarly, **esp32ap** and **12345678** for ESP32. You can change both by setting [apid](apiconfig.md#apid) and [psk](apiconfig.md#psk). @@ -486,7 +547,7 @@ But this method is not recommended. The broadcast radio of SSID emitted from Sof ### Relocate the AutoConnect home path -A home path of AutoConnect is **/\_ac** by default. You can access from the browser with http://IPADDRESS/\_ac. You can change the home path by revising [**AUTOCONNECT_URI**](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDefs.h#L62) macro in the include header file as [AutoConnectDef.h](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDef.h). +A home path of AutoConnect is **/\_ac** by default. You can access from the browser with http://IPADDRESS/\_ac. You can change the home path by revising [**AUTOCONNECT_URI**](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDefs.h#L69) macro in the include header file as [AutoConnectDef.h](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDef.h). ```cpp #define AUTOCONNECT_URI "/_ac" @@ -581,3 +642,18 @@ NodeMCU 32s | Active-high | 2 | T2 LOLIN32 Pro | Active-low | 5 | SS SparkFun ESP32 Thing | Active-high | 5 Adafruit Feather HUZZAH32 | Active-high | 13 | A12 + +### Built-in OTA update feature + +AutoConnect features a built-in OTA function to update ESP module firmware. You can easily make the Sketch that equips OTA and able to operate with the AutoConnect menu. + + + +[AutoConnectConfig::ota](apiconfig.md#ota) specifies to import the [built-in OTA update class](otabrowser.md) into the Sketch. +See the [Updates with the Web Browser](otabrowser.md) chapter for details. + + diff --git a/mkdocs/api.md b/mkdocs/api.md index 6f8cd4f..956933d 100644 --- a/mkdocs/api.md +++ b/mkdocs/api.md @@ -13,17 +13,22 @@ They contain in ```AutoConnectDefs.h```. ```cpp #define AC_DEBUG // Monitor message output activation #define AC_DEBUG_PORT Serial // Default message output device -#define AUTOCONNECT_AP_IP 0x01F4A8C0 // Default SoftAP IP -#define AUTOCONNECT_AP_GW 0x01F4A8C0 // Default SoftAP Gateway IP +#define AUTOCONNECT_AP_IP 0x011CD9AC // Default SoftAP IP +#define AUTOCONNECT_AP_GW 0x011CD9AC // Default SoftAP Gateway IP #define AUTOCONNECT_AP_NM 0x00FFFFFF // Default subnet mask #define AUTOCONNECT_DNSPORT 53 // Default DNS port at captive portal #define AUTOCONNECT_HTTPPORT 80 // Default HTTP #define AUTOCONNECT_MENU_TITLE "AutoConnect" // Default AutoConnect menu title -#define AUTOCONNECT_STARTUPTIME 10 // Default waiting time[s] for after reset #define AUTOCONNECT_URI "/_ac" // Default AutoConnect root path #define AUTOCONNECT_TIMEOUT 30000 // Default connection timeout[ms] #define AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT 0 // Captive portal timeout value +#define AUTOCONNECT_STARTUPTIME 30 // Default waiting time[s] for after reset #define AUTOCONNECT_USE_JSON // Allow AutoConnect elements to be handled by JSON format +#define AUTOCONNECT_USE_UPDATE // Indicator of whether to use the AutoConnectUpdate feature. +#define AUTOCONNECT_UPDATE_PORT 8000 // Available HTTP port number for the update +#define AUTOCONNECT_UPDATE_TIMEOUT 8000 // HTTP client timeout limitation for the update [ms] +#define AUTOCONNECT_TICKER_PORT LED_BUILTIN // Ticker port +#endif ``` !!! note "Macros placement moved" @@ -110,7 +115,7 @@ bool config(AutoConnectConfig& config) bool config(const char* ap, const char* password = nullptr) ``` -Set SoftAP's WiFi configuration and static IP configuration. +Set SoftAP's WiFi configuration and static IP configuration.
**Parameters**
configReference to [**AutoConnectConfig**](apiconfig.md) containing SoftAP's parameters and static IP parameters.
@@ -121,6 +126,35 @@ Set SoftAP's WiFi configuration and static IP configuration.
falseConfiguration parameter is invalid, some values out of range.
+### enableMenu + +```cpp +void enableMenu(const uint16_t items) +``` + +Enable the [AutoConnect menu](menu.md) items specified by the items parameter with logical OR value using **AC_MENUITEM_t** constant. +
+
**Parameter**
+
itemsSpecify the combined value of **AC_MENUITEM_t** of the items applying to the AutoConnect menu. It provides the value calculated from the **logical OR** by the AC_MENUITEM_t value of each item applied as a menu. AC_MENUITEM_t is enumeration type to identify each menu item and it has the below values.
+: - **AC_MENUITEM_CONFIGNEW** : + [Configure new AP](menu.md#configure-new-ap) +: - **AC_MENUITEM_OPENSSIDS** : + [Open SSIDs](menu.md#open-ssids) +: - **AC_MENUITEM_DISCONNECT** : + [Disconnect](menu.md#disconnect) +: - **AC_MENUITEM_RESET** : + [Reset...](menu.md#reset) +: - **AC_MENUITEM_HOME** : + [HOME](menu.md#home) +: - **AC_MENUITEM_DEVINFO** : + [Device statistics](menu.md#where-the-from) as AutoConnect root page +
+ +!!! note "It is added, not replaced." + The initial configuration of the AutoConnect menu items: + `AC_MENUITEM_CONFIGNEW | AC_MENUITEM_OPENSSIDS | AC_MENUITEM_DISCONNECT | AC_MENUITEM_RESET | AC_MENUITEM_HOME` + The enableMenu function adds an indication of the specified items to the current. Therefore, use the [disableMenu](#disableMenu) to remove the specified item from the initial menu. + ### end ```cpp @@ -132,6 +166,19 @@ Stops AutoConnect captive portal service. Release ESP8266WebServer/WebServer and !!! warning "Attention to end" The end function releases the instance of ESP8266WebServer/WebServer and DNSServer. It can not process them after the end function. + +### disableMenu + +```cpp +void disableMenu(const uint16_t items) +``` + +Disable the [AutoConnect menu](menu.md) items specified by the items parameter with logical OR value using **AC_MENUITEM_t** constant. +
+
**Parameter**
+
itemsSpecify the combined value of **AC_MENUITEM_t** of the items deleting from the AutoConnect menu. It provides the value calculated from the **logical OR** by the AC_MENUITEM_t value of each item. Refer to the [enableMenu](#enablemenu) about AC_MENUITEM_t.
+
+ ### handleClient ```cpp diff --git a/mkdocs/apiaux.md b/mkdocs/apiaux.md index 06749fd..2033906 100644 --- a/mkdocs/apiaux.md +++ b/mkdocs/apiaux.md @@ -188,7 +188,7 @@ Load specified element from JSON document into AutoConnectAux. The JSON document !!! caution "Maybe it is an array" Please note that the JSON document that is the input for loadElement is an array syntax of AutoConnectElements when there are multiple elements. For example, the following JSON document has a syntax error: - ```json + ```js { "name": "Caption", "type": "ACText", diff --git a/mkdocs/apiconfig.md b/mkdocs/apiconfig.md index 83f314a..faadab3 100644 --- a/mkdocs/apiconfig.md +++ b/mkdocs/apiconfig.md @@ -97,7 +97,7 @@ Specify the location to be redirected after module reset in the AutoConnect menu
**Type**
AC_ONBOOTURI_t
**Value**
-
AC_ONBOOTURI_ROOT Resetting the module redirects it to the AutoConnect root path. The root path is assumed to be AUTOCONNECT_URI defined in AutoConnectDefs.h.
+
AC_ONBOOTURI_ROOT Resetting the module redirects it to the AutoConnect root path. The root path is assumed to be AUTOCONNECT_URI defined in [`AutoConnectDefs.h`](api.md#defined-macros).
AC_ONBOOTURI_HOME It is redirected to the URI specified by [**AutoConnectConfig::homeUri**](apiconfig.md#homeuri).
@@ -189,6 +189,31 @@ Disable the first WiFi.begin() and start the captive portal. If this option is e
falseEnable the first WiFi.begin() and it will start captive portal when connection failed. This is default.
+### menuItems + +Configure applying items of the [AutoConnect menu](menu.md). You can arbitrarily combine valid menus by coordinating the menuItems value. +
+
**Type**
+
uint16_tIt provides the combined **AC_MENUITEM_t** value of the item to apply to the AutoConnect menu.
Specify the value calculated from the **logical OR** by the AC_MENUITEM_t value of each item applied as a menu. It affects not only disappear the items from the menu also invalidates the URI they have. As a consequence, even if it accesses the URL directly will occur a 404 error.
The default value is logical OR of AC_MENUITEM_CONFIGNEW, AC_MENUITEM_OPENSSIDS, AC_MENUITEM_DISCONNECT, AC_MENUITEM_RESET, AC_MENUITEM_UPDATE and AC_MENUITEM_HOME.
+
**Value**
+
AC_MENUITEM_NONE No assign items except for the AutoConnectAux page item.
+
AC_MENUITEM_CONFIGNEW Appends [Configure new AP](menu.md#config-new-ap) item.
+
AC_MENUITEM_OPENSSIDS Appends [Open SSIDs](menu.md#open-ssids) item.
+
AC_MENUITEM_DISCONNECT Appends [Disconnect](menu.md#disconnect) item.
+
AC_MENUITEM_RESET Appends [Reset...](menu.md#reset) item.
+
AC_MENUITEM_UPDATE Appends [Update](menu.md#update) item.
+
AC_MENUITEM_HOME Appends [HOME](menu.md#home) item.
+
AC_MENUITEM_DEVINFO Appends the **Device info** item which links to [AutoConnect statistics page](menu.md##where-the-from).
+
+ +!!! info "How to specify the value of the menu items" + An menuItems accepts the logical OR of AC_MENUITEM_t type value. For example, to enable only Open SSIDs and HOME items, specify: + ```cpp + AutoConnectConfig config; + config.menuItems = AC_MENUITEM_OPENSSIDS | AC_MENUITEM_HOME; + ``` + However, even if you specify like the above, the AutoConnectAux page items still display on the menu. To remove the AutoConnectAux items, use the [AutoConnectAux::menu](apiaux.md#menu) function. + ### netmask Sets subnet mask for Soft AP in captive portal. When AutoConnect fails the initial WiFi.begin, it starts the captive portal with the IP address specified this. @@ -197,6 +222,18 @@ Sets subnet mask for Soft AP in captive portal. When AutoConnect fails the initi
IPAddressThe default value is **255.255.255.0**
+### ota + +Specifies to import the built-in OTA update class into the sketch. When this option is enabled, an **Update** item will appear in the AutoConnect menu, and the OTA update via Web browser will be automatically embedded to the Sketch. +
+
**Type**
+
AC_OTA_t
+
**Value**
+
AC_OTA_EXTRA AutoConnect does not import AutoConnectOTA. This is the default.
+
AC_OTA_BUILTIN Specifies to include AutoConnectOTA in the Sketch.
+
+ + ### portalTimeout Specify the timeout value of the captive portal in [ms] units. It is valid when the station is not connected and does not time out if the station is connected to the ESP module in SoftAP mode (i.e. Attempting WiFi connection with the portal function). If 0, the captive portal will not be timed-out. @@ -267,7 +304,7 @@ Set flicker signal output according to WiFi connection status during AutoConnect ### tickerPort -Specifies the GPIO port number to output the flicker signal of the ticker. The default assumes on the board dependent definition LED_BUILTIN macro redefined by **AUTOCONNECT_TICKER_PORT** in `AutoConnectDefs.h`. +Specifies the GPIO port number to output the flicker signal of the ticker. The default assumes on the board dependent definition LED_BUILTIN macro redefined by **AUTOCONNECT_TICKER_PORT** in [`AutoConnectDefs.h`](api.md#defined-macros).
**Type**
uint8_t
diff --git a/mkdocs/apiupdate.md b/mkdocs/apiupdate.md index 4056ca4..d41503c 100644 --- a/mkdocs/apiupdate.md +++ b/mkdocs/apiupdate.md @@ -8,9 +8,9 @@ AutoConnectUpdate(const String& host, const uint16_t port, const String& uri, co
**Parameters**
hostUpdate server address. Specifies IP address or FQDN.
-
portSpecifies HTTP port for the updating process. The default is defined as the **AUTOCONNECT_UPDATE_PORT** macro in the `AutoConnectDefs.h` header file.
+
portSpecifies HTTP port for the updating process. The default is defined as the **AUTOCONNECT_UPDATE_PORT** macro in the [`AutoConnectDefs.h`](api.md#defined-macros) header file.
uriSpecifies a URI on the update server that has deployed available binary sketch files.
-
timeoutSpecifies the maximum response time for the update server. The default is defined as the **AUTOCONNECT_UPDATE_TIMEOUT** macro in the `AutoConnectDefs.h` header file. +
timeoutSpecifies the maximum response time for the update server. The default is defined as the **AUTOCONNECT_UPDATE_TIMEOUT** macro in the [`AutoConnectDefs.h`](api.md#defined-macros) header file.
ledOnActive signal to light the LED ticker during the update. Specifies **HIGH** or **LOW**
@@ -82,7 +82,7 @@ void AutoConnectUpdate::setLedPin(int ledPin, uint8_t ledOn) Sets the port and the ON signal level of the externally connected LED that should act as a ticker during the update process.
**Parameter**
-
ledPinSpecifies the PIN connected external LED for the ticker. The default is defined as the **AUTOCONNECT_TICKER_PORT** macro in the `AutoConnectDefs.h` header file and it is derived from the board-specific **LED_BUILTIN**. By default, the AutoConnectUpdate class does not use the ticker for boards without the LED_BUILTIN definition. If you connect the ticker LED externally, you need to specify the PIN using the [setLedPin](#setledpin) function.
+
ledPinSpecifies the PIN connected external LED for the ticker. The default is defined as the **AUTOCONNECT_TICKER_PORT** macro in the [`AutoConnectDefs.h`](api.md#defined-macros) header file and it is derived from the board-specific **LED_BUILTIN**. By default, the AutoConnectUpdate class does not use the ticker for boards without the LED_BUILTIN definition. If you connect the ticker LED externally, you need to specify the PIN using the [setLedPin](#setledpin) function.
ledOnSpecifies the the ON signal level of the LED PIN port. It is **HIGH** or **LOW**.
@@ -123,7 +123,7 @@ Update server address. Specifies IP address or FQDN. HTTP port for the updating process.
**Type**
-
StringThe default is defined as the **AUTOCONNECT_UPDATE_PORT** macro in the `AutoConnectDefs.h` header file.
+
StringThe default is defined as the **AUTOCONNECT_UPDATE_PORT** macro in the [`AutoConnectDefs.h`](api.md#defined-macros) header file.
### uri diff --git a/mkdocs/changelabel.md b/mkdocs/changelabel.md index 0875425..951a866 100644 --- a/mkdocs/changelabel.md +++ b/mkdocs/changelabel.md @@ -29,13 +29,15 @@ AutoConnect label texts are pre-assigned with a fixed string so that it can be d - + - + + + @@ -64,6 +66,10 @@ AutoConnect label texts are pre-assigned with a fixed string so that it can be d + + + + @@ -88,7 +94,7 @@ You prepare its header file and place it in the `src` folder of the project fold When you store `mylabels.h` containing the new label text definition in the `src` folder, your Arduino project folder structure should look like this: -``` +```javascript |-- |-- <.vscode> diff --git a/mkdocs/changelog.md b/mkdocs/changelog.md index 856e22c..0a63a9a 100644 --- a/mkdocs/changelog.md +++ b/mkdocs/changelog.md @@ -1,3 +1,8 @@ +#### [1.1.5] Apr. 15, 2020 +- Changed the [bootUri behavior](advancedusage.md#assign-user-sketchs-home-path) to be an automatic pop-up at the captive portal. +- Supports AutoConnect [menu configuration](menu.md#applying-the-active-menu-items). +- Supports the built-in OTA feature as [AutoConnectOTA](otabrowser.md#updates-with-the-web-browserupdated-wv115). + #### [1.1.4] Feb. 14, 2020 - Supports for overriding text of the menu items with user-defined labels. - Fixed the compiler warning with experimental WiFi mode of ESP8266. diff --git a/mkdocs/credit.md b/mkdocs/credit.md index 65fd20b..4aefeb5 100644 --- a/mkdocs/credit.md +++ b/mkdocs/credit.md @@ -207,6 +207,6 @@ There may be 0xff as an invalid data in the credential saving area. The 0xff are !!! 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 + ```powershell + esptool -c esp8266 (or esp32) -p [COM_PORT] erase_flash ``` diff --git a/mkdocs/css/paragraph.css b/mkdocs/css/paragraph.css index 7fe9434..0c12c87 100644 --- a/mkdocs/css/paragraph.css +++ b/mkdocs/css/paragraph.css @@ -9,6 +9,7 @@ } .md-typeset pre { + background-color: #272822 !important; font-size: 12px; } diff --git a/mkdocs/datatips.md b/mkdocs/datatips.md index e104d38..cd37bfb 100644 --- a/mkdocs/datatips.md +++ b/mkdocs/datatips.md @@ -149,31 +149,31 @@ Here, represent examples the typical regular expression for the input validation ### URL -``` +```powershell ^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$ ``` ### DNS hostname -``` +```powershell ^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$ ``` ### email address [^2] -``` +```powershell ^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$ ``` ### IP Address -``` +```powershell ^(([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])$ ``` ### Date as MM/DD/YYYY [^3] -``` +```powershell ^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d$ ``` diff --git a/mkdocs/faq.md b/mkdocs/faq.md index ed0daa6..4cabb01 100644 --- a/mkdocs/faq.md +++ b/mkdocs/faq.md @@ -32,7 +32,7 @@ You can avoid a compile error in one of two ways: 1. Disable an AutoConnectUpdate feature if you don't need. - You can disable the AutoConnectUpdate feature by commenting out the **AUTOCONNECT_USE_UPDATE** macro in the `AutoConnectDefs.h` header file. + You can disable the AutoConnectUpdate feature by commenting out the [**AUTOCONNECT_USE_UPDATE**](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDefs.h#L34) macro in the [`AutoConnectDefs.h`](api.md#defined-macros) header file. ```cpp #define AUTOCONNECT_USE_UPDATE ``` @@ -115,7 +115,7 @@ If ESP8266 hang up after reset by AutoConnect menu, perhaps manual reset is not If you received the following message, the boot mode is still sketch uploaded. It needs to the manual reset once. -``` +```powershell ets Jan 8 2013,rst cause:2, boot mode:(1,6) or (1,7) ets Jan 8 2013,rst cause:4, boot mode:(1,6) or (1,7) wdt reset @@ -124,7 +124,7 @@ wdt reset The correct boot mode for starting the sketch is **(3, x)**. !!! info "ESP8266 Boot Messages" - It is described by [ESP8266 Non-OS SDK API Reference](view-source:https://www.espressif.com/en/products/hardware/esp8266ex/resources), section A.5. + It is described by [ESP8266 Non-OS SDK API Reference](https://www.espressif.com/en/products/hardware/esp8266ex/resources), section A.5. | Messages | Description | |----------|-------------| @@ -137,7 +137,7 @@ You can use the [AutoConnect::onDetect](api.md#ondetect) exit routine. For more ## How change HTTP port? -HTTP port number is defined as a macro in [AutoConnectDefs.h](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDefs.h#L112) header file. You can change it directly with several editors and must re-compile. +HTTP port number is defined as a macro in [AutoConnectDefs.h](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDefs.h#L123) header file. You can change it directly with several editors and must re-compile. ```cpp #define AUTOCONNECT_HTTPPORT 80 @@ -154,7 +154,7 @@ To completely remove ArduinoJson at compile-time from the binary, you need to de To exclude ArduinoJson at compile-time, give the following `#define` directive as a compiler option such as the [arduino-cli](https://github.com/arduino/arduino-cli) or [PlatformIO](https://platformio.org/). -``` +```cpp #define AUTOCONNECT_NOUSE_JSON ``` @@ -200,7 +200,7 @@ If the sketch is correct, a JSON syntax error may have occurred. In this case, a ## 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. -``` +```powershell esptool -c esp8266 (or esp32) -p [COM_PORT] erase_flash ``` @@ -216,7 +216,7 @@ Also, you can check the memory running out status by rebuilding the sketch with If the heap memory is insufficient, the following message is displayed on the serial console. -``` +```powershell [PB] Failed building, free heap: ``` diff --git a/mkdocs/images/applymenu.png b/mkdocs/images/applymenu.png new file mode 100644 index 0000000..b5bc7af Binary files /dev/null and b/mkdocs/images/applymenu.png differ diff --git a/mkdocs/images/castmenu.png b/mkdocs/images/castmenu.png new file mode 100644 index 0000000..1110395 Binary files /dev/null and b/mkdocs/images/castmenu.png differ diff --git a/mkdocs/images/menu.png b/mkdocs/images/menu.png index 66f50f0..ddd33ef 100644 Binary files a/mkdocs/images/menu.png and b/mkdocs/images/menu.png differ diff --git a/mkdocs/images/webupdate.gif b/mkdocs/images/webupdate.gif index 9068186..c6bdee5 100644 Binary files a/mkdocs/images/webupdate.gif and b/mkdocs/images/webupdate.gif differ diff --git a/mkdocs/images/webupdate.png b/mkdocs/images/webupdate.png index 6ed86c8..202b319 100644 Binary files a/mkdocs/images/webupdate.png and b/mkdocs/images/webupdate.png differ diff --git a/mkdocs/images/webupdate.svg b/mkdocs/images/webupdate.svg index ae34cff..fe966ea 100644 --- a/mkdocs/images/webupdate.svg +++ b/mkdocs/images/webupdate.svg @@ -30,8 +30,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1" - inkscape:cx="651.92637" - inkscape:cy="34.265665" + inkscape:cx="296.75158" + inkscape:cy="216.8199" inkscape:document-units="mm" inkscape:current-layer="layer1" showgrid="false" @@ -41,8 +41,8 @@ fit-margin-bottom="0" inkscape:window-width="1728" inkscape:window-height="951" - inkscape:window-x="1256" - inkscape:window-y="402" + inkscape:window-x="1435" + inkscape:window-y="57" inkscape:window-maximized="0" inkscape:snap-global="false" units="px" /> @@ -54,7 +54,7 @@ image/svg+xml - + @@ -63,6 +63,17 @@ inkscape:groupmode="layer" id="layer1" transform="translate(-12.547598,-15.546577)"> + ESP8266HTTPUpdateServer + id="tspan926">AutoConnectOTA ESP8266HTTPUpdate - ESP8266 Arduino Core + id="tspan924" + x="66.312286" + y="178.21082">Update class of Arduino core - UPDATE AutoConnectAux + x="47.78421" + y="120.98036" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333333px;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:center;writing-mode:tb;text-anchor:middle;stroke-width:0.26458332;">AutoConnectAux -### Quick and easy to equip the [OTA update feature](otaupdate.md) ENHANCED w/v1.0.0 +### Quick and easy to equip the [OTA update feature](otaupdate.md) UPDATED w/v1.1.5 You can quickly and easily equip the OTA update feature to your sketch and also you can operate the firmware update process via OTA from AutoConnect menu. - + ## Installation diff --git a/mkdocs/menu.md b/mkdocs/menu.md index 5702340..c7fe316 100644 --- a/mkdocs/menu.md +++ b/mkdocs/menu.md @@ -12,12 +12,13 @@ The following screen will appear as the AutoConnect menu when you access to **Au ## Right on top -Currently, AutoConnect supports four menus. Undermost menu as "HOME" returns to the home path of its sketch. +Currently, AutoConnect supports six menus. Undermost menu as "HOME" returns to the home path of its sketch. - **Configure new AP**: Configure SSID and Password for new access point. - **Open SSIDs**: Opens the past SSID which has been established connection from the flash. - **Disconnect**: Disconnects current connection. - **Reset...**: Rest the ESP8266/ESP32 module. +- **Update**: OTA updates. (Optional) - **HOME**: Return to user home page. @@ -43,8 +44,8 @@ After WiFi connected, AutoConnect will automatically save the established SSID a !!! 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 + ```powershell + esptool -c esp8266 (or esp32) -p [COM_PORT] erase_flash ``` ## Disconnect @@ -66,6 +67,13 @@ Resetting the ESP8266/ESP32 module will initiate a reboot. When the module resta 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). +## Update + +If you specify [AutoConnectConfig::ota](apiconfig.md#ota) to import the OTA update feature into Sketch, an item will appear in the menu list as **Update**. + +!!! note "The Update menu item will appear only AutoConnectOTA enabled" + The Update item is displayed automatically in the menu only when [AutoConnectConfig::ota](apiconfig.md#ota) is specified with **AC_OTA_BUILTIN** or [AutoConnectUpdate](otaserver.md#how-to-embed-autoconnectupdate-to-your-sketch) is attached. + ## HOME 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. @@ -76,6 +84,38 @@ A **HOME** item at the bottom of the menu list is a link to the home path, and t 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. +## Applying the active menu items + +Each of the above menu items can be configured with a Sketch. [AutoConnectConfig::menuItems](apiconfig.md#menuitems) specifies the menu items that will be enabled at runtime. You can also adjust available menu items using [AutoConnect::enableMenu](api.md#enablemenu) and [AutoConnect::disableMenu](api.md#disablemenu) function. It is an alternative to [AutoConnectConfig::menuItems](apiconfig.md#menuitems) and provides a shortcut to avoid using AutoConnectConfig. +For example, by disabling the [Configure new AP](#configure-new-ap) and [Disconnect](#disconnect) item, you can prevent the configuration for unknown access points. + +```cpp +AutoConnect portal; +AutoConnectConfig config; + +void setup() { + config.menuItems = AC_MENUITEM_OPENSSIDS | AC_MENUITEM_RESET | AC_MENUITEM_HOME; + portal.config(config); +} +``` + +The next is another way to achieve the same effect. + +```cpp +AutoConnect portal; + +void setup() { + portal.disableMenu(AC_MENUITEM_CONFIGNEW | AC_MENUITEM_DISCONNECT); + portal.config(config); +} +``` + +The result of executing the above Sketch is as below: + + + +Details for [AutoConnectConfig::menuItems](apiconfig.md#menuitems). + ## Attaching to AutoConnect menu 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. diff --git a/mkdocs/otabrowser.md b/mkdocs/otabrowser.md index f4da8da..f71f601 100644 --- a/mkdocs/otabrowser.md +++ b/mkdocs/otabrowser.md @@ -1,21 +1,141 @@ -## Updates with the Web Browser +## Updates with the Web Browser UPDATED w/v1.1.5 -You can implement the user sketch as described in the [ESP8266 Arduino Core documentation](https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#implementation-overview) to realize using the web browser as an update client. By incorporating the ESP8266HTTPUpdateServer class into AutoConnect, you can operate the dialog page for selecting the updating binary sketch file owned by ESP8266HTTPUpdateServer from the AutoConnect menu. +AutoConnect features a built-in OTA function to update ESP module firmware. You can easily make the Sketch that equips OTA and able to operate with the AutoConnect menu. As the **AutoConnectOTA** class, which is compliant with OTA updates using a web browser as described in the [ESP8266 Arduino Core documentation](https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#implementation-overview). -Update feature with a web browser is implemented using ESP8266HTTPUpdateServer class and ESP8266mDNS class. However, **ESP32 Arduino core does not provide a class implementation equivalent to ESP8266HTTPUpdateServer**. Therefore, it is necessary to implement an HTTPUpdateServer class for ESP32 to realize the update using a Web browser. **The AutoConnect library includes an implementation of the HTTPUpdateServer class for ESP32 to make it easy for you to experience**. [^1] +You will be able to import the AutoConnectOTA class into your sketch just by specifying [AutoConnectConfig::ota](apiconfig.md#ota). By incorporating the AutoConnectOTA class into your Sketch, you can have an OTA updating feature which able to updating binary sketch from the AutoConnect menu. -[^1]: You can find the implementation of the **HTTPUpdateServer** class in the **WebUpdate** folder included in the **AutoConnect library examples folder**. + + +The AutoConnectOTA feature is implemented based on the [Updater class](https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#updater-class) of the ESP8266 arduino core library. Its Updater class is also supported by the ESP32 Arduino core, so you can commonly import AutoConnectOTA into the Sketch without being aware of the differences between ESP8266 and ESP32 modules. -!!! warning "For the client devices equipped with Android OS" - Depending on the state of Android OS configuration, Bonjour service may not be incorporated. This method does not work with some Android devices as the client. +!!! info "Limitation of AutoConnectOTA with authentication" + AutoConnectOTA does not support authentication in v1.1.5 yet. It is planned for inclusion in AutoConnect v1.2.0, which will support HTTP authentication. + +### How to embed AutoConnectOTA in your sketch + +To embed the AutoConnectOTA class into your sketch, basically follow these steps: + +1. Include `ESP8266WiFi.h`, `ESP8266WebServer.h` and `AutoConnect.h` as usual.[^1] +2. Declare an ESP8266WebServer object. It's optional. (as WebServer for ESP32) +3. Declare an AutoConnect object, with an argument as ESP8266WebServer if separate the declarations. +4. Declare an AutoConnectConfig object. +5. Declare an AutoConnectAux object for your sketch own if needed. +6. Perform the following procedure steps in the `setup()` function: + 1. Set [AutoConnectConfig::ota](apiconfig.md#ota) to **AC_OTA_BUILTIN** and configure AutoConnect. + 2. Load the AutoConnectAux pages declared in step #4 for your application. + 3. Join these pages to AutoConnect. + 4. Invokes [AutoConnect::begin](api.md#begin) function. +7. Invokes [AutoConnect::handleClient](api.md#handleclient) function in the `loop()`. + +```cpp +#include // Step #1 +#include // Step #1 +#include // Step #1 + +ESP8266WebServer server; // Step #2 +AutoConnect portal(server); // Step #3 +AutoConnectConfig config; // Step #4 +AutoConnectAux hello; // Step #5 + +static const char HELLO_PAGE[] PROGMEM = R"( +{ "title": "Hello world", "uri": "/", "menu": true, "element": [ + { "name": "caption", "type": "ACText", "value": "

Hello, world

", "style": "text-align:center;color:#2f4f4f;padding:10px;" }, + { "name": "content", "type": "ACText", "value": "In this page, place the custom web page handled by the sketch application." } ] +} +)"; // Step #5 + +void setup() { + config.ota = AC_OTA_BUILTIN; // Step #6.a + portal.config(config); // Step #6.a + hello.load(HELLO_PAGE); // Step #6.b + portal.join({ hello }); // Step #6.c + portal.begin(); // Step #6.d +} + +void loop() { + portal.handleClient(); // Step #7 +} +``` + +[^1]:For ESP32, change the following items: + + - Change the include directives appropriately for the ESP32 environment. + - Change ESP8266WebServer to Web. + +!!! faq "How LED ticking during updates" + AutoConnectOTA applies LED ticking during updates automatically. The destination LED port and ticker drive depends on [AutoConnectConfig::tickerPort](apiconfig.md#tickerport) and [AutoConnectConfig::tickerOn](apiconfig.md#tickeron) specifying. + + **IMPORTANT** + The AutoConnectOTA activates the ticker constantly regardless of the [AutoConnectConfig::ticker](apiconfig.md#ticker) value. If you want to stop the ticker output to GPIO during updates, give `0xff` to [AutoConnectConfig::tickerPort](apiconfig.md#tickerport). + +### AutoConnectOTA allocation URI + +AutoConnectOTA has implemented using AutoConnectAUX. So it occupies two URIs by default. An update operation page is assigned to **AUTOCONNECT_URI_UPDATE** and the binary file uploader for the update is assigned to **AUTOCONNECT_URI_UPDATE_ACT**. These symbols are defined in the `AutoConnectDefs.h` header file as follows: + +```cpp +#define AUTOCONNECT_URI "/_ac" +#define AUTOCONNECT_URI_UPDATE AUTOCONNECT_URI "/update" +#define AUTOCONNECT_URI_UPDATE_ACT AUTOCONNECT_URI "/update_act" +``` + +Therefore, the normal Sketch that imports AutoConnectOTA while keeping the default, you cannot use the two URIs `/_ac/update` and `/_ac/update_act` for your specific. If you want to use the URIs for any purpose other than AutoConnectOTA, you need to override the `AutoConnectDefs.h` definition at compile time. It can be overwritten by giving the build flags for platformio.ini as follows with the PlatformIO environment for example. + +```ini +build_flags = + -DAUTOCONNECT_URI_UPDATE='"/YOURURI"' + -DAUTOCONNECT_URI_UPDATE_ACT='"/YOURURIACT"' +``` + +### Timing of AutoConnectOTA instantiation + +It will be born during [AutoConnect::handleClient](api.md#handleclient) process. AutoConnect will evaluate the enabled state of [AutoConnectConfig::ota](apiconfig.md#ota) each time the handleClient is executed, and if OTA is enabled then it creates an AutoConnectAux internally and assigns it to the update page. At this time, AutoConnectOTA is also instantiated together. The generated AUX page containing AutoConnectOTA is bound to AutoConnect inside the AutoConnect::handleClient process. + +If you want to attach AutoConnectOTA dynamically with an external trigger, you can sketch like this: +_This sketch imports the OTA update feature with an external switch assigned to the GPIO pin. While the trigger not occurs, AutoConnect OTA will not be imported into Sketch and will not appear on the menu list._ + +```cpp +#include +#include +#include + +#define TRIGGER 4 // pin assigned to external trigger switch + +AutoConnect portal; +AutoConnectConfig config; + +void setup() { + pinMode(TRIGGER, INPUT); + portal.begin(); +} + +void loop() { + if (digitalRead(TRIGGER) == HIGH) { + config.ota = AC_OTA_BUILTIN; + portal.config(config); + } + portal.handleClient(); +} +``` + +!!! note "AutoConnectOTA **cannot** detach dynamically" + Once imported, AutoConnectOTA cannot be removed from the Sketch. It can be only excluded from the menu by overriding [AutoConnectConfig::menuItems](apiconfig.md#menuitems). In this case, the AutoConnectOTA instance remains as a residue. + +### How to make the binary sketch + +Binary sketch files for updating can be retrieved using the Arduino IDE. Open the **Sketch** menu and select the **Export compiled Binary**, then starts compilation. + + + +When the compilation is complete, a binary sketch will save with the extension `.bin` in the same folder as the sketch. -### How to embed ESP8266HTTPUpdateServer in AutoConnect +### OTA updates w/browser without using AutoConnectOTA +The legacy OTA method based on ESP8266HTTPUpdateServer without AutoConnectOTA is still valid. To embed the ESP8266HTTPUpdateServer class with AutoConnect into your sketch, basically follow these steps: -1. Include `ESP8266mDNS.h` and `ESP8266HTTPUpdateServer.h`, also `WiFiClient.h`, in addition to the usual directives as `ESP8266WebServer.h` and `AutoConnect.h`. +1. Include `ESP8266HTTPUpdateServer.h`, also `WiFiClient.h`, in addition to the usual directives as `ESP8266WebServer.h` and `AutoConnect.h`. 2. Declare an ESP8266WebServer object. (In ESP32, as WebServer) 3. Declare an ESP8266HTTPUpdateServer object. 4. Declare an AutoConnect object with an ESP8266WebServer object as an argument. @@ -28,16 +148,12 @@ To embed the ESP8266HTTPUpdateServer class with AutoConnect into your sketch, ba 2. Load the AutoConnectAux pages declared in step #8 for your application. (Except the update dialog page) 3. Join these pages to AutoConnect along with the update dialog page declared in step #5. 4. Invokes [AutoConnect::begin](api.md#begin) function. - 5. Call the `MDNS.begin` and `MDNS.addServer` functions to start the multi cast DNS service. -10. Perform the following procedure steps in the `loop()` function: - 1. Call the `MDNS.update` function to parse requests for mDNS. (No needed as ESP32) - 2. Invokes [AutoConnect::handleClient](api.md#handleclient) function. +10. Invokes [AutoConnect::handleClient](api.md#handleclient) function in the `loop()`. ```cpp #include #include #include // Step #1 -#include // Step #1 #include // Step #1 #include @@ -56,54 +172,16 @@ AutoConnectAux hello; // Step #8 void setup() { httpUpdate.setup(&httpServer, "USERNAME", "PASSWORD"); // Step #9.a - hello.load(HELLO_PAGE); // Step #9.b - portal.join({ hello, update }); // Step #9.c - if (portal.begin()) { // Step #9.d - if (MDNS.begin("esp-webupdate")) // Step #9.e - MDNS.addService("http", "tcp", 80); // Step #9.e - } + hello.load(HELLO_PAGE); // Step #9.b + portal.join({ hello, update }); // Step #9.c + portal.begin(); // Step #9.d } void loop() { - MDNS.update(); // Step #10.a - portal.handleClient(); // Step #10.b + portal.handleClient(); // Step #10 } ``` -!!! hint "For ESP32" - This procedure is equally applicable to ESP32. If the target module is ESP32, change the following items: - - - Change the include directives appropriately for the ESP32 environment. - - Change ESP8266HTTPUpdaetServer to HTTPUpdateServer using an implementation provided from AutoConnect library example code. - - Remove `MDNS.update` line from the sketch code. - -!!! example "Share an ESP8266WebServer" - AutoConnect shares the ESP8266WebServer instance with the ESP8266HTTPUpdateServer class. You can give the same instance as ESP8266WebServer instance given to AutoConnect to ESP8266HTTPUpdateServer class. - ```cpp - ESP8266WebServer httpServer; - ESP8266HTTPUpdateServer updateServer; - AutoConnect portal(httpServer); - updateServer(&httpServer); - ``` - This sharing specification is the same for ESP32. - -The result of the above sketch should be as follows. [^2] - -[^2]: The authentication dialog is displayed first. - - - -!!! faq "How LED ticking during updates" - You **cannot** get the ticker with LED during updates by using this way. It is since the current implementation of the ESP8266HTTPUpdateServer class of the Arduino core **library does not assign an LED PIN** to the ESP8266HTTPUpdate class. - -### How to make the binary sketch - -Binary sketch files for updating can be retrieved using the Arduino IDE. Open the **Sketch** menu and select the **Export compiled Binary**, then starts compilation. - - - -When the compilation is complete, a binary sketch will save with the extension `.bin` in the same folder as the sketch. - " "" diff --git a/src/AutoConnectDefs.h b/src/AutoConnectDefs.h index 3c407eb..aca44ce 100644 --- a/src/AutoConnectDefs.h +++ b/src/AutoConnectDefs.h @@ -185,7 +185,7 @@ #define AUTOCONNECT_JSONPSRAM_SIZE (16* 1024) #endif // !AUTOCONNECT_JSONPSRAM_SIZE -// Available HTTP port number for the update [ms] +// Available HTTP port number for the update #ifndef AUTOCONNECT_UPDATE_PORT #define AUTOCONNECT_UPDATE_PORT 8000 #endif // !AUTOCONNECT_UPDATE_PORT @@ -207,7 +207,7 @@ // Wait timer for rebooting after updated #ifndef AUTOCONNECT_UPDATE_WAITFORREBOOT -#define AUTOCONNECT_UPDATE_WAITFORREBOOT 9000 +#define AUTOCONNECT_UPDATE_WAITFORREBOOT 15000 #endif // !AUTOCONNECT_UPDATE_WAITFORREBOOT // A signal value that the board dependent LED turns on. diff --git a/src/AutoConnectElementBasisImpl.h b/src/AutoConnectElementBasisImpl.h index 1c6f1c0..ed245b8 100644 --- a/src/AutoConnectElementBasisImpl.h +++ b/src/AutoConnectElementBasisImpl.h @@ -100,7 +100,7 @@ const String AutoConnectFileBasis::toHTML(void) const { /** * Instantiate the upload handler with the specified store type. - * @param store An enumuration value of ACFile_t + * @param store An enumeration value of ACFile_t */ bool AutoConnectFileBasis::attach(const ACFile_t store) { AutoConnectUploadFS* handlerFS; diff --git a/src/AutoConnectElementJson.h b/src/AutoConnectElementJson.h index ad4d06a..07724ae 100644 --- a/src/AutoConnectElementJson.h +++ b/src/AutoConnectElementJson.h @@ -139,7 +139,7 @@ class AutoConnectCheckboxJson : public AutoConnectElementJson, public AutoConnec * @param value A string value entered by the selected file name. * @param label A label string that follows file-select box, optionally. * The label is placed in front of file-select box. - * @param store An enumuration value of store type. + * @param store An enumeration value of store type. */ class AutoConnectFileJson : public AutoConnectElementJson, public AutoConnectFileBasis { public: diff --git a/src/AutoConnectLabels.h b/src/AutoConnectLabels.h index ba80649..c3488c6 100644 --- a/src/AutoConnectLabels.h +++ b/src/AutoConnectLabels.h @@ -2,8 +2,8 @@ * AutoConnect proper menu label constant definition. * @file AutoConnectLabels.h * @author hieromon@gmail.com - * @version 1.1.4 - * @date 2020-02-13 + * @version 1.1.5 + * @date 2020-04-09 * @copyright MIT license. */ @@ -61,12 +61,22 @@ #define AUTOCONNECT_MENULABEL_UPDATE "Update" #endif // !AUTOCONNECT_MENULABEL_UPDATE +// Menu item: Device Info +#ifndef AUTOCONNECT_MENULABEL_DEVINFO +#define AUTOCONNECT_MENULABEL_DEVINFO "Device info" +#endif // !AUTOCONNECT_MENULABEL_DEVINFO + // Button label: RESET #ifndef AUTOCONNECT_BUTTONLABEL_RESET #define AUTOCONNECT_BUTTONLABEL_RESET "RESET" //#define AUTOCONNECT_BUTTONLABEL_RESET "Reboot" #endif // !AUTOCONNECT_BUTTONLABEL_RESET +// Button label: UPDATE +#ifndef AUTOCONNECT_BUTTONLABEL_UPDATE +#define AUTOCONNECT_BUTTONLABEL_UPDATE "UPDATE" +#endif // !AUTOCONNECT_BUTTONLABEL_UPDATE + // Page title: Page not found #ifndef AUTOCONNECT_PAGETITLE_NOTFOUND #define AUTOCONNECT_PAGETITLE_NOTFOUND "Page not found" @@ -217,6 +227,26 @@ #define AUTOCONNECT_TEXT_NOSAVEDCREDENTIALS "No saved credentials." #endif // !AUTOCONNECT_TEXT_NOSAVEDCREDENTIALS +// Text: The update page caption +#ifndef AUTOCONNECT_TEXT_UPDATINGFIRMWARE +#define AUTOCONNECT_TEXT_UPDATINGFIRMWARE "Updating firmware" +#endif // !AUTOCONNECT_TEXT_UPDATINGFIRMWARE + +// Text: The update page's file selection button label +#ifndef AUTOCONNECT_TEXT_SELECTFIRMWARE +#define AUTOCONNECT_TEXT_SELECTFIRMWARE "Select firmware: " +#endif // !AUTOCONNECT_TEXT_SELECTFIRMWARE + +// Text: OTA success +#ifndef AUTOCONNECT_TEXT_OTASUCCESS +#define AUTOCONNECT_TEXT_OTASUCCESS "Successfully updated, rebooting..." +#endif // !AUTOCONNECT_TEXT_OTASUCCESS + +// Text: OTA failure +#ifndef AUTOCONNECT_TEXT_OTAFAILURE +#define AUTOCONNECT_TEXT_OTAFAILURE "Failed to update: " +#endif // !AUTOCONNECT_TEXT_OTAFAILURE + // Menu Text: Connecting #ifndef AUTOCONNECT_MENUTEXT_CONNECTING #define AUTOCONNECT_MENUTEXT_CONNECTING "Connecting" diff --git a/src/AutoConnectOTA.cpp b/src/AutoConnectOTA.cpp new file mode 100644 index 0000000..8a094ec --- /dev/null +++ b/src/AutoConnectOTA.cpp @@ -0,0 +1,229 @@ +/** + * AutoConnectOTA class implementation. + * @file AutoConnectOTA.cpp + * @author hieromon@gmail.com + * @version 1.1.5 + * @date 2020-04-09 + * @copyright MIT license. + */ + +#include +#if defined(ARDUINO_ARCH_ESP8266) +#include +#include +#elif defined(ARDUINO_ARCH_ESP32) +#include +#endif +#include +#include "AutoConnectOTA.h" +#include "AutoConnectOTAPage.h" + +/** + * A destructor. Release the OTA operation pages. + */ +AutoConnectOTA::~AutoConnectOTA() { + _auxUpdate.reset(nullptr); + _auxResult.reset(nullptr); +} + +/** + * Attach the AutoConnectOTA to hosted AutoConnect which constitutes + * the update process. This function creates an OTA operation page as + * AutoConnectAux instance and allows it to receive binary updates. + * @param portal A reference of AutoConnect + */ +void AutoConnectOTA::attach(AutoConnect& portal) { + AutoConnectAux* updatePage; + + updatePage = new AutoConnectAux(String(FPSTR(_pageUpdate.uri)), String(FPSTR(_pageUpdate.title)), _pageUpdate.menu); + _buildAux(updatePage, &_pageUpdate, lengthOf(_elmUpdate)); + _auxUpdate.reset(updatePage); + + updatePage = new AutoConnectAux(String(FPSTR(_pageResult.uri)), String(FPSTR(_pageResult.title)), _pageResult.menu); + _buildAux(updatePage, &_pageResult, lengthOf(_elmResult)); + _auxResult.reset(updatePage); + + _auxResult->on(std::bind(&AutoConnectOTA::_updated, this, std::placeholders::_1, std::placeholders::_2)); + _auxResult->onUpload(*this); + + portal.join(*_auxUpdate.get()); + portal.join(*_auxResult.get()); +} + +/** + * Create the update operation pages using a predefined page structure + * with two structures as ACPage_t and ACElementProp_t which describe + * for AutoConnectAux configuration. + * This function receives instantiated AutoConnectAux, instantiates + * defined AutoConnectElements by ACPage_t, and configures it into + * received AutoConnectAux. + * @param aux An instantiated AutoConnectAux that will configure according to ACPage_t. + * @param page Pre-defined ACPage_t + * @param elementNum Number of AutoConnectElements to configure. + */ +void AutoConnectOTA::_buildAux(AutoConnectAux* aux, const AutoConnectOTA::ACPage_t* page, const size_t elementNum) { + for (size_t n = 0; n < elementNum; n++) { + if (page->element[n].type == AC_Button) { + AutoConnectButton* element = new AutoConnectButton; + element->name = String(FPSTR(page->element[n].name)); + if (page->element[n].value) + element->value = String(FPSTR(page->element[n].value)); + if (page->element[n].peculiar) + element->action = String(FPSTR(page->element[n].peculiar)); + aux->add(reinterpret_cast(*element)); + } + else if (page->element[n].type == AC_Element) { + AutoConnectElement* element = new AutoConnectElement; + element->name = String(FPSTR(page->element[n].name)); + if (page->element[n].value) + element->value = String(FPSTR(page->element[n].value)); + aux->add(reinterpret_cast(*element)); + } + else if (page->element[n].type == AC_File) { + AutoConnectFile* element = new AutoConnectFile; + element->name = String(FPSTR(page->element[n].name)); + element->label = String(FPSTR(page->element[n].peculiar)); + element->store = ACFile_t::AC_File_Extern; + aux->add(reinterpret_cast(*element)); + } + else if (page->element[n].type == AC_Style) { + AutoConnectStyle* element = new AutoConnectStyle; + element->name = String(FPSTR(page->element[n].name)); + if (page->element[n].value) + element->value = String(FPSTR(page->element[n].value)); + aux->add(reinterpret_cast(*element)); + } + else if (page->element[n].type == AC_Text) { + AutoConnectText* element = new AutoConnectText; + element->name = String(FPSTR(page->element[n].name)); + if (page->element[n].value) + element->value = String(FPSTR(page->element[n].value)); + if (page->element[n].peculiar) + element->style = String(FPSTR(page->element[n].peculiar)); + aux->add(reinterpret_cast(*element)); + } + } +} + +/** + * Check the space needed for the update + * This function overrides AutoConnectUploadHandler::_open. + * @param filename An updater bin file name + * @param mode File access mode, but it is not be used. + * @return true Ready for update + * @return false Not enough FLASH space to update. + */ +bool AutoConnectOTA::_open(const char* filename, const char* mode) { + AC_UNUSED(mode); + _binName = String(strchr(filename, '/') + sizeof(char)); +#ifdef ARDUINO_ARCH_ESP8266 + WiFiUDP::stopAll(); +#endif + uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; + // It only supports FLASH as a sketch area for updating. + if (Update.begin(maxSketchSpace, U_FLASH)) { + if (_tickerPort != -1) + pinMode(static_cast(_tickerPort), OUTPUT); + _status = OTA_START; + AC_DBG("%s updating start\n", filename); + return true; + } + _setError(); + return false; +} + +/** + * Writes received updater to the flash. + * This function overrides AutoConnectUploadHandler::_write. + * @param buf Buffer address where received update file was stored. + * @param size Size to be written. + * @return the amount written + */ +size_t AutoConnectOTA::_write(const uint8_t *buf, const size_t size) { + size_t wsz = 0; + if (_tickerPort != -1) + digitalWrite(_tickerPort, digitalRead(_tickerPort) ^ 0x01); + if (!_err.length()) { + _status = OTA_PROGRESS; + wsz = Update.write(const_cast(buf), size); + if (wsz != size) + _setError(); + } + return wsz; +} + +/** + * All bytes are written, this call writes the config to reboot. + * If there is an error this will clear everything. + * This function overrides AutoConnectUploadHandler::_close. + * @param status Updater binary upload completion status. + */ +void AutoConnectOTA::_close(const HTTPUploadStatus status) { + AC_DBG("OTA update"); + if (!_err.length()) { + if (status == UPLOAD_FILE_END) { + if (Update.end(true)) { + _status = OTA_SUCCESS; + AC_DBG_DUMB(" succeeds, turn to reboot"); + } + else { + _setError(); + AC_DBG_DUMB(" flash failed"); + } + } + else { + AC_DBG_DUMB(" aborted"); + } + } + AC_DBG_DUMB(". %s\n", _err.c_str()); + if (_err.length()) + Update.end(false); + if (_tickerPort != -1) + digitalWrite(_tickerPort, !_tickerOn); +} + +/** + * Callback of the update operation page as AutoConnectAux. + * Reflect the flash result of Update class to the page. + * @param result Upload post-process page + * @param args Unused + * @return Empty string + */ +String AutoConnectOTA::_updated(AutoConnectAux& result, PageArgument& args) { + AC_UNUSED(args); + PGM_P stColor; + String st; + + // Build an updating result caption. + // Change the color of the bin name depending on the result of the update. + if (_status == OTA_SUCCESS) { + st = String(F(AUTOCONNECT_TEXT_OTASUCCESS)); + stColor = PSTR("3d7e9a"); + // Notify to the handleClient of loop() thread that it can reboot. + _status = OTA_RIP; + } + else { + st = String(F(AUTOCONNECT_TEXT_OTAFAILURE)) + _err; + stColor = PSTR("e66157"); + } + result["bin"].as().value = _binName; + result["bin"].as().style += String(stColor); + result["result"].as().value = st; + + // AutoConnectOTA result page generates a transition after reboot + // according to the error code from the Update class. By setting the + // error code of the Update class into the rc element, this page will + // automatically GET the homepage of the updated sketch. + result["rc"].value.replace("%d", String(Update.getError())); + return String(""); +} + +/** + * Save the last error + */ +void AutoConnectOTA::_setError(void) { + StreamString eStr; + Update.printError(eStr); + _err = String(eStr.c_str()); + _status = OTA_FAIL; +} diff --git a/src/AutoConnectOTA.h b/src/AutoConnectOTA.h new file mode 100644 index 0000000..2e0d2ef --- /dev/null +++ b/src/AutoConnectOTA.h @@ -0,0 +1,87 @@ +/** + * Declaration of AutoConnectOTA class. + * The AutoConnecOTA class is a class for web updating a Sketch binary + * via OTA and implements with an AutoConnectAux page handler that + * inherits from AutoConnectUploadHandler. + * By overriding the _write function of AutoConnectUploadHandler to + * write the executable binary using the Update class, it can update + * the module firmware in synchronization with the upload of the sketch + * binary file. + * @file AutoConnectOTA.h + * @author hieromon@gmail.com + * @version 1.1.5 + * @date 2020-04-09 + * @copyright MIT license. + */ + +#ifndef _AUTOCONNECTOTA_H_ +#define _AUTOCONNECTOTA_H_ + +#include +#include "AutoConnect.h" +#include "AutoConnectUpload.h" + +class AutoConnectOTA : public AutoConnectUploadHandler { + public: + // Updating process status + typedef enum { + OTA_IDLE, /**< Update process has not started */ + OTA_START, /**< Update process has started */ + OTA_PROGRESS, /**< Update process in progress */ + OTA_SUCCESS, /**< A binary updater has uploaded fine */ + OTA_RIP, /**< Ready for module restart */ + OTA_FAIL /**< Failed to save binary updater by Update class */ + } AC_OTAStatus_t; + + AutoConnectOTA() : _status(OTA_IDLE), _tickerPort(-1), _tickerOn(LOW) {} + ~AutoConnectOTA(); + void attach(AutoConnect& portal); + String error(void) const { return _err; } /**< Returns current error string */ + void menu(const bool post) { _auxUpdate->menu(post); }; /**< Enabel or disable arranging a created AutoConnectOTA page in the menu. */ + AC_OTAStatus_t status(void) const { return _status; } /**< Return current error status of the Update class */ + void setTicker(int8_t pin, uint8_t on) { _tickerPort = pin, _tickerOn = on; } /**< Set ticker LED port */ + + protected: + // Attribute definition of the element to be placed on the update page. + typedef struct { + const ACElement_t type; + const char* name; /**< Name to assign to AutoConnectElement */ + const char* value; /**< Value owned by an element */ + const char* peculiar; /**< Specific ornamentation for the element */ + } ACElementProp_t; + + // Attributes to treat included update pages as AutoConnectAux. + typedef struct { + const char* uri; /**< URI for the page */ + const char* title; /**< Menu title of update page */ + const bool menu; /**< Whether to display in menu */ + const ACElementProp_t* element; + } ACPage_t; + + template constexpr + size_t lengthOf(T(&)[N]) noexcept { return N; } + void _buildAux(AutoConnectAux* aux, const AutoConnectOTA::ACPage_t* page, const size_t elementNum); + bool _open(const char* filename, const char* mode) override; + size_t _write(const uint8_t *buf, const size_t size) override; + void _close(const HTTPUploadStatus status) override; + String _updated(AutoConnectAux& result, PageArgument& args); + + std::unique_ptr _auxUpdate; /**< An update operation page */ + std::unique_ptr _auxResult; /**< An update result page */ + + private: + void _setError(void); + + AC_OTAStatus_t _status; /**< Status for update progress */ + int8_t _tickerPort; /**< GPIO for flicker */ + uint8_t _tickerOn; /**< A signal for flicker turn on */ + String _binName; /**< An updater file name */ + String _err; /**< Occurred error stamp */ + + static const ACPage_t _pageUpdate PROGMEM; + static const ACElementProp_t _elmUpdate[] PROGMEM; + static const ACPage_t _pageResult PROGMEM; + static const ACElementProp_t _elmResult[] PROGMEM; +}; + +#endif // !_AUTOCONNECTOTA_H_ diff --git a/src/AutoConnectOTAPage.h b/src/AutoConnectOTAPage.h new file mode 100644 index 0000000..8a8c67e --- /dev/null +++ b/src/AutoConnectOTAPage.h @@ -0,0 +1,39 @@ +/** + * Define pages to operate updates using the AutoConnectUpdate class. + * @file AutoConnectOTAPage.h + * @author hieromon@gmail.com + * @version 1.1.5 + * @date 2020-04-09 + * @copyright MIT license. + */ + +#ifndef _AUTOCONNECTOTAPAGE_H_ +#define _AUTOCONNECTOTAPAGE_H_ + +const AutoConnectOTA::ACElementProp_t AutoConnectOTA::_elmUpdate[] PROGMEM = { + { AC_Style, "s_rc", ".s_rc{display:none}", nullptr }, + { AC_Text, "cap", "

" AUTOCONNECT_TEXT_UPDATINGFIRMWARE "

", nullptr }, + { AC_File, "bin", nullptr, AUTOCONNECT_TEXT_SELECTFIRMWARE }, + { AC_Button, "update", AUTOCONNECT_BUTTONLABEL_UPDATE, "_upd(this,'bin','" AUTOCONNECT_URI_UPDATE_ACT "')" }, + { AC_Element, "js", "", nullptr } +}; + +// The definition of the OTA update operation page, which will be located to AUTOCONNECT_URI_UPDATE. +const AutoConnectOTA::ACPage_t AutoConnectOTA::_pageUpdate PROGMEM = { + AUTOCONNECT_URI_UPDATE, AUTOCONNECT_MENULABEL_UPDATE, true, AutoConnectOTA::_elmUpdate +}; + +const AutoConnectOTA::ACElementProp_t AutoConnectOTA::_elmResult[] PROGMEM = { + { AC_Text, "bin", nullptr, "margin-bottom:0.5em;font-size:1.2em;font-weight:bold;color:#" }, + { AC_Text, "result", nullptr, nullptr }, + { AC_Element, "rc", "
%d
", nullptr } +}; + +// The definition of the OTA update result display page. +// This page is assigned to AUTOCONNECT_URI_UPDATE_ACT, but the actual +// HTML document is dynamically rewritten on AUTOCONNECT_URI_UPDATE page +// by the JavaScript function included in the _pageUpdate AutoConnectAux. +const AutoConnectOTA::ACPage_t AutoConnectOTA::_pageResult PROGMEM = { + AUTOCONNECT_URI_UPDATE_ACT, AUTOCONNECT_MENULABEL_UPDATE, false, AutoConnectOTA::_elmResult +}; +#endif // !_AUTOCONNECTOTAPAGE_H_ diff --git a/src/AutoConnectPage.cpp b/src/AutoConnectPage.cpp index f69b99a..725e372 100644 --- a/src/AutoConnectPage.cpp +++ b/src/AutoConnectPage.cpp @@ -2,8 +2,8 @@ * AutoConnect portal site web page implementation. * @file AutoConnectPage.h * @author hieromon@gmail.com - * @version 1.1.4 - * @date 2020-02-13 + * @version 1.1.5 + * @date 2020-04-01 * @copyright MIT license. */ @@ -550,13 +550,10 @@ const char AutoConnect::_ELM_MENU_PRE[] PROGMEM = { "
" "" "
" "
" @@ -972,6 +970,12 @@ String AutoConnect::_token_HEAD(PageArgument& args) { String AutoConnect::_token_MENU_PRE(PageArgument& args) { String currentMenu = FPSTR(_ELM_MENU_PRE); + String menuItem = _attachMenuItem(AC_MENUITEM_CONFIGNEW) + + _attachMenuItem(AC_MENUITEM_OPENSSIDS) + + _attachMenuItem(AC_MENUITEM_DISCONNECT) + + _attachMenuItem(AC_MENUITEM_RESET); + currentMenu.replace(String(F("MENU_LIST")), menuItem); + currentMenu.replace(String(F("BOOT_URI")), _getBootUri()); currentMenu.replace(String(F("MENU_TITLE")), _menuTitle); currentMenu.replace(String(F("{{CUR_SSID}}")), _token_ESTAB_SSID(args)); return currentMenu; @@ -987,7 +991,9 @@ String AutoConnect::_token_MENU_AUX(PageArgument& args) { String AutoConnect::_token_MENU_POST(PageArgument& args) { AC_UNUSED(args); String postMenu = FPSTR(_ELM_MENU_POST); + postMenu.replace(String(F("MENU_HOME")), _attachMenuItem(AC_MENUITEM_HOME)); postMenu.replace(String(F("HOME_URI")), _apConfig.homeUri); + postMenu.replace(String(F("MENU_DEVINFO")), _attachMenuItem(AC_MENUITEM_DEVINFO)); return postMenu; } @@ -1272,7 +1278,7 @@ String AutoConnect::_token_CONFIG_STAIP(PageArgument& args) { char* liBuf = liCont; for (uint8_t i = 0; i < 5; i++) { - IPAddress* ip; + IPAddress* ip = nullptr; if (i == 0) ip = &_apConfig.staip; else if (i == 1) @@ -1283,7 +1289,7 @@ String AutoConnect::_token_CONFIG_STAIP(PageArgument& args) { ip = &_apConfig.dns1; else if (i == 4) ip = &_apConfig.dns2; - String ipStr = *ip ? ip->toString() : String(F("0.0.0.0")); + String ipStr = ip != nullptr ? ip->toString() : String(F("0.0.0.0")); snprintf_P(liBuf, sizeof(liCont) - (liBuf - liCont), (PGM_P)_configIPList, reps[i].lid, reps[i].lbl, reps[i].lid, reps[i].lid, ipStr.c_str()); liBuf += strlen(liBuf); } @@ -1340,12 +1346,7 @@ String AutoConnect::_token_UPTIME(PageArgument& args) { String AutoConnect::_token_BOOTURI(PageArgument& args) { AC_UNUSED(args); - if (_apConfig.bootUri == AC_ONBOOTURI_ROOT) - return String(AUTOCONNECT_URI); - else if (_apConfig.bootUri == AC_ONBOOTURI_HOME) - return _apConfig.homeUri.length() > 0 ? _apConfig.homeUri : String("/"); - else - return _emptyString; + return _getBootUri(); } String AutoConnect::_token_CURRENT_SSID(PageArgument& args) { @@ -1357,6 +1358,60 @@ String AutoConnect::_token_CURRENT_SSID(PageArgument& args) { return ssid; } +/** + * Generate AutoConnect menu item configured by AutoConnectConfig::attachMenu. + * @param item An enumerated value for the generating item configured in AutoConnectConfig. + * @return HTML string of a li tag with the menu item. + */ +String AutoConnect::_attachMenuItem(const AC_MENUITEM_t item) { + static const char _liTempl[] PROGMEM = "
  • %s
  • "; + PGM_P id; + PGM_P link; + PGM_P label; + + switch (static_cast(_apConfig.menuItems & static_cast(item))) { + case AC_MENUITEM_CONFIGNEW: + id = PSTR(""); + link = PSTR(AUTOCONNECT_URI_CONFIG); + label = PSTR(AUTOCONNECT_MENULABEL_CONFIGNEW); + break; + case AC_MENUITEM_OPENSSIDS: + id = PSTR(""); + link = PSTR(AUTOCONNECT_URI_OPEN); + label = PSTR(AUTOCONNECT_MENULABEL_OPENSSIDS); + break; + case AC_MENUITEM_DISCONNECT: + id = PSTR(""); + link = PSTR(AUTOCONNECT_URI_DISCON); + label = PSTR(AUTOCONNECT_MENULABEL_DISCONNECT); + break; + case AC_MENUITEM_RESET: + id = PSTR(" id=\"reset\""); + link = PSTR("#rdlg"); + label = PSTR(AUTOCONNECT_MENULABEL_RESET); + break; + case AC_MENUITEM_HOME: + id = PSTR(""); + link = PSTR("HOME_URI"); + label = PSTR(AUTOCONNECT_MENULABEL_HOME); + break; + case AC_MENUITEM_DEVINFO: + id = PSTR(""); + link = PSTR(AUTOCONNECT_URI); + label = PSTR(AUTOCONNECT_MENULABEL_DEVINFO); + break; + default: + id = nullptr; + link = nullptr; + label = nullptr; + break; + } + char li[128] = { '\0' }; + if (!!id && !!link && !!label) + snprintf(li, sizeof(li), (PGM_P)_liTempl, id, link, label); + return String(li); +} + /** * This function dynamically build up the response pages that conform to * the requested URI. A PageBuilder instance is stored in _responsePage @@ -1365,7 +1420,7 @@ String AutoConnect::_token_CURRENT_SSID(PageArgument& args) { * @retval true A response page generated. * @retval false Requested uri is not defined. */ -PageElement* AutoConnect::_setupPage(String uri) { +PageElement* AutoConnect::_setupPage(String& uri) { PageElement *elm = new PageElement(); // Restore menu title @@ -1400,7 +1455,7 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("CHIP_ID")), std::bind(&AutoConnect::_token_CHIP_ID, this, std::placeholders::_1)); elm->addToken(String(FPSTR("FREE_HEAP")), std::bind(&AutoConnect::_token_FREE_HEAP, this, std::placeholders::_1)); } - else if (uri == String(AUTOCONNECT_URI_CONFIG)) { + else if (uri == String(AUTOCONNECT_URI_CONFIG) && (_apConfig.menuItems & AC_MENUITEM_CONFIGNEW)) { // Setup /auto/config elm->setMold(_PAGE_CONFIGNEW); @@ -1419,7 +1474,7 @@ PageElement* AutoConnect::_setupPage(String uri) { 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) && (_apConfig.menuItems & AC_MENUITEM_CONFIGNEW || _apConfig.menuItems & AC_MENUITEM_OPENSSIDS)) { // Setup /auto/connect _menuTitle = FPSTR(AUTOCONNECT_MENUTEXT_CONNECTING); @@ -1433,7 +1488,7 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CUR_SSID")), std::bind(&AutoConnect::_token_CURRENT_SSID, this, std::placeholders::_1)); } - else if (uri == String(AUTOCONNECT_URI_OPEN)) { + else if (uri == String(AUTOCONNECT_URI_OPEN) && (_apConfig.menuItems & AC_MENUITEM_OPENSSIDS)) { // Setup /auto/open elm->setMold(_PAGE_OPENCREDT); @@ -1447,7 +1502,7 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); elm->addToken(String(FPSTR("OPEN_SSID")), std::bind(&AutoConnect::_token_OPEN_SSID, this, std::placeholders::_1)); } - else if (uri == String(AUTOCONNECT_URI_DISCON)) { + else if (uri == String(AUTOCONNECT_URI_DISCON) && (_apConfig.menuItems & AC_MENUITEM_DISCONNECT)) { // Setup /auto/disc _menuTitle = FPSTR(AUTOCONNECT_MENUTEXT_DISCONNECT); @@ -1459,7 +1514,7 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); } - else if (uri == String(AUTOCONNECT_URI_RESET)) { + else if (uri == String(AUTOCONNECT_URI_RESET) && (_apConfig.menuItems & AC_MENUITEM_RESET)) { // Setup /auto/reset elm->setMold(_PAGE_RESETTING); diff --git a/src/AutoConnectUpdate.h b/src/AutoConnectUpdate.h index 3fdc4f1..c9300af 100644 --- a/src/AutoConnectUpdate.h +++ b/src/AutoConnectUpdate.h @@ -11,7 +11,7 @@ * The dialog pages are all AutoConnectAux, and they select available * sketch binary, display during update processing, and display * update results. - * 2. Daialog pages handler + * 2. Dialog pages handler * In the dialog page, AUTOCONNECT_URI_UPDATE, AUTOCONNECT_URI_UPDATE_ACT, * AUTOCONNECT_URI_UPDATE_RESULT are assigned and there is a page * handler for each. @@ -65,7 +65,7 @@ typedef enum AC_UPDATESTATUS { UPDATE_RESET, /**< Update process ended, need to reset */ UPDATE_IDLE, /**< Update process has not started */ UPDATE_START, /**< Update process has been started */ - UPDATE_PROGRESS, /**< Update process has been started */ + UPDATE_PROGRESS, /**< Update process in progress */ UPDATE_SUCCESS, /**< Update successfully completed */ UPDATE_NOAVAIL, /**< No available update */ UPDATE_FAIL /**< Update fails */ diff --git a/src/AutoConnectUpdatePage.h b/src/AutoConnectUpdatePage.h index 880d2c2..960c468 100644 --- a/src/AutoConnectUpdatePage.h +++ b/src/AutoConnectUpdatePage.h @@ -8,8 +8,8 @@ * @copyright MIT license. */ -#ifndef _AUTOCONNECTUPDATEPAGE_H -#define _AUTOCONNECTUPDATEPAGE_H +#ifndef _AUTOCONNECTUPDATEPAGE_H_ +#define _AUTOCONNECTUPDATEPAGE_H_ // Define the AUTOCONNECT_URI_UPDATE page to select the sketch binary // for update and order update execution. @@ -19,10 +19,10 @@ const AutoConnectUpdateAct::ACElementProp_t AutoConnectUpdateAct::_elmCatalog[] { AC_Element, "c1", "
    ", nullptr }, { AC_Radio, "firmwares", nullptr, nullptr }, { AC_Element, "c1", "
    ", nullptr }, - { AC_Submit, "update", "UPDATE", AUTOCONNECT_URI_UPDATE_ACT } + { AC_Submit, "update", AUTOCONNECT_BUTTONLABEL_UPDATE, AUTOCONNECT_URI_UPDATE_ACT } }; const AutoConnectUpdateAct::ACPage_t AutoConnectUpdateAct::_pageCatalog PROGMEM = { - AUTOCONNECT_URI_UPDATE, "Update", false, AutoConnectUpdateAct::_elmCatalog + AUTOCONNECT_URI_UPDATE, AUTOCONNECT_MENULABEL_UPDATE, false, AutoConnectUpdateAct::_elmCatalog }; // Define the AUTOCONNECT_URI_UPDATE_ACT page to display during the @@ -45,7 +45,7 @@ const AutoConnectUpdateAct::ACElementProp_t AutoConnectUpdateAct::_elmProgress[] { AC_Element, "c7", "}window.onload=bar;", nullptr } }; const AutoConnectUpdateAct::ACPage_t AutoConnectUpdateAct::_pageProgress PROGMEM = { - AUTOCONNECT_URI_UPDATE_ACT, "Update", false, AutoConnectUpdateAct::_elmProgress + AUTOCONNECT_URI_UPDATE_ACT, AUTOCONNECT_MENULABEL_UPDATE, false, AutoConnectUpdateAct::_elmProgress }; // Definition of the AUTOCONNECT_URI_UPDATE_RESULT page to notify update results @@ -54,7 +54,7 @@ const AutoConnectUpdateAct::ACElementProp_t AutoConnectUpdateAct::_elmResult[] P { AC_Element, "restart", "", nullptr } }; const AutoConnectUpdateAct::ACPage_t AutoConnectUpdateAct::_pageResult PROGMEM = { - AUTOCONNECT_URI_UPDATE_RESULT, "Update", false, AutoConnectUpdateAct::_elmResult + AUTOCONNECT_URI_UPDATE_RESULT, AUTOCONNECT_MENULABEL_UPDATE, false, AutoConnectUpdateAct::_elmResult }; #endif // _AUTOCONNECTUPDATEPAGE_H diff --git a/src/AutoConnectUpload.h b/src/AutoConnectUpload.h index 9004991..ba8c603 100644 --- a/src/AutoConnectUpload.h +++ b/src/AutoConnectUpload.h @@ -32,7 +32,7 @@ class AutoConnectUploadHandler { protected: virtual bool _open(const char* filename, const char* mode) = 0; virtual size_t _write(const uint8_t *buf, const size_t size) = 0; - virtual void _close(void) = 0; + virtual void _close(const HTTPUploadStatus status) = 0; }; #endif // !_AUTOCONNECTUPLOAD_H_ diff --git a/src/AutoConnectUploadImpl.h b/src/AutoConnectUploadImpl.h index c181227..4e4276f 100644 --- a/src/AutoConnectUploadImpl.h +++ b/src/AutoConnectUploadImpl.h @@ -74,7 +74,7 @@ void AutoConnectUploadHandler::upload(const String& requestUri, const HTTPUpload break; case UPLOAD_FILE_ABORTED: case UPLOAD_FILE_END: - _close(); + _close(upload.status); break; } } @@ -83,7 +83,7 @@ void AutoConnectUploadHandler::upload(const String& requestUri, const HTTPUpload class AutoConnectUploadFS : public AutoConnectUploadHandler { public: explicit AutoConnectUploadFS(SPIFFST& media) : _media(&media) {} - ~AutoConnectUploadFS() { _close(); } + ~AutoConnectUploadFS() { _close(HTTPUploadStatus::UPLOAD_FILE_END); } protected: bool _open(const char* filename, const char* mode) override { @@ -106,7 +106,8 @@ class AutoConnectUploadFS : public AutoConnectUploadHandler { return -1; } - void _close(void) override { + void _close(const HTTPUploadStatus status) override { + AC_UNUSED(status); if (_file) _file.close(); _media->end(); @@ -142,7 +143,7 @@ class AutoConnectUploadFS : public AutoConnectUploadHandler { class AutoConnectUploadSD : public AutoConnectUploadHandler { public: explicit AutoConnectUploadSD(SDClassT& media, const uint8_t cs = AUTOCONNECT_SD_CS, const uint32_t speed = AUTOCONNECT_SD_SPEED) : _media(&media), _cs(cs), _speed(speed) {} - ~AutoConnectUploadSD() { _close(); } + ~AutoConnectUploadSD() { _close(HTTPUploadStatus::UPLOAD_FILE_END); } protected: bool _open(const char* filename, const char* mode) override { @@ -205,7 +206,8 @@ class AutoConnectUploadSD : public AutoConnectUploadHandler { return -1; } - void _close(void) override { + void _close(const HTTPUploadStatus status) override { + AC_UNUSED(status); if (_file) _file.close(); AutoConnectUtil::end(_media);

    Label placedPre-defined textID (#define macro)
    Menu itemConfigure new APAUTOCONNECT_MENULABEL_CONFIGNEW
    Menu itemConfigure new APAUTOCONNECT_MENULABEL_CONFIGNEW
    Open SSIDsAUTOCONNECT_MENULABEL_OPENSSIDS
    DisconnectAUTOCONNECT_MENULABEL_DISCONNECT
    Reset...AUTOCONNECT_MENULABEL_RESET
    HOMEAUTOCONNECT_MENULABEL_HOME
    UpdateAUTOCONNECT_MENULABEL_UPDATE
    Button labelRESETAUTOCONNECT_BUTTONLABEL_RESET
    Device infoAUTOCONNECT_MENULABEL_DEVINFO
    Button labelRESETAUTOCONNECT_BUTTONLABEL_RESET
    UPDATEAUTOCONNECT_BUTTONLABEL_UPDATE
    Page titlePage not foundAUTOCONNECT_PAGETITLE_NOTFOUND
    AutoConnect configAUTOCONNECT_PAGETITLE_CONFIG
    AutoConnect connectingAUTOCONNECT_PAGETITLE_CONNECTING
    PassphraseAUTOCONNECT_PAGECONFIG_PASSPHRASE
    Enable DHCPAUTOCONNECT_PAGECONFIG_ENABLEDHCP
    ApplyAUTOCONNECT_PAGECONFIG_APPLY
    Page:[update] textUpdating firmwareAUTOCONNECT_TEXT_UPDATINGFIRMWARE
    Select firmware:AUTOCONNECT_TEXT_SELECTFIRMWARE
    Successfully updated, rebooting...AUTOCONNECT_TEXT_OTASUCCESS
    Failed to update:AUTOCONNECT_TEXT_OTAFAILURE
    Page:[connection failed]Connection FailedAUTOCONNECT_PAGECONNECTIONFAILED_CONNECTIONFAILED
    TextNo saved credentials.AUTOCONNECT_TEXT_NOSAVEDCREDENTIALS
    Menu TextConnectingAUTOCONNECT_MENUTEXT_CONNECTING