ESP32 IDF 连接阿里云物联网平台进行一个OTA升级

ESP32 IDF 连接阿里云物联网平台进行一个OTA升级

1、阿里云平台进行一个–产品–>设备创建

1.1、选择控制台

在这里插入图片描述

1.2、搜索找到物联网平台

在这里插入图片描述

1.3、选择公共示例

在这里插入图片描述

1.4、创建一个产品–ESP32Test

在这里插入图片描述

1.4.1、

输入产品名称、自定义品类、直连设备、WiFi连接方式、其余保持默认别去动。
在这里插入图片描述

1.5、在对应产品下创建设备

在这里插入图片描述

1.5.1、

输入设备名、进行一个设备用途备注
在这里插入图片描述

1.5.2、

设备创建成功,目前设备显示未激活,我们前往代码部分
在这里插入图片描述

2、直接创建一个基础示例,从零开始

在这里插入图片描述

2.1、main.c部分

主要就是进行一个NVS初始化,然后进行一个连接WiFi的操作,

#include <stdio.h>
#include "wifi.h"

/*
    函数内容:初始化NVS
    函数参数:无
    返回值:  无
*/
void Init_NVS(void)
{
    esp_err_t ret = nvs_flash_init(); // 初始化NVS

    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {                                       // 如果NVS存储不包含空页或者NVS库存在新的版本
        ESP_ERROR_CHECK(nvs_flash_erase()); // 擦除NVS
        ret = nvs_flash_init();             // 重新初始化NVS
    }

    ESP_ERROR_CHECK(ret); // 再次检测返回值
}
void app_main(void)
{
    //初始化NVS
    Init_NVS();

    //进行WiFi连接
    wifi_init_sta("Xiaomi_F617", (uint8_t)strlen("Xiaomi_F617"), "chenlong", (uint8_t)strlen("chenlong"));
    
    while (1)
    {
         vTaskDelay(pdMS_TO_TICKS(100));
    }
}

2.2、wifi.c

主要就是进行一个WiFi连接,WiFi连接成功之后进行一个阿里云连接,依据ESP32WiFiSTA示例进行改动,注释都已经打全,不理解或者注释有误的欢迎评论区讨论

#include "wifi.h"
#include "ALY.h"

static EventGroupHandle_t s_wifi_event_group; // wifi事件组句柄

static const char *WIFI_TAG = "wifi station"; // wifi部分日志标记

static int s_retry_num = 0; // 记录wifi重连的次数

/**
 *  函数内容:STA模式回调函数,处理连接WIFI的相关事件
 *  函数参数:
 *          void *arg-----------------------空指针,具体作用不清楚
 *          esp_event_base_t event_base-----WIFI事件类型
 *          int32_t event_id---------------WIFI事件ID
 *          void *event_data---------------事件数据
 */
static void STA_event_handler(void *arg, esp_event_base_t event_base,
                              int32_t event_id, void *event_data)
{

    // 事件为WIFI事件且事件ID为WIFI事件开始
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
    {
        esp_wifi_connect(); // 连接WIFI
    }
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        // 如果事件为wifi事件且事件ID为wifi事件连接失败
        if (s_retry_num < STA_EXAMPLE_ESP_MAXIMUM_RETRY)
        { // 如果重连次数少与规定次数

            esp_wifi_connect(); // 重新连接

            s_retry_num++; // 重连次数自增

            ESP_LOGI(WIFI_TAG, "retry to connect to the AP"); // 打印日志--重新连接wifi
        }
        else
        {
            xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); // 如果大于规定次数,事件组标志设置为wifi连接失败

            ESP_LOGI(WIFI_TAG, "connect to the AP fail"); // 打印日志,连接失败
        }
    }
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    { // 如果事件是IP事件,且得到了IP
        ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;

        ESP_LOGI(WIFI_TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); // 打印日志--打印得到的IP号

        s_retry_num = 0; // 清除重新连接次数

        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); // 事件组标志位设置为wifi连接成功
    }
}

/*
 *  函数名称:wifi STA模式初始化
 *  函数参数:
 *             const char *WifiName---WiFi名称
 *             uint8_t name_len-------WiFi名称长度
 *             const char *WifiKey----WiFi密码
 *             uint8_t key_len--------WiFi密码长度 
 *  返回值:  无
 */
void wifi_init_sta(const char *WifiName, uint8_t name_len, const char *WifiKey, uint8_t key_len)
{
    esp_netif_t *sta_netif = NULL;

    // 因为wifi的连接是需要建立时间的,所以需要创建一个事件标示组,通过事件标志组等待wifi连接。
    s_wifi_event_group = xEventGroupCreate(); // 创建一个事件组

    ESP_ERROR_CHECK(esp_netif_init()); // 创建一个 LwIP 核心任务,并初始化 LwIP 相关工作

    ESP_ERROR_CHECK(esp_event_loop_create_default()); // 创建默认事件循环--不断的接收注册进事件循环内的事件

    sta_netif = esp_netif_create_default_wifi_sta(); // 创建有 TCP/IP 堆栈的默认网络接口实例绑定 station

    /* 使用WIFI_INIT_CONFIG_DEFAULT() 来获取一个默认的wifi配置参数结构体变量*/
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();

    /* 根据cfg参数初始化wifi连接所需要的资源 */
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    esp_event_handler_instance_t instance_any_id; // 初始化事件id

    esp_event_handler_instance_t instance_got_ip;
    /* 将事件处理程序注册到系统默认事件循环,分别是WiFi事件和IP地址事件 */
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,         // wifi事件
                                                        ESP_EVENT_ANY_ID,   // 注册回调对于任何的事件
                                                        &STA_event_handler, // 回调函数名
                                                        NULL,               // 传入的参数
                                                        &instance_any_id)); // 事件id
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &STA_event_handler,
                                                        NULL,
                                                        &instance_got_ip));

    /* 定义WiFi连接的ssid和password参数 */
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = STA_EXAMPLE_ESP_WIFI_SSID,     // 要连接的wifi名称
            .password = STA_EXAMPLE_ESP_WIFI_PASS, // 要连接的wifi密码
            /* Setting a password implies station will connect to all security modes including WEP/WPA.
             * However these modes are deprecated and not advisable to be used. Incase your Access point
             * doesn't support WPA2, these mode can be enabled by commenting below line */
            .threshold.authmode = WIFI_AUTH_WPA2_PSK, // WiFi的安全配置
        },
    };

    memset(wifi_config.sta.ssid,0,strlen((const char *)wifi_config.sta.ssid));      //清除原有WiFi名称    

    memset(wifi_config.sta.password,0,strlen((const char *)wifi_config.sta.password));  //清除原有WiFi密码

    memcpy(wifi_config.sta.ssid, WifiName, name_len);   //拷贝新WiFi名称

    memcpy(wifi_config.sta.password, WifiKey, key_len); //拷贝新WiFi密码

    /* 设置WiFi的工作模式为 STA */
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));

    /* 设置WiFi连接的参数,主要是ssid和password */
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));

    /* 启动WiFi连接 */
    ESP_ERROR_CHECK(esp_wifi_start());

    ESP_LOGI(WIFI_TAG, "wifi_init_sta finished.");

    /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
     * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
    /* 定义一个事件位变量来接收事件标志组等待函数的返回值 */
    EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,                 /* 需要等待的事件标志组的句柄 */
                                           WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, /* 需要等待的事件位 */
                                           pdFALSE,                            /* 为pdFALSE时,当等待到事件满足任务唤醒事件时,系统不会清除指定的事件标志位*/
                                           pdFALSE,                            /* 为pdFALSE时,设置的这些事件位任意一个置1就会返回,为pdTRUE则需全为1才返回 */
                                           portMAX_DELAY);                     /* 设置为最长阻塞等待时间,单位为时钟节拍 */

    /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
     * happened. */

    if (bits & WIFI_CONNECTED_BIT)
    {
        /* WiFi连接成功事件 */
        ESP_LOGI(WIFI_TAG, "connected to ap SSID:%s password:%s",
                 wifi_config.sta.ssid, wifi_config.sta.password);
                 
        //连接阿里云
        user_mqtt_app_start();
    }
    else if (bits & WIFI_FAIL_BIT)
    {
        /* WiFi连接失败事件 */
        ESP_LOGI(WIFI_TAG, "Failed to connect to SSID:%s, password:%s",
                 wifi_config.sta.ssid, wifi_config.sta.password);
    }
    else
    {
        ESP_LOGE(WIFI_TAG, "UNEXPECTED EVENT"); /* 没有等待到事件 */
    }
}
2.2.1、wifi.h

