图文手把手教程--ESP32 MQTT对接EMQX本地服务器(VSCODE+ESP-IDF)

本文内容

1)使用MQTT_TCP例程,ESP32通过MQTT协议与MQTT本地服务器(EMQX)进行通信。

2)如何搭建EMQX MQTT本地服务器。

3)如何使用MQTT.fx客户端调试工具或MQTTX客户端调试工具。

开发环境

1)系统平台:windows7或windows10。

2)开发板:乐鑫开发板ESP32-DevKitC-V4(模组是ESP32­WROOM­32E)。

3)集成开发环境:VSCODE+ESP-IDF插件,见以下链接

图文手把手教程(史上最强):windows下ESP32集成开发环境搭建和HelloWorld显示(乐鑫官方推荐方法-使用VSCode安装ESP-IDF插件)

一、准备工作

需要下载工具并安装,如下:

1.下载MQTT.fx客户端(版本v1.7.1):http://mqttfx.jensd.de/index.php/download,官网找不到下载入口?

这里提供博客下载:https://download.csdn.net/download/felix_tao/86248840

2.下载MQTT X客户端(版本v1.8.0.win64):https://mqttx.app/zh

二、搭建EMQX本地MQTT服务器

1.下载EMQX开源版,官方网址:https://www.emqx.com/zh/try?product=broker

选择版本号v5.0.3,系统:windows,然后点击“免费下载”。

 

2.将下载好的 emqx-5.0.3-windows-amd64.tar.gz,进行解压,我是解压到E盘根目录。

注意:根目录下最好不要有中文。

3.打开命令行工具,进入目录运行EMQX服务。

电脑左下角,右键开始->运行->输入cmd,确定->打开命令行工具,操作如下:

1)切换到E盘:输入e:

2)进入到EMQX的bin目录:输入cd E:\emqx-5.0.3-windows-amd64\bin

3)启动EMQX服务器,输入emqx start,如需停止服务器,输入emqx stop

4)查看EMQX服务器状态,先进入bin目录:输入cd E:\emqx-5.0.3-windows-amd64\bin

5)接着输入:emqx_ctl status,可以看到EMQX服务器已启动

 4.登陆EMQX服务器,验证是否可用。

1)打开浏览器,输入地址:http://127.0.0.1:18083/#/login

2)输入用户名:admin,输入密码:public,点击Login

3)更改界面为中文。

至此,本地EMQX本地MQTT服务器已搭建成功。

三、MQTT.fx客户端简单说明,如下图所示。

1主页面

2通用设置界面

3用户信息设置

4安全证书设置

5网络代理设置

6遗嘱设置

 四、MQTT.fx客户端与WebSocket 客户端互发消息。

1.使用MQTT.fx连接到EMQX本地服务器。

1)General设置如下图所示。

 2)User Credentials设置。

 以上设置完毕后,点击Apply保存,然后关闭退出。

3)进行连接,亮绿灯,表示连接成功。

 2.MQTT.fx发布和订阅主题,以ESP32例程的topic主题为例。

1)MQTT.fx客户端发布主题:/topic/qos1,服务质量等级选择QoS1,消息内容如下:

{ "msg": "hello I am mqtt.fx" }

2)MQTT.fx客户端订阅主题:/topic/qos0,服务质量等级选择QoS0

3.登陆EMQX服务器管理页面,连接WebSocket 客户端到服务器,并发布和订阅主题。

1)打开WebSocket 客户端,输入IP地址、端口号,用户名和密码,即可连接。

 

2)WebSocket客户端订阅主题:/topic/qos1,服务质量等级选择QoS1。

3)WebSocket客户端发布主题:/topic/qos0,服务质量等级选择QoS0,消息内容如下:

{ "msg": "hello I am emqx web" }

4.MQTT.fx客户端与WebSocket 客户端互发消息。

1)MQTT.fx客户端发送,WebSocket 客户端接收。

 

2)WebSocket 客户端发送,MQTT.fx客户端接收。

 

