当前位置:首页 » 《随便一记》 » 正文

ESP32-C3入门教程 网络篇⑦——MQTT 应用示例_小康师兄

29 人参与  2022年02月26日 16:32  分类 : 《随便一记》  评论

点击全文阅读


文章目录

  • 一、前言
  • 二、快速运行
  • 三、运行效果
  • 四、程序流程
    • 4.1 主程序
    • 4.2 回调函数
  • 五、关键函数
    • 5.1 MQTT初始化
    • 5.2 MQTT事件的回调函数
    • 5.3 MQTT启动
    • 5.4 MQTT订阅
    • 5.5 MQTT取消订阅
    • 5.6 MQTT发布
  • 六、参考

一、前言

MQTT 是轻量级的发布/订阅消息协议
ESP-MQTT 是 MQTT 协议客户端的实现
基于TCP/SSL/WebSocket/WebSocket Secure等MQTT实现

二、快速运行

  • 示例项目中,选择protocols—>mqtt->tcp
  • menuconfig配置ESP32C3-Specific—>Rec 0
  • 芯片选择ESP32-C3(Built-in USB JTAG)
  • 快速运行ESP-IDF Build, Flash and Monitor(左下角)

三、运行效果

  • 修改WiFi AP的SSIDpassword
  • 基于mqtt.eclipseprojects.io这个mqtt服务器进行测试
  • MQTTBox订阅topic"/小康师兄/topic/start""/小康师兄/topic/end"
  • ESP32-C3订阅topic"/小康师兄/topic/wait"
  • ESP32-C3往topic"/小康师兄/topic/start"发送数据"小康师兄start"
  • MQTTBox往topic"/小康师兄/topic/wait"发送数据"小康师兄end"
  • ESP32-C3接收到topic"/小康师兄/topic/wait"的数据"小康师兄end"
    • 则往topic"/小康师兄/topic/end"发送数据"小康师兄end"
    • 并取消订阅topic"/小康师兄/topic/wait"

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

四、程序流程

4.1 主程序

  • nvs_flash_init,初始化默认 NVS 分区
  • esp_netif_init,初始化底层TCP/IP堆栈
  • esp_event_loop_create_default,创建默认事件循环
  • example_connect,连接到指定WiFi
  • esp_mqtt_client_init,MQTT初始化
  • esp_mqtt_client_register_event,MQTT事件回调函数
  • esp_mqtt_client_start,MQTT启动

4.2 回调函数

  • MQTT_EVENT_CONNECTED,MQTT连接成功
    • esp_mqtt_client_publish,往topic"/小康师兄/topic/start"发送数据"小康师兄start"
    • esp_mqtt_client_subscribe,订阅topic"/小康师兄/topic/wait"
  • MQTT_EVENT_DATA,MQTT接收到数据
    • 判断topic是不是"/小康师兄/topic/wait",判断data是不是"小康师兄end",如果全是,则:
      • esp_mqtt_client_publish,往topic"/小康师兄/topic/end"发送数据"小康师兄end"
      • esp_mqtt_client_unsubscribe,取消订阅topic"/小康师兄/topic/wait"

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:
            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
            msg_id = esp_mqtt_client_publish(client, "/小康师兄/topic/start", "小康师兄start", 0, 1, 0);
            ESP_LOGI(TAG, "publish successful, msg_id=%d", msg_id);

            msg_id = esp_mqtt_client_subscribe(client, "/小康师兄/topic/wait", 0);
            ESP_LOGI(TAG, "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, topic=%.*s", event->msg_id, event->topic_len, event->topic);
            break;
        case MQTT_EVENT_UNSUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d, topic=%.*s", event->msg_id, event->topic_len, event->topic);
            break;
        case MQTT_EVENT_PUBLISHED:
            ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d, topic=%.*s", event->msg_id, event->topic_len, event->topic);
            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, "/小康师兄/topic/wait")!=0 && 
                strstr(event->data, "小康师兄end")!=0){
                msg_id = esp_mqtt_client_publish(client, "/小康师兄/topic/end", "小康师兄end", 0, 0, 0);
                ESP_LOGI(TAG, "publish successful, msg_id=%d", msg_id);
                
                msg_id = esp_mqtt_client_unsubscribe(client, "/小康师兄/topic/wait");
                ESP_LOGI(TAG, "unsubscribe successful, msg_id=%d", msg_id);
            }
            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;
    }
    return ESP_OK;
}

五、关键函数

5.1 MQTT初始化

  • esp_mqtt_client_config_t:mqtt配置参数

/**
 * MQTT client configuration structure
 */
