Qt5.8.0編譯QtMqtt庫並使用該庫連接有人云的例子

一 編譯QtMqtt庫

Qt5.10才官方支持MQTT,但我用的Qt版本是5.8.0 Mingw_32BIT, 爲了在Qt5.8.0上添加MQTT支持,需要自己編譯源碼

步驟:

(1) git clone https://github.com/qt/qtmqtt.git

(2) 使用Qt5.8.0自帶的qtcreator打開qtmqtt的pro文件,然後切換到release模式編譯

(3) 編譯結束後會在工程生成的文件下生成如下一些文件

二 連接有人云

(1)首先按照有人云官方的教程添加一個透傳設備,我添加的是“默認設備”(也可以是NBIOT等支持透傳的設備),設備的ID爲:00021153000000000001

(2)然後將這個設備使用有人虛擬串口軟件映射爲本地的虛擬串口,如下圖所示

(3)創建Qt工程,主要代碼如下:

#-------------------------------------------------
#
# Project created by QtCreator 2018-12-27T18:02:41
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = MQTTest
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as 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 you use 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

LIBS += -LE:/EWorkSpace/20190109_mqtt/build-qtmqtt-Qt580_MINGW_32BIT-Release/bin -lQt5Mqtt

INCLUDEPATH += E:/EWorkSpace/20190109_mqtt/build-qtmqtt-Qt580_MINGW_32BIT-Release/include


SOURCES += main.cpp \
    mainwidget.cpp \
    mqttclient.cpp

HEADERS  += \
    mainwidget.h \
    mqttclient.h

FORMS    += \
    mainwidget.ui
#ifndef MQTTCLIENT_H
#define MQTTCLIENT_H

#include <QObject>
#include <QtMqtt/QMqttClient>
#include <QtMqtt/QMqttSubscription>

typedef QMqttSubscription::SubscriptionState SubscriptionState;

class MQTTClient : public QObject
{
    Q_OBJECT
public:
    explicit MQTTClient(const QString &userName, const QString &passwordMD5, const QString &deviceId, QObject *parent = nullptr);
    ~MQTTClient();

    bool isOpened();
    void open();
    void close();
    void write(const QByteArray &data);

private:
    QString m_userName;
    QString m_passwordMD5;
    QString m_deviceId;
    QMqttClient *m_client;
    QByteArray m_buffer;

private slots:
    void doConnected();
    void doDisconnected();
    void doMessageReceived(const QByteArray &message, const QMqttTopicName &topic);
    void doQMqttSubscriptionStateChanged(SubscriptionState subscriptionState);

signals:
    void log(const QString &text);

public slots:
};

#endif // MQTTCLIENT_H
#include "mqttclient.h"
#include <QDebug>

#define MQTT_HOSTNAME   "clouddata.usr.cn"
#define MQTT_PORT       1883

#define MQTT_CLIENT_SUBSCRIBE_PREFIX    "$USR/DevTx"
#define MQTT_CLIENT_PUBLISH_PREFIX      "$USR/DevRx"

MQTTClient::MQTTClient(const QString &userName, const QString &passwordMD5, const QString &deviceId, QObject *parent) : QObject(parent)
{
    m_client=NULL;
    this->m_userName=userName;
    this->m_passwordMD5=passwordMD5;
    this->m_deviceId=deviceId;
}

MQTTClient::~MQTTClient()
{
    if(m_client!=NULL)
    {
        if(m_client->state()==QMqttClient::Connected)
        {
            m_client->disconnectFromHost();
        }
        delete m_client;
        m_client=NULL;
    }
}

bool MQTTClient::isOpened()
{
    if(m_client==NULL)
    {
        return false;
    }
    else if(m_client->state()==QMqttClient::Connected)
    {
        return true;
    }
    else
    {
        return false;
    }
}

