]> granicus.if.org Git - esp-idf/commitdiff
update ota examples to support both Wi-Fi and Ethernet
authorsuda-morris <362953310@qq.com>
Wed, 22 May 2019 09:56:10 +0000 (17:56 +0800)
committersuda-morris <362953310@qq.com>
Wed, 22 May 2019 09:56:10 +0000 (17:56 +0800)
17 files changed:
examples/system/ota/OTA_workflow.png [deleted file]
examples/system/ota/README.md
examples/system/ota/advanced_https_ota/CMakeLists.txt
examples/system/ota/advanced_https_ota/Makefile
examples/system/ota/advanced_https_ota/main/Kconfig.projbuild
examples/system/ota/advanced_https_ota/main/advanced_https_ota_example.c
examples/system/ota/advanced_https_ota/sdkconfig.defaults [new file with mode: 0644]
examples/system/ota/native_ota_example/CMakeLists.txt
examples/system/ota/native_ota_example/Makefile
examples/system/ota/native_ota_example/main/Kconfig.projbuild
examples/system/ota/native_ota_example/main/native_ota_example.c
examples/system/ota/ota_workflow.png [new file with mode: 0644]
examples/system/ota/simple_ota_example/CMakeLists.txt
examples/system/ota/simple_ota_example/Makefile
examples/system/ota/simple_ota_example/main/Kconfig.projbuild
examples/system/ota/simple_ota_example/main/simple_ota_example.c
examples/wifi/getting_started/softAP/main/softap_example_main.c

diff --git a/examples/system/ota/OTA_workflow.png b/examples/system/ota/OTA_workflow.png
deleted file mode 100644 (file)
index 3e91daf..0000000
Binary files a/examples/system/ota/OTA_workflow.png and /dev/null differ
index 4f692d98f50f81ec2934abb8ea393f0713153678..1c971d59717a46787989a6514e17350e9ef10a6b 100644 (file)
-# OTA Demo
+# OTA Example
 
-## Introduction
+**Notes:** *This guide is common for all ota examples*
 
-Over The Air (OTA) updates can be performed in esp32 in two ways:
+## Overview
 
-- Using native APIs which are part of OTA component.
-- Using simplified APIs which are part of `esp_https_ota`, it's an abstraction layer over OTA APIs to perform updates using HTTPS.
+ESP32 application can do upgrading at runtime by downloading new image from specific server through Wi-Fi or Ethernet and then flash it into some partitions. There’re two ways in ESP-IDF to perform Over The Air (OTA) upgrading:
 
-Both these methods are demonstrated in OTA Demo under `native_ota_example` and `simple_ota_example` respectively.
+- Using the native APIs provided by `app_update` component.
+- Using simplified APIs provided by  `esp_https_ota` component, which adds an abstraction layer over the native OTA APIs in order to upgrading with HTTPS protocol.
 
-*Note: This guide is common for both the examples*
+Both methods are demonstrated in OTA Demos under `native_ota_example` and `simple_ota_example` respectively.
 
----
+For simplicity, the OTA examples choose the pre-defined partition table by enabling `CONFIG_PARTITION_TABLE_TWO_OTA` option in menuconfig, which supports three app partitions: factory, OTA_0 and OTA_1. For more information about partition table, please refer to [Partition Tables](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html).
 
-## Aim
+On first boot, the bootloader will load the factory app image (i.e. the example image) and then triggers an OTA upgrading. It will download a new image from HTTPS server and save it into the OTA_0 partition. It will update the ota_data partition automatically as well to indicate which app should boot from in the next reset. The bootloader will read the content in ota_data partition and run the selected application.
 
-An app running on ESP32 can upgrade itself by downloading a new app "image" binary file, and storing it in flash.
+The OTA workflow can be demonstrated as in the following diagram:
 
-In this example, the ESP32 has 3 images in flash: factory, OTA_0, OTA_1. Each of these is a self-contained partition. The number of OTA image partition is determined by the partition table layout.
+![OTA Workflow](ota_workflow.png)
 
-Flashing the example over serial with "make flash" updates the factory app image. On first boot, the bootloader loads this factory app image which then performs an OTA update (triggered in the example code). The update downloads a new image from a HTTPS server and saves it into the OTA_0 partition. At this point the example code updates the ota_data partition to indicate the new app partition, and resets. The bootloader reads ota_data, determines the new OTA image has been selected, and runs it.
+## How to use the examples
 
