ESP32的MQTT使用

一、ESP32的MQTT函数介绍

1、esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *config)

函数描述:根据配置创建MQTT客户端句柄

参数esp_mqtt_client_config_t的结构体如下

typedef struct {
    mqtt_event_callback_t event_handle; / *!<处理MQTT事件作为传统模式的回调* /
    esp_event_loop_handle_t event_loop_handle; / *!<MQTT事件循环库的句柄* /
    const char * host; / *!<MQTT服务器域(ipv4 as string)* /
    const char * uri; / *!<完整的MQTT代理URI * /
    uint32_t port; / *!<MQTT服务器端口* /
    const char * client_id; / *!<默认客户端ID是``ESP32_%CHIPID%``其中%CHIPID%是十六进制格式的MAC地址的最后3个字节* /
    const char * username; / *!<MQTT用户名* /
    const char *密码; / *!<MQTT密码* /
    const char * lwt_topic; / *!<LWT(遗嘱和遗嘱)消息主题(默认为NULL)* /
    const char * lwt_msg; / *!<LWT消息(默认为NULL)* /
    int lwt_qos; / *!<LWT消息qos * /
    int lwt_retain; / *!<LWT保留消息标志* /
    int lwt_msg_len; / *!<LWT消息长度* /
    int disable_clean_session; / *!<mqtt clean session,默认clean_session为true * /
    int keepalive; / *!<mqtt keepalive,默认为120秒* /
    bool disable_auto_reconnect; / *!<此mqtt客户端将重新连接到服务器(当出错/断开连接时)。设置disable_auto_reconnect = true以禁用* /
    void * user_context; / *!<将用户上下文传递给此选项,然后可以在``event-> user_context`` * /中接收该上下文
    int task_prio; / *!<MQTT任务优先级,默认为5,可以在``make menuconfig``中更改* /
    int task_stack; / *!<MQTT任务堆栈大小,默认为6144字节,可以在``make menuconfig``中更改* /
    int buffer_size; / *!<MQTT发送/接收缓冲区的大小,默认为1024 * /
    const char * cert_pem; / *!<用于服务器验证的PEM格式的证书数据指针(使用SSL),默认为NULL,不需要验证服务器* /
    const char * client_cert_pem; / *!<指向用于SSL相互身份验证的PEM格式的证书数据的指针,默认为NULL,如果不需要相互身份验证,则不需要。如果它不是NULL,则还必须提供`client_key_pem`。 * /
    const char * client_key_pem; / *!<指向用于SSL相互身份验证的PEM格式的私钥数据的指针,默认为NULL,如果不需要相互身份验证,则不需要。如果它不是NULL,则还必须提供`client_cert_pem`。 * /
    esp_mqtt_transport_t transport; / *!<覆盖URI传输* /
    int refresh_connection_after_ms; / *!<刷新此值后的连接(以毫秒为单位)* /
esp_mqtt_client_config_t;

返回值:MQTT句柄 错误的时候返回NULL

使用举例:

    esp_mqtt_client_config_t mqtt_cfg = {
        .host = "192.168.43.95", //MQTT 地址
		.port = 1883,    //MQTT端口
		.username = "admin",//用户名字
		.password = "public",//密码
    };

    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);

2、sp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client)

函数描述:启动MQTT客户端

参数:创建的MQTT句柄

返回值:ESP_OK表示成功ESP_ERR_无效_ARG错误初始化ESP_FERT其他错误

3、esp_err_t esp_mqtt_client_stop(esp_mqtt_client_handle_t client)

函数描述:停止MQTT客户端

参数:创建的MQTT句柄

4、int esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char *topic, int qos)

函数描述:订阅主题

参数:A、esp_mqtt_client_handle_t client     创建的MQTT句柄

         B、char *topic  订阅的主题

         C、Qos级别 0 、1、 2

返回值:成功时订阅消息返回Message_id- 失败返回-1

5、int esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *topic)

函数描述:取消订阅的主题

参数:A、esp_mqtt_client_handle_t client     创建的MQTT句柄

         B、B、char *topic  订阅的主题

返回值:成功时订阅消息返回Message_id- 失败返回-1

6、int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain)

函数描述:往代理发布消息

参数:A、esp_mqtt_client_handle_t client     创建的MQTT句柄

          B、char *topic  发布的主题

         C、 const char *data  发布的数据

        D、int len    数据长度,如果设置为0,则从发布的数据长度

        E、Qos级别

       F、retain  当我们使用MQTT客户端发布消息(PUBLISH)时,如果将RETAIN标志位设置为true,那么MQTT服务器会将最近收到的一条RETAIN标志位为true的消息保存在服务器端

