如何对 ESP32s3 Wifi Mesh 节点/子节点进行 OTA 更新?

How to OTA update ESP32s3 Wifi Mesh nodes/children?

提问人:Darren Morrison 提问时间:8/10/2023 最后编辑:mpromonetDarren Morrison 更新时间:11/19/2023 访问量:259

问:

ESP-IDF v5.1+。固定网关(root)。

我找不到有关仅使用 ESP-IDF 的 OTA 更新 WIFI MESH 节点的示例或文档。我无意使用 ESP-MDF 或 MESH-LITE,因为它们已经过时,并且对较新版本的 IDF 的支持很差。

我的网关能够使用和功能。是否有解决方案可以让节点使用相同的包装器并通过网关转发 GET 请求和响应?esp_https_ota()esp_http_client_perform()

网关和节点的固件版本不同,因此我无法直接从网关的APP分区读取固件。 .bin 文件托管在 EC2 服务器上,在使用 HTTPS 包装器更新根时按预期工作。

C ESP32 ESP-IDF

评论


答:

-1赞 Ryan 11/14/2023 #1

要使用 ESP32-S3 节点在 Wifi Mesh 网络上执行 OTA 更新,请按照以下步骤操作。该方法利用网关上的自定义 OTA 代理转发请求,并在节点上使用 ESP-IDF OTA 包装器来更新固件。

步骤 1:在网关上创建自定义 OTA 代理

在网关上将 OTA 代理实现为 HTTP 服务器。此服务器侦听 OTA 请求并将其转发到节点。然后,代理将节点的响应中继回客户端。

下面是网关 OTA 代理的代码:

#include <esp_http_server.h>

static httpd_handle_t server = NULL;

// OTA Handler which receives update requests and forwards to the node
static esp_err_t ota_handler(httpd_req_t *req) {
    // Extract node IP from the request headers
    char *node_ip = httpd_req_get_hdr_value_str(req, "X-Node-IP");
    if (node_ip == NULL) {
        // Respond with an error if the header is missing
        httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Node IP header is missing");
        return ESP_FAIL;
    }
    
    // Configure the HTTP client to forward the request
    esp_http_client_config_t client_cfg = {
        .url = node_ip, // URL is the node's IP address obtained from header
        .port = req->uri_port // Use the same port as the server
    };
    esp_http_client_handle_t client = esp_http_client_init(&client_cfg);

    // Forward the request to the node and fetch the response
    esp_err_t err = esp_http_client_perform(client);
    if (err != ESP_OK) {
        // Handle errors in forwarding
        httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Forwarding failed");
        esp_http_client_cleanup(client);
        return err;
    }

    // Allocate buffer for the response
    char *buffer = malloc(MAX_HTTP_OUTPUT_BUFFER);
    int content_len = esp_http_client_fetch_headers(client);
    esp_http_client_read(client, buffer, content_len);

    // Send the response back to the original requester
    httpd_resp_send(req, buffer, content_len);

    // Clean up and free allocated resources
    free(buffer);
    esp_http_client_cleanup(client);

    return ESP_OK;
}

// Function to start the OTA agent server
void start_ota_agent() {
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.server_port = 80;
    
    // Start the server
    if (httpd_start(&server, &config) == ESP_OK) {
        // Register OTA handler
        httpd_uri_t ota_uri = {
            .uri = "/ota",
            .method = HTTP_GET,
            .handler = ota_handler
        };
        httpd_register_uri_handler(server, &ota_uri);
    } else {
        ESP_LOGE("OTA", "Server start failed");
    }
}

调用以开始侦听网关上的 OTA 请求。start_ota_agent()

第 2 步:更新节点上的固件

节点使用 OTA 包装器从网关代理请求更新。

节点固件更新代码:

#include <esp_https_ota.h>

void update_firmware() {
    // HTTPS client configuration for the OTA update
    esp_http_client_config_t ota_client_cfg = {
        .url = "http://gateway_ip/ota", // URL to the gateway OTA agent
        .cert_pem = gateway_server_cert_pem_start // SSL certificate for the server
    };
    // Perform the OTA update
    if (esp_https_ota(&ota_client_cfg) != ESP_OK) {
        ESP_LOGE("OTA Update", "Firmware update failed");
        return;
    }
    // Reboot after successful update
    esp_restart();
}

确保替换为网关的实际 IP 地址,并在需要时提供正确的 SSL 证书。gateway_ip

总结

网关 OTA 代理:

  • 网关作为 HTTP 服务器,用于接收来自节点的 OTA 请求。

  • OTA 处理程序函数从请求标头中提取节点 IP 地址。

  • 它将请求转发到相应节点的 IP 地址和端口。

  • 它接收节点的响应并将其发送回原始请求者。

节点固件更新:

  • 节点使用 ESP-IDF OTA 封装器发起 OTA 更新。

  • 节点固件更新代码为 OTA 配置 HTTPS 客户端 请求。

  • 它指定网关 OTA 代理和 SSL 证书的 URL 如有必要。

  • 它使用 esp_https_ota() 触发 OTA 更新过程。

  • 成功更新后,它会重新启动设备以应用新的 固件。