diff --git a/src/actors/polynomalactor.cpp b/src/actors/polynomalactor.cpp index cc783fd..3f115f0 100644 --- a/src/actors/polynomalactor.cpp +++ b/src/actors/polynomalactor.cpp @@ -31,7 +31,7 @@ void PolynomalActor::getCoeffiancts( double& pow3, double& pow2, double& pow1, d pow0=pow0_; } -void PolynomalActor::sensorEvent(Sensor sensor) +void PolynomalActor::sensorEvent(Sensor sensor, sensor_update_type_t type) { if(active && sensor == sensor_) { diff --git a/src/actors/polynomalactor.h b/src/actors/polynomalactor.h index 1ff3675..7f1f54b 100644 --- a/src/actors/polynomalactor.h +++ b/src/actors/polynomalactor.h @@ -18,7 +18,7 @@ private: public slots: - void sensorEvent(Sensor sensor); + void sensorEvent(Sensor sensor, sensor_update_type_t type); public: diff --git a/src/actors/regulator.cpp b/src/actors/regulator.cpp index 94f8bb6..7ec2bb5 100644 --- a/src/actors/regulator.cpp +++ b/src/actors/regulator.cpp @@ -21,7 +21,7 @@ void Regulator::setSensor(const Sensor sensor) sensor_ = sensor; } -void Regulator::sensorEvent(Sensor sensor) +void Regulator::sensorEvent(Sensor sensor, sensor_update_type_t type) { if(active && sensor == sensor_) { diff --git a/src/actors/regulator.h b/src/actors/regulator.h index 339b2ca..a1b3a5a 100644 --- a/src/actors/regulator.h +++ b/src/actors/regulator.h @@ -26,7 +26,7 @@ private slots: public slots: - void sensorEvent(Sensor sensor); + void sensorEvent(Sensor sensor, sensor_update_type_t type); void setSensor(const Sensor sensor); void setPoint(float setPoint ); diff --git a/src/actors/sensoractor.cpp b/src/actors/sensoractor.cpp index 758b761..5e083ef 100644 --- a/src/actors/sensoractor.cpp +++ b/src/actors/sensoractor.cpp @@ -17,7 +17,7 @@ void SensorActor::setSensor(const Sensor sensor) sensor_ = sensor; } -void SensorActor::sensorEvent(Sensor sensor) +void SensorActor::sensorEvent(Sensor sensor, sensor_update_type_t type) { if(sensor == sensor_) { diff --git a/src/actors/sensoractor.h b/src/actors/sensoractor.h index 27a9355..99e2865 100644 --- a/src/actors/sensoractor.h +++ b/src/actors/sensoractor.h @@ -18,7 +18,7 @@ private: public slots: - void sensorEvent(Sensor sensor); + void sensorEvent(Sensor sensor, sensor_update_type_t type); void setSloap(uint8_t sloap); void setSensor(const Sensor sensor); diff --git a/src/items/poweritem.cpp b/src/items/poweritem.cpp index aec7642..743c456 100644 --- a/src/items/poweritem.cpp +++ b/src/items/poweritem.cpp @@ -6,7 +6,7 @@ PowerItem::PowerItem(uint32_t itemIdIn, QString name, uint8_t value, QObject* parent): Item(itemIdIn, name, value, parent) { - stateChanged(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 0, "Shutdown Imminent", true)); + stateChanged(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 0, "Shutdown Imminent", true), SENSOR_UPDATE_BACKEND); value_ = true; hidden_ = true; type_ = ITEM_VALUE_NO_VALUE; @@ -18,7 +18,7 @@ void PowerItem::enactValue(uint8_t value) { qDebug()<<"shutdown"; QTimer::singleShot(5000, this, &PowerItem::timeout); - stateChanged(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 1, "Shutdown Imminent", true)); + stateChanged(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 1, "Shutdown Imminent", true), SENSOR_UPDATE_BACKEND); } } diff --git a/src/items/poweritem.h b/src/items/poweritem.h index d6a610f..216927e 100644 --- a/src/items/poweritem.h +++ b/src/items/poweritem.h @@ -13,7 +13,7 @@ private: signals: - void stateChanged(Sensor sensor); + void stateChanged(Sensor sensor, sensor_update_type_t type = SENSOR_UPDATE_BACKEND); private slots: void timeout(); diff --git a/src/mainobject.cpp b/src/mainobject.cpp index aeb90de..ce227f4 100644 --- a/src/mainobject.cpp +++ b/src/mainobject.cpp @@ -120,6 +120,7 @@ PrimaryMainObject::~PrimaryMainObject() void PrimaryMainObject::store(QJsonObject &json) { globalItems.store(json); + globalSensors.store(json); QJsonObject mqttJson = json["Mqtt"].toObject(); mqttClient->store(mqttJson); mqttSensorSource.store(mqttJson); @@ -130,6 +131,7 @@ void PrimaryMainObject::load(const QJsonObject& json) { settings = json; itemLoader.updateJson(json); + globalSensors.load(json); globalItems.clear(); globalItems.refresh(); } diff --git a/src/microcontroller.cpp b/src/microcontroller.cpp index 8005278..2a766b5 100644 --- a/src/microcontroller.cpp +++ b/src/microcontroller.cpp @@ -190,7 +190,7 @@ void Microcontroller::processSensorState(const QString& buffer) { Sensor sensor = Sensor::sensorFromString(buffer); if(sensor.type != Sensor::TYPE_DUMMY) - gotSensorState(sensor); + gotSensorState(sensor, SENSOR_UPDATE_BACKEND); } diff --git a/src/microcontroller.h b/src/microcontroller.h index c6d56bf..fc5d805 100644 --- a/src/microcontroller.h +++ b/src/microcontroller.h @@ -78,7 +78,7 @@ private slots: signals: void textRecived(const QString string); - void gotSensorState(Sensor sensor); + void gotSensorState(Sensor sensor, sensor_update_type_t type = SENSOR_UPDATE_BACKEND); }; #endif // MICROCONTROLLER_H diff --git a/src/sensors/mqttsensorsource.cpp b/src/sensors/mqttsensorsource.cpp index eaa23e1..737068f 100644 --- a/src/sensors/mqttsensorsource.cpp +++ b/src/sensors/mqttsensorsource.cpp @@ -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); } } } diff --git a/src/sensors/mqttsensorsource.h b/src/sensors/mqttsensorsource.h index c726d70..e863418 100644 --- a/src/sensors/mqttsensorsource.h +++ b/src/sensors/mqttsensorsource.h @@ -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 diff --git a/src/sensors/sensor.cpp b/src/sensors/sensor.cpp index 576d1db..3f19e37 100644 --- a/src/sensors/sensor.cpp +++ b/src/sensors/sensor.cpp @@ -1,6 +1,7 @@ #include "sensor.h" #include +#include 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_); } diff --git a/src/sensors/sensor.h b/src/sensors/sensor.h index d24090a..e181088 100644 --- a/src/sensors/sensor.h +++ b/src/sensors/sensor.h @@ -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(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 sensors_; + std::vector 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 sensors); - void sensorChangedState(Sensor sensor); + void sensorChangedState(Sensor sensor, sensor_update_type_t type); void sensorDeleted(Sensor sensor); }; diff --git a/src/sensors/sunsensor.cpp b/src/sensors/sunsensor.cpp index 37a1c9b..c1c0366 100644 --- a/src/sensors/sunsensor.cpp +++ b/src/sensors/sunsensor.cpp @@ -21,5 +21,5 @@ void SunSensorSource::abort() void SunSensorSource::doTick() { - stateChanged(Sensor(Sensor::TYPE_SUN_ALTITUDE, 0, static_cast(sun_.altitude()))); + stateChanged(Sensor(Sensor::TYPE_SUN_ALTITUDE, 0, static_cast(sun_.altitude())), SENSOR_UPDATE_BACKEND); } diff --git a/src/sensors/sunsensor.h b/src/sensors/sunsensor.h index 65d84c3..8c0c35d 100644 --- a/src/sensors/sunsensor.h +++ b/src/sensors/sunsensor.h @@ -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(); diff --git a/src/service/service.cpp b/src/service/service.cpp index a43a313..4d55b16 100644 --- a/src/service/service.cpp +++ b/src/service/service.cpp @@ -19,7 +19,7 @@ QJsonObject Service::createMessage(const QString& type, const QJsonArray& data) return json; } -void Service::sensorEvent(Sensor sensor) +void Service::sensorEvent(Sensor sensor, sensor_update_type_t type) { QJsonArray sensors; QJsonObject sensorjson; @@ -85,7 +85,7 @@ void Service::processIncomeingJson(const QByteArray& jsonbytes) { QJsonObject jsonobject = sensorjson.toObject(); Sensor sensor(jsonobject); - gotSensor(sensor); + gotSensor(sensor, SENSOR_UPDATE_REMOTE); } } } diff --git a/src/service/service.h b/src/service/service.h index 32dba33..3b09e52 100644 --- a/src/service/service.h +++ b/src/service/service.h @@ -20,10 +20,10 @@ protected: } client_state_t; signals: - void gotSensor(Sensor sensor); + void gotSensor(Sensor sensor, sensor_update_type_t type = SENSOR_UPDATE_BACKEND); public slots: - void sensorEvent(Sensor sensor); + void sensorEvent(Sensor sensor, sensor_update_type_t type); virtual void itemUpdated(ItemUpdateRequest update); virtual void refresh() override; diff --git a/tests/unit/sensors/test_sensor.cpp b/tests/unit/sensors/test_sensor.cpp index 7ff4505..d77d792 100644 --- a/tests/unit/sensors/test_sensor.cpp +++ b/tests/unit/sensors/test_sensor.cpp @@ -219,6 +219,161 @@ private slots: QVERIFY(audio.type == Sensor::TYPE_AUDIO_OUTPUT); } + void testSensorStoreUserUpdateUpdatesNameAndHidden() + { + // Create a SensorStore + SensorStore store; + store.getSensors()->clear(); + + // Add initial sensor + Sensor initialSensor(Sensor::TYPE_TEMPERATURE, 1, 20.0, "Initial Name", false); + store.sensorGotState(initialSensor, SENSOR_UPDATE_BACKEND); + + // Verify initial state + std::vector* sensors = store.getSensors(); + QVERIFY(sensors->size() == 1); + QVERIFY(sensors->at(0).name == "Initial Name"); + QVERIFY(sensors->at(0).hidden == false); + + // Send USER update with new name and hidden state + Sensor userUpdate(Sensor::TYPE_TEMPERATURE, 1, 25.0, "New Name", true); + store.sensorGotState(userUpdate, SENSOR_UPDATE_USER); + + // Verify name and hidden were updated + QVERIFY(sensors->size() == 1); + QVERIFY(sensors->at(0).name == "New Name"); + QVERIFY(sensors->at(0).hidden == true); + QVERIFY(sensors->at(0).field == 25.0); + } + + void testSensorStoreNonUserUpdateIgnoresNameAndHidden() + { + // Create a SensorStore + SensorStore store; + store.getSensors()->clear(); + + // Add initial sensor + Sensor initialSensor(Sensor::TYPE_TEMPERATURE, 1, 20.0, "Initial Name", false); + store.sensorGotState(initialSensor, SENSOR_UPDATE_BACKEND); + + // Verify initial state + std::vector* sensors = store.getSensors(); + QVERIFY(sensors->size() == 1); + QVERIFY(sensors->at(0).name == "Initial Name"); + QVERIFY(sensors->at(0).hidden == false); + + // Send BACKEND update with new name and hidden state + Sensor backendUpdate(Sensor::TYPE_TEMPERATURE, 1, 25.0, "Backend Name", true); + store.sensorGotState(backendUpdate, SENSOR_UPDATE_BACKEND); + + // Verify name and hidden were NOT updated + QVERIFY(sensors->size() == 1); + QVERIFY(sensors->at(0).name == "Initial Name"); + QVERIFY(sensors->at(0).hidden == false); + QVERIFY(sensors->at(0).field == 25.0); + } + + void testSensorStoreUserUpdateUpdatesKnownSensors() + { + // Create a SensorStore + SensorStore store; + store.getSensors()->clear(); + + // Add initial sensor + Sensor initialSensor(Sensor::TYPE_TEMPERATURE, 1, 20.0, "Initial Name", false); + store.sensorGotState(initialSensor, SENSOR_UPDATE_BACKEND); + + // Send USER update with new name and hidden state + Sensor userUpdate(Sensor::TYPE_TEMPERATURE, 1, 25.0, "New Name", true); + store.sensorGotState(userUpdate, SENSOR_UPDATE_USER); + + // Store to JSON and reload + QJsonObject json; + store.store(json); + + SensorStore store2; + store2.getSensors()->clear(); + store2.load(json); + + // Add the sensor again - should use the updated name from knownSensors_ + Sensor newSensor(Sensor::TYPE_TEMPERATURE, 1, 30.0, "Original Name", false); + store2.sensorGotState(newSensor, SENSOR_UPDATE_BACKEND); + + // Verify the name was taken from knownSensors_ + std::vector* sensors = store2.getSensors(); + QVERIFY(sensors->size() == 1); + QVERIFY(sensors->at(0).name == "New Name"); + QVERIFY(sensors->at(0).hidden == true); + } + + void testSensorStoreNewSensorNotInKnownSensors() + { + // Create a SensorStore + SensorStore store; + store.getSensors()->clear(); + + // Add a new sensor (not in knownSensors_) + Sensor newSensor(Sensor::TYPE_TEMPERATURE, 99, 25.0, "New Sensor Name", true); + store.sensorGotState(newSensor, SENSOR_UPDATE_BACKEND); + + // Verify sensor was added with its original name + std::vector* sensors = store.getSensors(); + QVERIFY(sensors->size() == 1); + QVERIFY(sensors->at(0).name == "New Sensor Name"); + QVERIFY(sensors->at(0).hidden == true); + } + + void testSensorStoreNewSensorInKnownSensors() + { + // Create a SensorStore + SensorStore store; + store.getSensors()->clear(); + + // Load known sensors + QJsonObject json; + QJsonArray sensorsArray; + QJsonObject knownSensor; + knownSensor["SensorType"] = Sensor::TYPE_TEMPERATURE; + knownSensor["Id"] = 99; + knownSensor["Name"] = "Known Sensor Name"; + knownSensor["Hidden"] = true; + sensorsArray.append(knownSensor); + json["Sensors"] = sensorsArray; + store.load(json); + + // Add a new sensor that matches knownSensors_ + Sensor newSensor(Sensor::TYPE_TEMPERATURE, 99, 25.0, "Original Name", false); + store.sensorGotState(newSensor, SENSOR_UPDATE_BACKEND); + + // Verify name was overridden from knownSensors_ + std::vector* sensors = store.getSensors(); + QVERIFY(sensors->size() == 1); + QVERIFY(sensors->at(0).name == "Known Sensor Name"); + QVERIFY(sensors->at(0).hidden == true); + } + + void testSensorStoreRemoteUpdateIgnored() + { + // Create a SensorStore + SensorStore store; + store.getSensors()->clear(); + + // Add initial sensor + Sensor initialSensor(Sensor::TYPE_TEMPERATURE, 1, 20.0, "Initial Name", false); + store.sensorGotState(initialSensor, SENSOR_UPDATE_BACKEND); + + // Send REMOTE update with new name and hidden state + Sensor remoteUpdate(Sensor::TYPE_TEMPERATURE, 1, 25.0, "Remote Name", true); + store.sensorGotState(remoteUpdate, SENSOR_UPDATE_REMOTE); + + // Verify name and hidden were NOT updated + std::vector* sensors = store.getSensors(); + QVERIFY(sensors->size() == 1); + QVERIFY(sensors->at(0).name == "Initial Name"); + QVERIFY(sensors->at(0).hidden == false); + QVERIFY(sensors->at(0).field == 25.0); + } + void cleanupTestCase() { // Cleanup after all tests