ESP32学习笔记(基于IDF):基于OneNet的ESP32的OTA功能

目录

前言

本文是基于ESP32学习笔记(基于IDF):ESP32接入OneNET该片文章的延续,继成功接入OneNet后基于OneNet进行OTA的功能

一、相关知识

1、OTA框架

2、OTA分区

3、APP镜像

4、OTA流程

5、订阅、回复OTA升级通知消息格式

咱的ESP32需要订阅OneNet平台的升级topic,当需要升级时,平台会下发升级通知

这个是我们收到OneNet平台的升级通知后,设备进行应答回复的消息格式

6、MQTT协议和HTTP协议

HTTP :是为互联网内容(如网页、API)设计的请求-响应协议。

MQTT :是为物联网设备设计的发布-订阅协议。

特性 MQTT HTTP
通信模型 发布-订阅 请求-响应
工作方式 客户端连接到代理,订阅感兴趣的主题。当有客户端向该主题发布消息时,代理会将消息推送给所有订阅者。 客户端主动向服务器发起请求,服务器处理请求后返回一个响应。通信总是由客户端发起。
连接关系 多对多,通过代理解耦。发布者和订阅者不需要知道彼此的存在。 一对一,紧密耦合。客户端必须知道服务器的确切地址。

二、代码编写、操作流程

1、新建这两个文件,在里面写有关OTA的代码
2、在根目录的CMakeLists.txt文件下写入该语句,用来确认当前工程的版本

bash 复制代码
set(PROJECT_VER "1.0.0")

这样在编译的时候,构建系统就会把这个字符串(版本号)写入esp_app_desc_t这个结构体

3、启用APP的回滚功能,就是OTA后如果发现这个新程序不好使,则会自动返回运行OTA前的程序

在工程目录下,输入以下指令,开启工程配置

bash 复制代码
idf.py menuconfig

然后进到这个Bootloader 配置

然后启用这个APP回滚功能

4、在onenet_ota.c文件下写入如下代码

c 复制代码
#include "esp_ota_ops.h"   //引入 ESP32 OTA相关操作库
#include <stdio.h>
#include "esp_http_client.h"
#include "onenet_token.h"
#include "onenet_mqtt.h"
#include <string.h>
#include "cJSON.h"
#include "esp_https_ota.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

#define TAG  "onenet_ota"

#define TOKEN_VALID_TIMESTAMP   1791515811                //时间有效期

#define ONENET_OTA_URL    "http://iot-api.heclouds.com/fuse-ota"

static char target_version[32] = {0};
static int task_id = 0;
static bool ota_is_running = false;

const char* get_app_version()
{
    // 静态缓冲区,用于存储版本号(仅初始化一次,避免重复分配内存)
    static char app_version[32] = {0};
    // 如果缓冲区未初始化(首次调用),则读取版本信息
    if(app_version[0] == 0)
    {
        // 获取当前正在运行的固件分区(OTA 中可能有多个固件分区,这里定位当前激活的分区)
        const esp_partition_t * running = esp_ota_get_running_partition();
          // 存储固件描述信息的结构体(包含版本号、编译时间等)
        esp_app_desc_t app_desc;
        // 从当前运行的分区中读取固件描述信息(包括 version 字段)
        esp_ota_get_partition_description(running,&app_desc);
          // 将固件版本号(app_desc.version)复制到缓冲区中
        snprintf(app_version,sizeof(app_version),"%s",app_desc.version);
    }
    return app_version;
}

void set_app_valid(int valid)
{
     // 获取当前正在运行的固件分区
    const esp_partition_t * running = esp_ota_get_running_partition();
    esp_ota_img_states_t state; // 存储当前固件的状态(如:待验证、有效、无效等)
    // 获取当前固件分区的状态(检查是否处于"待验证"状态)
    if(esp_ota_get_state_partition(running,&state) == ESP_OK)
    {
        // 仅当固件处于"待验证"状态时,才执行标记操作
        // (OTA 升级后,新固件首次启动时会处于此状态,等待确认)
        if(state == ESP_OTA_IMG_PENDING_VERIFY)
        {
            if(valid)
            {
                 // 标记当前固件为有效,取消回滚(确认升级成功)
                esp_ota_mark_app_valid_cancel_rollback();
            }
            else
            {
                // 标记当前固件为无效,触发回滚到上一版本并重启(升级失败)
                esp_ota_mark_app_invalid_rollback_and_reboot();
            }
        }

    }
}

