当前位置:   article > 正文

嵌入式开发之移植MQTT到RK3568_arm 移植 qt mqtt库

arm 移植 qt mqtt库

目录

前言

一、下载qmqtt源码

二、编译库文件

三、移植到RK3568

3.1 移植动态库libQt5Qmqtt

四、联机测试

4.1 制作demo

4.1.1 创建demo新项目

4.1.2 添加network模块支持

4.1.3 添加qmqtt外部库

4.1.4 功能实现

4.1.5 编译与发布

4.2 移植与测试

4.2.1 启动应用程序

4.2.2 联合测试

总结


前言

        MQTT是一种基于发布/订阅模式的"轻量级"通讯协议。它最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。

        瑞芯微RK3568芯片是一款定位中高端的通用型SOC,主要面向物联网、NVR存储、工控平板、工业检测、云终端、车载中控等行业定制市场。本人移植MQTT到RK3568的目的是将飞凌的RK3568开发板作为一个物联网的终端,来实时采集相关数据(例如:温度等)。

本次移植的软硬件环境如下:

  • 开发环境操作系统: Ubuntu 18.04 64位
  • 开发环境工具:Qt 5.14.2
  • 交叉工具链:aarch64-linux-gnu
  • 开发板芯片:飞凌 RK3568-C
  • 开发板内核:linux-4.1.19
  • 手机端工具:MQTT Dashboard

一、下载qmqtt源码

 github官网下载qmqtt源码(地址GitHub - emqx/qmqtt: MQTT client for Qt)。

下载完成后, 解压qmqtt-master.zip到本地文件夹。

  1. forlinx@ubuntu:~/3568/mqtt$ sudo unzip qmqtt-master.zip
  2. forlinx@ubuntu:~/3568/mqtt/qmqtt-master$ ls
  3. CMakeLists.txt examples qmqtt.pri README.md tests
  4. edl-v10 LICENSE qmqtt.pro src
  5. epl-v10 qmqtt-API.md qmqtt.qbs sync.profile

二、编译库文件

 启动Qt-5.14.2,打开qmqtt.pro,配置为rk3568交叉编译环境,编译为Release下的message库。

 修改qmqtt-master/src/mqtt/qmqtt.pro配置文件,设置设置库文件的输出目录为mqtt_lib。

  1. # qmqtt-master/src/mqtt/qmqtt.pro
  2. TARGET = QtQmqtt
  3. QT = core network
  4. qtHaveModule(websockets): QMQTT_WEBSOCKETS: QT += websockets
  5. DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
  6. # CONFIG += QMQTT_NO_SSL
  7. HEADERS += \
  8. $$PWD/qmqtt_global.h \
  9. $$PWD/qmqtt.h
  10. include(qmqtt.pri)
  11. HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
  12. load(qt_module)
  13. # Set the output directory of library files
  14. DESTDIR = $$MODULE_BASE_OUTDIR/../mqtt_lib

编译完成后,在mqtt_lib目录下生成库文件libQt5Qmqtt.so.1.0.2,详细查看如下:

  1. root@ubuntu:/home/forlinx/3568/mqtt/mqtt_lib# ls -all
  2. total 6540
  3. drwxr-xr-x 3 root root 4096 Mar 11 18:19 .
  4. drwx------ 4 root root 4096 Mar 11 18:26 ..
  5. -rw-r--r-- 1 root root 809 Mar 11 18:26 libQt5Qmqtt.la
  6. -rw-r--r-- 1 root root 1651 Mar 11 18:26 libQt5Qmqtt.prl
  7. lrwxrwxrwx 1 root root 20 Mar 11 18:19 libQt5Qmqtt.so -> libQt5Qmqtt.so.1.0.2
  8. lrwxrwxrwx 1 root root 20 Mar 11 18:19 libQt5Qmqtt.so.1 -> libQt5Qmqtt.so.1.0.2
  9. lrwxrwxrwx 1 root root 20 Mar 11 18:19 libQt5Qmqtt.so.1.0 -> libQt5Qmqtt.so.1.0.2
  10. -rwxr-xr-x 1 root root 285448 Mar 11 18:19 libQt5Qmqtt.so.1.0.2
  11. -rw-r--r-- 1 root root 6388344 Mar 11 18:19 libQt5Qmqtt.so.1.0.2.debug
  12. drwxr-xr-x 2 root root 4096 Mar 11 18:19 pkgconfig

三、移植到RK3568

3.1 移植动态库libQt5Qmqtt