对一些宏定义进行声明

#ifndef __WIFI_H
#define __WIFI_H

#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "lwip/err.h"
#include "lwip/sys.h"

#include "esp_attr.h"
#include "esp_sleep.h"
#include "string.h"

#define STA_EXAMPLE_ESP_WIFI_SSID "Redmi"      // STA 默认wifi名称

#define STA_EXAMPLE_ESP_WIFI_PASS "1234567890" // STA 默认wifi密码

#define STA_EXAMPLE_ESP_MAXIMUM_RETRY 5        // STA 最大重连次数

#define WIFI_CONNECTED_BIT BIT0 // wifi连接成功位

#define WIFI_FAIL_BIT BIT1      // wifi连接失败位

void wifi_init_sta(const char * WifiName, uint8_t name_len, const char * WifiKey, uint8_t key_len);

#endif
2.3.1、aly.c

主要是进行一个阿里云的一个连接、连接成功之后在MQTT事件回调函数处对收到的阿里云数据进行一个分析处理,如果是OTA—topic则进行一个json数据解析,获取url,然后进行一个OTA升级,升级完成之后给阿里云部分进行一个进度上报。然后复位芯片,开始运行更新之后的程序

#include "ALY.h"

/*
    函数内容:HTTP事件回调
    函数参数:
            esp_http_client_event_t *evt--事件指针
    返回值:esp_err_t--错误代码
*/
static esp_err_t _http_event_handler(esp_http_client_event_t *evt)
{
    switch (evt->event_id) {
    case HTTP_EVENT_ERROR:
        ESP_LOGD(MQTT_TAG, "HTTP_EVENT_ERROR");
        break;
    case HTTP_EVENT_ON_CONNECTED:
        ESP_LOGD(MQTT_TAG, "HTTP_EVENT_ON_CONNECTED");
        break;
    case HTTP_EVENT_HEADER_SENT:
        ESP_LOGD(MQTT_TAG, "HTTP_EVENT_HEADER_SENT");
        break;
    case HTTP_EVENT_ON_HEADER:
        ESP_LOGD(MQTT_TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
        break;
    case HTTP_EVENT_ON_DATA:
        ESP_LOGD(MQTT_TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
        break;
    case HTTP_EVENT_ON_FINISH:
        ESP_LOGD(MQTT_TAG, "HTTP_EVENT_ON_FINISH");
        break;
    case HTTP_EVENT_DISCONNECTED:
        ESP_LOGD(MQTT_TAG, "HTTP_EVENT_DISCONNECTED");
        break;
    }
    return ESP_OK;
}

/*
    函数内容:MQTT事件回调
    函数参数:
            esp_mqtt_event_handle_t event--事件参数
    返回值:esp_err_t--错误代码
*/
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    esp_mqtt_client_handle_t client = event->client;    //事件句柄

    int msg_id; //消息ID号

    // 根据事件ID确定事件内容
    switch (event->event_id)
    {
    case MQTT_EVENT_CONNECTED: // MQTT连接成功事件
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_CONNECTED");
        // 使用QOS订阅指定主题
        msg_id = esp_mqtt_client_subscribe(client, AliyunSubscribeTopic_user_get, 0); // 订阅阿里云自定义消息 topic

        msg_id = esp_mqtt_client_subscribe(client, AliyunOTAupgrade, 0); // 订阅阿里云OTA topic

        ESP_LOGI(MQTT_TAG, "sent subscribe successful, msg_id=%d", msg_id);

        break;
    case MQTT_EVENT_DISCONNECTED: // MQTT断开连接
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DISCONNECTED");
        break;

    case MQTT_EVENT_SUBSCRIBED: // MQTT订阅成功事件
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);

        // 发布自定义topic 测试信息
        msg_id = esp_mqtt_client_publish(client, AliyunPublishTopic_user_update, mqtt_publish_Testdata, strlen(mqtt_publish_Testdata), 0, 0);

        // 上报阿里云OTA版本
        msg_id = esp_mqtt_client_publish(client, AliyunOTAInform, mqtt_OTA_Data, strlen(mqtt_OTA_Data), 0, 0);

        ESP_LOGI(MQTT_TAG, "sent publish successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED: // MQTT订阅失败事件
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED: // MQTT发布事件
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA: // MQTT接收到数据事件
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DATA");
        printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("DATA=%.*s\r\n", event->data_len, event->data);

        // 根据阿里云topic进行数据解析
        Get_ALY_Topic(event->topic, event->data);
        break;
    case MQTT_EVENT_ERROR: // MQTT错误事件
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_ERROR");
        break;
    default: // 其他事件
        ESP_LOGI(MQTT_TAG, "Other event id:%d", event->event_id);
        break;
    }
    return ESP_OK;
}

// MQTT事件回调
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    ESP_LOGD(MQTT_TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
    mqtt_event_handler_cb(event_data);
}

/*
    函数内容:进行阿里云连接
    函数参数:无
    返回值:  无
*/

void user_mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
        .host = Aliyun_host,    //目标服务端域名
        .port = Aliyun_port,    //目标服务端端口
        .client_id = Aliyun_client_id,  //目标服务端id
        .username = Aliyun_username,    //目标服务端用户名
        .password = Aliyun_password,    //目标服务端密码

    };
    client = esp_mqtt_client_init(&mqtt_cfg);                                             // 创建MQTT客户端句柄
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client); // 注册MQTT事件
    esp_mqtt_client_start(client);                                                        // 启动MQTT客户端
}