至此, MQTT.fx客户端与WebSocket 客户端互发消息成功,服务器是EMQX。

 五、ESP32连接到EMQX服务器,与MQTT.fx客户端互发消息

1.VSCODE+ESP-IDF插件开发环境的搭建,见本文的开头的链接。

2.打开示例项目MQTT_TCP:VSCODE中->"查看"->”命令面板“->输入:Show Examples projects->选择Use current ESP-IDF(E:\ESP32-IDF\esp\esp-idf)->弹出示例ESP-IDF Examples,选择mqtt->tcp->Create project using example tcp->选择示例保存的路径。

 例如:E:\ESP32-IDF\project-example,因ESP-IDF框架与示例是分离的,所以示例保存的路径可以随意,但需要注意:路径不能有中文和空格,否则报错。

 创建完后,如下图所示。

关于示例的说明,请阅读官方的注释。

 打开E:\ESP32-IDF\esp\esp-idf\examples\protocols->README,如下图所示。

 README的内容如下:

 对示例有个大概了解后,接下来需要修改代码。

3.修改示例代码。

1)修改wifi配置,这里修改为自己的wifi帐号和密码即可。

wifi_config_t wifi_config = {
        .sta = {
            .ssid = "Xiaomi_tao",
            .password = "123456",
        },
    };

2)修改MQTT配置,如果是使用EMQX本地服务器,即只需要修改MQTT服务器IP即可。

注意:这里的IP是指自己电脑的IPv4地址,如果是win7系统,ESP32连不上EMQX服务器,则需要将IPv4地址修改为静态固定IP地址,我这里是win10系统,不改固定IP地址也可以连上。

esp_mqtt_client_config_t mqtt_cfg = {
        .host = "192.168.31.107",                  //MQTT服务器IP
        .event_handle = mqtt_event_handler,        //MQTT事件
        .port=1883,                                //端口
        .username = "admin",                       //用户名
        .password = "public",                      //密码
        // .user_context = (void *)your_context
    };

3.修改app_main.c,如下:

/* 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 <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_event_loop.h"
#include "tcpip_adapter_types.h"
//#include "protocol_examples_common.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/event_groups.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";

//wifi连上事件
static EventGroupHandle_t wifi_event_group;
//mqtt连上事件
static EventGroupHandle_t mqtt_event_group;
const static int CONNECTED_BIT = BIT0;
esp_mqtt_client_handle_t mqttclient;

// static void log_error_if_nonzero(const char *message, int error_code)
// {
//     if (error_code != 0) {
//         ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
//     }
// }

/*
 * @brief Event handler registered to receive MQTT events
 *
 *  This function is called by the MQTT client event loop.
 *
 * @param handler_args user data registered to the event.
 * @param base Event base for the handler(always MQTT Base in this example).
 * @param event_id The id for the received event.
 * @param event_data The data for the event, esp_mqtt_event_handle_t.
 */
//事件处理函数
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);
    esp_mqtt_event_handle_t event = event_data;
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;

    switch ((esp_mqtt_event_id_t)event_id) {
    case MQTT_EVENT_CONNECTED:  //MQTT连上事件
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        xEventGroupSetBits(mqtt_event_group, CONNECTED_BIT);
        
        //发布主题
        // printf("Connecting to MQTT broker OK");
        // 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:  //MQTT断开连接事件
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        //mqtt连上事件
        xEventGroupClearBits(mqtt_event_group, CONNECTED_BIT);
        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:  //MQTT错误事件
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        xEventGroupClearBits(mqtt_event_group, CONNECTED_BIT);
        // 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;
    }
}

//wifi状态机
static esp_err_t wifi_event_handler(void *ctx, system_event_t *event)
{
    switch (event->event_id) {
        case SYSTEM_EVENT_STA_START:
            esp_wifi_connect();
            break;
        case SYSTEM_EVENT_STA_GOT_IP:
            xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);

            break;
        case SYSTEM_EVENT_STA_DISCONNECTED:
            esp_wifi_connect();
            xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
            break;
        default:
            break;
    }
    return ESP_OK;
}

