国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

ESP32學習筆記(46)——MQTT客戶端

Jenny_Tong / 2260人閱讀

摘要:一簡介實現方式實現協議需要客戶端和服務器端通訊完成,在通訊過程中,協議中有三種身份發布者代理服務器訂閱者。其中,消息的發布者和訂閱者都是客戶端,消息代理是服務器,消息發布者可以同時是訂閱者。

一、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 (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";static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event){    // 獲取MQTT客戶端結構體指針    esp_mqtt_client_handle_t client = event->client;    int msg_id;    // your_context_t *context = event->context;    // 通過事件ID來分別處理對應的事件    switch (event->event_id) {        case MQTT_EVENT_CONNECTED:    // MQTT連上事件            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");            // MQTT Client發布主題函數,主題是/topic/qos1,服務質量qos1,發布的數據是data-3            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);            // MQTT Client訂閱主題函數,主題是/topic/qos0,服務質量qos0            msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);            ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);            // MQTT Client訂閱主題函數,主題是/topic/qos1,服務質量qos1            msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);            ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);            // MQTT Client取消訂閱主題函數            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:    // MQTT發送訂閱成功事件            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:    // MQTT取消訂閱事件            ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);            break;        case MQTT_EVENT_PUBLISHED:    // MQTT發布成功事件            ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);            break;        case MQTT_EVENT_DATA:    // MQTT接收數據事件            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;}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){     // 1、定義一個MQTT客戶端配置結構體,輸入MQTT的url    esp_mqtt_client_config_t mqtt_cfg = {        .host = "192.168.61.67",    // MQTT服務器地址        .port = 1883,               // MQTT服務器端口    };#if CONFIG_BROKER_URL_FROM_STDIN    char line[128];    if (strcmp(mqtt_cfg.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.uri = line;        printf("Broker url: %s/n", line);    } else {        ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");        abort();    }#endif /* CONFIG_BROKER_URL_FROM_STDIN */    // 2、通過esp_mqtt_client_init獲取一個MQTT客戶端結構體指針,參數是MQTT客戶端配置結構體    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);    // 3、注冊MQTT事件    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);    // 4、開啟MQTT功能    esp_mqtt_client_start(client);}void app_main(void){    ESP_LOGI(TAG, "[APP] Startup..");    ESP_LOGI(TAG, "[APP] Free memory: %d 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_TCP", ESP_LOG_VERBOSE);    esp_log_level_set("TRANSPORT_SSL", 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());    mqtt_app_start();}

五、搭建本地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服務器

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/119623.html

相關文章

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<