/*
    函数内容:解析阿里云的OTA升级数据--并下载更新内容
    函数参数:const char *Data---阿里云下发的数据
    返回值    无
*/

static esp_err_t Parse_Data(const char *Data)
{
    char ALY_url[OTA_URL_SIZE] = {0};
    // char *str;

    cJSON *root = NULL;
    root = cJSON_Parse(Data);

    cJSON *code = cJSON_GetObjectItem(root, "code");    //状态码
    ESP_LOGI(MQTT_TAG, "Code:%s", code->valuestring);

    cJSON *data = cJSON_GetObjectItem(root, "data");    //数据字段名

    cJSON *size = cJSON_GetObjectItem(data, "size");    //升级包文件大小,单位:字节。
    ESP_LOGI(MQTT_TAG, "Size:%d", size->valueint);

    cJSON *sign = cJSON_GetObjectItem(data, "sign");    //OTA升级包文件的签名。
    ESP_LOGI(MQTT_TAG, "Sign:%s", sign->valuestring);

    cJSON *version = cJSON_GetObjectItem(data, "version");  //设备升级包的版本信息。
    ESP_LOGI(MQTT_TAG, "Version:%s", version->valuestring);

    cJSON *signMethod = cJSON_GetObjectItem(data, "signMethod");    //签名方法。取值:SHA256,MD5
    ESP_LOGI(MQTT_TAG, "SignMethod:%s", signMethod->valuestring);

    cJSON *url = cJSON_GetObjectItem(data, "url");  //升级包在对象存储(OSS)上的存储地址
    ESP_LOGI(MQTT_TAG, "URL:%s", url->valuestring);

    memcpy(ALY_url, url->valuestring, strlen(url->valuestring)); // https升级时使用
    /*str = strstr(url->valuestring, "//iot");  //HTTP升级时使用
    if(str!=NULL)
    {
        ESP_LOGI(MQTT_TAG, "Test:%s", str);
        sprintf(ALY_url, "http:%s", str);
        ESP_LOGI(MQTT_TAG, "ALY_url:%s", ALY_url);
    }*/

    cJSON *md5 = cJSON_GetObjectItem(data, "md5");  //当签名方法为MD5时,除了会给sign赋值外还会给md5赋值。
    ESP_LOGI(MQTT_TAG, "Md5:%s", md5->valuestring);

    cJSON *id = cJSON_GetObjectItem(root, "id");    //消息ID号。每个消息ID在当前设备中具有唯一性。
    ESP_LOGI(MQTT_TAG, "ID:%d", id->valueint);

    cJSON *message = cJSON_GetObjectItem(root, "message");  //结果信息。
    ESP_LOGI(MQTT_TAG, "Message:%s", message->valuestring);

    cJSON_Delete(root); //释放json资源
    root = NULL;

    esp_http_client_config_t config = { 
        .url = ALY_url,                     //升级包地址
        .cert_pem = (char *)server_cert_pem_start,  //设备证书校验
        .event_handler = _http_event_handler,       //http回调
        .keep_alive_enable = true,                  //保持活跃
    };

    esp_err_t ret = esp_https_ota(&config);         //开始进行OTA升级

    return ret;
}

