Add Mqtt item

This commit is contained in:
Carl Philipp Klemm 2026-04-12 18:06:19 +02:00
parent 0fd50eb227
commit eb60f85604
19 changed files with 901 additions and 48 deletions

164
src/items/mqttitem.cpp Normal file
View file

@ -0,0 +1,164 @@
#include "mqttitem.h"
#include <QJsonObject>
#include <QJsonDocument>
#include <QtMqtt/QMqttClient>
#include "mqttclient.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<MqttClient> workClient = client.lock();
assert(workClient);
connect(workClient->getClient().get(), &QMqttClient::stateChanged, this, &MqttItem::onClientStateChanged);
}
MqttItem::~MqttItem()
{
qDebug()<<__func__;
std::shared_ptr<MqttClient> 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<MqttClient> 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<MqttClient> 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);
}