Qt工程使用MQTT-C库与mqtt服务器数据通信

news2024/11/17 3:49:08

实现mqtt订阅与发布话题,与mqtt服务器进行数据通信

编译环境:Qt5.15.2 + vs2019

需要mqttc库:mqttc.lib, mqttc.dll(根据MQTT-C源码编译出来的库,参考cmake编译MQTT-C源码-CSDN博客)

一、Qt pro文件编写

在Demo中创建mqtt-c文件夹,将mqttc库放在指定文件夹下,MQTT-C头文件包括mqtt_pal.h与mqtt.h。

QT += quick

CONFIG += c++17

SOURCES += \
        main.cpp

RESOURCES += qml.qrc

INCLUDEPATH += $$PWD/ mqtt-c/include \
                $$PWD/mqtt-c/templates

# 链接静态库
LIBS += -L$$PWD/mqtt-c/lib -lmqttc

DebugBuild {
    DESTDIR  = $${OUT_PWD}/debug
} else {
    DESTDIR  = $${OUT_PWD}/release
}

win32 {
    message("Building for MQTT-C Windows")
    # MQTT文件夹名
    MQTT_PATH = mqtt-c

    DESTDIR_WIN = $$replace(DESTDIR, "/", "\\")
    message($$DESTDIR_WIN)

    # 拷贝动态库
    MQTTC_DLL = \
        $$PWD\\$$MQTT_PATH\\bin\\mqttc.dll
    # 拷贝动态库到exe可执行文件同级文件夹下
    QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"$$MQTTC_DLL\" \"$$DESTDIR_WIN\"
}

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
二、实现Mqtt发布、订阅话题功能,与mqtt服务器数据通信。 
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <iostream>

#include "posix_sockets.h"
#include "mqtt.h"  // 包含MQTT库的头文件

const char* DEFAULT_HOST = "47.120.xx.xxx"; // 替换成mqtt服务器地址
const char* DEFAULT_PORT = "1883";
const char* TOPIC = "testtopic/MAV";

void publish_callback(void** unused, struct mqtt_response_publish *published) {
    // 收到发布消息时的回调
    char* topic_name = (char*)malloc(published->topic_name_size + 1);
    memcpy(topic_name, published->topic_name, published->topic_name_size);
    topic_name[published->topic_name_size] = '\0';

    // 修复收到的多余字符
    char* message = (char*)malloc(published->application_message_size + 1);
    memcpy(message, published->application_message, published->application_message_size);
    message[published->application_message_size] = '\0';  // 添加结束符
    
std::cout << "Received message on topic: " << std::string((const char*)published->topic_name, published->topic_name_size)
              << ", message: " << message << std::endl;
}

DWORD WINAPI client_refresher(LPVOID client) {
    while (1) {
        mqtt_sync((struct mqtt_client*)client);
        Sleep(100);
    }
    return 0;
}

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
        qDebug() << "WSAStartup failed.";
        return -1;
    }

    //SOCKET sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    int sockfd = open_nb_socket(DEFAULT_HOST, DEFAULT_PORT);
    if (sockfd == INVALID_SOCKET) {
        qDebug() << "Socket creation failed.";
        WSACleanup();
        return -1;
    }

    struct mqtt_client client;
    uint8_t sendbuf[2048];
    uint8_t recvbuf[1024];
    mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback);

    /* Create an anonymous session */
    const char* client_id = NULL;
    /* Ensure we have a clean session */
    uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION;
    /* Send connection request to the broker. */
    mqtt_connect(&client, client_id, NULL, NULL, 0, NULL, NULL, connect_flags, 400);

    /* check that we don't have any errors */
    if (client.error != MQTT_OK) {
        qDebug() << "error:" << mqtt_error_str(client.error);
        //fprintf(stderr, "error: %s\n", mqtt_error_str(client.error));
    }

    // 订阅
    mqtt_subscribe(&client, TOPIC, 0);

    HANDLE refresh_thread = CreateThread(NULL, 0, client_refresher, &client, 0, NULL);
    if (refresh_thread == NULL) {
        qDebug() << "Failed to start client daemon thread.";
        mqtt_disconnect(&client);
        closesocket(sockfd);
        WSACleanup();
        return -1;
    }

    // 发布
    const char* _mockData = "CusData";
    mqtt_publish(&client, TOPIC, _mockData, strlen(_mockData), MQTT_PUBLISH_QOS_0);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty()) {
        qDebug() << "Failed to load QML.";
        return -1;
    }

    int result = app.exec();

    WaitForSingleObject(refresh_thread, INFINITE);
    CloseHandle(refresh_thread);
    mqtt_disconnect(&client);
    closesocket(sockfd);
    WSACleanup();

    return result;
}
三、编译报错

