diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5c24e80 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,169 @@ +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 Mqtt 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 + src/sensors/mqttsensorsource.h src/sensors/mqttsensorsource.cpp) + +# Add sources to executable +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 +) + +# 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 + Qt6::Mqtt + ${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 c7ff09f..0000000 --- a/SHinterface.pro +++ /dev/null @@ -1,156 +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/broadcast.cpp \ - src/iomuliplexer.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/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 - -SOURCES += \ - src/alarmactions.cpp \ - src/main.cpp \ - src/microcontroller.cpp \ - src/sun.cpp - - -HEADERS += \ - src/actors/factoractor.h \ - src/actors/polynomalactor.h \ - src/broadcast.h \ - src/iomuliplexer.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/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 - -HEADERS += \ - src/alarmactions.h \ - src/microcontroller.h \ - src/sun.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/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 "< #include -#include "../items/item.h" +#include "items/item.h" class Actor : public Item { 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/actors/polynomalactor.h b/src/actors/polynomalactor.h index d91f2ba..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 "../sensors/sensor.h" +#include "sensors/sensor.h" class PolynomalActor: public Actor { diff --git a/src/actors/regulator.h b/src/actors/regulator.h index 733d643..339b2ca 100644 --- a/src/actors/regulator.h +++ b/src/actors/regulator.h @@ -3,7 +3,7 @@ #include #include "actor.h" -#include "../sensors/sensor.h" +#include "sensors/sensor.h" class Regulator : public Actor { diff --git a/src/actors/sensoractor.h b/src/actors/sensoractor.h index 720146e..27a9355 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 "sensors/sensor.h" class SensorActor : public Actor { diff --git a/src/alarmactions.cpp b/src/alarmactions.cpp deleted file mode 100644 index 20853ce..0000000 --- a/src/alarmactions.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "alarmactions.h" -#include - -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/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 860a121..5bee87e 100644 --- a/src/items/auxitem.cpp +++ b/src/items/auxitem.cpp @@ -3,12 +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::setValue(uint8_t value) +void AuxItem::enactValue(uint8_t value) { - Item::setValue(value); + assert(micro_); micro_->setAuxPwm(value); } diff --git a/src/items/auxitem.h b/src/items/auxitem.h index 512144f..774d44e 100644 --- a/src/items/auxitem.h +++ b/src/items/auxitem.h @@ -1,7 +1,7 @@ #pragma once #include "item.h" -#include "../microcontroller.h" +#include "microcontroller.h" class AuxItem: public Item { @@ -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 = "", + AuxItem(Microcontroller* micro = nullptr, 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/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..e535842 --- /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 "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 862834c..e297094 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -1,14 +1,20 @@ #include "item.h" +#include "actors/sensoractor.h" +#include "actors/regulator.h" +#include "actors/polynomalactor.h" +#include "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 "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) { } @@ -33,11 +39,63 @@ 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)); + 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 -bool Item::secondaryFlag = false; - Item::Item(uint32_t itemIdIn, QString name, uint8_t value, QObject *parent): QObject(parent), ItemData (itemIdIn, name, value) { @@ -55,8 +113,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 +130,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) @@ -85,46 +138,60 @@ 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); } } } 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_); + qDebug()<<__func__; + informValue(value); + if(programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY) + enactValue(value); } void Item::informValue(uint8_t value) { - Item::setValue(value); + if(value_ != 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); - 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) @@ -167,5 +234,50 @@ 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(); } + +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; + 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") + { + 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 18aa0cc..1aaa090 100644 --- a/src/items/item.h +++ b/src/items/item.h @@ -8,31 +8,52 @@ 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 { - 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; + 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); }; @@ -44,20 +65,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: @@ -76,9 +92,15 @@ 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); + static std::shared_ptr loadItem(const QJsonObject& json); + +protected: + virtual void enactValue(uint8_t value); + }; 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.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..9fee9c1 --- /dev/null +++ b/src/items/itemsource.h @@ -0,0 +1,25 @@ +#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 requestReplaceItems(std::vector> items); + 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..1242afc 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"<<(item->getLoaded() ? "from loaded" : ""); itemAdded(std::weak_ptr(items_.back())); } + else + { + if(item->getLoaded()) + matched->mergeLoaded(*item); + else if(item->getValue() != matched->getValue()) + updateItem(*item, inform); + } } -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,12 +45,26 @@ void ItemStore::removeItem(const ItemData& item) { if(item == *items_[j]) { + qDebug()<<"Item"<>& 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() { @@ -69,19 +73,33 @@ void ItemStore::clear() } -void ItemStore::itemStateChanged(const ItemData& item) +void ItemStore::updateItems(std::vector 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]->hasChanged(item)) + { + 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]); + } } - } - } void ItemStore::store(QJsonObject& json) @@ -96,35 +114,41 @@ void ItemStore::store(QJsonObject& json) json["Items"] = itemsArray; } -void ItemStore::load(const QJsonObject& json) +void ItemStore::itemUpdateSlot(ItemData data) { - const QJsonArray itemsArray(json["Items"].toArray(QJsonArray())); - for(int i = 0; i < itemsArray.size(); ++i) + for(std::shared_ptr& item: items_) { - 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(*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 44d8fd6..830cc40 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 "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,8 +22,10 @@ public: return &items_; } + std::shared_ptr getItem(uint32_t id); + + void registerItemSource(ItemSource* source); void store(QJsonObject &json); - void load(const QJsonObject &json); void clear(); @@ -31,11 +33,21 @@ 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 replaceItems(const std::vector>& items); + 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 0174586..151b934 100644 --- a/src/items/messageitem.cpp +++ b/src/items/messageitem.cpp @@ -1,20 +1,19 @@ #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); + type_ = ITEM_VALUE_NO_VALUE; } MessageItem::MessageItem(const ItemData& itemData, QObject *parent): Item(itemData, parent) { - + alertSound.setVolume(1.0); } MessageItem::~MessageItem() @@ -22,13 +21,12 @@ MessageItem::~MessageItem() closeMessageBox(); } -void MessageItem::setValue(uint8_t value) +void MessageItem::enactValue(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..d23fb11 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,17 +14,13 @@ private: QString message_; QMessageBox* messageBox_ = nullptr; QString alertSoundFileName = ""; - -public: - static BroadCast* broadCast; + QSoundEffect alertSound; private slots: - void closeMessageBox(); -public: - - virtual void setValue(uint8_t value); +protected: + virtual void enactValue(uint8_t value) override; public: @@ -38,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..2b2e4e1 100644 --- a/src/items/poweritem.cpp +++ b/src/items/poweritem.cpp @@ -3,19 +3,20 @@ #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)); - setValue(true); + PowerItem::setValue(true); + hidden_ = true; + type_ = ITEM_VALUE_NO_VALUE; } -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 dd13629..d6a610f 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 "sensors/sensor.h" +#include "microcontroller.h" #include @@ -16,19 +16,17 @@ 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, + PowerItem(uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "Power", uint8_t value = 0, QObject* parent = nullptr); void emmitSensor() { 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..f801e1b 100644 --- a/src/items/relay.cpp +++ b/src/items/relay.cpp @@ -9,16 +9,17 @@ 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 "<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 0ba4849..3c3c4b4 100644 --- a/src/items/relay.h +++ b/src/items/relay.h @@ -4,7 +4,7 @@ #include #include -#include "../sensors/sensor.h" +#include "sensors/sensor.h" #include "item.h" class Microcontroller; @@ -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..6df7c33 100644 --- a/src/items/rgbitem.cpp +++ b/src/items/rgbitem.cpp @@ -6,9 +6,9 @@ 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); + assert(micro_); value ? micro_->rgbOn() : micro_->rgbOff(); } diff --git a/src/items/rgbitem.h b/src/items/rgbitem.h index 9aff188..db721b9 100644 --- a/src/items/rgbitem.h +++ b/src/items/rgbitem.h @@ -1,6 +1,6 @@ #pragma once -#include "../microcontroller.h" +#include "microcontroller.h" #include "item.h" class RgbItem: public Item @@ -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 = "", + RgbItem(Microcontroller* micro = nullptr, 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 9fe7a11..392e914 100644 --- a/src/items/systemitem.h +++ b/src/items/systemitem.h @@ -1,23 +1,19 @@ #ifndef SYSTEMITEM_H #define SYSTEMITEM_H - #include "item.h" 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); @@ -34,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..8e5ca4c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,26 +1,16 @@ #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" - - -#define BAUD QSerialPort::Baud38400 +#include "programmode.h" int main(int argc, char *argv[]) { @@ -37,102 +27,113 @@ int main(int argc, char *argv[]) QDir::setCurrent(a.applicationDirPath()); //parse comand line -#ifndef Q_OS_ANDROID QCommandLineParser parser; parser.setApplicationDescription("Smart Home Interface"); parser.addHelpOption(); parser.addVersionOption(); - QCommandLineOption tcpOption(QStringList() << "t" << "tcp", QCoreApplication::translate("main", "Use Tcp connection")); - parser.addOption(tcpOption); - QCommandLineOption hostOption(QStringList() << "H" << "host", QCoreApplication::translate("main", - "Set server host ip addres"), "adress"); + QCommandLineOption masterOption(QStringList() << "m" << "master", QCoreApplication::translate("main", "Use in master mode")); + parser.addOption(masterOption); + QCommandLineOption hostOption(QStringList() << "H" << "host", QCoreApplication::translate("main", "Set server host ip addres"), "address", "0.0.0.0"); parser.addOption(hostOption); - QCommandLineOption portOption(QStringList() << "p" << "port", QCoreApplication::translate("main", - "Set server Port in TCP mode or Serial port in serial mode"), "port"); + QCommandLineOption portOption(QStringList() << "p" << "port", QCoreApplication::translate("main", "Set server Port"), "port", "104476"); parser.addOption(portOption); - QCommandLineOption serialOption(QStringList() << "s" << "serial", QCoreApplication::translate("main", - "Use serial connection")); - parser.addOption(serialOption); - QCommandLineOption baudOption(QStringList() << "b" << "baud", QCoreApplication::translate("main", "Set Baud Rate")); - parser.addOption(baudOption); - QCommandLineOption settingsPathOption(QStringList() << "c" << "config", QCoreApplication::translate("main", - "Set config file"), "configFilePath"); + QCommandLineOption settingsPathOption(QStringList()<<"c"<<"config", QCoreApplication::translate("main", "Set config file"), "configFilePath", + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/shinterface.json"); parser.addOption(settingsPathOption); - QCommandLineOption secondaryOption(QStringList() << "e" << "secondary", QCoreApplication::translate("main", - "Set if instance is not main instance")); - parser.addOption(secondaryOption); + QCommandLineOption headlessOption(QStringList()<<"e"<<"headless", QCoreApplication::translate("main", "Dont start the gui")); + parser.addOption(headlessOption); parser.process(a); -#endif - QIODevice* masterIODevice = nullptr; + int retVal; -#ifndef Q_OS_ANDROID - if(parser.isSet(tcpOption)) + programMode = PROGRAM_MODE_UI_ONLY; + if(parser.isSet(masterOption)) { - QTcpSocket* microSocket = new QTcpSocket; + programMode = PROGRAM_MODE_PRIMARY; + if(parser.isSet(headlessOption)) + programMode = PROGRAM_MODE_HEADLESS_PRIMARY; + } + if(programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY) + { + QString settingsPath = parser.value(settingsPathOption); + QJsonObject json = MainObject::getJsonObjectFromDisk(settingsPath); + bool tcpMicro = json["MicroTcp"].toBool(true); + json["MicroTcp"] = tcpMicro; - int port = 6856; - if(parser.isSet(portOption)) port = parser.value(portOption).toInt(); - - QString host("127.0.0.1"); - if(parser.isSet(hostOption)) host = parser.value(hostOption); - std::cout<<"connecting to "<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"; + MainObject::storeJsonObjectToDisk(settingsPath, json); + 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; } 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::createdItem, &globalItems, [](std::shared_ptr item){globalItems.addItem(item, false);}); + QObject::connect(&w, &MainWindow::sigSave, mainObject.tcpClient, &TcpClient::sendItems); + 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..0f41d19 100644 --- a/src/mainobject.cpp +++ b/src/mainobject.cpp @@ -1,139 +1,35 @@ #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) -{ - items.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(); -} - -void MainObject::storeToDisk() -{ - if(master && !noSave) - { - QJsonObject json; - store(json); - storeJsonObjectToDisk(json, settingsPath); - } -} - -void MainObject::recivedJson(const QJsonObject json) -{ - 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) +QJsonObject MainObject::getJsonObjectFromDisk(const QString& filename, bool* error) { QFile file; + file.setFileName(filename); -#ifndef Q_OS_ANDROID - if(filePath.size() > 0) file.setFileName(filePath); - else -#endif + bool ret = file.open(QIODevice::ReadOnly); + if(!file.isOpen() || !ret) { - file.setFileName(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/shinterface.json"); + std::cerr<<"Can not open config file: "<launch(QHostAddress(host), port); + connect(&globalItems, &ItemStore::itemUpdated, tcpServer, &TcpServer::itemUpdated); +} + +PrimaryMainObject::~PrimaryMainObject() +{ + storeToDisk(settingsPath); +} + +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) +{ + settings = json; + itemLoader.updateJson(json); + globalItems.clear(); + 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) +{ + connect(tcpClient, &TcpClient::gotSensor, &globalSensors, &SensorStore::sensorGotState); + globalItems.registerItemSource(tcpClient); + + if(!tcpClient->launch(QHostAddress(host), port)) + { + QMessageBox::critical(nullptr, "Error", "Could not connect to "+host+":"+QString::number(port)); + 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 cfa5fff..79f5ed2 100644 --- a/src/mainobject.h +++ b/src/mainobject.h @@ -2,7 +2,6 @@ #define MAINOBJECT_H #include -#include #include #include #include @@ -12,80 +11,65 @@ #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 "sensors/mqttsensorsource.h" +#include "items/fixeditemsource.h" +#include "items/itemloadersource.h" +#include "tcpserver.h" class MainObject : public QObject { Q_OBJECT -public: - - //io - const bool master; - - bool noSave = false; - - QIODevice * const masterIODevice = nullptr; - IoMuliplexer ioMultiplexer; - - Microcontroller micro; - BroadCast broadCast; - - - const QString settingsPath; - - //sensors - SunSensorSource sunSensorSource; - OcupancySensorSource ocupancySensor; - - //items - ItemStore items; - - std::shared_ptr powerItem; - std::shared_ptr rgbItem; - std::shared_ptr auxItem; - - //PipeWireHandler pwHandler; - -private: - - static QJsonObject getJsonObjectFromDisk(const QString& filePath = "", bool* error = nullptr); - static bool storeJsonObjectToDisk(const QJsonObject& json, QString filePath = ""); public: - explicit MainObject(QIODevice* ioDevice, const QString& settingsPathIn, const bool masterIn, QObject *parent = nullptr); + explicit MainObject(QObject *parent = nullptr); ~MainObject(); - - void store(QJsonObject& json); - - void load(const QJsonObject& json); - -signals: + static QJsonObject getJsonObjectFromDisk(const QString& filename, bool* error = nullptr); + static bool storeJsonObjectToDisk(const QString& filename, const QJsonObject& json); public slots: + void refresh(); +}; - void storeToDisk(); - void sendJson(); - void recivedJson(const QJsonObject json); +class PrimaryMainObject : public MainObject +{ + Q_OBJECT +public: + + QString settingsPath; + QJsonObject settings; + + Microcontroller micro; + TcpServer* tcpServer; + + //sensors + SunSensorSource sunSensorSource; + MqttSensorSource mqttSensorSource; + + //item sources + FixedItemSource fixedItems; + ItemLoaderSource itemLoader; + +public: + 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 +{ + Q_OBJECT +public: + TcpClient* tcpClient; + +public: + explicit SecondaryMainObject(QString host, int port, QObject *parent = nullptr); + ~SecondaryMainObject(); }; diff --git a/src/microcontroller.cpp b/src/microcontroller.cpp index ba5f54b..4833461 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"); } @@ -151,8 +142,7 @@ void Microcontroller::processList(const QString& buffer) else if(buffer.contains("EOL")) { listMode = false; - qDebug()<<"got relay list " << relayList.size(); - gotRelayList(relayList); + gotItems(relayList); relayList.clear(); } else listMode = false; @@ -160,19 +150,23 @@ 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) { Sensor sensor = Sensor::sensorFromString(buffer); - if(sensor.type != Sensor::TYPE_DUMMY) gotSensorState(sensor); + if(sensor.type != Sensor::TYPE_DUMMY) + gotSensorState(sensor); } void Microcontroller::processMicroReturn() { - if(listMode) processList(_buffer); + if(listMode) + { + processList(_buffer); + } else { if(_buffer.startsWith("Items:")) @@ -180,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); + } } } @@ -192,7 +192,7 @@ void Microcontroller::isReadyRead() while(_port->getChar(&charBuf)) { _buffer.push_back(charBuf); - if( _buffer.endsWith('\n') ) + 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/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/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..bc5e748 100644 --- a/src/sensors/sensor.h +++ b/src/sensors/sensor.h @@ -4,6 +4,7 @@ #include #include #include +#include class Sensor { @@ -16,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; @@ -24,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(); @@ -41,6 +46,15 @@ public: { lastSeen = QDateTime::currentDateTime(); } + Sensor(const QJsonObject& json) + { + type = json["SensorType"].toInt(0); + id = json["Id"].toInt(0); + field = json["Field"].toDouble(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 +91,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/sensors/sunsensor.h b/src/sensors/sunsensor.h index bfbce04..65d84c3 100644 --- a/src/sensors/sunsensor.h +++ b/src/sensors/sunsensor.h @@ -2,7 +2,7 @@ #include -#include "../sun.h" +#include "sun.h" #include "sensor.h" diff --git a/src/tcpserver.cpp b/src/tcpserver.cpp new file mode 100644 index 0000000..f49150f --- /dev/null +++ b/src/tcpserver.cpp @@ -0,0 +1,342 @@ +#include +#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["MessageType"] = 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) +{ + qDebug()<<__func__; + QJsonArray items; + QJsonObject itemjson; + item.lock()->store(itemjson); + items.append(itemjson); + QJsonObject json = createMessage("ItemUpdate", items); + json["FullList"] = false; + 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); + } + QJsonObject json = createMessage("ItemUpdate", items); + json["FullList"] = true; + sendJson(json); +} + + +void TcpService::processIncomeingJson(const QByteArray& jsonbytes) +{ + QJsonDocument doc = QJsonDocument::fromJson(jsonbytes); + qDebug()<<"Got Json:"<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") + { + std::cout<<"Got item json:\n"<> items; + for(QJsonValueRef itemjson : data) + { + 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); + } + else + { + TcpService::processIncomeingJson(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; +} + +TcpServer::TcpServer(QObject* parent): + TcpService(parent), + server(this) +{ + connect(&server, &QTcpServer::newConnection, this, &TcpServer::incomingConnection); +} + +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") + { + 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(FullList && !items.empty()) + { + requestReplaceItems(items); + sigRequestSave(); + } + else 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(); + qDebug()<<"Got new client from"<peerAddress().toString(); + 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) +{ + if(command.startsWith("MSG JSON LEN ")) + { + client.state = STATE_RECV_JSON; + client.recievebytes = command.mid(13).toLongLong(); + qDebug()<<"Got command:"<readAll(); + clients[i].buffer += newChars; + + bool remianing = true; + while(remianing) + { + qDebug()< +#include + +#include "sensors/sensor.h" +#include "items/item.h" +#include "items/itemsource.h" + +class TcpService : public ItemSource +{ + Q_OBJECT +protected: + + typedef enum + { + STATE_IDLE, + STATE_RECV_JSON, + } client_state_t; + +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; + client_state_t state = STATE_IDLE; + long long recievebytes = 0; + QByteArray buffer; + +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; + +private slots: + void socketReadyRead(); + void processComand(const QByteArray& command); +}; + +class TcpServer : public TcpService +{ + Q_OBJECT + + 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; + +signals: + void sigRequestSave(); + +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/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..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 a6784a3..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 8e9d967..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/itemscrollbox.cpp b/src/ui/itemscrollbox.cpp index 6a7e6b4..170a557 100644 --- a/src/ui/itemscrollbox.cpp +++ b/src/ui/itemscrollbox.cpp @@ -21,18 +21,9 @@ void ItemScrollBox::addItem(std::weak_ptr 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/itemsettingsdialog.cpp b/src/ui/itemsettingsdialog.cpp index 1bf371c..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) : @@ -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()); 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-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 b3e317e..79a6b3e 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -1,46 +1,35 @@ #include "mainwindow.h" + +#include + #include "ui_mainwindow.h" #include "itemscrollbox.h" #include "itemsettingsdialog.h" #include "itemcreationdialog.h" -#include "../mainobject.h" -#include +#include "mainobject.h" +#include "programmode.h" +#include "items/poweritem.h" 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)); + + if(programMode != PROGRAM_MODE_PRIMARY) + ui->label_serialRecive->setHidden(true); //Sensors ui->sensorListView->setShowHidden(false); @@ -48,12 +37,14 @@ MainWindow::MainWindow(MainObject * const mainObject, QWidget *parent) : 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, &mainObject->items, &ItemStore::removeItem); + connect(ui->relayList, &ItemScrollBox::deleteRequest, &globalItems, &ItemStore::removeItem); ui->splitter->setStretchFactor(1, 1); } @@ -65,29 +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::saved() -{ - QMessageBox::information(this, "Saved", "Settings where saved"); -} - -void MainWindow::slotChangedRgb(const QColor 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 e15c466..5b04b64 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -5,14 +5,9 @@ #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 class MainObject; @@ -34,23 +29,17 @@ private: QColorDialog colorChooser; - Microcontroller *_micro; - - std::shared_ptr _powerItem; - signals: - void sigBrodcast(); 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(); - void saved(); public slots: diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui index c44b0e9..0e6732c 100644 --- a/src/ui/mainwindow.ui +++ b/src/ui/mainwindow.ui @@ -37,21 +37,21 @@
- Qt::LeftToRight + Qt::LayoutDirection::LeftToRight false - + - 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 @@ -114,49 +114,11 @@ 0 - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 48 - - - - - 0 - 128 - - - - Color - - - - - - - Config Shutdown - - - - + @@ -194,49 +156,91 @@ 0 - - - - Refesh - - - - - - - Save - - - - - - - Add Item - - - - - - - - 0 - 0 - - - - Qt::RightToLeft - - - Quit - - -
+ + + + + + Config Shutdown + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 0 + 128 + + + + Color + + + + + + + Refesh + + + + + + + Save + + + + + + + Add Item + + + + + + + + 0 + 0 + + + + Qt::LayoutDirection::RightToLeft + + + Quit + + + + + @@ -245,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 c963a05..4c84d54 100644 --- a/src/ui/sensorlistwidget.h +++ b/src/ui/sensorlistwidget.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include "../sensors/sensor.h" +#include "sensors/sensor.h" class SensorListItem : public QTableWidgetItem {