+### Hardware Required
 
-## Workflow
+To run the OTA examples, you need an ESP32 dev board (e.g. ESP32-WROVER Kit) or ESP32 core board (e.g. ESP32-DevKitC). If you want to test the OTA with Ethernet, make sure your board has set up the Ethernet correctly. For extra information about setting up Ethernet, please refer to Ethernet examples.
 
-The OTA_workflow.png diagram demonstrates the overall workflow:
+### Configure the project
 
-![OTA Workflow diagram](OTA_workflow.png)
+Enter `make menuconfig` if you are using GNU Make based build system or enter `idf.py menuconfig` if you are using CMake based build system. 
 
-### Step 1: Connect to AP
+In the `Example Connection Configuration` menu:
 
-Connect your host PC to the same AP that you will use for the ESP32.
+* Choose the network interface in `Connect using`  option based on your board. Currently we support both Wi-Fi and Ethernet.
+* If you have selected the Wi-Fi interface, you also have to set:
+  * Wi-Fi SSID and Wi-Fi password that your ESP32 will connect to
+* If you have selected the Ethernet interface, you also have to set:
+  * PHY model in `Ethernet PHY` option, e.g. IP101
+  * PHY address in `PHY Address` option, which should be determined by your board schematic
+  * EMAC Clock mode, SMI GPIOs
 
-### Step 2: Run HTTPS Server
+In the `Example Configuration` menu:
 
-For our upgrade example OTA file, we're going to use the `get-started/hello_world` example.
+* Set the URL of the new firmware that you will download from in the `Firmware Upgrade URL` option, whose format should be `https://<host-ip-address>:<host-port>/<firmware-image-filename>`, e.g. `https://192.168.2.106:8070/hello-world.bin`
+  * **Notes:** The server part of this URL (e.g. `192.168.2.106`) must match the **CN** field used when [generating the certificate and key](#run-https-server).
 
-Open a new terminal to run the HTTP server, then run these commands to build the example and start the server:
+### Build and Flash
 
-Build the example:
+Enter `make -j4 flash monitor` if you are using GNU Make based build system or enter `idf.py build flash monitor` if you are using CMake based build system. This command will find if partition table has ota_data partition (as in our case) then ota_data will erase to initial. It allows to run the newly loaded app from a factory partition.
 
-```
-cd $IDF_PATH/examples/get-started/hello_world
-make
-cd build
-```
+(To exit the serial monitor, type ``Ctrl-]``.)
 
-Generate self-signed certificate and key:
+See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
 
-*NOTE: `Common Name` of server certificate should be host-name of your server.*
+## Example Output
 
-```
-openssl req -x509 -newkey rsa:2048 -keyout ca_key.pem -out ca_cert.pem -days 365
+### Run HTTPS Server
 
-```
+After a successful build, we need to create a self-signed certificate and run a simple HTTPS server as follows:
 
-* openssl configuration may require you to enter a passphrase for the key.
-* When prompted for the `Common Name (CN)`, enter the name of the server that the ESP32 will connect to. For this local example, it is probably the IP address. The HTTPS client will make sure that the `CN` matches the address given in the HTTPS URL (see Step 3).
+![create_self_signed_certificate](https://dl.espressif.com/dl/esp-idf/docs/_static/ota_self_signature.gif)
 
+* Enter a directory where holds the root of the HTTPS server, e.g. `cd build`.
+* To create a new self-signed certificate and key, you can simply run command `openssl req -x509 -newkey rsa:2048 -keyout ca_key.pem -out ca_cert.pem -days 365 -nodes`.
+  * When prompted for the `Common Name (CN)`, enter the name of the server that the ESP32 will connect to. Regarding this example, it is probably the IP address. The HTTPS client will make sure that the `CN` matches the address given in the HTTPS URL.
+* To start the HTTPS server, you can simply run command `openssl s_server -WWW -key ca_key.pem -cert ca_cert.pem -port 8070`.
+* In the same directory, there should be the firmware (e.g. hello-world.bin) that ESP32 will download later. It can be any other ESP-IDF application as well, as long as you also update the `Firmware Upgrade URL` in the menuconfig. The only difference is that when flashed via serial the binary is flashed to the "factory" app partition, and an OTA update flashes to an OTA app partition.
+* **Notes:** If you have any firewall software running that will block incoming access to port *8070*, configure it to allow access while running the example.
+* **Notes:** For Windows users, you should add `winpty` before `openssl` command:
+  * `winpty openssl req -x509 -newkey rsa:2048 -keyout ca_key.pem -out ca_cert.pem -days 365 -nodes`
+  * `winpty openssl s_server -WWW -key ca_key.pem -cert ca_cert.pem -port 8070`
 
-Copy the certificate to `server_certs` directory inside OTA example directory:
-
-```
-cp ca_cert.pem /path/to/ota/example/server_certs/
-```
-
+### Flash Certificate to ESP32
 
-Start the HTTPS server:
+Before you flash the example, make sure to copy the generated certificate to `server_certs` directory inside OTA example directory so that it can be flashed into ESP32 together with the firmware, e.g. `cp ca_cert.pem ../server_certs/`.
 
 ```
-openssl s_server -WWW -key ca_key.pem -cert ca_cert.pem -port 8070
+cp ca_cert.pem /path/to/ota/example/server_certs/
 ```
 
-NB: You've probably noticed there is nothing special about the "hello world" example when used for OTA updates. This is because any .bin app file which is built by esp-idf can be used as an app image for OTA. The only difference is that when flashed via serial the binary is flashed to the "factory" app partition, and an OTA update flashes to an OTA app partition.
-
-If you have any firewall software running that will block incoming access to port 8070, configure it to allow access while running the example.
+### Internal workflow of the OTA Example
 
-### Step 3: Build OTA Example
+When the example starts up, it will print "Starting OTA example" to the console and then:
 
-Change back to the OTA example directory, and type `make menuconfig` to configure the OTA example. Under the "Example Configuration" submenu, fill in the following details:
-
-* WiFi SSID & Password
-* Firmware Upgrade URL. The URL will be look like this:
-
-```
-https://<host-ip-address>:<host-port>/<firmware-image-filename>
-
-for e.g,
-https://192.168.0.3:8070/hello-world.bin
-```
-
-Note: The server part of this URL (e.g. `192.168.0.3`) must match the CN used when generating the certificate and key in Step 2.
+1. Connect to the AP with configured SSID and Password (Wi-Fi case) or just by Ethernet.
+2. Connect to the HTTPS server and download the new image.
+3. Write the image to flash, and configure the next boot from this image.
+4. Reboot
 
-Save your changes, and type `make` to build the example.
+If you want to rollback to factory app (or the first OTA partition when the factory partition do not exist) after the upgrade, then run the command `make erase_otadata` or `idf.py erase_otadata`. It can erase the ota_data partition to initial state.
 
-### Step 4: Flash OTA Example
+**Notes:** This assumes that the partition table of this project is the one that is on the device.
 
-When flashing, use the `make flash` to flash the factory image. This command will find if partition table has ota_data partition (as in our case) then ota_data will erase to initial. 
-It allows to run the newly loaded app from a factory partition.
+### Output from HTTPS server
 
-```
-make flash
+```bash
+FILE:hello-world.bin
+ACCEPT
 ```
 
-After first update, if you want to return back to factory app (or the first OTA partition, if factory partition is not present) then use the command `make erase_otadata`. 
-It erases the ota_data partition to initial state. **Take note that this assumes that the partition table of this project is the one that is on the device**.
 
-### Step 5: Run the OTA Example
+## Support rollback
 
-When the example starts up, it will print "Starting OTA example..." then:
-
-1. Connect to the AP with configured SSID and password.
-2. Connect to the HTTP server and download the new image.
-3. Write the image to flash, and configure the next boot from this image.
-4. Reboot
-
-## Support the rollback
-
-This feature allows you to roll back to the previous firmware if the app is not operable. Option :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` allows you to track the first boot of the application (see the``Over The Air Updates (OTA)`` article). 
-For ``native_ota_example``, added a bit of code to demonstrate how a rollback works. To use it, you need enable the :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option in Kconfig and under the "Example Configuration" submenu to set "Number of the GPIO input for diagnostic" to manage the rollback process.
+This feature allows you to roll back to the previous firmware if the app is not operable. Option `CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` allows you to track the first boot of the application (see the ``Over The Air Updates (OTA)`` article). 
+For ``native_ota_example``, added a bit of code to demonstrate how a rollback works. To use it, you need enable the `CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option in menuconfig and under the "Example Configuration" submenu to set "Number of the GPIO input for diagnostic" to manage the rollback process.
 
 To trigger a rollback, this GPIO must be pulled low while the message `Diagnostics (5 sec)...` which will be on first boot.
 If GPIO is not pulled low then the operable of the app will be confirmed.
@@ -138,12 +122,7 @@ In ``native_ota_example``, ``$PROJECT_PATH/version.txt`` is used to define the v
 
 * Check your PC can ping the ESP32 at its IP, and that the IP, AP and other configuration settings are correct in menuconfig.
 * Check if any firewall software is preventing incoming connections on the PC.
-* Check whether you can see the configured file (default hello-world.bin), by checking the output of following command:
-
- ```
- curl -v https://<host-ip-address>:<host-port>/<firmware-image-filename>
- ```
-
+* Check whether you can see the configured file (default hello-world.bin), by checking the output of the command `curl -v https://<host-ip-address>:<host-port>/<firmware-image-filename>`
 * If you have another PC or a phone, try viewing the file listing from the separate host.
 
 ### Error "ota_begin error err=0x104"
index 3386014f6e1edd45392642158746e4b75542927f..7f8b1cb53f3b2785375839d7d765f81a3e0879ce 100644 (file)
@@ -2,5 +2,9 @@
 # in this exact order for cmake to work correctly
 cmake_minimum_required(VERSION 3.5)
 
+# (Not part of the boilerplate)
+# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
+set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
+
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 project(advanced_https_ota)
index 301cf1eb9910cc550e00198c10d0261d1dbc5a16..df5c335c4a9e36e7a2ddc62004cbe50958c9d490 100644 (file)
@@ -5,5 +5,7 @@
 
 PROJECT_NAME := advanced_https_ota
 
+EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common
+
 include $(IDF_PATH)/make/project.mk
 
index 3bfb017948c61a089ddaaa64f88567714224bd2d..22b772a05284c96c63309940cdbdac79fd9582f5 100644 (file)
@@ -1,21 +1,9 @@
 menu "Example Configuration"
 
-    config EXAMPLE_WIFI_SSID
-        string "WiFi SSID"
-        default "myssid"
-        help
-            SSID (network name) for the example to connect to.
-
-    config EXAMPLE_WIFI_PASSWORD
-        string "WiFi Password"
-        default "mypassword"
-        help
-            WiFi password (WPA or WPA2) for the example to use.
-
     config EXAMPLE_FIRMWARE_UPGRADE_URL
-        string "firmware upgrade url endpoint"
-        default "https://192.168.0.3:8070/hello-world.bin"
+        string "Firmware Upgrade URL"
+        default "https://192.168.2.106:8070/hello-world.bin"
         help
-            URL of server which hosts the firmware
-            image.
+            URL of server which hosts the firmware image.
+
 endmenu
index e2cd48e425b58deeb2cba03efde2eedc02afe03d..c2b01e14441d9a930b59794cce1dcfd68b1aa297 100644 (file)
@@ -6,75 +6,25 @@
    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    CONDITIONS OF ANY KIND, either express or implied.
 */
-#include "string.h"
+#include <string.h>
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/event_groups.h"
-
 #include "esp_system.h"
-#include "esp_wifi.h"
+#include "esp_event.h"
 #include "esp_event_loop.h"
 #include "esp_log.h"
 #include "esp_ota_ops.h"
 #include "esp_http_client.h"
 #include "esp_https_ota.h"
-
 #include "nvs.h"
 #include "nvs_flash.h"
+#include "protocol_examples_common.h"
 
 static const char *TAG = "advanced_https_ota_example";
 extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start");
 extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");
 
-/* FreeRTOS event group to signal when we are connected & ready to make a request */
-static EventGroupHandle_t wifi_event_group;
-
-/* The event group allows multiple bits for each event,
-   but we only care about one event - are we connected
-   to the AP with an IP? */
-const int CONNECTED_BIT = BIT0;
-
-static esp_err_t event_handler(void *ctx, system_event_t *event)
-{
-    switch (event->event_id) {
-    case SYSTEM_EVENT_STA_START:
-        esp_wifi_connect();
-        break;
-    case SYSTEM_EVENT_STA_GOT_IP:
-        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
-        break;
-    case SYSTEM_EVENT_STA_DISCONNECTED:
-        /* This is a workaround as ESP32 WiFi libs don't currently
-           auto-reassociate. */
-        esp_wifi_connect();
-        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
-        break;
-    default:
-        break;
-    }
-    return ESP_OK;
-}
-
-static void initialise_wifi(void)
-{
-    tcpip_adapter_init();
-    wifi_event_group = xEventGroupCreate();
-    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
-    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
-    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
-    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
-    wifi_config_t wifi_config = {
-        .sta = {
-            .ssid = CONFIG_EXAMPLE_WIFI_SSID,
-            .password = CONFIG_EXAMPLE_WIFI_PASSWORD,
-        },
-    };
-    ESP_LOGI(TAG, "Setting WiFi configuration SSID %s", wifi_config.sta.ssid);
-    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
-    ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
-    ESP_ERROR_CHECK( esp_wifi_start() );
-}
-
 static esp_err_t validate_image_header(esp_app_desc_t *new_app_info)
 {
     if (new_app_info == NULL) {
@@ -94,24 +44,20 @@ static esp_err_t validate_image_header(esp_app_desc_t *new_app_info)
     return ESP_OK;
 }
 
-void advanced_ota_example_task(void * pvParameter)
+void advanced_ota_example_task(void *pvParameter)
 {
     ESP_LOGI(TAG, "Starting Advanced OTA example");
 
-    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
-                        false, true, portMAX_DELAY);
-    ESP_LOGI(TAG, "Connected to WiFi network! Attempting to connect to server...");
-    
     esp_err_t ota_finish_err = ESP_OK;
     esp_http_client_config_t config = {
         .url = CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL,
         .cert_pem = (char *)server_cert_pem_start,
     };
-    
+
     esp_https_ota_config_t ota_config = {
         .http_config = &config,
     };
-    
+
     esp_https_ota_handle_t https_ota_handle = NULL;
     esp_err_t err = esp_https_ota_begin(&ota_config, &https_ota_handle);
     if (err != ESP_OK) {
@@ -171,7 +117,15 @@ void app_main()
     }
     ESP_ERROR_CHECK( err );
 
-    initialise_wifi();
+    tcpip_adapter_init();
+    ESP_ERROR_CHECK(esp_event_loop_create_default());
+
+    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
+     * Read "Establishing Wi-Fi or Ethernet Connection" section in
+     * examples/protocols/README.md for more information about this function.
+    */
+    ESP_ERROR_CHECK(example_connect());
+
     xTaskCreate(&advanced_ota_example_task, "advanced_ota_example_task", 1024 * 8, NULL, 5, NULL);
 }
 
diff --git a/examples/system/ota/advanced_https_ota/sdkconfig.defaults b/examples/system/ota/advanced_https_ota/sdkconfig.defaults
new file mode 100644 (file)
index 0000000..2289a82
--- /dev/null
@@ -0,0 +1,4 @@
+# Default sdkconfig parameters to use the OTA
+# partition table layout, with a 4MB flash size
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_PARTITION_TABLE_TWO_OTA=y
index 9e1828169e376ff2e32bc79160d8b4a39b258f1d..9cb3fe6e4ed7940e374b569aa78532681fb6a14a 100644 (file)
@@ -2,5 +2,9 @@
 # in this exact order for cmake to work correctly
 cmake_minimum_required(VERSION 3.5)
 
+# (Not part of the boilerplate)
+# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
+set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
+
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 project(native_ota)
index 3bcbefac0d8370d5f6e63a7fdeab1c36155b8b3f..06414285051af4011923ed7b3c227a229acbffab 100644 (file)
@@ -5,5 +5,7 @@
 
 PROJECT_NAME := native_ota
 
+EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common
+
 include $(IDF_PATH)/make/project.mk
 
index fb50b5a1e817bec1c5f37dfdb4ec724669a78624..15c4390b803357fc271cc0a30b655220ab3d168e 100644 (file)
@@ -1,26 +1,10 @@
 menu "Example Configuration"
 
-    config EXAMPLE_WIFI_SSID
-        string "WiFi SSID"
-        default "myssid"
-        help
-            SSID (network name) for the example to connect to.
-
-    config EXAMPLE_WIFI_PASSWORD
-        string "WiFi Password"
-        default "mypassword"
-        help
-            WiFi password (WPA or WPA2) for the example to use.
-
-            Can be left blank if the network has no security set.
-
     config EXAMPLE_FIRMWARE_UPG_URL
-        string "HTTP Server URL"
-        default "https://192.168.0.3:8070/hello-world.bin"
+        string "Firmware Upgrade URL"
+        default "https://192.168.2.106:8070/hello-world.bin"
         help
-            HTTP Server IP to download the image file from.
-
-            See example README.md for details.
+            URL of server which hosts the firmware image.
 
     config EXAMPLE_GPIO_DIAGNOSTIC
         int "Number of the GPIO input for diagnostic"
index 4b5f158810e532f1afbf1c1ba1a7db98ecad0f71..6387438929de24fe9f976efb8d9e0a9169f562d1 100644 (file)
@@ -6,27 +6,22 @@
    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    CONDITIONS OF ANY KIND, either express or implied.
 */
-#include "string.h"
+#include <string.h>
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
-#include "freertos/event_groups.h"
-
 #include "esp_system.h"
-#include "esp_wifi.h"
+#include "esp_event.h"
 #include "esp_event_loop.h"
 #include "esp_log.h"
 #include "esp_ota_ops.h"
 #include "esp_http_client.h"
 #include "esp_flash_partitions.h"
 #include "esp_partition.h"
-
 #include "nvs.h"
 #include "nvs_flash.h"
 #include "driver/gpio.h"
+#include "protocol_examples_common.h"
 
-#define EXAMPLE_WIFI_SSID CONFIG_EXAMPLE_WIFI_SSID
-#define EXAMPLE_WIFI_PASS CONFIG_EXAMPLE_WIFI_PASSWORD
-#define EXAMPLE_SERVER_URL CONFIG_EXAMPLE_FIRMWARE_UPG_URL
 #define BUFFSIZE 1024
 #define HASH_LEN 32 /* SHA-256 digest length */
 
@@ -36,55 +31,6 @@ static char ota_write_data[BUFFSIZE + 1] = { 0 };
 extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start");
 extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");
 
-/* FreeRTOS event group to signal when we are connected & ready to make a request */
-static EventGroupHandle_t wifi_event_group;
-
-/* The event group allows multiple bits for each event,
-   but we only care about one event - are we connected
-   to the AP with an IP? */
-const int CONNECTED_BIT = BIT0;
-
-static esp_err_t event_handler(void *ctx, system_event_t *event)
-{
-    switch (event->event_id) {
-    case SYSTEM_EVENT_STA_START:
-        esp_wifi_connect();
-        break;
-    case SYSTEM_EVENT_STA_GOT_IP:
-        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
-        break;
-    case SYSTEM_EVENT_STA_DISCONNECTED:
-        /* This is a workaround as ESP32 WiFi libs don't currently
-           auto-reassociate. */
-        esp_wifi_connect();
-        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
-        break;
-    default:
-        break;
-    }
-    return ESP_OK;
-}
-
-static void initialise_wifi(void)
-{
-    tcpip_adapter_init();
-    wifi_event_group = xEventGroupCreate();
-    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
-    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
-    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
-    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
-    wifi_config_t wifi_config = {
-        .sta = {
-            .ssid = EXAMPLE_WIFI_SSID,
-            .password = EXAMPLE_WIFI_PASS,
-        },
-    };
-    ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
-    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
-    ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
-    ESP_ERROR_CHECK( esp_wifi_start() );
-}
-
 static void http_cleanup(esp_http_client_handle_t client)
 {
     esp_http_client_close(client);
@@ -128,7 +74,7 @@ static void ota_example_task(void *pvParameter)
     esp_ota_handle_t update_handle = 0 ;
     const esp_partition_t *update_partition = NULL;
 
-    ESP_LOGI(TAG, "Starting OTA example...");
+    ESP_LOGI(TAG, "Starting OTA example");
 
     const esp_partition_t *configured = esp_ota_get_boot_partition();
     const esp_partition_t *running = esp_ota_get_running_partition();
@@ -141,15 +87,8 @@ static void ota_example_task(void *pvParameter)
     ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
              running->type, running->subtype, running->address);
 
-    /* Wait for the callback to set the CONNECTED_BIT in the
-       event group.
-    */
-    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
-                        false, true, portMAX_DELAY);
-    ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server....");
-    
     esp_http_client_config_t config = {
-        .url = EXAMPLE_SERVER_URL,
+        .url = CONFIG_EXAMPLE_FIRMWARE_UPG_URL,
         .cert_pem = (char *)server_cert_pem_start,
     };
     esp_http_client_handle_t client = esp_http_client_init(&config);
