From 01130f0036e758ea43af81628f21c213dbf0c978 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Sun, 8 Dec 2019 16:28:22 +0100 Subject: [PATCH] add mqtt subscribe capability --- soft/thermostat/inc/backgroundloop.h | 42 +++++++++++ soft/thermostat/inc/mainwindow.h | 7 +- soft/thermostat/src/backgroundloop.cpp | 126 +++++++++++++++++++++++++++++++++ soft/thermostat/src/mainwindow.cpp | 1 + soft/thermostat/thermostat.pro | 7 +- 5 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 soft/thermostat/inc/backgroundloop.h create mode 100644 soft/thermostat/src/backgroundloop.cpp diff --git a/soft/thermostat/inc/backgroundloop.h b/soft/thermostat/inc/backgroundloop.h new file mode 100644 index 0000000..74700fc --- /dev/null +++ b/soft/thermostat/inc/backgroundloop.h @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +/* + * Qt mutizone MQTT thermostat + * + * Copyright (C) 2019 Richard Genoud + * + */ + +#ifndef BACKGROUNDLOOP_H +#define BACKGROUNDLOOP_H + +#include + +#include "qmqtt.h" + + +class BackgroundLoop : public QThread +{ + Q_OBJECT + + +public: + BackgroundLoop(); + ~BackgroundLoop(); + bool connectMQTT(); + +private: + void run() override; + QMQTT::Client *m_mqtt_client; + +private slots: + void mqtt_connected(void); + void mqtt_disconnected(void); + void mqtt_error(const QMQTT::ClientError error); + void mqtt_subscribed(const QString& topic, const quint8 qos); + void mqtt_received(const QMQTT::Message& message); + +}; + +#endif // BACKGROUNDLOOP_H + +/* vim: set tabstop=8 shiftwidth=8 softtabstop=0 noexpandtab: */ diff --git a/soft/thermostat/inc/mainwindow.h b/soft/thermostat/inc/mainwindow.h index a523395..9fd4d26 100644 --- a/soft/thermostat/inc/mainwindow.h +++ b/soft/thermostat/inc/mainwindow.h @@ -13,13 +13,18 @@ #include #include +#include "backgroundloop.h" + class MainWindow : public QMainWindow { Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(QWidget *parent = NULL); ~MainWindow(); + +private: + BackgroundLoop m_backLoop; }; #endif // MAINWINDOW_H diff --git a/soft/thermostat/src/backgroundloop.cpp b/soft/thermostat/src/backgroundloop.cpp new file mode 100644 index 0000000..991259f --- /dev/null +++ b/soft/thermostat/src/backgroundloop.cpp @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +/* + * Qt mutizone MQTT thermostat + * + * Copyright (C) 2019 Richard Genoud + * + */ + +#include +#include +#include +#include +#include +#include + + +#include "qmqtt.h" +#include "backgroundloop.h" + +#define MQTT_SERVER "nas" +#define MQTT_PORT 1883 +#define MQTT_USERNAME "" +#define MQTT_PASSWORD "" +#define MQTT_CLIENT_ID "" +#define LOOP_SLEEP_TIME_S 5 + + +BackgroundLoop::BackgroundLoop() { + m_mqtt_client = NULL; + qsrand((uint)QDateTime::currentMSecsSinceEpoch()); +} + +BackgroundLoop::~BackgroundLoop() { +} + +bool BackgroundLoop::connectMQTT() +{ + QHostInfo info; + QHostAddress address; + bool result = false, ok; + + if (m_mqtt_client) { + delete m_mqtt_client; + m_mqtt_client = NULL; + } + + ok = address.setAddress(MQTT_SERVER); + if (!ok) { + /* This must be a domain name, not an IP */ + info = QHostInfo::fromName(MQTT_SERVER); + if (info.error() != QHostInfo::NoError) { + qWarning() << QString("Error looking for address %1").arg(MQTT_SERVER) + << info.errorString(); + goto out; + } + if (info.addresses().isEmpty()) { + qWarning() << QString("No address returned for %1").arg(MQTT_SERVER); + goto out; + } + address = info.addresses().first(); + } + + m_mqtt_client = new QMQTT::Client(address, MQTT_PORT); + if (!m_mqtt_client) { + qWarning() << QString("Error allocating memory for MQTT client"); + goto out; + } + if (QString(MQTT_CLIENT_ID).isEmpty()) { + m_mqtt_client->setClientId(QString("thermostat%1").arg(qrand())); + } else { + m_mqtt_client->setClientId(MQTT_CLIENT_ID); + } + connect(m_mqtt_client, SIGNAL(connected()), this, SLOT(mqtt_connected())); + connect(m_mqtt_client, SIGNAL(disconnected()), this, SLOT(mqtt_disconnected())); + connect(m_mqtt_client, SIGNAL(error(const QMQTT::ClientError)), + this, SLOT(mqtt_error(const QMQTT::ClientError))); + connect(m_mqtt_client, SIGNAL(subscribed(const QString&, const quint8)), + this, SLOT(mqtt_subscribed(const QString&, const quint8))); + connect(m_mqtt_client, SIGNAL(received(const QMQTT::Message&)), + this, SLOT(mqtt_received(const QMQTT::Message&))); + + m_mqtt_client->setUsername(MQTT_USERNAME); + m_mqtt_client->setPassword(MQTT_PASSWORD); + m_mqtt_client->connectToHost(); + + result = true; + +out: + return result; +} + +void BackgroundLoop::mqtt_connected(void) +{ + qDebug() << "MQTT connected !"; +} + +void BackgroundLoop::mqtt_disconnected(void) +{ + qDebug() << "MQTT disconnected !"; +} + +void BackgroundLoop::mqtt_error(const QMQTT::ClientError error) +{ + qDebug() << "MQTT error ! code: " << error; +} + +void BackgroundLoop::mqtt_subscribed(const QString& topic, const quint8 qos) +{ + qDebug() << "MQTT subscribed! topic: " << topic << " QoS: " << qos; +} + +void BackgroundLoop::mqtt_received(const QMQTT::Message& message) +{ + qDebug() << "MQTT recieved: " << QString::fromUtf8(message.payload()); +} + + +void BackgroundLoop::run() +{ + connectMQTT(); + while(!isInterruptionRequested()) { + this->sleep(LOOP_SLEEP_TIME_S); + } +} + +/* vim: set tabstop=8 shiftwidth=8 softtabstop=0 noexpandtab: */ diff --git a/soft/thermostat/src/mainwindow.cpp b/soft/thermostat/src/mainwindow.cpp index 7f161ed..87d0336 100644 --- a/soft/thermostat/src/mainwindow.cpp +++ b/soft/thermostat/src/mainwindow.cpp @@ -39,6 +39,7 @@ MainWindow::MainWindow(QWidget *parent) : setCentralWidget(mainWidget); setWindowTitle(tr("Sorico's thermostat")); + m_backLoop.start(); } MainWindow::~MainWindow() diff --git a/soft/thermostat/thermostat.pro b/soft/thermostat/thermostat.pro index 29f68e5..8f8d829 100644 --- a/soft/thermostat/thermostat.pro +++ b/soft/thermostat/thermostat.pro @@ -1,4 +1,6 @@ -QT += core gui +QT += core gui network + +QT += qmqtt greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -21,10 +23,12 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs depr SOURCES += src/main.cpp \ src/mainwindow.cpp \ src/zoneitem.cpp \ + src/backgroundloop.cpp \ HEADERS += inc/mainwindow.h \ inc/zoneitem.h \ + inc/backgroundloop.h \ RESOURCES += thermostat.qrc @@ -40,6 +44,7 @@ INSTALLS += target VERSION = $$system(./scripts/get_tag_version.sh) +# to see debug messages in console, run with environment variable QT_LOGGING_RULES="debug=true;" QMAKE_CXXFLAGS += -Wall -Werror QMAKE_CXXFLAGS += -std=c++11 QMAKE_CXXFLAGS += -DVERSION=\'\"$$VERSION\"\'