#define OTA_BUFF_LEN  1024
static uint8_t ota_data_buff[OTA_BUFF_LEN];
static int ota_data_size = 0;

esp_err_t _http_event_handler(esp_http_client_event_t *evt)
{
    switch(evt->event_id) {
        case HTTP_EVENT_ERROR:
            ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
            break;
        case HTTP_EVENT_ON_CONNECTED:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
            break;
        case HTTP_EVENT_HEADER_SENT:
            ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
            break;
        case HTTP_EVENT_ON_HEADER:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
            break;
        case HTTP_EVENT_ON_DATA:
        {
            ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
            printf("HTTP_EVENT_ON_DATA data=%.*s\r\n",evt->data_len,(char*)evt->data);
            int copy_len = 0;
            if(evt->data_len > OTA_BUFF_LEN - ota_data_size)
            {
                copy_len = OTA_BUFF_LEN - ota_data_size;
            }
            else
            {
                copy_len = evt->data_len;
            }
            memcpy(&ota_data_buff,evt->data,copy_len);
            ota_data_size += copy_len;
            break;
        }
            break;
        case HTTP_EVENT_ON_FINISH:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
            break;
        case HTTP_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
            break;
        case HTTP_EVENT_REDIRECT:
            ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT");
            break;
        default:break;
    }
    return ESP_OK;
}



static esp_err_t onenet_ota_http_connect(const char *url,esp_http_client_method_t method,const char* payload)
{
    esp_http_client_config_t config = {
        .url = url,
        .event_handler = _http_event_handler,
    };
    esp_http_client_handle_t client = esp_http_client_init(&config);

    char *token = (char*)malloc(256);
    memset(token,0,256);
    dev_token_generate(token,SIG_METHOD_SHA256,TOKEN_VALID_TIMESTAMP,ONENET_PRODUCT_ID,NULL,ONENET_PRODUCT_ACCESS_KEY);
    ESP_LOGI(TAG,"ota token:%s",token);
    // POST
    esp_http_client_set_method(client, method);
    esp_http_client_set_header(client, "Content-Type", "application/json");
    esp_http_client_set_header(client,"host","iot-api.heclouds.com");
    esp_http_client_set_header(client,"Authorization",token);
    if(payload)
    {
        ESP_LOGI(TAG,"post data:%s",payload);
        esp_http_client_set_post_field(client, payload, strlen(payload));
    }
    memset(ota_data_buff,0,sizeof(ota_data_buff));
    ota_data_size = 0;
    esp_err_t err = esp_http_client_perform(client);
    free(token);
    esp_http_client_cleanup(client);
    return err;
}

//检测升级任务
esp_err_t onenet_ota_check_task(const char* type,const char* version)
{
    char url[128];
    esp_err_t ret = ESP_FAIL;
    snprintf(url,256,ONENET_OTA_URL"/%s/%s/check?type=%s&version=%s",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME,type,version);
    if(ESP_OK == onenet_ota_http_connect(url,HTTP_METHOD_GET,NULL))
    {
        cJSON *root = cJSON_Parse((const char*)ota_data_buff);
        if(root)
        {
            cJSON* code_js = cJSON_GetObjectItem(root,"code");
            cJSON* data_js = cJSON_GetObjectItem(root,"data");
            cJSON* target_js = cJSON_GetObjectItem(data_js,"target");
            cJSON* tid_js = cJSON_GetObjectItem(data_js,"tid");
            if(code_js && cJSON_GetNumberValue(code_js) == 0)
            {
                if(target_js && tid_js)
                {
                    snprintf(target_version,sizeof(target_version),"%s",cJSON_GetStringValue(target_js));
                    task_id = cJSON_GetNumberValue(tid_js);
                    ret = ESP_OK;
                }
                
            }
            else
            {
                ESP_LOGI(TAG,"check ota task invalid code");
            }
            cJSON_Delete(root);
        }
    }
    return ret;
}


