当前位置 博文首页 > freemote的博客:【玩转ESP32】15、esp32 mqtt client

    freemote的博客:【玩转ESP32】15、esp32 mqtt client

    作者:[db:作者] 时间:2021-07-05 09:53

    系列文章:

    【玩转ESP32】1、开发环境搭建
    【玩转ESP32】2、开发参考资料
    【玩转ESP32】3、点亮LED,Blink,blink,blink
    【玩转ESP32】4、ESP32驱动DHT11
    【玩转ESP32】5、i2c-tools访问i2c设备
    【玩转ESP32】6、驱动i2c设备—0.96 OLED
    【玩转ESP32】7、ESP32连接wifi
    【玩转ESP32】8、ESP32 Guru MeditationError报错分析
    【玩转ESP32】9、ESP32 作为TCP客户端连接服务器(非阻塞接收)
    【玩转ESP32】10、创建用户分区表,数据读写存储
    【玩转ESP32】11、编译报错:esp_bt.h:No such file or directory
    【玩转ESP32】12、esp32串口使用
    【玩转ESP32】13、软件定时器esp_timer使用
    【玩转ESP32】14、esp32 mqtt基础

    1、前言

    ESP-IDF提供了mqtt组件,在components/mqtt,相关的API位于components/mqtt/esp-mqtt目录下,这个组件是基于https://github.com/tuanpmt/esp_mqtt的 。组件支持MQTT over TCP、SSL with mbedtls、MQTT over Websocket、 MQTT over Websocket Secure;支持订阅、发布、身份验证、遗嘱消息、心跳、以及3个消息等级。

    2、API说明

    2.1、MQTT客户端配置结构体

    esp_mqtt_client_config_t
    

    通过这个结构体,可以设置回调函数、服务器地址、用户名、client id、密码、证书等,基本上与mqtt相关的参数都可以设置。

    2.2、基于配置创建MQTT Client句柄

    esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *config);
    

    config:配置结构体变量指针;
    esp_mqtt_client_handle_t :创建成功返回的mqtt client句柄。

    2.3、启动MQTT Client(客户端)

    esp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client);
    

    client:mqtt client句柄;
    esp_err_t :返回值为ESP_OK标识启动成功。

    2.4、订阅主题

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

    client:mqtt client句柄;
    topic :主题;
    qos:消息质量。

    2.5、发布主题

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

    client:mqtt client句柄;
    topic :主题;
    data:数据;
    len:长度;
    qos:消息质量;
    retain:保持标识。

    2.6、MQTT Client重连

    esp_err_t esp_mqtt_client_reconnect(esp_mqtt_client_handle_t client);
    

    client:mqtt client句柄;
    esp_err_t :返回值为ESP_OK标识启动成功。

    2.7、设置MQTT Client配置,一般用于更新 配置

    esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_client_config_t *config);
    

    client:mqtt client句柄;
    config:配置结构体变量指针;
    esp_err_t :返回值为ESP_OK标识启动成功。

    2.8、MQTT Client回调

    static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
    

    event:事件结构体变量;
    在这个函数中可以通过event_id来处理各种MQTT事件,比如:MQTT_EVENT_CONNECTED(MQTT链接)、MQTT_EVENT_SUBSCRIBED(订阅)、MQTT_EVENT_DATA(MQTT数据)等;订阅主题后,接受MQTT消息,正是通过这个事件来回调的。

    3、代码实现

    3.1、定义并初始化MQTT Client配置结构体、MQTT Client句柄

    static esp_mqtt_client_handle_t mqtt_client; 
    //MQTT Client句柄
    
    static char mqtt_msg[512];
    //mqtt接收消息缓冲区
    
    static esp_mqtt_client_config_t    mqtt_cfg = {
                .host= IOT_CORE_MQTT_BROKER_URL,
                .event_handle = mqtt_event_handler,//注册回调函数
                .port = 1883,
                .username = mqtt_token,
                .client_id = my_clinet_id
                };
    //定义并初始化MQTT Client配置结构体
    

    client_id 默认使用的是ESP32_%CHIPID%的形式;
    这里要注意,如果mqtt连接断开了,重连的时候最好变换一个client_id,或者在client_id中加入时间戳,保证每次都不一样
    client_idhostusername 需要根据实际情况替换。

    3.2、创建客户端并连接服务器

    static void mqtt_app_start(void)
    {
        mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
        //创建客户端
        ESP_ERROR_CHECK(esp_mqtt_client_start(mqtt_client));
        //启动客户端,连接服务器
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    

    3.3、mqtt回调处理

    static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
    {
        assert(event != NULL);
        switch (event->event_id)
        {
        case MQTT_EVENT_CONNECTED: //mqtt连接事件
            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
            break;
        case MQTT_EVENT_DISCONNECTED: //mqtt断开事件
            ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
            break;
        case MQTT_EVENT_SUBSCRIBED:  //mqtt订阅事件
            ESP_LOGD(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_UNSUBSCRIBED:  //mqtt取消订阅事件
            ESP_LOGD(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_PUBLISHED:  //mqtt发布事件
            ESP_LOGD(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_DATA: //mqtt接收数据事件
            ESP_LOGD(TAG, "MQTT_EVENT_DATA, msg_id=%d, %s", event->msg_id, event->topic);
            if (event->data_len >= (sizeof(mqtt_msg) - 1))
            {
                ESP_LOGE(TAG, "Received MQTT message size [%d] more than expected [%d]", event->data_len, (sizeof(mqtt_msg) - 1));
                return ESP_FAIL;
            }
            break;
        case MQTT_EVENT_ERROR: //mqtt错误事件
            ESP_LOGD(TAG, "MQTT_EVENT_ERROR");
            break;
        case MQTT_EVENT_BEFORE_CONNECT: //mqtt连接之前,已发生的事件
            ESP_LOGD(TAG, "MQTT_EVENT_BEFORE_CONNECT");
            break;
        default:
            break;    
        }
        return ESP_OK;
    }
    

    经过以上几个步骤,esp32就可以通过mqtt连接到服务器了。

    cs