本篇文章主要记录一下首次调试mqtt的过程,全是实操流程
YOCTO环境下安装mqtt
先贴一下paho的bb文件安装
bash
SUMMARY = "Industrial MQTT Client for Yocto Linux"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/MIT;md5=0835ade698e0bcf8506eceed2064e710"
SRC_URI = "file://mqtt_client.c"
S = "${WORKDIR}"
DEPENDS = "paho-mqtt-c"
CFLAGS += "-Wall -Wextra"
do_compile() {
${CC} ${CFLAGS} ${LDFLAGS} mqtt_client.c -o mqtt_client -lpaho-mqtt3c -lpthread
}
do_install() {
install -d ${D}${bindir}
install -m 0755 mqtt_client ${D}${bindir}/
}
本地kali环境下测试流程
1、先安装docker
bash
#删除原有的docker源
sudo rm -f /etc/apt/sources.list.d/docker.list
#添加正确的源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
#更新一下
sudo apt clean
sudo apt update
#安装并启动
sudo apt install -y docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
检测安装成功使用 docker --version 查看版本,正常显示版本即代表安装成功
2、安装EMQX(这个是mqtt服务端,后面用以测试我们的代码)
bash
#下载离线安装包
wget https://www.emqx.com/zh/downloads/broker/v5.8.0/emqx-5.8.0-debian12-amd64.deb
#安装
sudo dpkg -i emqx-5.8.0-debian12-amd64.deb
#启动
sudo systemctl start emqx
sudo systemctl enable emqx
#查看状态 出现 active (running) 就是成功!
sudo systemctl status emqx
同时也可以使用http://localhost:18083通过网页访问,界面如下,后续可以通过这个平台来测试代码可行性

然后编写测试用例代码如下
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include "MQTTClient.h"
//本地环境测试
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "kali_publisher"
#define TOPIC "system/status"
/*
** 质量等级
** 0 - 最多一次:消息发送一次,可能丢失,不会重试。
** 1 - 至少一次:消息至少发送一次,可能重复。
** 2 - 只有一次:消息确保只发送一次,使用四步握手协议。(客户端发布->broker回复接收确认->客户端回复释放->broker转发消息并向客户端回复确认)
*/
#define QOS 1
#define TIMEOUT 10000L
typedef struct
{
int battery;
long uptime_sec;
long traffic_rx;
long traffic_tx;
} SystemStatus;
//获取所有状态
void get_system_status(SystemStatus *status)
{
// 获取电量
FILE *fp_bat = fopen("/sys/class/power_supply/BAT0/capacity", "r");
if (fp_bat) {
fscanf(fp_bat, "%d", &status->battery);
fclose(fp_bat);
} else {
status->battery = -1;
}
// 获取开机时长
struct sysinfo info;
sysinfo(&info);
status->uptime_sec = info.uptime;
// 获取网卡流量
FILE *fp_net = fopen("/proc/net/dev", "r");
status->traffic_rx = 0;
status->traffic_tx = 0;
if (fp_net) {
char line[256];
while (fgets(line, sizeof(line), fp_net)) {
if (strstr(line, "eth0")) {
sscanf(line + 10, "%ld %*s %*s %*s %*s %*s %*s %*s %ld",
&status->traffic_rx, &status->traffic_tx);
break;
}
}
fclose(fp_net);
}
}
int main()
{
// 创建mqtt对象
MQTTClient client;
// MQTT 连接选项结构体
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
// MQTT 消息结构体
MQTTClient_message pubmsg = MQTTClient_message_initializer;
// 消息发布令牌
MQTTClient_deliveryToken token;
int rc;
// 创建 MQTT 客户端
MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.cleansession = 1;
// 连接broker
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
printf("连接失败,错误码:%d\n", rc);
return -1;
}
printf("✅ MQTT 连接成功,开始每5秒发布系统状态...\n\n");
while(1) {
// 每次循环都重新获取最新数据
SystemStatus sys_status;
get_system_status(&sys_status);
// 拼接 JSON,实际推荐使用cjson等库,这里为了简单直接拼接字符串
char payload[512];
sprintf(payload,
"{"
"\"battery\":%d,"
"\"uptime_sec\":%ld,"
"\"traffic_rx_bytes\":%ld,"
"\"traffic_tx_bytes\":%ld"
"}",
sys_status.battery,
sys_status.uptime_sec,
sys_status.traffic_rx,
sys_status.traffic_tx
);
// 发布消息
pubmsg.payload = payload;
pubmsg.payloadlen = strlen(payload);
pubmsg.qos = QOS;
pubmsg.retained = 1;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
MQTTClient_waitForCompletion(client, token, TIMEOUT);
// 打印
printf("📤 5秒周期发布成功:%s\n", payload);
sleep(5); // 5秒后再次发布
}
// 这里放一下断链、销毁接口,永远不会走到这里,如果需要优雅退出,可以捕获信号并在信号处理函数中断开连接和销毁客户端
//MQTTClient_disconnect(client, TIMEOUT);
//MQTTClient_destroy(&client);
return 0;
}
通过上述代码。你可以在mqttx上面接收到对应的消息如下
