3. 使用RT-Thread连接EMQX云平台
任务目标
在EMQX Cloud创建MQTT Broker部署,配置设备用户名与密码认证;基于RT-Thread的paho_mqtt软件包完成设备接入,实现主题订阅与消息发布,验证端到端通信链路。
前置准备
- EMQX Cloud(serverless或专有版)已创建部署,获取连接地址、端口(默认8083/8084)与连接凭证。
- RT-Thread工程已开启
paho_mqtt软件包(ENV中menuconfig勾选,依赖netutils与lwIP)。 - 开发板已能正常联网(ping通外网)。
EMQX Cloud侧配置
- 在EMQX Cloud控制台创建部署,选择版本与地域。
- 进入认证 → 添加认证,选择用户名密码方式,添加设备:
device_001/pass1234。 - 在访问控制 → 授权中,为
device_001添加发布/订阅权限(允许test/topic/#)。 - 记录部署的连接地址(形如
broker.emqx.io或自定义域名)与TCP端口(默认1883,TLS为8883)。
核心代码实现
以下代码基于RT-Thread的paho_mqtt软件包,完成MQTT连接、订阅与发布。将代码保存为mqtt_emqx_sample.c,加入工程编译。
#include <rtthread.h>
#include <stdio.h>
#include <string.h>
#include "paho_mqtt.h"
#define MQTT_HOST "your-deployment-id.emqxsl.com" // 替换为实际地址
#define MQTT_PORT 1883
#define MQTT_USERNAME "device_001"
#define MQTT_PASSWORD "pass1234"
#define MQTT_CLIENTID "rtthread-device-001"
#define SUB_TOPIC "test/topic/data"
#define PUB_TOPIC "test/topic/cmd"
static MQTTClient client;
static int msg_count = 0;
/* 消息到达回调 */
static void mqtt_message_arrived(MQTTClient *c, char *topicName, int topicLen,
MQTTMessage *message)
{
rt_kprintf(" [SUB] topic: %.*s, payload: %.*s\n",
topicLen, topicName,
(int)message->payloadlen, (char *)message->payload);
}
/* 连接成功回调 */
static void mqtt_connect_callback(MQTTClient *c)
{
rt_kprintf(" MQTT connected to EMQX\n");
}
/* 连接断开回调 */
static void mqtt_disconnect_callback(MQTTClient *c)
{
rt_kprintf(" MQTT disconnected\n");
}
/* 发布线程 */
static void mqtt_publish_thread(void *param)
{
char buf[64];
MQTTMessage msg;
while (1)
{
rt_thread_mdelay(5000); // 每5秒发布一次
if (MQTTIsConnected(&client))
{
msg_count++;
rt_snprintf(buf, sizeof(buf), "hello from rt-thread #%d", msg_count);
msg.qos = 1;
msg.retained = 0;
msg.payload = buf;
msg.payloadlen = strlen(buf);
if (MQTTPublish(&client, PUB_TOPIC, &msg) == SUCCESS)
rt_kprintf(" [PUB] %s -> %s\n", PUB_TOPIC, buf);
else
rt_kprintf(" [PUB] failed\n");
}
}
}
/* MQTT初始化与连接 */
static int mqtt_emqx_init(void)
{
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
Network n;
int rc;
/* 初始化网络 */
NetworkInit(&n);
if (NetworkConnect(&n, MQTT_HOST, MQTT_PORT) != 0)
{
rt_kprintf(" Network connect failed\n");
return -1;
}
/* 配置连接参数 */
data.clientID.cstring = MQTT_CLIENTID;
data.username.cstring = MQTT_USERNAME;
data.password.cstring = MQTT_PASSWORD;
data.keepAliveInterval = 30;
data.cleansession = 1;
MQTTClientInit(&client, &n, 1024, 1024);
MQTTClientSetCallbacks(&client, NULL, mqtt_connect_callback,
mqtt_message_arrived, mqtt_disconnect_callback);
rc = MQTTConnect(&client, &data);
if (rc != SUCCESS)
{
rt_kprintf(" MQTT connect failed, rc=%d\n", rc);
return -1;
}
/* 订阅主题 */
if (MQTTSubscribe(&client, SUB_TOPIC, 1) != SUCCESS)
{
rt_kprintf(" Subscribe failed\n");
return -1;
}
rt_kprintf(" Subscribed to %s\n", SUB_TOPIC);
/* 创建发布线程 */
rt_thread_t tid = rt_thread_create("mqtt_pub", mqtt_publish_thread,
RT_NULL, 2048, 20, 10);
if (tid)
rt_thread_startup(tid);
return 0;
}
/* 导出到MSH命令 */
static void mqtt_start(void)
{
if (mqtt_emqx_init() != 0)
rt_kprintf(" MQTT start failed\n");
}
MSH_CMD_EXPORT(mqtt_start, start mqtt connection to emqx);
编译与烧录
- 将上述代码放入工程
applications目录。 - 在ENV中确认已开启
paho_mqtt软件包,并配置网络(如ESP8266/以太网)。 - 使用
scons编译,烧录固件至开发板。
运行与验证
- 开发板启动后,在MSH控制台输入
mqtt_start。 - 观察串口输出,预期出现
MQTT connected to EMQX与Subscribed to test/topic/data。 - 每5秒应看到
[PUB] test/topic/cmd -> hello from rt-thread #N,N递增。 - 在EMQX Cloud控制台的在线客户端页面,应能看到
rtthread-device-001处于在线状态。 - 使用MQTT X或EMQX控制台的WebSocket客户端,向
test/topic/data发送消息,开发板串口应打印[SUB]开头的接收日志。
通过条件:开发板成功连接EMQX并保持在线;发布消息能在MQTT X中收到;MQTT X发送的消息能被开发板订阅接收。若连接失败,优先检查地址端口、用户名密码及EMQX授权规则。