Post

IOT - More ESP32 Remotely

IOT - More ESP32 Remotely

In-Depth Explanation of ESP32 Over-the-Air (OTA) Update

OTA (Over-the-Air) Updates allow firmware and configurations to be updated wirelessly without needing a physical connection to the ESP32. This is especially useful for IoT deployments where devices are often placed in hard-to-reach locations.

The ArduinoOTA library simplifies the process, providing the following capabilities:

  1. Firmware Updates: Upload new code remotely via Wi-Fi.
  2. Configuration Updates: Modify parameters like Wi-Fi credentials, MQTT topics, or other application settings.
  3. Security: OTA updates can be secured with password protection to prevent unauthorized access.

How OTA Works

  1. Arduino IDE Integration: After enabling OTA, the ESP32 will appear as a network port in the Arduino IDE for wireless programming.
  2. Two Steps for Update:
    • Initial Deployment: Upload the OTA-enabled firmware via USB.
    • Subsequent Updates: Use the OTA feature to wirelessly upload firmware or configurations.

Step-by-Step Guide to Enable OTA on ESP32

1. Initial Setup (Prerequisite)

  • Install the following in the Arduino IDE:
    • ESP32 Board Manager:
      1. Go to File > Preferences.
      2. In Additional Board Manager URLs, add:
        1
        
        https://dl.espressif.com/dl/package_esp32_index.json
        
      3. Go to Tools > Board > Boards Manager and install ESP32.
    • ArduinoOTA Library:
      1. Open Sketch > Include Library > Manage Libraries.
      2. Search for ArduinoOTA and install it.

2. OTA-Enabled Firmware for Initial Upload

Use the following code for the initial upload via USB:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <WiFi.h>
#include <ArduinoOTA.h>

// WiFi credentials
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

void setup() {
  Serial.begin(115200);

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected");

  // OTA setup
  ArduinoOTA.setHostname("ESP32_OTA"); // Set a unique hostname

  // Optional: Add OTA password for security
  ArduinoOTA.setPassword("YOUR_OTA_PASSWORD");

  // Start OTA service
  ArduinoOTA.begin();

  Serial.println("Ready for OTA updates");
}

void loop() {
  ArduinoOTA.handle(); // Handle OTA requests
}

3. Initial Deployment

  1. Connect your ESP32 to the computer via USB.
  2. In the Arduino IDE:
    • Select the correct Board: ESP32 Dev Module.
    • Select the Port (USB).
  3. Upload the firmware.

4. Subsequent OTA Updates

  1. Ensure ESP32 is Powered On and Connected to Wi-Fi:
    • After the initial firmware upload, the ESP32 will broadcast itself as a network port.
  2. Upload Over-the-Air:
    • In Arduino IDE, select the network port (e.g., ESP32_OTA).
    • Modify your code if needed.
    • Click Upload. The firmware will be sent wirelessly.

Security Best Practices for OTA

  1. Use a Strong Password: Set a strong password in the ArduinoOTA.setPassword() function to secure OTA updates.

  2. Secure Wi-Fi: Ensure your Wi-Fi network is protected with WPA2.

  3. Encrypt OTA Communication: While ArduinoOTA does not natively support encryption, you can use a secure communication library (like TLS) to further protect sensitive updates.


Troubleshooting OTA

  1. ESP32 Not Appearing in Network Ports:
    • Ensure the device is powered on and connected to the same network as your computer.
    • Disable firewalls that might block the OTA communication.
  2. Failed OTA Update:
    • Check Wi-Fi signal strength.
    • Verify the correct password and hostname.
  3. Debugging:
    • Use the Serial Monitor to see OTA-related logs from the ESP32.

Extending OTA for Configuration Updates

To allow configuration updates along with firmware:

  1. Create a specific OTA configuration mode in your code.
  2. Use an MQTT topic to trigger the configuration update remotely.
  3. Save updated configurations to non-volatile storage (e.g., ESP32’s EEPROM or SPIFFS).

This approach enables full remote management and makes your ESP32 IoT deployment flexible and scalable.

Bulk OTA Updates for a Group of ESP32 Devices

Updating multiple ESP32 devices wirelessly in a bulk or group setup requires a structured approach. Here’s how you can achieve it:


Approaches for Bulk OTA Updates

  1. OTA Using MQTT (Centralized Control)
    Push OTA updates to multiple ESP32 devices by sending firmware files and commands over MQTT.

  2. OTA Using Web Server
    Host the firmware on a central server, and the ESP32 devices periodically check and download updates.

  3. OTA Using Scripts and Tools
    Use Python scripts or specialized tools (e.g., espota.py provided by Espressif) to programmatically update devices in bulk.


Step-by-Step Guide: OTA Using MQTT

1. Architecture Overview

  • Each ESP32 subscribes to a unique topic (e.g., devices/device1/ota, devices/device2/ota).
  • The central MQTT broker sends update commands and firmware URLs.
  • ESP32 devices download and apply the new firmware.

2. Initial Setup on Each ESP32

Upload the following firmware via USB to each ESP32:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <WiFi.h>
#include <PubSubClient.h>
#include <Update.h>
#include <ArduinoOTA.h>

// WiFi credentials
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

