ex07a
ex07a_01
ex07a_01.pro
QT += quick mqtt
// ...
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12 
Window {
   width: 640
   height: 480
   visible: true
   title: qsTr("ex07a - v0.1")
   EstatMqtt{
       anchors.centerIn: parent
   }
}
EstatMqtt.qml
import QtQuick 2.4
EstatMqttForm {
}
EstatMqttForm.ui.qml
import QtQuick 2.4
import QtQuick.Controls 2.15
Item {
   id: item1
   width: 400
   height: 400
   property alias btConnecta: btConnecta
   property alias textInfo: textInfo
   Text {
       id: textInfo
       y: 56
       height: 53
       color: "#ee2222"
       text: qsTr("MQTT desconnectat")
       anchors.left: parent.left
       anchors.right: parent.right
       anchors.bottom: btConnecta.top
       font.pixelSize: 35
       horizontalAlignment: Text.AlignHCenter
       anchors.bottomMargin: 25
       anchors.rightMargin: 10
       anchors.leftMargin: 10
       font.bold: true
   }
   Button {
       id: btConnecta
       x: 164
       y: 214
       text: qsTr("&Connecta")
       anchors.verticalCenter: parent.verticalCenter
       anchors.horizontalCenter: parent.horizontalCenter
   }
}
ex07a_02
EstatMqttForm.ui.qml
   // ...
   property alias btLedBlanc: btLedBlanc
   // ...
   Button {
       id: btLedBlanc
       x: 169
       text: qsTr("Encén led blanc")
       anchors.top: btConnecta.bottom
       anchors.horizontalCenterOffset: 0
       anchors.topMargin: 25
       anchors.horizontalCenter: btConnecta.horizontalCenter
       enabled: false
   }
   // ...
main.qml
   title: qsTr("ex07a - v0.2")
   EstatMqtt{
       anchors.centerIn: parent
       btConnecta.onClicked: {
           textInfo.text = (textInfo.text === qsTr("MQTT desconnectat"))?qsTr("MQTT connectat"):qsTr("MQTT desconnectat")
           textInfo.color = (textInfo.text === qsTr("MQTT desconnectat"))?"#ee2222":"#22ee22"
           btConnecta.text = (textInfo.text === qsTr("MQTT desconnectat"))?qsTr("&Connecta"):qsTr("Des&connecta")
           btLedBlanc.enabled = (textInfo.text === qsTr("MQTT desconnectat"))?false:true
       }
       btLedBlanc.onClicked: {
           btLedBlanc.text = (btLedBlanc.text === qsTr("Encén led blanc"))?qsTr("Apaga led blanc"):qsTr("Encén led blanc")
       }
   }
ex07a_03
rerefonsmqtt.h
#ifndef REREFONSMQTT_H
#define REREFONSMQTT_H
#include <QObject>
#include <QMqttClient>
class RerefonsMqtt : public QObject
{
   Q_OBJECT
public:
   explicit RerefonsMqtt(QObject *parent = nullptr);
signals:
   void senyalEstatConnexioMqtt(int nEstatConnexioMqtt);
public slots:
   void vBotoConnectaDesconnectaMqtt();
private:
   int m_nEstat;
};
#endif // REREFONSMQTT_H
rerefonsmqtt.cpp
#include "rerefonsmqtt.h"
RerefonsMqtt::RerefonsMqtt(QObject *parent) : QObject(parent)
{
   m_nEstat = 1;
}
void RerefonsMqtt::vBotoConnectaDesconnectaMqtt(){
   if(m_nEstat > 2)
       m_nEstat = 0;
   emit senyalEstatConnexioMqtt(m_nEstat++);
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "rerefonsmqtt.h"
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
   QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
   QGuiApplication app(argc, argv);
   qmlRegisterType<RerefonsMqtt>("desDel.rerefonsMqtt",1,0,"RerefonsMqtt");
   QQmlApplicationEngine engine;
   const QUrl url(QStringLiteral("qrc:/main.qml"));
   QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                    &app, [url](QObject *obj, const QUrl &objUrl) {
       if (!obj && url == objUrl)
           QCoreApplication::exit(-1);
   }, Qt::QueuedConnection);
   engine.load(url);
   return app.exec();
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12 // <---
import desDel.rerefonsMqtt 1.0 // <---
ApplicationWindow { // <--- !!!!
   width: 640
   height: 480
   visible: true
   title: qsTr("ex07a - v0.3")
   RerefonsMqtt{ // <--- !!!!
       id: rfMqtt
       onSenyalEstatConnexioMqtt: {
           console.log(nEstatConnexioMqtt)
       }
   }
   EstatMqtt{
       id: eMqtt // <--- !!!!
       anchors.centerIn: parent
       btConnecta.onClicked: {
           textInfo.text = (textInfo.text === qsTr("MQTT desconnectat"))?qsTr("MQTT connectat"):qsTr("MQTT desconnectat")
           textInfo.color = (textInfo.text === qsTr("MQTT desconnectat"))?"#ee2222":"#22ee22"
           btConnecta.text = (textInfo.text === qsTr("MQTT desconnectat"))?qsTr("&Connecta"):qsTr("Des&connecta")
           btLedBlanc.enabled = (textInfo.text === qsTr("MQTT desconnectat"))?false:true
           rfMqtt.vBotoConnectaDesconnectaMqtt() // <--- !!!!
       }
       btLedBlanc.onClicked: {
           btLedBlanc.text = (btLedBlanc.text === qsTr("Encén led blanc"))?qsTr("Apaga led blanc"):qsTr("Encén led blanc")
       }
   }
}
ex07a_04
main.qml
ApplicationWindow { 
   id: aw
   width: 640
   height: 480
   visible: true
   title: qsTr("ex07a - v0.4")
   function actualitzaFrontal(nEstatConnexioMqtt){
       switch(nEstatConnexioMqtt){
       case 0:
           eMqtt.textInfo.text = qsTr("MQTT desconnectat")
           eMqtt.textInfo.color = "#ee2222"
           eMqtt.btConnecta.text =qsTr("&Connecta")
           eMqtt.btConnecta.enabled = true
           eMqtt.btLedBlanc.enabled = false
           break;
       case 1:
           eMqtt.textInfo.text = qsTr("MQTT connectant")
           eMqtt.textInfo.color = "#2222ee"
           //eMqtt.btConnecta.enabled = false
           eMqtt.btLedBlanc.enabled = false
           break;
       case 2:
           eMqtt.textInfo.text = qsTr("MQTT connectat")
           eMqtt.textInfo.color = "#22ee22"
           eMqtt.btConnecta.text =qsTr("Des&connecta")
           eMqtt.btConnecta.enabled = true
           eMqtt.btLedBlanc.enabled = true
           break;
       }
   }
   RerefonsMqtt{ 
       id: rfMqtt
       onSenyalEstatConnexioMqtt: {
           console.log(nEstatConnexioMqtt)
           aw.actualitzaFrontal(nEstatConnexioMqtt)
       }
   }
   EstatMqtt{
       id: eMqtt // <--- !!!!
       anchors.centerIn: parent
       btConnecta.onClicked: {
           rfMqtt.vBotoConnectaDesconnectaMqtt() // <--- !!!!
       }
       btLedBlanc.onClicked: {
           btLedBlanc.text = (btLedBlanc.text === qsTr("Encén led blanc"))?qsTr("Apaga led blanc"):qsTr("Encén led blanc")
       }
   }
}
ex07a_05
credencials.h
#ifndef CREDENCIALS_H
#define CREDENCIALS_H
#define BROKER_NAME "formacio.things.cat"
#define BROKER_PORT 1883
#define BROKER_USER "ecat"
#define BROKER_PASSWORD "clotClot"
#endif // CREDENCIALS_H
rerefonsmqtt.h
#include <QMqttClient>
#include "credencials.h"
// ...
private:
   int m_nEstat;
   QMqttClient *m_client;