//上报版本号给OneNet
esp_err_t onenet_ota_upload_version(void)
{
    char url[128];
    char version_info[128];
    esp_err_t ret = ESP_FAIL;
    const char* version = get_app_version();
    snprintf(version_info,sizeof(version_info),"{\"s_version\":\"%s\", \"f_version\": \"%s\"}",version,version);
    snprintf(url,256,ONENET_OTA_URL"/%s/%s/version",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);
    if(ESP_OK == onenet_ota_http_connect(url,HTTP_METHOD_POST,version_info))
    {
        cJSON *root = cJSON_Parse((const char*)ota_data_buff);
        if(root)
        {
            cJSON* code_js = cJSON_GetObjectItem(root,"code");
            if(code_js && cJSON_GetNumberValue(code_js) == 0)
            {
                ret = ESP_OK;
            }
            cJSON_Delete(root);
        }
    }
    else
    {
        ESP_LOGI(TAG,"Upload version fail!");
        return ret;
    }
    return ret;
}


//上报固件下载进度
esp_err_t onenet_ota_upload_status(int tid,int step)
{
    char url[128];
    char payload[16];
    esp_err_t ret = ESP_FAIL;
    snprintf(url,sizeof(url),ONENET_OTA_URL"/%s/%s/%d/status",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME,tid);
    snprintf(payload,sizeof(payload),"{\"step\":%d} ",step);
    if(ESP_OK == onenet_ota_http_connect(url,HTTP_METHOD_POST,payload))
    {
        cJSON *root = cJSON_Parse((const char*)ota_data_buff);
        if(root)
        {
            cJSON* code_js = cJSON_GetObjectItem(root,"code");
            if(code_js && cJSON_GetNumberValue(code_js) == 0)
            {
                ret = ESP_OK;
            }
            cJSON_Delete(root);
        }
    }
    if(ret != ESP_OK)
    {
        ESP_LOGI(TAG,"Upload task status fail!");
    }
    return ret;
}


esp_err_t onenet_ota_init_cb(esp_http_client_handle_t client)
{
    static char token[256];
    memset(token,0,256);
    dev_token_generate(token,SIG_METHOD_SHA256,TOKEN_VALID_TIMESTAMP,ONENET_PRODUCT_ID,NULL,ONENET_PRODUCT_ACCESS_KEY);
    // POST
    esp_http_client_set_method(client, HTTP_METHOD_GET);
    esp_http_client_set_header(client, "Content-Type", "application/json");
    esp_http_client_set_header(client,"host","iot-api.heclouds.com");
    esp_http_client_set_header(client,"Authorization",token);
    return ESP_OK;
}

//下载固件
esp_err_t onenet_ota_download(int tid)
{
    char url[128];
    snprintf(url,sizeof(url),"http://iot-api.heclouds.com/fuse-ota/%s/%s/%d/download",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME,tid);
    esp_http_client_config_t http_cfg = 
    {
        .url = url,
    }; 
    esp_https_ota_config_t ota_cfg = 
    {
        .http_config = &http_cfg,
        .http_client_init_cb = onenet_ota_init_cb,
    };
    esp_err_t ota_ret = ESP_FAIL;
    ota_ret = esp_https_ota(&ota_cfg);
    if(ota_ret == ESP_OK)
    {
        ESP_LOGI(TAG,"Upgrade successful...");
    }
    else
    {
        ESP_LOGI(TAG,"Upgrade fail! Code:%d",ota_ret);
    }
    return ota_ret;
}

static void onenet_ota_task(void* param)
{
    esp_err_t ret = ESP_FAIL;
    //上报版本号
    ret = onenet_ota_upload_version();
    if(ret != ESP_OK)
    {
        ESP_LOGE(TAG,"Upload version fail!");
        goto delete_ota_task;
    }
    //检测升级任务
    ret = onenet_ota_check_task("1",get_app_version());
        if(ret != ESP_OK)
    {
        ESP_LOGE(TAG,"Check task fail!");
        goto delete_ota_task;
    }
    //上报任务升级状态 10%
    ret = onenet_ota_upload_status(task_id,10);
        if(ret != ESP_OK)
    {
        ESP_LOGE(TAG,"Upload status fail!");
        goto delete_ota_task;
    }
    //进行HTTP下载
    ret = onenet_ota_download(task_id);
        if(ret != ESP_OK)
    {
        ESP_LOGE(TAG,"download fail!");
        goto delete_ota_task;
    }
    //上报任务升级状态 100%
    ret = onenet_ota_upload_status(task_id,100);
        if(ret != ESP_OK)
    {
        ESP_LOGE(TAG,"Upload status fail!");
        goto delete_ota_task;
    }
    //重启
    esp_restart();
delete_ota_task:
    ota_is_running = false;
    vTaskDelete(NULL);
}

