-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
578d8ef
commit e6cbf21
Showing
5 changed files
with
289 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -107,7 +107,7 @@ This section describes how to create an IoT hub using the [Azure portal](https:/ | |
![Assign tags for the hub using the Azure portal](https://github.com/MicrosoftDocs/azure-docs/blob/master/includes/media/iot-hub-include-create-hub/iot-hub-create-tabs.png?raw=true) | ||
1. Select **Next: Review + create** to review your choices. You see something similar to this screen, but with the values you selected when creating the hub. | ||
1. Select **Next: Review + create** to review your choices. You see something similar to this screen, but with the values you selected when creating the hub. | ||
![Review information for creating the new hub](https://github.com/MicrosoftDocs/azure-docs/blob/master/includes/media/iot-hub-include-create-hub/iot-hub-create-review.png?raw=true) | ||
|
@@ -139,9 +139,180 @@ In this section, you create a device identity in the identity registry in your I | |
In this section, you set the device twin desired properties. | ||
### Install this repository as an Arduino Library | ||
### Clone this project repository | ||
In this section, you install this repository as an Arduino Library on your computer. | ||
1. Download the library from the releases on github: [https://github.com/kbeaugrand/ESP32_AzureIoT_OTA/releases](https://github.com/kbeaugrand/ESP32_AzureIoT_OTA/releases) | ||
1. Extract the release to Arduino Library (see: [https://www.arduino.cc/en/Guide/Libraries#manual-installation](https://www.arduino.cc/en/Guide/Libraries#manual-installation)) | ||
### Configure the device settings | ||
In this section you create a new sketch called "Device Initiator" that helps you to configure the device settings. This sketch will create a new partition scheme on the device storage, and create the device settings file on that storage. | ||
> [!NOTE] | ||
> Storing those settings enables the possibility to work with Firmware update Over The Air without storing the device identity with the Firmware. | ||
1. Start a new sketch from an example | ||
* Open VS Code and press `F1` or `Ctrl + Shift + P` to open command palette | ||
* Select `Ardiuno: Examples` command | ||
* On Arduino Examples Window, select `Examples from Custom Libraries` > `ESP32_AzureIoT_OTA` > `ESP32_Device_Initiator` | ||
1. Configure your ESP 32 board from VSCode | ||
* Open VS Code and press `F1` or `Ctrl + Shift + P` to open command palette | ||
* Select `Ardiuno: Board Config` command | ||
* On Arduino Board Configuration Window select the `Minimal SPIFFS` Partition Scheme | ||
1. On `ESP32_Device_Initiator`, type your device connection settings | ||
```c++ | ||
const char *connectionString = "Type your Device Connection String"; | ||
const char *ssid = "Type here your WiFi SSID"; | ||
const char *password = "Type here your WiFi shared Key"; | ||
``` | ||
1. Upload this sketch to Arduino ESP32 | ||
* `Alt + Cmd + U` or `Alt + Ctrl + U` | ||
> [!NOTE] | ||
> Once this sketch is uploaded on the ESP 32, the integrated LED will be high. | ||
### Create the device Firmware | ||
In this section, you create the device firmware code. | ||
1. Start a new sketch from an example | ||
* Open VS Code and press `F1` or `Ctrl + Shift + P` to open command palette | ||
* Select `Ardiuno: Examples` command | ||
* On Arduino Examples Window, select `Examples from Custom Libraries` > `ESP32_AzureIoT_OTA` > `ESP32_Device_OTA` | ||
1. Configure your ESP 32 board from VSCode | ||
* Open VS Code and press `F1` or `Ctrl + Shift + P` to open command palette | ||
* Select `Ardiuno: Board Config` command | ||
* On Arduino Board Configuration Window select the `Minimal SPIFFS` Partition Scheme | ||
> [!NOTE] | ||
> This sketch will use the device settings file previously created to get its credentials and connect to WiFi and IoT Hub. | ||
> You will have to update the device logic on this one. | ||
1. Configure the Arduino build output for this sketch | ||
* Open the `.vscode/arduino.json` | ||
* Update the settings file with this line: | ||
```json | ||
{ | ||
"output": "./.build" | ||
} | ||
``` | ||
1. Upload this sketch to Arduino ESP32 | ||
* `Alt + Cmd + U` or `Alt + Ctrl + U` | ||
### Upload the device firmware to a Cloud Storage | ||
In this section, you create a cloud storage account and upload you device firmware to it. | ||
#### Create a storage account | ||
Every storage account must belong to an Azure resource group. A resourcegroup is a logical container for grouping your Azure services. When you create a storage account, you have the option to either create a new resource group, or use an existing resource group. This article shows howto create a new resource group. | ||
A **general-purpose v2** storage account provides access to all of theAzure Storage services: blobs, files, queues, tables, and disks. The steps outlined here create a general-purpose v2 storage account, but the steps to create any type of storage account are similar. For more information about types of storage accounts and other storage account settings, see [Azure storage account overview](storage-account-overview.md). | ||
To create a general-purpose v2 storage account in the Azure portal, follow these steps: | ||
1. On the Azure portal menu, select **All services**. In the list of resources, type **Storage Accounts**. As you begin typing, the list filters based on your input. Select **Storage Accounts**. | ||
1. On the **Storage Accounts** window that appears, choose **Add**. | ||
1. On the **Basics** tab, select the subscription in which to create the storage account. | ||
1. Under the **Resource group** field, select your desired resource group, or create a new resource group. For more information on Azure resource groups, see [Azure Resource Manager overview](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-overview). | ||
1. Next, enter a name for your storage account. The name you choose must be unique across Azure. The name also must be between 3 and 24 characters in length, and may include only numbers and lowercase letters. | ||
1. Select a location for your storage account, or use the default location. | ||
1. Select a performance tier. The default tier is *Standard*. | ||
1. Set the **Account kind** field to *Storage V2 (general-purpose v2)*. | ||
1. Specify how the storage account will be replicated. The default replication option is *Read-access geo-redundant storage (RA-GRS)*. For more information about available replication options, see [Azure Storage redundancy](https://docs.microsoft.com/en-us/azure/storage/common/storage-redundancy). | ||
1. Specify the access tier for blobs in the storage account. The default tier is *hot*. For more information about blob access tiers, see [Hot, cool, and archive access tiers for blobs](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-storage-tiers). | ||
1. To use Azure Data Lake Storage, choose the **Advanced** tab, and then set **Hierarchical namespace** to **Enabled**. For more information, see [Azure Data Lake Storage Gen2 Introduction](https://docs.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-introduction) | ||
1. Select **Review + Create** to review your storage account settings and create the account. | ||
1. Select **Create**. | ||
The following image shows the settings on the Basics tab for a new storage account: | ||
![https://docs.microsoft.com/en-us/azure/includes/media/storage-create-account-portal-include/account-create-portal.png](https://docs.microsoft.com/en-us/azure/includes/media/storage-create-account-portal-include/account-create-portal.png) | ||
#### Create a container | ||
1. Navigate to your new storage account in the Azure portal. | ||
1. In the left menu for the storage account, scroll to the **Blob service** section, then select **Containers**. | ||
1. Select the **+ Container** button. | ||
1. Type a name for your new container. The container name must be lowercase, must start with a letter or number, and can include only letters, numbers, and the dash (-) character. For more information about container and blob names, see [Naming and referencing containers, blobs, and metadata](https://docs.microsoft.com/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata). | ||
1. Set the level of public access to the container. | ||
`Blob (anonymous read access for blobs only)` | ||
1. Select **OK** to create the container. | ||
![./src/.assets/create-container.png](./src/.assets/create-container.png) | ||
#### Build the firmware binary | ||
1. Open the sketch repository with VS Code | ||
1. Update the `FIRMWARE_VERSION` | ||
```cpp | ||
#define FIRMWARE_VERSION "0.0.2" | ||
``` | ||
1. Build the firmware | ||
* `Alt + Cmd + R` or `Alt + Ctrl + R` | ||
#### Upload the binary to your storage account container | ||
1. Navigate to your new storage account container in the Azure portal. | ||
1. Select the **Upload** button. | ||
1. Click on the **Select file** button. | ||
1. On the `Open`Window, select the firmware binary from the sketch build directory `./.build/`.The default name is `ESP32_Device_OTA.ino.bin`. | ||
### Create a Firmware update OTA with device Twin | ||
In this section, you update your device twin to set a firmware update from the cloud portal. | ||
1. In your IoT hub navigation menu, open **IoT Devices**, then select the IoT device you created. | ||
1. Select the **Device Twin** button. | ||
1. Use the twin editor to update your device twin with this following statements | ||
```json | ||
{ | ||
"properties": { | ||
"desired": { | ||
"firmware": { | ||
"version": "0.0.2", | ||
"source": "https://<storage_account_name>.blob.core.windows.net/<container_name>/ESP32_Device_OTA.ino.bin" | ||
} | ||
} | ||
} | ||
``` | ||
1. Select the **Save** button. | ||
1. Select the **Refresh** button to review the reported properties and verify once the device successfully applied the firmware update | ||
```json | ||
{ | ||
"properties": { | ||
"reported": { | ||
"firmware": { | ||
"version": "0.0.2" | ||
} | ||
} | ||
} | ||
``` | ||
> [!NOTE] | ||
> On device Serial Monitor, you may see the device update done | ||
> Open VS Code and press `F1` or `Ctrl + Shift + P` to open command palette | ||
> Select `Arduino: Open Serial Monitor` command | ||
```bash | ||
git clone [email protected]:kbeaugrand/ESP32_AzureIoT_OTA.git | ||
``` | ||
> Debug: Begin request for: https://<storage_account_name>.blob.core.windows.net/<container_name>/ESP32_Device_OTA.ino.bin | ||
> Debug: Trying to start OTA with 1040864 bytes | ||
> Info: Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience! | ||
> Info: Written: 1040864 successfully | ||
> Info: OTA done! | ||
> Info: Update successfully completed. Rebooting. | ||
``` |
113 changes: 113 additions & 0 deletions
113
examples/ESP32_Device_Initiator/ESP32_Device_Initiator.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
#include <SPIFFSIniFile.h> | ||
#include <SPIFFS.h> | ||
|
||
const char *connectionString = "Type your Device Connection String"; | ||
const char *ssid = "Type here your WiFi SSID"; | ||
const char *password = "Type here your WiFi shared Key"; | ||
|
||
const char certificates[] = | ||
/* DigiCert Baltimore Root --Used Globally--*/ | ||
// This cert should be used when connecting to Azure IoT on the Azure Cloud available globally. When in doubt, use this cert. | ||
"-----BEGIN CERTIFICATE-----\r\n" | ||
"MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ\r\n" | ||
"RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD\r\n" | ||
"VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX\r\n" | ||
"DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y\r\n" | ||
"ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy\r\n" | ||
"VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr\r\n" | ||
"mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr\r\n" | ||
"IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK\r\n" | ||
"mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\r\n" | ||
"XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy\r\n" | ||
"dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye\r\n" | ||
"jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1\r\n" | ||
"BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3\r\n" | ||
"DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92\r\n" | ||
"9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx\r\n" | ||
"jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0\r\n" | ||
"Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz\r\n" | ||
"ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\r\n" | ||
"R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\r\n" | ||
"-----END CERTIFICATE-----\r\n"; | ||
|
||
void printErrorMessage(uint8_t e, bool eol = true) | ||
{ | ||
switch (e) { | ||
case SPIFFSIniFile::errorNoError: | ||
Serial.print("no error"); | ||
break; | ||
case SPIFFSIniFile::errorFileNotFound: | ||
Serial.print("file not found"); | ||
break; | ||
case SPIFFSIniFile::errorFileNotOpen: | ||
Serial.print("file not open"); | ||
break; | ||
case SPIFFSIniFile::errorBufferTooSmall: | ||
Serial.print("buffer too small"); | ||
break; | ||
case SPIFFSIniFile::errorSeekError: | ||
Serial.print("seek error"); | ||
break; | ||
case SPIFFSIniFile::errorSectionNotFound: | ||
Serial.print("section not found"); | ||
break; | ||
case SPIFFSIniFile::errorKeyNotFound: | ||
Serial.print("key not found"); | ||
break; | ||
case SPIFFSIniFile::errorEndOfFile: | ||
Serial.print("end of file"); | ||
break; | ||
case SPIFFSIniFile::errorUnknownError: | ||
Serial.print("unknown error"); | ||
break; | ||
default: | ||
Serial.print("unknown error value"); | ||
break; | ||
} | ||
if (eol) | ||
Serial.println(); | ||
} | ||
|
||
void setup() { | ||
Serial.begin(115200); | ||
pinMode(2, OUTPUT); | ||
|
||
Serial.println("Formating the SPIFFS partition"); | ||
SPIFFS.format(); | ||
|
||
// Launch SPIFFS file system | ||
if(!SPIFFS.begin(false, "/device")){ | ||
Serial.println("An Error has occurred while mounting SPIFFS"); | ||
return; | ||
} | ||
|
||
const size_t bufferLen = 80; | ||
char buffer[bufferLen]; | ||
|
||
const char *certFileName = "/device/ca.pem"; | ||
File writerCA = SPIFFS.open(certFileName, "w"); | ||
writerCA.print(certificates); | ||
writerCA.close(); | ||
|
||
const char *filename = "/device/config.ini"; | ||
|
||
File writerFile = SPIFFS.open(filename, "w"); | ||
|
||
writerFile.println("[core]"); | ||
writerFile.println("ssid = " + String(ssid)); | ||
writerFile.println("password = " + String(password)); | ||
writerFile.println("connectionString = " + String(connectionString)); | ||
writerFile.println("caPath = " + String(certFileName)); | ||
|
||
writerFile.println("[ntp]"); | ||
writerFile.println("hostname = pool.ntp.org"); | ||
|
||
writerFile.close(); | ||
|
||
Serial.printf("Used %d over %d bytes\n", SPIFFS.usedBytes(), SPIFFS.totalBytes()); | ||
digitalWrite(2, HIGH); | ||
} | ||
|
||
void loop() { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.