7、esp_err_t esp_mqtt_client_register_event(esp_mqtt_client_handle_t client, esp_mqtt_event_id_t event, esp_event_handler_t event_handler, void* event_handler_arg)

函数描述:注册MQTT事件

参数:A、esp_mqtt_client_handle_t client     创建的MQTT句柄

         B、esp_mqtt_event_id_t event     注册任何事件id的处理程序

       C、esp_event_handler_t event_handler  回调函数

       D、void* event_handler_arg  处理程序上下文

 

二、实验内容

1、初始化wifi,并连接wifi

2、初始化MQTT,连接成功发布、订阅主题

 

1、初始化wifi,并连接wifi

static EventGroupHandle_t wifi_event_group;

/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
const int CONNECTED_BIT = BIT0;
//wifi 事件
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch (event->event_id) {
        case SYSTEM_EVENT_STA_START:
            esp_wifi_connect();
            break;
        case SYSTEM_EVENT_STA_GOT_IP:
        	//Mqtt_init();
            xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
            break;
        case SYSTEM_EVENT_STA_DISCONNECTED:
            /* This is a workaround as ESP32 WiFi libs don't currently
               auto-reassociate. */
            esp_wifi_connect();
            xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
            break;
        default:
            break;
    }
    return ESP_OK;
}
//初始化wifi
void app_wifi_initialise(void)
{
    tcpip_adapter_init();
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = "tplingk",
            .password = "12345678",
        },
    };
    ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
    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());
}
//等待wifi成功连接
void app_wifi_wait_connected()
{
    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
}

上面就是初始化wifi ,并且连接wifi.在wifi连接成功里面设置事件标志

2、初始化MQTT,连接成功发布、订阅主题

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;
    // your_context_t *context = event->context;
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED://连接MQTT成功
            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
            msg_id = esp_mqtt_client_publish(client, "/World", "data_3", 0, 1, 0);
            ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);

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

            msg_id = esp_mqtt_client_subscribe(client, "/topic1", 1);
            ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
            msg_id = esp_mqtt_client_subscribe(client, "/topic1", 2);
            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);
            break;
        case MQTT_EVENT_DISCONNECTED://断开MQTT
            ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
            break;

        case MQTT_EVENT_SUBSCRIBED://订阅成功
        	printf("_---------订阅--------\n");
            ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
            msg_id = esp_mqtt_client_publish(client, "/World", "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://发布成功
        	printf("_--------发布----------\n");
            ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_DATA://数据接收
            ESP_LOGI(TAG, "MQTT_EVENT_DATA");
            printf("主题长度:%d 数据长度:%d\n",event->topic_len,event->data_len);

            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://MQTT错误
            ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
            break;
        default:
            ESP_LOGI(TAG, "Other event id:%d", event->event_id);
            break;
    }
    return ESP_OK;
}

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=%d", base, event_id);
    mqtt_event_handler_cb(event_data);
}

static void mqtt_app_start(void)
{
    printf("\n______________等待wifi连接____________\n");
    app_wifi_wait_connected();
    vTaskDelay(5000 / portTICK_PERIOD_MS);
    printf("\n______________wifi连接成功____________\n");
    esp_mqtt_client_config_t mqtt_cfg = {
        .host = "192.168.43.95",//MQTT 地址
		.port = 1883,   //MQTT端口
		.username = "admin",//用户名
		.password = "public",//密码
    };

    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);//初始化MQTT
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);//注册事件
    esp_mqtt_client_start(client);//启动mQTT
    while(1){

    	vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

在连接成功MQTT之后,发布一个消息,订阅三个消息如下

            msg_id = esp_mqtt_client_publish(client, "/World", "data_3", 0, 1, 0);

            msg_id = esp_mqtt_client_subscribe(client, "/topic0", 0);

            msg_id = esp_mqtt_client_subscribe(client, "/topic1", 1);
            msg_id = esp_mqtt_client_subscribe(client, "/topic1", 2);
 

三、实验结果

连接的是本地搭建的MQTT服务器emqttd,网上很多教程。

连接成功之后就可以在里面看到,ESP32_050F44就是连接成功的设备

 

发布和订阅的主题

 

发布和订阅消息

串口打印的数据

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

做了不一定能实现但不做一定不会实现

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值