@@ -330,6 +269,14 @@ void app_main()
     }
     ESP_ERROR_CHECK( err );
 
-    initialise_wifi();
+    tcpip_adapter_init();
+    ESP_ERROR_CHECK(esp_event_loop_create_default());
+
+    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
+     * Read "Establishing Wi-Fi or Ethernet Connection" section in
+     * examples/protocols/README.md for more information about this function.
+     */
+    ESP_ERROR_CHECK(example_connect());
+
     xTaskCreate(&ota_example_task, "ota_example_task", 8192, NULL, 5, NULL);
 }
diff --git a/examples/system/ota/ota_workflow.png b/examples/system/ota/ota_workflow.png
new file mode 100644 (file)
index 0000000..d48fb8f
Binary files /dev/null and b/examples/system/ota/ota_workflow.png differ
index ae979292deda92793dd7adf324135e16831d3e13..2d8bd77c48cf5ba5dc4b52cb74609aa5dccb6998 100644 (file)
@@ -2,5 +2,9 @@
 # in this exact order for cmake to work correctly
 cmake_minimum_required(VERSION 3.5)
 
+# (Not part of the boilerplate)
+# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
+set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
+
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-project(simple_ota)
\ No newline at end of file
+project(simple_ota)
index 63bca1abe9031490e7010fd7c94d382a1bcf6da4..63c0d6be23c50db3316edff2da26a651db77705a 100644 (file)
@@ -5,5 +5,7 @@
 
 PROJECT_NAME := simple_ota
 
+EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common
+
 include $(IDF_PATH)/make/project.mk
 
index 3bfb017948c61a089ddaaa64f88567714224bd2d..c5be1f27622244a1a0df5ed76209c789fcb242b8 100644 (file)
@@ -1,21 +1,8 @@
 menu "Example Configuration"
 
-    config EXAMPLE_WIFI_SSID
-        string "WiFi SSID"
-        default "myssid"
-        help
-            SSID (network name) for the example to connect to.
-
-    config EXAMPLE_WIFI_PASSWORD
-        string "WiFi Password"
-        default "mypassword"
-        help
-            WiFi password (WPA or WPA2) for the example to use.
-
     config EXAMPLE_FIRMWARE_UPGRADE_URL
-        string "firmware upgrade url endpoint"
-        default "https://192.168.0.3:8070/hello-world.bin"
+        string "Firmware Upgrade URL"
+        default "https://192.168.2.106:8070/hello-world.bin"
         help
-            URL of server which hosts the firmware
-            image.
+            URL of server which hosts the firmware image.
 endmenu
index 026f8603295d665b0c4344e993edf073c884f8cd..1b63aec18ac1051874c1090b37e083d35599ee85 100644 (file)
 */
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
-#include "freertos/event_groups.h"
-
 #include "esp_system.h"
