赞
踩
目录
MQTT是一种基于发布/订阅模式的"轻量级"通讯协议。它最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
瑞芯微RK3568芯片是一款定位中高端的通用型SOC,主要面向物联网、NVR存储、工控平板、工业检测、云终端、车载中控等行业定制市场。本人移植MQTT到RK3568的目的是将飞凌的RK3568开发板作为一个物联网的终端,来实时采集相关数据(例如:温度等)。
本次移植的软硬件环境如下:
github官网下载qmqtt源码(地址GitHub - emqx/qmqtt: MQTT client for Qt)。
下载完成后, 解压qmqtt-master.zip到本地文件夹。
- forlinx@ubuntu:~/3568/mqtt$ sudo unzip qmqtt-master.zip
-
- forlinx@ubuntu:~/3568/mqtt/qmqtt-master$ ls
- CMakeLists.txt examples qmqtt.pri README.md tests
- edl-v10 LICENSE qmqtt.pro src
- 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。
- # qmqtt-master/src/mqtt/qmqtt.pro
-
- TARGET = QtQmqtt
- QT = core network
- qtHaveModule(websockets): QMQTT_WEBSOCKETS: QT += websockets
-
- DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
-
- # CONFIG += QMQTT_NO_SSL
-
- HEADERS += \
- $$PWD/qmqtt_global.h \
- $$PWD/qmqtt.h
-
- include(qmqtt.pri)
-
- HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
-
- load(qt_module)
-
- # Set the output directory of library files
- DESTDIR = $$MODULE_BASE_OUTDIR/../mqtt_lib
编译完成后,在mqtt_lib目录下生成库文件libQt5Qmqtt.so.1.0.2,详细查看如下:
- root@ubuntu:/home/forlinx/3568/mqtt/mqtt_lib# ls -all
- total 6540
- drwxr-xr-x 3 root root 4096 Mar 11 18:19 .
- drwx------ 4 root root 4096 Mar 11 18:26 ..
- -rw-r--r-- 1 root root 809 Mar 11 18:26 libQt5Qmqtt.la
- -rw-r--r-- 1 root root 1651 Mar 11 18:26 libQt5Qmqtt.prl
- lrwxrwxrwx 1 root root 20 Mar 11 18:19 libQt5Qmqtt.so -> libQt5Qmqtt.so.1.0.2
- lrwxrwxrwx 1 root root 20 Mar 11 18:19 libQt5Qmqtt.so.1 -> libQt5Qmqtt.so.1.0.2
- lrwxrwxrwx 1 root root 20 Mar 11 18:19 libQt5Qmqtt.so.1.0 -> libQt5Qmqtt.so.1.0.2
- -rwxr-xr-x 1 root root 285448 Mar 11 18:19 libQt5Qmqtt.so.1.0.2
- -rw-r--r-- 1 root root 6388344 Mar 11 18:19 libQt5Qmqtt.so.1.0.2.debug
- drwxr-xr-x 2 root root 4096 Mar 11 18:19 pkgconfig
复制Ubuntu18.04下交叉编译出的动态库libQt5Qmqtt.so.1.0.2,放到开发板/usr/lib目录下并对应的配置软链接。
- cd /usr/lib
- sudo ln -s libQt5Qmqtt.so.1.0.2 libQt5Qmqtt.so
- sudo ln -s libQt5Qmqtt.so.1.0.2 libQt5Qmqtt.so.1
- 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
创建一个Widget应用程序,其控件布局如下:
在mqtt_demo项目的pro文件中添加对网络模块的支持。
QT += network
库文件位于mqtt_lib下,mqtt头文件位于源码的src/mqtt目录下,浏览到对应的目录,即可。
演示工具的源码已上传到github,链接地址:GitHub - lingdan2008/mqtt_demo。
mqtt_demo.pro文件
- QT += core gui network
-
- greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
- CONFIG += c++11
-
- # The following define makes your compiler emit warnings if you use
- # any Qt feature that has been marked deprecated (the exact warnings
- # depend on your compiler). Please consult the documentation of the
- # deprecated API in order to know how to port your code away from it.
- DEFINES += QT_DEPRECATED_WARNINGS
-
- # You can also make your code fail to compile if it uses deprecated APIs.
- # In order to do so, uncomment the following line.
- # You can also select to disable deprecated APIs only up to a certain version of Qt.
- #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
- SOURCES += \
- main.cpp \
- widget.cpp
-
- HEADERS += \
- widget.h
-
- FORMS += \
- widget.ui
-
- # Default rules for deployment.
- qnx: target.path = /tmp/$${TARGET}/bin
- else: unix:!android: target.path = /opt/$${TARGET}/bin
- !isEmpty(target.path): INSTALLS += target
-
-
-
- unix:!macx: LIBS += -L$$PWD/../../mqtt_lib/ -lQt5Qmqtt
-
- INCLUDEPATH += $$PWD/../../qmqtt-master/src/mqtt
- DEPENDPATH += $$PWD/../../qmqtt-master/src/mqtt
widget.h文件
- #ifndef WIDGET_H
- #define WIDGET_H
-
- #include <QWidget>
-
- // add necessary includes here
- #include <qmqtt.h>
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class Widget; }
- QT_END_NAMESPACE
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
- public:
- Widget(QWidget *parent = nullptr);
- ~Widget();
-
- private slots:
- void on_pushButton_Connect_clicked();
-
- void on_pushButton_Subscribe_clicked();
-
- void on_pushButton_Publish_clicked();
-
-
- void slotConnectedMQTT();
-
- void slotDisconnectedMQTT();
-
- void slotSubscribedMQTT(QString sTopic, quint8 qos = 0);
-
- void slotReceivedMessageByMQTT(QMQTT::Message sMsg);
-
- private:
- Ui::Widget *ui;
-
- // the mqtt client pointer
- QMQTT::Client *m_pMQTT = nullptr;
- };
- #endif // WIDGET_H
widget.cpp文件
- #include "widget.h"
- #include "ui_widget.h"
-
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::Widget)
- {
- ui->setupUi(this);
-
- this->setWindowTitle(tr("MQTT Demo"));
-
- ui->pushButton_Connect->setEnabled(true);
- ui->pushButton_Publish->setEnabled(false);
- ui->pushButton_Subscribe->setEnabled(false);
- }
-
- Widget::~Widget()
- {
- delete ui;
- }
-
-
- void Widget::on_pushButton_Connect_clicked()
- {
- if(tr("Connect") == ui->pushButton_Connect->text().trimmed()) {
- ui->pushButton_Publish->setEnabled(true);
- ui->pushButton_Subscribe->setEnabled(true);
-
- ui->pushButton_Connect->setText(tr("Disconnect"));
-
- QString sHost = ui->lineEdit_Host->text().trimmed();
- int nPort = ui->lineEdit_Port->text().trimmed().toInt();
-
- // Create a QMQTT client
- if(nullptr == m_pMQTT) {
- m_pMQTT = new QMQTT::Client(QHostAddress(sHost), nPort);
- Q_ASSERT(m_pMQTT);
- }
-
- // Signal-slot initialization
- std::vector<bool> vecConnect;
-
- vecConnect.push_back(QObject::connect(m_pMQTT, SIGNAL(connected()), this, SLOT(slotConnectedMQTT())));
- vecConnect.push_back(QObject::connect(m_pMQTT, SIGNAL(disconnected()), this, SLOT(slotDisconnectedMQTT())));
- vecConnect.push_back(QObject::connect(m_pMQTT, SIGNAL(subscribed(QString, quint8)), this, SLOT(slotSubscribedMQTT(QString, quint8))));
- vecConnect.push_back(QObject::connect(m_pMQTT, SIGNAL(received(QMQTT::Message)), this, SLOT(slotReceivedMessageByMQTT(QMQTT::Message))));
-
- for(int i=0; i<(int)vecConnect.size(); i++) {
- Q_ASSERT(vecConnect.at(i));
- }
-
- // Connect to host
- m_pMQTT->setCleanSession(true);
- m_pMQTT->connectToHost();
- }
- else {
- ui->pushButton_Publish->setEnabled(false);
- ui->pushButton_Subscribe->setEnabled(false);
-
- ui->pushButton_Connect->setText(tr("Connect"));
- m_pMQTT->disconnectFromHost();
-
- delete m_pMQTT;
- m_pMQTT = nullptr;
- }
-
-
-
- }
-
- void Widget::on_pushButton_Subscribe_clicked()
- {
- // Subscribe a topic
- QString sTopic = ui->lineEdit_SubscribeTopic->text().trimmed();
- m_pMQTT->subscribe(sTopic, 1);
- }
-
- void Widget::on_pushButton_Publish_clicked()
- {
- // Publish a topic
- QMQTT::Message sMsg;
- QString sTopic = ui->lineEdit_PublishTopic->text().trimmed();
- QString sContent = ui->lineEdit_PublishContent->text().trimmed();
-
- sMsg.setTopic(sTopic);
- sMsg.setPayload(sContent.toLocal8Bit());
-
- m_pMQTT->publish(sMsg);
- }
-
- void Widget::slotConnectedMQTT()
- {
- ui->textBrowser_ReceivedMessage->append(tr("Connection succeeded"));
- }
-
- void Widget::slotDisconnectedMQTT()
- {
- ui->textBrowser_ReceivedMessage->append(tr("Connection disconnected"));
- }
-
- void Widget::slotSubscribedMQTT(QString sTopic,quint8 qos)
- {
- Q_UNUSED(sTopic);
- Q_UNUSED(qos);
-
- QString sMsg = "Subscribe Topic ";
- sMsg += ui->lineEdit_SubscribeTopic->text();
- sMsg += " Succeeded";
- ui->textBrowser_ReceivedMessage->append(sMsg);
- }
-
- void Widget::slotReceivedMessageByMQTT(QMQTT::Message sMsg)
- {
- QString sPayload = sMsg.payload();
- QString sMsgTotal = "Topic:";
-
- sMsgTotal += sMsg.topic();
- sMsgTotal += " Payload:";
- sMsgTotal += sPayload;
-
- ui->textBrowser_ReceivedMessage->append(sMsgTotal);
- }
使用3568 Kit交叉编译后得到mqtt_demo,并将其发布到开发板。
- cd /home/forlinx/work/example/mqtt
- sudo ./mqtt_dem
(1)搭建MQTT服务器,
启动MQTT服务器,可参阅我的博客linux下搭建MQTT服务。
(2)启动MQTT Dashboard
从Google Paly商店下载,安装到手机后,连接MQTT服务器后,即可在手机端监控开发板。
(3)连接网络
(4)运行demo
在demo上配置服务器IP、端口、订阅主题、发布主题和发布内容,执行连接、订阅和发布,演示效果如下图所示:
至此,云服务器、RK3568和手机端通过了联合测试,它们组成了一个小型的物联网智能监控系统,通过MQTT轻松的实现了物联网,很有成就感!已经深夜了,周末可以安心睡个好觉了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。