UvosSmartHomeInterface/src/sensors/mqttsensorsource.cpp

171 lines
4.3 KiB
C++

#include "mqttsensorsource.h"
#include<QJsonArray>
MqttSensorSource::MqttSensorSource(QObject *parent)
: QObject{parent}
{
}
void MqttSensorSource::start(std::shared_ptr<MqttClient> 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);
}