求ESP32通过HTTP下载.bin文件实现OTA自动升级的Arduino示例代码
ESP32 HTTP OTA 升级实现方案
下面是基于ESP-IDF框架的实现代码,分为HTTP文件下载和OTA升级两个核心部分:
1. HTTP 下载.bin 文件(客户端模式)
这个模块负责从指定HTTP服务器下载固件文件,核心使用ESP-IDF的esp_http_client组件实现:
#include <stdio.h> #include <string.h> #include "esp_wifi.h" #include "esp_http_client.h" #include "esp_ota_ops.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" // WiFi配置信息,按需修改 #define WIFI_SSID "your_wifi_ssid" #define WIFI_PASS "your_wifi_password" // HTTP固件地址,按需修改 #define FIRMWARE_URL "http://your-server.com/firmware.bin" // WiFi连接函数 static void wifi_connect(void) { wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&cfg); esp_wifi_set_mode(WIFI_MODE_STA); wifi_config_t wifi_cfg = { .sta = { .ssid = WIFI_SSID, .password = WIFI_PASS, }, }; esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); esp_wifi_start(); esp_wifi_connect(); // 等待连接成功 while (1) { wifi_ap_record_t ap_info; esp_wifi_sta_get_ap_info(&ap_info); if (ap_info.rssi != 0) break; vTaskDelay(pdMS_TO_TICKS(500)); } } // HTTP下载固件的回调函数,边下载边写入OTA分区 static esp_err_t http_event_handler(esp_http_client_event_t *evt) { static esp_ota_handle_t ota_handle = 0; switch(evt->event_id) { case HTTP_EVENT_ON_CONNECTED: printf("Connected to HTTP server\n"); // 初始化OTA升级 const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL); esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &ota_handle); break; case HTTP_EVENT_ON_DATA: if (evt->data_len > 0 && ota_handle != 0) { esp_ota_write(ota_handle, evt->data, evt->data_len); printf("Written %d bytes to OTA partition\n", evt->data_len); } break; case HTTP_EVENT_ON_FINISH: printf("HTTP download finished\n"); // 完成OTA升级并重启 esp_ota_end(ota_handle); esp_ota_set_boot_partition(esp_ota_get_next_update_partition(NULL)); printf("OTA upgrade done, rebooting...\n"); esp_restart(); break; case HTTP_EVENT_ON_DISCONNECTED: printf("Disconnected from HTTP server\n"); break; default: break; } return ESP_OK; } // 启动OTA升级任务 void ota_upgrade_task(void *pvParameter) { wifi_connect(); esp_http_client_config_t config = { .url = FIRMWARE_URL, .event_handler = http_event_handler, .timeout_ms = 5000, }; esp_http_client_handle_t client = esp_http_client_init(&config); esp_err_t err = esp_http_client_perform(client); if (err == ESP_OK) { printf("HTTP status code: %d\n", esp_http_client_get_status_code(client)); } else { printf("HTTP request failed: %s\n", esp_err_to_name(err)); } esp_http_client_cleanup(client); vTaskDelete(NULL); }
2. 解析.bin 文件并完成OTA升级
上面的代码已将下载与OTA升级整合,核心逻辑可拆分单独实现,比如先将固件存到SPIFFS再升级:
// 从SPIFFS读取.bin文件执行OTA升级 esp_err_t ota_upgrade_from_spiffs(const char *file_path) { FILE *f = fopen(file_path, "rb"); if (!f) { printf("Failed to open firmware file\n"); return ESP_FAIL; } const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL); esp_ota_handle_t ota_handle; esp_err_t err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &ota_handle); if (err != ESP_OK) { fclose(f); return err; } uint8_t buffer[1024]; size_t bytes_read; while ((bytes_read = fread(buffer, 1, sizeof(buffer), f)) > 0) { err = esp_ota_write(ota_handle, buffer, bytes_read); if (err != ESP_OK) { fclose(f); esp_ota_abort(ota_handle); return err; } } fclose(f); err = esp_ota_end(ota_handle); if (err != ESP_OK) return err; err = esp_ota_set_boot_partition(update_partition); if (err != ESP_OK) return err; printf("OTA upgrade completed, rebooting...\n"); esp_restart(); return ESP_OK; }
关键配置与说明
- 分区表要求:项目
partitions.csv必须包含OTA分区,示例片段:# Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000, otadata, data, ota, 0xf000, 0x2000, app0, app, ota_0, 0x10000, 0x140000, app1, app, ota_1, 0x150000,0x140000, - 核心OTA API:
esp_ota_get_next_update_partition:获取可用OTA分区esp_ota_begin:初始化升级流程esp_ota_write:写入固件数据esp_ota_end:验证固件并结束写入esp_ota_set_boot_partition:设置下次启动分区
注意事项
- 确保WiFi连接稳定,避免下载中断导致升级失败
- 固件必须是适配ESP32的正确.bin格式,与分区表大小匹配
- 若开启固件签名验证,需确保服务器固件已签名并配置密钥
内容的提问来源于stack exchange,提问作者Joe Ijam
相关产品推荐
相关产品推荐

