MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。找了很久资料,在arm中可以运行的QT比较少,结合在linux的上的一些例子,经过两天的调试,把整个QT mqtt调试出来了,这里记录下来,分享给有需要的人。
下载qmqtt源码
1、很多介绍去https://github.com/emqx/qmqtt
下载,但是我就是打不开这个网址。后面找到其的地方下载了了源码
我这里把他上传上来:*附件:qmqtt-master.zip
2、把这个源代码下载到ubuntu虚拟机中(需要安装好飞凌源码编译的机子里)并解压出来:
目录如下:
├── CMakeLists.txt
├── edl-v10
├── epl-v10
├── examples
│ ├── examples.pro
│ ├── examples.qbs
│ └── qmqtt
│ ├── client
│ │ ├── client.pro
│ │ ├── client.qbs
│ │ └── example.cpp
│ ├── qmqtt.pro
│ └── qmqtt.qbs
├── LICENSE
├── qmqtt-API.md
├── qmqtt.pri
├── qmqtt.pro
├── qmqtt.qbs
├── README.md
├── src
│ ├── mqtt
│ │ ├── qmqtt_client.cpp
│ │ ├── qmqtt_client.h
│ │ ├── qmqtt_client_p.cpp
│ │ ├── qmqtt_client_p.h
│ │ ├── qmqtt_frame.cpp
│ │ ├── qmqtt_frame.h
│ │ ├── qmqtt_global.h
│ │ ├── qmqtt.h
│ │ ├── qmqtt_message.cpp
│ │ ├── qmqtt_message.h
│ │ ├── qmqtt_message_p.h
│ │ ├── qmqtt_network.cpp
│ │ ├── qmqtt_networkinterface.h
│ │ ├── qmqtt_network_p.h
│ │ ├── qmqtt.pri
│ │ ├── qmqtt.pro
│ │ ├── qmqtt.qbs
│ │ ├── qmqtt_routedmessage.h
│ │ ├── qmqtt_router.cpp
│ │ ├── qmqtt_router.h
│ │ ├── qmqtt_routesubscription.cpp
│ │ ├── qmqtt_routesubscription.h
│ │ ├── qmqtt_socket.cpp
│ │ ├── qmqtt_socketinterface.h
│ │ ├── qmqtt_socket_p.h
│ │ ├── qmqtt_ssl_socket.cpp
│ │ ├── qmqtt_ssl_socket_p.h
│ │ ├── qmqtt_timer.cpp
│ │ ├── qmqtt_timerinterface.h
│ │ ├── qmqtt_timer_p.h
│ │ ├── qmqtt_websocket.cpp
│ │ ├── qmqtt_websocketiodevice.cpp
│ │ ├── qmqtt_websocketiodevice_p.h
│ │ └── qmqtt_websocket_p.h
│ ├── src.pro
│ └── src.qbs
├── sync.profile
用原先安装的的QT打开目录下的qmqtt.pro工程
![image.png](//file.elecfans.com/web2/M00/81/BC/pYYBAGOQg1KAabgJAAPtsfMY0bM742.png)
![image.png](//file.elecfans.com/web2/M00/81/BD/pYYBAGOQg7-AE669AATz-olMqDk010.png)
![image.png](//file.elecfans.com/web2/M00/81/33/poYBAGOQhAeAVsA0AAetLtDQut0781.png)
在打开的项目中,先右键qmakeSRC项目,再右键构建SRC项目
![image.png](//file.elecfans.com/web2/M00/81/BD/pYYBAGOQhJiAFFr3AAZE1nU5qR8209.png)
显示如下就是构建成功了:
![image.png](//file.elecfans.com/web2/M00/81/BE/pYYBAGOQhSyAB2kdAANt6fWCDB4252.png)
创建lib文件夹
在其他的目录中创建lib文件夹用于存入编译出来的文件,以备后用。
编译好后,会在mqtt_build目录下生成一个build输出文件夹:
![image.png](//file.elecfans.com/web2/M00/81/BE/pYYBAGOQhbuAQjNPAAKtMwF1Flo215.png)
1、把lib下面生成的lib文件复制到新建的文件中。
![image.png](//file.elecfans.com/web2/M00/81/BE/pYYBAGOQhsSAX7SqAAE3YftDCVQ441.png)
2、然后把原来解压出来的目录里的mqtt文件夹里拷到与lib同目录里来备用:
![image.png](//file.elecfans.com/web2/M00/81/34/poYBAGOQh6KAA1kYAAL0uRKloLU146.png)
这样源码编译到这里就结束了。
把lib下面的文件拷到开发板的/lib/下面:
![image.png](//file.elecfans.com/web2/M00/81/35/poYBAGOQiBiAdLnEAAL8H5zve5g343.png)
要不估生成的代码到开发板下面运行时,会提示头文件找不到。
虚拟机创建QT项目:
新建项目大家可以自行去创建,这里不详细说。
1、添加好新建工程后把原来准备的lib、mqtt两个文件拷到项目目录里面:
![image.png](//file.elecfans.com/web2/M00/81/BF/pYYBAGOQiTSAF9JNAAP6AkaAYwg153.png)
2、在.pro文件里面右键,选择库:
![image.png](//file.elecfans.com/web2/M00/81/35/poYBAGOQiVeABaVAAAp1f1zg9po003.png)
3、选择外部库
![image.png](//file.elecfans.com/web2/M00/81/35/poYBAGOQiY6AeKyQAAJZB3MP6II755.png)
![image.png](//file.elecfans.com/web2/M00/81/35/poYBAGOQid2AF_UEAALWTiaCX0g127.png)
找到lib下面的库
![image.png](//file.elecfans.com/web2/M00/81/BF/pYYBAGOQifuAYuJyAAFEpui0eUI655.png)
再选择头文件路径:
![image.png](//file.elecfans.com/web2/M00/81/35/poYBAGOQiiqARLQ5AAH74gx8_xI014.png)
![image.png](//file.elecfans.com/web2/M00/81/35/poYBAGOQikuAZgfyAAJvBk6tgA4947.png)
钩选linux然后下一步
![image.png](//file.elecfans.com/web2/M00/81/35/poYBAGOQinSALQgDAAE7Zssj4Hw512.png)
点击完成,会自动添加代码:
![image.png](//file.elecfans.com/web2/M00/81/35/poYBAGOQiqOAArl3AAHgVLzWKXQ511.png)
到此QT项目创建就完成了,下面进行界面设计
界面
![image.png](//file.elecfans.com/web2/M00/81/BF/pYYBAGOQivKADXKfAAFibxgZNU8564.png)
代码
mqtt_pro.pro:
QT += core gui widgets network
TARGET = mqtt_pro
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
CONFIG += c++11
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
unix:!macx: LIBS += -L$$PWD/../test/mqtt_pro/lib/ -lQt5Qmqtt
INCLUDEPATH += $$PWD/../test/mqtt_pro/mqtt
DEPENDPATH += $$PWD/../test/mqtt_pro/mqtt
unix:!macx: LIBS += -L$$PWD/lib/ -lQt5Qmqtt
INCLUDEPATH += $$PWD/mqtt
DEPENDPATH += $$PWD/mqtt
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "qmqtt.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_connectBt_clicked();
void on_pubBt_clicked();
void mqtt_connect_success();
void mqtt_disconnect();
void mqtt_sub_success(QString topic, quint8 qos = 0);
void mqtt_recv_msg(QMQTT::Message msg);
void on_subBt_clicked();
private:
Ui::MainWindow *ui;
QMQTT::Client *mqtt;
};
#endif
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_connectBt_clicked()
{
mqtt = new QMQTT::Client(QHostAddress(QString(ui->hostLe->text())),ui->portLe->text().toInt());
connect(mqtt, SIGNAL(connected()), this, SLOT(mqtt_connect_success()));
connect(mqtt, SIGNAL(disconnected()), this, SLOT(mqtt_disconnect()));
connect(mqtt, SIGNAL(subscribed(QString,quint8)), this, SLOT(mqtt_sub_success(QString,quint8)));
connect(mqtt, SIGNAL(received(QMQTT::Message)), this, SLOT(mqtt_recv_msg(QMQTT::Message)));
mqtt->setClientId("Qt-test0x10");
mqtt->setUsername("admin1");
mqtt->setPassword("public1");
mqtt->setCleanSession(true);
mqtt->connectToHost();
}
void MainWindow::mqtt_connect_success()
{
ui->textBrowser->append(QObject::tr("连接成功"));
}
void MainWindow::mqtt_disconnect()
{
ui->textBrowser->append("连接断开");
}
void MainWindow::mqtt_sub_success(QString topic,quint8 qos)
{
QString msg = "订阅主题 ";
msg += ui->subthemeLe->text();
msg += " 成功";
ui->textBrowser->append(msg);
}
void MainWindow::mqtt_recv_msg(QMQTT::Message msg)
{
QString recv_msg = "Topic:";
QString data = msg.payload();
recv_msg += msg.topic();
recv_msg += " Payload:";
recv_msg += data;
ui->textBrowser->append(recv_msg);
}
void MainWindow::on_pubBt_clicked()
{
QMQTT::Message msg;
msg.setTopic(ui->pubthemeLe->text());
msg.setPayload(ui->pubMsgLe->text().toLocal8Bit());
mqtt->publish(msg);
}
void MainWindow::on_subBt_clicked()
{
mqtt->subscribe(ui->subthemeLe->text(),1);
}
mainwindow.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1103</width>
<height>822</height>
</rect>
</property>
<property name="windowTitle">
<string>飞凌OK3568MQTT</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>60</x>
<y>70</y>
<width>129</width>
<height>34</height>
</rect>
</property>
<property name="text">
<string>主机:</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>490</x>
<y>70</y>
<width>129</width>
<height>34</height>
</rect>
</property>
<property name="text">
<string>端口:</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>10</x>
<y>150</y>
<width>129</width>
<height>34</height>
</rect>
</property>
<property name="text">
<string>发布主题:</string>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>440</x>
<y>150</y>
<width>129</width>
<height>34</height>
</rect>
</property>
<property name="text">
<string>订阅主题:</string>
</property>
</widget>
<widget class="QLineEdit" name="hostLe">
<property name="geometry">
<rect>
<x>150</x>
<y>60</y>
<width>261</width>
<height>42</height>
</rect>
</property>
<property name="text">
<string>192.168.3.192</string>
</property>
</widget>
<widget class="QLineEdit" name="pubthemeLe">
<property name="geometry">
<rect>
<x>150</x>
<y>150</y>
<width>261</width>
<height>42</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="portLe">
<property name="geometry">
<rect>
<x>570</x>
<y>60</y>
<width>261</width>
<height>42</height>
</rect>
</property>
<property name="text">
<string>1883</string>
</property>
</widget>
<widget class="QLineEdit" name="subthemeLe">
<property name="geometry">
<rect>
<x>570</x>
<y>140</y>
<width>261</width>
<height>42</height>
</rect>
</property>
</widget>
<widget class="QTextBrowser" name="textBrowser">
<property name="geometry">
<rect>
<x>70</x>
<y>270</y>
<width>941</width>
<height>341</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="connectBt">
<property name="geometry">
<rect>
<x>860</x>
<y>50</y>
<width>170</width>
<height>48</height>
</rect>
</property>
<property name="text">
<string>连接</string>
</property>
</widget>
<widget class="QPushButton" name="subBt">
<property name="geometry">
<rect>
<x>860</x>
<y>130</y>
<width>170</width>
<height>48</height>
</rect>
</property>
<property name="text">
<string>订阅</string>
</property>
</widget>
<widget class="QPushButton" name="pubBt">
<property name="geometry">
<rect>
<x>860</x>
<y>210</y>
<width>170</width>
<height>48</height>
</rect>
</property>
<property name="text">
<string>发布</string>
</property>
</widget>
<widget class="QLineEdit" name="pubMsgLe">
<property name="geometry">
<rect>
<x>120</x>
<y>210</y>
<width>661</width>
<height>42</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_5">
<property name="geometry">
<rect>
<x>290</x>
<y>630</y>
<width>451</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string>电子发烧友 OK3568试用</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1103</width>
<height>48</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
编译
点击构建项目,就可以在目录下面生成mqtt_pro文件,把这个文件拷到开发板。
![image.png](//file.elecfans.com/web2/M00/81/35/poYBAGOQi_2AY9HrAAIKBXZFZ5c289.png)
![image.png](//file.elecfans.com/web2/M00/81/BF/pYYBAGOQjFOAayWrAAF5GKXE3Uw667.png)
运行后显示界面如下:
![574aba4513e360641aa71d7b2e61ad1.jpg](//file.elecfans.com/web2/M00/81/BF/pYYBAGOQjI-AelfHAAKnKQH03Pg414.jpg)
#创建测试服务器:
1、下载emqtx服务器,或者用期的也可以创建mqtt服务端。
下载 EMQX下载后解压,执行./bin/emqx start就可以了。
打开127.0.0.1:18083(或者本机地址:18083就可以进入管理端,第一次进管理端用户名是admin 密码为:public。
2、查看接入情况:打开subscriptions菜单可以看到客户端接入情况:
![image.png](//file.elecfans.com/web2/M00/81/36/poYBAGOQjnuANV9UAAJKVcnltgM429.png)
3、按装一个MQTTx调试助手,建立一个连接:
![image.png](//file.elecfans.com/web2/M00/81/BF/pYYBAGOQjvCALmylAALvsGXdwDc233.png)
![image.png](//file.elecfans.com/web2/M00/81/C0/pYYBAGOQj2WAL9LjAALR7yP_DDA359.png)
![image.png](//file.elecfans.com/web2/M00/81/C0/pYYBAGOQj5OAY2eGAADmshdREu4556.png)
![image.png](//file.elecfans.com/web2/M00/81/C0/pYYBAGOQj66AKH50AAKstcqrTAE352.png)
建立订阅主题、发送主题 :
![image.png](//file.elecfans.com/web2/M00/81/36/poYBAGOQj-6AKz_9AAHlqqQGfd8620.png)
3、QT界面也按指示填写相应的服务器IP、订阅、发送主题 发布内容。然后点击连,如果连接成功就可以发送与接收数据了,同时也在MQTT调试助手上看到内容:
![image.png](//file.elecfans.com/web2/M00/81/C0/pYYBAGOQkNeAIB4WAAFoV-ZpQoY551.png)
![image.png](//file.elecfans.com/web2/M00/81/36/poYBAGOQkOqAB_0fAAF7ZyBu_fs303.png)
![image.png](//file.elecfans.com/web2/M00/81/C0/pYYBAGOQkQmAA7evAANNT9QJrp4024.png)
![image.png](//file.elecfans.com/web2/M00/81/C0/pYYBAGOQkRmAbMqMAAIkMhpbyX4371.png)
![4d12950c18b7f9f86f927008c195cff.jpg](//file.elecfans.com/web2/M00/81/C0/pYYBAGOQkUOAfTu8AAJ59ZDRD7s970.jpg)
到此,QT上的mqtt就调试完了。
工程我放附件:
*附件:mqtt_pro.zip