Set Up OTA Updates
Over-the-air updates let you deploy new firmware to ESP devices over WiFi without physical access to the serial port. This guide walks through creating the partition layout, building an OTA package, deploying it, and recovering with rollback if something goes wrong.
Create an OTA partition layout
Section titled “Create an OTA partition layout”OTA requires at least two application slots (ota_0 and ota_1) plus an otadata partition that tracks which slot is active. The esp_partition_create_ota tool generates this layout automatically.
-
Generate the partition table CSV:
esp_partition_create_ota({"flash_size": "4MB","app_size": "1MB"})This produces a table with
nvs,otadata,phy_init,ota_0,ota_1, and astoragepartition using whatever space remains. -
Convert the CSV to binary using ESP-IDF’s partition tool:
Terminal window python $IDF_PATH/components/partition_table/gen_esp32part.py \partitions.csv partitions.bin -
Flash the partition table to the device:
esp_flash_firmware({"port": "/dev/ttyUSB0","firmware_path": "partitions.bin","address": "0x8000"})
Build an OTA package
Section titled “Build an OTA package”The esp_ota_package_create tool bundles your firmware binary with a manifest containing version, SHA-256 hash, and timestamp into a zip archive.
esp_ota_package_create({ "firmware_path": "build/my_app.bin", "version": "1.2.0", "output_path": "releases/my_app-1.2.0-ota.zip"})The response includes the manifest contents and package size. The SHA-256 hash in the manifest can be used by the device to verify the firmware before applying it.
Deploy to a device
Section titled “Deploy to a device”Your device must be running an HTTP OTA server — either the ESP-IDF esp_https_ota component or a custom HTTP handler that accepts firmware binary data via POST.
-
Ensure the device is connected to the network and its OTA endpoint is reachable.
-
Deploy the package:
esp_ota_deploy({"package_path": "releases/my_app-1.2.0-ota.zip","target_url": "http://192.168.1.100/ota/update"}) -
The tool extracts
firmware.binfrom the zip and POSTs it to the target URL. A2xxHTTP response indicates the device accepted the update. -
The device typically reboots into the new firmware automatically. Monitor the serial output to confirm:
esp_serial_monitor({"port": "/dev/ttyUSB0","baud_rate": 115200,"duration_seconds": 10,"reset_on_connect": false})
Roll back to previous firmware
Section titled “Roll back to previous firmware”If the new firmware is broken or the device becomes unresponsive over the network, you can force a rollback via the serial port.
esp_ota_rollback({ "port": "/dev/ttyUSB0"})How rollback works internally
Section titled “How rollback works internally”The tool reads the partition table from the device to locate the otadata partition, then erases that region. On the next boot:
- The bootloader checks the otadata partition for a valid boot selection.
- Finding all
0xFF(erased state), it falls back to the factory app if one exists, orota_0otherwise. - The device boots the fallback firmware.
For more precise control over which partition to erase, use esp_partition_analyze to find the otadata offset and esp_flash_erase to clear it manually.