ESP32学习笔记(46)——MQTT客户端
一、MQTT簡介
1.1 實現方式
實現MQTT協議需要客戶端和服務器端通訊完成,在通訊過程中,MQTT協議中有三種身份:發布者(Publish)、代理(Broker)(服務器)、訂閱者(Subscribe)。其中,消息的發布者和訂閱者都是客戶端,消息代理是服務器,消息發布者可以同時是訂閱者。
MQTT傳輸的消息分為:主題(Topic)和負載(payload)兩部分:
Topic,可以理解為消息的類型,訂閱者訂閱(Subscribe)后,就會收到該主題的消息內容(payload);
payload,可以理解為消息的內容,是指訂閱者具體要使用的內容。
- MQTT服務器的主要工作是數據分發,沒有數據保存功能。
- 可以訂閱自己發布的主題,服務器就是回發測試。
- MQTT讓邏輯變得更清晰,需要什么訂閱什么。
- 走標準化流程,解放了私有協議制定、實現、調試、測試一整套復雜的流程。
1.2 ESP-MQTT
ESP-MQTT 是 MQTT 協議客戶端的實現(MQTT 是輕量級的發布/訂閱消息協議)。
- 支持 MQTT over TCP、SSL with mbedtls、MQTT over Websocket、MQTT over Websocket Secure。
- 使用 URI 輕松設置
- 多個實例(一個應用程序中有多個客戶端)
- 支持訂閱、發布、身份驗證、最后遺囑消息、保持活動 ping 和所有 3 個 QoS 級別(它應該是一個功能齊全的客戶端)。
ESP-IDF 編程指南——ESP-MQTT
二、API說明
以下 MQTT 客戶端接口位于 components/mqtt/esp-mqtt/include/mqtt_client.h 。
2.1 esp_mqtt_client_init
2.2 esp_mqtt_client_register_event
2.3 esp_mqtt_client_start
2.4 esp_mqtt_client_publish
2.5 esp_mqtt_client_subscribe
2.6 esp_mqtt_client_unsubscribe
三、MQTT客戶端
3.1 主要流程
3.2 配置MQTT參數
首先,要定義一個 MQTT 客戶端配置結構體,最小配置即填入 MQTT 服務器的 URL 即可。
esp_mqtt_client_config_t mqtt_cfg = {.uri = CONFIG_BROKER_URL, };esp_mqtt_client_config_t 結構體如下:
typedef struct {mqtt_event_callback_t event_handle; /*回調*/const char *host; /*!< MQTT 服務器域名(ipv4 as string)*/const char *uri; /*!< MQTT 服務器域名 */uint32_t port; /*!< MQTT服務器端口*/const char *client_id; /*MQTT Client的名字默認是ESP32_加上MAC后3hex*/const char *username; /*MQTT用戶名*/const char *password; /*MQTT密碼*/const char *lwt_topic; /*!< LWT主題,默認為空*/const char *lwt_msg; /*!< LWT信息,默認為空*/int lwt_qos; /*!< LWT消息質量*/int lwt_retain; /*!< LWT保留消息標志*/int lwt_msg_len; /*!< LWT消息長度*/int disable_clean_session; /*!< mqtt clean session,默認為真*/int keepalive; /*MQTT心跳,默認120秒 */bool disable_auto_reconnect; /*錯誤,斷開后重連,true不連*/void *user_context; /*用戶信息 */int task_prio; /*!< MQTT任務優先級,默認為5,可以在make menuconfig中修改*/int task_stack; /*!< MQTT 任務堆棧大小,默認6144 bytes,可以在make menuconfig中修改*/int buffer_size; /*!< MQTT收發緩存,默認1024 */const char *cert_pem; /*指向用于服務器驗證(使用SSL)的PEM格式的證書數據的指針,默認值為空,不需要驗證服務器 */const char *client_cert_pem; /*指向用于SSL相互身份驗證的PEM格式的證書數據的指針,默認值為空,如果不需要相互身份驗證,則不需要。如果不為空,還必須提供“客戶機密鑰”。*/const char *client_key_pem; /*指向用于SSL相互身份驗證的PEM格式的私鑰數據的指針,默認值為空,如果不需要相互身份驗證,則不需要。如果不為空,還必須提供“client-cert-pem”。*/esp_mqtt_transport_t transport; /*覆蓋URI傳輸*/ } esp_mqtt_client_config_t;3.3 初始化MQTT客戶端
然后通過 esp_mqtt_client_init() 獲取一個 MQTT 客戶端結構體指針,參數是 MQTT 客戶端配置結構體。
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);3.4 注冊MQTT事件
默認情況下,MQTT 客戶端使用事件循環庫來發布相關的 MQTT 事件(已連接,已訂閱,已發布等)。
所以我們要注冊一個 MQTT 事件,填入 MQTT 事件處理函數 mqtt_event_handler(),
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); }- 第一個參數為MQTT客戶端結構體,
- 第二個是事件ID對應的事件類型,
- 第三個參數即事件處理函數,
- 第四個參數為事件處理函數的參數。
3.5 開啟MQTT客戶端
esp_mqtt_client_start(client);3.6 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: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);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");break;default:ESP_LOGI(TAG, "Other event id:%d", event->event_id);break;}return ESP_OK; }四、示例代碼
根據 examples\protocols\mqtt\tcp 中的例程修改
 根據服務器地址修改.host = "192.168.61.67",
五、搭建本地MQTT服務器
EMQ官網下載:https://www.emqx.com/zh/downloads?product=broker
- 下載EMQ X開源版
 
- 解壓后進入 emqx-windows-4.3.8\emqx\bin 目錄
 
- Shift+右鍵在此處打開 Powershell 窗口,輸入命令 emqx start
 
- 打開瀏覽器,輸入 http://127.0.0.1:18083/,賬號 admin,密碼 public,進入管理界面
 
- 工具 - Websocket,選擇連接
 
- 訂閱主題和發布消息
 
六、運行測試
配置連接方式:
 
 選擇WIFI連接方式,并修改要連接路由器的SSID和密碼
 
 調試打印:
 
 服務器查看:
 
 
? 由 Leung 寫于 2021 年 9 月 8 日
? 參考:第二十一章 ESP32開發MQTT Client ESP-IDF
     ESP32學習筆記(6)MQTT應用
     ESP32開發之路(9)—ESP32連接到MQTT服務器
總結
以上是生活随笔為你收集整理的ESP32学习笔记(46)——MQTT客户端的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 编程中的幂等性(一):http幂等性
- 下一篇: 项目开发总结报告
