侧边栏壁纸
博主头像
xiaoming博主等级

累死自己,卷死别人,为了小刘而努力!!!

  • 累计撰写 24 篇文章
  • 累计创建 7 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Ubuntu 和 ARM 移植 Qt5Mqtt 库教程

Administrator
2024-06-04 / 0 评论 / 0 点赞 / 21 阅读 / 13663 字 / 正在检测是否收录...

1、 移植环境

开发板:正点原子 IMX6ULL 开发板

Ubuntu:20.04

Ubuntu Qt版本:5.12.9

Buildroot Qt5版本:5.15.8

2、 下载 Qt5Mqtt 库

Qt 开发 MQTT 程序有两种方式,一个是 Qt 官方提供的基于 MQTT 的封装,一个是第三方(EMQ)开发的用于 Qt 调用 MQTT 的接口,二者使用方法大同小异,并且均提供了源码。那么,这里介绍第一种,如基于 Qt 官方提供的封装来使用 MQTT。

Qt 官方虽然在 2017 年就已经提供了对 MQTT 的封装,但是并没有正式加入到 Qt 的标准库里面,所以需要自己下载源码进行编译。

Qt 官方介绍文档地址:https://doc.qt.io/QtMQTT/qtmqtt-index.html

Qt 官方在 github 上提供了源代码,地址:https://github.com/qt/qtmqtt

image-20240604204654399

这里我使用的 Ubuntu 中的 Qt 版本是 5.12.9 ,Buildroot Qt5 版本是 5.15.8 所以这里下载 5.15.2 版本的,尽量下载和自己使用的版本相同或者相近的,相差太大的可能会出问题。

3、 编译 Ubuntu 下的 Qt5Mqtt 库

将下载的文件复制到 Ubuntu 中,执行如下命令解压缩文件

sudo tar -vzxf qtmqtt-5.15.2.tar.gz    //解压所有的文件
sudo chmod 777 -R qtmqtt-5.15.2/       //赋予所有的文件执行权限

解压后的文件如下

image-20240604210514462

因为下载的下来的源码并不能直接的编译使用还需要修改一些代码,所有我们先使用 Ubuntu 下的 QT5 编译测试,测试完成之后再编译 arm 上面的 Qt5Mqtt 库。其实之所以这样是因为我没有找到相关的资料,只能先用编译 Ubuntu 下的 Qt5Mqtt 库测试,在测试成功之后再按照相应的移植方法去编译移植 arm 上面的 Qt5Mqtt 库。

使用 Ubuntu 下的 Qt5 打开 qtmqtt.pro ,打开之后选择 Release 模式,点击下面的小锤子进行编译

image-20240604211110275

3.1 错误解决方式

点击编译之后会报很多的错误,接下来我们就需要逐条的解决这些错误

  • 问题1

    • qmqttauthenticationproperties.h:33: error: C1083: 无法打开包括文件: “QtMqtt/qmqttglobal.h”: No such file or directory

      打开 qmqttauthenticationproperties.h 文件,发现有这么两句:

      #include <QtMqtt/qmqttglobal.h>
      #include <QtMqtt/qmqtttype.h>
      
    • 解决方式

      将源码下面的 /home/xiaoming/桌面/qtmqtt-5.15.2/src/mqtt 里面的所有文件复制到 Qt 的安装目录下面的 Gcc 编译器下面

      image-20240604211615891

      我的Qt安装在 opt/Qt5.12.9 下面,所以将mqtt文件夹复制到 /opt/Qt5.12.9/5.12.9/gcc_64/include 文件下面并改名为 QtMqtt ,再编译就不报这个错误了。

      image-20240604211955666

  • 问题2

    • qmqttconnection.cpp:169: error: C2039: “errorOccurred”: 不是“QAbstractSocket”的成员

      qmqttconnection.cpp 中 168行有这么一句:

      connect(socket, &QAbstractSocket::errorOccurred, this, &QMqttConnection::transportError);
      

      就是这句出了问题。查帮助文档或者源代码都可以发现 QAbstractSocket 没有 errorOccurred 这个 信号。有的那个信号叫:

      void error(QAbstractSocket::SocketError socketError)
      
    • 解决方式

      要改写成:

      connect(socket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)> (&QAbstractSocket::error), this, static_cast<void(QMqttConnection::*)(QAbstractSocket::SocketError)>(&QMqttConnection::transportError));
      
  • 问题3

    • 还有错误:

      qmqtttopicname.cpp:148: error: C2039: “KeepEmptyParts”: 不是“Qt”的成员
      

      qmqtttopicname.cpp 148 行代码是这样的:

      return d->name.split(QLatin1Char('/'), Qt::KeepEmptyParts);
      
    • 解决方式

      改写成:

      return d->name.split(QLatin1Char('/'), QString::KeepEmptyParts);
      
  • 问题4

    • 还有最后一个错误:

      qmqtttopicname.cpp:189: error: call to 'qHash' is ambiguous
      

      qmqtttopicname.cpp 189行是:

      return qHash(name.d->name, seed);
      

      类似的还有:

      return qHash(filter.d->filter, seed);
      
    • 解决方式

      改为:

      return qHash(static_cast<QString>(name.d->name), static_cast<uint>(seed));
      

      改为:

      return qHash(static_cast<QString>(filter.d->filter), static_cast<uint>(seed));
      