复制Ubuntu18.04下交叉编译出的动态库libQt5Qmqtt.so.1.0.2,放到开发板/usr/lib目录下并对应的配置软链接。

  1. cd /usr/lib
  2. sudo ln -s libQt5Qmqtt.so.1.0.2 libQt5Qmqtt.so
  3. sudo ln -s libQt5Qmqtt.so.1.0.2 libQt5Qmqtt.so.1
  4. sudo ln -s libQt5Qmqtt.so.1.0.2 libQt5Qmqtt.so.1.0

若未正确配置软链接,则启动app客户端时会出现错误:

./mqtt_demo: error while loading shared libraries: libQt5Qmqtt.so.1: cannot open shared object file: No such file or directory

四、联机测试

4.1 制作demo

4.1.1 创建demo新项目

创建一个Widget应用程序,其控件布局如下:

4.1.2 添加network模块支持

在mqtt_demo项目的pro文件中添加对网络模块的支持。

QT += network

4.1.3 添加qmqtt外部库

库文件位于mqtt_lib下,mqtt头文件位于源码的src/mqtt目录下,浏览到对应的目录,即可。

 

4.1.4 功能实现

演示工具的源码已上传到github,链接地址:GitHub - lingdan2008/mqtt_demo

mqtt_demo.pro文件

  1. QT += core gui network
  2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
  3. CONFIG += c++11
  4. # The following define makes your compiler emit warnings if you use
  5. # any Qt feature that has been marked deprecated (the exact warnings
  6. # depend on your compiler). Please consult the documentation of the
  7. # deprecated API in order to know how to port your code away from it.
  8. DEFINES += QT_DEPRECATED_WARNINGS
  9. # You can also make your code fail to compile if it uses deprecated APIs.
  10. # In order to do so, uncomment the following line.
  11. # You can also select to disable deprecated APIs only up to a certain version of Qt.
  12. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
  13. SOURCES += \
  14. main.cpp \
  15. widget.cpp
  16. HEADERS += \
  17. widget.h
  18. FORMS += \
  19. widget.ui
  20. # Default rules for deployment.
  21. qnx: target.path = /tmp/$${TARGET}/bin
  22. else: unix:!android: target.path = /opt/$${TARGET}/bin
  23. !isEmpty(target.path): INSTALLS += target
  24. unix:!macx: LIBS += -L$$PWD/../../mqtt_lib/ -lQt5Qmqtt
  25. INCLUDEPATH += $$PWD/../../qmqtt-master/src/mqtt
  26. DEPENDPATH += $$PWD/../../qmqtt-master/src/mqtt

