- // SPDX-License-Identifier: GPL-3.0-or-later
- /*
- * Qt mutizone MQTT thermostat
- *
- * Copyright (C) 2019 Richard Genoud
- *
- */
-
- #include <QLoggingCategory>
- #include <QtMqtt/QtMqtt>
- #include <QJsonDocument>
- #include <QJsonObject>
- #include <QJsonValue>
-
-
- #include "mqttclient.h"
- #include "settings.h"
-
- #define TIMER_PERIOD_MS 30000
-
- MQTTClient::MQTTClient(const QString& host, int port, QObject* parent)
- : QMqttClient(parent)
- {
- this->setHostname(host);
- this->setPort(port);
-
- connect(this, SIGNAL(connected(void)), this, SLOT(onConnected(void)));
- connect(this, SIGNAL(disconnected(void)), this, SLOT(onDisconnected(void)));
- connect(this, SIGNAL(messageReceived(const QByteArray &, const QMqttTopicName &)),
- this, SLOT(onReceived(const QByteArray &, const QMqttTopicName &)));
- connect(this, SIGNAL(messageSent(qint32)), this, SLOT(onPublished(qint32)));
- connect(this, SIGNAL(errorChanged(ClientError)),
- this, SLOT(onError(ClientError)));
- connect(this, SIGNAL(stateChanged(ClientState)),
- this, SLOT(onStateChanged(ClientState)));
-
- connect(&m_timer, SIGNAL(timeout()), this, SLOT(onConnectTimeout()));
- m_timer.start(TIMER_PERIOD_MS);
- }
-
- MQTTClient::~MQTTClient() {
- }
-
- /*
- * the QMqttClient doesn't handle auto-reconnection.
- * It can stay in the connecting state for ever, even
- * if the server is back on.
- */
- void MQTTClient::onConnectTimeout(void)
- {
- switch (state()) {
- case Connecting:
- qDebug() << "force to disconnect";
- disconnectFromHost();
- /* fall through */
- case Disconnected:
- qDebug() << "re-try do connect";
- connectToHost();
- break;
- case Connected:
- break;
- }
- }
-
- void MQTTClient::onStateChanged(ClientState state)
- {
- qDebug() << "mqtt state: ";
-
- switch (state) {
- case Disconnected:
- qDebug() << "disconnected";
- break;
- case Connecting:
- qDebug() << "Connecting";
- break;
- case Connected:
- qDebug() << "Connected";
- break;
- }
- }
-
- void MQTTClient::onError(ClientError error)
- {
- qDebug() << "mqtt error " << error;
- /* TODO */
- switch (error) {
- case NoError: break;
- case InvalidProtocolVersion: break;
- case IdRejected: break;
- case ServerUnavailable: break;
- case BadUsernameOrPassword: break;
- case NotAuthorized: break;
- case TransportInvalid: break;
- case ProtocolViolation: break;
- case UnknownError: break;
- default: break;
- }
- }
-
- void MQTTClient::onConnected()
- {
- qDebug() << "subscribe";
- this->subscribe(QString("sensors/#"), 1);
- }
-
- void MQTTClient::onReceived(const QByteArray &message, const QMqttTopicName &topic)
- {
- Settings *s = Settings::getInstance();
- QJsonDocument sensorData;
- QJsonValue val;
-
- qDebug() << "publish received: \"" << QString::fromUtf8(message)
- << "\"" << " from: " << topic.name();
-
- for (int i = 0; i < s->nbZones(); ++i) {
- if (s->m_rooms.at(i).sensor_topic == topic.name()) {
- qDebug() << "this is for us !";
- sensorData = QJsonDocument::fromJson(message);
- if (!sensorData.isObject()) {
- qWarning() << "malformed JSON data";
- goto out;
- }
- QJsonObject obj(sensorData.object());
- val = obj["temperature"];
- if (val.isDouble()) {
- emit new_temperature(i, val.toDouble());
- qDebug() << val.toDouble();
- }
-
- val = obj["humidity"];
- if (val.isDouble()) {
- emit new_hygro(i, val.toDouble());
- qDebug() << val.toDouble();
- }
-
- val = obj["battery"];
- if (val.isDouble()) {
- emit new_battery(i, val.toDouble());
- qDebug() << val.toDouble();
- }
-
- break;
- }
-
- if (s->m_rooms.at(i).availability_topic == topic.name()) {
-
- emit new_availability(i, message == QString("online").toUtf8());
- }
- }
- out:
- return;
- }
-
- void MQTTClient::onPublished(qint32 msgid)
- {
- qDebug() << "published id " << msgid;
- }
-
- void MQTTClient::onDisconnected(void)
- {
- /* TODO */
- qDebug() << "disconnected";
- }
-
- void MQTTClient::publish_msg(const QString& topic, const QString& payload)
- {
- qint32 msgid;
-
- msgid = this->publish(QMqttTopicName(topic), payload.toUtf8(), 1, true);
- if (msgid == -1) {
- qDebug() << "fail to publish message " << payload << " on " << topic;
- }
- }
-
- void MQTTClient::allHeatersOn(bool on) {
- Settings *s = Settings::getInstance();
-
- QString payload = on ? QString("1") : QString("0");
-
- for (int i = 0; i < s->nbZones(); i++) {
- const struct Room *r = &(s->m_rooms.at(i));
- for (int j = 0; j < r->heaters.count(); j++) {
- const struct Heater *h = &(r->heaters.at(j));
-
- publish_msg(h->ctrl_topic, payload);
- }
- }
- }
-
- /* vim: set tabstop=8 shiftwidth=8 softtabstop=0 noexpandtab: */
|