【ESP32】阿里云物联网平台连接及数据互传(MQTT)

一、连接阿里云物联网平台

1.创建示例项目tcp:VSCODE中->“查看”->”命令面板“->输入:Show Examples projects->选择Use current ESP-IDF(C:\Espressif\frameworks\esp-idf-v5.1)->弹出示例ESP-IDF Examples,选择protocols->mqtt->tcp->Create project using example tcp->选择示例保存的路径
【ESP32】阿里云物联网平台连接及数据互传(MQTT)_第1张图片
【ESP32】阿里云物联网平台连接及数据互传(MQTT)_第2张图片
2.选择esp32型号
3.选择COM口
4.选择烧录方式
5.点击“menuconfig”按键,修改WiFi SSID和WiFi Password,点击“保存”

注意:如果SSID为汉字,点击保存后可能还会出现乱码,下一步编译失败。可通过此链接中的方法解决:windows默认编码格式修改

6.app_main.c添加阿里云MQTT相关宏定义

参考【阿里云物联网平台】配置获取MQTT参数信息

/*!!!!!!如下信息请替换成自己在阿里云的信息!!!!!!*/
/*由阿里网平台可得如下信息*/
// ProductKey:"a1Pvdruq4mz"; 
// DeviceName:"FTY_Temp_01"; 
// DeviceSecret:"XXXXXXXXXXXXXXXXXXXXXXXXXXX";
// Region:"cn-shanghai";     

/*下面一参数为自定义*/
// ClientID:="112233";       

/*Broker Address:${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com*/
#define   Aliyun_host       "a1Pvdruq4mz.iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define   Aliyun_port       1883
/*Client ID:     ${ClientID}|securemode=${Mode},signmethod=${SignMethod}|*/
#define   Aliyun_client_id  "a1Pvdruq4mz.FTY_Temp_01|securemode=2,signmethod=hmacsha256,timestamp=1690303682987|"
/*User Name:     ${DeviceName}&${ProductKey}*/
#define   Aliyun_username   "FTY_Temp_01&a1Pvdruq4mz"
/*使用官网 MQTT_Password 工具生成*/
#define   Aliyun_password   "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

7.app_main.c添加user_mqtt_app_start函数

static void user_mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
		.broker.address.hostname = Aliyun_host,
		.broker.address.port = Aliyun_port,
        .broker.address.transport = MQTT_TRANSPORT_OVER_TCP,
		.credentials.client_id = Aliyun_client_id,
		.credentials.username = Aliyun_username,
		.credentials.authentication.password = Aliyun_password,

    };

    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
    esp_mqtt_client_start(client);
}

8.app_main.c中app_main函数中的mqtt_app_start()替换为user_mqtt_app_start()

这一步骤完成后,编译烧录可以直接连接到阿里云物联网平台

9.点击“编译”按键
10.点击“烧录”按键
11.点击“监控”按键,可以看到连接成功的信息
【ESP32】阿里云物联网平台连接及数据互传(MQTT)_第3张图片
12.查看阿里云物联网平台设备为在线状态
在这里插入图片描述

二、设备发布消息至物联网平台

1.获取MQTT发布主题
【ESP32】阿里云物联网平台连接及数据互传(MQTT)_第4张图片
2.app_main.c添加MQTT发布主题

///a1Pvdruq4mz/${deviceName}/user/update    //注意把deviceName换成测试的设备名
#define   AliyunPublishTopic_user_update    "/a1Pvdruq4mz/FTY_Temp_01/user/update"

3.app_main.c中user_mqtt_app_start函数中添加下面的代码,添加到user_mqtt_app_start函数的最下面

char mqtt_publish_data3[] = "mqtt i am esp32";
uint8_t num = 0;
while(1)
{
   esp_mqtt_client_publish(client, AliyunPublishTopic_user_update, mqtt_publish_data3, strlen(mqtt_publish_data3), 1, 0);
   vTaskDelay(2000 / portTICK_PERIOD_MS);
   if(num++ > 5) break;
}
vTaskDelete(NULL);

4.编译烧录运行后,查看阿里云物联网平台信息
【ESP32】阿里云物联网平台连接及数据互传(MQTT)_第5张图片

三、物联网平台发布消息至设备

1.获取MQTT订阅主题
【ESP32】阿里云物联网平台连接及数据互传(MQTT)_第6张图片
2.app_main.c添加MQTT订阅主题

///a1Pvdruq4mz/${deviceName}/user/get    //注意把deviceName换成测试的设备名
#define   AliyunSubscribeTopic_user_get     "/a1Pvdruq4mz/FTY_Temp_01/user/get"

3.app_main.c中mqtt_event_handler函数中MQTT_EVENT_CONNECTED事件的最下面添加下面的代码

//订阅主题
msg_id = esp_mqtt_client_subscribe(client, AliyunSubscribeTopic_user_get, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);

4.编译烧录运行前,物联网平台的已订阅Topic列表为空
【ESP32】阿里云物联网平台连接及数据互传(MQTT)_第7张图片
5.编译烧录运行后,物联网平台的已订阅Topic列表显示设备订阅的主题
【ESP32】阿里云物联网平台连接及数据互传(MQTT)_第8张图片
6.点击“发送消息”,填写待发送的消息后点击“确定”
【ESP32】阿里云物联网平台连接及数据互传(MQTT)_第9张图片
7.通过打印信息可以看到,设备收到了物联网平台发送的信息
【ESP32】阿里云物联网平台连接及数据互传(MQTT)_第10张图片