-#include "esp_wifi.h"
+#include "esp_event.h"
 #include "esp_event_loop.h"
 #include "esp_log.h"
 #include "esp_ota_ops.h"
 #include "esp_http_client.h"
 #include "esp_https_ota.h"
-
 #include "nvs.h"
 #include "nvs_flash.h"
+#include "protocol_examples_common.h"
 
 static const char *TAG = "simple_ota_example";
 extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start");
 extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");
 
-/* FreeRTOS event group to signal when we are connected & ready to make a request */
-static EventGroupHandle_t wifi_event_group;
-
-/* The event group allows multiple bits for each event,
-   but we only care about one event - are we connected
-   to the AP with an IP? */
-const int CONNECTED_BIT = BIT0;
-
 esp_err_t _http_event_handler(esp_http_client_event_t *evt)
 {
-    switch(evt->event_id) {
-        case HTTP_EVENT_ERROR:
-            ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
-            break;
-        case HTTP_EVENT_ON_CONNECTED:
-            ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
-            break;
-        case HTTP_EVENT_HEADER_SENT:
-            ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
-            break;
-        case HTTP_EVENT_ON_HEADER:
-            ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
-            break;
-        case HTTP_EVENT_ON_DATA:
-            ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
-            break;
-        case HTTP_EVENT_ON_FINISH:
-            ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
-            break;
-        case HTTP_EVENT_DISCONNECTED:
-            ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED");
-            break;
-    }
-    return ESP_OK;
-}
-
-static esp_err_t event_handler(void *ctx, system_event_t *event)
-{
-    switch (event->event_id) {
-    case SYSTEM_EVENT_STA_START:
-        esp_wifi_connect();
+    switch (evt->event_id) {
+    case HTTP_EVENT_ERROR:
+        ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
+        break;
+    case HTTP_EVENT_ON_CONNECTED:
+        ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
         break;
-    case SYSTEM_EVENT_STA_GOT_IP:
-        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
+    case HTTP_EVENT_HEADER_SENT:
+        ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
         break;
-    case SYSTEM_EVENT_STA_DISCONNECTED:
-        /* This is a workaround as ESP32 WiFi libs don't currently
-           auto-reassociate. */
-        esp_wifi_connect();
-        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
+    case HTTP_EVENT_ON_HEADER:
+        ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
         break;
-    default:
+    case HTTP_EVENT_ON_DATA:
+        ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
+        break;
+    case HTTP_EVENT_ON_FINISH:
+        ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
+        break;
+    case HTTP_EVENT_DISCONNECTED:
+        ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED");
         break;
     }
     return ESP_OK;
 }
 
-static void initialise_wifi(void)
-{
-    tcpip_adapter_init();
-    wifi_event_group = xEventGroupCreate();
-    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
-    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
-    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
-    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
-    wifi_config_t wifi_config = {
-        .sta = {
-            .ssid = CONFIG_EXAMPLE_WIFI_SSID,
-            .password = CONFIG_EXAMPLE_WIFI_PASSWORD,
-        },
-    };
-    ESP_LOGI(TAG, "Setting WiFi configuration SSID %s", wifi_config.sta.ssid);
-    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
-    ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
-    ESP_ERROR_CHECK( esp_wifi_start() );
-}
-
-void simple_ota_example_task(void * pvParameter)
+void simple_ota_example_task(void *pvParameter)
 {
     ESP_LOGI(TAG, "Starting OTA example");
 
-    /* Wait for the callback to set the CONNECTED_BIT in the
-       event group.
-    */
-    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
-                        false, true, portMAX_DELAY);
-    ESP_LOGI(TAG, "Connected to WiFi network! Attempting to connect to server...");
-    
     esp_http_client_config_t config = {
         .url = CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL,
         .cert_pem = (char *)server_cert_pem_start,
@@ -141,8 +83,16 @@ void app_main()
         ESP_ERROR_CHECK(nvs_flash_erase());
         err = nvs_flash_init();
     }
-    ESP_ERROR_CHECK( err );
+    ESP_ERROR_CHECK(err);
+
+    tcpip_adapter_init();
+    ESP_ERROR_CHECK(esp_event_loop_create_default());
+
+    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
+     * Read "Establishing Wi-Fi or Ethernet Connection" section in
+     * examples/protocols/README.md for more information about this function.
+     */
+    ESP_ERROR_CHECK(example_connect());
 
-    initialise_wifi();
     xTaskCreate(&simple_ota_example_task, "ota_example_task", 8192, NULL, 5, NULL);
 }