void MQTTClient::open()
{
    if(m_client!=NULL)
    {
        return;
    }
    m_client = new QMqttClient(this);
    m_client->setHostname(MQTT_HOSTNAME);
    m_client->setPort(MQTT_PORT);
    m_client->setUsername(m_userName);
    m_client->setClientId(QString("APP:%1").arg(m_userName));
    m_client->setPassword(m_passwordMD5);
    m_client->setProtocolVersion(QMqttClient::MQTT_3_1_1);

    connect(m_client, SIGNAL(connected()), this, SLOT(doConnected()));
    connect(m_client, SIGNAL(disconnected()), this, SLOT(doDisconnected()));
    connect(m_client, SIGNAL(messageReceived(QByteArray,QMqttTopicName)), this, SLOT(doMessageReceived(QByteArray,QMqttTopicName)));

    m_client->connectToHost();
    emit log("MQTTClient 正在連接...");
}

void MQTTClient::close()
{
    if(m_client!=NULL)
    {
        if(m_client->state()==QMqttClient::Connected)
        {
            m_client->disconnectFromHost();
        }
        delete m_client;
        m_client=NULL;
    }
}

void MQTTClient::write(const QByteArray &data)
{
    if(m_client!=NULL)
    {
        m_client->publish(QString("%1/%2").arg(MQTT_CLIENT_PUBLISH_PREFIX).arg(this->m_deviceId), data);
        emit log(QString("MQTTClient 正發佈設備消息,設備ID: %1, 消息:%2").arg(this->m_deviceId).arg(QString::fromLatin1(data)));
    }
}

void MQTTClient::doConnected()
{
    emit log("MQTTClient 已建立連接!");
    emit log(QString("MQTTClient 正訂閱設備消息,設備ID: %1").arg(this->m_deviceId));
    QMqttSubscription *subscription=m_client->subscribe(QString("%1/%2").arg(MQTT_CLIENT_SUBSCRIBE_PREFIX).arg(this->m_deviceId));
    connect(subscription, SIGNAL(stateChanged(SubscriptionState)),
            this, SLOT(doQMqttSubscriptionStateChanged(SubscriptionState)));
}

void MQTTClient::doDisconnected()
{
    emit log("MQTTClient 已斷開連接!");
    this->close();
}

void MQTTClient::doMessageReceived(const QByteArray &message, const QMqttTopicName &topic)
{
    emit log(QString("MQTTClient 接收到數據: %1").arg(QString::fromLatin1(message)));
}

void MQTTClient::doQMqttSubscriptionStateChanged(SubscriptionState subscriptionState)
{
    if(subscriptionState==QMqttSubscription::Subscribed)
    {
        emit log("訂閱設備消息成功!");
    }
}
#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>
#include "mqttclient.h"

namespace Ui {
class MainWidget;
}

class MainWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MainWidget(QWidget *parent = 0);
    ~MainWidget();

private slots:
    void on_buttonConnect_clicked();

    void on_buttonWrite_clicked();

    void on_buttonClear_clicked();

    void doLog(const QString &text);

private:
    Ui::MainWidget *ui;

    MQTTClient *m_mqttClient;
};

#endif // MAINWIDGET_H
#include "mainwidget.h"
#include "ui_mainwidget.h"

MainWidget::MainWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MainWidget)
{
    ui->setupUi(this);
    m_mqttClient=NULL;
}

MainWidget::~MainWidget()
{
    delete ui;
}

void MainWidget::on_buttonConnect_clicked()
{
    if(m_mqttClient!=NULL)
    {
        m_mqttClient->close();
        m_mqttClient=NULL;
    }
    m_mqttClient=new MQTTClient(ui->lineUsername->text(), ui->linePasswordMD5->text(), ui->lineDeviceId->text());
    connect(m_mqttClient, SIGNAL(log(QString)), this, SLOT(doLog(QString)));
    m_mqttClient->open();
}

void MainWidget::on_buttonWrite_clicked()
{
    if((m_mqttClient==NULL) || (!m_mqttClient->isOpened()))
    {
        ui->textLog->append("MQTT客戶端未打開!");
        return;
    }
    m_mqttClient->write(ui->lineWrite->text().toLatin1());
}

void MainWidget::on_buttonClear_clicked()
{
    ui->textLog->clear();
}

void MainWidget::doLog(const QString &text)
{
    ui->textLog->append(text);
}

然後運行測試:

(------- 完 -------)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章