typedef struct {
    mqtt_event_callback_t event_handle;     /*!< handle for MQTT events as a callback in legacy mode */
    esp_event_loop_handle_t event_loop_handle; /*!< handle for MQTT event loop library */
    const char *host;                       /*!< MQTT server domain (ipv4 as string) */
    const char *uri;                        /*!< Complete MQTT broker URI */
    uint32_t port;                          /*!< MQTT server port */
    const char *client_id;                  /*!< default client id is ``ESP32_%CHIPID%`` where %CHIPID% are last 3 bytes of MAC address in hex format */
    const char *username;                   /*!< MQTT username */
    const char *password;                   /*!< MQTT password */
    const char *lwt_topic;                  /*!< LWT (Last Will and Testament) message topic (NULL by default) */
    const char *lwt_msg;                    /*!< LWT message (NULL by default) */
    int lwt_qos;                            /*!< LWT message qos */
    int lwt_retain;                         /*!< LWT retained message flag */
    int lwt_msg_len;                        /*!< LWT message length */
    int disable_clean_session;              /*!< mqtt clean session, default clean_session is true */
    int keepalive;                          /*!< mqtt keepalive, default is 120 seconds */
    bool disable_auto_reconnect;            /*!< this mqtt client will reconnect to server (when errors/disconnect). Set disable_auto_reconnect=true to disable */
    void *user_context;                     /*!< pass user context to this option, then can receive that context in ``event->user_context`` */
    int task_prio;                          /*!< MQTT task priority, default is 5, can be changed in ``make menuconfig`` */
    int task_stack;                         /*!< MQTT task stack size, default is 6144 bytes, can be changed in ``make menuconfig`` */
    int buffer_size;                        /*!< size of MQTT send/receive buffer, default is 1024 (only receive buffer size if ``out_buffer_size`` defined) */
    const char *cert_pem;                   /*!< Pointer to certificate data in PEM or DER format for server verify (with SSL), default is NULL, not required to verify the server. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in cert_len. */
    size_t cert_len;                        /*!< Length of the buffer pointed to by cert_pem. May be 0 for null-terminated pem */
    const char *client_cert_pem;            /*!< Pointer to certificate data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_key_pem` has to be provided. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_cert_len. */
    size_t client_cert_len;                 /*!< Length of the buffer pointed to by client_cert_pem. May be 0 for null-terminated pem */
    const char *client_key_pem;             /*!< Pointer to private key data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_cert_pem` has to be provided. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_key_len */
    size_t client_key_len;                  /*!< Length of the buffer pointed to by client_key_pem. May be 0 for null-terminated pem */
    esp_mqtt_transport_t transport;         /*!< overrides URI transport */
    int refresh_connection_after_ms;        /*!< Refresh connection after this value (in milliseconds) */
    const struct psk_key_hint* psk_hint_key;     /*!< Pointer to PSK struct defined in esp_tls.h to enable PSK authentication (as alternative to certificate verification). If not NULL and server/client certificates are NULL, PSK is enabled */
    bool          use_global_ca_store;      /*!< Use a global ca_store for all the connections in which this bool is set. */
    int reconnect_timeout_ms;               /*!< Reconnect to the broker after this value in miliseconds if auto reconnect is not disabled (defaults to 10s) */
    const char **alpn_protos;               /*!< NULL-terminated list of supported application protocols to be used for ALPN */
    const char *clientkey_password;         /*!< Client key decryption password string */
    int clientkey_password_len;             /*!< String length of the password pointed to by clientkey_password */
    esp_mqtt_protocol_ver_t protocol_ver;   /*!< MQTT protocol version used for connection, defaults to value from menuconfig*/
    int out_buffer_size;                    /*!< size of MQTT output buffer. If not defined, both output and input buffers have the same size defined as ``buffer_size`` */
    bool skip_cert_common_name_check;       /*!< Skip any validation of server certificate CN field, this reduces the security of TLS and makes the mqtt client susceptible to MITM attacks  */
    bool use_secure_element;                /*!< enable secure element for enabling SSL connection */
    void *ds_data;                          /*!< carrier of handle for digital signature parameters */
    int network_timeout_ms;                 /*!< Abort network operation if it is not completed after this value, in milliseconds (defaults to 10s) */
    bool disable_keepalive;                 /*!< Set disable_keepalive=true to turn off keep-alive mechanism, false by default (keepalive is active by default). Note: setting the config value `keepalive` to `0` doesn't disable keepalive feature, but uses a default keepalive period */
} esp_mqtt_client_config_t;

esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *config)

5.2 MQTT事件的回调函数

  • client:mqtt实例
  • event:mqtt事件id
  • event_handler:回调函数
  • event_handler_arg:回调参数
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)

5.3 MQTT启动

使用已创建的MQTT实例启动MQTT。

  • client:mqtt实例
esp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client)

5.4 MQTT订阅

  • client:mqtt实例
  • topic:需要订阅的标题
  • qos:quality of service,即 “质量服务”
    • 0,At most once,至多一次;
    • 1,At least once,至少一次;
    • 2,Exactly once,确保只有一次
int esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char *topic, int qos)

5.5 MQTT取消订阅

  • client:mqtt实例
  • topic:需要取消订阅的标题
int esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *topic)

5.6 MQTT发布

  • client:mqtt实例
  • topic:标题
  • data:数据
  • len:数据长度
  • retain:保留标志
  • qos:quality of service,即 “质量服务”
    • 0,At most once,至多一次;
    • 1,At least once,至少一次;
    • 2,Exactly once,确保只有一次
int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain)

六、参考

https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32c3/api-reference/protocols/mqtt.html?highlight=esp_mqtt_client_start#

觉得好,就一键三连呗(点赞+收藏+关注)


点击全文阅读


本文链接:http://zhangshiyu.com/post/35427.html

小康  师兄  订阅  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1