index 014c439636981bf77679e6d5eec33566c12ba9a1..515e3618ee132c8b2d0f0d8c294a592e8aa01389 100644 (file)
@@ -9,7 +9,6 @@
 #include <string.h>
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
-#include "freertos/event_groups.h"
 #include "esp_system.h"
 #include "esp_wifi.h"
 #include "esp_event.h"
 #define EXAMPLE_ESP_WIFI_PASS      CONFIG_ESP_WIFI_PASSWORD
 #define EXAMPLE_MAX_STA_CONN       CONFIG_ESP_MAX_STA_CONN
 
-/* FreeRTOS event group to signal when we are connected*/
-static EventGroupHandle_t s_wifi_event_group;
-
 static const char *TAG = "wifi softAP";
 
-static void wifi_event_handler(void* arg, esp_event_base_t event_base, 
+static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                     int32_t event_id, void* event_data)
 {
     if (event_id == WIFI_EVENT_AP_STACONNECTED) {
@@ -49,8 +45,6 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base,
 
 void wifi_init_softap()
 {
-    s_wifi_event_group = xEventGroupCreate();
-
     tcpip_adapter_init();
     ESP_ERROR_CHECK(esp_event_loop_create_default());
 
@@ -89,7 +83,7 @@ void app_main()
       ret = nvs_flash_init();
     }
     ESP_ERROR_CHECK(ret);
-    
+
     ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");
     wifi_init_softap();
 }