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

View file

@ -7,22 +7,11 @@ MqttSensorSource::MqttSensorSource(QObject *parent)
{
}
void MqttSensorSource::start(const QJsonObject& settings)
void MqttSensorSource::start(std::shared_ptr<MqttClient> client, const QJsonObject& settings)
{
baseTopicName = settings["BaseTopic"].toString("zigbee2mqtt");
this->client = client;
connect(&client, &QMqttClient::stateChanged, this, &MqttSensorSource::onClientStateChanged);
connect(&client, &QMqttClient::errorChanged, this, &MqttSensorSource::onClientError);
client.setHostname(settings["Host"].toString("127.0.0.1"));
client.setPort(settings["Port"].toInt(1883));
if(settings.contains("User"))
client.setUsername(settings["User"].toString());
if(settings.contains("Password"))
client.setPassword(settings["Password"].toString());
client.setProtocolVersion(QMqttClient::MQTT_5_0);
client.connectToHost();
connect(client->getClient().get(), &QMqttClient::stateChanged, this, &MqttSensorSource::onClientStateChanged);
QJsonArray sensorsArray = settings["Sensors"].toArray();
@ -37,21 +26,16 @@ void MqttSensorSource::start(const QJsonObject& settings)
sensor.name = sensor.topic;
else
sensor.name = sensorObject["Name"].toString();
sensor.id = qHash(baseTopicName + "/" + sensor.topic);
sensor.id = qHash(client->getBaseTopic() + "/" + sensor.topic);
sensors.push_back(sensor);
}
}
void MqttSensorSource::onClientError(QMqttClient::ClientError error)
{
qWarning()<<"MQTT Client error:"<<error;
}
MqttSensorSource::SensorSubscription& MqttSensorSource::findSubscription(const QString& topic)
{
for(SensorSubscription& sensor : sensors)
{
if(baseTopicName + "/" + sensor.topic == topic)
if(client->getBaseTopic() + "/" + sensor.topic == topic)
return sensor;
}
assert(false);
@ -61,30 +45,24 @@ void MqttSensorSource::onClientStateChanged(QMqttClient::ClientState state)
{
if(state == QMqttClient::ClientState::Connected)
{
qInfo()<<"Connected to MQTT broker at "<<client.hostname()<<client.port();
for(SensorSubscription& sensor : sensors)
{
qDebug()<<"MQTT subscribeing to"<<baseTopicName + "/" + sensor.topic;
sensor.subscription = client.subscribe(baseTopicName + "/" + sensor.topic);
connect(sensor.subscription, &QMqttSubscription::messageReceived, this, &MqttSensorSource::onMessageReceived);
qDebug()<<"MQTT subscribeing to"<<client->getBaseTopic() + "/" + sensor.topic;
sensor.subscription = client->subscribe(client->getBaseTopic() + "/" + sensor.topic);
connect(sensor.subscription->subscription, &QMqttSubscription::messageReceived, this, &MqttSensorSource::onMessageReceived);
}
}
else if (state == QMqttClient::ClientState::Disconnected)
{
qWarning()<<"Lost connection to MQTT broker";
for(SensorSubscription& sensor : sensors)
{
if(sensor.subscription)
{
client.unsubscribe(sensor.topic);
client->unsubscribe(sensor.topic);
sensor.subscription = nullptr;
}
}
}
else if(state == QMqttClient::ClientState::Connecting)
{
qInfo()<<"Connecting to MQTT broker at "<<client.hostname()<<client.port();
}
}
void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
@ -107,6 +85,14 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
stateChanged(sensor);
}
if(obj.contains("local_temperature"))
{
sensor.name = baseName + " Temperature";
sensor.type = Sensor::TYPE_TEMPERATURE;
sensor.field = obj["local_temperature"].toDouble(0);
stateChanged(sensor);
}
if(obj.contains("humidity"))
{
sensor.name = baseName + " Humidity";
@ -167,13 +153,6 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
void MqttSensorSource::store(QJsonObject& json)
{
json["Host"] = client.hostname();
json["Port"] = client.port();
json["BaseTopic"] = baseTopicName;
if(client.username() != "")
json["User"] = client.username();
if(client.password() != "")
json["Password"] = client.password();
QJsonArray sensorsArray;
for(const SensorSubscription& sensor : sensors)
{
@ -185,3 +164,9 @@ void MqttSensorSource::store(QJsonObject& json)
json["Sensors"] = sensorsArray;
}
MqttSensorSource::~MqttSensorSource()
{
for(SensorSubscription& sub : sensors)
client->unsubscribe(sub.topic);
}

View file

@ -7,6 +7,7 @@
#include <vector>
#include "sensor.h"
#include "mqttclient.h"
class MqttSensorSource : public QObject
{
@ -17,12 +18,11 @@ class MqttSensorSource : public QObject
uint64_t id;
QString topic;
QString name;
QMqttSubscription* subscription = nullptr;
MqttClient::Subscription* subscription = nullptr;
};
QString baseTopicName;
std::vector<SensorSubscription> sensors;
QMqttClient client;
std::shared_ptr<MqttClient> client;
private:
SensorSubscription& findSubscription(const QString& topic);
@ -30,11 +30,11 @@ private:
private slots:
void onClientStateChanged(QMqttClient::ClientState state);
void onMessageReceived(const QMqttMessage& message);
void onClientError(QMqttClient::ClientError error);
public:
explicit MqttSensorSource(QObject *parent = nullptr);
void start(const QJsonObject& settings);
~MqttSensorSource();
void start(std::shared_ptr<MqttClient> client, const QJsonObject& settings);
void store(QJsonObject& json);
signals: