#include "mqttsensorsource.h" #include MqttSensorSource::MqttSensorSource(QObject *parent) : QObject{parent} { } void MqttSensorSource::start(std::shared_ptr client, const QJsonObject& settings) { this->client = client; connect(client->getClient().get(), &QMqttClient::stateChanged, this, &MqttSensorSource::onClientStateChanged); QJsonArray sensorsArray = settings["Sensors"].toArray(); for(QJsonValueRef sensorRef : sensorsArray) { QJsonObject sensorObject = sensorRef.toObject(); if(!sensorObject.contains("Topic")) continue; SensorSubscription sensor; sensor.topic = sensorObject["Topic"].toString(); if(!sensorObject.contains("Name")) sensor.name = sensor.topic; else sensor.name = sensorObject["Name"].toString(); sensor.id = qHash(client->getBaseTopic() + "/" + sensor.topic); sensors.push_back(sensor); } } MqttSensorSource::SensorSubscription& MqttSensorSource::findSubscription(const QString& topic) { for(SensorSubscription& sensor : sensors) { if(client->getBaseTopic() + "/" + sensor.topic == topic) return sensor; } assert(false); } void MqttSensorSource::onClientStateChanged(QMqttClient::ClientState state) { if(state == QMqttClient::ClientState::Connected) { for(SensorSubscription& sensor : sensors) { sensor.subscription = client->subscribe(client->getBaseTopic() + "/" + sensor.topic); connect(sensor.subscription->subscription, &QMqttSubscription::messageReceived, this, &MqttSensorSource::onMessageReceived); } } else if (state == QMqttClient::ClientState::Disconnected) { for(SensorSubscription& sensor : sensors) { if(sensor.subscription) { client->unsubscribe(client->getBaseTopic() + "/" + sensor.topic); sensor.subscription = nullptr; } } } } void MqttSensorSource::onMessageReceived(const QMqttMessage& message) { Sensor sensor; SensorSubscription& sensorSub = findSubscription(message.topic().name()); QString baseName = sensorSub.name; sensor.id = sensorSub.id; sensor.updateSeen(); QJsonDocument doc = QJsonDocument::fromJson(message.payload()); if(doc.isObject()) { QJsonObject obj = doc.object(); if(obj.contains("temperature")) { sensor.name = baseName + " Temperature"; sensor.type = Sensor::TYPE_TEMPERATURE; sensor.field = obj["temperature"].toDouble(0); 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"; sensor.type = Sensor::TYPE_HUMIDITY; sensor.field = obj["humidity"].toDouble(0); stateChanged(sensor); } if(obj.contains("illuminance")) { sensor.name = baseName + " Illuminance"; sensor.type = Sensor::TYPE_BRIGHTNESS; sensor.field = obj["illuminance"].toDouble(0); stateChanged(sensor); } if(obj.contains("presence")) { sensor.name = baseName + " Presence"; sensor.type = Sensor::TYPE_OCUPANCY; sensor.field = obj["presence"].toBool() ? 1 : 0; stateChanged(sensor); } if(obj.contains("co2")) { sensor.name = baseName + " co2"; sensor.type = Sensor::TYPE_CO2; sensor.field = obj["co2"].toDouble(0); stateChanged(sensor); } if(obj.contains("formaldehyd")) { sensor.name = baseName + " Formaldehyd"; sensor.type = Sensor::TYPE_FORMALDEHYD; sensor.field = obj["formaldehyd"].toDouble(0); stateChanged(sensor); } if(obj.contains("pm25")) { sensor.name = baseName + " pm25"; sensor.type = Sensor::TYPE_PM25; sensor.field = obj["pm25"].toDouble(0); stateChanged(sensor); } if(obj.contains("voc")) { sensor.name = baseName + " VOC"; sensor.type = Sensor::TYPE_TOTAL_VOC; sensor.field = obj["voc"].toDouble(0); stateChanged(sensor); } } } void MqttSensorSource::store(QJsonObject& json) { QJsonArray sensorsArray; for(const SensorSubscription& sensor : sensors) { QJsonObject sensorObject; sensorObject["Name"] = sensor.name; sensorObject["Topic"] = sensor.topic; sensorsArray.append(sensorObject); } json["Sensors"] = sensorsArray; } MqttSensorSource::~MqttSensorSource() { for(SensorSubscription& sub : sensors) client->unsubscribe(client->getBaseTopic() + "/" + sub.topic); }