private slots:
   void updateLogStateChange();
   void brokerDisconnected();
// ...
rerefonsmqtt.cpp
// ...
#include <QtCore/QDateTime>
#include <QtMqtt/QMqttClient>
#include <QDebug>
RerefonsMqtt::RerefonsMqtt(QObject *parent) : QObject(parent)
{
   m_client = new QMqttClient(this);
   m_client->setHostname(BROKER_NAME);
   m_client->setPort(BROKER_PORT);
   m_nEstat = 1;
   connect(m_client, &QMqttClient::stateChanged, this, &RerefonsMqtt::updateLogStateChange);
   connect(m_client, &QMqttClient::disconnected, this, &RerefonsMqtt::brokerDisconnected);
}
void RerefonsMqtt::vBotoConnectaDesconnectaMqtt(){
   if (m_client->state() == QMqttClient::Disconnected) {
       m_client->setUsername(BROKER_USER);
       m_client->setPassword(BROKER_PASSWORD);
       m_client->connectToHost();
   } else {
       m_client->disconnectFromHost();
   }
}
void RerefonsMqtt::updateLogStateChange(){
   const QString content = QDateTime::currentDateTime().toString()
                   + QLatin1String(": State Change")
                   + QString::number(m_client->state())
                   + QLatin1Char('\n');
   qDebug() << content;
   emit senyalEstatConnexioMqtt(m_nEstat = m_client->state());
}
void RerefonsMqtt::brokerDisconnected(){
   qDebug() << "Broker desconnectat!";
}
ex07a_06
temes.h
#ifndef TEMES_H
#define TEMES_H
#define TOPIC_LED_W "/ledW"
#endif // TEMES_H
rerefonsmqtt.h
// ...
#include "temes.h"
#define MAC_PLACA "AABBCCDDEE01"
// ...
public:
   explicit RerefonsMqtt(QObject *parent = nullptr);
   ~RerefonsMqtt();
// ...
public slots:
   void vBotoConnectaDesconnectaMqtt();
   void vPublicaEstatLed(QString szQuinLed,QString szEstat);
// ...
rerefonsmqtt.cpp
RerefonsMqtt::~RerefonsMqtt(){
   if (m_client->state() == QMqttClient::Connected || m_client->state() == QMqttClient::Connecting) {
       m_client->disconnectFromHost();
   }
}
void RerefonsMqtt::vPublicaEstatLed(QString szQuinLed,QString szEstat){
   if(szQuinLed == "w" || szQuinLed == "W" || szQuinLed == "ledW"){
       QString szTopic = QString("/") + MAC_PLACA + TOPIC_LED_W;
       qDebug() << "Tema: " << szTopic << ", Missatge: " << szEstat;
       if (m_client->publish(szTopic, szEstat.toUtf8()) == -1)
           qDebug() << "Error. No es pot publicar el missatge";
   }
}
main.qml
   EstatMqtt{
       id: eMqtt 
       anchors.centerIn: parent
       btConnecta.onClicked: {
           rfMqtt.vBotoConnectaDesconnectaMqtt() 
       }
       btLedBlanc.onClicked: {
           btLedBlanc.text = (btLedBlanc.text === qsTr("Encén led blanc"))?qsTr("Apaga led blanc"):qsTr("Encén led blanc")
           rfMqtt.vPublicaEstatLed("w",(btLedBlanc.text === qsTr("Encén led blanc"))?"0":"1")
       }
   }
