From 8fcca909de8476a1dbaaf76ad3ffbb7be7ea7253 Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Sat, 7 Feb 2026 18:31:34 +0100 Subject: [PATCH 1/7] Remove alarmactions --- SHinterface.pro | 2 - src/actor.cpp.autosave | 100 ---------------------------------- src/alarmactions.cpp | 15 ----- src/alarmactions.h | 25 --------- src/ui/itemsettingsdialog.cpp | 2 +- 5 files changed, 1 insertion(+), 143 deletions(-) delete mode 100644 src/actor.cpp.autosave delete mode 100644 src/alarmactions.cpp delete mode 100644 src/alarmactions.h diff --git a/SHinterface.pro b/SHinterface.pro index c7ff09f..054b25e 100644 --- a/SHinterface.pro +++ b/SHinterface.pro @@ -73,7 +73,6 @@ SOURCES += \ src/items/rgbitem.cpp SOURCES += \ - src/alarmactions.cpp \ src/main.cpp \ src/microcontroller.cpp \ src/sun.cpp @@ -129,7 +128,6 @@ HEADERS += \ src/items/rgbitem.h HEADERS += \ - src/alarmactions.h \ src/microcontroller.h \ src/sun.h diff --git a/src/actor.cpp.autosave b/src/actor.cpp.autosave deleted file mode 100644 index 72a0dd4..0000000 --- a/src/actor.cpp.autosave +++ /dev/null @@ -1,100 +0,0 @@ -#include "actor.h" -#include - -Actor::Actor(QObject *parent): QObject(parent) -{ - buildName(); -} - -Actor::~Actor() -{ - -} - -void Actor::performAction() -{ - if(active) - { - trigger(); - if(action_ == ACTION_OFF) off(); - else if(action_ == ACTION_ON) on(); - else if(action_ != ACTION_TOGGLE) toggle(); - else if(action_ != ACTION_VALUE) sigValue(value_); - } -} - -void Actor::makeActive() -{ - active = true; -} - - -void Actor::makeInactive() -{ - active = false; -} - -void Actor::buildName() -{ - name = "Actor"; - appendActionToName(); -} - -void Actor::appendActionToName() -{ - if(action_ == ACTION_OFF || action_ == ACTION_DEFAULT ) name.append("off"); - else if(action_ == ACTION_ON ) name.append("on"); - else if(action_ == ACTION_TOGGLE ) name.append("toggle"); - else if(action_ == ACTION_VALUE ) name.append("value to " + QString::number(value_)); -} - -void Actor::setActive(int state) -{ - state ? makeActive() : makeInactive(); - buildName(); -} - -bool Actor::isActive() -{ - return active; -} - -bool Actor::isExausted() -{ - return exausted; -} - -void Actor::saveSettings(QString subsecton, QSettings* settings) -{ - settings->setValue(subsecton + "Active", active); - settings->setValue(subsecton + "Exausted", exausted); - settings->setValue(subsecton + "Name", name); - settings->setValue(subsecton + "Action", action_); -} - -void Actor::loadSettings(QString subsecton, QSettings* settings) -{ - active = settings->value(subsecton + "Active").toBool(); - exausted = settings->value(subsecton + "Exausted").toBool(); - name = settings->value(subsecton + "Name").toString(); - action_ = settings->value(subsecton + "Action").toUInt(); -} - -void Actor::setAction(uint8_t action) -{ - action_ = action; - qDebug()<<"setting action to "< - -AlarmActions::AlarmActions(QApplication* a, Microcontroller* micro, QObject *parent) : QObject(parent), _micro(micro), - a_(a) -{ - -} - -void AlarmActions::syncoff() -{ - qDebug()<<"syncoff"; - QProcess::execute ("syncoff", QStringList()); - a_->exit(0); -} diff --git a/src/alarmactions.h b/src/alarmactions.h deleted file mode 100644 index 2922e9d..0000000 --- a/src/alarmactions.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef POWER_H -#define POWER_H - -#include -#include "microcontroller.h" - -class AlarmActions : public QObject -{ -private: - Q_OBJECT - Microcontroller* _micro; - QApplication* a_; - -public: - explicit AlarmActions(QApplication* a, Microcontroller* micro, QObject *parent = nullptr); - -signals: - -public slots: - - void syncoff(); - -}; - -#endif // POWER_H diff --git a/src/ui/itemsettingsdialog.cpp b/src/ui/itemsettingsdialog.cpp index 1bf371c..23d4f4d 100644 --- a/src/ui/itemsettingsdialog.cpp +++ b/src/ui/itemsettingsdialog.cpp @@ -177,7 +177,7 @@ void ItemSettingsDialog::editActor() dialog->show(); dialog->exec(); - for(int i = 0; i < ui->tableWidget->rowCount() && i < static_cast(item_->getActors().size()); ++i) + for(int i = 0; i < ui->tableWidget->rowCount() && i < static_cast(item_->getActors().size()); ++i) { ui->tableWidget->item(i, 0)->setText(item_->getActors()[i]->getName()); ui->tableWidget->item(i, 1)->setText(item_->getActors()[i]->actionName()); From cbeb8d49a7ef19d391ae0c034feed25784dbab3a Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Sat, 7 Feb 2026 18:53:31 +0100 Subject: [PATCH 2/7] Port to qt6 --- SHinterface.pro | 2 +- src/actors/actor.h | 2 +- src/actors/polynomalactor.h | 2 +- src/actors/regulator.h | 2 +- src/actors/sensoractor.h | 2 +- src/items/auxitem.h | 2 +- src/items/itemstore.h | 2 +- src/items/messageitem.cpp | 18 ++++++++++-------- src/items/messageitem.h | 6 ++---- src/items/poweritem.h | 4 ++-- src/items/relay.h | 2 +- src/items/rgbitem.h | 2 +- src/items/systemitem.h | 1 - src/sensors/sunsensor.h | 2 +- src/ui/actorwidgets/alarmwidget.ui | 10 +++++----- src/ui/actorwidgets/polynomalactorwidget.ui | 2 +- src/ui/actorwidgets/regulatorwdiget.ui | 2 +- src/ui/actorwidgets/sensoractorwidget.ui | 2 +- src/ui/mainwindow.ui | 20 ++++++++++---------- src/ui/sensorlistwidget.h | 2 +- 20 files changed, 43 insertions(+), 44 deletions(-) diff --git a/SHinterface.pro b/SHinterface.pro index 054b25e..55a7b33 100644 --- a/SHinterface.pro +++ b/SHinterface.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui widgets network multimedia +QT += core gui widgets network multimedia httpserver QT += serialport diff --git a/src/actors/actor.h b/src/actors/actor.h index 2e99f4c..4cdb048 100644 --- a/src/actors/actor.h +++ b/src/actors/actor.h @@ -5,7 +5,7 @@ #include #include -#include "../items/item.h" +#include "src/items/item.h" class Actor : public Item { diff --git a/src/actors/polynomalactor.h b/src/actors/polynomalactor.h index d91f2ba..9c4d64f 100644 --- a/src/actors/polynomalactor.h +++ b/src/actors/polynomalactor.h @@ -1,7 +1,7 @@ #ifndef POLYNOMALACTOR_H #define POLYNOMALACTOR_H #include "actor.h" -#include "../sensors/sensor.h" +#include "src/sensors/sensor.h" class PolynomalActor: public Actor { diff --git a/src/actors/regulator.h b/src/actors/regulator.h index 733d643..f4588b2 100644 --- a/src/actors/regulator.h +++ b/src/actors/regulator.h @@ -3,7 +3,7 @@ #include #include "actor.h" -#include "../sensors/sensor.h" +#include "src/sensors/sensor.h" class Regulator : public Actor { diff --git a/src/actors/sensoractor.h b/src/actors/sensoractor.h index 720146e..6499dbe 100644 --- a/src/actors/sensoractor.h +++ b/src/actors/sensoractor.h @@ -1,6 +1,6 @@ #pragma once #include "actor.h" -#include "../sensors/sensor.h" +#include "src/sensors/sensor.h" class SensorActor : public Actor { diff --git a/src/items/auxitem.h b/src/items/auxitem.h index 512144f..b9347f9 100644 --- a/src/items/auxitem.h +++ b/src/items/auxitem.h @@ -1,7 +1,7 @@ #pragma once #include "item.h" -#include "../microcontroller.h" +#include "src/microcontroller.h" class AuxItem: public Item { diff --git a/src/items/itemstore.h b/src/items/itemstore.h index 44d8fd6..4ee9651 100644 --- a/src/items/itemstore.h +++ b/src/items/itemstore.h @@ -2,7 +2,7 @@ #include #include #include "item.h" -#include "../sensors/sensor.h" +#include "src/sensors/sensor.h" #include diff --git a/src/items/messageitem.cpp b/src/items/messageitem.cpp index 0174586..0f51c53 100644 --- a/src/items/messageitem.cpp +++ b/src/items/messageitem.cpp @@ -1,20 +1,18 @@ #include "messageitem.h" #include -#include - -BroadCast* MessageItem::broadCast = nullptr; +#include MessageItem::MessageItem(uint32_t itemIdIn, QString name, uint8_t value, QObject *parent): Item(itemIdIn, name, value, parent) { - + alertSound.setVolume(1.0); } MessageItem::MessageItem(const ItemData& itemData, QObject *parent): Item(itemData, parent) { - + alertSound.setVolume(1.0); } MessageItem::~MessageItem() @@ -27,8 +25,8 @@ void MessageItem::setValue(uint8_t value) Item::setValue(value); if(value && !messageBox_) { - if(broadCast) broadCast->sendMessage(name_, message_); - if(!alertSoundFileName.isEmpty()) QSound::play(alertSoundFileName); + if(!alertSoundFileName.isEmpty()) + alertSound.play(); messageBox_ = new QMessageBox(QMessageBox::NoIcon, name_, message_); messageBox_->setModal(false); connect(messageBox_, &QMessageBox::finished, this, &MessageItem::closeMessageBox); @@ -60,6 +58,7 @@ QString MessageItem::getAlert() void MessageItem::setAlert(const QString &in) { alertSoundFileName = in; + alertSound.setSource(QUrl::fromLocalFile(alertSoundFileName)); } void MessageItem::setMessage(const QString& in) @@ -77,7 +76,8 @@ void MessageItem::store(QJsonObject &json) json["Type"] = "Message"; Item::store(json); json["Message"] = message_; - if(!alertSoundFileName.isEmpty()) json["Alert"] = alertSoundFileName; + if(!alertSoundFileName.isEmpty()) + json["Alert"] = alertSoundFileName; } void MessageItem::load(const QJsonObject &json, const bool preserve) @@ -85,4 +85,6 @@ void MessageItem::load(const QJsonObject &json, const bool preserve) Item::load(json,preserve); message_ = json["Message"].toString("Invalid Message"); alertSoundFileName = json["Alert"].toString(""); + if(!alertSoundFileName.isEmpty()) + alertSound.setSource(QUrl::fromLocalFile(alertSoundFileName)); } diff --git a/src/items/messageitem.h b/src/items/messageitem.h index fadeda6..8b503c1 100644 --- a/src/items/messageitem.h +++ b/src/items/messageitem.h @@ -2,9 +2,9 @@ #define MESSAGEITEM_H #include +#include #include "item.h" -#include "../broadcast.h" class MessageItem : public Item { @@ -14,9 +14,7 @@ private: QString message_; QMessageBox* messageBox_ = nullptr; QString alertSoundFileName = ""; - -public: - static BroadCast* broadCast; + QSoundEffect alertSound; private slots: diff --git a/src/items/poweritem.h b/src/items/poweritem.h index dd13629..ff1f263 100644 --- a/src/items/poweritem.h +++ b/src/items/poweritem.h @@ -1,8 +1,8 @@ #pragma once #include "item.h" -#include "../sensors/sensor.h" -#include "../microcontroller.h" +#include "src/sensors/sensor.h" +#include "src/microcontroller.h" #include diff --git a/src/items/relay.h b/src/items/relay.h index 0ba4849..f0ae640 100644 --- a/src/items/relay.h +++ b/src/items/relay.h @@ -4,7 +4,7 @@ #include #include -#include "../sensors/sensor.h" +#include "src/sensors/sensor.h" #include "item.h" class Microcontroller; diff --git a/src/items/rgbitem.h b/src/items/rgbitem.h index 9aff188..a503406 100644 --- a/src/items/rgbitem.h +++ b/src/items/rgbitem.h @@ -1,6 +1,6 @@ #pragma once -#include "../microcontroller.h" +#include "src/microcontroller.h" #include "item.h" class RgbItem: public Item diff --git a/src/items/systemitem.h b/src/items/systemitem.h index 9fe7a11..778780a 100644 --- a/src/items/systemitem.h +++ b/src/items/systemitem.h @@ -1,7 +1,6 @@ #ifndef SYSTEMITEM_H #define SYSTEMITEM_H - #include "item.h" class SystemItem : public Item diff --git a/src/sensors/sunsensor.h b/src/sensors/sunsensor.h index bfbce04..dfb9a87 100644 --- a/src/sensors/sunsensor.h +++ b/src/sensors/sunsensor.h @@ -2,7 +2,7 @@ #include -#include "../sun.h" +#include "src/sun.h" #include "sensor.h" diff --git a/src/ui/actorwidgets/alarmwidget.ui b/src/ui/actorwidgets/alarmwidget.ui index 1b29275..3b99187 100644 --- a/src/ui/actorwidgets/alarmwidget.ui +++ b/src/ui/actorwidgets/alarmwidget.ui @@ -24,16 +24,16 @@ - QFormLayout::AllNonFixedFieldsGrow + QFormLayout::FieldGrowthPolicy::AllNonFixedFieldsGrow - QFormLayout::DontWrapRows + QFormLayout::RowWrapPolicy::DontWrapRows - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop 50 @@ -57,7 +57,7 @@ false - QDateTimeEdit::DaySection + QDateTimeEdit::Section::DaySection dd.MM.yyyy hh:mm diff --git a/src/ui/actorwidgets/polynomalactorwidget.ui b/src/ui/actorwidgets/polynomalactorwidget.ui index e1733df..4cf9fb2 100644 --- a/src/ui/actorwidgets/polynomalactorwidget.ui +++ b/src/ui/actorwidgets/polynomalactorwidget.ui @@ -132,7 +132,7 @@ SensorListWidget QListView -
../src/ui/sensorlistwidget.h
+
src/ui/sensorlistwidget.h
diff --git a/src/ui/actorwidgets/regulatorwdiget.ui b/src/ui/actorwidgets/regulatorwdiget.ui index a6784a3..7365523 100644 --- a/src/ui/actorwidgets/regulatorwdiget.ui +++ b/src/ui/actorwidgets/regulatorwdiget.ui @@ -110,7 +110,7 @@ SensorListWidget QListView -
../src/ui/sensorlistwidget.h
+
src/ui/sensorlistwidget.h
diff --git a/src/ui/actorwidgets/sensoractorwidget.ui b/src/ui/actorwidgets/sensoractorwidget.ui index 8e9d967..f3fddd2 100644 --- a/src/ui/actorwidgets/sensoractorwidget.ui +++ b/src/ui/actorwidgets/sensoractorwidget.ui @@ -89,7 +89,7 @@ SensorListWidget QListView -
../src/ui/sensorlistwidget.h
+
src/ui/sensorlistwidget.h
diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui index c44b0e9..510daa8 100644 --- a/src/ui/mainwindow.ui +++ b/src/ui/mainwindow.ui @@ -37,7 +37,7 @@
- Qt::LeftToRight + Qt::LayoutDirection::LeftToRight false @@ -46,12 +46,12 @@ - Qt::Horizontal + Qt::Orientation::Horizontal false - + @@ -62,13 +62,13 @@ - QFrame::Box + QFrame::Shape::Box SHinterface - Qt::AutoText + Qt::TextFormat::AutoText @@ -99,7 +99,7 @@ - QAbstractItemView::NoSelection + QAbstractItemView::SelectionMode::NoSelection false @@ -156,7 +156,7 @@
- + @@ -224,7 +224,7 @@ - Qt::RightToLeft + Qt::LayoutDirection::RightToLeft Quit @@ -245,12 +245,12 @@ SensorListWidget QListView -
../src/ui/sensorlistwidget.h
+
src/ui/sensorlistwidget.h
ItemScrollBox QWidget -
../src/ui/itemscrollbox.h
+
src/ui/itemscrollbox.h
1
diff --git a/src/ui/sensorlistwidget.h b/src/ui/sensorlistwidget.h index c963a05..d87bd30 100644 --- a/src/ui/sensorlistwidget.h +++ b/src/ui/sensorlistwidget.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include "../sensors/sensor.h" +#include "src/sensors/sensor.h" class SensorListItem : public QTableWidgetItem { From 6d742e60db06af9c235b90cd54354b3b7a9a47c4 Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Sun, 1 Mar 2026 14:39:27 +0100 Subject: [PATCH 3/7] Major wip refactor Allow running without gui Remove serialPortMultiplexer broadcast use Add TcpServer and TcpClient Introduce the concept of an item source --- SHinterface.pro | 24 +-- src/actors/alarmtime.cpp | 6 +- src/items/auxitem.cpp | 3 +- src/items/auxitem.h | 7 +- src/items/item.cpp | 84 +++++++--- src/items/item.h | 21 +-- src/items/itemsource.cpp | 5 + src/items/itemsource.h | 24 +++ src/items/itemstore.cpp | 153 ++++++++++-------- src/items/itemstore.h | 22 ++- src/items/messageitem.cpp | 3 +- src/items/messageitem.h | 10 +- src/items/poweritem.cpp | 7 +- src/items/poweritem.h | 8 +- src/items/relay.cpp | 9 +- src/items/relay.h | 9 +- src/items/rgbitem.cpp | 3 +- src/items/rgbitem.h | 7 +- src/items/systemitem.cpp | 2 +- src/items/systemitem.h | 11 +- src/main.cpp | 219 ++++++++++++++++---------- src/mainobject.cpp | 209 ++++++++----------------- src/mainobject.h | 77 ++++----- src/microcontroller.cpp | 26 ++-- src/microcontroller.h | 11 +- src/programmode.cpp | 3 + src/programmode.h | 13 ++ src/sensors/ocupancysensor.cpp | 62 -------- src/sensors/ocupancysensor.h | 33 ---- src/sensors/pipewiresensor.cpp | 74 --------- src/sensors/pipewiresensor.h | 40 ----- src/sensors/sensor.h | 41 ++++- src/sensors/speakersensor.cpp | 59 ------- src/sensors/speakersensor.h | 45 ------ src/tcpserver.cpp | 277 +++++++++++++++++++++++++++++++++ src/tcpserver.h | 89 +++++++++++ src/ui/mainwindow.cpp | 44 ++---- src/ui/mainwindow.h | 13 +- 38 files changed, 928 insertions(+), 825 deletions(-) create mode 100644 src/items/itemsource.cpp create mode 100644 src/items/itemsource.h create mode 100644 src/programmode.cpp create mode 100644 src/programmode.h delete mode 100644 src/sensors/ocupancysensor.cpp delete mode 100644 src/sensors/ocupancysensor.h delete mode 100644 src/sensors/pipewiresensor.cpp delete mode 100644 src/sensors/pipewiresensor.h delete mode 100644 src/sensors/speakersensor.cpp delete mode 100644 src/sensors/speakersensor.h create mode 100644 src/tcpserver.cpp create mode 100644 src/tcpserver.h diff --git a/SHinterface.pro b/SHinterface.pro index 55a7b33..e2954c7 100644 --- a/SHinterface.pro +++ b/SHinterface.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui widgets network multimedia httpserver +QT += core gui widgets network multimedia QT += serialport @@ -26,7 +26,7 @@ QMAKE_CXXFLAGS += -std=c++17 -O2 SOURCES += \ src/actors/factoractor.cpp \ src/actors/polynomalactor.cpp \ - src/broadcast.cpp \ + src/tcpserver.cpp \ src/iomuliplexer.cpp \ src/items/messageitem.cpp \ src/items/systemitem.cpp \ @@ -61,27 +61,29 @@ SOURCES += \ SOURCES += \ src/sensors/sensor.cpp \ - src/sensors/speakersensor.cpp \ src/sensors/sunsensor.cpp \ - src/sensors/ocupancysensor.cpp SOURCES += \ src/items/relay.cpp \ src/items/item.cpp \ src/items/itemstore.cpp \ src/items/auxitem.cpp \ - src/items/rgbitem.cpp + src/items/rgbitem.cpp \ + src/items/itemsource.cpp SOURCES += \ src/main.cpp \ src/microcontroller.cpp \ - src/sun.cpp + src/sun.cpp \ + src/programmode.cpp HEADERS += \ src/actors/factoractor.h \ src/actors/polynomalactor.h \ - src/broadcast.h \ + src/items/itemsource.h \ + src/programmode.h \ + src/tcpserver.h \ src/iomuliplexer.h \ src/items/messageitem.h \ src/items/systemitem.h \ @@ -116,20 +118,20 @@ HEADERS += \ HEADERS += \ src/sensors/sensor.h \ - src/sensors/speakersensor.h \ src/sensors/sunsensor.h \ - src/sensors/ocupancysensor.h HEADERS += \ src/items/relay.h \ src/items/item.h \ src/items/itemstore.h \ src/items/auxitem.h \ - src/items/rgbitem.h + src/items/rgbitem.h \ + src/items/itemsource.h HEADERS += \ src/microcontroller.h \ - src/sun.h + src/sun.h \ + src/programmode.h FORMS += \ src/ui/actorwidgets/factoractorwidget.ui \ diff --git a/src/actors/alarmtime.cpp b/src/actors/alarmtime.cpp index ff26813..0f38f27 100644 --- a/src/actors/alarmtime.cpp +++ b/src/actors/alarmtime.cpp @@ -4,17 +4,17 @@ AlarmTime::AlarmTime(const QDateTime time, QObject *parent) : Actor(parent), tim { connect(&timer, SIGNAL(timeout()), this, SLOT(doTick())); timer.setInterval(1000); - run(); + AlarmTime::run(); } AlarmTime::~AlarmTime() { - makeInactive(); + AlarmTime::makeInactive(); } void AlarmTime::run() { - makeInactive(); + AlarmTime::makeInactive(); active = true; timer.start(); diff --git a/src/items/auxitem.cpp b/src/items/auxitem.cpp index 860a121..42f3efd 100644 --- a/src/items/auxitem.cpp +++ b/src/items/auxitem.cpp @@ -6,9 +6,8 @@ AuxItem::AuxItem(Microcontroller* micro, uint32_t itemIdIn, QString name, uint8 } -void AuxItem::setValue(uint8_t value) +void AuxItem::enactValue(uint8_t value) { - Item::setValue(value); micro_->setAuxPwm(value); } diff --git a/src/items/auxitem.h b/src/items/auxitem.h index b9347f9..0483c39 100644 --- a/src/items/auxitem.h +++ b/src/items/auxitem.h @@ -9,13 +9,12 @@ class AuxItem: public Item private: Microcontroller* micro_; -public slots: - - virtual void setValue(uint8_t value); +protected: + virtual void enactValue(uint8_t value) override; public: AuxItem(Microcontroller* micro, uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "", uint8_t value = 0, QObject* parent = nullptr); - virtual void store(QJsonObject& json); + virtual void store(QJsonObject& json) override; }; diff --git a/src/items/item.cpp b/src/items/item.cpp index 862834c..2596b4f 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -1,10 +1,12 @@ #include "item.h" +#include "src/actors/sensoractor.h" +#include "src/actors/regulator.h" +#include "src/actors/polynomalactor.h" +#include "src/programmode.h" #include "relay.h" -#include "../microcontroller.h" -#include "../actors/sensoractor.h" -#include "../actors/regulator.h" -#include "../actors/polynomalactor.h" +#include "messageitem.h" +#include "systemitem.h" #include @@ -33,11 +35,25 @@ uint32_t ItemData::id() const return itemId_; } +void ItemData::store(QJsonObject &json) +{ + json["Name"] = name_; + json["ItemId"] = static_cast(itemId_); + json["Value"] = static_cast(value_); +} + +void ItemData::load(const QJsonObject &json, const bool preserve) +{ + if(!preserve) + { + name_ = json["Name"].toString(name_); + itemId_ = static_cast(json["ItemId"].toDouble(0)); + } +} + //item -bool Item::secondaryFlag = false; - Item::Item(uint32_t itemIdIn, QString name, uint8_t value, QObject *parent): QObject(parent), ItemData (itemIdIn, name, value) { @@ -55,8 +71,7 @@ Item::~Item() void Item::store(QJsonObject &json) { - json["Name"] = name_; - json["ItemId"] = static_cast(itemId_); + ItemData::store(json); json["override"] = override_; QJsonArray actorsArray; for(size_t i = 0; i < actors_.size(); ++i) @@ -73,11 +88,7 @@ void Item::store(QJsonObject &json) void Item::load(const QJsonObject &json, const bool preserve) { - if(!preserve) - { - name_ = json["Name"].toString(name_); - itemId_ = static_cast(json["ItemId"].toDouble(0)); - } + ItemData::load(json, preserve); override_ = json["override"].toBool(false); const QJsonArray actorsArray(json["Actors"].toArray(QJsonArray())); for(int i = 0; i < actorsArray.size(); ++i) @@ -92,28 +103,35 @@ void Item::load(const QJsonObject &json, const bool preserve) void Item::actorSetValue(uint8_t value) { - if(!override_) setValue(value); + if(!override_ && (programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY)) + setValue(value); } void Item::setValue(uint8_t value) { - value_ = value; - valueChanged(value_); + informValue(value); + if(programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY) + enactValue(value); } void Item::informValue(uint8_t value) { - Item::setValue(value); + value_ = value; + valueChanged(value_); + updated(*this); +} + +void Item::enactValue(uint8_t value) +{ + (void)value; } void Item::addActor(std::shared_ptr actor) { actor->setParent(this); actors_.push_back(actor); - if(!secondaryFlag) - { + if(programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY) connect(actor.get(), &Actor::sigValue, this, &Item::actorSetValue); - } connect(this, &Item::valueChanged, actor.get(), &Actor::onValueChanged); std::shared_ptr sensorActor = std::dynamic_pointer_cast(actor); @@ -167,5 +185,29 @@ bool Item::hasActors() void Item::setActorsActive(bool in) { - for(unsigned i = 0; i < actors_.size(); i++) in ? actors_[i]->makeActive() : actors_[i]->makeInactive(); + for(unsigned i = 0; i < actors_.size(); i++) + in ? actors_[i]->makeActive() : actors_[i]->makeInactive(); +} + +std::shared_ptr Item::loadItem(const QJsonObject& json) +{ + std::shared_ptr newItem = nullptr; + if(json["Type"].toString("") == "Relay") + { + newItem = std::shared_ptr(new Relay); + } + else if(json["Type"].toString("") == "Message") + { + newItem = std::shared_ptr(new MessageItem); + } + else if(json["Type"].toString("") == "System") + { + newItem = std::shared_ptr(new SystemItem); + } + else if(json["Type"].toString("") == "Aux") + { + } + if(newItem) + newItem->load(json); + return newItem; } diff --git a/src/items/item.h b/src/items/item.h index 18aa0cc..bfa43f6 100644 --- a/src/items/item.h +++ b/src/items/item.h @@ -16,16 +16,15 @@ protected: uint32_t itemId_; public: - ItemData(uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "Item", uint8_t value = 0); inline bool operator==(const ItemData& in) const { - return itemId_==in.itemId_; + return itemId_ == in.itemId_; } inline bool operator!=(const ItemData& in) const { - return itemId_!=in.itemId_; + return itemId_ != in.itemId_; } uint32_t id() const; @@ -33,6 +32,8 @@ public: void setName(QString name); uint8_t getValue() const; virtual QString getName() const; + virtual void store(QJsonObject& json); + virtual void load(const QJsonObject& json, const bool preserve = false); }; @@ -44,20 +45,15 @@ private: bool override_ = false; -public: - - static bool secondaryFlag; - signals: - void valueChanged(uint8_t value); + void updated(ItemData data); private slots: virtual void actorSetValue(uint8_t value); public slots: - - virtual void setValue(uint8_t value); + void setValue(uint8_t value); public: @@ -80,5 +76,10 @@ public: virtual void store(QJsonObject& json); virtual void load(const QJsonObject& json, const bool preserve = false); + static std::shared_ptr loadItem(const QJsonObject& json); + +protected: + virtual void enactValue(uint8_t value); + }; diff --git a/src/items/itemsource.cpp b/src/items/itemsource.cpp new file mode 100644 index 0000000..1a223dc --- /dev/null +++ b/src/items/itemsource.cpp @@ -0,0 +1,5 @@ +#include "itemsource.h" + +ItemSource::ItemSource(QObject *parent) + : QObject{parent} +{} diff --git a/src/items/itemsource.h b/src/items/itemsource.h new file mode 100644 index 0000000..8e26c18 --- /dev/null +++ b/src/items/itemsource.h @@ -0,0 +1,24 @@ +#ifndef ITEMSOURCE_H +#define ITEMSOURCE_H + +#include +#include +#include + +#include "item.h" + +class ItemSource : public QObject +{ + Q_OBJECT +public: + explicit ItemSource(QObject *parent = nullptr); + +public slots: + virtual void refresh() = 0; + +signals: + void gotItems(std::vector> items, bool inform = true); + void updateItems(std::vector items, bool inform = true); +}; + +#endif // ITEMSOURCE_H diff --git a/src/items/itemstore.cpp b/src/items/itemstore.cpp index f3e4ab1..e681a97 100644 --- a/src/items/itemstore.cpp +++ b/src/items/itemstore.cpp @@ -1,52 +1,42 @@ #include "itemstore.h" -#include "relay.h" -#include "messageitem.h" -#include "systemitem.h" #include +#include ItemStore::ItemStore(QObject *parent): QObject(parent) { } -void ItemStore::addItem(std::shared_ptr item) +void ItemStore::addItem(std::shared_ptr item, bool inform) { - bool mached = false; - for(unsigned i = 0; i < items_.size(); i++ ) if(*items_[i] == *item) mached = true; - if(!mached) + std::shared_ptr matched = nullptr; + for(unsigned i = 0; i < items_.size(); i++ ) + { + if(*items_[i] == *item) + { + matched = items_[i]; + break; + } + } + if(!matched) { items_.push_back(std::shared_ptr(item)); + connect(item.get(), &Item::updated, this, &ItemStore::itemUpdateSlot); + qDebug()<<"Item"<getName()<<"added"; itemAdded(std::weak_ptr(items_.back())); } + else if(item->getValue() != matched->getValue()) + { + if(inform) + matched->informValue(item->getValue()); + else + matched->setValue(item->getValue()); + } } -void ItemStore::addItems(const std::vector>& itemIn) +void ItemStore::addItems(const std::vector>& itemIn, bool inform) { - for(unsigned i = 0; i < items_.size(); i++ ) - { - if(Relay* relay = dynamic_cast(items_[i].get())) - { - bool mached = false; - for(unsigned j = 0; j < itemIn.size(); j++) if(*(items_[i]) == *(itemIn[j])) - { - mached = true; - if(itemIn[j]->getValue() != items_[i]->getValue()) items_[i]->informValue(itemIn[j]->getValue()); - Relay* relayIn = dynamic_cast(itemIn[j].get()); - if(relayIn) - { - if(relay->getId() != relayIn->getId()) relay->setId(relayIn->getId()); - } - - } - if(!mached) - { - itemDeleted(*items_[i].get()); - items_.erase(items_.begin()+i); - } - } - } - - for(unsigned j = 0; j < itemIn.size(); j++)addItem(itemIn[j]); - + for(unsigned j = 0; j < itemIn.size(); j++) + addItem(itemIn[j], inform); } void ItemStore::removeItem(const ItemData& item) @@ -55,13 +45,14 @@ void ItemStore::removeItem(const ItemData& item) { if(item == *items_[j]) { + qDebug()<<"Item"< items, bool inform) { + for(const ItemData& item : items) + updateItem(item, inform); +} + +void ItemStore::updateItem(const ItemData& item, bool inform) +{ for(unsigned i = 0; i < items_.size(); i++ ) { if(items_[i]->operator==(item)) { - - if(items_[i]->getValue() != item.getValue())items_[i]->informValue(item.getValue()); + if(items_[i]->getValue() != item.getValue()) + { + if(inform) + items_[i]->informValue(item.getValue()); + else + items_[i]->setValue(item.getValue()); + } + qDebug()<<"Item"<getName()<<"updated"; + itemUpdated(items_[i]); } - } - } void ItemStore::store(QJsonObject& json) @@ -101,30 +103,51 @@ void ItemStore::load(const QJsonObject& json) const QJsonArray itemsArray(json["Items"].toArray(QJsonArray())); for(int i = 0; i < itemsArray.size(); ++i) { - if(itemsArray[i].isObject()) - { - const QJsonObject itemObject = itemsArray[i].toObject(); - std::shared_ptr newItem; - if(itemObject["Type"].toString("") == "Relay") - { - newItem = std::shared_ptr(new Relay()); - } - else if(itemObject["Type"].toString("") == "Message") - { - newItem = std::shared_ptr(new MessageItem); - } - else if(itemObject["Type"].toString("") == "System") - { - newItem = std::shared_ptr(new SystemItem()); - } - else if(itemObject["Type"].toString("") == "Aux") - { - } - if(newItem) - { - newItem->load(itemObject); - addItem(newItem); - } - } + if(!itemsArray[i].isObject()) + continue; + + const QJsonObject itemObject = itemsArray[i].toObject(); + std::shared_ptr newItem = Item::loadItem(itemObject); + if(newItem) + addItem(newItem); } } + +void ItemStore::itemUpdateSlot(ItemData data) +{ + qDebug()<<__func__; + for(std::shared_ptr& item: items_) + { + if(*item == data) + itemUpdated(std::weak_ptr(item)); + } +} + +std::shared_ptr ItemStore::getItem(uint32_t id) +{ + for(std::shared_ptr& item : items_) + { + if(item->id() == id) + return item; + } + return nullptr; +} + +void ItemStore::registerItemSource(ItemSource* source) +{ + qDebug()<<__func__<& item : items_) + itemDeleted(*item); + items_.clear(); + sigRefresh(); +} + +ItemStore globalItems; + diff --git a/src/items/itemstore.h b/src/items/itemstore.h index 4ee9651..437c4cc 100644 --- a/src/items/itemstore.h +++ b/src/items/itemstore.h @@ -2,7 +2,7 @@ #include #include #include "item.h" -#include "src/sensors/sensor.h" +#include "itemsource.h" #include @@ -10,7 +10,7 @@ class ItemStore: public QObject { Q_OBJECT private: - std::vector< std::shared_ptr > items_; + std::vector > items_; public: @@ -22,6 +22,9 @@ public: return &items_; } + std::shared_ptr getItem(uint32_t id); + + void registerItemSource(ItemSource* source); void store(QJsonObject &json); void load(const QJsonObject &json); @@ -31,11 +34,20 @@ signals: void itemDeleted(ItemData item); void itemAdded(std::weak_ptr Item); + void itemUpdated(std::weak_ptr Item); + void sigRefresh(); public slots: void removeItem(const ItemData& item); - void addItem(std::shared_ptr item); - void addItems(const std::vector>& itemsIn); - void itemStateChanged(const ItemData& item); + void addItem(std::shared_ptr item, bool inform = true); + void addItems(const std::vector>& itemsIn, bool inform = true); + void updateItems(std::vector items, bool inform = true); + void updateItem(const ItemData& item, bool inform = true); + void refresh(); + +private slots: + void itemUpdateSlot(ItemData data); }; + +extern ItemStore globalItems; diff --git a/src/items/messageitem.cpp b/src/items/messageitem.cpp index 0f51c53..32f9d5e 100644 --- a/src/items/messageitem.cpp +++ b/src/items/messageitem.cpp @@ -20,9 +20,8 @@ MessageItem::~MessageItem() closeMessageBox(); } -void MessageItem::setValue(uint8_t value) +void MessageItem::enactValue(uint8_t value) { - Item::setValue(value); if(value && !messageBox_) { if(!alertSoundFileName.isEmpty()) diff --git a/src/items/messageitem.h b/src/items/messageitem.h index 8b503c1..d23fb11 100644 --- a/src/items/messageitem.h +++ b/src/items/messageitem.h @@ -17,12 +17,10 @@ private: QSoundEffect alertSound; private slots: - void closeMessageBox(); -public: - - virtual void setValue(uint8_t value); +protected: + virtual void enactValue(uint8_t value) override; public: @@ -36,8 +34,8 @@ public: void setAlert(const QString& in); QString getAlert(); - virtual void store(QJsonObject& json); - virtual void load(const QJsonObject& json, const bool preserve = false); + virtual void store(QJsonObject& json) override; + virtual void load(const QJsonObject& json, const bool preserve = false) override; }; #endif // MESSAGEITEM_H diff --git a/src/items/poweritem.cpp b/src/items/poweritem.cpp index 998e6d2..cea1470 100644 --- a/src/items/poweritem.cpp +++ b/src/items/poweritem.cpp @@ -7,15 +7,14 @@ PowerItem::PowerItem(uint32_t itemIdIn, QString name, uint8_t value, QObject* p parent) { stateChanged(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 0, "Shutdown Imminent", true)); - setValue(true); + PowerItem::setValue(true); } -void PowerItem::setValue(uint8_t value) +void PowerItem::enactValue(uint8_t value) { - qDebug()<<"shutdown"; - Item::setValue(value); if(!value) { + qDebug()<<"shutdown"; QTimer::singleShot(5000, this, &PowerItem::timeout); stateChanged(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 1, "Shutdown Imminent", true)); } diff --git a/src/items/poweritem.h b/src/items/poweritem.h index ff1f263..76dea5e 100644 --- a/src/items/poweritem.h +++ b/src/items/poweritem.h @@ -16,12 +16,10 @@ signals: void stateChanged(Sensor sensor); private slots: - void timeout(); -public slots: - - virtual void setValue(uint8_t value); +protected: + virtual void enactValue(uint8_t value) override; public: PowerItem(uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "", uint8_t value = 0, @@ -30,5 +28,5 @@ public: { stateChanged(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 0, "Shutdown Imminent", true)); } - virtual void store(QJsonObject& json); + virtual void store(QJsonObject& json) override; }; diff --git a/src/items/relay.cpp b/src/items/relay.cpp index 67197e0..e0a3d30 100644 --- a/src/items/relay.cpp +++ b/src/items/relay.cpp @@ -12,13 +12,14 @@ Relay::Relay(uint8_t id, QString name, uint16_t address, bool state, QObject* pa qDebug()<<"Relay "<relayOn(id_); - else micro_->relayOff(id_); + if(value) + micro_->relayOn(id_); + else + micro_->relayOff(id_); } } diff --git a/src/items/relay.h b/src/items/relay.h index f0ae640..8a35e98 100644 --- a/src/items/relay.h +++ b/src/items/relay.h @@ -18,9 +18,10 @@ private: uint8_t id_; uint16_t address_; -public slots: +protected: + virtual void enactValue(uint8_t value) override; - virtual void setValue(uint8_t value); +public slots: void on(); void off(); void toggle(); @@ -37,7 +38,7 @@ public: micro_ = micro; } - virtual void store(QJsonObject& json); - virtual void load(const QJsonObject& json, const bool preserve = false); + virtual void store(QJsonObject& json) override; + virtual void load(const QJsonObject& json, const bool preserve = false) override; }; #endif // RELAY_H diff --git a/src/items/rgbitem.cpp b/src/items/rgbitem.cpp index 46bc80d..cd47c7b 100644 --- a/src/items/rgbitem.cpp +++ b/src/items/rgbitem.cpp @@ -6,9 +6,8 @@ RgbItem::RgbItem(Microcontroller* micro, uint32_t itemIdIn, QString name, uint8 } -void RgbItem::setValue(uint8_t value) +void RgbItem::enactValue(uint8_t value) { - Item::setValue(value); value ? micro_->rgbOn() : micro_->rgbOff(); } diff --git a/src/items/rgbitem.h b/src/items/rgbitem.h index a503406..6e2a923 100644 --- a/src/items/rgbitem.h +++ b/src/items/rgbitem.h @@ -9,13 +9,12 @@ class RgbItem: public Item private: Microcontroller* micro_; -public slots: - - virtual void setValue(uint8_t value); +protected: + virtual void enactValue(uint8_t value) override; public: RgbItem(Microcontroller* micro, uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "", uint8_t value = 0, QObject* parent = nullptr); - virtual void store(QJsonObject& json); + virtual void store(QJsonObject& json) override; }; diff --git a/src/items/systemitem.cpp b/src/items/systemitem.cpp index c11ee29..7887ce5 100644 --- a/src/items/systemitem.cpp +++ b/src/items/systemitem.cpp @@ -1,7 +1,7 @@ #include "systemitem.h" #include -void SystemItem::setValue(uint8_t value) +void SystemItem::enactValue(uint8_t value) { QProcess::execute(value ? onCommand_ : offCommand_); } diff --git a/src/items/systemitem.h b/src/items/systemitem.h index 778780a..392e914 100644 --- a/src/items/systemitem.h +++ b/src/items/systemitem.h @@ -7,16 +7,13 @@ class SystemItem : public Item { Q_OBJECT private: - QString onCommand_; QString offCommand_; -public: - - virtual void setValue(uint8_t value); +protected: + virtual void enactValue(uint8_t value) override; public: - SystemItem(uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "Item", uint8_t value = 0, QObject *parent = nullptr); SystemItem(const ItemData& itemData, QObject *parent = nullptr); @@ -33,8 +30,8 @@ public: return offCommand_; } - virtual void store(QJsonObject& json); - virtual void load(const QJsonObject& json, const bool preserve = false); + virtual void store(QJsonObject& json) override; + virtual void load(const QJsonObject& json, const bool preserve = false) override; }; #endif // SYSTEMITEM_H diff --git a/src/main.cpp b/src/main.cpp index 529202d..f94ff78 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,26 +1,64 @@ #include -#include #include #include #include - -//Currently pipewire support is disabled -//#include - - -#ifndef Q_OS_ANDROID +#include #include #include #include -#endif -#include "microcontroller.h" #include "ui/mainwindow.h" #include "items/itemstore.h" #include "mainobject.h" +#include "programmode.h" -#define BAUD QSerialPort::Baud38400 +QJsonObject getJsonObjectFromDisk(const QString& filePath, bool* error = nullptr) +{ + QFile file; + file.setFileName(filePath); + + bool ret = file.open(QIODevice::ReadOnly); + if(!file.isOpen() || !ret) + { + std::cerr<<"Can not open config file: "<connectToHost(host, port, QIODevice::ReadWrite); - if(!microSocket->waitForConnected(1000)) + QIODevice* microDevice = nullptr; + if(tcpMicro) { - std::cout<<"Can not connect to to Server.\n"; - QMessageBox::critical(nullptr, "Error", "Can not connect to to Server"); - return 1; + int port = json["MicroTcpPort"].toInt(6856); + json["MicroTcpPort"] = port; + QString host = json["MicroTcpHost"].toString("127.0.0.1"); + json["MicroTcpHost"] = host; + + QTcpSocket* microSocket = new QTcpSocket; + + qInfo()<<"connecting to "<connectToHost(host, port, QIODevice::ReadWrite); + + if(!microSocket->waitForConnected(1000)) + { + qCritical()<<"Can not connect to tcp micro"; + storeJsonObjectToDisk(json, parser.value(settingsPathOption)); + if(programMode == PROGRAM_MODE_PRIMARY) + QMessageBox::critical(nullptr, "Error", "Can not connect to tcp micro"); + return 1; + } + microDevice = microSocket; } - masterIODevice = microSocket; + else + { + QString port = json["MicroSerialPort"].toString("ttyUSB0"); + json["MicroSerialPort"] = port; + int baud = json["MicroSerialBaud"].toInt(38400); + json["MicroSerialBaud"] = baud; + + QSerialPort *microPort = new QSerialPort; + microPort->setPortName(port); + microPort->setBaudRate(baud); + microPort->open(QIODevice::ReadWrite); + + if(!microPort->isOpen()) + { + qCritical()<<"Can not open serial port"< item){globalItems.addItem(item, false);}); + w->show(); + } + retVal = a.exec(); + + delete w; + delete microDevice; + mainObject.store(json); + storeJsonObjectToDisk(json, parser.value(settingsPathOption)); } else { - QSerialPort* microPort = new QSerialPort; - if(parser.isSet(portOption)) microPort->setPortName(parser.value(portOption)); - else microPort->setPortName("ttyUSB0"); + SecondaryMainObject mainObject(parser.value(hostOption), parser.value(portOption).toInt()); + MainWindow w(&mainObject); + //QObject::connect(&w, &MainWindow::sigSave, &mainObject, &MainObject::sendJson); + w.show(); - if(parser.isSet(portOption)) microPort->setBaudRate(parser.value(baudOption).toInt()); - else microPort->setBaudRate(BAUD); - - if(!microPort->open(QIODevice::ReadWrite)) std::cout<<"Can not open serial port "<portName().toStdString() - <<". Continueing in demo mode"<<'\n'; - masterIODevice = microPort; + retVal = a.exec(); } - MainObject mainObject(masterIODevice, parser.isSet(settingsPathOption) ? parser.value(settingsPathOption) : "", - !parser.isSet(secondaryOption)); - -#else - QTcpSocket* microSocket = new QTcpSocket; - microSocket->connectToHost("10.0.0.1", 6856, QIODevice::ReadWrite); - if(!microSocket->waitForConnected(1000)) - { - std::cout<<"Can not connect to to Server.\n"; - return 1; - } - masterIODevice = microSocket; - - MainObject mainObject(masterIODevice, parser.isSet(settingsPathOption) ? parser.value(settingsPathOption) : "", - !parser.isSet(secondaryOption)); -#endif - - - //mainwindow - MainWindow w(&mainObject); - QObject::connect(&mainObject.micro, SIGNAL(textRecived(QString)), &w, SLOT(changeHeaderLableText(QString))); - QObject::connect(&w, &MainWindow::sigBrodcast, &mainObject, &MainObject::sendJson); - QObject::connect(&w, &MainWindow::sigSave, &mainObject, &MainObject::storeToDisk); - QObject::connect(&w, &MainWindow::createdItem, &mainObject.items, &ItemStore::addItem); - if(!mainObject.micro.connected()) - w.changeHeaderLableText("No io debug only!"); - - w.show(); - - int retVal = a.exec(); - - if(masterIODevice) - delete masterIODevice; return retVal; } diff --git a/src/mainobject.cpp b/src/mainobject.cpp index d474d87..d92e0ae 100644 --- a/src/mainobject.cpp +++ b/src/mainobject.cpp @@ -1,179 +1,94 @@ #include "mainobject.h" -#include "items/messageitem.h" -MainObject::MainObject(QIODevice* ioDevice, const QString& settingsPathIn, const bool masterIn, QObject *parent) : - QObject(parent), - master(masterIn), - masterIODevice(ioDevice), - ioMultiplexer(masterIODevice), - micro(ioMultiplexer.getIoDevice()), - broadCast(ioMultiplexer.getIoDevice(), masterIn), - settingsPath(settingsPathIn), - sunSensorSource(49.884450, 8.650536), - powerItem(new PowerItem), - rgbItem(new RgbItem(µ, 5487422, "Rgb Lights")), - auxItem(new AuxItem(µ, 5487421, "Desk Light")) +#include +#include +#include +#include "items/itemstore.h" + +MainObject::MainObject(QObject *parent) : + QObject(parent) { - qDebug()<<"Is master:"<emmitSensor(); - items.addItem(rgbItem); - items.addItem(auxItem); - MessageItem::broadCast = &broadCast; - - Relay::setMicrocontroller(µ); - - connect(&broadCast, &BroadCast::gotJson, this, &MainObject::recivedJson); - QObject::connect(&broadCast, &BroadCast::gotSensorState, &globalSensors, &SensorStore::sensorGotState); - if(master) - connect(&broadCast, &BroadCast::jsonRequested, this, &MainObject::sendJson); - - if(master) - { - load(getJsonObjectFromDisk(settingsPath, &noSave)); - } - else - { - broadCast.requestJson(); - broadCast.requestSensors(); - } - -#ifndef Q_OS_ANDROID - Item::secondaryFlag = !master; -#endif } MainObject::~MainObject() { } -void MainObject::store(QJsonObject &json) +void MainObject::refresh() { - items.store(json); - - QJsonObject powerObject; - powerItem->store(powerObject); - json.insert("Power", powerObject); - QJsonDocument pwrDoc(powerObject); - - QJsonObject ocupancyObject; - ocupancySensor.store(ocupancyObject); - json.insert("Ocupancy", ocupancyObject); + globalItems.refresh(); } -void MainObject::load(const QJsonObject& json) +PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, QJsonObject* settings, QString host, int port, QObject *parent) : + MainObject(parent), + settings(settings), + microDevice(microDevice), + ioMultiplexer(microDevice), + micro(microDevice), + tcpServer(new TcpServer), + sunSensorSource(49.824972, 8.702194), + powerItem(new PowerItem), + rgbItem(new RgbItem(µ, 5487422, "Rgb Lights")), + auxItem(new AuxItem(µ, 5487421, "Desk Light")) { - items.clear(); + //connect sensors subsystem + connect(&globalSensors, &SensorStore::sensorChangedState, tcpServer, &TcpServer::sensorEvent); + connect(tcpServer, &TcpServer::gotSensor, &globalSensors, &SensorStore::sensorGotState); + connect(&sunSensorSource, &SunSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState); + connect(µ, &Microcontroller::gotSensorState, &globalSensors, &SensorStore::sensorGotState); + + globalItems.registerItemSource(tcpServer); + globalItems.registerItemSource(µ); + + load(*settings); + + tcpServer->launch(QHostAddress(host), port); +} + +PrimaryMainObject::~PrimaryMainObject() +{ + store(*settings); +} + +void PrimaryMainObject::store(QJsonObject &json) +{ + globalItems.store(json); +} + +void PrimaryMainObject::load(const QJsonObject& json) +{ + globalItems.clear(); rgbItem->removeAllActors(); auxItem->removeAllActors(); powerItem->removeAllActors(); - items.addItem(rgbItem); - items.addItem(auxItem); - items.load(json); - powerItem->load(json["Power"].toObject()); - ocupancySensor.load(json["Ocupancy"].toObject()); - qDebug()<<"aray size: "<= 2) { rgbItem->load(json["Items"].toArray()[0].toObject()); auxItem->load(json["Items"].toArray()[1].toObject()); } - micro.requestState(); + globalItems.refresh(); } -void MainObject::storeToDisk() +SecondaryMainObject::SecondaryMainObject(QString host, int port, QObject *parent) : + MainObject(parent), + tcpClient(new TcpClient) { - if(master && !noSave) + connect(tcpClient, &TcpClient::gotSensor, &globalSensors, &SensorStore::sensorGotState); + globalItems.registerItemSource(tcpClient); + + if(!tcpClient->launch(QHostAddress(host), port)) { - QJsonObject json; - store(json); - storeJsonObjectToDisk(json, settingsPath); + QMessageBox::critical(nullptr, "Error", "Could not connect to "+host+":"+QString::number(port)); + exit(1); } } -void MainObject::recivedJson(const QJsonObject json) +SecondaryMainObject::~SecondaryMainObject() { - if(master && !noSave) - storeJsonObjectToDisk(json, settingsPath); - load(json); -} - -void MainObject::sendJson() -{ - QJsonObject json; - store(json); - broadCast.sendJson(json); -} - -QJsonObject MainObject::getJsonObjectFromDisk(const QString& filePath, bool* error) -{ - QFile file; - -#ifndef Q_OS_ANDROID - if(filePath.size() > 0) file.setFileName(filePath); - else -#endif - { - file.setFileName(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/shinterface.json"); - } - - file.open(QIODevice::ReadOnly); - if(!file.isOpen()) std::cerr<<"Can not open config file: "< -#include #include #include #include @@ -12,80 +11,66 @@ #include #include - -#ifndef Q_OS_ANDROID -#include -#include -#include -#endif - -#include "actors/alarmtime.h" #include "microcontroller.h" #include "ui/mainwindow.h" -#include "sensors/speakersensor.h" #include "sensors/sunsensor.h" -#include "sensors/ocupancysensor.h" -#include "sensors/sensor.h" -#include "items/itemstore.h" #include "items/auxitem.h" #include "items/rgbitem.h" #include "items/poweritem.h" #include "iomuliplexer.h" #include "broadcast.h" -//#include "pipewire.h" +#include "tcpserver.h" class MainObject : public QObject +{ + Q_OBJECT + +public: + explicit MainObject(QObject *parent = nullptr); + ~MainObject(); + +public slots: + void refresh(); +}; + +class PrimaryMainObject : public MainObject { Q_OBJECT public: + QJsonObject* settings; + //io - const bool master; - - bool noSave = false; - - QIODevice * const masterIODevice = nullptr; + QIODevice * const microDevice = nullptr; IoMuliplexer ioMultiplexer; Microcontroller micro; - BroadCast broadCast; - - - const QString settingsPath; + TcpServer* tcpServer; //sensors - SunSensorSource sunSensorSource; - OcupancySensorSource ocupancySensor; + SunSensorSource sunSensorSource; //items - ItemStore items; - std::shared_ptr powerItem; std::shared_ptr rgbItem; std::shared_ptr auxItem; - //PipeWireHandler pwHandler; +public: + explicit PrimaryMainObject(QIODevice* microDevice, QJsonObject* settings, QString host, int port, QObject *parent = nullptr); + ~PrimaryMainObject(); + void store(QJsonObject& json); + void load(const QJsonObject& json); +}; -private: - - static QJsonObject getJsonObjectFromDisk(const QString& filePath = "", bool* error = nullptr); - static bool storeJsonObjectToDisk(const QJsonObject& json, QString filePath = ""); +class SecondaryMainObject : public MainObject +{ + Q_OBJECT +public: + TcpClient* tcpClient; public: - explicit MainObject(QIODevice* ioDevice, const QString& settingsPathIn, const bool masterIn, QObject *parent = nullptr); - ~MainObject(); - - void store(QJsonObject& json); - - void load(const QJsonObject& json); - -signals: - -public slots: - - void storeToDisk(); - void sendJson(); - void recivedJson(const QJsonObject json); + explicit SecondaryMainObject(QString host, int port, QObject *parent = nullptr); + ~SecondaryMainObject(); }; diff --git a/src/microcontroller.cpp b/src/microcontroller.cpp index ba5f54b..174cfd0 100644 --- a/src/microcontroller.cpp +++ b/src/microcontroller.cpp @@ -3,8 +3,6 @@ #include #include -static constexpr bool debug = true; - void Microcontroller::relayToggle(int state, int relay) { char buffer[8]; @@ -40,7 +38,6 @@ void Microcontroller::changeRgbColor(const QColor color) char buffer[64]; int length = sprintf(buffer, "rgb set %03d %03d %03d\n", color.red(), color.green(), color.blue()); write(buffer, length); - std::cout<write(buffer); @@ -65,9 +59,6 @@ void Microcontroller::write(const QByteArray& buffer) void Microcontroller::write(char* buffer, const size_t length) { -#ifndef Q_OS_ANDROID - if constexpr(debug) std::cerr<write(buffer, length); @@ -95,7 +86,7 @@ bool Microcontroller::connected() else return false; } -void Microcontroller::requestState() +void Microcontroller::refresh() { write("state\n"); } @@ -147,12 +138,13 @@ void Microcontroller::processList(const QString& buffer) if(bufferList.size() >= 8 && buffer.startsWith("ITEM NUMBER:")) { relayList.push_back(processRelayLine(buffer)); + qDebug()<<"Micro item recived:"<getName(); } else if(buffer.contains("EOL")) { listMode = false; qDebug()<<"got relay list " << relayList.size(); - gotRelayList(relayList); + gotItems(relayList); relayList.clear(); } else listMode = false; @@ -160,7 +152,7 @@ void Microcontroller::processList(const QString& buffer) void Microcontroller::processRelayState(const QString& buffer) { - itemChanged(static_cast(*processRelayLine(buffer))); + updateItems({static_cast(*processRelayLine(buffer))}); } void Microcontroller::processSensorState(const QString& buffer) @@ -172,7 +164,11 @@ void Microcontroller::processSensorState(const QString& buffer) void Microcontroller::processMicroReturn() { - if(listMode) processList(_buffer); + qDebug()<<_buffer; + if(listMode) + { + processList(_buffer); + } else { if(_buffer.startsWith("Items:")) @@ -192,7 +188,9 @@ void Microcontroller::isReadyRead() while(_port->getChar(&charBuf)) { _buffer.push_back(charBuf); - if( _buffer.endsWith('\n') ) + + qDebug()<<_buffer; + if(_buffer.endsWith('\n') ) { _buffer.remove('\n'); processMicroReturn(); diff --git a/src/microcontroller.h b/src/microcontroller.h index 8392491..1845dc0 100644 --- a/src/microcontroller.h +++ b/src/microcontroller.h @@ -1,8 +1,6 @@ #ifndef MICROCONTROLLER_H #define MICROCONTROLLER_H -#include - #include #include #include @@ -17,8 +15,9 @@ #include "items/item.h" #include "items/relay.h" #include "sensors/sensor.h" +#include "items/itemsource.h" -class Microcontroller : public QObject +class Microcontroller : public ItemSource { Q_OBJECT @@ -65,7 +64,7 @@ public slots: void setPattern(int pattern); void startSunrise(); - void requestState(); + void refresh() override; void setAuxPwm(int duty); @@ -79,10 +78,6 @@ private slots: signals: void textRecived(const QString string); - void itemChanged(ItemData relay); - void auxStateChanged(int value); - void gotRelayList(std::vector< std::shared_ptr >&); - void gotSensorState(Sensor sensor); }; diff --git a/src/programmode.cpp b/src/programmode.cpp new file mode 100644 index 0000000..d37ba81 --- /dev/null +++ b/src/programmode.cpp @@ -0,0 +1,3 @@ +#include "programmode.h" + +program_mode_t programMode = PROGRAM_MODE_PRIMARY; diff --git a/src/programmode.h b/src/programmode.h new file mode 100644 index 0000000..ccbb900 --- /dev/null +++ b/src/programmode.h @@ -0,0 +1,13 @@ +#ifndef PROGRAMMODE_H +#define PROGRAMMODE_H + +typedef enum +{ + PROGRAM_MODE_PRIMARY = 0, + PROGRAM_MODE_HEADLESS_PRIMARY, + PROGRAM_MODE_UI_ONLY +} program_mode_t; + +extern program_mode_t programMode; + +#endif // PROGRAMMODE_H diff --git a/src/sensors/ocupancysensor.cpp b/src/sensors/ocupancysensor.cpp deleted file mode 100644 index 3bf7b7c..0000000 --- a/src/sensors/ocupancysensor.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "ocupancysensor.h" -#include -#include - -#include "../apgetconnected.h" - - -OcupancySensorSource::OcupancySensorSource(QObject *parent, const QString& device, - const QString& deviceMac): QObject (parent), deviceMac_(deviceMac), device_(device) -{ - QTimer::singleShot(timeoutMs, this, &OcupancySensorSource::Timeout); -} - -void OcupancySensorSource::sensorEvent(Sensor sensor) -{ - if(sensor.type == Sensor::TYPE_DOOR && sensor.id == 1 && sensor.field != 0.0f) - { - if(occupied == false) stateChanged(Sensor(Sensor::TYPE_OCUPANCY, 0, 1, "Occupancy")); - QTimer::singleShot(timeoutMs, this, &OcupancySensorSource::Timeout); - } -} - -void OcupancySensorSource::Timeout() -{ - int error = 0; - qDebug()<<"testing for occupancy"; - std::vector devices = ap::connectedDevices(device_.toLatin1().toStdString(), error); - if(error == 0) - { - bool found = false; - for(size_t i = 0; i < devices.size(); ++i) - { - std::string mac = ap::macAddrToString(devices[i]); - if(mac.find(deviceMac_.toLatin1().toStdString()) != std::string::npos) - { - found = true; - qDebug()<<"occupied"; - break; - } - } - stateChanged(Sensor(Sensor::TYPE_OCUPANCY, 0, found, "Occupancy")); - occupied = found; - } - else - { - stateChanged(Sensor(Sensor::TYPE_OCUPANCY, 0, true, "Occupancy")); - qDebug()<<"occupancy sensor error "< -#include -#include "sensor.h" - -class OcupancySensorSource : public QObject -{ - Q_OBJECT -private: - - QString deviceMac_; - QString device_; - bool occupied = true; - static constexpr unsigned timeoutMs = (15 * 60) * 1000; - -public: - explicit OcupancySensorSource(QObject *parent = nullptr, const QString& device = "wlan0", - const QString& deviceMac = "60:BE:B5:25:8C:E0"); - - void store(QJsonObject& json); - void load(const QJsonObject& json); - -public slots: - void sensorEvent(Sensor sensor); - -private slots: - - void Timeout(); - -signals: - void stateChanged(Sensor sensor); -}; diff --git a/src/sensors/pipewiresensor.cpp b/src/sensors/pipewiresensor.cpp deleted file mode 100644 index 89ee7e4..0000000 --- a/src/sensors/pipewiresensor.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "pipewiresensor.h" -#include - -static const struct pw_node_events node_events = { - .version = PW_VERSION_NODE_EVENTS, - .info = &PipeWireSensorSource::nodeEventHandler, - .param = nullptr -}; - -PipeWireSensorSource::PipeWireSensorSource(PipeWireHandler* handler, const std::string& nodeName, uint8_t id, QObject *parent) - : QObject{parent}, handler_(handler), nodeName_(nodeName), id_(id) -{ - connect(handler_, &PipeWireHandler::nodeAdded, this, &PipeWireSensorSource::nodeAdded); - connect(&timer, &QTimer::timeout, this, &PipeWireSensorSource::offTimeout); - timer.setSingleShot(true); -} - -void PipeWireSensorSource::offTimeout() -{ - if(state == false) - return; - state = false; - stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, id_, state)); -} - -void PipeWireSensorSource::nodeEventHandler(void* data, const struct pw_node_info *info) -{ - PipeWireSensorSource* source = static_cast(data); - - if(info->state == source->prevState) - return; - - source->prevState = info->state; - - switch (info->state) - { - case PW_NODE_STATE_ERROR: - case PW_NODE_STATE_CREATING: - source->state = false; - source->stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, source->id_, 0)); - break; - case PW_NODE_STATE_SUSPENDED: - case PW_NODE_STATE_IDLE: - if(source->state == true) - source->timer.start(10000); - break; - case PW_NODE_STATE_RUNNING: - if(source->state == false) - { - source->state = true; - source->stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, source->id_, source->state)); - } - break; - default: - break; - } -} - -void PipeWireSensorSource::nodeAdded(PipeWireHandler::PwNode node) -{ - if(node.name == nodeName_) - { - - sinkNode = static_cast(pw_registry_bind(handler_->getRegistry(), node.id, PW_TYPE_INTERFACE_Node, PW_VERSION_CLIENT, 0)); - if(sinkNode) - { - qDebug()<<"Failed to register to required pipewire node"< -#include -#include -#include -#include - -#include "sensor.h" -#include "../pipewire.h" - -class PipeWireSensorSource : public QObject -{ - Q_OBJECT - - PipeWireHandler* handler_; - std::string nodeName_; - struct pw_node* sinkNode = nullptr; - struct spa_hook sinkListener; - pw_node_state prevState = PW_NODE_STATE_SUSPENDED; - QTimer timer; - uint8_t id_; - bool state = false; - -private slots: - void offTimeout(); - -public: - explicit PipeWireSensorSource(PipeWireHandler* handler, const std::string& nodeName, uint8_t id, QObject *parent = nullptr); - static void nodeEventHandler(void* data, const struct pw_node_info *info); - -signals: - void stateChanged(Sensor sensor); - -private slots: - void nodeAdded(PipeWireHandler::PwNode node); -}; - -#endif // PIPEWIRESENSOR_H diff --git a/src/sensors/sensor.h b/src/sensors/sensor.h index e64498e..80c37ab 100644 --- a/src/sensors/sensor.h +++ b/src/sensors/sensor.h @@ -4,6 +4,7 @@ #include #include #include +#include class Sensor { @@ -41,6 +42,15 @@ public: { lastSeen = QDateTime::currentDateTime(); } + Sensor(const QJsonObject& json) + { + type = json["SensorType"].toInt(0); + id = json["Id"].toInt(0); + field = json["Field"].toInt(0); + name = json["Name"].toString("Sensor"); + lastSeen = QDateTime::fromString(json["LastSeen"].toString("")); + hidden = json["Hidden"].toBool(false); + } inline bool operator==(const Sensor& in) const { return type==in.type && id == in.id; @@ -77,15 +87,32 @@ public: QString::number((type == Sensor::TYPE_HUMIDITY || type == Sensor::TYPE_TEMPERATURE) ? field*10 : field) + " TIME: " + QString::number(lastSeen.toSecsSinceEpoch()); } + inline void store(QJsonObject& json) + { + json["Type"] = "Sensor"; + json["SensorType"] = static_cast(type); + json["Id"] = static_cast(id); + json["Field"] = field; + json["Name"] = name; + json["LastSeen"] = lastSeen.toString(); + json["Hidden"] = hidden; + } inline void generateName() { - if(type == TYPE_TEMPERATURE) name = "Temperature " + QString::number(id); - else if(type == TYPE_DOOR) name = "Door " + QString::number(id); - else if(type == TYPE_BUTTON) name = "Button " + QString::number(id); - else if(type == TYPE_AUDIO_OUTPUT) name = "Speakers " + QString::number(id); - else if(type == TYPE_HUMIDITY) name = "Humidity " + QString::number(id); - else if(type == TYPE_SUN_ALTITUDE) name = "Solar Altitude"; - else if(type == TYPE_SHUTDOWN_IMMINENT) name = "Shutdown Imminent"; + if(type == TYPE_TEMPERATURE) + name = "Temperature " + QString::number(id); + else if(type == TYPE_DOOR) + name = "Door " + QString::number(id); + else if(type == TYPE_BUTTON) + name = "Button " + QString::number(id); + else if(type == TYPE_AUDIO_OUTPUT) + name = "Speakers " + QString::number(id); + else if(type == TYPE_HUMIDITY) + name = "Humidity " + QString::number(id); + else if(type == TYPE_SUN_ALTITUDE) + name = "Solar Altitude"; + else if(type == TYPE_SHUTDOWN_IMMINENT) + name = "Shutdown Imminent"; else name = "Sensor Type " + QString::number(type) + " Id " + QString::number(id); } }; diff --git a/src/sensors/speakersensor.cpp b/src/sensors/speakersensor.cpp deleted file mode 100644 index e2a4171..0000000 --- a/src/sensors/speakersensor.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "speakersensor.h" - -#include - -SpeakerSensorSource::SpeakerSensorSource(QString name, QObject *parent) : QObject(parent), name_(name) -{ - silenceCount = 0; -} - -SpeakerSensorSource::~SpeakerSensorSource() -{ - abort(); -} - -void SpeakerSensorSource::run() -{ - abort(); - arecord.start( "arecord", {"--disable-softvol", "-r", "8000", "-D", "front", "-"}); - - connect(&timer, SIGNAL(timeout()), this, SLOT(doTick())); - timer.setInterval(500); - timer.start(); - - stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, 0, 1, name_)); -} - - -void SpeakerSensorSource::abort() -{ - if(arecord.state() == QProcess::Running)arecord.close(); - if(timer.isActive())timer.stop(); -} - -void SpeakerSensorSource::doTick() -{ - if(arecord.state() == QProcess::Running) - { - QByteArray buffer = arecord.readAllStandardOutput(); - //qDebug()<<(int16_t)buffer[0]; - for(long i = 0; i < buffer.size(); i++) - { - if((int16_t)buffer.at(i) != -128) - { - silenceCount = 0; - } - } - if(silenceCount > 40 && state) - { - stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, 0, 0, name_)); - state = false; - } - else if(silenceCount == 0 && !state) - { - stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, 0, 1, name_)); - state = true; - } - silenceCount++; - } -} diff --git a/src/sensors/speakersensor.h b/src/sensors/speakersensor.h deleted file mode 100644 index 8479ff2..0000000 --- a/src/sensors/speakersensor.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef AMPMANAGER_H -#define AMPMANAGER_H - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "sensor.h" - - -class SpeakerSensorSource : public QObject -{ - Q_OBJECT -private: - QString name_; - bool state = true; - QTimer timer; - -public: - explicit SpeakerSensorSource(QString name = "", QObject *parent = nullptr); - ~SpeakerSensorSource(); - -public slots: - void run(); - void abort(); - -signals: - void stateChanged(Sensor sensor); - -private slots: - void doTick(); - -private: - long silenceCount = 0; - - QProcess arecord; -}; - -#endif // AMPMANAGER_H diff --git a/src/tcpserver.cpp b/src/tcpserver.cpp new file mode 100644 index 0000000..b6f82e2 --- /dev/null +++ b/src/tcpserver.cpp @@ -0,0 +1,277 @@ +#include +#include +#include + +#include "items/item.h" +#include "items/itemstore.h" +#include "tcpserver.h" + + +TcpService::TcpService(QObject* parent): + ItemSource(parent) +{} + +QJsonObject TcpService::createMessage(const QString& type, const QJsonArray& data) +{ + QJsonObject json; + json["MesageType"] = type; + json["Data"] = data; + return json; +} + +void TcpService::sensorEvent(Sensor sensor) +{ + QJsonArray sensors; + QJsonObject sensorjson; + sensor.store(sensorjson); + sensors.append(sensorjson); + QJsonObject json = createMessage("SensorUpdate", sensors); + + sendJson(json); +} + +void TcpService::itemUpdated(std::weak_ptr item) +{ + QJsonArray items; + QJsonObject itemjson; + item.lock()->store(itemjson); + items.append(itemjson); + QJsonObject json = createMessage("ItemUpdate", items); + sendJson(json); +} + +void TcpService::refresh() +{ + sendJson(createMessage("GetSensors", QJsonArray())); + sendJson(createMessage("GetItems", QJsonArray())); +} + +void TcpService::sendSensors() +{ + QJsonArray sensors; + for(auto& sensor: *globalSensors.getSensors()) + { + QJsonObject sensorjson; + sensor.store(sensorjson); + sensors.append(sensorjson); + } + sendJson(createMessage("SensorUpdate", sensors)); +} + +void TcpService::sendItems() +{ + QJsonArray items; + for(auto& item: *globalItems.getItems()) + { + QJsonObject itemjson; + item->store(itemjson); + items.append(itemjson); + } + sendJson(createMessage("ItemUpdate", items)); +} + + +void TcpService::processIncomeingJson(const QByteArray& jsonbytes) +{ + qDebug()<<__func__<write(QString("MSG JSON LEN " + QString::number(jsonData.size()) + "\n").toLatin1() + jsonData); +} + +bool TcpClient::launch(const QHostAddress &address, quint16 port) +{ + socket->connectToHost(address, port); + return socket->waitForConnected(2000); +} + +void TcpClient::processIncomeingJson(const QByteArray& jsonbytes) +{ + QJsonDocument doc = QJsonDocument::fromJson(jsonbytes); + QJsonObject json = doc.object(); + QString type = json["MessageType"].toString(); + if(type == "ItemUpdate") + { + QJsonArray data = json["Data"].toArray(); + std::vector> items; + for(QJsonValueRef itemjson : data) + { + QJsonObject jsonobject = itemjson.toObject(); + std::shared_ptr item = Item::loadItem(jsonobject); + if(item) + items.push_back(item); + } + if(!items.empty()) + gotItems(items, true); + } + else + { + TcpService::processIncomeingJson(jsonbytes); + } +} + +TcpClient::~TcpClient() +{ + delete socket; +} + +TcpServer::TcpServer(QObject* parent): + TcpService(parent), + server(this) +{ +} + +void TcpServer::sendJson(const QJsonObject& json) +{ + for(auto client: clients) + { + QByteArray jsonData = QJsonDocument(json).toJson(); + client.socket->write(QString("MSG JSON LEN " + QString::number(jsonData.size()) + "\n").toLatin1() + jsonData); + } +} + +void TcpServer::processIncomeingJson(const QByteArray& jsonbytes) +{ + QJsonDocument doc = QJsonDocument::fromJson(jsonbytes); + QJsonObject json = doc.object(); + QString type = json["MessageType"].toString(); + if(type == "ItemUpdate") + { + QJsonArray data = json["Data"].toArray(); + std::vector> items; + for(QJsonValueRef itemjson : data) + { + QJsonObject jsonobject = itemjson.toObject(); + std::shared_ptr item = Item::loadItem(jsonobject); + if(item) + items.push_back(item); + } + if(!items.empty()) + gotItems(items, false); + } + else + { + TcpService::processIncomeingJson(jsonbytes); + } +} + +bool TcpServer::launch(const QHostAddress &address, quint16 port) +{ + return server.listen(address, port); +} + +void TcpServer::incomingConnection() +{ + while(server.hasPendingConnections()) + { + QTcpSocket* client = server.nextPendingConnection(); + if(client) + { + clients.push_back({client}); + connect(client, &QTcpSocket::errorOccurred, this, &TcpServer::socketError); + connect(client, &QTcpSocket::disconnected, this, &TcpServer::socketDisconnect); + connect(client, &QTcpSocket::readyRead, this, &TcpServer::socketReadyRead); + } + } +} + +void TcpServer::socketError(QAbstractSocket::SocketError socketError) +{ + (void)socketError; + for(size_t i = 0; i < clients.size(); i++) + { + if(clients[i].socket == TcpServer::sender()) + { + clients.erase(clients.begin()+i); + --i; + } + } +} +void TcpServer::socketDisconnect() +{ + for(size_t i = 0; i < clients.size(); i++) + { + if(clients[i].socket == TcpServer::sender()) + { + clients.erase(clients.begin()+i); + --i; + } + } +} + +void TcpServer::processComand(const QByteArray& command, Client& client) +{ + qDebug()<<__func__<readAll(); + bool remianing = true; + while(remianing) + { + remianing = false; + while(clients[i].state == STATE_IDLE && clients[i].buffer.contains('\n')) + { + size_t newlineIndex = clients[i].buffer.indexOf('\n'); + QByteArray command = clients[i].buffer.chopped(newlineIndex); + clients[i].buffer.chop(newlineIndex); + processComand(command, clients[i]); + remianing = true; + } + if(clients[i].state == STATE_RECV_JSON) + { + if(clients[i].recievebytes <= clients[i].buffer.size()) + { + QByteArray json = clients[i].buffer.chopped(clients[i].recievebytes); + clients[i].buffer.chop(clients[i].recievebytes); + clients[i].recievebytes = 0; + clients[i].state = STATE_IDLE; + processIncomeingJson(json); + remianing = true; + } + } + } + } + } +} + diff --git a/src/tcpserver.h b/src/tcpserver.h new file mode 100644 index 0000000..9c02556 --- /dev/null +++ b/src/tcpserver.h @@ -0,0 +1,89 @@ +#ifndef TCPSERVER_H +#define TCPSERVER_H + +#include +#include + +#include "sensors/sensor.h" +#include "items/item.h" +#include "items/itemsource.h" + +class TcpService : public ItemSource +{ + Q_OBJECT +signals: + void gotSensor(Sensor sensor); + +public slots: + void sensorEvent(Sensor sensor); + void itemUpdated(std::weak_ptr item); + virtual void refresh() override; + +public: + TcpService(QObject* parent = nullptr); + void sendSensors(); + void sendItems(); + virtual void sendJson(const QJsonObject& json) = 0; + virtual bool launch(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) = 0; + +protected: + static QJsonObject createMessage(const QString& type, const QJsonArray& data); + virtual void processIncomeingJson(const QByteArray& jsonbytes); +}; + +class TcpClient : public TcpService +{ + Q_OBJECT + + QTcpSocket* socket; + +public: + TcpClient(QObject* parent = nullptr); + ~TcpClient(); + virtual bool launch(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) override; + virtual void sendJson(const QJsonObject& json) override; + +protected: + virtual void processIncomeingJson(const QByteArray& jsonbytes) override; +}; + +class TcpServer : public TcpService +{ + Q_OBJECT + + typedef enum + { + STATE_IDLE, + STATE_RECV_JSON, + } client_state_t; + + struct Client + { + QTcpSocket* socket; + QByteArray buffer; + client_state_t state = STATE_IDLE; + long long recievebytes = 0; + }; + + std::vector clients; + QTcpServer server; + +public: + TcpServer(QObject* parent = nullptr); + virtual bool launch(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) override; + virtual void sendJson(const QJsonObject& json) override; + +private slots: + void incomingConnection(); + void socketError(QAbstractSocket::SocketError socketError); + void socketDisconnect(); + void socketReadyRead(); + +protected: + virtual void processIncomeingJson(const QByteArray& jsonbytes) override; + +private: + void processComand(const QByteArray& command, Client& client); +}; + +#endif // TCPSERVER_H diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index b3e317e..fe02c56 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -9,38 +9,20 @@ MainWindow::MainWindow(MainObject * const mainObject, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), - colorChooser(this), - _micro(&mainObject->micro), - _powerItem(mainObject->powerItem) + colorChooser(this) { ui->setupUi(this); - - if(!mainObject->master) - { - connect(ui->pushButton_broadcast, &QPushButton::clicked, this, &MainWindow::sigBrodcast); - } - else - { - connect(ui->pushButton_broadcast, &QPushButton::clicked, this, &MainWindow::sigSave); - connect(ui->pushButton_broadcast, &QPushButton::clicked, this, &MainWindow::saved); - } + connect(ui->pushButton_broadcast, &QPushButton::clicked, this, &MainWindow::sigSave); + connect(ui->pushButton_broadcast, &QPushButton::clicked, this, [this](){QMessageBox::information(this, "Saved", "Settings where saved");}); connect(ui->pushButton_power, SIGNAL(clicked()), this, SLOT(showPowerItemDialog())); - //Relays - if(mainObject->master)connect(ui->pushButton_refesh, &QPushButton::clicked, _micro, &Microcontroller::requestState); - else - { - connect(ui->pushButton_refesh, &QPushButton::clicked, &mainObject->broadCast, &BroadCast::requestJson); - connect(ui->pushButton_refesh, &QPushButton::clicked, &mainObject->broadCast, &BroadCast::requestSensors); - } - connect(&mainObject->items, &ItemStore::itemAdded, ui->relayList, &ItemScrollBox::addItem); - connect(&mainObject->items, &ItemStore::itemDeleted, ui->relayList, &ItemScrollBox::removeItem); + connect(ui->pushButton_refesh, &QPushButton::clicked, mainObject, &MainObject::refresh); + connect(&globalItems, &ItemStore::itemAdded, ui->relayList, &ItemScrollBox::addItem); + connect(&globalItems, &ItemStore::itemDeleted, ui->relayList, &ItemScrollBox::removeItem); - for(size_t i = 0; i < mainObject->items.getItems()->size(); ++i) - { - ui->relayList->addItem(mainObject->items.getItems()->at(i)); - } + for(size_t i = 0; i < globalItems.getItems()->size(); ++i) + ui->relayList->addItem(globalItems.getItems()->at(i)); //Sensors ui->sensorListView->setShowHidden(false); @@ -53,7 +35,7 @@ MainWindow::MainWindow(MainObject * const mainObject, QWidget *parent) : connect(ui->button_color, SIGNAL(clicked()), &colorChooser, SLOT(show())); connect(ui->pushButton_addItem, &QPushButton::clicked, this, &MainWindow::showItemCreationDialog); - connect(ui->relayList, &ItemScrollBox::deleteRequest, &mainObject->items, &ItemStore::removeItem); + connect(ui->relayList, &ItemScrollBox::deleteRequest, &globalItems, &ItemStore::removeItem); ui->splitter->setStretchFactor(1, 1); } @@ -70,14 +52,10 @@ void MainWindow::showPowerItemDialog() diag.exec(); } -void MainWindow::saved() -{ - QMessageBox::information(this, "Saved", "Settings where saved"); -} - void MainWindow::slotChangedRgb(const QColor color) { - _micro->changeRgbColor(color); + (void)color; + //_micro->changeRgbColor(color); } void MainWindow::showItemCreationDialog() diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index e15c466..186b98d 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -5,13 +5,8 @@ #include #include #include -#include -#include "../actors/alarmtime.h" -#include "../microcontroller.h" -#include "../sensors/sensor.h" -#include "../items/itemstore.h" -#include "../items/poweritem.h" -#include "../broadcast.h" +#include +#include "src/items/poweritem.h" class MainObject; @@ -34,13 +29,10 @@ private: QColorDialog colorChooser; - Microcontroller *_micro; - std::shared_ptr _powerItem; signals: - void sigBrodcast(); void sigSave(); void createdItem(std::shared_ptr item); @@ -50,7 +42,6 @@ private slots: void slotChangedRgb(const QColor color); void showPowerItemDialog(); void showItemCreationDialog(); - void saved(); public slots: From 913d7df56dd61a62291277f898fc65a32e731161 Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Sun, 22 Mar 2026 23:23:18 +0100 Subject: [PATCH 4/7] Finish lerge refactor of systems --- SHinterface.pro | 10 ++- src/broadcast.cpp | 139 ----------------------------- src/broadcast.h | 55 ------------ src/iomuliplexer.cpp | 76 ---------------- src/iomuliplexer.h | 54 ------------ src/items/auxitem.cpp | 3 +- src/items/auxitem.h | 2 +- src/items/fixeditemsource.cpp | 14 +++ src/items/fixeditemsource.h | 22 +++++ src/items/item.cpp | 88 +++++++++++++++++-- src/items/item.h | 23 ++++- src/items/itemloadersource.cpp | 38 ++++++++ src/items/itemloadersource.h | 21 +++++ src/items/itemsource.h | 1 + src/items/itemstore.cpp | 61 ++++++------- src/items/itemstore.h | 2 +- src/items/messageitem.cpp | 1 + src/items/poweritem.cpp | 6 +- src/items/poweritem.h | 2 +- src/items/relay.cpp | 2 +- src/items/rgbitem.cpp | 1 + src/items/rgbitem.h | 2 +- src/main.cpp | 66 +++----------- src/mainobject.cpp | 105 +++++++++++++++++----- src/mainobject.h | 27 +++--- src/microcontroller.cpp | 18 ++-- src/sensors/sensor.h | 2 +- src/tcpserver.cpp | 87 +++++++++++++++--- src/tcpserver.h | 24 +++-- src/ui/itemscrollbox.cpp | 15 +--- src/ui/itemwidget.cpp | 67 ++++++++------ src/ui/itemwidget.h | 2 +- src/ui/itemwidget.ui | 6 +- src/ui/mainwindow.cpp | 44 ++++++---- src/ui/mainwindow.h | 6 +- src/ui/mainwindow.ui | 156 +++++++++++++++++---------------- 36 files changed, 614 insertions(+), 634 deletions(-) delete mode 100644 src/broadcast.cpp delete mode 100644 src/broadcast.h delete mode 100644 src/iomuliplexer.cpp delete mode 100644 src/iomuliplexer.h create mode 100644 src/items/fixeditemsource.cpp create mode 100644 src/items/fixeditemsource.h create mode 100644 src/items/itemloadersource.cpp create mode 100644 src/items/itemloadersource.h diff --git a/SHinterface.pro b/SHinterface.pro index e2954c7..f4dad1d 100644 --- a/SHinterface.pro +++ b/SHinterface.pro @@ -26,8 +26,8 @@ QMAKE_CXXFLAGS += -std=c++17 -O2 SOURCES += \ src/actors/factoractor.cpp \ src/actors/polynomalactor.cpp \ + src/items/fixeditemsource.cpp \ src/tcpserver.cpp \ - src/iomuliplexer.cpp \ src/items/messageitem.cpp \ src/items/systemitem.cpp \ src/ui/actorwidgets/factoractorwidget.cpp \ @@ -69,7 +69,8 @@ SOURCES += \ src/items/itemstore.cpp \ src/items/auxitem.cpp \ src/items/rgbitem.cpp \ - src/items/itemsource.cpp + src/items/itemsource.cpp\ + src/items/itemloadersource.cpp SOURCES += \ src/main.cpp \ @@ -81,10 +82,10 @@ SOURCES += \ HEADERS += \ src/actors/factoractor.h \ src/actors/polynomalactor.h \ + src/items/fixeditemsource.h \ src/items/itemsource.h \ src/programmode.h \ src/tcpserver.h \ - src/iomuliplexer.h \ src/items/messageitem.h \ src/items/systemitem.h \ src/ui/actorwidgets/factoractorwidget.h \ @@ -126,7 +127,8 @@ HEADERS += \ src/items/itemstore.h \ src/items/auxitem.h \ src/items/rgbitem.h \ - src/items/itemsource.h + src/items/itemsource.h \ + src/items/itemloadersource.h HEADERS += \ src/microcontroller.h \ diff --git a/src/broadcast.cpp b/src/broadcast.cpp deleted file mode 100644 index ed42f16..0000000 --- a/src/broadcast.cpp +++ /dev/null @@ -1,139 +0,0 @@ -#include "broadcast.h" -#include -#include -#include -#include - -BroadCast::BroadCast(QIODevice* const iodevice, bool master ): master_(master), iodevice_(iodevice) -{ - if(iodevice_ != nullptr) connect(iodevice_, &QIODevice::readyRead, this, &BroadCast::readyRead); -} - -void BroadCast::write(const char * const buffer, const size_t length) -{ - QByteArray mBuffer("bcst: "); - for (size_t i = 0; i < length; ++i) - { - if(buffer[i] != '\n' && buffer[i] != '\0') mBuffer.push_back(buffer[i]); - else - { - mBuffer.push_back('\\'); - if(buffer[i] == '\n')mBuffer.push_back('n'); - else mBuffer.push_back('0'); - } - } - mBuffer.push_back('\n'); - if(iodevice_)iodevice_->write(mBuffer); -} - -void BroadCast::write(const QByteArray& buffer) -{ - write(buffer.data(), buffer.size()); -} - -void BroadCast::sendJson(const QJsonObject& json) -{ - QJsonDocument jsonDocument(json); - QByteArray buffer("JSON: "); - buffer.append(jsonDocument.toJson()); - write(buffer); -} - -void BroadCast::sendSensors() -{ - if(iodevice_) - { - for(auto& sensor: *globalSensors.getSensors()) - iodevice_->write("bcst: "+sensor.toString().toLatin1()+'\n'); - } -} - -void BroadCast::requestSensors() -{ - if(iodevice_) - iodevice_->write("bcst: GETSENSORS\n"); -} - -void BroadCast::requestJson() -{ - if(iodevice_) - iodevice_->write("bcst: GETJSN\n"); -} - -void BroadCast::decodeMaster(const QByteArray& buffer) -{ - if(buffer.startsWith("GETJSN")) - { - qDebug()<<"json requested"; - jsonRequested(); - } - else if(buffer.startsWith("GETSENSORS") ) - { - qDebug()<<"sensors requested"; - sendSensors(); - } -} - -void BroadCast::decode(QByteArray buffer) -{ - qDebug()<<"decodeing: "<= 6 && buffer[0] == 'J' && buffer[1] == 'S' && buffer[2] == 'O' && buffer[3] == 'N' - && buffer[4] == ':') - { - qDebug()<<"got json"; - buffer.remove(0,6); - for(int i = 0; i < buffer.size()-1; ++i) - { - if( buffer[i] == '\\' && buffer[i+1] == 'n' ) - { - buffer[i] = '\n'; - buffer.remove(i+1,1); - } - else if( buffer[i] == '\\' && buffer[i+1] == '0' ) - { - buffer[i] = '\0'; - buffer.remove(i+1,1); - } - } - - QJsonParseError error; - QJsonDocument document = QJsonDocument::fromJson(buffer, &error); - - qDebug()<<"JSON:"; - qDebug()<= 6 && buffer[0] == 'S' && buffer[1] == 'E' && buffer[2] == 'N' && buffer[3] == 'S' - && buffer[4] == 'O' && buffer[5] == 'R') - { - Sensor sensor = Sensor::sensorFromString(buffer); - if(sensor.type != Sensor::TYPE_DUMMY) gotSensorState(sensor); - } -} - -void BroadCast::sendMessage(const QString &title, const QString &body) -{ - write(QByteArray("MESG ") + title.toLatin1() + " BODY " + body.toLatin1()); -} - -void BroadCast::readyRead() -{ - buffer_.append(iodevice_->readAll()); - int newlineIndex = buffer_.indexOf('\n'); - while( newlineIndex != -1 ) - { - if(buffer_.startsWith("bcst: ")) - { - QByteArray tmp = buffer_.mid(6,newlineIndex-6); - decode(tmp); - if(master_)decodeMaster(tmp); - } - buffer_.remove(0, newlineIndex+1); - newlineIndex = buffer_.indexOf('\n'); - } -} diff --git a/src/broadcast.h b/src/broadcast.h deleted file mode 100644 index ae7e802..0000000 --- a/src/broadcast.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef BROADCAST_H -#define BROADCAST_H -#include -#include -#include -#include -#include "sensors/sensor.h" - -class BroadCast: public QObject -{ - Q_OBJECT - -private: - - bool master_; - - static constexpr uint8_t MODE_PREPACKET = 0; - static constexpr uint8_t MODE_PACKET = 1; - - QByteArray buffer_; - - QIODevice* const iodevice_; - - void write(const char * const buffer, const size_t length); - void write(const QByteArray& buffer); - - void decode(QByteArray buffer); - void decodeMaster(const QByteArray& buffer); - -private slots: - - void readyRead(); - -public slots: - - void requestJson(); - void requestSensors(); - -signals: - - void jsonRequested(); - void gotJson(QJsonObject json); - void gotSensorState(Sensor sensor); - -public: - - BroadCast(QIODevice* const iodevice = nullptr, bool master = true); - void sendJson(const QJsonObject& json); - void sendSensors(); - void sendMessage(const QString& title, const QString& body); - -}; - -#endif // BROADCAST_H - diff --git a/src/iomuliplexer.cpp b/src/iomuliplexer.cpp deleted file mode 100644 index 84b3b1a..0000000 --- a/src/iomuliplexer.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "iomuliplexer.h" -#include - -VirutalIODevice::VirutalIODevice(QObject* parent): QBuffer(parent) -{ - -} - -qint64 VirutalIODevice::writeData(const char *data, qint64 len) -{ - blockSignals(true); - qint64 ret = QBuffer::writeData(data, len); - blockSignals(false); - masterReadyRead(); - return ret; -} - -qint64 VirutalIODevice::masterWrite(const QByteArray &byteArray) -{ - return masterWrite(byteArray.data(), byteArray.length()); -} - -qint64 VirutalIODevice::masterWrite(const char *data, qint64 maxSize) -{ - blockSignals(true); - qint64 ret = QBuffer::writeData(data, maxSize); - blockSignals(false); - readyRead(); - return ret; -} - -IoMuliplexer::IoMuliplexer(QIODevice* mainDevice, QObject* Parent): IoMuliplexer(Parent) -{ - setIoDevice(mainDevice); -} - -IoMuliplexer::IoMuliplexer(QObject* Parent): QObject(Parent) -{ - -} - -IoMuliplexer::~IoMuliplexer() -{ - for(size_t i = 0; i < ioDevices_.size(); ++i) delete ioDevices_[i]; - ioDevices_.clear(); -} - -void IoMuliplexer::setIoDevice(QIODevice* mainDevice) -{ - mainDevice_ = mainDevice; - connect(mainDevice_, &QIODevice::readyRead, this, &IoMuliplexer::mainIsReadyRead); -} - -QIODevice* IoMuliplexer::getIoDevice() -{ - ioDevices_.push_back(new VirutalIODevice); - ioDevices_.back()->open(QIODevice::ReadWrite); - connect(ioDevices_.back(), &VirutalIODevice::masterReadyRead, this, &IoMuliplexer::clientIsReadyRead); - return ioDevices_.back(); -} - -void IoMuliplexer::clientIsReadyRead() -{ - VirutalIODevice* device = dynamic_cast(sender()); - if(device) - { - QByteArray array = device->readAll(); - mainDevice_->write(array); - } -} - -void IoMuliplexer::mainIsReadyRead() -{ - QByteArray array = mainDevice_->readAll(); - for(size_t i = 0; i < ioDevices_.size(); ++i) ioDevices_[i]->masterWrite(array); -} diff --git a/src/iomuliplexer.h b/src/iomuliplexer.h deleted file mode 100644 index 68ad624..0000000 --- a/src/iomuliplexer.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef IOMULIPLEXER_H -#define IOMULIPLEXER_H - -#include -#include -#include -#include - -class VirutalIODevice: public QBuffer -{ - Q_OBJECT -public: - - VirutalIODevice(QObject* parent = nullptr); - virtual ~VirutalIODevice() override {} - - virtual qint64 writeData(const char *data, qint64 len) override; - - qint64 masterWrite(const QByteArray &byteArray); - qint64 masterWrite(const char *data, qint64 maxSize); - -signals: - - void masterReadyRead(); - -}; - - -class IoMuliplexer: public QObject -{ - Q_OBJECT -private: - - QIODevice* mainDevice_; - std::vector< VirutalIODevice* > ioDevices_; - -public: - explicit IoMuliplexer(QIODevice* mainDevice, QObject* Parent = nullptr); - explicit IoMuliplexer(QObject* Parent = nullptr); - - ~IoMuliplexer(); - - void setIoDevice(QIODevice* mainDevice); - - QIODevice* getIoDevice(); - -private slots: - - void mainIsReadyRead(); - void clientIsReadyRead(); - -}; - -#endif // IOMULIPLEXER_H diff --git a/src/items/auxitem.cpp b/src/items/auxitem.cpp index 42f3efd..5bee87e 100644 --- a/src/items/auxitem.cpp +++ b/src/items/auxitem.cpp @@ -3,11 +3,12 @@ AuxItem::AuxItem(Microcontroller* micro, uint32_t itemIdIn, QString name, uint8_t value, QObject* parent): Item(itemIdIn, name, value, parent), micro_(micro) { - + type_ = ITEM_VALUE_UINT; } void AuxItem::enactValue(uint8_t value) { + assert(micro_); micro_->setAuxPwm(value); } diff --git a/src/items/auxitem.h b/src/items/auxitem.h index 0483c39..658b907 100644 --- a/src/items/auxitem.h +++ b/src/items/auxitem.h @@ -13,7 +13,7 @@ protected: virtual void enactValue(uint8_t value) override; public: - AuxItem(Microcontroller* micro, uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "", + AuxItem(Microcontroller* micro = nullptr, uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "", uint8_t value = 0, QObject* parent = nullptr); virtual void store(QJsonObject& json) override; diff --git a/src/items/fixeditemsource.cpp b/src/items/fixeditemsource.cpp new file mode 100644 index 0000000..d1abc21 --- /dev/null +++ b/src/items/fixeditemsource.cpp @@ -0,0 +1,14 @@ +#include "fixeditemsource.h" + +FixedItemSource::FixedItemSource(Microcontroller* micro, QObject *parent): + ItemSource{parent}, + powerItem(new PowerItem(5487423)), + rgbItem(new RgbItem(micro, 5487422, "Rgb Lights")), + auxItem(new AuxItem(micro, 5487421, "Desk Light")) +{ +} + +void FixedItemSource::refresh() +{ + gotItems({powerItem, rgbItem, auxItem}); +} diff --git a/src/items/fixeditemsource.h b/src/items/fixeditemsource.h new file mode 100644 index 0000000..150b9a1 --- /dev/null +++ b/src/items/fixeditemsource.h @@ -0,0 +1,22 @@ +#ifndef FIXEDITEMSOURCE_H +#define FIXEDITEMSOURCE_H + +#include "itemsource.h" +#include "poweritem.h" +#include "rgbitem.h" +#include "auxitem.h" +#include "src/microcontroller.h" + +class FixedItemSource : public ItemSource +{ + Q_OBJECT + std::shared_ptr powerItem; + std::shared_ptr rgbItem; + std::shared_ptr auxItem; + +public: + explicit FixedItemSource(Microcontroller* micro, QObject *parent = nullptr); + virtual void refresh() override; +}; + +#endif // FIXEDITEMSOURCE_H diff --git a/src/items/item.cpp b/src/items/item.cpp index 2596b4f..9b80254 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -7,10 +7,14 @@ #include "relay.h" #include "messageitem.h" #include "systemitem.h" +#include "auxitem.h" +#include "poweritem.h" +#include "rgbitem.h" #include -ItemData::ItemData(uint32_t itemIdIn, QString name, uint8_t value): name_(name), value_(value), itemId_(itemIdIn) +ItemData::ItemData(uint32_t itemIdIn, QString name, uint8_t value, bool loaded, bool hidden, item_value_type_t type): + name_(name), value_(value), itemId_(itemIdIn), loaded_(loaded), hidden_(hidden), type_(type) { } @@ -48,9 +52,47 @@ void ItemData::load(const QJsonObject &json, const bool preserve) { name_ = json["Name"].toString(name_); itemId_ = static_cast(json["ItemId"].toDouble(0)); + value_ = json["Value"].toInt(); } } +bool ItemData::getLoaded() const +{ + return loaded_; +} + +void ItemData::setLoaded(bool loaded) +{ + loaded_ = loaded; +} + +bool ItemData::hasChanged(const ItemData& other) +{ + if(other != *this) + return false; + if(other.getName() != getName()) + return true; + if(other.getValue() != getValue()) + return true; + if(other.getLoaded() != getLoaded()) + return true; + return false; +} + +bool ItemData::isHidden() +{ + return hidden_; +} + +void ItemData::setHidden(bool hidden) +{ + hidden_ = hidden; +} + +item_value_type_t ItemData::getValueType() +{ + return type_; +} //item @@ -96,7 +138,8 @@ void Item::load(const QJsonObject &json, const bool preserve) if(actorsArray[i].isObject()) { std::shared_ptr actor = Actor::loadActor(actorsArray[i].toObject()); - if(actor != nullptr) addActor(actor); + if(actor != nullptr) + addActor(actor); } } } @@ -109,6 +152,7 @@ void Item::actorSetValue(uint8_t value) void Item::setValue(uint8_t value) { + qDebug()<<__func__; informValue(value); if(programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY) enactValue(value); @@ -116,9 +160,12 @@ void Item::setValue(uint8_t value) void Item::informValue(uint8_t value) { - value_ = value; - valueChanged(value_); - updated(*this); + if(value_ != value) + { + value_ = value; + valueChanged(value_); + updated(*this); + } } void Item::enactValue(uint8_t value) @@ -135,14 +182,16 @@ void Item::addActor(std::shared_ptr actor) connect(this, &Item::valueChanged, actor.get(), &Actor::onValueChanged); std::shared_ptr sensorActor = std::dynamic_pointer_cast(actor); - if(sensorActor)connect(&globalSensors, &SensorStore::sensorChangedState, sensorActor.get(), &SensorActor::sensorEvent); + if(sensorActor) + connect(&globalSensors, &SensorStore::sensorChangedState, sensorActor.get(), &SensorActor::sensorEvent); std::shared_ptr regulator = std::dynamic_pointer_cast(actor); - if(regulator)connect(&globalSensors, &SensorStore::sensorChangedState, regulator.get(), &Regulator::sensorEvent); + if(regulator) + connect(&globalSensors, &SensorStore::sensorChangedState, regulator.get(), &Regulator::sensorEvent); std::shared_ptr polynomalActor = std::dynamic_pointer_cast(actor); - if(polynomalActor != nullptr )connect(&globalSensors, &SensorStore::sensorChangedState, polynomalActor.get(), - &PolynomalActor::sensorEvent); + if(polynomalActor != nullptr ) + connect(&globalSensors, &SensorStore::sensorChangedState, polynomalActor.get(), &PolynomalActor::sensorEvent); } bool Item::removeActor(std::shared_ptr actor) @@ -189,6 +238,14 @@ void Item::setActorsActive(bool in) in ? actors_[i]->makeActive() : actors_[i]->makeInactive(); } +void Item::mergeLoaded(Item& item) +{ + name_ = item.name_; + actors_.clear(); + for(std::shared_ptr actor : item.actors_) + addActor(actor); +} + std::shared_ptr Item::loadItem(const QJsonObject& json) { std::shared_ptr newItem = nullptr; @@ -206,8 +263,21 @@ std::shared_ptr Item::loadItem(const QJsonObject& json) } else if(json["Type"].toString("") == "Aux") { + newItem = std::shared_ptr(new AuxItem); + } + else if(json["Type"].toString("") == "Power") + { + newItem = std::shared_ptr(new PowerItem); + } + else if(json["Type"].toString("") == "Rgb") + { + newItem = std::shared_ptr(new RgbItem); } if(newItem) + { newItem->load(json); + newItem->setLoaded(true); + } return newItem; } + diff --git a/src/items/item.h b/src/items/item.h index bfa43f6..1aaa090 100644 --- a/src/items/item.h +++ b/src/items/item.h @@ -8,15 +8,29 @@ class Actor; +typedef enum { + ITEM_VALUE_BOOL = 0, + ITEM_VALUE_UINT, + ITEM_VALUE_NO_VALUE +} item_value_type_t; + class ItemData { protected: QString name_; uint8_t value_; uint32_t itemId_; + bool loaded_; + bool hidden_; + item_value_type_t type_; public: - ItemData(uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "Item", uint8_t value = 0); + ItemData(uint32_t itemIdIn = QRandomGenerator::global()->generate(), + QString name = "Item", + uint8_t value = 0, + bool loaded = false, + bool hidden = false, + item_value_type_t type = ITEM_VALUE_BOOL); inline bool operator==(const ItemData& in) const { @@ -29,8 +43,14 @@ public: uint32_t id() const; + bool hasChanged(const ItemData& other); void setName(QString name); uint8_t getValue() const; + bool getLoaded() const; + void setLoaded(bool loaded); + bool isHidden(); + void setHidden(bool hidden); + item_value_type_t getValueType(); virtual QString getName() const; virtual void store(QJsonObject& json); virtual void load(const QJsonObject& json, const bool preserve = false); @@ -72,6 +92,7 @@ public: void setOverride(const bool in); bool getOverride(); void informValue(uint8_t value); + void mergeLoaded(Item& item); virtual void store(QJsonObject& json); virtual void load(const QJsonObject& json, const bool preserve = false); diff --git a/src/items/itemloadersource.cpp b/src/items/itemloadersource.cpp new file mode 100644 index 0000000..d5e6afa --- /dev/null +++ b/src/items/itemloadersource.cpp @@ -0,0 +1,38 @@ +#include "itemloadersource.h" + +#include + +ItemLoaderSource::ItemLoaderSource(const QJsonObject& json, QObject *parent): + ItemSource{parent}, + json(json) +{ +} + +void ItemLoaderSource::refresh() +{ + std::vector> items; + const QJsonArray itemsArray(json["Items"].toArray()); + for(int i = 0; i < itemsArray.size(); ++i) + { + if(!itemsArray[i].isObject()) + continue; + + const QJsonObject itemObject = itemsArray[i].toObject(); + std::shared_ptr newItem = Item::loadItem(itemObject); + if(newItem) + { + items.push_back(newItem); + qDebug()<<"Loaded item"<getName(); + } + } + gotItems(items); +} + +void ItemLoaderSource::updateJson(const QJsonObject& json) +{ + this->json = json; +} + +ItemLoaderSource::~ItemLoaderSource() +{} + diff --git a/src/items/itemloadersource.h b/src/items/itemloadersource.h new file mode 100644 index 0000000..c31c7fd --- /dev/null +++ b/src/items/itemloadersource.h @@ -0,0 +1,21 @@ +#ifndef ITEMLOADERSOURCE_H +#define ITEMLOADERSOURCE_H + +#include + +#include "itemsource.h" + +class ItemLoaderSource : public ItemSource +{ + Q_OBJECT + + QJsonObject json; + +public: + explicit ItemLoaderSource(const QJsonObject& json = QJsonObject(), QObject *parent = nullptr); + ~ItemLoaderSource(); + void updateJson(const QJsonObject& json); + virtual void refresh() override; +}; + +#endif // ITEMLOADERSOURCE_H diff --git a/src/items/itemsource.h b/src/items/itemsource.h index 8e26c18..9fee9c1 100644 --- a/src/items/itemsource.h +++ b/src/items/itemsource.h @@ -18,6 +18,7 @@ public slots: signals: void gotItems(std::vector> items, bool inform = true); + void requestReplaceItems(std::vector> items); void updateItems(std::vector items, bool inform = true); }; diff --git a/src/items/itemstore.cpp b/src/items/itemstore.cpp index e681a97..1242afc 100644 --- a/src/items/itemstore.cpp +++ b/src/items/itemstore.cpp @@ -21,15 +21,15 @@ void ItemStore::addItem(std::shared_ptr item, bool inform) { items_.push_back(std::shared_ptr(item)); connect(item.get(), &Item::updated, this, &ItemStore::itemUpdateSlot); - qDebug()<<"Item"<getName()<<"added"; + qDebug()<<"Item"<getName()<<"added"<<(item->getLoaded() ? "from loaded" : ""); itemAdded(std::weak_ptr(items_.back())); } - else if(item->getValue() != matched->getValue()) + else { - if(inform) - matched->informValue(item->getValue()); - else - matched->setValue(item->getValue()); + if(item->getLoaded()) + matched->mergeLoaded(*item); + else if(item->getValue() != matched->getValue()) + updateItem(*item, inform); } } @@ -53,6 +53,19 @@ void ItemStore::removeItem(const ItemData& item) } } +void ItemStore::replaceItems(const std::vector>& items) +{ + addItems(items, true); + std::vector deletedItems; + for(std::shared_ptr item : items_) + { + if(std::find_if(items.begin(), items.end(), [item](const std::shared_ptr other){return *item == *other;}) == items.end()) + deletedItems.push_back(*item); + } + for(const ItemData& item : deletedItems) + removeItem(item); +} + void ItemStore::clear() { for(size_t i = 0; i < items_.size(); ++i) itemDeleted(*items_[i]); @@ -66,22 +79,25 @@ void ItemStore::updateItems(std::vector items, bool inform) updateItem(item, inform); } - void ItemStore::updateItem(const ItemData& item, bool inform) { for(unsigned i = 0; i < items_.size(); i++ ) { if(items_[i]->operator==(item)) { - if(items_[i]->getValue() != item.getValue()) + if(items_[i]->hasChanged(item)) { - if(inform) - items_[i]->informValue(item.getValue()); - else - items_[i]->setValue(item.getValue()); + if(items_[i]->getValue() != item.getValue()) + { + items_[i]->setLoaded(false); + if(inform) + items_[i]->informValue(item.getValue()); + else + items_[i]->setValue(item.getValue()); + } + qDebug()<<"Item"<getName()<<"updated"; + itemUpdated(items_[i]); } - qDebug()<<"Item"<getName()<<"updated"; - itemUpdated(items_[i]); } } } @@ -98,24 +114,8 @@ void ItemStore::store(QJsonObject& json) json["Items"] = itemsArray; } -void ItemStore::load(const QJsonObject& json) -{ - const QJsonArray itemsArray(json["Items"].toArray(QJsonArray())); - for(int i = 0; i < itemsArray.size(); ++i) - { - if(!itemsArray[i].isObject()) - continue; - - const QJsonObject itemObject = itemsArray[i].toObject(); - std::shared_ptr newItem = Item::loadItem(itemObject); - if(newItem) - addItem(newItem); - } -} - void ItemStore::itemUpdateSlot(ItemData data) { - qDebug()<<__func__; for(std::shared_ptr& item: items_) { if(*item == data) @@ -138,6 +138,7 @@ void ItemStore::registerItemSource(ItemSource* source) qDebug()<<__func__< item, bool inform = true); void addItems(const std::vector>& itemsIn, bool inform = true); + void replaceItems(const std::vector>& items); void updateItems(std::vector items, bool inform = true); void updateItem(const ItemData& item, bool inform = true); void refresh(); diff --git a/src/items/messageitem.cpp b/src/items/messageitem.cpp index 32f9d5e..151b934 100644 --- a/src/items/messageitem.cpp +++ b/src/items/messageitem.cpp @@ -7,6 +7,7 @@ MessageItem::MessageItem(uint32_t itemIdIn, QString name, uint8_t value, QObjec Item(itemIdIn, name, value, parent) { alertSound.setVolume(1.0); + type_ = ITEM_VALUE_NO_VALUE; } MessageItem::MessageItem(const ItemData& itemData, QObject *parent): diff --git a/src/items/poweritem.cpp b/src/items/poweritem.cpp index cea1470..2b2e4e1 100644 --- a/src/items/poweritem.cpp +++ b/src/items/poweritem.cpp @@ -3,11 +3,13 @@ #include #include -PowerItem::PowerItem(uint32_t itemIdIn, QString name, uint8_t value, QObject* parent): Item(itemIdIn, name, value, - parent) +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)); PowerItem::setValue(true); + hidden_ = true; + type_ = ITEM_VALUE_NO_VALUE; } void PowerItem::enactValue(uint8_t value) diff --git a/src/items/poweritem.h b/src/items/poweritem.h index 76dea5e..dda2f35 100644 --- a/src/items/poweritem.h +++ b/src/items/poweritem.h @@ -22,7 +22,7 @@ protected: virtual void enactValue(uint8_t value) override; public: - PowerItem(uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "", uint8_t value = 0, + PowerItem(uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "Power", uint8_t value = 0, QObject* parent = nullptr); void emmitSensor() { diff --git a/src/items/relay.cpp b/src/items/relay.cpp index e0a3d30..f801e1b 100644 --- a/src/items/relay.cpp +++ b/src/items/relay.cpp @@ -9,11 +9,11 @@ Relay::Relay(uint8_t id, QString name, uint16_t address, bool state, QObject* pa id_(id), address_(address) { itemId_ = address | ((uint32_t)id << 16); - qDebug()<<"Relay "<rgbOn() : micro_->rgbOff(); } diff --git a/src/items/rgbitem.h b/src/items/rgbitem.h index 6e2a923..8e6ae8c 100644 --- a/src/items/rgbitem.h +++ b/src/items/rgbitem.h @@ -13,7 +13,7 @@ protected: virtual void enactValue(uint8_t value) override; public: - RgbItem(Microcontroller* micro, uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "", + RgbItem(Microcontroller* micro = nullptr, uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "", uint8_t value = 0, QObject* parent = nullptr); virtual void store(QJsonObject& json) override; diff --git a/src/main.cpp b/src/main.cpp index f94ff78..d201f11 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,54 +12,6 @@ #include "mainobject.h" #include "programmode.h" - -QJsonObject getJsonObjectFromDisk(const QString& filePath, bool* error = nullptr) -{ - QFile file; - file.setFileName(filePath); - - bool ret = file.open(QIODevice::ReadOnly); - if(!file.isOpen() || !ret) - { - std::cerr<<"Can not open config file: "<waitForConnected(1000)) { qCritical()<<"Can not connect to tcp micro"; - storeJsonObjectToDisk(json, parser.value(settingsPathOption)); + MainObject::storeJsonObjectToDisk(settingsPath, json); if(programMode == PROGRAM_MODE_PRIMARY) QMessageBox::critical(nullptr, "Error", "Can not connect to tcp micro"); return 1; @@ -145,21 +98,23 @@ int main(int argc, char *argv[]) if(!microPort->isOpen()) { qCritical()<<"Can not open serial port"< item){globalItems.addItem(item, false);}); w->show(); } @@ -167,14 +122,13 @@ int main(int argc, char *argv[]) delete w; delete microDevice; - mainObject.store(json); - storeJsonObjectToDisk(json, parser.value(settingsPathOption)); } else { SecondaryMainObject mainObject(parser.value(hostOption), parser.value(portOption).toInt()); MainWindow w(&mainObject); - //QObject::connect(&w, &MainWindow::sigSave, &mainObject, &MainObject::sendJson); + QObject::connect(&w, &MainWindow::createdItem, &globalItems, [](std::shared_ptr item){globalItems.addItem(item, false);}); + QObject::connect(&w, &MainWindow::sigSave, mainObject.tcpClient, &TcpClient::sendItems); w.show(); retVal = a.exec(); diff --git a/src/mainobject.cpp b/src/mainobject.cpp index d92e0ae..4f31e78 100644 --- a/src/mainobject.cpp +++ b/src/mainobject.cpp @@ -20,17 +20,61 @@ void MainObject::refresh() globalItems.refresh(); } -PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, QJsonObject* settings, QString host, int port, QObject *parent) : +QJsonObject MainObject::getJsonObjectFromDisk(const QString& filename, bool* error) +{ + QFile file; + file.setFileName(filename); + + bool ret = file.open(QIODevice::ReadOnly); + if(!file.isOpen() || !ret) + { + std::cerr<<"Can not open config file: "<launch(QHostAddress(host), port); + connect(&globalItems, &ItemStore::itemUpdated, tcpServer, &TcpServer::itemUpdated); } PrimaryMainObject::~PrimaryMainObject() { - store(*settings); + storeToDisk(settingsPath); } void PrimaryMainObject::store(QJsonObject &json) @@ -58,22 +109,28 @@ void PrimaryMainObject::store(QJsonObject &json) void PrimaryMainObject::load(const QJsonObject& json) { + settings = json; + itemLoader.updateJson(json); globalItems.clear(); - rgbItem->removeAllActors(); - auxItem->removeAllActors(); - powerItem->removeAllActors(); - globalItems.addItem(rgbItem); - globalItems.addItem(auxItem); - globalItems.addItem(powerItem); - globalItems.load(json); - if(json["Items"].toArray().size() >= 2) - { - rgbItem->load(json["Items"].toArray()[0].toObject()); - auxItem->load(json["Items"].toArray()[1].toObject()); - } globalItems.refresh(); } +bool PrimaryMainObject::storeToDisk(const QString& filename) +{ + store(settings); + itemLoader.updateJson(settings); + return storeJsonObjectToDisk(filename, settings); +} + +bool PrimaryMainObject::loadFromDisk(const QString& filename) +{ + bool error = false; + QJsonObject json = getJsonObjectFromDisk(filename, &error); + if(!error) + load(json); + return error; +} + SecondaryMainObject::SecondaryMainObject(QString host, int port, QObject *parent) : MainObject(parent), tcpClient(new TcpClient) @@ -84,8 +141,12 @@ SecondaryMainObject::SecondaryMainObject(QString host, int port, QObject *parent if(!tcpClient->launch(QHostAddress(host), port)) { QMessageBox::critical(nullptr, "Error", "Could not connect to "+host+":"+QString::number(port)); - exit(1); + QMetaObject::invokeMethod(this, [](){exit(1);}, Qt::QueuedConnection); } + + connect(&globalItems, &ItemStore::itemUpdated, tcpClient, &TcpClient::itemUpdated); + + globalItems.refresh(); } SecondaryMainObject::~SecondaryMainObject() diff --git a/src/mainobject.h b/src/mainobject.h index 93a787a..05b8140 100644 --- a/src/mainobject.h +++ b/src/mainobject.h @@ -14,11 +14,8 @@ #include "microcontroller.h" #include "ui/mainwindow.h" #include "sensors/sunsensor.h" -#include "items/auxitem.h" -#include "items/rgbitem.h" -#include "items/poweritem.h" -#include "iomuliplexer.h" -#include "broadcast.h" +#include "items/fixeditemsource.h" +#include "items/itemloadersource.h" #include "tcpserver.h" class MainObject : public QObject @@ -28,6 +25,8 @@ class MainObject : public QObject public: explicit MainObject(QObject *parent = nullptr); ~MainObject(); + static QJsonObject getJsonObjectFromDisk(const QString& filename, bool* error = nullptr); + static bool storeJsonObjectToDisk(const QString& filename, const QJsonObject& json); public slots: void refresh(); @@ -38,11 +37,8 @@ class PrimaryMainObject : public MainObject Q_OBJECT public: - QJsonObject* settings; - - //io - QIODevice * const microDevice = nullptr; - IoMuliplexer ioMultiplexer; + QString settingsPath; + QJsonObject settings; Microcontroller micro; TcpServer* tcpServer; @@ -50,16 +46,17 @@ public: //sensors SunSensorSource sunSensorSource; - //items - std::shared_ptr powerItem; - std::shared_ptr rgbItem; - std::shared_ptr auxItem; + //item sources + FixedItemSource fixedItems; + ItemLoaderSource itemLoader; public: - explicit PrimaryMainObject(QIODevice* microDevice, QJsonObject* settings, QString host, int port, QObject *parent = nullptr); + explicit PrimaryMainObject(QIODevice* microDevice, const QString& settingsPath, const QString& host, int port, QObject *parent = nullptr); ~PrimaryMainObject(); void store(QJsonObject& json); void load(const QJsonObject& json); + bool storeToDisk(const QString& filename); + bool loadFromDisk(const QString& filename); }; class SecondaryMainObject : public MainObject diff --git a/src/microcontroller.cpp b/src/microcontroller.cpp index 174cfd0..4833461 100644 --- a/src/microcontroller.cpp +++ b/src/microcontroller.cpp @@ -138,12 +138,10 @@ void Microcontroller::processList(const QString& buffer) if(bufferList.size() >= 8 && buffer.startsWith("ITEM NUMBER:")) { relayList.push_back(processRelayLine(buffer)); - qDebug()<<"Micro item recived:"<getName(); } else if(buffer.contains("EOL")) { listMode = false; - qDebug()<<"got relay list " << relayList.size(); gotItems(relayList); relayList.clear(); } @@ -158,13 +156,13 @@ void Microcontroller::processRelayState(const QString& buffer) void Microcontroller::processSensorState(const QString& buffer) { Sensor sensor = Sensor::sensorFromString(buffer); - if(sensor.type != Sensor::TYPE_DUMMY) gotSensorState(sensor); + if(sensor.type != Sensor::TYPE_DUMMY) + gotSensorState(sensor); } void Microcontroller::processMicroReturn() { - qDebug()<<_buffer; if(listMode) { processList(_buffer); @@ -176,8 +174,14 @@ void Microcontroller::processMicroReturn() listMode = true; relayList.clear(); } - else if(_buffer.startsWith("ITEM NUMBER:"))processRelayState(_buffer); - else if(_buffer.startsWith("SENSOR")) processSensorState(_buffer); + else if(_buffer.startsWith("ITEM NUMBER:")) + { + processRelayState(_buffer); + } + else if(_buffer.startsWith("SENSOR")) + { + processSensorState(_buffer); + } } } @@ -188,8 +192,6 @@ void Microcontroller::isReadyRead() while(_port->getChar(&charBuf)) { _buffer.push_back(charBuf); - - qDebug()<<_buffer; if(_buffer.endsWith('\n') ) { _buffer.remove('\n'); diff --git a/src/sensors/sensor.h b/src/sensors/sensor.h index 80c37ab..86c82b9 100644 --- a/src/sensors/sensor.h +++ b/src/sensors/sensor.h @@ -46,7 +46,7 @@ public: { type = json["SensorType"].toInt(0); id = json["Id"].toInt(0); - field = json["Field"].toInt(0); + field = json["Field"].toDouble(0); name = json["Name"].toString("Sensor"); lastSeen = QDateTime::fromString(json["LastSeen"].toString("")); hidden = json["Hidden"].toBool(false); diff --git a/src/tcpserver.cpp b/src/tcpserver.cpp index b6f82e2..f49150f 100644 --- a/src/tcpserver.cpp +++ b/src/tcpserver.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "items/item.h" #include "items/itemstore.h" @@ -14,7 +15,7 @@ TcpService::TcpService(QObject* parent): QJsonObject TcpService::createMessage(const QString& type, const QJsonArray& data) { QJsonObject json; - json["MesageType"] = type; + json["MessageType"] = type; json["Data"] = data; return json; } @@ -26,17 +27,18 @@ void TcpService::sensorEvent(Sensor sensor) sensor.store(sensorjson); sensors.append(sensorjson); QJsonObject json = createMessage("SensorUpdate", sensors); - sendJson(json); } void TcpService::itemUpdated(std::weak_ptr item) { + qDebug()<<__func__; QJsonArray items; QJsonObject itemjson; item.lock()->store(itemjson); items.append(itemjson); QJsonObject json = createMessage("ItemUpdate", items); + json["FullList"] = false; sendJson(json); } @@ -67,22 +69,26 @@ void TcpService::sendItems() item->store(itemjson); items.append(itemjson); } - sendJson(createMessage("ItemUpdate", items)); + QJsonObject json = createMessage("ItemUpdate", items); + json["FullList"] = true; + sendJson(json); } void TcpService::processIncomeingJson(const QByteArray& jsonbytes) { - qDebug()<<__func__<> items; for(QJsonValueRef itemjson : data) @@ -129,7 +137,10 @@ void TcpClient::processIncomeingJson(const QByteArray& jsonbytes) QJsonObject jsonobject = itemjson.toObject(); std::shared_ptr item = Item::loadItem(jsonobject); if(item) + { + item->setLoaded(false); items.push_back(item); + } } if(!items.empty()) gotItems(items, true); @@ -140,6 +151,45 @@ void TcpClient::processIncomeingJson(const QByteArray& jsonbytes) } } +void TcpClient::processComand(const QByteArray& command) +{ + if(command.startsWith("MSG JSON LEN ")) + { + state = STATE_RECV_JSON; + recievebytes = command.mid(13).toLongLong(); + } +} + +void TcpClient::socketReadyRead() +{ + buffer += socket->readAll(); + bool remianing = true; + while(remianing) + { + remianing = false; + while(state == STATE_IDLE && buffer.contains('\n')) + { + size_t newlineIndex = buffer.indexOf('\n'); + QByteArray command = buffer.left(newlineIndex); + buffer.remove(0, newlineIndex+1); + processComand(command); + remianing = true; + } + if(state == STATE_RECV_JSON) + { + if(recievebytes <= buffer.size()) + { + QByteArray json = buffer.left(recievebytes); + buffer.remove(0, recievebytes); + recievebytes = 0; + state = STATE_IDLE; + processIncomeingJson(json); + remianing = true; + } + } + } +} + TcpClient::~TcpClient() { delete socket; @@ -149,6 +199,7 @@ TcpServer::TcpServer(QObject* parent): TcpService(parent), server(this) { + connect(&server, &QTcpServer::newConnection, this, &TcpServer::incomingConnection); } void TcpServer::sendJson(const QJsonObject& json) @@ -167,17 +218,27 @@ void TcpServer::processIncomeingJson(const QByteArray& jsonbytes) QString type = json["MessageType"].toString(); if(type == "ItemUpdate") { + qDebug()<<"Got Items"; QJsonArray data = json["Data"].toArray(); + bool FullList = json["FullList"].toBool(false); std::vector> items; for(QJsonValueRef itemjson : data) { QJsonObject jsonobject = itemjson.toObject(); std::shared_ptr item = Item::loadItem(jsonobject); + item->setLoaded(FullList); if(item) items.push_back(item); } - if(!items.empty()) + if(FullList && !items.empty()) + { + requestReplaceItems(items); + sigRequestSave(); + } + else if(!items.empty()) + { gotItems(items, false); + } } else { @@ -195,6 +256,7 @@ void TcpServer::incomingConnection() while(server.hasPendingConnections()) { QTcpSocket* client = server.nextPendingConnection(); + qDebug()<<"Got new client from"<peerAddress().toString(); if(client) { clients.push_back({client}); @@ -231,11 +293,11 @@ void TcpServer::socketDisconnect() void TcpServer::processComand(const QByteArray& command, Client& client) { - qDebug()<<__func__<readAll(); + QByteArray newChars = clients[i].socket->readAll(); + clients[i].buffer += newChars; + bool remianing = true; while(remianing) { + qDebug()< item) { if(auto workItem = item.lock()) { - if(dynamic_cast(workItem.get())) - { - widgets_.push_back(new ItemWidget(item, true)); - } - else if(dynamic_cast(workItem.get())) - { - widgets_.push_back(new ItemWidget(item, false, true)); - } - else - { - widgets_.push_back(new ItemWidget(item)); - } + if(workItem->isHidden()) + return; + widgets_.push_back(new ItemWidget(item)); ui->relayWidgetVbox->addWidget(widgets_.back()); connect(widgets_.back(), &ItemWidget::deleteRequest, this, &ItemScrollBox::deleteRequest); connect(widgets_.back(), &ItemWidget::deleteRequest, this, &ItemScrollBox::removeItem); diff --git a/src/ui/itemwidget.cpp b/src/ui/itemwidget.cpp index c1f681d..d073e50 100644 --- a/src/ui/itemwidget.cpp +++ b/src/ui/itemwidget.cpp @@ -5,39 +5,47 @@ #include #include -ItemWidget::ItemWidget(std::weak_ptr item, bool analog, bool nameOnly, QWidget *parent) : +ItemWidget::ItemWidget(std::weak_ptr item, QWidget *parent) : QWidget(parent), item_(item), ui(new Ui::ItemWidget) { ui->setupUi(this); - if(analog) + if(auto workingItem = item_.lock()) { - ui->horizontalSpacer->changeSize(0,0); - ui->checkBox->hide(); - } - else if(nameOnly) - { - ui->checkBox->hide(); - ui->slider->hide(); - } - else ui->slider->hide(); + if(workingItem->getValueType() == ITEM_VALUE_UINT) + { + ui->horizontalSpacer->changeSize(0,0); + ui->checkBox->hide(); + } + else if(workingItem->getValueType() == ITEM_VALUE_NO_VALUE) + { + ui->checkBox->hide(); + ui->slider->hide(); + } + else + { + ui->slider->hide(); + } - if(auto workingRelay = item_.lock()) - { - ui->checkBox->setChecked(workingRelay->getValue()); + ui->checkBox->setChecked(workingItem->getValue()); - ui->label->setText(workingRelay->getName()); + ui->label->setText(workingItem->getName()); - if(analog)connect(ui->slider, &QSlider::valueChanged, this, &ItemWidget::moveToValue); - else connect(ui->checkBox, &QCheckBox::toggled, this, &ItemWidget::moveToState); + if(workingItem->getValueType() == ITEM_VALUE_UINT) + connect(ui->slider, &QSlider::valueChanged, this, &ItemWidget::moveToValue); + else + connect(ui->checkBox, &QCheckBox::toggled, this, &ItemWidget::moveToState); connect(ui->pushButton, &QPushButton::clicked, this, &ItemWidget::showSettingsDialog); - connect(workingRelay.get(), &Relay::valueChanged, this, &ItemWidget::stateChanged); + connect(workingItem.get(), &Relay::valueChanged, this, &ItemWidget::stateChanged); connect(ui->pushButton_Remove, &QPushButton::clicked, this, &ItemWidget::deleteItem); } - else disable(); + else + { + disable(); + } } void ItemWidget::deleteItem() @@ -50,14 +58,18 @@ void ItemWidget::deleteItem() void ItemWidget::moveToValue(int value) { - if(auto workingItem = item_.lock()) workingItem->setValue(value); - else disable(); + if(auto workingItem = item_.lock()) + workingItem->setValue(value); + else + disable(); } void ItemWidget::moveToState(bool state) { - if(auto workingItem = item_.lock()) workingItem->setValue(state); - else disable(); + if(auto workingItem = item_.lock()) + workingItem->setValue(state); + else + disable(); } void ItemWidget::disable() @@ -70,9 +82,9 @@ void ItemWidget::disable() bool ItemWidget::controles(const ItemData& relay) { - if(auto workingRelay = item_.lock()) + if(auto workingItem = item_.lock()) { - if(relay == *workingRelay) return true; + if(relay == *workingItem) return true; else return false; } return true; @@ -80,9 +92,9 @@ bool ItemWidget::controles(const ItemData& relay) void ItemWidget::showSettingsDialog() { - if(auto workingRelay = item_.lock()) + if(auto workingItem = item_.lock()) { - ItemSettingsDialog dialog(workingRelay, this); + ItemSettingsDialog dialog(workingItem, this); dialog.exec(); } else disable(); @@ -95,7 +107,6 @@ std::weak_ptr ItemWidget::getItem() void ItemWidget::stateChanged(int state) { - qDebug()<<"widget got state "<slider->blockSignals(true); ui->slider->setValue(state); ui->slider->blockSignals(false); diff --git a/src/ui/itemwidget.h b/src/ui/itemwidget.h index d4c93c6..18d2861 100644 --- a/src/ui/itemwidget.h +++ b/src/ui/itemwidget.h @@ -30,7 +30,7 @@ private slots: void deleteItem(); public: - explicit ItemWidget(std::weak_ptr item, bool analog = false, bool nameOnly = false, QWidget *parent = nullptr); + explicit ItemWidget(std::weak_ptr item, QWidget *parent = nullptr); std::weak_ptr getItem(); bool controles(const ItemData& relay); ~ItemWidget(); diff --git a/src/ui/itemwidget.ui b/src/ui/itemwidget.ui index bdbc8a6..91d92f5 100644 --- a/src/ui/itemwidget.ui +++ b/src/ui/itemwidget.ui @@ -30,7 +30,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -46,10 +46,10 @@ 255 - true + false - Qt::Horizontal + Qt::Orientation::Horizontal
diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index fe02c56..cbae5f2 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -1,10 +1,14 @@ #include "mainwindow.h" + +#include + #include "ui_mainwindow.h" #include "itemscrollbox.h" #include "itemsettingsdialog.h" #include "itemcreationdialog.h" -#include "../mainobject.h" -#include +#include "src/mainobject.h" +#include "src/programmode.h" +#include "src/items/poweritem.h" MainWindow::MainWindow(MainObject * const mainObject, QWidget *parent) : QMainWindow(parent), @@ -24,15 +28,20 @@ MainWindow::MainWindow(MainObject * const mainObject, QWidget *parent) : for(size_t i = 0; i < globalItems.getItems()->size(); ++i) ui->relayList->addItem(globalItems.getItems()->at(i)); + if(programMode != PROGRAM_MODE_PRIMARY) + ui->label_serialRecive->setHidden(true); + //Sensors ui->sensorListView->setShowHidden(false); ui->sensorListView->sensorsChanged(*globalSensors.getSensors()); connect(&globalSensors, &SensorStore::stateChenged, ui->sensorListView, &SensorListWidget::sensorsChanged); //RGB Leds - connect(&colorChooser, SIGNAL(colorSelected(QColor)), this, SLOT(slotChangedRgb(QColor))); + connect(&colorChooser, &QColorDialog::colorSelected, this, &MainWindow::sigSetRgb); connect(ui->button_quit, SIGNAL(clicked()), this, SLOT(close())); connect(ui->button_color, SIGNAL(clicked()), &colorChooser, SLOT(show())); + if(programMode != PROGRAM_MODE_PRIMARY) + ui->button_color->hide(); connect(ui->pushButton_addItem, &QPushButton::clicked, this, &MainWindow::showItemCreationDialog); connect(ui->relayList, &ItemScrollBox::deleteRequest, &globalItems, &ItemStore::removeItem); @@ -47,25 +56,30 @@ MainWindow::~MainWindow() void MainWindow::showPowerItemDialog() { - ItemSettingsDialog diag(std::shared_ptr(_powerItem), this); - diag.show(); - diag.exec(); + std::shared_ptr powerItem; + for(std::shared_ptr item : *globalItems.getItems()) + { + powerItem = std::dynamic_pointer_cast(item); + if(powerItem) + break; + } + if(powerItem) + { + ItemSettingsDialog diag(std::shared_ptr(powerItem), this); + diag.show(); + diag.exec(); + } + else + { + QMessageBox::warning(this, "Error", "No power item found, refresh first"); + } } - -void MainWindow::slotChangedRgb(const QColor color) -{ - (void)color; - //_micro->changeRgbColor(color); -} - void MainWindow::showItemCreationDialog() { ItemCreationDialog diag(this); diag.show(); if(diag.exec()) - { createdItem(diag.item); - } } void MainWindow::changeHeaderLableText(QString string) diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index 186b98d..238dd41 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -6,8 +6,8 @@ #include #include #include -#include "src/items/poweritem.h" +#include class MainObject; @@ -29,17 +29,15 @@ private: QColorDialog colorChooser; - std::shared_ptr _powerItem; - signals: void sigSave(); void createdItem(std::shared_ptr item); + void sigSetRgb(const QColor color); private slots: //RGB - void slotChangedRgb(const QColor color); void showPowerItemDialog(); void showItemCreationDialog(); diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui index 510daa8..146ac88 100644 --- a/src/ui/mainwindow.ui +++ b/src/ui/mainwindow.ui @@ -42,7 +42,7 @@ false - + @@ -114,44 +114,6 @@ 0 - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 48 - - - - - 0 - 128 - - - - Color - - - - - - - Config Shutdown - - -
@@ -194,49 +156,91 @@ 0 - - - - Refesh - - - - - - - Save - - - - - - - Add Item - - - - - - - - 0 - 0 - - - - Qt::LayoutDirection::RightToLeft - - - Quit - - -
+ + + + + + Config Shutdown + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 0 + 128 + + + + Color + + + + + + + Refesh + + + + + + + Save + + + + + + + Add Item + + + + + + + + 0 + 0 + + + + Qt::LayoutDirection::RightToLeft + + + Quit + + + + + From c1f6b6e90febc576701a8b4be02390fcb66b704b Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Fri, 27 Mar 2026 11:29:20 +0100 Subject: [PATCH 5/7] Switch to cmake --- CMakeLists.txt | 124 +++++++++++++++ SHinterface.pro | 158 -------------------- src/actors/actor.h | 2 +- src/actors/polynomalactor.h | 2 +- src/actors/regulator.h | 2 +- src/actors/sensoractor.h | 2 +- src/items/auxitem.h | 2 +- src/items/fixeditemsource.h | 2 +- src/items/item.cpp | 8 +- src/items/poweritem.h | 4 +- src/items/relay.h | 2 +- src/items/rgbitem.h | 2 +- src/main.cpp | 2 +- src/sensors/sunsensor.h | 2 +- src/ui/actorwidgets/polynomalactorwidget.ui | 2 +- src/ui/actorwidgets/regulatorwdiget.ui | 2 +- src/ui/actorwidgets/sensoractorwidget.ui | 2 +- src/ui/itemsettingsdialog.cpp | 6 +- src/ui/mainwindow-android.ui | 4 +- src/ui/mainwindow.cpp | 6 +- src/ui/mainwindow.h | 2 +- src/ui/mainwindow.ui | 4 +- src/ui/sensorlistwidget.h | 2 +- 23 files changed, 155 insertions(+), 189 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 SHinterface.pro diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b2985c0 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,124 @@ +cmake_minimum_required(VERSION 4.0) + +project(SHinterface VERSION 1.0 LANGUAGES CXX) + +# Set C++ standard +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Enable all warnings +add_compile_options(-Wall) + +# Find Qt packages +find_package(Qt6 COMPONENTS Core Gui Widgets Network Multimedia SerialPort REQUIRED) + +# Find dependencies using pkg-config +find_package(PkgConfig REQUIRED) +pkg_check_modules(PIPEWIRE REQUIRED libpipewire-0.3) +pkg_check_modules(LIBNL3 REQUIRED libnl-3.0 libnl-genl-3.0) + +# Enable automatic moc and uic processing +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) + +# Add src to include path for relative includes +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) + +# Create executable +add_executable(SHinterface) + +# Add sources to executable +target_sources(SHinterface + PRIVATE + src/main.cpp + src/mainobject.cpp + src/apgetconnected.cpp + src/microcontroller.cpp + src/sun.cpp + src/programmode.cpp + src/tcpserver.cpp + src/pipewire.cpp + + src/actors/actor.cpp + src/actors/factoractor.cpp + src/actors/polynomalactor.cpp + src/actors/sensoractor.cpp + src/actors/alarmtime.cpp + src/actors/regulator.cpp + src/actors/timeractor.cpp + + src/sensors/sensor.cpp + src/sensors/sunsensor.cpp + + src/items/item.cpp + src/items/relay.cpp + src/items/poweritem.cpp + src/items/messageitem.cpp + src/items/systemitem.cpp + src/items/auxitem.cpp + src/items/rgbitem.cpp + src/items/itemsource.cpp + src/items/itemloadersource.cpp + src/items/fixeditemsource.cpp + src/items/itemstore.cpp + + src/ui/mainwindow.cpp + src/ui/itemwidget.cpp + src/ui/itemscrollbox.cpp + src/ui/sensorlistwidget.cpp + src/ui/itemcreationdialog.cpp + src/ui/itemsettingsdialog.cpp + src/ui/actorsettingsdialog.cpp + + src/ui/actorwidgets/factoractorwidget.cpp + src/ui/actorwidgets/polynomalactorwidget.cpp + src/ui/actorwidgets/sensoractorwidget.cpp + src/ui/actorwidgets/timeractorwidget.cpp + src/ui/actorwidgets/alarmwidget.cpp + src/ui/actorwidgets/regulatorwdiget.cpp + + src/ui/itemsettingswidgets/messageitemsettingswidget.cpp + src/ui/itemsettingswidgets/relayitemsettingswidget.cpp + src/ui/itemsettingswidgets/systemitemsettingswidget.cpp +) + +# Add UI files +target_sources(SHinterface + PRIVATE + src/ui/mainwindow.ui + src/ui/itemwidget.ui + src/ui/relayscrollbox.ui + src/ui/itemcreationdialog.ui + src/ui/itemsettingsdialog.ui + src/ui/actorsettingsdialog.ui + src/ui/actorwidgets/factoractorwidget.ui + src/ui/actorwidgets/polynomalactorwidget.ui + src/ui/actorwidgets/sensoractorwidget.ui + src/ui/actorwidgets/timeractorwidget.ui + src/ui/actorwidgets/alarmwidget.ui + src/ui/actorwidgets/regulatorwdiget.ui + src/ui/itemsettingswidgets/messageitemsettingswidget.ui + src/ui/itemsettingswidgets/relayitemsettingswidget.ui + src/ui/itemsettingswidgets/systemitemsettingswidget.ui +) + +# Add resource file +target_sources(SHinterface + PRIVATE + resources.qrc +) + +# Link libraries +target_link_libraries(SHinterface + Qt6::Core + Qt6::Gui + Qt6::Widgets + Qt6::Network + Qt6::Multimedia + Qt6::SerialPort + ${PIPEWIRE_LIBRARIES} + ${LIBNL3_LIBRARIES} +) + +# Add include paths +include_directories(${PIPEWIRE_INCLUDE_DIRS} ${LIBNL3_INCLUDE_DIRS}) diff --git a/SHinterface.pro b/SHinterface.pro deleted file mode 100644 index f4dad1d..0000000 --- a/SHinterface.pro +++ /dev/null @@ -1,158 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2017-06-01T22:31:38 -# -#------------------------------------------------- - -QT += core gui widgets network multimedia - -QT += serialport - -TARGET = SHinterface -TEMPLATE = app - -INCLUDEPATH += /usr/include/libnl3/ - -LIBS += -lnl-3 -lnl-genl-3 - -# The following define makes your compiler emit warnings if you use -# any feature of Qt which as been marked as deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -QMAKE_CXXFLAGS += -std=c++17 -O2 - -SOURCES += \ - src/actors/factoractor.cpp \ - src/actors/polynomalactor.cpp \ - src/items/fixeditemsource.cpp \ - src/tcpserver.cpp \ - src/items/messageitem.cpp \ - src/items/systemitem.cpp \ - src/ui/actorwidgets/factoractorwidget.cpp \ - src/ui/itemcreationdialog.cpp \ - src/ui/itemsettingswidgets/messageitemsettingswidget.cpp \ - src/mainobject.cpp \ - src/apgetconnected.cpp \ - src/ui/actorwidgets/polynomalactorwidget.cpp \ - src/ui/actorwidgets/sensoractorwidget.cpp \ - src/ui/actorwidgets/alarmwidget.cpp \ - src/ui/actorwidgets/timeractorwidget.cpp \ - src/ui/itemsettingswidgets/relayitemsettingswidget.cpp \ - src/ui/itemsettingswidgets/systemitemsettingswidget.cpp \ - src/ui/itemwidget.cpp \ - src/ui/itemsettingsdialog.cpp \ - src/ui/itemscrollbox.cpp \ - src/items/poweritem.cpp \ - src/ui/actorwidgets/regulatorwdiget.cpp - -SOURCES += \ - src/ui/actorsettingsdialog.cpp \ - src/ui/mainwindow.cpp \ - src/ui/sensorlistwidget.cpp - -SOURCES += \ - src/actors/actor.cpp \ - src/actors/sensoractor.cpp \ - src/actors/alarmtime.cpp \ - src/actors/regulator.cpp \ - src/actors/timeractor.cpp - -SOURCES += \ - src/sensors/sensor.cpp \ - src/sensors/sunsensor.cpp \ - -SOURCES += \ - src/items/relay.cpp \ - src/items/item.cpp \ - src/items/itemstore.cpp \ - src/items/auxitem.cpp \ - src/items/rgbitem.cpp \ - src/items/itemsource.cpp\ - src/items/itemloadersource.cpp - -SOURCES += \ - src/main.cpp \ - src/microcontroller.cpp \ - src/sun.cpp \ - src/programmode.cpp - - -HEADERS += \ - src/actors/factoractor.h \ - src/actors/polynomalactor.h \ - src/items/fixeditemsource.h \ - src/items/itemsource.h \ - src/programmode.h \ - src/tcpserver.h \ - src/items/messageitem.h \ - src/items/systemitem.h \ - src/ui/actorwidgets/factoractorwidget.h \ - src/ui/itemcreationdialog.h \ - src/ui/itemsettingswidgets/messageitemsettingswidget.h \ - src/mainobject.h \ - src/apgetconnected.h \ - src/ui/actorwidgets/alarmwidget.h \ - src/ui/actorwidgets/polynomalactorwidget.h \ - src/ui/actorwidgets/sensoractorwidget.h \ - src/ui/actorwidgets/timeractorwidget.h \ - src/ui/itemsettingswidgets/relayitemsettingswidget.h \ - src/ui/itemsettingswidgets/systemitemsettingswidget.h \ - src/ui/itemwidget.h \ - src/ui/itemsettingsdialog.h \ - src/ui/itemscrollbox.h \ - src/items/poweritem.h \ - src/ui/actorwidgets/regulatorwdiget.h - -HEADERS += \ - src/ui/actorsettingsdialog.h \ - src/ui/mainwindow.h \ - src/ui/sensorlistwidget.h - -HEADERS += \ - src/actors/actor.h \ - src/actors/alarmtime.h \ - src/actors/sensoractor.h \ - src/actors/regulator.h \ - src/actors/timeractor.h - -HEADERS += \ - src/sensors/sensor.h \ - src/sensors/sunsensor.h \ - -HEADERS += \ - src/items/relay.h \ - src/items/item.h \ - src/items/itemstore.h \ - src/items/auxitem.h \ - src/items/rgbitem.h \ - src/items/itemsource.h \ - src/items/itemloadersource.h - -HEADERS += \ - src/microcontroller.h \ - src/sun.h \ - src/programmode.h - -FORMS += \ - src/ui/actorwidgets/factoractorwidget.ui \ - src/ui/itemcreationdialog.ui \ - src/ui/itemsettingswidgets/messageitemsettingswidget.ui \ - src/ui/actorsettingsdialog.ui \ - src/ui/actorwidgets/polynomalactorwidget.ui \ - src/ui/itemsettingswidgets/relayitemsettingswidget.ui \ - src/ui/itemsettingswidgets/systemitemsettingswidget.ui \ - src/ui/mainwindow.ui \ - src/ui/relayscrollbox.ui \ - src/ui/actorwidgets/sensoractorwidget.ui \ - src/ui/actorwidgets/alarmwidget.ui \ - src/ui/actorwidgets/timeractorwidget.ui \ - src/ui/itemsettingsdialog.ui \ - src/ui/itemwidget.ui \ - src/ui/actorwidgets/regulatorwdiget.ui - -android:FORMS += src/ui/mainwindow-android.ui - -RESOURCES += \ - resources.qrc diff --git a/src/actors/actor.h b/src/actors/actor.h index 4cdb048..7b81bde 100644 --- a/src/actors/actor.h +++ b/src/actors/actor.h @@ -5,7 +5,7 @@ #include #include -#include "src/items/item.h" +#include "items/item.h" class Actor : public Item { diff --git a/src/actors/polynomalactor.h b/src/actors/polynomalactor.h index 9c4d64f..1ff3675 100644 --- a/src/actors/polynomalactor.h +++ b/src/actors/polynomalactor.h @@ -1,7 +1,7 @@ #ifndef POLYNOMALACTOR_H #define POLYNOMALACTOR_H #include "actor.h" -#include "src/sensors/sensor.h" +#include "sensors/sensor.h" class PolynomalActor: public Actor { diff --git a/src/actors/regulator.h b/src/actors/regulator.h index f4588b2..339b2ca 100644 --- a/src/actors/regulator.h +++ b/src/actors/regulator.h @@ -3,7 +3,7 @@ #include #include "actor.h" -#include "src/sensors/sensor.h" +#include "sensors/sensor.h" class Regulator : public Actor { diff --git a/src/actors/sensoractor.h b/src/actors/sensoractor.h index 6499dbe..27a9355 100644 --- a/src/actors/sensoractor.h +++ b/src/actors/sensoractor.h @@ -1,6 +1,6 @@ #pragma once #include "actor.h" -#include "src/sensors/sensor.h" +#include "sensors/sensor.h" class SensorActor : public Actor { diff --git a/src/items/auxitem.h b/src/items/auxitem.h index 658b907..774d44e 100644 --- a/src/items/auxitem.h +++ b/src/items/auxitem.h @@ -1,7 +1,7 @@ #pragma once #include "item.h" -#include "src/microcontroller.h" +#include "microcontroller.h" class AuxItem: public Item { diff --git a/src/items/fixeditemsource.h b/src/items/fixeditemsource.h index 150b9a1..e535842 100644 --- a/src/items/fixeditemsource.h +++ b/src/items/fixeditemsource.h @@ -5,7 +5,7 @@ #include "poweritem.h" #include "rgbitem.h" #include "auxitem.h" -#include "src/microcontroller.h" +#include "microcontroller.h" class FixedItemSource : public ItemSource { diff --git a/src/items/item.cpp b/src/items/item.cpp index 9b80254..e297094 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -1,9 +1,9 @@ #include "item.h" -#include "src/actors/sensoractor.h" -#include "src/actors/regulator.h" -#include "src/actors/polynomalactor.h" -#include "src/programmode.h" +#include "actors/sensoractor.h" +#include "actors/regulator.h" +#include "actors/polynomalactor.h" +#include "programmode.h" #include "relay.h" #include "messageitem.h" #include "systemitem.h" diff --git a/src/items/poweritem.h b/src/items/poweritem.h index dda2f35..d6a610f 100644 --- a/src/items/poweritem.h +++ b/src/items/poweritem.h @@ -1,8 +1,8 @@ #pragma once #include "item.h" -#include "src/sensors/sensor.h" -#include "src/microcontroller.h" +#include "sensors/sensor.h" +#include "microcontroller.h" #include diff --git a/src/items/relay.h b/src/items/relay.h index 8a35e98..3c3c4b4 100644 --- a/src/items/relay.h +++ b/src/items/relay.h @@ -4,7 +4,7 @@ #include #include -#include "src/sensors/sensor.h" +#include "sensors/sensor.h" #include "item.h" class Microcontroller; diff --git a/src/items/rgbitem.h b/src/items/rgbitem.h index 8e6ae8c..db721b9 100644 --- a/src/items/rgbitem.h +++ b/src/items/rgbitem.h @@ -1,6 +1,6 @@ #pragma once -#include "src/microcontroller.h" +#include "microcontroller.h" #include "item.h" class RgbItem: public Item diff --git a/src/main.cpp b/src/main.cpp index d201f11..8e5ca4c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,7 +70,7 @@ int main(int argc, char *argv[]) QTcpSocket* microSocket = new QTcpSocket; - qInfo()<<"connecting to "<connectToHost(host, port, QIODevice::ReadWrite); if(!microSocket->waitForConnected(1000)) diff --git a/src/sensors/sunsensor.h b/src/sensors/sunsensor.h index dfb9a87..65d84c3 100644 --- a/src/sensors/sunsensor.h +++ b/src/sensors/sunsensor.h @@ -2,7 +2,7 @@ #include -#include "src/sun.h" +#include "sun.h" #include "sensor.h" diff --git a/src/ui/actorwidgets/polynomalactorwidget.ui b/src/ui/actorwidgets/polynomalactorwidget.ui index 4cf9fb2..39bf709 100644 --- a/src/ui/actorwidgets/polynomalactorwidget.ui +++ b/src/ui/actorwidgets/polynomalactorwidget.ui @@ -132,7 +132,7 @@ SensorListWidget QListView -
src/ui/sensorlistwidget.h
+
ui/sensorlistwidget.h
diff --git a/src/ui/actorwidgets/regulatorwdiget.ui b/src/ui/actorwidgets/regulatorwdiget.ui index 7365523..ee79da6 100644 --- a/src/ui/actorwidgets/regulatorwdiget.ui +++ b/src/ui/actorwidgets/regulatorwdiget.ui @@ -110,7 +110,7 @@ SensorListWidget QListView -
src/ui/sensorlistwidget.h
+
ui/sensorlistwidget.h
diff --git a/src/ui/actorwidgets/sensoractorwidget.ui b/src/ui/actorwidgets/sensoractorwidget.ui index f3fddd2..5f49c96 100644 --- a/src/ui/actorwidgets/sensoractorwidget.ui +++ b/src/ui/actorwidgets/sensoractorwidget.ui @@ -89,7 +89,7 @@ SensorListWidget QListView -
src/ui/sensorlistwidget.h
+
ui/sensorlistwidget.h
diff --git a/src/ui/itemsettingsdialog.cpp b/src/ui/itemsettingsdialog.cpp index 23d4f4d..08417d3 100644 --- a/src/ui/itemsettingsdialog.cpp +++ b/src/ui/itemsettingsdialog.cpp @@ -8,9 +8,9 @@ #include "../actors/factoractor.h" #include "../items/messageitem.h" #include "../items/systemitem.h" -#include "./itemsettingswidgets/messageitemsettingswidget.h" -#include "./itemsettingswidgets/systemitemsettingswidget.h" -#include "./itemsettingswidgets/relayitemsettingswidget.h" +#include "itemsettingswidgets/messageitemsettingswidget.h" +#include "itemsettingswidgets/systemitemsettingswidget.h" +#include "itemsettingswidgets/relayitemsettingswidget.h" #include ItemSettingsDialog::ItemSettingsDialog(std::shared_ptr item, QWidget *parent) : diff --git a/src/ui/mainwindow-android.ui b/src/ui/mainwindow-android.ui index fa90bc9..e7802b3 100644 --- a/src/ui/mainwindow-android.ui +++ b/src/ui/mainwindow-android.ui @@ -245,13 +245,13 @@ ItemScrollBox QWidget -
../src/ui/itemscrollbox.h
+
../ui/itemscrollbox.h
1
SensorListWidget QListView -
../src/ui/sensorlistwidget.h
+
../ui/sensorlistwidget.h
diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index cbae5f2..79a6b3e 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -6,9 +6,9 @@ #include "itemscrollbox.h" #include "itemsettingsdialog.h" #include "itemcreationdialog.h" -#include "src/mainobject.h" -#include "src/programmode.h" -#include "src/items/poweritem.h" +#include "mainobject.h" +#include "programmode.h" +#include "items/poweritem.h" MainWindow::MainWindow(MainObject * const mainObject, QWidget *parent) : QMainWindow(parent), diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index 238dd41..5b04b64 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -7,7 +7,7 @@ #include #include -#include +#include class MainObject; diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui index 146ac88..2bb3874 100644 --- a/src/ui/mainwindow.ui +++ b/src/ui/mainwindow.ui @@ -249,12 +249,12 @@ SensorListWidget QListView -
src/ui/sensorlistwidget.h
+
ui/sensorlistwidget.h
ItemScrollBox QWidget -
src/ui/itemscrollbox.h
+
ui/itemscrollbox.h
1
diff --git a/src/ui/sensorlistwidget.h b/src/ui/sensorlistwidget.h index d87bd30..4c84d54 100644 --- a/src/ui/sensorlistwidget.h +++ b/src/ui/sensorlistwidget.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include "src/sensors/sensor.h" +#include "sensors/sensor.h" class SensorListItem : public QTableWidgetItem { From d6c8d799e3fdd05d033dccdadb715eb5e07ae6b7 Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Fri, 27 Mar 2026 11:31:14 +0100 Subject: [PATCH 6/7] Add headers to cmake --- CMakeLists.txt | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2985c0..11d7928 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,54 +31,97 @@ add_executable(SHinterface) target_sources(SHinterface PRIVATE src/main.cpp + src/mainobject.h src/mainobject.cpp + src/apgetconnected.h src/apgetconnected.cpp + src/microcontroller.h src/microcontroller.cpp + src/sun.h src/sun.cpp + src/programmode.h src/programmode.cpp + src/tcpserver.h src/tcpserver.cpp + src/pipewire.h src/pipewire.cpp + src/actors/actor.h src/actors/actor.cpp + src/actors/factoractor.h src/actors/factoractor.cpp + src/actors/polynomalactor.h src/actors/polynomalactor.cpp + src/actors/sensoractor.h src/actors/sensoractor.cpp + src/actors/alarmtime.h src/actors/alarmtime.cpp + src/actors/regulator.h src/actors/regulator.cpp + src/actors/timeractor.h src/actors/timeractor.cpp + src/sensors/sensor.h src/sensors/sensor.cpp + src/sensors/sunsensor.h src/sensors/sunsensor.cpp + src/items/item.h src/items/item.cpp + src/items/relay.h src/items/relay.cpp + src/items/poweritem.h src/items/poweritem.cpp + src/items/messageitem.h src/items/messageitem.cpp + src/items/systemitem.h src/items/systemitem.cpp + src/items/auxitem.h src/items/auxitem.cpp + src/items/rgbitem.h src/items/rgbitem.cpp + src/items/itemsource.h src/items/itemsource.cpp + src/items/itemloadersource.h src/items/itemloadersource.cpp + src/items/fixeditemsource.h src/items/fixeditemsource.cpp + src/items/itemstore.h src/items/itemstore.cpp + src/ui/mainwindow.h src/ui/mainwindow.cpp + src/ui/itemwidget.h src/ui/itemwidget.cpp + src/ui/itemscrollbox.h src/ui/itemscrollbox.cpp + src/ui/sensorlistwidget.h src/ui/sensorlistwidget.cpp + src/ui/itemcreationdialog.h src/ui/itemcreationdialog.cpp + src/ui/itemsettingsdialog.h src/ui/itemsettingsdialog.cpp + src/ui/actorsettingsdialog.h src/ui/actorsettingsdialog.cpp + src/ui/actorwidgets/factoractorwidget.h src/ui/actorwidgets/factoractorwidget.cpp + src/ui/actorwidgets/polynomalactorwidget.h src/ui/actorwidgets/polynomalactorwidget.cpp + src/ui/actorwidgets/sensoractorwidget.h src/ui/actorwidgets/sensoractorwidget.cpp + src/ui/actorwidgets/timeractorwidget.h src/ui/actorwidgets/timeractorwidget.cpp + src/ui/actorwidgets/alarmwidget.h src/ui/actorwidgets/alarmwidget.cpp + src/ui/actorwidgets/regulatorwdiget.h src/ui/actorwidgets/regulatorwdiget.cpp + src/ui/itemsettingswidgets/messageitemsettingswidget.h src/ui/itemsettingswidgets/messageitemsettingswidget.cpp + src/ui/itemsettingswidgets/relayitemsettingswidget.h src/ui/itemsettingswidgets/relayitemsettingswidget.cpp + src/ui/itemsettingswidgets/systemitemsettingswidget.h src/ui/itemsettingswidgets/systemitemsettingswidget.cpp ) From e3b6d5c3a60afb3c9a1356b23fa73a9b43f15492 Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Fri, 27 Mar 2026 17:47:09 +0100 Subject: [PATCH 7/7] Add support for mqtt sensors --- CMakeLists.txt | 6 +- src/mainobject.cpp | 7 ++ src/mainobject.h | 2 + src/sensors/mqttsensorsource.cpp | 187 +++++++++++++++++++++++++++++++ src/sensors/mqttsensorsource.h | 44 ++++++++ src/sensors/sensor.h | 8 +- src/ui/mainwindow.ui | 2 +- 7 files changed, 251 insertions(+), 5 deletions(-) create mode 100644 src/sensors/mqttsensorsource.cpp create mode 100644 src/sensors/mqttsensorsource.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 11d7928..5c24e80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) add_compile_options(-Wall) # Find Qt packages -find_package(Qt6 COMPONENTS Core Gui Widgets Network Multimedia SerialPort REQUIRED) +find_package(Qt6 COMPONENTS Core Gui Widgets Network Multimedia SerialPort Mqtt REQUIRED) # Find dependencies using pkg-config find_package(PkgConfig REQUIRED) @@ -25,7 +25,8 @@ set(CMAKE_AUTOUIC ON) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) # Create executable -add_executable(SHinterface) +add_executable(SHinterface + src/sensors/mqttsensorsource.h src/sensors/mqttsensorsource.cpp) # Add sources to executable target_sources(SHinterface @@ -159,6 +160,7 @@ target_link_libraries(SHinterface Qt6::Network Qt6::Multimedia Qt6::SerialPort + Qt6::Mqtt ${PIPEWIRE_LIBRARIES} ${LIBNL3_LIBRARIES} ) diff --git a/src/mainobject.cpp b/src/mainobject.cpp index 4f31e78..0f41d19 100644 --- a/src/mainobject.cpp +++ b/src/mainobject.cpp @@ -81,6 +81,7 @@ PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, const QString& sett connect(tcpServer, &TcpServer::gotSensor, &globalSensors, &SensorStore::sensorGotState); connect(&sunSensorSource, &SunSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState); connect(µ, &Microcontroller::gotSensorState, &globalSensors, &SensorStore::sensorGotState); + connect(&mqttSensorSource, &MqttSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState); sunSensorSource.run(); @@ -93,6 +94,9 @@ PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, const QString& sett loadFromDisk(settingsPath); + QJsonObject mqttJson = settings["Mqtt"].toObject(); + mqttSensorSource.start(mqttJson); + tcpServer->launch(QHostAddress(host), port); connect(&globalItems, &ItemStore::itemUpdated, tcpServer, &TcpServer::itemUpdated); } @@ -105,6 +109,9 @@ PrimaryMainObject::~PrimaryMainObject() void PrimaryMainObject::store(QJsonObject &json) { globalItems.store(json); + QJsonObject mqttJson = json["Mqtt"].toObject(); + mqttSensorSource.store(mqttJson); + json["Mqtt"] = mqttJson; } void PrimaryMainObject::load(const QJsonObject& json) diff --git a/src/mainobject.h b/src/mainobject.h index 05b8140..79f5ed2 100644 --- a/src/mainobject.h +++ b/src/mainobject.h @@ -14,6 +14,7 @@ #include "microcontroller.h" #include "ui/mainwindow.h" #include "sensors/sunsensor.h" +#include "sensors/mqttsensorsource.h" #include "items/fixeditemsource.h" #include "items/itemloadersource.h" #include "tcpserver.h" @@ -45,6 +46,7 @@ public: //sensors SunSensorSource sunSensorSource; + MqttSensorSource mqttSensorSource; //item sources FixedItemSource fixedItems; diff --git a/src/sensors/mqttsensorsource.cpp b/src/sensors/mqttsensorsource.cpp new file mode 100644 index 0000000..4202ab8 --- /dev/null +++ b/src/sensors/mqttsensorsource.cpp @@ -0,0 +1,187 @@ +#include "mqttsensorsource.h" + +#include + +MqttSensorSource::MqttSensorSource(QObject *parent) + : QObject{parent} +{ +} + +void MqttSensorSource::start(const QJsonObject& settings) +{ + baseTopicName = settings["BaseTopic"].toString("zigbee2mqtt"); + + connect(&client, &QMqttClient::stateChanged, this, &MqttSensorSource::onClientStateChanged); + connect(&client, &QMqttClient::errorChanged, this, &MqttSensorSource::onClientError); + + client.setHostname(settings["Host"].toString("127.0.0.1")); + client.setPort(settings["Port"].toInt(1883)); + if(settings.contains("User")) + client.setUsername(settings["User"].toString()); + if(settings.contains("Password")) + client.setPassword(settings["Password"].toString()); + client.setProtocolVersion(QMqttClient::MQTT_5_0); + + client.connectToHost(); + + 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(baseTopicName + "/" + sensor.topic); + sensors.push_back(sensor); + } +} + +void MqttSensorSource::onClientError(QMqttClient::ClientError error) +{ + qWarning()<<"MQTT Client error:"< +#include +#include +#include + +#include "sensor.h" + +class MqttSensorSource : public QObject +{ + Q_OBJECT + + struct SensorSubscription + { + uint64_t id; + QString topic; + QString name; + QMqttSubscription* subscription = nullptr; + }; + + QString baseTopicName; + std::vector sensors; + QMqttClient client; + +private: + SensorSubscription& findSubscription(const QString& topic); + +private slots: + void onClientStateChanged(QMqttClient::ClientState state); + void onMessageReceived(const QMqttMessage& message); + void onClientError(QMqttClient::ClientError error); + +public: + explicit MqttSensorSource(QObject *parent = nullptr); + void start(const QJsonObject& settings); + void store(QJsonObject& json); + +signals: + void stateChanged(Sensor sensor); +}; + +#endif // MQTTSENSORSOURCE_H diff --git a/src/sensors/sensor.h b/src/sensors/sensor.h index 86c82b9..bc5e748 100644 --- a/src/sensors/sensor.h +++ b/src/sensors/sensor.h @@ -17,6 +17,10 @@ public: static constexpr uint8_t TYPE_BRIGHTNESS = 4; static constexpr uint8_t TYPE_BUTTON = 5; static constexpr uint8_t TYPE_ADC = 6; + static constexpr uint8_t TYPE_CO2 = 7; + static constexpr uint8_t TYPE_FORMALDEHYD= 8; + static constexpr uint8_t TYPE_PM25 = 9; + static constexpr uint8_t TYPE_TOTAL_VOC = 10; static constexpr uint8_t TYPE_LOWBATTERY = 128; static constexpr uint8_t TYPE_SHUTDOWN_IMMINENT = 251; static constexpr uint8_t TYPE_OCUPANCY = 252; @@ -25,13 +29,13 @@ public: static constexpr uint8_t TYPE_DUMMY = 255; uint8_t type; - uint8_t id; + uint64_t id; float field; QString name; QDateTime lastSeen; bool hidden; - Sensor(uint8_t typeIn, uint8_t idIn, float fieldIn = 0, QString nameIn = "", bool hiddenIn = false): type(typeIn), + Sensor(uint64_t typeIn, uint8_t idIn, float fieldIn = 0, QString nameIn = "", bool hiddenIn = false): type(typeIn), id(idIn), field(fieldIn), name(nameIn), hidden(hiddenIn) { lastSeen = QDateTime::currentDateTime(); diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui index 2bb3874..0e6732c 100644 --- a/src/ui/mainwindow.ui +++ b/src/ui/mainwindow.ui @@ -42,7 +42,7 @@ false - +