// MQTT broker details
const char* mqtt_server = "YOUR_MQTT_BROKER_IP";
const char* ota_topic = "devices/device1/ota"; // Change this for each device

WiFiClient espClient;
PubSubClient client(espClient);

// OTA function
void performOTA(const char* url) {
  WiFiClient client;
  HTTPClient http;

  http.begin(client, url);
  int httpCode = http.GET();

  if (httpCode == HTTP_CODE_OK) {
    size_t contentLength = http.getSize();
    bool canBegin = Update.begin(contentLength);

    if (canBegin) {
      size_t written = Update.writeStream(http.getStream());

      if (written == contentLength && Update.end()) {
        Serial.println("OTA done!");
        ESP.restart();
      } else {
        Serial.println("OTA failed!");
      }
    } else {
      Serial.println("Not enough space for OTA");
    }
  } else {
    Serial.println("Failed to connect to OTA URL");
  }

  http.end();
}

void callback(char* topic, byte* payload, unsigned int length) {
  String message;
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }

  if (message.startsWith("http")) {
    Serial.println("Starting OTA from URL: " + message);
    performOTA(message.c_str());
  }
}

void setup() {
  Serial.begin(115200);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected");

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  while (!client.connected()) {
    if (client.connect("ESP32_Device1")) {
      client.subscribe(ota_topic);
    } else {
      delay(5000);
    }
  }
}

void loop() {
  client.loop();
}

3. Host Firmware File

  • Upload the new firmware to a web server or local file server.
  • Example:
    1
    
    http://your-server-ip/firmware.bin
    

4. Publish OTA Command via MQTT

Send an OTA update command to the relevant topic using mosquitto_pub or an MQTT client:

1
mosquitto_pub -h YOUR_MQTT_BROKER_IP -t "devices/device1/ota" -m "http://your-server-ip/firmware.bin"

This will trigger the OTA process on the specific ESP32.


Bulk Update Example (Multiple Devices)

  1. Assign each ESP32 a unique MQTT topic:
    • devices/device1/ota
    • devices/device2/ota
  2. Publish OTA commands to all topics:
    1
    2
    
    mosquitto_pub -h YOUR_MQTT_BROKER_IP -t "devices/device1/ota" -m "http://your-server-ip/firmware_v2.bin"
    mosquitto_pub -h YOUR_MQTT_BROKER_IP -t "devices/device2/ota" -m "http://your-server-ip/firmware_v2.bin"
    

Alternative Approach: Web Server Polling

  1. ESP32 devices periodically check a version file on a web server:
    • Version file (e.g., http://your-server-ip/version.txt) contains the latest firmware version.
    • If the version is higher than the current one, the ESP32 downloads and updates the firmware.
  2. Code for ESP32 to check and update:
    1
    2
    3
    4
    
    const char* version_url = "http://your-server-ip/version.txt";
    const char* firmware_url = "http://your-server-ip/firmware.bin";
    
    // Compare and perform OTA if necessary
    

Security Best Practices for Bulk OTA

  1. Encrypt OTA Communication:
    • Use HTTPS for firmware hosting.
    • Enable TLS for MQTT communication.
  2. Authenticate Devices:
    • Use device-specific MQTT credentials or tokens.
  3. Verify Firmware Integrity:
    • Sign firmware files and validate signatures on ESP32 before applying updates.

To generate a .bin file from an .ino Arduino sketch, follow these steps:


1. Compile the Sketch in Arduino IDE

  1. Open the Arduino IDE and load your .ino sketch.
  2. Select the correct board and port:
    • Go to Tools > Board and select your ESP32 board (e.g., “ESP32 Dev Module”).
    • Go to Tools > Port and select the connected COM port.
  3. Compile the sketch:
    • Click the Verify button (checkmark icon). This ensures your code compiles without errors.

2. Locate the Compiled .bin File

Once the sketch is successfully compiled, the Arduino IDE generates a .bin file. Here’s how to find it:

  1. Enable Verbose Output:
    • Go to File > Preferences.
    • Check the box for Show verbose output during: compilation.
    • Click OK.
  2. Recompile the Sketch:
    • Click the Verify button again.
  3. Locate the Temporary Directory:
    • During the compilation, look for a line in the verbose output like this:
      1
      
      .../AppData/Local/Temp/arduino_build_xxxxx/sketch_name.ino.bin
      
    • Copy the directory path from the output.
  4. Navigate to the Directory:
    • Open the file explorer and paste the path to locate the .bin file.

3. Alternative: Use PlatformIO (Optional)

If you prefer a more streamlined process, use PlatformIO (an extension for VS Code):

  1. Install PlatformIO in Visual Studio Code.
  2. Create a new project for the ESP32 and copy your .ino file into the src folder.
  3. Click Build in PlatformIO.
  4. The .bin file will be located in the /.pio/build/ directory.

4. Upload the .bin File to ESP32 Using OTA

Use the .bin file for Over-the-Air updates by hosting it on a web server or transferring it via MQTT, as explained earlier.

Conclusion

This setup allows for secure, scalable OTA updates for multiple ESP32 devices, ensuring minimal downtime and easy management of IoT deployments.

This post is licensed under CC BY 4.0 by the author.