widget.h文件

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. // add necessary includes here
  5. #include <qmqtt.h>
  6. QT_BEGIN_NAMESPACE
  7. namespace Ui { class Widget; }
  8. QT_END_NAMESPACE
  9. class Widget : public QWidget
  10. {
  11. Q_OBJECT
  12. public:
  13. Widget(QWidget *parent = nullptr);
  14. ~Widget();
  15. private slots:
  16. void on_pushButton_Connect_clicked();
  17. void on_pushButton_Subscribe_clicked();
  18. void on_pushButton_Publish_clicked();
  19. void slotConnectedMQTT();
  20. void slotDisconnectedMQTT();
  21. void slotSubscribedMQTT(QString sTopic, quint8 qos = 0);
  22. void slotReceivedMessageByMQTT(QMQTT::Message sMsg);
  23. private:
  24. Ui::Widget *ui;
  25. // the mqtt client pointer
  26. QMQTT::Client *m_pMQTT = nullptr;
  27. };
  28. #endif // WIDGET_H

 widget.cpp文件

  1. #include "widget.h"
  2. #include "ui_widget.h"
  3. Widget::Widget(QWidget *parent)
  4. : QWidget(parent)
  5. , ui(new Ui::Widget)
  6. {
  7. ui->setupUi(this);
  8. this->setWindowTitle(tr("MQTT Demo"));
  9. ui->pushButton_Connect->setEnabled(true);
  10. ui->pushButton_Publish->setEnabled(false);
  11. ui->pushButton_Subscribe->setEnabled(false);
  12. }
  13. Widget::~Widget()
  14. {
  15. delete ui;
  16. }
  17. void Widget::on_pushButton_Connect_clicked()
  18. {
  19. if(tr("Connect") == ui->pushButton_Connect->text().trimmed()) {
  20. ui->pushButton_Publish->setEnabled(true);
  21. ui->pushButton_Subscribe->setEnabled(true);
  22. ui->pushButton_Connect->setText(tr("Disconnect"));
  23. QString sHost = ui->lineEdit_Host->text().trimmed();
  24. int nPort = ui->lineEdit_Port->text().trimmed().toInt();
  25. // Create a QMQTT client
  26. if(nullptr == m_pMQTT) {
  27. m_pMQTT = new QMQTT::Client(QHostAddress(sHost), nPort);
  28. Q_ASSERT(m_pMQTT);
  29. }
  30. // Signal-slot initialization
  31. std::vector<bool> vecConnect;
  32. vecConnect.push_back(QObject::connect(m_pMQTT, SIGNAL(connected()), this, SLOT(slotConnectedMQTT())));
  33. vecConnect.push_back(QObject::connect(m_pMQTT, SIGNAL(disconnected()), this, SLOT(slotDisconnectedMQTT())));
  34. vecConnect.push_back(QObject::connect(m_pMQTT, SIGNAL(subscribed(QString, quint8)), this, SLOT(slotSubscribedMQTT(QString, quint8))));
  35. vecConnect.push_back(QObject::connect(m_pMQTT, SIGNAL(received(QMQTT::Message)), this, SLOT(slotReceivedMessageByMQTT(QMQTT::Message))));
  36. for(int i=0; i<(int)vecConnect.size(); i++) {
  37. Q_ASSERT(vecConnect.at(i));
  38. }
  39. // Connect to host
  40. m_pMQTT->setCleanSession(true);
  41. m_pMQTT->connectToHost();
  42. }
  43. else {
  44. ui->pushButton_Publish->setEnabled(false);
  45. ui->pushButton_Subscribe->setEnabled(false);
  46. ui->pushButton_Connect->setText(tr("Connect"));
  47. m_pMQTT->disconnectFromHost();
  48. delete m_pMQTT;
  49. m_pMQTT = nullptr;
  50. }
  51. }
  52. void Widget::on_pushButton_Subscribe_clicked()
  53. {
  54. // Subscribe a topic
  55. QString sTopic = ui->lineEdit_SubscribeTopic->text().trimmed();
  56. m_pMQTT->subscribe(sTopic, 1);
  57. }
  58. void Widget::on_pushButton_Publish_clicked()
  59. {
  60. // Publish a topic
  61. QMQTT::Message sMsg;
  62. QString sTopic = ui->lineEdit_PublishTopic->text().trimmed();
  63. QString sContent = ui->lineEdit_PublishContent->text().trimmed();
  64. sMsg.setTopic(sTopic);
  65. sMsg.setPayload(sContent.toLocal8Bit());
  66. m_pMQTT->publish(sMsg);
  67. }
  68. void Widget::slotConnectedMQTT()
  69. {
  70. ui->textBrowser_ReceivedMessage->append(tr("Connection succeeded"));
  71. }
  72. void Widget::slotDisconnectedMQTT()
  73. {
  74. ui->textBrowser_ReceivedMessage->append(tr("Connection disconnected"));
  75. }
  76. void Widget::slotSubscribedMQTT(QString sTopic,quint8 qos)
  77. {
  78. Q_UNUSED(sTopic);
  79. Q_UNUSED(qos);
  80. QString sMsg = "Subscribe Topic ";
  81. sMsg += ui->lineEdit_SubscribeTopic->text();
  82. sMsg += " Succeeded";
  83. ui->textBrowser_ReceivedMessage->append(sMsg);
  84. }
  85. void Widget::slotReceivedMessageByMQTT(QMQTT::Message sMsg)
  86. {
  87. QString sPayload = sMsg.payload();
  88. QString sMsgTotal = "Topic:";
  89. sMsgTotal += sMsg.topic();
  90. sMsgTotal += " Payload:";
  91. sMsgTotal += sPayload;
  92. ui->textBrowser_ReceivedMessage->append(sMsgTotal);
  93. }

4.1.5 编译与发布

使用3568 Kit交叉编译后得到mqtt_demo,并将其发布到开发板。

4.2 移植与测试

4.2.1 启动应用程序

  1. cd /home/forlinx/work/example/mqtt
  2. sudo ./mqtt_dem

 

4.2.2 联合测试

(1)搭建MQTT服务器,

        启动MQTT服务器,可参阅我的博客linux下搭建MQTT服务

(2)启动MQTT Dashboard

        从Google Paly商店下载,安装到手机后,连接MQTT服务器后,即可在手机端监控开发板。

(3)连接网络

(4)运行demo

        在demo上配置服务器IP、端口、订阅主题、发布主题和发布内容,执行连接、订阅和发布,演示效果如下图所示:

 


总结

至此,云服务器、RK3568和手机端通过了联合测试,它们组成了一个小型的物联网智能监控系统,通过MQTT轻松的实现了物联网,很有成就感!已经深夜了,周末可以安心睡个好觉了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/876892
推荐阅读
相关标签
  

闽ICP备14008679号