1、“close”: 找不到标识符报错
..\Qt-MQTT-C-Demo\mqtt-c\templates\posix_sockets.h(46): error C3861: “close”: 找不到标识符
原因是posix_sockets.h源码只适配了Linux,需要做Windows端的适配。

2、无法解析的外部符号 __imp_closesocket、无法解析的外部符号 __imp_socket 报错

原因:__imp_closesocket 等无法解析的外部符号,都是 Windows 网络 API(Winsock 库)中的函数。在 Windows 上,使用网络相关的功能时,通常需要链接 ws2_32.lib 库。

问题是由于在链接阶段没有包含 ws2_32.lib,这是 Winsock 库的静态链接库。

解决方案:确保项目正确地链接了 ws2_32.lib

在mcin.cpp使用到了 mqtt地方加上 #pragma comment(lib,"ws2_32.lib")

四、完整的MQTT发布与订阅Demo代码https://download.csdn.net/download/qq_38159549/89730327icon-default.png?t=O83Ahttps://download.csdn.net/download/qq_38159549/89730327

Demo基于MQTT-C examples下simple_publisher.c simple_subscriber.c例子修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2119943.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

android kotlin 基础复习 继承 inherit

1、新建文件kt 2、代码&#xff1a; /**用户基类**/ open class Person1(name:String){/**次级构造函数**/constructor(name:String,age:Int):this(name){//初始化println("-------基类次级构造函数---------")println("name:${name},age:${age}")} }/**子…

信息安全工程师(1)计算机网络分类

一、按分布范围分类 广域网&#xff08;WAN&#xff09;&#xff1a; 定义&#xff1a;广域网的任务是提供长距离通信&#xff0c;运送主机所发送的数据。其覆盖范围通常是直径为几十千米到几千千米的区域&#xff0c;因此也被称为远程网。特点&#xff1a;连接广域网的各个结点…

计算机毕业设计 财会信息管理系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

【吊打面试官系列-Redis面试题】怎么理解 Redis 事务?

大家好&#xff0c;我是锋哥。今天分享关于【怎么理解 Redis 事务&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 怎么理解 Redis 事务&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 1&#xff09;事务是一个单独的隔离操作&#xff1…

【LabVIEW学习篇 - 22】:ActiveX

文章目录 ActiveXActiveX打开Windows颜色选择对话框ActiveX将浏览器嵌入到前面板 ActiveX ActiveX是微软推出的一个开放的技术集的统称&#xff0c;它是很早之前出现的OLE(object linking and Embedding)技术的扩展&#xff0c;它是基于COM(Component Object Model)技术而建立…

meta元素

1&#xff0c;meta元素有4个全局属性 charset 设置文档的编码类型&#xff0c;通常设置为utf-8 <meta charset"utf-8" /> content 配合name或者http-equiv属性使用&#xff0c;为其value、 name 元数据名称(name的值)说明application name当前页所属Web应用系…

进程替换篇

文章目录 目录 前言 1.进程替换概念 2.进程替换的原理 3.进程替换的接口 4.接口功能验证 ①execl接口演示 ②execlp接口演示 ③execle接口演示 ④execv接口验证 5.尝试写一个自己的shell【了解】 前言 你一定见过类似于这样的“黑框框”&#xff0c;这个“黑框框”其实就是…

js 请求api + 解析数据 2个例子

起因&#xff0c; 目的: 补补 js 基础。 例1&#xff0c; 请求天气 api&#xff0c; 天气数据api js 中的 await await 关键字只能在 async 函数内部使用。函数内部可以使用 await&#xff0c;但是在函数外部直接使用 await 是不允许的。 async function fetchWeatherData…

[mysql]最基本的SELECT...FROM结构

第0种&#xff1a;最基本的查询语句 SELECT 字段名&#xff0c;字段名 FROM 表名 SELECT 1&#xff1b; SELECT 11,3*2&#xff1b; FROM SELECT 11,3*2 FROM DUAL&#xff1b;#dual&#xff1a;伪表 我们可以用它来保持一个平衡 这里我们的值不需要在任何一个表里&#xf…

MyBaits的初理解