/*
    函数内容:通过阿里云下发的topic进行对应的数据解析
    函数参数:
            const char *topic---topic数据
            const char *data----内容数据
    返回值:无
*/
void Get_ALY_Topic(const char *topic, const char *data)
{
    if (strstr(topic, "/ota/device/upgrade/a1pVSbsTyJb/test") != NULL) // 如果是阿里云的OTA升级数据
    {
        esp_err_t ret = 0;      //错误代码变量

        int msg_id=0;           //消息ID号

        ESP_LOGI(MQTT_TAG, "OTA Data");

        ret = Parse_Data(data); // 进行OTA数据解析获取升级数据

        if (ret == ESP_OK)  //如果OTA升级成功
        {
            // 构造JSON格式数据,该数据用于反馈给阿里云物联网平台,作用是通知升级包接收进度
            cJSON *Wroot = cJSON_CreateObject();    
            cJSON *Pitem = cJSON_CreateObject();

            cJSON_AddItemToObject(Wroot, "id", cJSON_CreateString("002"));  //消息ID
            cJSON_AddItemToObject(Wroot, "params", Pitem);                  //二层字段名
            cJSON_AddItemToObject(Pitem, "step", cJSON_CreateString("100"));    //当前进度
            cJSON_AddItemToObject(Pitem, "desc", cJSON_CreateString("OTA update successfully !"));  //内容描述

            char ota_inform_buf[256] = {0}; //发送消息的一个数组

            int len = strlen(cJSON_Print(Wroot));   //获取消息的长度

            memcpy(ota_inform_buf, cJSON_Print(Wroot), len); // 将JSON格式数据复制到数组中,将以数组的形式传递给发布函数

            ESP_LOGI(MQTT_TAG, "ota_inform_buf:%s,len:%d", ota_inform_buf,len); //打印提示信息

            msg_id = esp_mqtt_client_publish(client, AliyunOTAprogress, ota_inform_buf, strlen(ota_inform_buf), 0, 0);  //MQTT发布消息

            ESP_LOGI(MQTT_TAG, "sent publish ota inform successful, msg_id=%d", msg_id);//打印提示信息

            cJSON_Delete(Wroot);    //释放json资源

            esp_restart(); // ESP32设备重启,重启后将执行刚才下载的程序
        }
        else
        {
            ESP_LOGE(MQTT_TAG, "OTA failed");
        }

        vTaskDelay(pdMS_TO_TICKS(100));
    }
}
2.3.2、aly.h

主要是对阿里云的一些连接参数以及一些topic进行宏定义,需要按照自己的一个具体情况进行一个改动。

#ifndef __ALY_H
#define __ALY_H

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"

#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"

#include "esp_log.h"
#include "mqtt_client.h"
#include "os.h"
#include "cJSON.h"
//OTA
#include "esp_ota_ops.h"
#include "esp_http_client.h"
#include "esp_https_ota.h"
#include "esp_wifi.h"
#include "mqtt_client.h"
#include "string.h"
#include "nvs.h"
#include "nvs_flash.h"
#include <sys/socket.h>