//wifi初始化
static void wifi_init(void)
{
    tcpip_adapter_init();
    wifi_event_group = xEventGroupCreate();
    mqtt_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_init(wifi_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));
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = "Xiaomi_tao",
            .password = "123456",
        },
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
    ESP_LOGI(TAG, "start the WIFI SSID:[%s]", wifi_config.sta.ssid);
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_LOGI(TAG, "Waiting for wifi");
    //等待wifi连上
    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
}
//mqtt初始化
static void mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
        .host = "192.168.31.107",                  //MQTT服务器IP
        .event_handle = mqtt_event_handler,        //MQTT事件
        .port=1883,                                //端口
        .username = "admin",                       //用户名
        .password = "public",                      //密码
        // .user_context = (void *)your_context
    };
#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 */

    printf("esp_mqtt_client_start\r\n");

    //通过esp_mqtt_client_init获取一个MQTT客户端结构体指针,参数是MQTT客户端配置结构体
    mqttclient = esp_mqtt_client_init(&mqtt_cfg);
    
    /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
    //注册MQTT事件
    esp_mqtt_client_register_event(mqttclient, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    //开启MQTT功能
    esp_mqtt_client_start(mqttclient);

    //等mqtt连上
    xEventGroupWaitBits(mqtt_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
}

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_BASE", ESP_LOG_VERBOSE);
    esp_log_level_set("esp-tls", 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());
    nvs_flash_init();
    wifi_init();
    mqtt_app_start();

    while (1) {
        
        printf("system is running!\r\n");

        //发布主题
        esp_mqtt_client_publish(mqttclient, "/topic/qos0", "Hello MQTT,I am ESP32", 0, 0, 0);
        vTaskDelay(1000 / portTICK_PERIOD_MS);

    }
}

4.修改完毕后,编译下载,打开串口调试助手,可以看到连接EMQX服务器成功。

注意:EMQX服务器,每次开机后,都要重新启动,\bin目示下,命令:emqx start。

5.打开EMQX服务器网页http://127.0.0.1:18083/#/login,可以看到ESP32与MQTT.fx都连接成功。

 6.ESP32与MQTT.fx客户端互通消息。

1)ESP32主动发送消息给MQTT.fx客户端。

2)MQTT.fx客户端发送消息给ESP32。

 7.ESP32与MQTTX客户端互通消息,与MQTT.fx客户端用法是一样的。

1)修改中文版本。

2)填写相关信息。

 2)ESP32主动发送消息给MQTTX客户端。

3)MQTTX客户端发送消息给ESP32。

 至此,本文内容全部完毕,愉快的玩耍吧!

完整的例程代码下载:https://download.csdn.net/download/felix_tao/86248836

使用例程,报错怎么办,解决办法如下:

1)打开VSCODE报错,c_cpp_properties.json无法找到E:\\ESP32-IDF...

解决办法:点击.vscode->c_cpp_properties.json,修改盘符即可,例如将E盘改为D盘。

2)编译工程报错:

[0/1] Re-running CMake...
FAILED: build.ninja 
CreateProcess failed: The system cannot find the file specified.
ninja: error: rebuilding 'build.ninja': subcommand failed

解决方法:清除编译产生的所有文件,左下角->点击垃圾桶图标(ESP-IDF Full Clean)->清除后,接着重新编译即OK。

本文参考了以下博客,鸣谢!

第二十一章 ESP32开发MQTT Client ESP-IDF_开源一小步的博客-CSDN博客_esp32 mqtt

mqtt.fx | 一款超级好用的Mqtt客户端软件(下载、安装、使用详解)_Mculover666的博客-CSDN博客_mqtt.fx

验证EMQ X服务器的搭建以及MQTTX的简单使用_哈哈浩丶的博客-CSDN博客

  • 19
    点赞
  • 161
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 23
    评论