一.Mybaits的简介 Mybaits就是对JDBC的简化&#xff0c;就是对持久化的实现。 二.基础 需要导的dependencies <dependencies><!-- mybatis依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId>&l…

第 5 章多视图几何

本章讲解如何处理多个视图&#xff0c;以及如何利用多个视图的几何关系来恢复照相机位置信息和三维结构。通过在不同视点拍摄的图像&#xff0c;我们可以利用特征匹配来计算出三维场景点以及照相机位置。本章会介绍一些基本的方法&#xff0c;展示一个三维重建的完整例子&#…

获取多行文本内容,去掉首尾空格、去掉空字符串,解析为文本数组

核心代码 // 获取多行文本内容&#xff0c;去掉首尾空格、去掉空字符串&#xff0c;解析为文本数组 getMultiLineTexts(textareaValue) {return textareaValue.split("\n").map((v) > v.split("\t").join("").trim()).filter((v, i, ar) &g…

Qt | ubuntu20.04安装Qt6.5.3并创建一个example完整教程(涉及诸多开发细节,商用慎重)

点击上方"蓝字"关注我们 01、下载 >>> 下载Qt在线安装包 这里采用镜像地址进行下载,避免网络过慢。 镜像地址:http://mirrors.ustc.edu.cn/qtproject/archive/online_installers/4.5/ 选择最新版本下载,如截至目前最新版本为qt-unified-linux-x64-4.5.2…

“探索数字孪生技术:细数其在各行业的实际应用场景“

数字孪生城市是指在数字世界中创建一个同物理实体城市外观一致、行动一致、思想一致的 数字虚拟城市&#xff0c;实现对现实世界的监测、诊断、回溯、预测和决策控制&#xff0c;用于实体城市的规划、建设、 治理和优化等全生命周期管理&#xff0c;提高城市运行效率和市民居住…

内网穿透的应用-Deepin系统安装x11vnc实现任意设备无公网IP远程连接Deepin桌面

文章目录 前言1. 安装x11vnc2. 本地远程连接测试3. Deepin安装Cpolar4. 配置公网远程地址5. 公网远程连接Deepin桌面6. 固定连接公网地址7. 固定公网地址连接测试 前言 本文主要介绍在Deepin系统中安装x11vnc工具&#xff0c;并结合Cpolar内网穿透工具实现任意设备无公网IP也可…

计算机毕业设计Pyhive+Spark招聘可视化 职位薪资预测 招聘推荐系统 招聘大数据 招聘爬虫 大数据毕业设计 Hadoop Scrapy

《SparkHive招聘推荐与预测系统》开题报告 一、引言 随着互联网技术的飞速发展&#xff0c;招聘行业积累了大量的数据&#xff0c;包括职位信息、应聘者信息、企业信息等。这些数据中蕴含着丰富的价值&#xff0c;能够帮助企业和求职者更好地匹配&#xff0c;提高招聘效率。然…

浮点数精度问题

为什么会产生精度问题&#xff1f; 我们带着这个问题去探寻浮点数二进制的存储原理 浮点数是怎么存在计算机中的&#xff1f; 浮点数在计算机中的表示通常遵循IEEE 754标准。其基本概念如下&#xff1a; 结构&#xff1a;浮点数由三部分组成&#xff1a; 符号位&#xff08;…

Android主副屏显示-Android13

Android主副屏显示-Android13 1、DisplayDeviceInfo屏幕信息2、LogicalDisplay.java2.1 configureDisplayLocked刷新 DisplayManagerService启动及主屏添加-Android13 1、DisplayDeviceInfo屏幕信息 DisplayManagerService启动及主屏添加-Android13 中监听获取&#xff0c;在L…

Vue3+ElementPlus 封装图片空间组件的门面

什么是图片空间? 图片空间就是专门管理我们上传图片的地方。就好比用户管理一样&#xff0c;我们对要上传的图片进行管理。 这样做的好处有哪些&#xff1f; 我们把可能需要的图片都上传到图片管理中。在其他需要图片的地方&#xff08;如&#xff1a;商品图片等&#xff09;可…

【MATLAB】FIR滤波器的MATLAB实现

FIR滤波器的MATLAB实现 FIR滤波器的设计fir1函数fir2函数 与IIR滤波器相比&#xff0c;FIR滤波器既有其优势也有其局限性。FIR滤波器的主要优点包括&#xff1a; 精确的线性相位响应&#xff1b;永远保持稳定性&#xff1b;设计方法通常是线性的&#xff1b;在硬件实现中具有更…