Guia per a desenvolupar l'ex07 dels exercicis de QML

De binefa.com
Salta a la navegació Salta a la cerca

Avís important

Hom espera que feu aquest exerici 7 de Exercicis de QML fent servir propietats, tal i com s'ha ensenyat als Vídeos QML. Aquesta solució que us faig arribar és fent servir senyals, però vosaltres heu d'implementar la solució fent servir propietats.

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

rerefonsmqtt.h

signals:
   void senyalEstatConnexioMqtt(int nEstatConnexioMqtt);
   void senyalBotoI35(QString qszTextBotoI35);

rerefonsmqtt.cpp

void RerefonsMqtt::vGestionaMissatgeRebut(const QByteArray &message, const QMqttTopicName &topic){
   // ...
   if(message == "I35 pressed"){
       qDebug() << "Botó I35 premut";
       emit senyalBotoI35("Botó I35 premut");
   }
   if(message == "I35 released"){
       qDebug() << "Botó I35 no premut";
       emit senyalBotoI35("Botó I35 no premut");
   }
}

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
   }
// ..