至此,编译就没什么问题了。

3.2 移植 Qt5Mqtt 库文件

在上面编译完成之后就可以将 Qt5Mqtt 库文件移植到编译器里面使用了。要使用它有两种方式,一种是直接在项目中导入外部库和头文件,还有一种是将其以模块的形式移植到 Qt 的安装目录,其中第二种的好处就是,只需要做一次操作,以后需要再用 Mqtt 库就可以直接调用了,不需要每次都导入外部库。这里我们直接将库以模块的形式移植到 Qt 里面方便后续的操作。

  • 查看编译后的文件

    这里移植我们需要使用的就是 /lib/mkspecs 两个文件夹,/lib文件夹里面主要是 Qt5Mqtt 库,/mkspecs 是要将 Qt5Mqtt 库作为 Qt 模块使用要用到的文件

    image-20240605131603964

  • 查看 /lib下面文件夹下面的内容可以看到和 Qt Gcc 编译器下面的 /lib 文件夹下面的内容是一样的,所以直接将编译后的 /lib 文件夹下的所有内容复制到 Qt Gcc 编译器下面的 /lib 文件夹下面就可以了。

    image-20240605171026799

    image-20240605171103345

    执行如下命令:

    sudo cp -r /home/xiaoming/桌面/build-qtmqtt-Desktop_Qt_5_12_9_GCC_64bit-Release/lib/*  /opt/Qt5.12.9/5.12.9/gcc_64/lib/
    
  • 再将编译后的 /mkspecs/modules-inst 文件夹下面的内容复制到 Qt Gcc 编译器下面的 /mkspecs/modules 下面,这样在引用模块的时候才可以找到,执行如下命令

    sudo cp -r /home/xiaoming/桌面/build-qtmqtt-Desktop_Qt_5_12_9_GCC_64bit-Release/mkspecs/modules-inst/* /opt/Qt5.12.9/5.12.9/gcc_64/mkspecs/modules
    

这样我们移植完成了,这种方式配置在新建工程中引用只需要引入模块就可以直接使用了:

QT += mqtt

包含头文件:

#include "QtMqtt/qmqttclient.h"

4、 测试 Ubuntu 下的 Qt5Mqtt 库

为了方便演示,我们直接使用 Qt Mqtt 源码中自带的示例来编译运行。

image-20240605134544428

使用 Ubuntu 下的 Qt 打开文件,修改一下头文件的引用,改为 #include "QtMqtt/qmqttclient.h" ,然后直接编译运行,就可以看到已经运行成功。

image-20240605134746537

我们来输入一个ip地址来测试一下,这里我已经在服务器上搭建了 EMQX ,没有的自行搭建或者使用例如阿里云之类的免费 MQTT 也是可以的,可以看已经能够正常运行,至此 Ubuntu 下的 Qt5Mqtt 库下的移植就完成了。

image-20240605135040432

5、 编译 ARM 下的 Qt5Mqtt 库

将下载的文件复制到 Ubuntu 中,执行如下命令解压缩文件

sudo tar -vzxf qtmqtt-5.15.2.tar.gz    //解压所有的文件
sudo chmod 777 -R qtmqtt-5.15.2/       //赋予所有的文件执行权限

解压后的文件如下

image-20240604210514462

因为下载的下来的源码并不能直接的编译使用还需要修改一些代码,所有我们先使用 Ubuntu 下的 QT5 编译测试,测试完成之后再编译 arm 上面的 Qt5Mqtt 库。其实之所以这样是因为我没有找到相关的资料,只能先用编译 Ubuntu 下的 Qt5Mqtt 库测试,在测试成功之后再按照相应的移植方法去编译移植 arm 上面的 Qt5Mqtt 库。

使用 Ubuntu 下的 Qt5 打开 qtmqtt.pro ,打开之后选择 Release 模式,点击下面的小锤子进行编译

image-20240604211110275

5.1 查找 Buildroot 的 Qt 编译器目录

因为我们使用的是 Buildroot 下面的 Qt 编译器,所以首先就需要先找到编译器的目录是在什么地方的,这个也很简单,我们使用命令行的方式编译文件,在输出的编译信息就能看到编译器所在的目录了。先切换到下载的 QtMqtt 源码目录下面执行如下指令

/home/linux/buildroot/buildroot-2022.02.3/output/host/usr/bin/qmake    //使用buildroot的qmake构建用于编译的makefile文件
make     //进行编译

image-20240605141434662

根据编译出来的调试信息可以看到编译所需的头文件在 /home/linux/buildroot/buildroot-2022.02.3/output/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/include 目录下面,我们需要将问题1中的 mqtt 文件下的所有文件复制到这个目录下面。

5.2 错误解决方式

在上面移植 Ubuntu 下的 Qt5Mqtt 库的时候我们已经对源码中的一些错误进行了修改,这里我们在编译 ARM 下的 Qt5Mqtt 库的时候就不需要进行修改了。如果不需要移植 Ubuntu 下的 Qt5Mqtt 库,可以直接看3.1的错误处理方式。唯一一点不同的是问题1下面的文件头文件复制问题,使用下面的方式。

  • 问题1

    • qmqttauthenticationproperties.h:33: error: C1083: 无法打开包括文件: “QtMqtt/qmqttglobal.h”: No such file or directory

      打开 qmqttauthenticationproperties.h 文件,发现有这么两句:

      #include <QtMqtt/qmqttglobal.h>
      #include <QtMqtt/qmqtttype.h>
      
    • 解决方式

      将源码下面的 /home/xiaoming/桌面/qtmqtt-5.15.2/src/mqtt 里面的所有文件复制到 Qt 的安装目录下面的 Gcc 编译器下面

      image-20240604211615891

      我的 Qt 安装在 opt/Qt5.12.9 下面,所以将 mqtt 文件夹复制到 /home/linux/buildroot/buildroot-2022.02.3/output/host/usr/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/include/qt5 文件下面并改名为 QtMqtt ,再编译就不报这个错误了。

      image-20240605142044596

5.3 命令行编译 Qt5Mqtt 库源文件

这里我们使用命令行的方式在编译 Qt 文件,当然也可以使用 Qt creator 里面编译,当然需要额外的设置编译器为 Buildroot 里面的。

先切换到下载的 QtMqtt 源码目录下面执行如下指令

/home/linux/buildroot/buildroot-2022.02.3/output/host/usr/bin/qmake    //使用buildroot的qmake构建用于编译的makefile文件
make     //进行编译

编译完成之后会报一个错误,这个不用管。

image-20240605143806792

查看源文件目录下面就得到了我们需要移植的文件了

image-20240605143950039

5.4 移植 Qt5Mqtt 库文件

在上面编译完成之后就可以将 Qt5Mqtt 库文件移植到编译器里面使用了。要使用它有两种方式,一种是直接在项目中导入外部库和头文件,还有一种是将其以模块的形式移植到 Qt 的安装目录,其中第二种的好处就是,只需要做一次操作,以后需要再用 Mqtt 库就可以直接调用了,不需要每次都导入外部库。这里我们直接将库以模块的形式移植到 Qt 里面方便后续的操作。

  • 查看编译后的文件

    这里移植我们需要使用的就是 /lib/mkspecs 两个文件夹,/lib文件夹里面主要是 Qt5Mqtt 库,/mkspecs 是要将 Qt5Mqtt 库作为 Qt 模块使用要用到的文件

    image-20240605143950039

  • 查看 /lib 下面文件夹下面的内容可以看到和 Buildroot 编译器下面的 /lib 文件夹下面的内容是一样的,所以直接将编译后的 /lib 文件夹下的所有内容复制到 Buildroot 编译器下面的 /lib 文件夹下面就可以了。

    image-20240605144139146

    image-20240605144204333

    执行如下命令:

    sudo cp -r /home/xiaoming/桌面/qtmqtt-5.15.2/lib*  /home/linux/buildroot/buildroot-2022.02.3/output/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/lib/
    
  • 再将编译后的 /mkspecs/modules-inst 文件夹下面的内容复制到 Buildroot 编译器下面的 /mkspecs/modules 下面,这样在引用模块的时候才可以找到,执行如下命令

    sudo cp -r /home/xiaoming/桌面/qtmqtt-5.15.2/mkspecs/modules-inst/* /home/linux/buildroot/buildroot-2022.02.3/output/host/mkspecs
    

这样我们移植完成了,这种方式配置在新建工程中引用只需要引入模块就可以直接使用了:

QT += mqtt

包含头文件:

#include "QtMqtt/qmqttclient.h"

6、 测试 ARM 下的 Qt5Mqtt 库

为了方便演示,我们直接使用 Qt Mqtt 源码中自带的示例来编译运行。

image-20240605134544428

使用 Ubuntu 下的 Qt 打开文件,修改一下头文件的引用,改为 #include "QtMqtt/qmqttclient.h" ,然后直接使用命令行进行编译,编译完成之后就可以看到编译成功后的文件。

image-20240605145144644

image-20240605145637627

编译完成之后就可以把文件复制到开发板的根文件系统下面了。

在进行运行测试之前还需要将 Qt5Mqtt 库文件也移植到开发板上面,将源码下面的所有 Qt5Mqtt 文件复制到开发板的 /lib 目录下面

image-20240605150348979

开发板上面的 /lib 目录下面的内容如下

image-20240605150601046

在开发板上执行 ./simpleclient 查看屏幕上就可以显示了

671b62a46f8ee6c5a5e54382006fb52

至此,我们移植ARM下的Qt5Mqtt就成功了。

0

评论区