• 野路子学习esp32(十二) MQTT 学习记录@a.宏万


    官方的最新文档地址,

    https://docs.espressif.com/projects/esp-idf/zh_CN/latest/index.html

    持续更新,新的文档推出了很多新的案例。

    现在记录下我学习MQTT的过程,希望可以帮助到一些朋友和自己。

    官方的案例写的很好,我直接把官方的案例做一个说明。加上链接WiFi的代码

    本文默认您已经知道mqtt的相关知识,我前面有一篇写的emq。

    emq官方有升级,请安装时注意。

    EMQ 安装与部署 @a.宏万

    首先看官方的说明

    https://docs.espressif.com/projects/esp-idf/zh_CN/latest/api-reference/protocols/mqtt.html#

    本文选择 TCP协议

    链接wifi

        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) );
        ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
        wifi_config_t sta_config = {
            .sta = {
                .ssid = "",//wifi名称
                .password = "",//密码
                .bssid_set = false
            }
        };
        ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config) );
        ESP_ERROR_CHECK( esp_wifi_start() );
        ESP_ERROR_CHECK( esp_wifi_connect() );

    注册mqtt

        const esp_mqtt_client_config_t mqtt_cfg = {
        .host = "*.*.*.*",//服务器IP地址 默认端口 1883 
        };
        esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
        esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
        ESP_ERROR_CHECK(esp_mqtt_client_start(client));

    以上两端代码就可以链接到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_event_handler_cb


    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
    ", event->topic_len, event->topic);
                printf("DATA=%.*s
    ", event->data_len, event->data);
                break;
            case MQTT_EVENT_ERROR://错误事件
                ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
                break;
            case MQTT_EVENT_BEFORE_CONNECT: //事件在连接之前发生
    
                break;
            default:
                ESP_LOGI(TAG, "Other event id:%d", event->event_id);
                break;
        }
        return ESP_OK;
    }
     

    esp-idf mqtt 提供了很多事件

     代码中默认订阅的主题是 :/topic/qos0

    现在我们使用mqtt程序给这个主题发布消息

    使用串口链接软件 链接到esp32 查看打印内容

    测试成功!

    这里多说几句,如果你的设备可以链接mqtt了基本上就啥都可以干了。比如开灯。关灯。
    远程开关电脑,向日葵的开机棒基本上也就是这个原理。

    远程开关,温度传感器。火焰探测。这些都是可以的。

    mqtt最大支持的传输可以达到100多兆,你都可以用设备传输图像了。

    可以更新本地wifi链接,设备重启。

    凡是可以通过消息对话搞定的都可以试试。

    下面是完整代码。

    #include <stdio.h>
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_system.h"
    #include "esp_spi_flash.h"
     
    #include "esp_wifi.h" 
    #include "esp_event.h"
    #include "esp_event_loop.h"
    #include "nvs_flash.h"
    #include "driver/gpio.h"
    
    #include "esp_log.h"
    #include "mqtt_client.h"
    
    static const char *TAG = "MQTT_EXAMPLE";
    
    esp_err_t event_handler(void *ctx, system_event_t *event)
    {
        return ESP_OK;
    }
    
    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
    ", event->topic_len, event->topic);
                printf("DATA=%.*s
    ", event->data_len, event->data);
                break;
            case MQTT_EVENT_ERROR://错误事件
                ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
                break;
            case MQTT_EVENT_BEFORE_CONNECT: //事件在连接之前发生
    
                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);
    }
    
    
    void app_main()
    { 
        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());
        tcpip_adapter_init();
        ESP_ERROR_CHECK(esp_event_loop_create_default());
    
        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) );
        ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
        wifi_config_t sta_config = {
            .sta = {
                .ssid = "xz220",
                .password = "www",
                .bssid_set = false
            }
        };
        ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config) );
        ESP_ERROR_CHECK( esp_wifi_start() );
        ESP_ERROR_CHECK( esp_wifi_connect() );
      
        const esp_mqtt_client_config_t mqtt_cfg = {
        .host = "*.*.*.*", 
        };
        esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
        esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
        ESP_ERROR_CHECK(esp_mqtt_client_start(client));
     
        gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT);
        int level = 0;
        while (true) {
            gpio_set_level(GPIO_NUM_2, level);
            level = !level;
            vTaskDelay(300 / portTICK_PERIOD_MS);
        }
    }
     
  • 相关阅读:
    没了解这些,测试人也要为降薪做好准备!
    测试之巅—自动化测试!
    自动化测试现状趋势解读,附带近年自动化测试常用工具
    技术大佬:如何最快速度上手接口测试?(一篇文章搞定)
    三个Python自动化测试高效工具的使用总结
    Postman接口测试实战分享,这5个问题你必须得知道!【软件测试工程师经验分享】
    Python实现性能自动化测试的方法【推荐好文】
    md5加密
    python操作数据库
    time模块:时间戳和格式化好的时间表示方法及互相转换方法
  • 原文地址:https://www.cnblogs.com/hongwans/p/11217785.html
Copyright © 2020-2023  润新知