diff --git a/CMakeLists.txt b/CMakeLists.txt index fdf32b7..5990efc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,8 @@ add_executable(smartvos src/ui/itemsettingsdialog.cpp src/ui/actorsettingsdialog.h src/ui/actorsettingsdialog.cpp + src/ui/sensorsettingsdialog.h + src/ui/sensorsettingsdialog.cpp src/ui/actorwidgets/factoractorwidget.h src/ui/actorwidgets/factoractorwidget.cpp @@ -181,6 +183,7 @@ target_sources(smartvos src/ui/itemcreationdialog.ui src/ui/itemsettingsdialog.ui src/ui/actorsettingsdialog.ui + src/ui/sensorsettingsdialog.ui src/ui/actorwidgets/factoractorwidget.ui src/ui/actorwidgets/polynomalactorwidget.ui src/ui/actorwidgets/sensoractorwidget.ui 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/item.cpp b/src/items/item.cpp index 14d31b3..0ff8cd5 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -58,9 +58,9 @@ void ItemData::storeWithChanges(QJsonObject& json, const ItemFieldChanges& chang json["Name"] = name_; if(changes.value) json["Value"] = static_cast(value_); - if(changes.groupName) + if(changes.groupName && !groupName_.isEmpty() && groupName_ != "All") json["GroupName"] = groupName_; - if(changes.valueNames) + if(changes.valueNames && !valueNames_.empty()) { QJsonArray valueNamesArray; for(const QString& name : valueNames_) @@ -218,31 +218,37 @@ void Item::store(QJsonObject &json) { ItemData::store(json); json["override"] = override_; - QJsonArray actorsArray; - for(size_t i = 0; i < actors_.size(); ++i) + if(!actors_.empty()) { - if(!actors_[i]->isExausted()) + QJsonArray actorsArray; + for(size_t i = 0; i < actors_.size(); ++i) { - QJsonObject actorObject; - actors_[i]->store(actorObject); - actorsArray.append(actorObject); + if(!actors_[i]->isExausted()) + { + QJsonObject actorObject; + actors_[i]->store(actorObject); + actorsArray.append(actorObject); + } } + json["Actors"] = actorsArray; } - json["Actors"] = actorsArray; } void Item::load(const QJsonObject &json, const bool preserve) { ItemData::load(json, preserve); override_ = json["override"].toBool(false); - const QJsonArray actorsArray(json["Actors"].toArray(QJsonArray())); - for(int i = 0; i < actorsArray.size(); ++i) + if(json.contains("Actors")) { - if(actorsArray[i].isObject()) + const QJsonArray actorsArray(json["Actors"].toArray(QJsonArray())); + for(int i = 0; i < actorsArray.size(); ++i) { - std::shared_ptr actor = Actor::loadActor(actorsArray[i].toObject()); - if(actor != nullptr) - addActor(actor); + if(actorsArray[i].isObject()) + { + std::shared_ptr actor = Actor::loadActor(actorsArray[i].toObject()); + if(actor != nullptr) + addActor(actor); + } } } } diff --git a/src/items/itemloadersource.cpp b/src/items/itemloadersource.cpp index e2d1e68..b689a3c 100644 --- a/src/items/itemloadersource.cpp +++ b/src/items/itemloadersource.cpp @@ -26,6 +26,8 @@ void ItemLoaderSource::refresh() request.type = ITEM_UPDATE_LOADED; request.payload = newItem; request.changes = ItemFieldChanges(true); + if(newItem->hasActors()) + request.changes.actors = true; request.changes.value = false; itemAddRequests.push_back(request); } diff --git a/src/items/mqttitem.cpp b/src/items/mqttitem.cpp index 9c2ea78..da91bef 100644 --- a/src/items/mqttitem.cpp +++ b/src/items/mqttitem.cpp @@ -101,6 +101,7 @@ void MqttItem::onDevicesMessageReceived(const QMqttMessage& message) { loadExposeFromDevice(device); exposeLoaded_ = true; + Q_EMIT exposeLoaded(); // Unsubscribe from devices topic since we found our device std::shared_ptr workClient = client.lock(); @@ -293,6 +294,30 @@ void MqttItem::setFromExpose(const QJsonObject& expose) hashId(); } +void MqttItem::triggerExposeLookup() +{ + if(exposeLoaded_) + return; + + std::shared_ptr workClient = client.lock(); + if(!workClient) + return; + + // Reset expose loaded flag to allow re-detection + exposeLoaded_ = false; + + // Subscribe to bridge/devices + if(devicesSubscription) + { + disconnect(devicesSubscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onDevicesMessageReceived); + workClient->unsubscribe(devicesSubscription); + devicesSubscription = nullptr; + } + + devicesSubscription = workClient->subscribe(workClient->getBaseTopic() + "/bridge/devices"); + connect(devicesSubscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onDevicesMessageReceived); +} + QString MqttItem::getTopic() const { return topic_; diff --git a/src/items/mqttitem.h b/src/items/mqttitem.h index f31203c..b0248a2 100644 --- a/src/items/mqttitem.h +++ b/src/items/mqttitem.h @@ -9,6 +9,9 @@ class QString; class MqttItem : public Item { Q_OBJECT +Q_SIGNALS: + void exposeLoaded(); + public: inline static std::weak_ptr client; @@ -51,6 +54,9 @@ public: // Configure from Zigbee2MQTT expose info void setFromExpose(const QJsonObject& expose); + // Trigger expose lookup from bridge/devices + void triggerExposeLookup(); + QString getTopic() const; QString getValueKey() const; QString getValueOn() const; diff --git a/src/items/poweritem.cpp b/src/items/poweritem.cpp index aec7642..d37e233 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)); + globalSensors.sensorGotState(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)); + globalSensors.sensorGotState(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..1d50e90 100644 --- a/src/items/poweritem.h +++ b/src/items/poweritem.h @@ -12,8 +12,7 @@ class PowerItem: public Item 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/main.cpp b/src/main.cpp index 722f6ed..31356f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,17 +14,14 @@ int main(int argc, char *argv[]) { - QApplication a(argc, argv); - - //pw_init(&argc, &argv); - - //set info QCoreApplication::setOrganizationName("UVOS"); QCoreApplication::setOrganizationDomain("uvos.xyz"); QCoreApplication::setApplicationName("SHinterface"); QCoreApplication::setApplicationVersion("0.6"); - QDir::setCurrent(a.applicationDirPath()); + QStringList args; + for(int i = 0; i < argc; ++i) + args<load(uiSettings); + QObject::connect(&mainObject.micro, SIGNAL(textRecived(QString)), w, SLOT(changeHeaderLableText(QString))); QObject::connect(&mainObject.micro, SIGNAL(textRecived(QString)), w, SLOT(changeHeaderLableText(QString))); QObject::connect(w, &MainWindow::sigSetRgb, &mainObject.micro, &Microcontroller::changeRgbColor); @@ -118,7 +127,15 @@ int main(int argc, char *argv[]) QObject::connect(w, &MainWindow::createdItem, &globalItems, &ItemStore::addItem); w->show(); } - retVal = a.exec(); + + retVal = a->exec(); + + if(programMode != PROGRAM_MODE_HEADLESS_PRIMARY) + { + QJsonObject uiSettingsJson; + w->store(uiSettingsJson); + MainObject::storeJsonObjectToDisk(uiSettingsPath, uiSettingsJson); + } delete w; delete microDevice; @@ -127,13 +144,23 @@ int main(int argc, char *argv[]) { SecondaryMainObject mainObject(parser.value(hostOption), parser.value(portOption).toInt()); MainWindow w(&mainObject); + QJsonObject uiSettings = MainObject::getJsonObjectFromDisk(uiSettingsPath); + w.load(uiSettings); + QObject::connect(&w, &MainWindow::createdItem, &globalItems, &ItemStore::addItem); QObject::connect(&w, &MainWindow::sigSave, mainObject.tcpClient, &TcpClient::sendItems); + w.show(); - retVal = a.exec(); + retVal = a->exec(); + + QJsonObject uiSettingsJson; + w.store(uiSettingsJson); + MainObject::storeJsonObjectToDisk(uiSettingsPath, uiSettingsJson); } + delete a; + return retVal; } diff --git a/src/mainobject.cpp b/src/mainobject.cpp index aeb90de..103c8de 100644 --- a/src/mainobject.cpp +++ b/src/mainobject.cpp @@ -22,6 +22,11 @@ void MainObject::refresh() globalItems.refresh(); } +void MainObject::addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload) +{ + // Default implementation does nothing - derived classes override +} + QJsonObject MainObject::getJsonObjectFromDisk(const QString& filename, bool* error) { QFile file; @@ -89,8 +94,8 @@ PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, const QString& sett connect(&sunSensorSource, &SunSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState); connect(µ, &Microcontroller::gotSensorState, &globalSensors, &SensorStore::sensorGotState); connect(&mqttSensorSource, &MqttSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState); - - sunSensorSource.run(); + connect(tcpServer, &TcpServer::sensorAdded, &mqttSensorSource, &MqttSensorSource::onSensorAdded); + connect(webServer, &WebSocketServer::sensorAdded, &mqttSensorSource, &MqttSensorSource::onSensorAdded); globalItems.registerItemSource(&fixedItems); globalItems.registerItemSource(tcpServer); @@ -102,6 +107,8 @@ PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, const QString& sett loadFromDisk(settingsPath); + sunSensorSource.run(); + QJsonObject mqttJson = settings["Mqtt"].toObject(); mqttClient->start(mqttJson); mqttSensorSource.start(mqttClient, mqttJson); @@ -120,6 +127,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 +138,7 @@ void PrimaryMainObject::load(const QJsonObject& json) { settings = json; itemLoader.updateJson(json); + globalSensors.load(json); globalItems.clear(); globalItems.refresh(); } @@ -172,3 +181,8 @@ SecondaryMainObject::~SecondaryMainObject() { } +void SecondaryMainObject::addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload) +{ + tcpClient->addSensor(sensor, backend, payload); +} + diff --git a/src/mainobject.h b/src/mainobject.h index 5552c6f..405a7c3 100644 --- a/src/mainobject.h +++ b/src/mainobject.h @@ -33,6 +33,7 @@ public: public slots: void refresh(); + virtual void addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload = {}); }; class PrimaryMainObject : public MainObject @@ -74,6 +75,7 @@ public: public: explicit SecondaryMainObject(QString host, int port, QObject *parent = nullptr); ~SecondaryMainObject(); + void addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload = {}) override; }; 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..9dab556 100644 --- a/src/sensors/mqttsensorsource.cpp +++ b/src/sensors/mqttsensorsource.cpp @@ -31,6 +31,25 @@ void MqttSensorSource::start(std::shared_ptr client, const QJsonObje } } +void MqttSensorSource::addSensor(const QString& topic, const QString& name) +{ + if(!client) + return; + + SensorSubscription sensor; + sensor.topic = topic; + sensor.name = name; + sensor.id = qHash(client->getBaseTopic() + "/" + topic); + sensors.push_back(sensor); + + // Subscribe if already connected + if(client->getClient()->state() == QMqttClient::ClientState::Connected) + { + sensor.subscription = client->subscribe(client->getBaseTopic() + "/" + topic); + connect(sensor.subscription->subscription, &QMqttSubscription::messageReceived, this, &MqttSensorSource::onMessageReceived); + } +} + MqttSensorSource::SensorSubscription& MqttSensorSource::findSubscription(const QString& topic) { for(SensorSubscription& sensor : sensors) @@ -39,6 +58,7 @@ MqttSensorSource::SensorSubscription& MqttSensorSource::findSubscription(const Q return sensor; } assert(false); + return sensors.front(); } void MqttSensorSource::onClientStateChanged(QMqttClient::ClientState state) @@ -81,7 +101,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 +109,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 +117,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 +125,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 +133,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 +141,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 +149,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 +157,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 +165,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 +173,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 +181,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 +189,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); } } } @@ -193,3 +213,16 @@ MqttSensorSource::~MqttSensorSource() client->unsubscribe(client->getBaseTopic() + "/" + sub.topic); } +void MqttSensorSource::onSensorAdded(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload) +{ + if(backend != Sensor::BACKEND_MQTT) + return; + + QString topic = payload["Topic"].toString(); + QString name = payload["Name"].toString(); + if(topic.isEmpty()) + return; + + addSensor(topic, name); +} + diff --git a/src/sensors/mqttsensorsource.h b/src/sensors/mqttsensorsource.h index c726d70..f0736d8 100644 --- a/src/sensors/mqttsensorsource.h +++ b/src/sensors/mqttsensorsource.h @@ -31,14 +31,18 @@ private slots: void onClientStateChanged(QMqttClient::ClientState state); void onMessageReceived(const QMqttMessage& message); +public slots: + void onSensorAdded(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload); + public: explicit MqttSensorSource(QObject *parent = nullptr); ~MqttSensorSource(); void start(std::shared_ptr client, const QJsonObject& settings); + void addSensor(const QString& topic, const QString& name); 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..de07db4 100644 --- a/src/sensors/sensor.cpp +++ b/src/sensors/sensor.cpp @@ -1,6 +1,7 @@ #include "sensor.h" #include +#include SensorStore globalSensors; @@ -10,28 +11,115 @@ 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())); + } +} + +std::vector SensorStore::allGroups() const +{ + std::vector groups; + for(const Sensor& sensor : sensors_) + { + if(!sensor.groupName.isEmpty()) + { + bool found = false; + for(const QString& group : groups) + { + if(group == sensor.groupName) + { + found = true; + break; + } + } + if(!found) + groups.push_back(sensor.groupName); + } + } + return groups; +} + +void SensorStore::sensorGotState(const Sensor& sensor, sensor_update_type_t type) +{ + bool inSensors = false; + + qDebug()<<"Sensor update for id"<