#include "mqttitem.h" #include #include #include #include "mqttclient.h" #include "programmode.h" MqttItem::MqttItem(QString name, uint8_t value, QObject *parent) : Item(0, name, value, parent), topic_(""), valueKey_("state"), valueOn_("ON"), valueOff_("OFF") { hashId(); std::shared_ptr workClient = client.lock(); assert(workClient || programMode == PROGRAM_MODE_UI_ONLY); if(workClient) connect(workClient->getClient().get(), &QMqttClient::stateChanged, this, &MqttItem::onClientStateChanged); } MqttItem::~MqttItem() { qDebug()<<__func__; std::shared_ptr workClient = client.lock(); if(!workClient || topic_.isEmpty() || !subscription) return; workClient->unsubscribe(subscription); } void MqttItem::onClientStateChanged(QMqttClient::ClientState state) { if(state == QMqttClient::Connected) refreshSubscription(); } void MqttItem::refreshSubscription() { std::shared_ptr workClient = client.lock(); if(!workClient || topic_.isEmpty()) return; if(workClient->getClient()->state() != QMqttClient::Connected) return; if(subscription) { disconnect(subscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onMessageReceived); workClient->unsubscribe(subscription); } subscription = workClient->subscribe(workClient->getBaseTopic() + "/" + getTopic()); connect(subscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onMessageReceived); } void MqttItem::onMessageReceived(const QMqttMessage& message) { QJsonDocument doc = QJsonDocument::fromJson(message.payload()); if(doc.isObject()) { QJsonObject obj = doc.object(); if(obj.contains(getValueKey())) { QString value = obj[getValueKey()].toString(); ItemUpdateRequest req = createValueUpdateRequest(ITEM_UPDATE_BACKEND); req.changes.value = true; if(value == getValueOn()) req.payload.setValueData(true); else req.payload.setValueData(false); requestUpdate(req); } } } void MqttItem::hashId() { QString hashString = topic_ + "/" + valueKey_; itemId_ = qHash(hashString.toLatin1()); } void MqttItem::setTopic(const QString& topic) { topic_ = topic; hashId(); refreshSubscription(); } void MqttItem::setValueKey(const QString& valueKey) { valueKey_ = valueKey; hashId(); } void MqttItem::setValueOn(const QString& valueOn) { valueOn_ = valueOn; } void MqttItem::setValueOff(const QString& valueOff) { valueOff_ = valueOff; } QString MqttItem::getTopic() const { return topic_; } QString MqttItem::getValueKey() const { return valueKey_; } QString MqttItem::getValueOn() const { return valueOn_; } QString MqttItem::getValueOff() const { return valueOff_; } void MqttItem::store(QJsonObject& json) { Item::store(json); json["Type"] = "Mqtt"; json["Topic"] = topic_; json["ValueKey"] = valueKey_; json["ValueOn"] = valueOn_; json["ValueOff"] = valueOff_; } void MqttItem::load(const QJsonObject& json, const bool preserve) { Item::load(json, preserve); topic_ = json["Topic"].toString(); valueKey_ = json["ValueKey"].toString("state"); valueOn_ = json["ValueOn"].toString("ON"); valueOff_ = json["ValueOff"].toString("OFF"); hashId(); refreshSubscription(); } void MqttItem::enactValue(uint8_t value) { std::shared_ptr workClient = client.lock(); if(!workClient || topic_.isEmpty()) return; QString fullTopic = workClient->getBaseTopic() + "/" + topic_ + "/set"; QJsonObject payload; payload[valueKey_] = value ? valueOn_ : valueOff_; QJsonDocument doc(payload); QByteArray data = doc.toJson(QJsonDocument::Compact); qDebug() << "MqttItem publishing to" << fullTopic << ":" << data; workClient->getClient()->publish(fullTopic, data); }