ex07b
ex07b_07
temes.h
#ifndef TEMES_H
#define TEMES_H
#define TOPIC_LED_W "/ledW"
#define TOPIC_BT_I35 "/btI35"
#endif // TEMES_H
rerefonsmqtt.cpp
RerefonsMqtt::RerefonsMqtt(QObject *parent) : QObject(parent)
{
   // ...
   connect(m_client, &QMqttClient::messageReceived, this, [this](const QByteArray &message, const QMqttTopicName &topic) {
       const QString content = QDateTime::currentDateTime().toString()
                   + QLatin1String(" Received Topic: ")
                   + topic.name()
                   + QLatin1String(" Message: ")
                   + message
                   + QLatin1Char('\n');
       qDebug() << content;
   });
}
void RerefonsMqtt::updateLogStateChange(){
   const QString content = QDateTime::currentDateTime().toString()
                   + QLatin1String(": State Change")
                   + QString::number(m_client->state())
                   + QLatin1Char('\n');
   qDebug() << content;
   emit senyalEstatConnexioMqtt(m_nEstat = m_client->state());
   if(m_nEstat == 2){
       QString szSubscriptionTopic = QString("/") + MAC_PLACA + TOPIC_BT_I35;
       auto subscription = m_client->subscribe(szSubscriptionTopic);
       if (!subscription) {
           qDebug() << "Error: No m'hi puc subscriure. Hi ha una connexió vàlida?";
           return;
       }else
           qDebug() << "Subscrit a " << szSubscriptionTopic;
   }
}
ex07b_08
rerefonsmqtt.h
// ...
private slots:
   void updateLogStateChange();
   void brokerDisconnected();
   void vGestionaMissatgeRebut(const QByteArray &message, const QMqttTopicName &topic);
// ...
rerefonsmqtt.cpp
RerefonsMqtt::RerefonsMqtt(QObject *parent) : QObject(parent)
{
   m_client = new QMqttClient(this);
   m_client->setHostname(BROKER_NAME);
   m_client->setPort(BROKER_PORT);
   m_nEstat = 1;
   connect(m_client, &QMqttClient::stateChanged, this, &RerefonsMqtt::updateLogStateChange);
   connect(m_client, &QMqttClient::disconnected, this, &RerefonsMqtt::brokerDisconnected);
   connect(m_client, &QMqttClient::messageReceived, this, &RerefonsMqtt::vGestionaMissatgeRebut);
}
void RerefonsMqtt::vGestionaMissatgeRebut(const QByteArray &message, const QMqttTopicName &topic){
   const QString content = QDateTime::currentDateTime().toString()
               + QLatin1String(" Received Topic: ")
               + topic.name()
               + QLatin1String(" Message: ")
               + message
               + QLatin1Char('\n');
   qDebug() << content;
   // Amb més d'un tema subscrit caldria filtrar per tema ( topic.name() ) 
   if(message == "I35 pressed"){
       qDebug() << "Botó I35 premut";
   }
   if(message == "I35 released"){
       qDebug() << "Botó I35 no premut";
   }
}
ex07b_09
main.qml
   // ...
   function actualitzaFrontal(nEstatConnexioMqtt){
       switch(nEstatConnexioMqtt){
       case 0:
           // ...
           eMqtt.textBotoI35.visible = false
           break;
       case 1:
           // ...
       case 2:
           // ...
           eMqtt.textBotoI35.visible = true
           break;
       }
   }
   // ...
   RerefonsMqtt{ 
       id: rfMqtt
       onSenyalEstatConnexioMqtt: {
           console.log(nEstatConnexioMqtt)
           aw.actualitzaFrontal(nEstatConnexioMqtt)
       }
       onSenyalBotoI35: {
           console.log(qszTextBotoI35)
           eMqtt.textBotoI35.text = qszTextBotoI35
       }
   }
EstatMqttForm.ui.qml
// ..
property alias textBotoI35: textBotoI35 
// ..
   Text {
       id: textBotoI35
       x: 188
       text: qsTr("Botó I35 no premut")
       anchors.top: btLedBlanc.bottom
       font.pixelSize: 15
       horizontalAlignment: Text.AlignHCenter
       font.bold: true
       minimumPixelSize: 24
       anchors.topMargin: 25
       anchors.horizontalCenter: parent.horizontalCenter
   }
// ..