File indexing completed on 2024-05-12 03:49:29

0001 /*
0002     File                 : MQTT_test.cpp
0003     Project              : LabPlot
0004     Description          : Tests for MQTT import.
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2018 Kovacs Ferencz <kferike98@gmail.com>
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "MQTT_test.h"
0011 #include "ui_MQTT_test.h"
0012 
0013 #include <QDateTime>
0014 #include <QMessageBox>
0015 #include <QMqttClient>
0016 #include <QTimer>
0017 
0018 #include <chrono>
0019 #include <iostream>
0020 #include <random>
0021 
0022 MainWindow::MainWindow(QWidget* parent)
0023     : QMainWindow(parent)
0024     , ui(new Ui::MainWindow)
0025     , m_run(false)
0026     , m_pathes(1)
0027     , m_itersTotal(100000)
0028     , m_iters(300)
0029     , m_iterCount(0)
0030     , m_delta(0.25)
0031     , m_dt(0.1)
0032     , m_interval(1000)
0033     , m_seed(std::chrono::system_clock::now().time_since_epoch().count()) {
0034     ui->setupUi(this);
0035 
0036     m_timer = new QTimer(this);
0037     m_timer->setInterval(m_interval);
0038 
0039     m_generator = new std::default_random_engine(m_seed);
0040     m_distribution = new std::normal_distribution<double>(0.0, (std::pow(m_delta, 2.0) * m_dt));
0041 
0042     m_x.fill(0.0, m_pathes);
0043 
0044     m_client = new QMqttClient(this);
0045     m_client->setHostname(ui->lineEditHost->text());
0046     m_client->setPort(ui->spinBoxPort->value());
0047 
0048     connect(m_client, &QMqttClient::disconnected, this, &MainWindow::brokerDisconnected);
0049     connect(m_timer, &QTimer::timeout, this, &MainWindow::onTimeout);
0050     connect(ui->lePublishInterval, &QLineEdit::textChanged, this, &MainWindow::intervalChanged);
0051     connect(ui->bPublish, &QPushButton::clicked, this, &MainWindow::onTimeout);
0052     connect(m_client, &QMqttClient::connected, this, &MainWindow::onConnect);
0053 
0054     connect(m_client, &QMqttClient::messageReceived, this, [this](const QByteArray& message, const QMqttTopicName& topic) {
0055         const QString content = QDateTime::currentDateTime().toString() + QLatin1String(" Received Topic: ") + topic.name() + QLatin1String(" Message:\n")
0056             + message + QLatin1Char('\n');
0057         ui->editLog->insertPlainText(content);
0058     });
0059 
0060     connect(ui->lineEditHost, &QLineEdit::textChanged, m_client, &QMqttClient::setHostname);
0061     connect(ui->spinBoxPort, QOverload<int>::of(&QSpinBox::valueChanged), this, &MainWindow::setClientPort);
0062 }
0063 
0064 MainWindow::~MainWindow() {
0065     delete ui;
0066     qApp->quit();
0067 }
0068 
0069 void MainWindow::on_buttonConnect_clicked() {
0070     if (m_client->state() == QMqttClient::Disconnected) {
0071         ui->lineEditHost->setEnabled(false);
0072         ui->spinBoxPort->setEnabled(false);
0073         ui->buttonConnect->setText(tr("Disconnect"));
0074         m_client->connectToHost();
0075     } else {
0076         ui->lineEditHost->setEnabled(true);
0077         ui->spinBoxPort->setEnabled(true);
0078         ui->buttonConnect->setText(tr("Connect"));
0079         m_client->disconnectFromHost();
0080     }
0081 }
0082 
0083 void MainWindow::on_buttonQuit_clicked() {
0084     QApplication::quit();
0085 }
0086 
0087 void MainWindow::brokerDisconnected() {
0088     ui->lineEditHost->setEnabled(true);
0089     ui->spinBoxPort->setEnabled(true);
0090     ui->buttonConnect->setText(tr("Connect"));
0091 }
0092 
0093 void MainWindow::setClientPort(int p) {
0094     m_client->setPort(p);
0095 }
0096 
0097 void MainWindow::on_buttonSubscribe_clicked() {
0098     if (m_client->state() == QMqttClient::ClientState::Connected) {
0099         QMqttTopicFilter filterX{"brownian/x"};
0100 
0101         QMqttSubscription* subscription;
0102         subscription = m_client->subscribe(filterX, ui->spinQoS->text().toUInt());
0103         if (!subscription) {
0104             QMessageBox::critical(this, QLatin1String("Error"), QLatin1String("Could not subscribe. Is there a valid connection?"));
0105             return;
0106         }
0107         m_qos = subscription->qos();
0108         m_brownianX = new QMqttTopicName(subscription->topic().filter());
0109 
0110         for (int i = 0; i < m_pathes; i++) {
0111             QMqttTopicFilter filterY{"brownian/y" + QString::number(i)};
0112             subscription = m_client->subscribe(filterY, ui->spinQoS->text().toUInt());
0113             if (!subscription) {
0114                 QMessageBox::critical(this, QLatin1String("Error"), QLatin1String("Could not subscribe. Is there a valid connection?"));
0115                 return;
0116             }
0117             m_brownianTopics.push_back(new QMqttTopicName(subscription->topic().filter()));
0118         }
0119         m_timer->start();
0120     }
0121 }
0122 
0123 void MainWindow::onTimeout() {
0124     if (m_client->state() == QMqttClient::ClientState::Connected && !m_brownianTopics.isEmpty()) {
0125         QString s;
0126         QVector<QString> brownianY;
0127         brownianY.fill(QString(), m_pathes);
0128 
0129         if (m_iterCount < m_itersTotal - m_iters - 1)
0130             for (int i = 0; i < m_iters; i++) {
0131                 if (!s.isEmpty())
0132                     s.append("\n");
0133 
0134                 s.append(QString::number(m_iterCount * m_dt));
0135                 for (int j = 0; j < m_pathes; j++) {
0136                     if (!brownianY[j].isEmpty())
0137                         brownianY[j].append("\n");
0138                     m_x[j] = m_x[j] + m_distribution->operator()(*m_generator);
0139                     brownianY[j].append(QString::number(m_x[j]));
0140                 }
0141                 m_iterCount++;
0142             }
0143 
0144         if (m_client->publish(*m_brownianX, s.toUtf8(), m_qos, false) == -1)
0145             QMessageBox::critical(this, QLatin1String("Error"), QLatin1String("Could not publish message"));
0146         for (int i = 0; i < m_pathes; i++) {
0147             if (m_client->publish(*m_brownianTopics[i], brownianY[i].toUtf8(), m_qos, false) == -1)
0148                 QMessageBox::critical(this, QLatin1String("Error"), QLatin1String("Could not publish message"));
0149         }
0150     }
0151 }
0152 
0153 void MainWindow::intervalChanged(const QString& interval) {
0154     int newInterval = interval.toInt();
0155     m_timer->start(newInterval);
0156     m_interval = newInterval;
0157 }
0158 
0159 void MainWindow::onConnect() {
0160     const QString content = QDateTime::currentDateTime().toString() + "  Successfully connected to broker";
0161     ui->editLog->insertPlainText(content);
0162 }