File indexing completed on 2024-04-28 15:14:08

0001 /***************************************************************************
0002 File                 : MQTT_test.cpp
0003 Project              : LabPlot
0004 Description          : Tests for MQTT import.
0005 --------------------------------------------------------------------
0006 --------------------------------------------------------------------
0007 Copyright   : (C) 2018 Kovacs Ferencz (kferike98@gmail.com)
0008 
0009 ***************************************************************************/
0010 
0011 /***************************************************************************
0012  *                                                                         *
0013  *  This program is free software; you can redistribute it and/or modify   *
0014  *  it under the terms of the GNU General Public License as published by   *
0015  *  the Free Software Foundation; either version 2 of the License, or      *
0016  *  (at your option) any later version.                                    *
0017  *                                                                         *
0018  *  This program is distributed in the hope that it will be useful,        *
0019  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0020  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0021  *  GNU General Public License for more details.                           *
0022  *                                                                         *
0023  *   You should have received a copy of the GNU General Public License     *
0024  *   along with this program; if not, write to the Free Software           *
0025  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0026  *   Boston, MA  02110-1301  USA                                           *
0027  *                                                                         *
0028  ***************************************************************************/
0029 
0030 #include "MQTT_test.h"
0031 #include "ui_MQTT_test.h"
0032 
0033 #include <QDateTime>
0034 #include <QMqttClient>
0035 #include <QMessageBox>
0036 #include <QtMath>
0037 #include <QTimer>
0038 
0039 #include <iostream>
0040 #include <chrono>
0041 #include <random>
0042 
0043 MainWindow::MainWindow(QWidget *parent) :
0044     QMainWindow(parent),
0045     ui(new Ui::MainWindow),
0046     m_run (false),
0047     m_pathes (1),
0048     m_itersTotal (100000),
0049     m_iters (300),
0050     m_iterCount (0),
0051     m_delta (0.25),
0052     m_dt (0.1),
0053     m_interval (1000),
0054     m_seed (std::chrono::system_clock::now().time_since_epoch().count())
0055 {
0056     ui->setupUi(this);
0057 
0058     m_timer = new QTimer(this);
0059     m_timer->setInterval(m_interval);
0060 
0061     m_generator = new std::default_random_engine (m_seed);
0062     m_distribution = new std::normal_distribution<double> (0.0, (qPow(m_delta, 2.0) * m_dt));
0063 
0064     m_x.fill(0.0, m_pathes);
0065 
0066     m_client = new QMqttClient(this);
0067     m_client->setHostname(ui->lineEditHost->text());
0068     m_client->setPort(ui->spinBoxPort->value());
0069 
0070 
0071     connect(m_client, &QMqttClient::disconnected, this, &MainWindow::brokerDisconnected);
0072     connect(m_timer, &QTimer::timeout, this, &MainWindow::onTimeout);
0073     connect(ui->lePublishInterval, &QLineEdit::textChanged, this, &MainWindow::intervalChanged);
0074     connect(ui->bPublish, &QPushButton::clicked, this, &MainWindow::onTimeout);
0075     connect(m_client, &QMqttClient::connected, this, &MainWindow::onConnect);
0076 
0077     connect(m_client, &QMqttClient::messageReceived, this, [this](const QByteArray &message, const QMqttTopicName &topic) {
0078         const QString content = QDateTime::currentDateTime().toString()
0079                 + QLatin1String(" Received Topic: ")
0080                 + topic.name()
0081                 + QLatin1String(" Message:\n")
0082                 + message
0083                 + QLatin1Char('\n');
0084         ui->editLog->insertPlainText(content);
0085     });
0086 
0087     connect(ui->lineEditHost, &QLineEdit::textChanged, m_client, &QMqttClient::setHostname);
0088     connect(ui->spinBoxPort, QOverload<int>::of(&QSpinBox::valueChanged), this, &MainWindow::setClientPort);
0089 
0090 }
0091 
0092 MainWindow::~MainWindow() {
0093     delete ui;
0094     qApp->quit();
0095 }
0096 
0097 void MainWindow::on_buttonConnect_clicked() {
0098     if (m_client->state() == QMqttClient::Disconnected) {
0099         ui->lineEditHost->setEnabled(false);
0100         ui->spinBoxPort->setEnabled(false);
0101         ui->buttonConnect->setText(tr("Disconnect"));
0102         m_client->connectToHost();
0103     } else {
0104         ui->lineEditHost->setEnabled(true);
0105         ui->spinBoxPort->setEnabled(true);
0106         ui->buttonConnect->setText(tr("Connect"));
0107         m_client->disconnectFromHost();
0108     }
0109 }
0110 
0111 void MainWindow::on_buttonQuit_clicked() {
0112     QApplication::quit();
0113 }
0114 
0115 void MainWindow::brokerDisconnected() {
0116     ui->lineEditHost->setEnabled(true);
0117     ui->spinBoxPort->setEnabled(true);
0118     ui->buttonConnect->setText(tr("Connect"));
0119 }
0120 
0121 void MainWindow::setClientPort(int p) {
0122     m_client->setPort(p);
0123 }
0124 
0125 
0126 void MainWindow::on_buttonSubscribe_clicked() {
0127     if(m_client->state() == QMqttClient::ClientState::Connected) {
0128         QMqttTopicFilter filterX{"brownian/x"};
0129 
0130         QMqttSubscription* subscription;
0131         subscription = m_client->subscribe(filterX , ui->spinQoS->text().toUInt());
0132         if (!subscription) {
0133             QMessageBox::critical(this, QLatin1String("Error"), QLatin1String("Could not subscribe. Is there a valid connection?"));
0134             return;
0135         }
0136         m_qos = subscription->qos();
0137         m_brownianX = new QMqttTopicName(subscription->topic().filter()) ;
0138 
0139         for (int i = 0; i < m_pathes; i++) {
0140             QMqttTopicFilter filterY{"brownian/y"+QString::number(i)};
0141             subscription = m_client->subscribe(filterY , ui->spinQoS->text().toUInt());
0142             if (!subscription) {
0143                 QMessageBox::critical(this, QLatin1String("Error"), QLatin1String("Could not subscribe. Is there a valid connection?"));
0144                 return;
0145             }
0146             m_brownianTopics.push_back(new QMqttTopicName(subscription->topic().filter())) ;
0147         }
0148         m_timer->start();
0149     }
0150 }
0151 
0152 void MainWindow::onTimeout() {
0153     if(m_client->state() == QMqttClient::ClientState::Connected &&
0154             !m_brownianTopics.isEmpty()) {
0155         QString s;
0156         QVector<QString> brownianY;
0157         brownianY.fill(QString(), m_pathes);
0158 
0159         if(m_iterCount < m_itersTotal - m_iters - 1)
0160             for (int i = 0; i < m_iters; i++) {
0161                 if (!s.isEmpty())
0162                     s.append("\n");
0163 
0164                 s.append(QString::number(m_iterCount * m_dt));
0165                 for(int j = 0; j < m_pathes; j++) {
0166                     if(!brownianY[j].isEmpty())
0167                         brownianY[j].append("\n");
0168                     m_x[j] =m_x[j] + m_distribution->operator() (*m_generator);
0169                     brownianY[j].append(QString::number(m_x[j]));
0170                 }
0171                 m_iterCount++;
0172             }
0173 
0174         if (m_client->publish(*m_brownianX,
0175                               s.toUtf8(),
0176                               m_qos,
0177                               false) == -1)
0178             QMessageBox::critical(this, QLatin1String("Error"), QLatin1String("Could not publish message"));
0179         for (int i = 0; i < m_pathes; i++) {
0180             if (m_client->publish(*m_brownianTopics[i],
0181                                   brownianY[i].toUtf8(),
0182                                   m_qos,
0183                                   false) == -1)
0184                 QMessageBox::critical(this, QLatin1String("Error"), QLatin1String("Could not publish message"));
0185         }
0186     }
0187 }
0188 
0189 void MainWindow::intervalChanged(const QString& interval) {
0190     int newInterval = interval.toInt();
0191     m_timer->start(newInterval);
0192     m_interval = newInterval;
0193 }
0194 
0195 void MainWindow::onConnect() {
0196     const QString content = QDateTime::currentDateTime().toString() +"  Successfully connected to broker";
0197     ui->editLog->insertPlainText(content);
0198 }