Support different Sensor update types

This commit is contained in:
Carl Philipp Klemm 2026-04-21 16:31:13 +02:00
parent ff07551a59
commit 09f7e55b4e
20 changed files with 258 additions and 41 deletions

View file

@ -39,6 +39,7 @@ MqttSensorSource::SensorSubscription& MqttSensorSource::findSubscription(const Q
return sensor;
}
assert(false);
return sensors.front();
}
void MqttSensorSource::onClientStateChanged(QMqttClient::ClientState state)
@ -81,7 +82,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " Temperature";
sensor.type = Sensor::TYPE_TEMPERATURE;
sensor.field = obj["temperature"].toDouble(0);
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
if(obj.contains("local_temperature"))
@ -89,7 +90,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " Temperature";
sensor.type = Sensor::TYPE_TEMPERATURE;
sensor.field = obj["local_temperature"].toDouble(0);
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
if(obj.contains("humidity"))
@ -97,7 +98,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " Humidity";
sensor.type = Sensor::TYPE_HUMIDITY;
sensor.field = obj["humidity"].toDouble(0);
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
if(obj.contains("illuminance"))
@ -105,7 +106,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " Illuminance";
sensor.type = Sensor::TYPE_BRIGHTNESS;
sensor.field = obj["illuminance"].toDouble(0);
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
if(obj.contains("presence"))
@ -113,7 +114,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " Presence";
sensor.type = Sensor::TYPE_OCUPANCY;
sensor.field = obj["presence"].toBool() ? 1 : 0;
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
if(obj.contains("co2"))
@ -121,7 +122,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " co2";
sensor.type = Sensor::TYPE_CO2;
sensor.field = obj["co2"].toDouble(0);
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
if(obj.contains("formaldehyd"))
@ -129,7 +130,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " Formaldehyd";
sensor.type = Sensor::TYPE_FORMALDEHYD;
sensor.field = obj["formaldehyd"].toDouble(0);
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
if(obj.contains("pm25"))
@ -137,7 +138,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " pm25";
sensor.type = Sensor::TYPE_PM25;
sensor.field = obj["pm25"].toDouble(0);
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
if(obj.contains("voc"))
@ -145,7 +146,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " VOC";
sensor.type = Sensor::TYPE_TOTAL_VOC;
sensor.field = obj["voc"].toDouble(0);
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
if(obj.contains("power"))
@ -153,7 +154,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " Power";
sensor.type = Sensor::TYPE_POWER;
sensor.field = obj["power"].toDouble(0);
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
if(obj.contains("energy"))
@ -161,7 +162,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " Energy";
sensor.type = Sensor::TYPE_ENERGY_USE;
sensor.field = obj["energy"].toDouble(0);
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
if(obj.contains("voltage"))
@ -169,7 +170,7 @@ void MqttSensorSource::onMessageReceived(const QMqttMessage& message)
sensor.name = baseName + " Voltage";
sensor.type = Sensor::TYPE_VOLTAGE;
sensor.field = obj["voltage"].toDouble(0);
stateChanged(sensor);
stateChanged(sensor, SENSOR_UPDATE_BACKEND);
}
}
}

View file

@ -38,7 +38,7 @@ public:
void store(QJsonObject& json);
signals:
void stateChanged(Sensor sensor);
void stateChanged(Sensor sensor, sensor_update_type_t type = SENSOR_UPDATE_BACKEND);
};
#endif // MQTTSENSORSOURCE_H

View file