### 回答1: 要将STM32与ESP8266连接到EMQX,需要遵循以下步骤: 1. 首先,您需要在STM32上安装MQTT客户端库,例如MQTT-SN或Paho MQTT。 2. 然后,您需要将ESP8266配置为MQTT客户端,并确保它可以连接到EMQX代理。 3. 接下来,您需要编写STM32代码来连接到ESP8266,并使用MQTT协议与EMQX代理通信。 4. 最后,您需要测试连接并确保数据可以在STM32和EMQX之间传输。 需要注意的是,连接到EMQX代理需要正确的配置和设置,以确保安全和可靠的通信。您可以参考EMQX文档和社区支持来获取更多信息和帮助。 ### 回答2: STM32是一款常用的嵌入式处理器,而ESP8266则是一款常用的Wi-Fi模块,可以提供网络连接功能。而EMQX则是一款开源的MQTT消息服务器,可以提供MQTT协议的消息传递功能。将这三个模块结合在一起,可以实现STM32通过ESP8266模块连接EMQX消息服务器的功能,并可以实现简单的消息传递。 要实现STM32使用ESP8266连接EMQX,需要先了解MQTT协议的相关知识。MQTT协议是一种轻量级的物联网通信协议,可以实现消息的订阅、发布和分发。ESP8266模块可以通过Wi-Fi连接到EMQX服务器,并且使用MQTT协议向服务器发送消息或从服务器接收消息。而STM32代码可以使用MQTT库实现协议的相应控制。 具体实现步骤如下: 1. 搭建EMQX服务器,并在MQTT客户端中创建一个新的Topic。 2. 将ESP8266连接到Wi-Fi网络,并设置其为MQTT客户端。在ESP8266代码中,可以使用MQTT库来实现连接到EMQX服务器。 3. STM32需要使用串口通信与ESP8266进行数据通信。可以使用USART或UART来实现这种通信,其中USART可以提供更高的传输速度,并能够同时实现发送和接收数据。 4. 将STM32连接到ESP8266,再通过USART或UART实现数据的双向传输。将STM32中的MQTT库与ESP8266的MQTT库结合起来,就可以实现STM32使用ESP8266连接EMQX服务器的功能。 总之,STM32通过ESP8266连接EMQX服务器,需要实现的主要功能包括建立Wi-Fi连接,使用MQTT协议进行通信,实现STM32与ESP8266之间的双向数据传输等。需要对MQTT协议、ESP8266的操作和STM32的串口通信有较深入的了解才能实现这一功能。 ### 回答3: stm32是一款广泛应用于嵌入式系统的微控制器,而esp8266是一款高集成度、高性能的Wi-Fi芯片,可用于连接互联网。emqx是一款开源的分布式消息中间件,在物联网领域中得到了广泛的应用。在这篇文章中,我们将探讨如何使用stm32和esp8266mqtt连接emqx。 首先,我们需要准备一些材料。我们需要一块stm32开发板和一块esp8266无线模块,以及相应的连接电缆。我们还需要在计算机上安装keilMDK开发环境和相关的驱动程序。 接下来,我们需要在开发板上连接esp8266模块。我们可以使用UART串口或SPI接口来进行连接。如果使用UART串口,我们需要连接GND、TX和RX引脚。如果使用SPI接口,我们需要连接GPIO引脚和SPI接口。可以根据不同的开发板和esp8266模块来进行调整。 一旦我们成功地将stm32和esp8266连接起来,我们就可以开始编程了。我们可以使用keilMDK环境和相应的库文件来实现这个过程。在代码中,我们需要封装mqtt连接指令,以实现与emqx的连接。我们还需要将mqtt协议的实现代码加入到我们的程序中。 最后,在我们的代码中添加相应的数据包并发送到emqx服务器,以与其他设备进行通信。我们可以在emqx中配置相应的订阅和发布主题,确保我们的设备能够正确地接收和发送消息。 总之,使用stm32和esp8266mqtt连接emqx可以帮助我们实现设备之间的通信,提高物联网系统的整体性能。使用正确的工具和方法,可以使这个过程变得非常简单,让我们能够更好地应对物联网的挑战。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淘梦TaoDream

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值