【随手记】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上面接收到对应的消息如下

相关推荐
励志的小陈12 小时前
贪吃蛇(C语言实现,API)
c语言·开发语言
Hello_Embed15 小时前
嵌入式上位机开发入门(二十六):将 MQTT 测试程序加入 APP 任务
网络·笔记·网络协议·tcp/ip·嵌入式
爱编码的小八嘎16 小时前
C语言完美演绎8-15
c语言
YSF2017_316 小时前
C语言16-makefile(3)——makefile的模式规则
linux·c语言·开发语言
dgaf18 小时前
谢谢 AI (打靶测试用文)
c语言·gpt·ai编程·d3d12
IpdataCloud19 小时前
IP查询高精度怎么选?8个指标判断是否适合你
网络·网络协议·tcp/ip
聊点儿技术19 小时前
IP风险等级评估是什么?跨境电商业务场景全解析
网络·网络协议·tcp/ip
一行代码一行诗++19 小时前
C语言中scanf详解
c语言·开发语言
ZenosDoron19 小时前
keil软件修改字体,Asm editor,和C/C++ editor的区别
c语言·开发语言·c++
yuan1999720 小时前
C&CG(列与约束生成)算法,来解决“风光随机性”下的微网鲁棒配置问题
c语言·开发语言·算法