四、app_main.c完整代码

/* MQTT (over TCP) Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

#include 
#include 
#include 
#include 
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "protocol_examples_common.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"

static const char *TAG = "MQTT_EXAMPLE";

/*!!!!!!如下信息请替换成自己在阿里云的信息!!!!!!*/
/*由阿里网平台可得如下信息*/
// ProductKey:"a1Pvdruq4mz"; 
// DeviceName:"FTY_Temp_01"; 
// DeviceSecret:"1eaa0a454d2f790ba620108af762294c";
// Region:"cn-shanghai";     

/*下面一参数为自定义*/
// ClientID:="112233";       

/*Broker Address:${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com*/
#define   Aliyun_host       "a1Pvdruq4mz.iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define   Aliyun_port       1883
/*Client ID:     ${ClientID}|securemode=${Mode},signmethod=${SignMethod}|*/
#define   Aliyun_client_id  "a1Pvdruq4mz.FTY_Temp_01|securemode=2,signmethod=hmacsha256,timestamp=1690303682987|"
/*User Name:     ${DeviceName}&${ProductKey}*/
#define   Aliyun_username   "FTY_Temp_01&a1Pvdruq4mz"
/*使用官网 MQTT_Password 工具生成*/
#define   Aliyun_password   "0520d5ec394b7d406cf24c65033a982322c4e317ad98ef1f2ca080e5a91400d0"

///a1Pvdruq4mz/${deviceName}/user/update    //注意把deviceName换成测试的设备名
#define   AliyunPublishTopic_user_update    "/a1Pvdruq4mz/FTY_Temp_01/user/update"
#define   AliyunSubscribeTopic_user_get     "/a1Pvdruq4mz/FTY_Temp_01/user/get"


static void log_error_if_nonzero(const char *message, int error_code)
{
    if (error_code != 0) {
        ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
    }
}

/*
 * @brief Event handler registered to receive MQTT events
 *
 *  This function is called by the MQTT client event loop.
 *
 * @param handler_args user data registered to the event.
 * @param base Event base for the handler(always MQTT Base in this example).
 * @param event_id The id for the received event.
 * @param event_data The data for the event, esp_mqtt_event_handle_t.
 */
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
    esp_mqtt_event_handle_t event = event_data;
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;
    switch ((esp_mqtt_event_id_t)event_id) {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0);
        ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);

        msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);

        msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);

        msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
        ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);

        //订阅主题
        msg_id = esp_mqtt_client_subscribe(client, AliyunSubscribeTopic_user_get, 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
        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);
        msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
        ESP_LOGI(TAG, "sent publish successful, msg_id=%d", 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);
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
            log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
            log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
            log_error_if_nonzero("captured as transport's socket errno",  event->error_handle->esp_transport_sock_errno);
            ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));

        }
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        break;
    }
}

static void mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
        .broker.address.uri = CONFIG_BROKER_URL,
    };
#if CONFIG_BROKER_URL_FROM_STDIN
    char line[128];

    if (strcmp(mqtt_cfg.broker.address.uri, "FROM_STDIN") == 0) {
        int count = 0;
        printf("Please enter url of mqtt broker\n");
        while (count < 128) {
            int c = fgetc(stdin);
            if (c == '\n') {
                line[count] = '\0';
                break;
            } else if (c > 0 && c < 127) {
                line[count] = c;
                ++count;
            }
            vTaskDelay(10 / portTICK_PERIOD_MS);
        }
        mqtt_cfg.broker.address.uri = line;
        printf("Broker url: %s\n", line);
    } else {
        ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
        abort();
    }
#endif /* CONFIG_BROKER_URL_FROM_STDIN */

    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    esp_mqtt_client_start(client);
}

static void user_mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
		.broker.address.hostname = Aliyun_host,
		.broker.address.port = Aliyun_port,
        .broker.address.transport = MQTT_TRANSPORT_OVER_TCP,
		.credentials.client_id = Aliyun_client_id,
		.credentials.username = Aliyun_username,
		.credentials.authentication.password = Aliyun_password,

    };

    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
    esp_mqtt_client_start(client);

    char mqtt_publish_data3[] = "mqtt i am esp32";
    uint8_t num = 0;
    while(1)
    {
       esp_mqtt_client_publish(client, AliyunPublishTopic_user_update, mqtt_publish_data3, strlen(mqtt_publish_data3), 1, 0);
       vTaskDelay(2000 / portTICK_PERIOD_MS);
	   if(num++ > 5) break;
	}
    vTaskDelete(NULL);
}

void app_main(void)
{
    ESP_LOGI(TAG, "[APP] Startup..");
    ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
    ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());

    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
    esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
    esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
    esp_log_level_set("outbox", ESP_LOG_VERBOSE);

    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
     * Read "Establishing Wi-Fi or Ethernet Connection" section in
     * examples/protocols/README.md for more information about this function.
     */
    ESP_ERROR_CHECK(example_connect());

    user_mqtt_app_start();
}

本文档编写参考ESP32基础应用之ESP32与阿里云物联网平台实现数据互传(MQTT协议)

你可能感兴趣的:(tcp/ip,网络协议,网络,ide,vscode,编辑器)