void onenet_ota_start(void)
{
    if(ota_is_running)
    {
        return;
    }
    ota_is_running = true;
    ESP_LOGI(TAG,"Start OTA");
    xTaskCreatePinnedToCore(onenet_ota_task,"onenet_ota",8192,NULL,2,NULL,0);
}

5、在onenet_ota.h文件下,写入如下代码

c 复制代码
#ifndef _ONENET_OTA_H_
#define _ONENET_OTA_H_
#include "esp_err.h"

const char* get_app_version(void);

void set_app_valid(int valid);

esp_err_t onenet_ota_upload_version(void);

void onenet_ota_start(void);

#endif

6、在onenet_mqtt.c文件下写入如下代码

c 复制代码
#include "onenet_mqtt.h"
#include "onenet_token.h"
#include "mqtt_client.h"
#include "esp_log.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "cJSON.h"
#include "onenet_dm.h"
#include "onenet_ota.h"

#define TAG "onenet"

static esp_mqtt_client_handle_t mqtt_handle = NULL;

static void onenet_property_ack(const char* id,int code,const char* msg);

static void onenet_ota_ack(const char* id, int code, const char* msg);

static void onenet_subscribe(void);

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    esp_mqtt_event_handle_t event = event_data;
    switch ((esp_mqtt_event_id_t)event_id) {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        onenet_subscribe();
        cJSON* property_js = onenet_property_upload();
        char* data = cJSON_PrintUnformatted(property_js);
        onenet_post_property_data(data);
        onenet_ota_upload_version();//上报版本号
        set_app_valid(true);   //设置当前程序是合法的
        cJSON_free(data);
        cJSON_Delete(property_js);
        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        break;

    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA:
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("DATA=%.*s\r\n", event->data_len, event->data);
        if(strstr(event->topic,"property/set"))
        {
            cJSON* property = cJSON_Parse(event->data);
            cJSON* id_js = cJSON_GetObjectItem(property,"id");
            onenet_property_handle(property);
            onenet_property_ack(cJSON_GetStringValue(id_js),200,"success");
            cJSON_Delete(property);
        }
        else if(strstr(event->topic,"ota/inform"))
        {
            cJSON* ota_js = cJSON_Parse(event->data);
            cJSON* id_js = cJSON_GetObjectItem(ota_js,"id");

            onenet_ota_ack(cJSON_GetStringValue(id_js),200,"success");
            cJSON_Delete(ota_js);

            //开始OTA升级流程
            onenet_ota_start();
        }
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        break;
    }
}
  
esp_err_t onenet_start(void)
{
    esp_mqtt_client_config_t mqtt_config;
    memset(&mqtt_config,0,sizeof(esp_mqtt_client_config_t));
    mqtt_config.broker.address.uri = "mqtt://mqtts.heclouds.com";
    mqtt_config.broker.address.port = 1883;

    mqtt_config.credentials.client_id = ONENET_DEVICE_NAME;
    mqtt_config.credentials.username = ONENET_PRODUCT_ID;
       
    static char token[256];
    dev_token_generate(token,SIG_METHOD_SHA256,2232933411,ONENET_PRODUCT_ID,NULL,ONENET_PRODUCT_ACCESS_KEY);
    mqtt_config.credentials.authentication.password = token;
    //将鉴权信息打印出来
    ESP_LOGI(TAG,"onenet connect->clientId:%s,username:%s,password:%s",
        mqtt_config.credentials.client_id,mqtt_config.credentials.username,
        mqtt_config.credentials.authentication.password);
    mqtt_handle = esp_mqtt_client_init(&mqtt_config);
    esp_mqtt_client_register_event(mqtt_handle,ESP_EVENT_ANY_ID,mqtt_event_handler,NULL);
    return esp_mqtt_client_start(mqtt_handle);
}

static void onenet_property_ack(const char* id, int code, const char* msg)
{
    char topic[128];
    snprintf(topic,128,"$sys/%s/%s/thing/property/set_reply",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);
    cJSON* reply_js = cJSON_CreateObject();
    cJSON_AddStringToObject(reply_js,"id",id);
    cJSON_AddNumberToObject(reply_js,"code",code);
    cJSON_AddStringToObject(reply_js,"msg",msg);
    char* data = cJSON_PrintUnformatted(reply_js);
    esp_mqtt_client_publish(mqtt_handle,topic,data,strlen(data),1,0);
    cJSON_free(data);
    cJSON_Delete(reply_js);
}


static void onenet_ota_ack(const char* id, int code, const char* msg)
{
    char topic[128];
    snprintf(topic,128,"$sys/%s/%s/thing/ota/inform_reply",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);
    cJSON* reply_js = cJSON_CreateObject();
    cJSON_AddStringToObject(reply_js,"id",id);
    cJSON_AddNumberToObject(reply_js,"code",code);
    cJSON_AddStringToObject(reply_js,"msg",msg);
    char* data = cJSON_PrintUnformatted(reply_js);
    esp_mqtt_client_publish(mqtt_handle,topic,data,strlen(data),1,0);
    cJSON_free(data);
    cJSON_Delete(reply_js);
}



static void onenet_subscribe(void)
{
    char topic[128];
    sniprintf(topic,128,"$sys/%s/%s/thing/property/post/reply",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);
    esp_mqtt_client_subscribe_single(mqtt_handle,topic,1);
    //订阅属性设置主题
    sniprintf(topic,128,"$sys/%s/%s/thing/property/set",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);
    esp_mqtt_client_subscribe_single(mqtt_handle,topic,1);
    //订阅OTA升级通知主题
    sniprintf(topic,128,"$sys/%s/%s/ota/inform",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);
    esp_mqtt_client_subscribe_single(mqtt_handle,topic,1);
}

esp_err_t onenet_post_property_data(const char* data)
{
    char topic[128];
    snprintf(topic,128,"$sys/%s/%s/thing/property/post",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);
    ESP_LOGI(TAG,"Upload topic:%s,payload:%s",topic,data);
    return esp_mqtt_client_publish(mqtt_handle,topic,data,strlen(data),1,0);
}

7、在onenet_mqtt.h文件下写入如下代码

c 复制代码
#ifndef _ONENET_MQTT_H_
#define _ONENET_MQTT_H_
#include "esp_err.h"

//产品ID
#define ONENET_PRODUCT_ID            "E3Sgq5fGjC"  
//产品密钥
#define ONENET_PRODUCT_ACCESS_KEY    "a82bv2/LWRePdSfT+cmRDw2Jt+8bl3NZJxOxbdN3O6M="
//设备名称                  
#define ONENET_DEVICE_NAME           "esp32led01"

esp_err_t onenet_start(void);

esp_err_t onenet_post_property_data(const char* data);

#endif

8、在onenet.c文件下写入如下代码

c 复制代码
#include <stdio.h>
#include "onenet_mqtt.h"
#include "wifi_manager.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/task.h"
#include "onenet_dm.h"
#include "esp_log.h"

static EventGroupHandle_t wifi_ev = NULL;
#define WIFI_CONNECT_BIT   BIT0
#define TAG "app_main"
/**
 * wifi事件回调函数
 * @param ev wifi事件
 * @return 无
 */
static void wifi_state_callback(WIFI_STATE state)
{
    if(state == WIFI_STATE_CONNECTED)
    {
        xEventGroupSetBits(wifi_ev,WIFI_CONNECT_BIT);
    }
}

void app_main(void)
{
    esp_err_t ret;

        // 1. 初始化 NVS 闪存(必须处理返回值!)
    ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        // NVS 分区满了或版本不兼容,尝试擦除后重新初始化
        ESP_LOGE(TAG, "NVS init failed, try to erase...");
        ret = nvs_flash_erase();
        if (ret != ESP_OK) {
            ESP_LOGE(TAG, "NVS erase failed: %s", esp_err_to_name(ret));
            return; // 无法修复,直接退出
        }
        ret = nvs_flash_init(); // 重新初始化
    }
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "NVS init failed: %s", esp_err_to_name(ret));
        return; // NVS 初始化失败,无法继续
    }
    ESP_LOGI(TAG, "NVS init success");

    // 2. 创建事件组(用于同步 Wi-Fi 连接状态)
    // 事件组是 FreeRTOS 提供的同步机制,这里用于标记 Wi-Fi 是否连接成功
    wifi_ev = xEventGroupCreate();
    // 3. 初始化 Wi-Fi 管理器,并注册状态回调函数
    // wifi_manager_init:初始化 Wi-Fi 相关资源(如配置 Wi-Fi 模式、注册事件处理等)
    // wifi_state_callback:自定义回调函数,用于接收 Wi-Fi 连接/断开等状态通知
    onenet_dm_init();
    wifi_manager_init(wifi_state_callback);
    // 4. 调用 Wi-Fi 管理器连接指定的 Wi-Fi 热点
    // 参数:Wi-Fi 热点名称(SSID)为 "Lymow",密码为 "1415926535"
    wifi_manager_connect("Lymow","1415926535");//连接的WIFI用户名跟密码
    EventBits_t ev;
    while(1)
    {
        //等待WIFI连接成功,然后才开始连接onenet
        ev = xEventGroupWaitBits(wifi_ev,WIFI_CONNECT_BIT,pdTRUE,pdFALSE,pdMS_TO_TICKS(10*1000));
        if(ev & WIFI_CONNECT_BIT)
        {
            // Wi-Fi 已就绪,启动 OneNet 平台连接(如 MQTT 连接)
            onenet_start();
        }
    }
}

9、输入以下指令进入配置菜单

10、在这个路径下,选择第三个选项,一个出厂默认固件+两个OTA分区

11、在这个路径下,打开HTTP之中OTA的功能,不过正式产品的开发不能用HTTP来OTA,得用HTTPS,因为HTTP是不加密的,很危险,这个只能用来在本地测试OTA流程是否跑通

12、flash这里选择4M,因为我的C3芯片模组的FLAH最大是4M

13、主频选择160M,根据自己的芯片选择最大即可

14、在CMakeLists文件下写入如下代码

bash 复制代码
idf_component_register(SRCS "iot/onenet_dm.c" "iot/onenet_token.c" "iot/wifi_manager.c" "iot/onenet_mqtt.c" "iot/onenet_ota.c" "onenet.c"
                    INCLUDE_DIRS "." "iot")

15、在终端,使用以下指令对工程进行编译

bash 复制代码
idf.py build

16、编译成功

17、使用以下指令把程序下载进板子,并打开监控

bash 复制代码
idf.py flash monitor

18、可以看到程序跑起来了,上报版本号之后,OneNet平台进行了回复

19、我们把软件版本改成1.0.1,然后重新编译一个固件

20、我们在OneNet平台点击添加升级包

21、这里填一下,然后上传固件

22、点这个验证升级

23、这里填一下,然后开始验证

24、升级成功

25、可以看到平台这边也显示验证成功了

相关推荐
陈天伟教授2 小时前
基于学习的人工智能(5)机器学习基本框架
人工智能·学习·机器学习
初願致夕霞2 小时前
学习笔记——基础hash思想及其简单C++实现
笔记·学习·哈希算法
小女孩真可爱2 小时前
大模型学习记录(五)-------调用大模型API接口
pytorch·深度学习·学习
hd51cc2 小时前
C++ 学习笔记 名称
笔记·学习
t***L2662 小时前
Python物联网案例
物联网
摇滚侠3 小时前
2025最新 SpringCloud 教程,负载均衡 API 测试,笔记10
笔记·spring cloud·负载均衡
TH_13 小时前
腾讯云-(3)-Linux宝塔面板使用
linux·云计算·腾讯云
风123456789~4 小时前
【OceanBase专栏】OB租户-创建实验
数据库·笔记·oceanbase
cmcm!4 小时前
学习笔记1
数据库·笔记·学习