@ -1,6 +1,7 @@
#include "sensor.h"
#include <QDebug>
#include <QJsonArray>
SensorStore globalSensors;
@ -10,9 +11,31 @@ SensorStore::SensorStore(QObject *parent): QObject(parent)
sensors_.push_back(Sensor(Sensor::TYPE_DOOR,0,0,"Bedroom door"));
}
void SensorStore::sensorGotState(const Sensor& sensor)
void SensorStore::store(QJsonObject& json)
{
bool exsisting = false;
QJsonArray sensorsArray;
for(const Sensor& sensor : sensors_)
{
QJsonObject sensorObject;
sensor.store(sensorObject);
sensorsArray.append(sensorObject);
}
json["Sensors"] = sensorsArray;
}
void SensorStore::load(const QJsonObject& json)
{
knownSensors_.clear();
QJsonArray sensorsArray = json["Sensors"].toArray();
for(const QJsonValue& value : sensorsArray)
{
knownSensors_.push_back(Sensor(value.toObject()));
}
}
void SensorStore::sensorGotState(const Sensor& sensor, sensor_update_type_t type)
{
bool inSensors = false;
for(unsigned i = 0; i < sensors_.size(); ++i)
{
if(sensor.type == sensors_[i].type && sensor.id == sensors_[i].id)
@ -21,17 +44,43 @@ void SensorStore::sensorGotState(const Sensor& sensor)
if(sensors_[i].field != sensor.field)
{
sensors_[i].field = sensor.field;
sensorChangedState(sensor);
if(type == SENSOR_UPDATE_USER)
{
sensors_[i].name = sensor.name;
sensors_[i].hidden = sensor.hidden;
// Also update knownSensors_
for(Sensor& known : knownSensors_)
{
if(sensor.type == known.type && sensor.id == known.id)
{
known.name = sensor.name;
known.hidden = sensor.hidden;
break;
}
}
}
sensorChangedState(sensors_[i], type);
stateChenged(sensors_);
}
exsisting = true;
inSensors = true;
break;
}
}
if(!exsisting)
if(!inSensors)
{
sensors_.push_back(sensor);
sensorChangedState(sensor);
Sensor newSensor = sensor;
// Check knownSensors_ for matching sensor to override name and hidden state
for(const Sensor& known : knownSensors_)
{
if(sensor.type == known.type && sensor.id == known.id)
{
newSensor.name = known.name;
newSensor.hidden = known.hidden;
break;
}
}
sensors_.push_back(newSensor);
sensorChangedState(newSensor, type);
stateChenged(sensors_);
}

View file

@ -98,7 +98,7 @@ public:
QString::number((type == Sensor::TYPE_HUMIDITY || type == Sensor::TYPE_TEMPERATURE) ? field*10 : field) +
" TIME: " + QString::number(lastSeen.toSecsSinceEpoch());
}
inline void store(QJsonObject& json)
inline void store(QJsonObject& json) const
{
json["Type"] = "Sensor";
json["SensorType"] = static_cast<int>(type);
@ -127,7 +127,7 @@ public:
name = "Shutdown Imminent";
else name = "Sensor Type " + QString::number(type) + " Id " + QString::number(id);
}
QString getUnit()
QString getUnit() const
{
switch(type)
{
@ -160,11 +160,19 @@ public:
}
};
typedef enum {
SENSOR_UPDATE_USER = 0,
SENSOR_UPDATE_BACKEND,
SENSOR_UPDATE_REMOTE,
SENSOR_UPDATE_INVALID
} sensor_update_type_t;
class SensorStore: public QObject
{
Q_OBJECT
private:
std::vector<Sensor> sensors_;
std::vector<Sensor> knownSensors_;
public:
@ -176,15 +184,17 @@ public:
return &sensors_;
}
void store(QJsonObject& json);
void load(const QJsonObject& json);
public slots:
void sensorGotState(const Sensor& sensor);
void sensorGotState(const Sensor& sensor, sensor_update_type_t type = SENSOR_UPDATE_BACKEND);
signals:
void stateChenged(std::vector<Sensor> sensors);
void sensorChangedState(Sensor sensor);
void sensorChangedState(Sensor sensor, sensor_update_type_t type);
void sensorDeleted(Sensor sensor);
};

View file

@ -21,5 +21,5 @@ void SunSensorSource::abort()
void SunSensorSource::doTick()
{
stateChanged(Sensor(Sensor::TYPE_SUN_ALTITUDE, 0, static_cast<float>(sun_.altitude())));
stateChanged(Sensor(Sensor::TYPE_SUN_ALTITUDE, 0, static_cast<float>(sun_.altitude())), SENSOR_UPDATE_BACKEND);
}

View file

@ -22,7 +22,7 @@ public slots:
void abort();
signals:
void stateChanged(Sensor sensor);
void stateChanged(Sensor sensor, sensor_update_type_t type = SENSOR_UPDATE_BACKEND);
private slots:
void doTick();