Introduction

MQTT is a machine-to-machine communication protocol that uses the publish-and-subscribe concept. OPC UA is a data modeling and data exchange standard protocol for industrial applications. Modbus is a serial communication request/reply protocol with one Modbus client and several Modbus servers in its network, it mainly work with programmable logic controllers (PLCs). A RESTful API is a design approach for an application program interface (API) that accesses and uses data via HTTP requests. Both MQTT and REST API are very popular in the internet industry, OPC UA and Modbus is applied more on the manufacturing machine with automation.

MQTT and OPC UA modules are not standard modules in Qt 5 open source version, they belong to Qt Extra Module with GPL v3 license. We need to compile these modules by ourselves if we want to use them in project. This article will show you how to compile/use MQTT and OPC UA in Qt 5, and how to configure/use Modbus and REST API for communication.

Qt MQTT

Qt MQTT can work with other non-Qt version MQTT. Firstly, ensure that you have installed Qt 5 Open Source (GPL v3) version, I am using Qt 5.12 in Ubuntu 18.04, and you need to know your Qt 5 installation path.

Compile

Let’s start to compile MQTT in Qt:

# go to Qt installtion source folder, yours may be different
cd ~/Qt/5.12.0/Src 
# dowoload qtmqtt module from github
wget -O qtmqtt.zip https://github.com/qt/qtmqtt/archive/v5.12.0.zip
# unzip the file
unzip  qtmqtt.zip
# go to qtmqtt folder
cd qtmqtt
# create a .git folder, very important!!!
mkdir .git 
# create a build folder 
mkdir build && cd build
# start to compile, your qmake path may be different, don't forget two dots
~/Qt/5.12.0/gcc_64/bin/qmake -r ..  
# installation
make install

Note: In the above steps, you should notice that I create a .git folder. Becasue Qt module’s headers auto-generation depends on a git_build feature, a .git directory can make it work. So either clone git repo or otherwise mkdir .git in the module-root directory (it is where you’ll find the qmqtt.pro and .qmake.conf files).

I will use git clone method in OPC UA part.

Usage

At the start, don’t forget to add mqtt in .pro file of your Qt project.

QT += core gui mqtt

Here are some common headers for Qt MQTT client.

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

Qt has constructed its own MQTT class, we can just use it. For examoke, in client side:

MqttClient::MqttClient(QObject *parent) : QObject(parent)
{
    // create a new object of QMqttClient
    QMqttClient *mqttClient;
    mqttClient = new QMqttClient(this); 
    // Then do initialization
}

// this is a standard process of connecting to broker
void MqttClient::connectToBroker(QString ip, QString mqttPort, QString username, QString password)
{
    if (mqttClient->state() == QMqttClient::Disconnected)
    {
        mqttClient->setHostname(ip);
        mqttClient->setPort(mqttPort.toInt());
        mqttClient->setUsername(username);
        mqttClient->setPassword(password);
        mqttClient->connectToHost();
    }
}

There are more other MQTT funtion usages in my code, you can check it out.

Qt OPC UA

Compile

We use open62541 as the Qt OPC UA backend here, let’s start to compile open62541 first:

# only python2 work, python3 can not!
sudo apt install python-pip 
# dependency for open62541
pip install six
# download the source code
git clone https://github.com/open62541/open62541.git
cd open62541
git checkout 0.3 
mkdir build && cd build
# compile and install
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DUA_ENABLE_AMALGAMATION=ON ..
make
sudo make install

Now let’s start to compile OPC UA with Qt:

# go to Qt installtion source folder, yours may be different
cd ~/Qt/5.12.0/Src
# clone d qtopcua module from github
git clone https://code.qt.io/qt/qtopcua.git
# go to the folder
cd qtopcua
# checkout to version 5.12
git checkout 5.12
# create build folder
mkdir build && cd build
# # start to compile, your qmake path may be different, don't forget two dots
~/Qt/5.12.0/gcc_64/bin/qmake ..
# installation
make
sudo make install

Usage

Don’t forget to add opcua in .pro file of your Qt project.

QT += core gui mqtt opcua

Here are some common headers for Qt OPC UA client.

#include <QOpcUaClient>
#include <QOpcUaNode>
#include <QtOpcUa>

We take an example on how to connect to an OPC UA server:

QOpcUaProvider *opcuaProvider;
opcuaProvider = new QOpcUaProvider(this);
QOpcUaClient *opcuaClient;
// the backend is open62541
opcuaClient = opcuaProvider->createClient(opcuaProvider->availableBackends()[0]);
if (!opcuaClient) {
    qDebug() << "Fail to create OPCUA client.";
    return;
}else{
    opcuaClient->connectToEndpoint(serverURL);
}

There are more other OPC UA funtion usages in my code, you can check it out.

Qt Modbus

Modbus is a standard module in Qt 5 Open Source version, there is no need to compile again, we can directly use it.

Usage

Add serialbus in .pro file of your Qt project.

QT += core gui mqtt opcua serialbus

Here are some common headers for Qt Modbus client.

#include <QModbusClient>
#include <QModbusTcpClient>
#include <QModbusDataUnit>

We still take an example on how to connect to a Modbus server:

void connectToPLC(ip, port) {
    QModbusClient *modbusDevice;
    modbusDevice = new QModbusTcpClient(this);
    if (modbusDevice->state() != QModbusDevice::ConnectedState){
        modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, ip);
        modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);

        modbusDevice->setTimeout(1000); // 1s
        modbusDevice->setNumberOfRetries(3);

        if (!modbusDevice->connectDevice()){
            qDebug() << "Modbus connection failure.";
        }
    }
}

You can click here to check the code on how to read and write from Modbus or PLC server.

Qt REST API (Curl)

I use curl to interact with REST API in Qt, so I just need to figure out how to use curl in Qt.

Configure

Install curl library:

sudo apt install libcurl4-openssl-dev

Add the following code in .pro file to use curl:

LIBS += -lcurl

Include the curl header in header file:

#include <curl/curl.h>

Usage

The following code is a standard usage of curl. You can click here to see how do I use it (line 180 - 272).

void curlDemo(){
    CURL *curl;
    CURLcode res;
    std::string readBuffer;
    QString result;

    QString restURL = "http://xxxxxx";

    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();

    if (curl){
        curl_easy_setopt(curl, CURLOPT_URL, qstr2char(restURL));
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        struct curl_slist *chunk = NULL;
        chunk = curl_slist_append(chunk, "Accept: application/json");  // depend on your application
        chunk = curl_slist_append(chunk, "Content-Type: application/json");  // depend on your application

        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
        curl_easy_setopt(curl, CURLOPT_POST, 1);  // depend on your application
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, qstr2char(postfield)); // depend on your application

        res = curl_easy_perform(curl);

        if(res != CURLE_OK){
            qDebug() << curl_easy_strerror(res);
        }

        curl_easy_cleanup(curl);
        curl_slist_free_all(chunk);
        result = QString::fromStdString(readBuffer);
    }

    curl_global_cleanup();
}