// SPDX-License-Identifier: GPL-3.0-or-later /* * Qt mutizone MQTT thermostat * * Copyright (C) 2019 Richard Genoud * */ #include #include #include #include #include "mqttclient.h" #include "settings.h" #include "qmqtt.h" MQTTClient::MQTTClient(const QHostAddress& host, const quint16 port, QObject* parent) : QMQTT::Client(host, port, parent) { connect(this, SIGNAL(connected(void)), this, SLOT(onConnected(void))); connect(this, SIGNAL(subscribed(const QString&)), this, SLOT(onSubscribed(const QString&))); connect(this, SIGNAL(received(const QMQTT::Message&)), this, SLOT(onReceived(const QMQTT::Message&))); connect(this, SIGNAL(published(const QMQTT::Message&, quint16)), this, SLOT(onPublished(const QMQTT::Message&, quint16))); connect(this, SIGNAL(error(const QMQTT::ClientError)), this, SLOT(onError(const QMQTT::ClientError))); /* * 2 more signals: * void unsubscribed(const QString& topic); * void disconnected(void); * void pingresp(); */ } MQTTClient::~MQTTClient() { } void MQTTClient::onError(const QMQTT::ClientError error) { qDebug() << "error" << error; } void MQTTClient::onConnected() { qDebug() << "connected"; this->subscribe("sensors/#", 1); } void MQTTClient::onSubscribed(const QString& topic) { qDebug() << "subscribed " << topic; } void MQTTClient::onReceived(const QMQTT::Message& message) { Settings *s = Settings::getInstance(); QJsonDocument sensorData; QJsonValue val; qDebug() << "publish received: \"" << QString::fromUtf8(message.payload()) << "\"" << " from: " << message.topic(); for (int i = 0; i < s->nbZones(); ++i) { if (s->m_rooms.at(i).sensor_topic == message.topic()) { qDebug() << "this is for us !"; sensorData = QJsonDocument::fromJson(message.payload()); 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 == message.topic()) { emit new_availability(i, message.payload() == QString("online").toUtf8()); } } out: return; } void MQTTClient::onPublished(const QMQTT::Message& message, quint16 msgid) { qDebug() << "published" << msgid << " topic: " << message.topic() << "payload" << QString::fromUtf8(message.payload()); } void MQTTClient::onDisconnected(void) { qDebug() << "disconnected"; } void MQTTClient::publish_msg(const QString& topic, const QString& payload) { // id is automatically incremented if ==0 and QoS>0 // DUP: if a message is resent, it should have the DUP flag QMQTT::Message message(0, topic, payload.toUtf8(), 1, true, false); publish(message); } 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)); /* TODO: check if connected */ publish_msg(h->ctrl_topic, payload); } } } /* vim: set tabstop=8 shiftwidth=8 softtabstop=0 noexpandtab: */