【随手记】YOCTO下MQTT使用简记

本篇文章主要记录一下首次调试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上面接收到对应的消息如下

相关推荐
@insist1233 小时前
网络工程师-OSI 七层模型与 TCP/IP 协议族:核心考点全解析
网络·网络协议·tcp/ip·网络工程师·软考·软件水平考试
计算机安禾3 小时前
【数据结构与算法】第22篇:线索二叉树(Threaded Binary Tree)
c语言·开发语言·数据结构·学习·算法·链表·visual studio code
算法鑫探3 小时前
解密2025数字密码:数位统计之谜
c语言·数据结构·算法·新人首发
:mnong3 小时前
Superpowers 项目设计分析
java·c语言·c++·python·c#·php·skills
计算机安禾3 小时前
【数据结构与算法】第21篇:二叉树遍历的经典问题:由遍历序列重构二叉树
c语言·数据结构·学习·算法·重构·visual studio code·visual studio
笨笨饿5 小时前
26_为什么工程上必须使用拉普拉斯变换
c语言·开发语言·人工智能·嵌入式硬件·机器学习·编辑器·概率论
初生牛犊不怕苦6 小时前
与AI一起学习《C专家编程》:数组与指针
c语言·学习·算法
小CC吃豆子7 小时前
C/C++中 int 的最大最小值
c语言·开发语言·c++
co_wait9 小时前
【C语言】字符串处理函数
c语言·开发语言