//阿里云连接三元组
#define   Aliyun_host       ""
#define   Aliyun_port       1883
#define   Aliyun_client_id  ""
#define   Aliyun_username   ""
#define   Aliyun_password   ""

//自定义订阅与发布
#define   AliyunSubscribeTopic_user_get     ""
#define   AliyunPublishTopic_user_update    ""

//OTA相关
#define AliyunOTAInform                     ""
#define AliyunOTAupgrade                    ""
#define AliyunOTAprogress                   ""
#define AliyunOTAfirmware                   ""
extern const uint8_t server_cert_pem_start[] asm("_binary_root_crt_start");
extern const uint8_t server_cert_pem_end[] asm("_binary_root_crt_end");
#define OTA_URL_SIZE 256

static const char *MQTT_TAG = "MQTT_EXAMPLE";

//MQTT测试发布数据
static char mqtt_publish_Testdata[] = "mqtt i am esp32";
static char mqtt_OTA_Data[]="{\"id\":\"001\",\"params\":{\"version\":\"1.0.1\"}}";

esp_mqtt_client_handle_t client;   //MQTT客户端句柄

//进行阿里云连接
void user_mqtt_app_start(void);

//void Parse_Data(const char *Data);

//通过阿里云下发的topic进行对应的数据解析
void Get_ALY_Topic(const char *topic, const char *data);
#endif
2.3.3、

在OTA、自定义topic在产品中,通过点击查看自己的一个topic列表可以进行查看,需要注意topic中有一个${deviceName}是需要填入自己的一个设备名称的。
在这里插入图片描述

2.3.4、

阿里云连接三元组在设备中可以通过查看设备信息–MQTT连接参数进行一个查看,需注意,该连接参数不可随意让人知道,本教程为示例。
在这里插入图片描述

3、需注意

这边有一个server_certs的一个文件夹,里面存放的是阿里云的一个https根证书,我们需要下载根证书进行一个导入添加,不然就只能通过HTTP的方式进行一个下载文件升级。

在这里插入图片描述

最后,到这里我们的一个ESP32OTADemo就结束了

参考文章:来自while(1)博主的

ESP32入门基础之空中升级(OTA)

完整代码:直接下载,不需要积分

  • 8
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 好的,以下是一个简单的esp32连接阿里云的例程: #include <WiFi.h> #include <PubSubClient.h> // WiFi网络信息 const char* ssid = "你的WiFi名称"; const char* password = "你的WiFi密码"; // 阿里云物联网平台信息 const char* mqttServer = "你的MQTT服务器地址"; const int mqttPort = 1883; const char* mqttUsername = "你的MQTT用户名"; const char* mqttPassword = "你的MQTT密码"; const char* mqttClientId = "你的MQTT客户端ID"; // WiFi客户端和MQTT客户端 WiFiClient wifiClient; PubSubClient mqttClient(wifiClient); void setup() { // 初始化串口 Serial.begin(115200); // 连接WiFi网络 WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.println("Connecting to WiFi..."); } Serial.println("WiFi connected"); // 连接MQTT服务器 mqttClient.setServer(mqttServer, mqttPort); mqttClient.setCallback(callback); while (!mqttClient.connected()) { if (mqttClient.connect(mqttClientId, mqttUsername, mqttPassword)) { Serial.println("MQTT connected"); } else { Serial.print("MQTT failed with state "); Serial.println(mqttClient.state()); delay(200); } } // 订阅主题 mqttClient.subscribe("你的订阅主题"); } void loop() { // 处理MQTT消息 mqttClient.loop(); // 发布消息 mqttClient.publish("你的发布主题", "你的消息内容"); } void callback(char* topic, byte* payload, unsigned int length) { // 处理接收到的消息 Serial.print("Message received: "); Serial.println((char*)payload); } ### 回答2: esp32是一款强大的物联网开发板,在连接阿里云时,首先需要准备好以下步骤: 1. 注册阿里云账号并创建物联网平台实例。 2. 下载并安装ESP-IDF开发环境,ESP-IDF是官方提供的esp32开发框架,具有丰富的API和示例。 3. 在开发环境中创建一个新的工程。 下面是一个连接ESP32阿里云的简单例程: 1. 首先,需要引入必要的库文件: ```c++ #include <stdio.h> #include "esp_system.h" #include "nvs_flash.h" #include "wifi.h" #include "aliyun_iot.h" ``` 2. 初始化ESP系统和硬件: ```c++ void app_main() { // 初始化非易失性存储(NVS) esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); // 初始化WiFi wifi_init(); // 初始化阿里云IoT aliyun_iot_init(); // 连接阿里云 aliyun_iot_connect(); } ``` 3. 配置Wi-Fi网络: ```c++ void wifi_init() { // 配置Wi-Fi (注意:以下代码仅作示例,具体配置根据实际情况修改) wifi_config_t wifi_config = { .sta = { .ssid = "YOUR_SSID", .password = "YOUR_PASSWORD" }, }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); } ``` 4. 连接阿里云: ```c++ void aliyun_iot_connect() { // 配置阿里云IoT连接信息(Endpoint、ProductKey、DeviceName、DeviceSecret) aliyun_iot_config_t iot_config = { .endpoint = "YOUR_ENDPOINT", .product_key = "YOUR_PRODUCT_KEY", .device_name = "YOUR_DEVICE_NAME", .device_secret = "YOUR_DEVICE_SECRET" }; // 连接阿里云IoT aliyun_iot_err_t err = aliyun_iot_connect(&iot_config); if (err != ALIYUN_IOT_SUCCESS) { printf("Failed to connect to Aliyun IoT, err: %d\n", err); } } ``` 以上是一个简单的ESP32连接阿里云的例程,你可以根据实际情况修改Wi-Fi网络、阿里云IoT连接信息等设置。同时,你还可以在连接成功后,根据需要发送和接收数据,实现更丰富的物联网应用! ### 回答3: ESP32是一款功能强大的物联网开发板,可以通过WiFi连接到互联网,并实现与云平台的通信。连接阿里云的例程如下: 首先,在Arduino IDE中安装ESP32开发板支持库,然后打开一个新的Arduino项目。 然后,引入必要的库文件。在代码的开头,加上以下几行: ``` #include <WiFi.h> #include <WiFiClientSecure.h> #include <PubSubClient.h> #include <ArduinoJson.h> ``` 接下来,配置WiFi连接。在`setup`函数中,添加以下代码: ``` const char* ssid = "YOUR_SSID"; const char* password = "YOUR_PASSWORD"; void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to WiFi"); } ``` 替换`YOUR_SSID`和`YOUR_PASSWORD`为你的WiFi网络名称和密码。 然后,配置阿里云IoT平台信息。在`setup`函数中,添加以下代码: ``` const char* aliyunServer = "YOUR_ALIYUN_SERVER"; const int aliyunPort = YOUR_ALIYUN_PORT; const char* deviceId = "YOUR_DEVICE_ID"; const char* productKey = "YOUR_PRODUCT_KEY"; const char* deviceSecret = "YOUR_DEVICE_SECRET"; WiFiClientSecure client; PubSubClient mqttClient(client); void setup() { // ... mqttClient.setServer(aliyunServer, aliyunPort); String clientId = String(deviceId) + "|securemode=2,signmethod=hmacsha1|"; mqttClient.setCallback(callback); if (mqttClient.connect(clientId.c_str(), productKey, deviceSecret)) { Serial.println("Connected to Aliyun IoT Platform"); } else { Serial.println("Failed to connect to Aliyun IoT Platform"); } mqttClient.subscribe("YOUR_TOPIC"); } ``` 替换`YOUR_ALIYUN_SERVER`、`YOUR_ALIYUN_PORT`、`YOUR_DEVICE_ID`、`YOUR_PRODUCT_KEY`和`YOUR_DEVICE_SECRET`为你在阿里云平台中创建的设备信息。 最后,实现回调函数来处理接收到的消息: ``` void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Received message: "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); } ``` 以上是一个简单的ESP32连接阿里云的例程,可以实现基本的连接与消息接收。你可以根据自己的需求进一步扩展功能。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值