嵌入式开发之移植MQTT到RK3568
文章目录
前言
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到本地文件夹。
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
- 1
- 2
- 3
- 4
- 5
- 6
二、编译库文件
启动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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
编译完成后,在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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
三、移植到RK3568
3.1 移植动态库libQt5Qmqtt
复制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
- 1
- 2
- 3
- 4
若未正确配置软链接,则启动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文件
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
4.1.5 编译与发布
使用3568 Kit交叉编译后得到mqtt_demo,并将其发布到开发板。
4.2 移植与测试
4.2.1 启动应用程序
cd /home/forlinx/work/example/mqtt
sudo ./mqtt_dem
- 1
- 2
4.2.2 联合测试
(1)搭建MQTT服务器,
启动MQTT服务器,可参阅我的博客linux下搭建MQTT服务。
(2)启动MQTT Dashboard
从Google Paly商店下载,安装到手机后,连接MQTT服务器后,即可在手机端监控开发板。
(3)连接网络
(4)运行demo
在demo上配置服务器IP、端口、订阅主题、发布主题和发布内容,执行连接、订阅和发布,演示效果如下图所示:
总结
至此,云服务器、RK3568和手机端通过了联合测试,它们组成了一个小型的物联网智能监控系统,通过MQTT轻松的实现了物联网,很有成就感!
- 分享
- 举报

-
浏览量:9123次2019-09-01 11:08:57
-
浏览量:6113次2021-12-10 15:40:21
-
浏览量:1772次2020-08-19 16:43:27
-
浏览量:2570次2020-08-20 17:57:43
-
浏览量:2556次2020-08-19 16:46:46
-
浏览量:4020次2020-07-17 16:50:14
-
浏览量:2408次2020-08-17 18:01:42
-
浏览量:2189次2020-08-17 18:04:26
-
浏览量:2193次2020-08-17 18:06:38
-
浏览量:2121次2020-08-19 16:45:18
-
浏览量:3437次2020-08-17 18:05:11
-
浏览量:2099次2020-08-20 18:01:22
-
浏览量:2505次2020-08-20 18:03:14
-
浏览量:2291次2020-08-19 16:49:12
-
浏览量:1060次2023-12-25 15:42:30
-
浏览量:934次2023-10-23 16:21:43
-
浏览量:3742次2024-03-18 14:27:20
-
浏览量:3923次2020-08-19 16:34:45
-
浏览量:2028次2020-08-17 18:03:03
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖

thatk






举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明