OTA Firmware Upgrades
ESP RainMaker OTA service provides a simple interface to upgrade the firmware on the nodes remotely. At a high level, you just need to upload the firmware image on some secure web server (https) and provide the url to the node.
ESP RainMaker also offers a firmware image hosting service as well as a web dashboard to make the process simpler.
Enabling OTA Upgrades in the Firmware
The ESP RainMaker agent provides a simple API to enable the OTA Upgrade functionality. It has 2 variants.
1. OTA Using Parameters
This is the simplest way of pushing out an OTA FW upgrade by "End Users" and can be triggered from the RainMaker CLI.
esp_rmaker_ota_config_t ota_config = {
.server_cert = ESP_RMAKER_OTA_DEFAULT_SERVER_CERT,
};
esp_rmaker_ota_enable(&ota_config, OTA_USING_PARAMS);
Sample usage can be found in the switch example.
2. OTA Using Topics
This is a more advanced way of pushing out an OTA FW Upgrade, avaiable to "Admin Users" and can be triggered from the RainMaker Dashboard.
esp_rmaker_ota_config_t ota_config = {
..server_cert = ESP_RMAKER_OTA_DEFAULT_SERVER_CERT,
};
esp_rmaker_ota_enable(&ota_config, OTA_USING_TOPICS);
Add this API in your firmware, compile and flash the image on your board and provision it using the RainMaker phone app (or CLI). The board will then be ready for OTA upgrade.
More details about the OTA APIs can be found here.
Setting up OTA Upgrade Image
Compile an ota upgrade firmware image as you would normally do, but ensure the following:
- The project name should be same as that used for the firmware already flashed on the node(s).
- The firmware version should be different than what the nodes already have (check
set(PROJECT_VER "1.0")
in the example's CMakeLists.txt).
If you miss out any of the above, the OTA upgrade will fail. You can change this behaviour by setting these config options:
CONFIG_ESP_RMAKER_SKIP_VERSION_CHECK=y
CONFIG_ESP_RMAKER_SKIP_PROJECT_NAME_CHECK=y
Upgrading the Firmware
OTA Using Params
For OTA using parameters, you will need the RainMaker CLI to upgrade the firmware. Please set it up as per the instructions here. Once done, follow these steps
$ cd /path/to/esp-rainmaker/cli
$ ./rainmaker.py login # Use the same credentials used in phone app for setting up the node
$ ./rainmaker.py getnodes # Just to verify that you see the node that you want to upgrade
$ ./rainmaker.py otaupgrade <node_id> <path_to_ota_fw_image>
As the firmware upgrade starts, you will see the progress as below:
$ ./rainmaker.py otaupgrade 7CDFA1XXXXXX ../examples/switch/switch-2.0.bin
Uploading OTA Firmware Image...
Checking esp.service.ota in node config...
Setting the OTA URL parameter...
OTA Upgrade Started. This may take time.
Getting OTA Status...
[19:49:50] in-progress : Downloading Firmware Image
[19:49:58] in-progress : Downloading Firmware Image
[19:50:07] in-progress : Downloading Firmware Image
[19:50:16] in-progress : Downloading Firmware Image
[19:50:25] in-progress : Downloading Firmware Image
[19:50:34] in-progress : Downloading Firmware Image
[19:50:43] success : OTA Upgrade finished successfully
How does this work?
This OTA service is built on top of the RainMaker Services concept. When you call esp_rmaker_ota_enable(&ota_config, OTA_USING_PARAMS)
, the OTA service gets added to the node configuration. It has 3 parameters:
- url (esp.param.ota_url)
- status (esp.param.ota_status)
- info (esp.param.ota_info)
When you use the otaupgrade command from the CLI, the following happens
- The CLI reads the firmware upgrade image from the path provided and uploads it to the RainMaker Cloud service.
- It gets back a pre-signed URL in return. Note that this URL is valid for a limited time (1 day currently, may change in future).
- It sets the url parameter with the value of this pre-signed URL.
- The node starts downloading the image and reports the status and additional information as it progresses.
- The CLI keeps querying this (using getparams) and shows the status.
- The OTA upgrade ends when the status changes to either "failed" or "success".
- If the status is reported as "success", the node boots up into the new firmware, 10 seconds after reporting "success".
- It then resets the values of all the 3 parameters to the defaults (i.e. blank)
OTA Using Topics
Before you can push out an OTA using Topics, you need to have admin access for the node. Please check here to find out how to get the admin access. Once done, please visit the ESP RainMaker Dashboard and follow the further steps.
Uploading the OTA Upgrade Image
- Go to the "Firmware Images" section in the sidebar on the Dashboard. Tap on "Add Image"
- Fill in the details in the pop-up window. You can skip the fw version and model (which is same as project name) as they will be read from the binary directly.
- Select the upgrade image just compiled and add it.
- The image should now be visible in the Firmware Images list.
Starting an OTA
- Check the OTA Image that you want to use for your OTA Upgrade in the list of OTA Images.
- Tap on the "Start OTA" button for that Image.
- Enter some name for the OTA Job and select the nodes which you want to upgrade.
For testing purpose, please select the "Force Push" option, so that the OTA job information is sent to the node right away. Else, the node(s) will get the OTA URL as per the OTA Upgrade policy defined (check during boot-up, check periodically, etc.), which can delay the actual Upgrade. Please check the
CONFIG_ESP_RMAKER_OTA_AUTOFETCH
andCONFIG_ESP_RMAKER_OTA_AUTOFETCH_PERIOD
to see how you can control this.
Monitoring an OTA Job
- Once you start an OTA, if it is successful, you will directly get a link to "Go to job details". Tap on it to see the status of your OTA Job. You can also browse to the OTA Job from the side panel.
- The OTA Job status page will give overall picture of the job. You can also view status of individual nodes.
- If you wish to cancel a job midway, you can do so, but the nodes who had already got the URL will continue with the upgrade.
How does this work?
As the name suggests, this uses dedicated topics for OTA Upgrades.
- When the node connects to the MQTT broker, it subscribes to the topic
node/<node_id>/otaurl
- Whenever an OTA is triggered from the dashboard (using force push option), the cloud service sends this information to the node on
node/<node_id>/otaurl
{
"url": "<ota_image_url>",
"ota_job_id": "<ota_job_id>",
"file_size": <num_bytes>
}
- The node then starts downloading the image from the received
<ota_image_url>
and publishes the progress onnode/<node_id>/otastatus
in this format:
{
"ota_job_id": "<ota_job_id>",
"status": "<in-progress/success/fail>",
"additional_info": "<additional_info>"
}
- OTA Job ends when all nodes have either reported success or fail.
Auto Fetch configuration
Most of the times, it is desired that the OTA upgrades are sent to the nodes in a staggered way, so as to not load the server with too many image download requests at the same time. Moreover, it is also possible that the node itself was offline when the cloud published to node/<node_id>/otaurl
and so, some other logic to fetch the upgrade info again is required.
When CONFIG_ESP_RMAKER_OTA_AUTOFETCH=y
is set , the node tries to fetch the OTA Upgrade periodically as per the interval specified by CONFIG_ESP_RMAKER_OTA_AUTOFETCH_PERIOD
. This is accomplished by publishing the following data to node/<node_id>/otafetch
:
{
“node_id": “<node_id>",
“fw_version": “<fw_version>"
}
If the cloud service finds any ota job pending for the node, it publishes it to node/<node_id>/otaurl
as specified above and the job starts.
Server Validation
You must have noticed that the OTA configuration accepts a server certificate (server_cert). This is used to validate the server from which the OTA firmware image is fetched and prevents DNS spoofing attacks. The default certificate (ESP_RMAKER_OTA_DEFAULT_SERVER_CERT) is used to validate the ESP RainMaker Firmware Image hosting server. If you plan to use your own server (valid only for OTA_USING_PARAMS), you can copy the appropriate server.crt file into your example's main/ folder and embed it into the binary using the below line in main/CMakeLists.txt
target_add_binary_data(${COMPONENT_TARGET} "server.crt" TEXT)
It can be accessed in your code using this
extern const uint8_t ota_server_cert[] asm("_binary_server_crt_start");
{
...
esp_rmaker_ota_config_t ota_config = {
.server_cert = (char *)ota_server_cert,
};
esp_rmaker_ota_enable(&ota_config, OTA_USING_PARAMS);
...
If you want to skip server authentication, or use HTTP server instead of HTTPS (Not recommended), please set CONFIG_OTA_ALLOW_HTTP=y
in your sdkconfig.