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 otherwisemkdir .git
in the module-root directory (it is where you’ll find theqmqtt.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();
}