文章目录
- 一、搭建EMQX本地MQTT服务器
- 1.1 下载
- 1.2 使用
- 二、MQTT.fx安装使用
- 2.1 破解及安装
- 2.2 客户端界面说明
- 2.3 与 WebSocket 客户端互发消息
- 2.3.1 使用MQTT.fx连接到EMQX本地服务器
- 1.General设置
- 2.User Credentials设置
- 3.进行连接
- 2.3.2 MQTT.fx发布和订阅主题
- 1.发布主题
- 2.订阅主题
- 2.3.3 EMQX服务器操作
- 2.3.4 MQTT.fx客户端与 WebSocket 客户端互发消息
- 三、EPS32C3适配MQTT
一、搭建EMQX本地MQTT服务器
1.1 下载
下载EMQX开源版,官方网址:https://www.emqx.com/zh/try?product=broker
选择 5.10.0 版本 ,选择红框下载即可:
将下载好的压缩包进行解压,解压到任意盘即可,注意不要是中文路径。
1.2 使用
操作如下:
1)进入到EMQX的bin目录:输入cd D:\emqx-5.3.0-windows-amd64\bin
2)启动EMQX服务器,输入emqx start
,如需停止服务器,输入emqx stop
3)查看EMQX服务器状态,先进入bin目录:输入cd D:\emqx-5.3.0-windows-amd64\bin
4)接着输入:emqx_ctl status
,可以看到EMQX服务器已启动
1)打开浏览器,输入地址:[http://127.0.0.1:18083/#/login](http://127.0.0.1:18083/#/login)
2)输入用户名:admin,输入密码:public,点击Login
3)修改默认密码,可以修改直接跳过
至此,本地EMQX本地MQTT服务器已搭建成功。
EMQX官方文档:
https://docs.emqx.com/zh/emqx/latest/
二、MQTT.fx安装使用
2.1 破解及安装
这里我提供了MQTT.fx软件的安装压缩包,点击下方连接一路点击next即可,进入界面后需要我们提供密钥,可复制下方密钥输入就可以正常使用了。
压缩包:https://download.csdn.net/download/2301_78772787/91646190
-----BEGIN CERTIFICATE-----
MIIG7jCCBNagAwIBAgIJAOiLlBQu/GDHMA0GCSqGSIb3DQEBDQUAMIGpMQswCQYD
VQQGEwJERTEQMA4GA1UECAwHQmF2YXJpYTERMA8GA1UEBwwIRXJsYW5nZW4xFzAV
BgNVBAoMDlNvZnRibGFkZSBHbWJIMRkwFwYDVQQLDBB3d3cuc29mdGJsYWRlLmRl
MRwwGgYDVQQDDBNTb2Z0YmxhZGUgUm9vdCBDQSAxMSMwIQYJKoZIhvcNAQkBFhRj
b250YWN0QHNvZnRibGFkZS5kZTAeFw0yMDEwMjIxOTEzMDRaFw00MDEwMTcxOTEz
MDRaMIGpMQswCQYDVQQGEwJERTEQMA4GA1UECAwHQmF2YXJpYTERMA8GA1UEBwwI
RXJsYW5nZW4xFzAVBgNVBAoMDlNvZnRibGFkZSBHbWJIMRkwFwYDVQQLDBB3d3cu
c29mdGJsYWRlLmRlMRwwGgYDVQQDDBNTb2Z0YmxhZGUgUm9vdCBDQSAxMSMwIQYJ
KoZIhvcNAQkBFhRjb250YWN0QHNvZnRibGFkZS5kZTCCAiIwDQYJKoZIhvcNAQEB
BQADggIPADCCAgoCggIBAMw3XhycExw0i5GtFgXJoQkYv4B7abAQgSvJoGB8qm9o
0zxr0mHtYBkH7VANQb/m49CEADEVMYVGLVEeBXJ8rEg11ckS4FMxwxzj+YPpvcwS
cqe453+tWC0pFbDkNsZF4Y1ATlSR3Ab7KiQtsgfrsft46oghFE8Oadp0gmwP5O1A
z7SZKBbNadTGfqOK67T5p2gR+TMrb2L2llsStspLfxmGoOZEzytW5goKWKXphio2
vtIuUTiQqAfr7utbY8ZAEjx/srdF9BbxQUpj4zFsqSJfSu1H+l/sN6zOsVAzqTpG
wU3mgttAzlxYlI/SMbhDN817LYHP4IEmg0hgqqk1oEBA1U3y8LWLUuNt4VREscSU
bvPwYdJjApi3CpTmp+YahMk4tqXeJ0bZA0WXpAzPAnCWMHOpGG4rzC2iUJu61klb
9jmmxkOzZV2p/RMKlCGEYuVBM3h7jx8oFZ19Hea9nBarSQyPSvkYt9q3gGgvxN6L
+RvHRmbkHkHsbImKCtNJGg/8wqVmO91GqqjJSuR0IAYta4aRVoNe7UnDMhM5A+jt
smfS4IDklqZrbw/NnVJL+FRnrBfcIHSVJbTs9IFdz6ZGjvCexEu/bgDTwBwvWu4o
YIKNdXMB+UBCifuQEuPEcn4ce2nL9UJcEIGDWjOnJNHhg8efxBenn3ENZNwRBD8P
AgMBAAGjggEVMIIBETAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRO6cF4TD6P
FCYoe+kyrhV335+BODCB3gYDVR0jBIHWMIHTgBRO6cF4TD6PFCYoe+kyrhV335+B
OKGBr6SBrDCBqTELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0JhdmFyaWExETAPBgNV
BAcMCEVybGFuZ2VuMRcwFQYDVQQKDA5Tb2Z0YmxhZGUgR21iSDEZMBcGA1UECwwQ
d3d3LnNvZnRibGFkZS5kZTEcMBoGA1UEAwwTU29mdGJsYWRlIFJvb3QgQ0EgMTEj
MCEGCSqGSIb3DQEJARYUY29udGFjdEBzb2Z0YmxhZGUuZGWCCQDoi5QULvxgxzAN
BgkqhkiG9w0BAQ0FAAOCAgEAda2ef3YTFI2euS2EjZXa5jgdSAvrCpPjX4HVrG0n
3Su+FjIAGam0PMX635wTqj7np9s7NKqZj7IWS7o8EhVL4RqnAHFBq+ta8PXIZQB3
xWf8qbKIBoSmdwUaJw44MeBdhc4nni5O6zho4RY00/FJddLf4kCtcBsXu6Zs8K3a
IW/frSU4I7kD91xnFZ6SQQEZH1UBAttZvK5pO1m2MFkgYqXIOWycNB3CsPqor8sT
zF296Fp4LbyhkI+9HkeoiTce7oZQGPl346FwVYw4ERuiH7C217gy5TMRK/bangxq
yDOoOXyrRbWfyfhYnmexAe8k/IFix5XzHU9yU7iWvc1Y1nj4tnqIUnas3oXK08TU
vesfK4iUXviJQdRYIWpIJ1g1bagzec2sijFVIdSG0qThBXWiQp98tojCi9Z7fm5U
Et5douMZMm17wc5ELyX2nx083b6+5xMBpEFYrES9iiefMFFD7hmHb5r8B17iOnW6
ujZi5U/9ZhpnuVvI3VGqSDQfne8p3ra814X1gOtKJPWQRU6i0/1tfo+Pxw+ATB1j
h4ZxMEGx9zGF3UAD6VATeKE6yepfwrKiXAHz3gyLeD5F7Di8IFtKs5yIpjK4/Jfp
IkolTm9gBMKDT723nlfOS7xVHHnfP5auH+Wmgmb9BlavBO/k5zcqxMA3VfWsqnIS
Ekc=
-----END CERTIFICATE-----
2.2 客户端界面说明
下载完毕并破解之后界面如下:
点击设置配置文件,进入如下界面:
2.3 与 WebSocket 客户端互发消息
2.3.1 使用MQTT.fx连接到EMQX本地服务器
1.General设置
2.User Credentials设置
以上设置完毕后,点击Apply保存,然后关闭退出。
3.进行连接
绿灯表示连接成功
2.3.2 MQTT.fx发布和订阅主题
1.发布主题
MQTT.fx客户端发布主题:testtopic/test1,服务质量等级选择QoS0,消息内容如下:LjunG666
2.订阅主题
MQTT.fx客户端订阅主题:testtopic/test2,服务质量等级选择QoS0
2.3.3 EMQX服务器操作
打开WebSocket 客户端,输入IP地址、端口号,用户名和密码,即可连接。
WebSocket客户端订阅主题:testtopic/test1,服务质量等级选择QoS0。
WebSocket客户端发布主题:testtopic/test2,服务质量等级选择QoS0,消息内容如下:LjunG666
2.3.4 MQTT.fx客户端与 WebSocket 客户端互发消息
MQTT.fx客户端发送,WebSocket 客户端接收。
WebSocket 客户端发送,MQTT.fx客户端接收。
至此, MQTT.fx客户端与WebSocket 客户端互发消息成功,服务器是EMQX。
三、EPS32C3适配MQTT
1.创建客户端
2.指定IP地址和端口号
3.进行连接
4.发布主题或者订阅主题
5.数据传输
6.断开连接
下载到官方示例(位于/esp/esp-idf/examples/protocols/mqtt/tcp),在官方示例上做修改,修改后的代码如下:
/* * MQTT (over TCP) 示例代码* 本示例代码属于公共领域(或根据CC0许可,可选)。* 除非适用法律要求或书面同意,否则本软件按"原样"分发,* 不提供任何明示或暗示的担保或条件。*/#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_event_loop.h"
#include "tcpip_adapter_types.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"// WiFi配置:连接的热点名称和密码
#define EXAMPLE_ESP_WIFI_SSID "FM_392383" // 要连接的WiFi名称
#define EXAMPLE_ESP_WIFI_PASS "12345678" // 要连接的WiFi密码// MQTT服务器配置:服务器IP和端口
#define EXAMPLE_ESP_MQTT_HOST "192.168.0.194" // MQTT服务器IP地址
#define EXAMPLE_ESP_MQTT_PORT 1883 // MQTT服务器端口(默认非加密端口)// 日志标签(用于区分不同模块的日志输出)
static const char *TAG = "MQTT_EXAMPLE";// 事件组句柄:用于同步WiFi和MQTT的连接状态
static EventGroupHandle_t wifi_event_group; // WiFi连接状态事件组
static EventGroupHandle_t mqtt_event_group; // MQTT连接状态事件组
const static int CONNECTED_BIT = BIT0; // 连接成功的标志位(二进制0001)
esp_mqtt_client_handle_t mqttclient; // MQTT客户端句柄(全局变量,方便各函数调用)// 函数声明(后续定义)
static void mqtt_app_start(void); // MQTT客户端初始化与启动
static void wifi_init(void); // WiFi初始化与连接
static esp_err_t wifi_event_handler(void *ctx, system_event_t *event); // WiFi事件处理函数
static void process_ctrl_message(char * str); // (未实现)处理控制消息的函数/** @brief 注册用于接收MQTT事件的事件处理函数** 此函数由MQTT客户端事件循环调用。** @param handler_args 注册到事件的用户数据* @param base 事件的基础(本示例中始终是MQTT相关)* @param event_id 接收的事件ID* @param event_data 事件的数据(esp_mqtt_event_handle_t类型)*/
// MQTT事件处理函数:处理各类MQTT事件(连接、断开、接收数据等)
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{ESP_LOGD(TAG, "事件从事件循环分发,base=%s, event_id=%d", base, event_id);esp_mqtt_event_handle_t event = event_data; // 事件数据指针转换esp_mqtt_client_handle_t client = event->client; // 当前MQTT客户端句柄int msg_id; // 消息ID(用于跟踪发布/订阅的结果)// 根据事件ID处理不同类型的事件switch ((esp_mqtt_event_id_t)event_id) {case MQTT_EVENT_CONNECTED: // MQTT连接成功事件ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");// 设置MQTT连接成功的标志位(用于通知其他等待连接的任务)xEventGroupSetBits(mqtt_event_group, CONNECTED_BIT);// 发送订阅:订阅主题"/topic/test1",QoS等级1msg_id = esp_mqtt_client_subscribe(client, "/topic/test1", 1);ESP_LOGI(TAG, "订阅主题成功, 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);// 订阅成功后,向"/topic/qos0"发布一条测试消息msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);ESP_LOGI(TAG, "发布消息成功, 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");// 打印接收的主题和数据(%.*s表示按指定长度输出字符串)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);break;default: // 其他未处理的事件ESP_LOGI(TAG, "Other event id:%d", event->event_id);break;}
}// WiFi事件处理函数:处理WiFi连接状态变化(启动、获取IP、断开等)
static esp_err_t wifi_event_handler(void *ctx, system_event_t *event)
{switch (event->event_id) {case SYSTEM_EVENT_STA_START: // WiFi STA模式启动事件esp_wifi_connect(); // 启动后主动连接WiFibreak;case SYSTEM_EVENT_STA_GOT_IP: // WiFi获取IP地址事件(连接成功)// 设置WiFi连接成功的标志位xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);break;case SYSTEM_EVENT_STA_DISCONNECTED: // WiFi断开连接事件esp_wifi_connect(); // 断开后自动重连xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); // 清除连接标志位break;default: // 其他未处理的WiFi事件break;}return ESP_OK; // 事件处理成功
}// WiFi初始化函数:配置WiFi为STA模式并连接到指定热点
static void wifi_init(void)
{tcpip_adapter_init(); // 初始化TCP/IP适配器(旧版ESP-IDF函数,新版可用esp_netif_init替代)// 创建事件组(用于同步WiFi和MQTT的连接状态)wifi_event_group = xEventGroupCreate();mqtt_event_group = xEventGroupCreate();// 初始化事件循环,注册WiFi事件处理函数ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL));// 初始化WiFi配置(使用默认配置)wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));// 设置WiFi配置存储位置(RAM:重启后不保留配置)ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));// 配置WiFi连接参数(SSID和密码)wifi_config_t wifi_config = {.sta = { // STA模式配置.ssid = EXAMPLE_ESP_WIFI_SSID, // 热点名称.password = EXAMPLE_ESP_WIFI_PASS, // 热点密码},};// 设置WiFi模式为STA(客户端模式,连接其他热点)ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));// 应用WiFi配置ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));ESP_LOGI(TAG, "启动WiFi,SSID:[%s]", wifi_config.sta.ssid);// 启动WiFiESP_ERROR_CHECK(esp_wifi_start());ESP_LOGI(TAG, "等待WiFi连接...");// 等待WiFi连接成功(阻塞直到获取到CONNECTED_BIT标志)xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
}// MQTT客户端初始化与启动函数
static void mqtt_app_start(void)
{// 配置MQTT客户端参数esp_mqtt_client_config_t mqtt_cfg = {.host = EXAMPLE_ESP_MQTT_HOST, // MQTT服务器IP地址.event_handle = mqtt_event_handler, // MQTT事件处理函数.port=EXAMPLE_ESP_MQTT_PORT, // MQTT服务器端口};// 条件编译:如果配置了从标准输入获取MQTT服务器URL(默认不启用)
#if CONFIG_BROKER_URL_FROM_STDINchar line[128]; // 存储输入的URLif (strcmp(mqtt_cfg.uri, "FROM_STDIN") == 0) {int count = 0;printf("请输入MQTT服务器的URL\n");// 读取用户输入的URL(最多127字符)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); // 短暂延时,避免占用CPU}mqtt_cfg.uri = line; // 更新服务器URLprintf("服务器URL: %s\n", line);} else {ESP_LOGE(TAG, "配置不匹配:错误的服务器URL");abort(); // 配置错误,终止程序}
#endif /* CONFIG_BROKER_URL_FROM_STDIN */printf("esp_mqtt_client_start\r\n");// 初始化MQTT客户端(根据配置创建客户端实例)mqttclient = esp_mqtt_client_init(&mqtt_cfg);/* 最后一个参数可用于向事件处理函数传递数据,本示例中为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连接成功(阻塞直到获取到CONNECTED_BIT标志)xEventGroupWaitBits(mqtt_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
}// 应用主函数(程序入口)
void app_main(void)
{ESP_LOGI(TAG, "[APP] 启动中..");ESP_LOGI(TAG, "[APP] 空闲内存: %d 字节", esp_get_free_heap_size()); // 打印当前空闲内存ESP_LOGI(TAG, "[APP] IDF版本: %s", esp_get_idf_version()); // 打印ESP-IDF版本// 设置日志输出级别(*表示所有模块,其他为特定模块)esp_log_level_set("*", ESP_LOG_INFO); // 全局日志级别:INFO(只输出重要信息)esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE); // MQTT客户端:VERBOSE(最详细)esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE); // 本示例模块:VERBOSEesp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE); // 传输层基础:VERBOSEesp_log_level_set("esp-tls", ESP_LOG_VERBOSE); // TLS层:VERBOSEesp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); // 传输层:VERBOSEesp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); // 消息发送队列:VERBOSE// 初始化NVS(非易失性存储,用于保存WiFi等配置)nvs_flash_init();// 初始化并连接WiFiwifi_init(); // 初始化并启动MQTT客户端mqtt_app_start();// 主循环:周期性发布消息while (1) {printf("Test running!\r\n"); // 打印运行状态// 向主题"/topic/esp32"发布消息"Hi, I am ESP32C3"// 参数:客户端句柄、主题、消息内容、内容长度(0表示自动计算)、QoS等级(0)、是否保留消息(0)esp_mqtt_client_publish(mqttclient, "/topic/esp32", "Hi, I am ESP32C3", 0, 0, 0);vTaskDelay(1000 / portTICK_PERIOD_MS); // 延时1秒(周期性执行)}
}
最主要的是要注意ip地址修改,需要修改成与MQTT服务器同一局域网ip。
现象如下:
输入minocom
查看串口打印:
ESP32中的发送订阅为:/topic/test1,在MQTT.fx中修改后发布主题:
ESP32中的发布主题为:/topic/esp32,在MQTT.fx中订阅后可接收到ESP32的消息: