diff --git a/AGENTS.md b/AGENTS.md
deleted file mode 100644
index 81908fc..0000000
--- a/AGENTS.md
+++ /dev/null
@@ -1,129 +0,0 @@
-# SHinterface - Smart Home Interface
-
-## Overview
-SHinterface is a Qt6-based smart home control application that interfaces with microcontrollers and various sensors to manage home automation devices. It supports both primary (master) and secondary (client) modes, allowing for distributed control across multiple devices.
-
-## Architecture
-
-### Core Components
-
-1. **Main Application** (`main.cpp`)
- - Entry point with command-line argument parsing
- - Supports three modes:
- - `PROGRAM_MODE_UI_ONLY`: Secondary client mode
- - `PROGRAM_MODE_PRIMARY`: Master mode with GUI
- - `PROGRAM_MODE_HEADLESS_PRIMARY`: Master mode without GUI (server only)
-
-2. **Main Object** (`mainobject.h`, `mainobject.cpp`)
- - Base class: `MainObject`
- - Primary mode: `PrimaryMainObject` - Manages microcontroller, sensors, and item sources
- - Secondary mode: `SecondaryMainObject` - Connects to primary via TCP
-
-3. **Microcontroller Interface** (`microcontroller.h`, `microcontroller.cpp`)
- - Communicates with embedded devices via serial or TCP
- - Handles relay control, sensor data, RGB lighting, and PWM outputs
- - Implements a write queue to prevent buffer overflows
-
-### Key Systems
-
-#### Items System
-- **Item** (`items/item.h`, `items/item.cpp`): Base class for all controllable items
- - Supports different value types: boolean, unsigned integer, no value
- - Tracks update sources (user, actor, remote, loaded, backend)
-
-- Item Types:
- - **Relay** (`items/relay.h`, `items/relay.cpp`): Switchable outputs
- - **PowerItem**: Power measurement items
- - **MessageItem**: Display messages
- - **SystemItem**: System-related controls
- - **AuxItem**: Auxiliary PWM outputs
- - **RGBItem**: RGB LED control
-
-- **ItemStore** (`items/itemstore.h`, `items/itemstore.cpp`): Manages collection of items
-- **ItemSource** (`items/itemsource.h`): Interface for item providers
- - **FixedItemSource**: Static predefined items
- - **ItemLoaderSource**: Loads items from configuration
-
-#### Actors System
-Actors trigger actions based on sensor conditions or timers:
-
-- **Actor** (`actors/actor.h`, `actors/actor.cpp`): Base actor class
- - Can be active/inactive and exhausted (preventing repeated triggers)
-
-- Actor Types:
- - **FactorActor**: Triggers when a factor crosses a threshold
- - **PolynomalActor**: Uses polynomial calculations for triggering
- - **SensorActor**: Reacts to specific sensor states
- - **TimerActor**: Time-based triggering
- - **AlarmTime**: Alarm/clock functionality
- - **Regulator**: PID-like regulation control
-
-#### Sensors System
-- **Sensor** (`sensors/sensor.h`, `sensors/sensor.cpp`): Represents physical sensors
- - Sensor types: door, temperature, humidity, pressure, brightness, button, ADC, CO2, PM2.5, VOC, etc.
-
-- Sensor Sources:
- - **SunSensorSource** (`sensors/sunsensor.h`, `sensors/sunsensor.cpp`): Solar position calculations
- - **MqttSensorSource** (`sensors/mqttsensorsource.h`, `sensors/mqttsensorsource.cpp`): MQTT-based sensor data
-
-#### Networking Services
-- **TcpServer** (`service/tcpserver.h`, `service/tcpserver.cpp`): TCP server for remote control
-- **WebSocketServer** (`service/websocketserver.h`, `service/websocketserver.cpp`): WebSocket interface
-- **TcpClient** (`service/tcpclient.h`, `service/tcpclient.cpp`): Client for secondary instances
-
-### UI Components
-- **MainWindow** (`ui/mainwindow.ui`, `ui/mainwindow.cpp`): Main application window
-- **ItemWidget**: Visual representation of items
-- **ItemScrollBox**: Scrollable container for items
-- **SensorListWidget**: Displays sensor information
-- **ItemCreationDialog**: Create new items
-- **ItemSettingsDialog**: Configure item properties
-- **ActorSettingsDialog**: Configure actor behavior
-
-## Data Flow
-
-### Primary Mode (Master)
-```
-Microcontroller ↔ Items ↔ Actors ↔ Sensors
- ↑ ↑ ↑ ↑
- TCP/WebSocket │ │ │
- └──────┬──────┘
- ↓
- UI (MainWindow)
-```
-
-### Secondary Mode (Client)
-```
-Secondary Client ↔ TCP Server (Primary) → Items → Microcontroller
-```
-
-## Configuration
-- Settings stored in JSON format
-- Default location: `~/.config/shinterface.json`
-- Command-line options:
- - `-m`, `--master`: Run in master mode
- - `-H`, `--host`: Set server host IP
- - `-p`, `--port`: Set server port (default: 38940)
- - `-c`, `--config`: Specify config file path
- - `-e`, `--headless`: Run without GUI (master mode only)
-
-## Build Requirements
-- CMake 4.0+
-- Qt6 (Core, Gui, Widgets, Network, Multimedia, SerialPort, Mqtt, WebSockets)
-- libpipewire-0.3
-- libnl-3.0
-
-## Communication Protocols
-- **Microcontroller**: Text-based protocol over serial or TCP
-- **Networking**: JSON messages over TCP/WebSocket
-- **Sensors**: MQTT for remote sensors, calculated values for sun position
-
-## Key Features
-1. Distributed control with primary/secondary architecture
-2. Actor-based automation system
-3. Multi-protocol sensor support (MQTT, serial, calculated)
-4. Relay and PWM control
-5. RGB lighting control
-6. WebSocket API for remote access
-7. Configurable via JSON
-8. Cross-platform Qt application
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c8fd913..ea99bbe 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,9 +1,9 @@
cmake_minimum_required(VERSION 4.0)
-project(smartvos VERSION 1.0 LANGUAGES CXX)
+project(SHinterface VERSION 1.0 LANGUAGES CXX)
# Set C++ standard
-set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Enable all warnings
@@ -24,114 +24,81 @@ set(CMAKE_AUTOUIC ON)
# Add src to include path for relative includes
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
-# Enable testing framework
-enable_testing()
-
-# Define shared sources for static library (core sources used by both main and tests)
-set(SHINTERFACE_CORE_SOURCES
- src/sensors/mqttsensorsource.h
- src/sensors/mqttsensorsource.cpp
- src/items/mqttitem.h
- src/items/mqttitem.cpp
- src/mqttclient.h
- src/mqttclient.cpp
- src/microcontroller.h
- src/microcontroller.cpp
- src/sun.h
- src/sun.cpp
- src/programmode.h
- src/programmode.cpp
-
- src/service/service.h
- src/service/service.cpp
- src/service/tcpclient.h
- src/service/tcpclient.cpp
- src/service/server.h
- src/service/server.cpp
- src/service/tcpserver.h
- src/service/tcpserver.cpp
- src/service/websocketserver.h
- src/service/websocketserver.cpp
-
- src/actors/actor.h
- src/actors/actor.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
-)
-
-# Create static library
-add_library(smartvos_core STATIC ${SHINTERFACE_CORE_SOURCES})
-
-# Link Qt and system libraries to static library
-target_link_libraries(smartvos_core
- Qt6::Core
- Qt6::Gui
- Qt6::Widgets
- Qt6::Network
- Qt6::Multimedia
- Qt6::SerialPort
- Qt6::Mqtt
- Qt6::WebSockets
- ${PIPEWIRE_LIBRARIES}
- ${LIBNL3_LIBRARIES}
-)
-
-# Add include paths to static library
-target_include_directories(smartvos_core PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src
- ${PIPEWIRE_INCLUDE_DIRS}
- ${LIBNL3_INCLUDE_DIRS}
-)
-
-# Add subdirectory for tests
-add_subdirectory(tests)
-
# Create executable
-add_executable(smartvos
+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/pipewire.h
src/pipewire.cpp
+ src/service/service.h
+ src/service/service.cpp
+ src/service/tcpclient.h
+ src/service/tcpclient.cpp
+ src/service/server.h
+ src/service/server.cpp
+ src/service/tcpserver.h
+ src/service/tcpserver.cpp
+ src/service/websocketserver.h
+ src/service/websocketserver.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
@@ -146,9 +113,9 @@ add_executable(smartvos
src/ui/itemsettingsdialog.cpp
src/ui/actorsettingsdialog.h
src/ui/actorsettingsdialog.cpp
- src/ui/sensorsettingsdialog.h
- src/ui/sensorsettingsdialog.cpp
+ src/ui/actorwidgets/factoractorwidget.h
+ src/ui/actorwidgets/factoractorwidget.cpp
src/ui/actorwidgets/polynomalactorwidget.h
src/ui/actorwidgets/polynomalactorwidget.cpp
src/ui/actorwidgets/sensoractorwidget.h
@@ -166,12 +133,10 @@ add_executable(smartvos
src/ui/itemsettingswidgets/relayitemsettingswidget.cpp
src/ui/itemsettingswidgets/systemitemsettingswidget.h
src/ui/itemsettingswidgets/systemitemsettingswidget.cpp
- src/ui/itemsettingswidgets/mqttitemsettingswidget.h
- src/ui/itemsettingswidgets/mqttitemsettingswidget.cpp
)
# Add UI files
-target_sources(smartvos
+target_sources(SHinterface
PRIVATE
src/ui/mainwindow.ui
src/ui/itemwidget.ui
@@ -179,7 +144,7 @@ target_sources(smartvos
src/ui/itemcreationdialog.ui
src/ui/itemsettingsdialog.ui
src/ui/actorsettingsdialog.ui
- src/ui/sensorsettingsdialog.ui
+ src/ui/actorwidgets/factoractorwidget.ui
src/ui/actorwidgets/polynomalactorwidget.ui
src/ui/actorwidgets/sensoractorwidget.ui
src/ui/actorwidgets/timeractorwidget.ui
@@ -188,18 +153,16 @@ target_sources(smartvos
src/ui/itemsettingswidgets/messageitemsettingswidget.ui
src/ui/itemsettingswidgets/relayitemsettingswidget.ui
src/ui/itemsettingswidgets/systemitemsettingswidget.ui
- src/ui/itemsettingswidgets/mqttitemsettingswidget.ui
)
# Add resource file
-target_sources(smartvos
+target_sources(SHinterface
PRIVATE
resources.qrc
)
-# Link libraries - link to static library plus UI-specific dependencies
-target_link_libraries(smartvos
- smartvos_core
+# Link libraries
+target_link_libraries(SHinterface
Qt6::Core
Qt6::Gui
Qt6::Widgets
@@ -214,16 +177,3 @@ target_link_libraries(smartvos
# Add include paths
include_directories(${PIPEWIRE_INCLUDE_DIRS} ${LIBNL3_INCLUDE_DIRS})
-
-# Installation
-install(TARGETS smartvos DESTINATION bin)
-install(TARGETS smartvos_core DESTINATION lib)
-
-# Install icon
-install(FILES xyz.uvos.icon.png DESTINATION share/icons/hicolor/128x128/apps)
-
-# Install .desktop file
-install(FILES xyz.uvos.smartvos.desktop DESTINATION share/applications)
-
-# Update icon cache (optional, for icon themes)
-install(CODE "execute_process(COMMAND gtk-update-icon-cache -f -t ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX})")
diff --git a/README.md b/README.md
deleted file mode 100644
index 962d87f..0000000
--- a/README.md
+++ /dev/null
@@ -1,90 +0,0 @@
-# SHinterface - Smart Home Control Interface
-
-A Qt6-based smart home control application that interfaces with microcontrollers and sensors to manage home automation devices.
-
-## Quick Start
-
-### Building
-```bash
-mkdir build
-cd build
-cmake ..
-make
-```
-
-### Running
-
-**Primary (Master) Mode:**
-```bash
-./SHinterface -m
-```
-
-**Secondary (Client) Mode:**
-```bash
-./SHinterface -H 192.168.1.100 -p 38940
-```
-
-**Headless Server Mode:**
-```bash
-./SHinterface -m -e
-```
-
-## Features
-
-- ✅ Control relays and PWM outputs
-- ✅ Monitor various sensors (temperature, humidity, doors, etc.)
-- ✅ MQTT sensor integration
-- ✅ Actor-based automation system
-- ✅ RGB lighting control
-- ✅ WebSocket API for remote access
-- ✅ Primary/secondary architecture for distributed control
-
-## Configuration
-
-Settings are stored in JSON format. Default location:
-```
-~/.config/shinterface.json
-```
-
-You can specify a custom config file with:
-```bash
-./SHinterface -c /path/to/config.json
-```
-
-## Usage
-
-### Primary Mode (Master)
-The primary instance connects to your microcontroller and manages all devices. It can run with or without a GUI.
-
-### Secondary Mode (Client)
-Secondary instances connect to the primary via TCP and provide additional control points without needing their own microcontroller connection.
-
-## Command Line Options
-
-```
--m, --master Use in master mode
--H, --host
Set server host IP address (default: 0.0.0.0)
--p, --port Set server port (default: 38940)
--c, --config Set config file path
--e, --headless Don't start the GUI (master mode only)
---help Show help
---version Show version
-```
-
-## Architecture
-
-- **Items**: Represent controllable devices (relays, lights, etc.)
-- **Actors**: Automate actions based on sensors or time
-- **Sensors**: Provide data from physical sensors and calculated sources
-- **Services**: TCP and WebSocket interfaces for remote control
-
-## Dependencies
-
-- CMake 4.0+
-- Qt6 (Core, Gui, Widgets, Network, Multimedia, SerialPort, Mqtt, WebSockets)
-- libpipewire-0.3
-- libnl-3.0
-
-## License
-
-See LICENSE file for details.
diff --git a/UVOSicon.bmp b/UVOSicon.bmp
new file mode 100644
index 0000000..fd0d9a2
Binary files /dev/null and b/UVOSicon.bmp differ
diff --git a/remote.html b/remote.html
deleted file mode 100644
index 4765978..0000000
--- a/remote.html
+++ /dev/null
@@ -1,529 +0,0 @@
-
-
-
-
-
- SHInterface Control
-
-
-
-
-
-
-
-
-
diff --git a/resources.qrc b/resources.qrc
index ebbb814..877c740 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -1,5 +1,5 @@
- xyz.uvos.icon.bmp
+ UVOSicon.bmp
diff --git a/src/actors/actor.cpp b/src/actors/actor.cpp
index b87a074..51c3c84 100644
--- a/src/actors/actor.cpp
+++ b/src/actors/actor.cpp
@@ -6,6 +6,7 @@
#include "timeractor.h"
#include "regulator.h"
#include "polynomalactor.h"
+#include "factoractor.h"
Actor::Actor(QObject *parent): Item(QRandomGenerator::global()->generate(), "", 0, parent)
{
@@ -23,7 +24,6 @@ void Actor::performValueAction(uint8_t value)
ItemUpdateRequest request;
request.type = ITEM_UPDATE_ACTOR;
request.payload = ItemData(QRandomGenerator::global()->generate(), "Item", value);
- request.changes.value = true;
sigItemUpdate(request);
}
}
@@ -47,12 +47,9 @@ void Actor::makeInactive()
QString Actor::actionName()
{
QString string;
- if(triggerValue == 0 )
- string = "off";
- else if(triggerValue == 1 )
- string = "on";
- else
- string = "value to " + QString::number(triggerValue);
+ if(triggerValue == 0 ) string = "off";
+ else if(triggerValue == 1 ) string = "on";
+ else string = "value to " + QString::number(triggerValue);
return string;
}
@@ -110,6 +107,7 @@ std::shared_ptr Actor::createActor(const QString& type)
else if(type == "Timer") actor = std::shared_ptr(new TimerActor());
else if(type == "Regulator") actor = std::shared_ptr(new Regulator());
else if(type == "Polynomal") actor = std::shared_ptr(new PolynomalActor());
+ else if(type == "MultiFactor") actor = std::shared_ptr(new MultiFactorActor());
else if(type == "Actor") actor = std::shared_ptr(new Actor());
return actor;
}
diff --git a/src/actors/alarmtime.h b/src/actors/alarmtime.h
index 99c0b7e..0d65d84 100644
--- a/src/actors/alarmtime.h
+++ b/src/actors/alarmtime.h
@@ -39,13 +39,13 @@ public:
virtual void load(const QJsonObject& json, const bool preserve = false);
uint8_t getRepeat();
- virtual QString getName() const;
public slots:
void run();
virtual void makeActive();
virtual void makeInactive();
+ virtual QString getName() const;
void doTick();
void changeTime(const QDateTime& time);
void setRepeat(const uint8_t repeat);
diff --git a/src/actors/factoractor.cpp b/src/actors/factoractor.cpp
new file mode 100644
index 0000000..cadd017
--- /dev/null
+++ b/src/actors/factoractor.cpp
@@ -0,0 +1,81 @@
+#include "factoractor.h"
+
+MultiFactorActor::MultiFactorActor(Actor* factorActor, const uint preCancleMin, QObject *parent):
+ Actor(parent),
+ factorActor_(factorActor),
+ preCancleMin_(preCancleMin)
+{
+ activationTime.setMSecsSinceEpoch(0);
+ if(factorActor)
+ connect(factorActor, &Actor::sigItemUpdate, this, &MultiFactorActor::factorActorSlot);
+}
+
+void MultiFactorActor::factorActorSlot(ItemUpdateRequest update)
+{
+ if(update.payload.getValue() == factorDirection)
+ {
+ activationTime = QDateTime::currentDateTime();
+ }
+}
+
+void MultiFactorActor::enactValue(uint8_t value)
+{
+ if(value)
+ {
+ QDateTime current = QDateTime::currentDateTime();
+ if(current.addSecs(-preCancleMin_*60) > activationTime )
+ {
+ performAction();
+ }
+ exausted = true;
+ for(size_t i = 0; i < getActors().size(); ++i) if(!getActors()[i]->isExausted())
+ exausted = false;
+ }
+}
+
+QString MultiFactorActor::getName() const
+{
+ if(name_.size() > 0) return name_;
+ else
+ {
+ QString string;
+ string = "Multi Factor \"" + (factorActor_ ? factorActor_->getName() : "NULL") + "\"";
+ return string;
+ }
+}
+
+void MultiFactorActor::setFactorActor(std::shared_ptr factorActor)
+{
+ factorActor_=factorActor;
+ connect(factorActor_.get(), &Actor::sigItemUpdate, this, &MultiFactorActor::factorActorSlot);
+}
+
+void MultiFactorActor::store(QJsonObject &json)
+{
+ json["Type"] = "MultiFactor";
+ Actor::store(json);
+ json["PreCancleMinutes"] = static_cast(preCancleMin_);
+ json["FactorDirection"] = factorDirection;
+ QJsonObject factorActorObject;
+ if(factorActor_)
+ {
+ factorActor_->store(factorActorObject);
+ }
+}
+
+void MultiFactorActor::load(const QJsonObject &json, bool preserve)
+{
+ Actor::load(json, preserve);
+ preCancleMin_ = static_cast(json["PreCancleMinutes"].toInt(10));
+ factorDirection = json["FacotorDirection"].toBool(true);
+ if(json["FactorActor"].isObject())
+ {
+ factorActor_ = Actor::loadActor(json["FactorActor"].toObject());
+ }
+ if(factorActor_)
+ {
+ connect(factorActor_.get(), &Actor::sigItemUpdate, this, &MultiFactorActor::factorActorSlot);
+ }
+}
+
+
diff --git a/src/actors/factoractor.h b/src/actors/factoractor.h
new file mode 100644
index 0000000..97a6814
--- /dev/null
+++ b/src/actors/factoractor.h
@@ -0,0 +1,59 @@
+#ifndef REMINDERACTOR_H
+#define REMINDERACTOR_H
+
+#include
+#include "actor.h"
+
+class MultiFactorActor: public Actor
+{
+private:
+
+ std::shared_ptr factorActor_;
+ QDateTime activationTime;
+ uint preCancleMin_;
+
+ bool factorDirection = true;
+
+private slots:
+
+ void factorActorSlot(ItemUpdateRequest update);
+
+public slots:
+
+ virtual void enactValue(uint8_t value) override;
+
+public:
+
+ MultiFactorActor(Actor* FactorActor = nullptr, const uint preCancleMin = 10, QObject *parent = nullptr);
+
+ virtual QString getName() const override;
+
+ void setFactorActor(std::shared_ptr factorActor);
+ std::shared_ptr getFactorActor()
+ {
+ return factorActor_;
+ }
+ void setFactorDirection(const bool direction)
+ {
+ factorDirection = direction;
+ }
+ bool getFactorDirection()
+ {
+ return factorDirection;
+ }
+ uint getPreCancleTime()
+ {
+ return preCancleMin_;
+ }
+ void setPreCancleTime(uint minutes)
+ {
+ preCancleMin_ = minutes;
+ }
+
+ virtual ~MultiFactorActor() {}
+
+ virtual void store(QJsonObject& json) override;
+ virtual void load(const QJsonObject& json, bool preserve) override;
+};
+
+#endif // REMINDERACTOR_H
diff --git a/src/actors/polynomalactor.cpp b/src/actors/polynomalactor.cpp
index 3f115f0..cc783fd 100644
--- a/src/actors/polynomalactor.cpp
+++ b/src/actors/polynomalactor.cpp
@@ -31,7 +31,7 @@ void PolynomalActor::getCoeffiancts( double& pow3, double& pow2, double& pow1, d
pow0=pow0_;
}
-void PolynomalActor::sensorEvent(Sensor sensor, sensor_update_type_t type)
+void PolynomalActor::sensorEvent(Sensor sensor)
{
if(active && sensor == sensor_)
{
diff --git a/src/actors/polynomalactor.h b/src/actors/polynomalactor.h
index 7f1f54b..1ff3675 100644
--- a/src/actors/polynomalactor.h
+++ b/src/actors/polynomalactor.h
@@ -18,7 +18,7 @@ private:
public slots:
- void sensorEvent(Sensor sensor, sensor_update_type_t type);
+ void sensorEvent(Sensor sensor);
public:
diff --git a/src/actors/regulator.cpp b/src/actors/regulator.cpp
index 7ec2bb5..94f8bb6 100644
--- a/src/actors/regulator.cpp
+++ b/src/actors/regulator.cpp
@@ -21,7 +21,7 @@ void Regulator::setSensor(const Sensor sensor)
sensor_ = sensor;
}
-void Regulator::sensorEvent(Sensor sensor, sensor_update_type_t type)
+void Regulator::sensorEvent(Sensor sensor)
{
if(active && sensor == sensor_)
{
diff --git a/src/actors/regulator.h b/src/actors/regulator.h
index a1b3a5a..339b2ca 100644
--- a/src/actors/regulator.h
+++ b/src/actors/regulator.h
@@ -26,7 +26,7 @@ private slots:
public slots:
- void sensorEvent(Sensor sensor, sensor_update_type_t type);
+ void sensorEvent(Sensor sensor);
void setSensor(const Sensor sensor);
void setPoint(float setPoint );
diff --git a/src/actors/sensoractor.cpp b/src/actors/sensoractor.cpp
index 5e083ef..758b761 100644
--- a/src/actors/sensoractor.cpp
+++ b/src/actors/sensoractor.cpp
@@ -17,7 +17,7 @@ void SensorActor::setSensor(const Sensor sensor)
sensor_ = sensor;
}
-void SensorActor::sensorEvent(Sensor sensor, sensor_update_type_t type)
+void SensorActor::sensorEvent(Sensor sensor)
{
if(sensor == sensor_)
{
diff --git a/src/actors/sensoractor.h b/src/actors/sensoractor.h
index 99e2865..27a9355 100644
--- a/src/actors/sensoractor.h
+++ b/src/actors/sensoractor.h
@@ -18,7 +18,7 @@ private:
public slots:
- void sensorEvent(Sensor sensor, sensor_update_type_t type);
+ void sensorEvent(Sensor sensor);
void setSloap(uint8_t sloap);
void setSensor(const Sensor sensor);
diff --git a/src/actors/timeractor.cpp b/src/actors/timeractor.cpp
index d916045..a0a6b1e 100644
--- a/src/actors/timeractor.cpp
+++ b/src/actors/timeractor.cpp
@@ -7,13 +7,11 @@ TimerActor::TimerActor(const int timeoutSec, QObject *parent): Actor(parent), ti
timer.setSingleShot(true);
}
-void TimerActor::onItemUpdated(ItemUpdateRequest update)
+void TimerActor::onValueChanged(uint8_t state)
{
- if(update.changes.value && ((update.payload.getValue() && !triggerValue) || (!update.payload.getValue() && triggerValue)))
+ if((state && !triggerValue) || (!state && triggerValue))
{
- qDebug()<<"Timer started";
- if(timer.isActive())
- timer.stop();
+ if(timer.isActive()) timer.stop();
timer.setInterval(timeoutMsec_);
timer.start();
}
diff --git a/src/actors/timeractor.h b/src/actors/timeractor.h
index f30ff7c..36290d9 100644
--- a/src/actors/timeractor.h
+++ b/src/actors/timeractor.h
@@ -16,15 +16,15 @@ private slots:
public slots:
- virtual void onItemUpdated(ItemUpdateRequest update) override;
+ virtual void onValueChanged(uint8_t state);
void setTimeout(const int timeoutSec);
public:
explicit TimerActor(const int timeoutSec = 60, QObject *parent = nullptr);
- virtual QString getName() const override;
+ virtual QString getName() const;
int getTimeout();
- virtual void store(QJsonObject& json) override;
- virtual void load(const QJsonObject& json, bool preserve) override;
+ virtual void store(QJsonObject& json);
+ virtual void load(const QJsonObject& json, bool preserve);
};
diff --git a/src/items/fixeditemsource.cpp b/src/items/fixeditemsource.cpp
index b166831..b4459ff 100644
--- a/src/items/fixeditemsource.cpp
+++ b/src/items/fixeditemsource.cpp
@@ -10,19 +10,5 @@ FixedItemSource::FixedItemSource(Microcontroller* micro, QObject *parent):
void FixedItemSource::refresh()
{
- std::vector requests;
-
- ItemAddRequest request;
- request.type = ITEM_UPDATE_BACKEND;
-
- request.payload = powerItem;
- requests.push_back(request);
-
- request.payload = rgbItem;
- requests.push_back(request);
-
- request.payload = auxItem;
- requests.push_back(request);
-
- gotItems(requests);
+ gotItems({powerItem, rgbItem, auxItem}, ITEM_UPDATE_BACKEND);
}
diff --git a/src/items/item.cpp b/src/items/item.cpp
index 6b2eb5b..7f350a2 100644
--- a/src/items/item.cpp
+++ b/src/items/item.cpp
@@ -10,12 +10,11 @@
#include "auxitem.h"
#include "poweritem.h"
#include "rgbitem.h"
-#include "mqttitem.h"
#include
-ItemData::ItemData(uint32_t itemIdIn, QString name, uint8_t value, bool loaded, bool hidden, item_value_type_t type, QString groupName):
- name_(name), value_(value), itemId_(itemIdIn), loaded_(loaded), hidden_(hidden), type_(type), groupName_(groupName)
+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)
{
}
@@ -47,76 +46,19 @@ uint32_t ItemData::id() const
void ItemData::store(QJsonObject &json)
{
- storeWithChanges(json, ItemFieldChanges(true));
-}
-
-void ItemData::storeWithChanges(QJsonObject& json, const ItemFieldChanges& changes)
-{
+ json["Name"] = name_;
json["ItemId"] = static_cast(itemId_);
- json["ValueType"] = type_;
- if(changes.name)
- json["Name"] = name_;
- if(changes.value)
- json["Value"] = static_cast(value_);
- if(changes.groupName && !groupName_.isEmpty() && groupName_ != "All")
- json["GroupName"] = groupName_;
- if(changes.valueNames && !valueNames_.empty())
- {
- QJsonArray valueNamesArray;
- for(const QString& name : valueNames_)
- valueNamesArray.append(name);
- json["ValueNames"] = valueNamesArray;
- }
- if(changes.override)
- json["override"] = override_;
+ json["Value"] = static_cast(value_);
}
void ItemData::load(const QJsonObject &json, const bool preserve)
{
- loadWithChanges(json, preserve);
-}
-
-ItemFieldChanges ItemData::loadWithChanges(const QJsonObject& json, const bool preserve)
-{
- ItemFieldChanges changes;
if(!preserve)
{
- if(json.contains("Name"))
- {
- name_ = json["Name"].toString();
- changes.name = true;
- }
- if(json.contains("Value"))
- {
- value_ = json["Value"].toInt();
- changes.value = true;
- }
- if(json.contains("GroupName"))
- {
- groupName_ = json["GroupName"].toString();
- changes.groupName = true;
- }
- if(json.contains("ValueType"))
- {
- type_ = static_cast(json["ValueType"].toInt());
- changes.type = true;
- }
- if(json.contains("ValueNames"))
- {
- valueNames_.clear();
- QJsonArray valueNamesArray = json["ValueNames"].toArray();
- for(int i = 0; i < valueNamesArray.size(); ++i)
- valueNames_.push_back(valueNamesArray[i].toString());
- changes.valueNames = true;
- }
- if(json.contains("override"))
- {
- override_ = json["override"].toBool(false);
- changes.override = true;
- }
+ name_ = json["Name"].toString(name_);
itemId_ = static_cast(json["ItemId"].toDouble(0));
+ value_ = json["Value"].toInt();
}
- return changes;
}
bool ItemData::getLoaded() const
@@ -129,27 +71,15 @@ void ItemData::setLoaded(bool loaded)
loaded_ = loaded;
}
-bool ItemData::hasChanged(const ItemData& other) const
+bool ItemData::hasChanged(const ItemData& other)
{
- ItemFieldChanges changes(true);
- return hasChanged(other, changes);
-}
-
-bool ItemData::hasChanged(const ItemData& other, const ItemFieldChanges& changes) const
-{
- if(changes.name && other.getName() != getName())
+ if(other != *this)
+ return false;
+ if(other.getName() != getName())
return true;
- if(changes.value && other.getValue() != getValue())
+ if(other.getValue() != getValue())
return true;
- if(changes.hidden && other.isHidden() != isHidden())
- return true;
- if(changes.groupName && other.getGroupName() != getGroupName())
- return true;
- if(changes.actors)
- return true;
- if(changes.valueNames && other.getValueNames() != getValueNames())
- return true;
- if(changes.override && other.getOverride() != getOverride())
+ if(other.getLoaded() != getLoaded())
return true;
return false;
}
@@ -169,57 +99,10 @@ item_value_type_t ItemData::getValueType()
return type_;
}
-QString ItemData::getGroupName() const
-{
- return groupName_;
-}
-
-void ItemData::setGroupName(QString groupName)
-{
- groupName_ = groupName;
-}
-
-std::vector ItemData::getValueNames() const
-{
- return valueNames_;
-}
-
-void ItemData::setValueNames(std::vector valueNames)
-{
- valueNames_ = std::move(valueNames);
-}
-
-int ItemData::valueNameToIndex(const QString& name) const
-{
- for(size_t i = 0; i < valueNames_.size(); ++i)
- {
- if(valueNames_[i] == name)
- return static_cast(i);
- }
- return -1;
-}
-
-QString ItemData::indexToValueName(int index) const
-{
- if(index >= 0 && static_cast(index) < valueNames_.size())
- return valueNames_[index];
- return QString();
-}
-
-bool ItemData::getOverride() const
-{
- return override_;
-}
-
-void ItemData::setOverride(bool overrideVal)
-{
- override_ = overrideVal;
-}
-
//item
Item::Item(uint32_t itemIdIn, QString name, uint8_t value, QObject *parent): QObject(parent), ItemData (itemIdIn, name,
- value, false, false, ITEM_VALUE_BOOL, "All")
+ value)
{
}
@@ -236,36 +119,33 @@ Item::~Item()
void Item::store(QJsonObject &json)
{
ItemData::store(json);
- if(!actors_.empty())
+ json["override"] = override_;
+ QJsonArray actorsArray;
+ for(size_t i = 0; i < actors_.size(); ++i)
{
- QJsonArray actorsArray;
- for(size_t i = 0; i < actors_.size(); ++i)
+ if(!actors_[i]->isExausted())
{
- if(!actors_[i]->isExausted())
- {
- QJsonObject actorObject;
- actors_[i]->store(actorObject);
- actorsArray.append(actorObject);
- }
+ QJsonObject actorObject;
+ actors_[i]->store(actorObject);
+ actorsArray.append(actorObject);
}
- json["Actors"] = actorsArray;
}
+ json["Actors"] = actorsArray;
+ json["ValueType"] = type_;
}
void Item::load(const QJsonObject &json, const bool preserve)
{
ItemData::load(json, preserve);
- if(json.contains("Actors"))
+ override_ = json["override"].toBool(false);
+ const QJsonArray actorsArray(json["Actors"].toArray(QJsonArray()));
+ for(int i = 0; i < actorsArray.size(); ++i)
{
- const QJsonArray actorsArray(json["Actors"].toArray(QJsonArray()));
- for(int i = 0; i < actorsArray.size(); ++i)
+ if(actorsArray[i].isObject())
{
- if(actorsArray[i].isObject())
- {
- std::shared_ptr actor = Actor::loadActor(actorsArray[i].toObject());
- if(actor != nullptr)
- addActor(actor);
- }
+ std::shared_ptr actor = Actor::loadActor(actorsArray[i].toObject());
+ if(actor != nullptr)
+ addActor(actor);
}
}
}
@@ -276,22 +156,13 @@ Item& Item::operator=(const ItemData& other)
value_ = other.getValue();
itemId_ = other.id();
hidden_ = other.isHidden();
- groupName_ = other.getGroupName();
- valueNames_ = other.getValueNames();
return *this;
}
void Item::requestUpdate(ItemUpdateRequest update)
{
assert(update.type != ITEM_UPDATE_INVALID);
- assert(!update.changes.isNone());
-
- if(update.type == ITEM_UPDATE_LOADED)
- {
- qDebug()<<__func__<& actor : update.newActors)
addActor(actor);
}
- if(update.changes.valueNames)
- valueNames_ = update.payload.getValueNames();
- if(update.changes.override)
- override_ = update.payload.getOverride();
update.payload = *this;
updated(update);
}
@@ -370,12 +233,12 @@ bool Item::removeActor(std::shared_ptr actor)
void Item::setOverride(const bool in)
{
- ItemData::setOverride(in);
+ override_ = in;
}
bool Item::getOverride()
{
- return ItemData::getOverride();
+ return override_;
}
void Item::removeAllActors()
@@ -416,8 +279,6 @@ std::shared_ptr- Item::loadItem(const QJsonObject& json)
newItem = std::shared_ptr(new PowerItem);
else if(json["Type"].toString("") == "Rgb")
newItem = std::shared_ptr(new RgbItem);
- else if(json["Type"].toString("") == "Mqtt")
- newItem = std::shared_ptr(new MqttItem);
else
qWarning()<<"Unable to load unkown item type: "< Item::loadItem(const QJsonObject& json)
return newItem;
}
-ItemUpdateRequest Item::createValueUpdateRequest(item_update_type_t type,
+ItemUpdateRequest Item::createValueUpdateRequest(uint8_t value,
+ item_update_type_t type,
bool withActors)
{
ItemUpdateRequest update;
update.type = type;
update.payload = *this;
+ update.payload.setValueData(value);
if(withActors)
update.newActors = actors_;
return update;
diff --git a/src/items/item.h b/src/items/item.h
index 6ddf6ef..d461006 100644
--- a/src/items/item.h
+++ b/src/items/item.h
@@ -11,8 +11,7 @@ class Actor;
typedef enum {
ITEM_VALUE_BOOL = 0,
ITEM_VALUE_UINT,
- ITEM_VALUE_NO_VALUE,
- ITEM_VALUE_ENUM,
+ ITEM_VALUE_NO_VALUE
} item_value_type_t;
typedef enum {
@@ -24,9 +23,6 @@ typedef enum {
ITEM_UPDATE_INVALID
} item_update_type_t;
-struct ItemFieldChanges;
-struct ItemUpdateRequest;
-
class ItemData
{
protected:
@@ -36,9 +32,6 @@ protected:
bool loaded_;
bool hidden_;
item_value_type_t type_;
- QString groupName_;
- std::vector valueNames_;
- bool override_ = false;
public:
ItemData(uint32_t itemIdIn = QRandomGenerator::global()->generate(),
@@ -46,8 +39,7 @@ public:
uint8_t value = 0,
bool loaded = false,
bool hidden = false,
- item_value_type_t type = ITEM_VALUE_BOOL,
- QString groupName = "");
+ item_value_type_t type = ITEM_VALUE_BOOL);
inline bool operator==(const ItemData& in) const
{
@@ -60,8 +52,7 @@ public:
uint32_t id() const;
- bool hasChanged(const ItemData& other) const;
- bool hasChanged(const ItemData& other, const ItemFieldChanges& changes) const;
+ bool hasChanged(const ItemData& other);
void setName(QString name);
uint8_t getValue() const;
void setValueData(uint8_t value);
@@ -70,26 +61,25 @@ public:
bool isHidden() const;
void setHidden(bool hidden);
item_value_type_t getValueType();
- QString getGroupName() const;
- void setGroupName(QString groupName);
- std::vector getValueNames() const;
- void setValueNames(std::vector valueNames);
- int valueNameToIndex(const QString& name) const;
- QString indexToValueName(int index) const;
- void storeWithChanges(QJsonObject& json, const ItemFieldChanges& changes);
- ItemFieldChanges loadWithChanges(const QJsonObject& json, const bool preserve = false);
virtual QString getName() const;
- bool getOverride() const;
- void setOverride(bool overrideVal);
virtual void store(QJsonObject& json);
virtual void load(const QJsonObject& json, const bool preserve = false);
};
+struct ItemUpdateRequest
+{
+ item_update_type_t type = ITEM_UPDATE_INVALID;
+ ItemData payload;
+ std::vector > newActors;
+};
+
+
class Item: public QObject, public ItemData
{
Q_OBJECT
private:
std::vector< std::shared_ptr > actors_;
+ bool override_ = false;
signals:
void updated(ItemUpdateRequest update);
@@ -114,7 +104,8 @@ public:
void setActorsActive(bool in);
void setOverride(const bool in);
bool getOverride();
- ItemUpdateRequest createValueUpdateRequest(item_update_type_t type,
+ ItemUpdateRequest createValueUpdateRequest(uint8_t value,
+ item_update_type_t type,
bool withActors = false);
virtual void store(QJsonObject& json);
@@ -127,56 +118,3 @@ protected:
};
-
-struct ItemFieldChanges
-{
- bool name :1;
- bool value :1;
- bool hidden :1;
- bool type :1;
- bool groupName :1;
- bool actors :1;
- bool valueNames :1;
- bool override :1;
- ItemFieldChanges(bool defaultVal = false)
- {
- name = defaultVal;
- value = defaultVal;
- hidden = defaultVal;
- type = defaultVal;
- groupName = defaultVal;
- actors = false;
- valueNames = defaultVal;
- override = defaultVal;
- }
- inline bool isNone() const
- {
- return !name && !value && !hidden && !type && !groupName && !actors && !valueNames && !override;
- }
-};
-
-struct ItemUpdateRequest
-{
- item_update_type_t type = ITEM_UPDATE_INVALID;
- ItemData payload;
- ItemFieldChanges changes;
- std::vector > newActors;
-};
-
-struct ItemAddRequest
-{
- item_update_type_t type = ITEM_UPDATE_INVALID;
- std::shared_ptr
- payload;
- ItemFieldChanges changes;
- inline ItemUpdateRequest updateRequest() const
- {
- ItemUpdateRequest update;
- update.payload = *payload;
- update.type = type;
- update.changes = changes;
- if(changes.actors)
- update.newActors = payload->getActors();
- return update;
- }
-};
-
diff --git a/src/items/itemloadersource.cpp b/src/items/itemloadersource.cpp
index b689a3c..a24e5a5 100644
--- a/src/items/itemloadersource.cpp
+++ b/src/items/itemloadersource.cpp
@@ -10,7 +10,7 @@ ItemLoaderSource::ItemLoaderSource(const QJsonObject& json, QObject *parent):
void ItemLoaderSource::refresh()
{
- std::vector itemAddRequests;
+ std::vector> items;
const QJsonArray itemsArray(json["Items"].toArray());
for(int i = 0; i < itemsArray.size(); ++i)
{
@@ -21,18 +21,11 @@ void ItemLoaderSource::refresh()
std::shared_ptr
- newItem = Item::loadItem(itemObject);
if(newItem)
{
+ items.push_back(newItem);
qDebug()<<"Loaded item"<getName();
- ItemAddRequest request;
- request.type = ITEM_UPDATE_LOADED;
- request.payload = newItem;
- request.changes = ItemFieldChanges(true);
- if(newItem->hasActors())
- request.changes.actors = true;
- request.changes.value = false;
- itemAddRequests.push_back(request);
}
}
- gotItems(itemAddRequests);
+ gotItems(items, ITEM_UPDATE_LOADED);
}
void ItemLoaderSource::updateJson(const QJsonObject& json)
diff --git a/src/items/itemsource.h b/src/items/itemsource.h
index 1753f75..5c2bba2 100644
--- a/src/items/itemsource.h
+++ b/src/items/itemsource.h
@@ -17,7 +17,7 @@ public slots:
virtual void refresh() = 0;
signals:
- void gotItems(std::vector items);
+ void gotItems(std::vector> items, item_update_type_t updateType);
void requestReplaceItems(std::vector> items);
void updateItems(std::vector updates);
};
diff --git a/src/items/itemstore.cpp b/src/items/itemstore.cpp
index 1b52bf9..232d319 100644
--- a/src/items/itemstore.cpp
+++ b/src/items/itemstore.cpp
@@ -6,38 +6,39 @@ ItemStore::ItemStore(QObject *parent): QObject(parent)
{
}
-void ItemStore::addItem(const ItemAddRequest& item)
+void ItemStore::addItem(const std::shared_ptr
- & item, item_update_type_t updateType)
{
- qDebug()<<"Item add request for"<getName()<id();
std::shared_ptr
- matched = nullptr;
for(unsigned i = 0; i < items_.size(); i++ )
{
- if(*items_[i] == *item.payload)
+ if(*items_[i] == *item)
{
matched = items_[i];
- assert(matched->id() == items_[i]->id());
break;
}
}
if(!matched)
{
- items_.push_back(item.payload);
- connect(item.payload.get(), &Item::updated, this, &ItemStore::itemUpdateSlot);
- qDebug()<<"Item"<getName()<<"added"<<(item.payload->getLoaded() ? "from loaded" : "");
+ 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.changes.isNone())
+ else
{
- qDebug()<<"Item"<getName()<<"was matched with"<getName()<<"and has changes";
- ItemUpdateRequest request = item.updateRequest();
+ ItemUpdateRequest request = item->createValueUpdateRequest(item->getValue(),
+ updateType,
+ updateType == ITEM_UPDATE_LOADED);
+ request.newActors = item->getActors();
updateItem(request);
}
}
-void ItemStore::addItems(const std::vector& itemIn)
+void ItemStore::addItems(const std::vector>& itemIn,
+ item_update_type_t updateType)
{
for(unsigned j = 0; j < itemIn.size(); j++)
- addItem(itemIn[j]);
+ addItem(itemIn[j], updateType);
}
void ItemStore::removeItem(const ItemData& item)
@@ -56,15 +57,8 @@ void ItemStore::removeItem(const ItemData& item)
void ItemStore::replaceItems(const std::vector>& items)
{
- for(const std::shared_ptr
- & item : items)
- {
- ItemAddRequest request;
- request.changes = ItemFieldChanges(true);
- request.changes.actors = true;
- request.type = ITEM_UPDATE_LOADED;
- request.payload = item;
- addItem(request);
- }
+ qDebug()<<__func__;
+ addItems(items, ITEM_UPDATE_LOADED);
std::vector deletedItems;
for(std::shared_ptr
- item : items_)
{
diff --git a/src/items/itemstore.h b/src/items/itemstore.h
index 93d1b9f..b4bdeaa 100644
--- a/src/items/itemstore.h
+++ b/src/items/itemstore.h
@@ -39,8 +39,8 @@ signals:
public slots:
void removeItem(const ItemData& item);
- void addItem(const ItemAddRequest& item);
- void addItems(const std::vector& itemsIn);
+ void addItem(const std::shared_ptr
- & item, item_update_type_t updateType);
+ void addItems(const std::vector>& itemsIn, item_update_type_t updateType);
void replaceItems(const std::vector>& items);
void updateItems(const std::vector& updates);
void updateItem(const ItemUpdateRequest& update);
diff --git a/src/items/mqttitem.cpp b/src/items/mqttitem.cpp
deleted file mode 100644
index da91bef..0000000
--- a/src/items/mqttitem.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-#include "mqttitem.h"
-
-#include
-#include
-#include
-#include
-
-#include "mqttclient.h"
-#include "programmode.h"
-
-MqttItem::MqttItem(QString name, uint8_t value, QObject *parent)
- : Item(0, name, value, parent),
- topic_(""),
- valueKey_("state"),
- valueOn_("ON"),
- valueOff_("OFF")
-{
- hashId();
- std::shared_ptr workClient = client.lock();
- assert(workClient || programMode == PROGRAM_MODE_UI_ONLY);
-
- if(workClient)
- connect(workClient->getClient().get(), &QMqttClient::stateChanged, this, &MqttItem::onClientStateChanged);
-}
-
-MqttItem::~MqttItem()
-{
- qDebug()<<__func__;
- std::shared_ptr workClient = client.lock();
- if(!workClient)
- return;
-
- if(subscription)
- {
- disconnect(subscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onMessageReceived);
- workClient->unsubscribe(subscription);
- }
-
- if(devicesSubscription)
- {
- disconnect(devicesSubscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onDevicesMessageReceived);
- workClient->unsubscribe(devicesSubscription);
- }
-}
-
-void MqttItem::onClientStateChanged(QMqttClient::ClientState state)
-{
- if(state == QMqttClient::Connected)
- {
- refreshSubscription();
- // Subscribe to bridge/devices to get exposes
- std::shared_ptr workClient = client.lock();
- if(workClient && !exposeLoaded_)
- {
- devicesSubscription = workClient->subscribe(workClient->getBaseTopic() + "/bridge/devices");
- connect(devicesSubscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onDevicesMessageReceived);
- }
- }
-}
-
-void MqttItem::refreshSubscription()
-{
- std::shared_ptr workClient = client.lock();
- if(!workClient || topic_.isEmpty())
- return;
-
- if(workClient->getClient()->state() != QMqttClient::Connected)
- return;
-
- if(subscription)
- {
- disconnect(subscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onMessageReceived);
- workClient->unsubscribe(subscription);
- }
-
- subscription = workClient->subscribe(workClient->getBaseTopic() + "/" + getTopic());
- connect(subscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onMessageReceived);
-}
-
-void MqttItem::onDevicesMessageReceived(const QMqttMessage& message)
-{
- if(exposeLoaded_)
- return;
-
- QJsonDocument doc = QJsonDocument::fromJson(message.payload());
- if(!doc.isArray())
- return;
-
- QJsonArray devices = doc.array();
- for(const QJsonValue& deviceValue : devices)
- {
- if(!deviceValue.isObject())
- continue;
-
- QJsonObject device = deviceValue.toObject();
- QString ieeeAddr = device["ieee_address"].toString();
-
- // Check if this device matches our topic (friendly_name)
- QString friendlyName = device["friendly_name"].toString();
- if(friendlyName == topic_)
- {
- loadExposeFromDevice(device);
- exposeLoaded_ = true;
- Q_EMIT exposeLoaded();
-
- // Unsubscribe from devices topic since we found our device
- std::shared_ptr workClient = client.lock();
- if(workClient && devicesSubscription)
- {
- disconnect(devicesSubscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onDevicesMessageReceived);
- workClient->unsubscribe(devicesSubscription);
- devicesSubscription = nullptr;
- }
- break;
- }
- }
-}
-
-void MqttItem::loadExposeFromDevice(const QJsonObject& device)
-{
- // Get definition - may be null for unsupported devices
- QJsonObject definition = device["definition"].toObject();
- if(definition.isEmpty())
- {
- qWarning() << "MqttItem" << topic_ << "device has no definition (unsupported)";
- return;
- }
-
- // Get exposes from definition
- QJsonArray exposes = definition["exposes"].toArray();
- if(exposes.isEmpty())
- {
- qWarning() << "MqttItem" << topic_ << "device has no exposes";
- return;
- }
-
- for(const QJsonValue& exposeValue : exposes)
- {
- if(!exposeValue.isObject())
- continue;
-
- QJsonObject expose = exposeValue.toObject();
- QString property = expose["property"].toString();
-
- // Check if this expose matches our valueKey
- if(property == valueKey_)
- {
- setFromExpose(expose);
- qDebug() << "MqttItem" << topic_ << "detected type" << expose["type"].toString() << "for property" << valueKey_;
- return;
- }
-
- // Check if it's a composite type with features
- if(expose["type"].toString() == "composite" || expose["type"].toString() == "light")
- {
- QJsonArray features = expose["features"].toArray();
- for(const QJsonValue& featureValue : features)
- {
- if(!featureValue.isObject())
- continue;
-
- QJsonObject feature = featureValue.toObject();
- if(feature["property"].toString() == valueKey_)
- {
- setFromExpose(feature);
- qDebug() << "MqttItem" << topic_ << "detected type" << feature["type"].toString() << "for property" << valueKey_;
- return;
- }
- }
- }
- }
-
- qWarning() << "MqttItem" << topic_ << "could not find expose for property" << valueKey_;
-}
-
-void MqttItem::onMessageReceived(const QMqttMessage& message)
-{
- QJsonDocument doc = QJsonDocument::fromJson(message.payload());
- if(doc.isObject())
- {
- QJsonObject obj = doc.object();
- if(obj.contains(getValueKey()))
- {
- QJsonValue value = obj[getValueKey()];
- ItemUpdateRequest req = createValueUpdateRequest(ITEM_UPDATE_BACKEND);
- req.changes.value = true;
-
- if(getValueType() == ITEM_VALUE_UINT)
- {
- // Numeric value
- req.payload.setValueData(value.toInt(0));
- }
- else if(getValueType() == ITEM_VALUE_ENUM)
- {
- // Enum value - find index
- QString strValue = value.toString();
- int index = valueNameToIndex(strValue);
- if(index >= 0)
- req.payload.setValueData(index);
- }
- else
- {
- // Binary value
- QString strValue = value.toString();
- if(strValue == getValueOn() || strValue == "ON" || strValue == "true")
- req.payload.setValueData(true);
- else
- req.payload.setValueData(false);
- }
- requestUpdate(req);
- }
- }
-}
-
-void MqttItem::hashId()
-{
- QString hashString = topic_ + "/" + valueKey_;
- itemId_ = qHash(hashString.toLatin1());
-}
-
-void MqttItem::setTopic(const QString& topic)
-{
- topic_ = topic;
- hashId();
- refreshSubscription();
-}
-
-void MqttItem::setValueKey(const QString& valueKey)
-{
- valueKey_ = valueKey;
- hashId();
-}
-
-void MqttItem::setValueOn(const QString& valueOn)
-{
- valueOn_ = valueOn;
-}
-
-void MqttItem::setValueOff(const QString& valueOff)
-{
- valueOff_ = valueOff;
-}
-
-void MqttItem::setValueMin(int min)
-{
- valueMin_ = min;
-}
-
-void MqttItem::setValueMax(int max)
-{
- valueMax_ = max;
-}
-
-void MqttItem::setValueStep(int step)
-{
- valueStep_ = step;
-}
-
-void MqttItem::setValueType(item_value_type_t type)
-{
- type_ = type;
-}
-
-void MqttItem::setFromExpose(const QJsonObject& expose)
-{
- QString type = expose["type"].toString();
- QString property = expose["property"].toString();
-
- setValueKey(property);
-
- if(type == "binary")
- {
- type_ = ITEM_VALUE_BOOL;
- setValueOn(expose["value_on"].toString("ON"));
- setValueOff(expose["value_off"].toString("OFF"));
- }
- else if(type == "numeric")
- {
- type_ = ITEM_VALUE_UINT;
- setValueMin(expose["value_min"].toInt(0));
- setValueMax(expose["value_max"].toInt(255));
- setValueStep(expose["value_step"].toInt(1));
- }
- else if(type == "enum")
- {
- type_ = ITEM_VALUE_ENUM;
- QJsonArray values = expose["values"].toArray();
- std::vector valueNames;
- for(const QJsonValue& v : values)
- valueNames.push_back(v.toString());
- setValueNames(valueNames);
- }
-
- hashId();
-}
-
-void MqttItem::triggerExposeLookup()
-{
- if(exposeLoaded_)
- return;
-
- std::shared_ptr workClient = client.lock();
- if(!workClient)
- return;
-
- // Reset expose loaded flag to allow re-detection
- exposeLoaded_ = false;
-
- // Subscribe to bridge/devices
- if(devicesSubscription)
- {
- disconnect(devicesSubscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onDevicesMessageReceived);
- workClient->unsubscribe(devicesSubscription);
- devicesSubscription = nullptr;
- }
-
- devicesSubscription = workClient->subscribe(workClient->getBaseTopic() + "/bridge/devices");
- connect(devicesSubscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onDevicesMessageReceived);
-}
-
-QString MqttItem::getTopic() const
-{
- return topic_;
-}
-
-QString MqttItem::getValueKey() const
-{
- return valueKey_;
-}
-
-QString MqttItem::getValueOn() const
-{
- return valueOn_;
-}
-
-QString MqttItem::getValueOff() const
-{
- return valueOff_;
-}
-
-int MqttItem::getValueMin() const
-{
- return valueMin_;
-}
-
-int MqttItem::getValueMax() const
-{
- return valueMax_;
-}
-
-int MqttItem::getValueStep() const
-{
- return valueStep_;
-}
-
-bool MqttItem::getExposeLoaded() const
-{
- return exposeLoaded_;
-}
-
-void MqttItem::store(QJsonObject& json)
-{
- Item::store(json);
- json["Type"] = "Mqtt";
- json["Topic"] = topic_;
- json["ValueKey"] = valueKey_;
- json["ValueOn"] = valueOn_;
- json["ValueOff"] = valueOff_;
- json["ValueMin"] = valueMin_;
- json["ValueMax"] = valueMax_;
- json["ValueStep"] = valueStep_;
-}
-
-void MqttItem::load(const QJsonObject& json, const bool preserve)
-{
- Item::load(json, preserve);
- topic_ = json["Topic"].toString();
- valueKey_ = json["ValueKey"].toString("state");
- valueOn_ = json["ValueOn"].toString("ON");
- valueOff_ = json["ValueOff"].toString("OFF");
- valueMin_ = json["ValueMin"].toInt(0);
- valueMax_ = json["ValueMax"].toInt(255);
- valueStep_ = json["ValueStep"].toInt(1);
- exposeLoaded_ = json["ExposeLoaded"].toBool(false);
- hashId();
- refreshSubscription();
-}
-
-void MqttItem::enactValue(uint8_t value)
-{
- std::shared_ptr workClient = client.lock();
- if(!workClient || topic_.isEmpty())
- return;
-
- QString fullTopic = workClient->getBaseTopic() + "/" + topic_ + "/set";
- QJsonObject payload;
-
- if(getValueType() == ITEM_VALUE_UINT)
- {
- payload[valueKey_] = static_cast(value);
- }
- else if(getValueType() == ITEM_VALUE_ENUM)
- {
- payload[valueKey_] = indexToValueName(value);
- }
- else
- {
- payload[valueKey_] = value ? valueOn_ : valueOff_;
- }
-
- QJsonDocument doc(payload);
- QByteArray data = doc.toJson(QJsonDocument::Compact);
-
- qDebug() << "MqttItem publishing to" << fullTopic << ":" << data;
- workClient->getClient()->publish(fullTopic, data);
-}
diff --git a/src/items/mqttitem.h b/src/items/mqttitem.h
deleted file mode 100644
index b0248a2..0000000
--- a/src/items/mqttitem.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef MQTTITEM_H
-#define MQTTITEM_H
-
-#include "item.h"
-#include "mqttclient.h"
-
-class QString;
-
-class MqttItem : public Item
-{
- Q_OBJECT
-Q_SIGNALS:
- void exposeLoaded();
-
-public:
- inline static std::weak_ptr client;
-
-private:
- QString topic_;
- QString valueKey_;
- QString valueOn_ = "ON";
- QString valueOff_ = "OFF";
- int valueMin_ = 0;
- int valueMax_ = 255;
- int valueStep_ = 1;
- bool exposeLoaded_ = false;
-
- MqttClient::Subscription* subscription = nullptr;
- MqttClient::Subscription* devicesSubscription = nullptr;
-
- void hashId();
- void refreshSubscription();
- void onMessageReceived(const QMqttMessage& message);
- void onClientStateChanged(QMqttClient::ClientState state);
- void onDevicesMessageReceived(const QMqttMessage& message);
- void loadExposeFromDevice(const QJsonObject& device);
-
-public:
- explicit MqttItem(QString name = "MqttItem",
- uint8_t value = 0,
- QObject *parent = nullptr);
- virtual ~MqttItem() override;
-
- void setTopic(const QString& topic);
- void setValueKey(const QString& valueKey);
- void setBaseTopic(const QString& baseTopic);
- void setValueOn(const QString& valueOn);
- void setValueOff(const QString& valueOff);
- void setValueMin(int min);
- void setValueMax(int max);
- void setValueStep(int step);
- void setValueType(item_value_type_t type);
-
- // Configure from Zigbee2MQTT expose info
- void setFromExpose(const QJsonObject& expose);
-
- // Trigger expose lookup from bridge/devices
- void triggerExposeLookup();
-
- QString getTopic() const;
- QString getValueKey() const;
- QString getValueOn() const;
- QString getValueOff() const;
- int getValueMin() const;
- int getValueMax() const;
- int getValueStep() const;
- bool getExposeLoaded() const;
-
- virtual void store(QJsonObject& json) override;
- virtual void load(const QJsonObject& json, const bool preserve = false) override;
-
-protected:
- virtual void enactValue(uint8_t value) override;
-};
-
-#endif // MQTTITEM_H
\ No newline at end of file
diff --git a/src/items/poweritem.cpp b/src/items/poweritem.cpp
index d37e233..aec7642 100644
--- a/src/items/poweritem.cpp
+++ b/src/items/poweritem.cpp
@@ -6,7 +6,7 @@
PowerItem::PowerItem(uint32_t itemIdIn, QString name, uint8_t value, QObject* parent):
Item(itemIdIn, name, value, parent)
{
- globalSensors.sensorGotState(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 0, "Shutdown Imminent", true), SENSOR_UPDATE_BACKEND);
+ stateChanged(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 0, "Shutdown Imminent", true));
value_ = true;
hidden_ = true;
type_ = ITEM_VALUE_NO_VALUE;
@@ -18,7 +18,7 @@ void PowerItem::enactValue(uint8_t value)
{
qDebug()<<"shutdown";
QTimer::singleShot(5000, this, &PowerItem::timeout);
- globalSensors.sensorGotState(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 1, "Shutdown Imminent", true), SENSOR_UPDATE_BACKEND);
+ stateChanged(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 1, "Shutdown Imminent", true));
}
}
diff --git a/src/items/poweritem.h b/src/items/poweritem.h
index 1d50e90..d6a610f 100644
--- a/src/items/poweritem.h
+++ b/src/items/poweritem.h
@@ -12,7 +12,8 @@ class PowerItem: public Item
private:
signals:
- void stateChanged(Sensor sensor, sensor_update_type_t type = SENSOR_UPDATE_BACKEND);
+
+ void stateChanged(Sensor sensor);
private slots:
void timeout();
diff --git a/src/main.cpp b/src/main.cpp
index f487ffd..e3a6e03 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,31 +6,25 @@
#include
#include
#include
-#include
#include "ui/mainwindow.h"
#include "items/itemstore.h"
#include "mainobject.h"
#include "programmode.h"
-void sigHandler(int s)
-{
- std::signal(s, SIG_DFL);
- QCoreApplication *app = QCoreApplication::instance();
- if(app)
- app->quit();
-}
-
int main(int argc, char *argv[])
{
+ QApplication a(argc, argv);
+
+ //pw_init(&argc, &argv);
+
+ //set info
QCoreApplication::setOrganizationName("UVOS");
QCoreApplication::setOrganizationDomain("uvos.xyz");
QCoreApplication::setApplicationName("SHinterface");
QCoreApplication::setApplicationVersion("0.6");
- QStringList args;
- for(int i = 0; i < argc; ++i)
- args<load(uiSettings);
-
QObject::connect(&mainObject.micro, SIGNAL(textRecived(QString)), w, SLOT(changeHeaderLableText(QString)));
QObject::connect(&mainObject.micro, SIGNAL(textRecived(QString)), w, SLOT(changeHeaderLableText(QString)));
QObject::connect(w, &MainWindow::sigSetRgb, &mainObject.micro, &Microcontroller::changeRgbColor);
QObject::connect(w, &MainWindow::sigSave, &mainObject, [&mainObject, settingsPath](){mainObject.storeToDisk(settingsPath);});
- QObject::connect(w, &MainWindow::createdItem, &globalItems, &ItemStore::addItem);
+ QObject::connect(w,
+ &MainWindow::createdItem,
+ &globalItems,
+ [](std::shared_ptr
- item) {
+ globalItems.addItem(item, ITEM_UPDATE_USER);
+ });
w->show();
}
-
- retVal = a->exec();
-
- if(programMode != PROGRAM_MODE_HEADLESS_PRIMARY)
- {
- QJsonObject uiSettingsJson;
- w->store(uiSettingsJson);
- MainObject::storeJsonObjectToDisk(uiSettingsPath, uiSettingsJson);
- }
+ retVal = a.exec();
delete w;
delete microDevice;
@@ -157,23 +132,15 @@ int main(int argc, char *argv[])
{
SecondaryMainObject mainObject(parser.value(hostOption), parser.value(portOption).toInt());
MainWindow w(&mainObject);
- QJsonObject uiSettings = MainObject::getJsonObjectFromDisk(uiSettingsPath);
- w.load(uiSettings);
-
- QObject::connect(&w, &MainWindow::createdItem, &globalItems, &ItemStore::addItem);
+ QObject::connect(&w, &MainWindow::createdItem, &globalItems, [](std::shared_ptr
- item) {
+ globalItems.addItem(item, ITEM_UPDATE_USER);
+ });
QObject::connect(&w, &MainWindow::sigSave, mainObject.tcpClient, &TcpClient::sendItems);
-
w.show();
- retVal = a->exec();
-
- QJsonObject uiSettingsJson;
- w.store(uiSettingsJson);
- MainObject::storeJsonObjectToDisk(uiSettingsPath, uiSettingsJson);
+ retVal = a.exec();
}
- delete a;
-
return retVal;
}
diff --git a/src/mainobject.cpp b/src/mainobject.cpp
index 95623fb..eed22d7 100644
--- a/src/mainobject.cpp
+++ b/src/mainobject.cpp
@@ -4,8 +4,6 @@
#include
#include
-#include "mqttclient.h"
-#include "items/mqttitem.h"
#include "items/itemstore.h"
MainObject::MainObject(QObject *parent) :
@@ -22,11 +20,6 @@ void MainObject::refresh()
globalItems.refresh();
}
-void MainObject::addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload)
-{
- // Default implementation does nothing - derived classes override
-}
-
QJsonObject MainObject::getJsonObjectFromDisk(const QString& filename, bool* error)
{
QFile file;
@@ -81,14 +74,9 @@ PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, const QString& sett
micro(microDevice),
tcpServer(new TcpServer(this)),
webServer(new WebSocketServer("shinterface", this)),
- mqttClient(new MqttClient),
sunSensorSource(49.824972, 8.702194),
fixedItems(µ)
{
- MqttItem::client = mqttClient;
-
- connect(tcpServer, &Server::sigRequestSave, this, [this](){storeToDisk(this->settingsPath);});
-
//connect sensors subsystem
connect(&globalSensors, &SensorStore::sensorChangedState, tcpServer, &TcpServer::sensorEvent);
connect(tcpServer, &TcpServer::gotSensor, &globalSensors, &SensorStore::sensorGotState);
@@ -96,8 +84,8 @@ PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, const QString& sett
connect(&sunSensorSource, &SunSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState);
connect(µ, &Microcontroller::gotSensorState, &globalSensors, &SensorStore::sensorGotState);
connect(&mqttSensorSource, &MqttSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState);
- connect(tcpServer, &TcpServer::sensorAdded, &mqttSensorSource, &MqttSensorSource::onSensorAdded);
- connect(webServer, &WebSocketServer::sensorAdded, &mqttSensorSource, &MqttSensorSource::onSensorAdded);
+
+ sunSensorSource.run();
globalItems.registerItemSource(&fixedItems);
globalItems.registerItemSource(tcpServer);
@@ -109,11 +97,8 @@ PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, const QString& sett
loadFromDisk(settingsPath);
- sunSensorSource.run();
-
QJsonObject mqttJson = settings["Mqtt"].toObject();
- mqttClient->start(mqttJson);
- mqttSensorSource.start(mqttClient, mqttJson);
+ mqttSensorSource.start(mqttJson);
tcpServer->launch(QHostAddress(host), port);
webServer->launch(QHostAddress(host), port+1);
@@ -129,9 +114,7 @@ PrimaryMainObject::~PrimaryMainObject()
void PrimaryMainObject::store(QJsonObject &json)
{
globalItems.store(json);
- globalSensors.store(json);
QJsonObject mqttJson = json["Mqtt"].toObject();
- mqttClient->store(mqttJson);
mqttSensorSource.store(mqttJson);
json["Mqtt"] = mqttJson;
}
@@ -140,7 +123,6 @@ void PrimaryMainObject::load(const QJsonObject& json)
{
settings = json;
itemLoader.updateJson(json);
- globalSensors.load(json);
globalItems.clear();
globalItems.refresh();
}
@@ -167,7 +149,6 @@ SecondaryMainObject::SecondaryMainObject(QString host, int port, QObject *parent
{
connect(tcpClient, &TcpClient::gotSensor, &globalSensors, &SensorStore::sensorGotState);
globalItems.registerItemSource(tcpClient);
- connect(&globalSensors, &SensorStore::sensorChangedState, tcpClient, &TcpClient::sensorEvent);
if(!tcpClient->launch(QHostAddress(host), port))
{
@@ -184,8 +165,3 @@ SecondaryMainObject::~SecondaryMainObject()
{
}
-void SecondaryMainObject::addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload)
-{
- tcpClient->addSensor(sensor, backend, payload);
-}
-
diff --git a/src/mainobject.h b/src/mainobject.h
index 405a7c3..48835dc 100644
--- a/src/mainobject.h
+++ b/src/mainobject.h
@@ -33,7 +33,6 @@ public:
public slots:
void refresh();
- virtual void addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload = {});
};
class PrimaryMainObject : public MainObject
@@ -47,7 +46,6 @@ public:
Microcontroller micro;
TcpServer* tcpServer;
WebSocketServer* webServer;
- std::shared_ptr mqttClient;
//sensors
SunSensorSource sunSensorSource;
@@ -75,7 +73,6 @@ public:
public:
explicit SecondaryMainObject(QString host, int port, QObject *parent = nullptr);
~SecondaryMainObject();
- void addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload = {}) override;
};
diff --git a/src/microcontroller.cpp b/src/microcontroller.cpp
index 2a766b5..0bf8690 100644
--- a/src/microcontroller.cpp
+++ b/src/microcontroller.cpp
@@ -157,31 +157,16 @@ void Microcontroller::processList(const QString& buffer)
else if(buffer.contains("EOL"))
{
listMode = false;
- std::vector requests;
- for(const std::shared_ptr
- & item : relayList)
- {
- ItemAddRequest request;
- request.changes.name = true;
- request.changes.value = true;
- request.payload = item;
- request.type = ITEM_UPDATE_BACKEND;
- requests.push_back(request);
- }
- gotItems(requests);
+ gotItems(relayList, ITEM_UPDATE_BACKEND);
relayList.clear();
}
- else
- {
- listMode = false;
- }
+ else listMode = false;
}
void Microcontroller::processRelayState(const QString& buffer)
{
ItemUpdateRequest update;
update.type = ITEM_UPDATE_BACKEND;
- update.changes.name = true;
- update.changes.value = true;
update.payload = static_cast(*processRelayLine(buffer));
updateItems({update});
}
@@ -190,7 +175,7 @@ void Microcontroller::processSensorState(const QString& buffer)
{
Sensor sensor = Sensor::sensorFromString(buffer);
if(sensor.type != Sensor::TYPE_DUMMY)
- gotSensorState(sensor, SENSOR_UPDATE_BACKEND);
+ gotSensorState(sensor);
}
diff --git a/src/microcontroller.h b/src/microcontroller.h
index fc5d805..c6d56bf 100644
--- a/src/microcontroller.h
+++ b/src/microcontroller.h
@@ -78,7 +78,7 @@ private slots:
signals:
void textRecived(const QString string);
- void gotSensorState(Sensor sensor, sensor_update_type_t type = SENSOR_UPDATE_BACKEND);
+ void gotSensorState(Sensor sensor);
};
#endif // MICROCONTROLLER_H
diff --git a/src/mqttclient.cpp b/src/mqttclient.cpp
deleted file mode 100644
index eb504a6..0000000
--- a/src/mqttclient.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-#include "mqttclient.h"
-
-MqttClient::MqttClient():
- client(new QMqttClient)
-{
-
-}
-
-void MqttClient::start(const QJsonObject& settings)
-{
- baseTopicName = settings["BaseTopic"].toString("zigbee2mqtt");
-
- QMqttClient* cl = client.get();
- connect(cl, &QMqttClient::stateChanged, this, &MqttClient::onClientStateChanged);
- connect(cl, &QMqttClient::errorChanged, this, &MqttClient::onClientError);
-
- client->setHostname(settings["Host"].toString("127.0.0.1"));
- client->setPort(settings["Port"].toInt(1883));
- client->setClientId(settings["ClientId"].toString("smartvos"));
- if(settings.contains("User"))
- client->setUsername(settings["User"].toString());
- if(settings.contains("Password"))
- client->setPassword(settings["Password"].toString());
- client->setProtocolVersion(QMqttClient::MQTT_3_1);
-
- client->connectToHost();
-}
-
-void MqttClient::onClientError(QMqttClient::ClientError error)
-{
- qWarning()<<"MQTT Client error:"<hostname()<port();
- else if (state == QMqttClient::ClientState::Disconnected)
- qWarning()<<"Lost connection to MQTT broker";
- else if(state == QMqttClient::ClientState::Connecting)
- qInfo()<<"Connecting to MQTT broker at "<hostname()<port();
-}
-
-void MqttClient::store(QJsonObject& json)
-{
- json["Host"] = client->hostname();
- json["Port"] = client->port();
- json["BaseTopic"] = baseTopicName;
- if(client->username() != "")
- json["User"] = client->username();
- if(client->password() != "")
- json["Password"] = client->password();
-}
-
-std::shared_ptr MqttClient::getClient()
-{
- return client;
-}
-
-MqttClient::Subscription* MqttClient::subscribe(QString topic)
-{
- if(subscriptions.contains(topic))
- {
- MqttClient::Subscription* sub = subscriptions[topic];
- ++sub->ref;
- return sub;
- }
- else
- {
- qDebug()<<"MqttClient: subscibeing to"<subscription = client->subscribe(topic);
- sub->ref = 1;
- subscriptions.insert({topic, sub});
- return sub;
- }
-}
-
-void MqttClient::unsubscribe(MqttClient::Subscription* subscription)
-{
- QString topic = subscription->subscription->topic().filter();
- unsubscribe(topic);
-}
-
-void MqttClient::unsubscribe(QString topic)
-{
- MqttClient::Subscription* sub = subscriptions[topic];
- if(!sub)
- {
- qWarning()<<"MqttClient: Trying to unsubscribe from unkown topic:"<ref > 0)
- return;
-
- qDebug()<<"MqttClient: unsubscibeing"<subscription->topic().filter();
- client->unsubscribe(sub->subscription->topic());
- subscriptions.erase(topic);
- delete sub;
-}
-
-QString MqttClient::getBaseTopic()
-{
- return baseTopicName;
-}
-
-MqttClient::~MqttClient()
-{
- for(const std::pair sub : subscriptions)
- {
- qWarning()<unsubscribe(sub.second->subscription->topic());
- }
-}
\ No newline at end of file
diff --git a/src/mqttclient.h b/src/mqttclient.h
deleted file mode 100644
index 1199855..0000000
--- a/src/mqttclient.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef MQTTCLIENT_H
-#define MQTTCLIENT_H
-
-#include
-#include
-#include
-#include
@@ -69,26 +64,13 @@
-
- -
-
-
- Qt::Orientation::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
- Qt::Orientation::Horizontal
+ Qt::Horizontal
- QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
diff --git a/src/ui/itemscrollbox.cpp b/src/ui/itemscrollbox.cpp
index d2b2f31..170a557 100644
--- a/src/ui/itemscrollbox.cpp
+++ b/src/ui/itemscrollbox.cpp
@@ -1,17 +1,15 @@
#include "itemscrollbox.h"
#include "ui_relayscrollbox.h"
-#include
-#include
-#include
+#include "../items/auxitem.h"
+#include "../items/messageitem.h"
ItemScrollBox::ItemScrollBox(QWidget *parent) :
QWidget(parent),
ui(new Ui::RelayScrollBox)
{
ui->setupUi(this);
-
- ensureTabExists("All");
- ui->tabWidget->setCurrentIndex(0);
+ QScroller::grabGesture(ui->scrollArea, QScroller::TouchGesture);
+ QScroller::grabGesture(ui->scrollArea, QScroller::LeftMouseButtonGesture);
}
ItemScrollBox::~ItemScrollBox()
@@ -25,191 +23,24 @@ void ItemScrollBox::addItem(std::weak_ptr- item)
{
if(workItem->isHidden())
return;
-
- // Add to "All" tab
- widgets_["All"].push_back(new ItemWidget(item, false));
- QWidget* allScrollContent = tabs_["All"].content;
- QLayout* layout = allScrollContent->layout();
- layout->removeItem(tabs_["All"].spacer);
- layout->addWidget(widgets_["All"].back());
- layout->addItem(tabs_["All"].spacer);
- connect(widgets_["All"].back(), &ItemWidget::deleteRequest, this, &ItemScrollBox::deleteRequest);
- connect(widgets_["All"].back(), &ItemWidget::deleteRequest, this, &ItemScrollBox::removeItem);
-
- addItemToTabs(item);
- }
-}
-
-void ItemScrollBox::addItemToTabs(std::weak_ptr
- item)
-{
- if(auto workItem = item.lock())
- {
- if(workItem->isHidden())
- return;
-
- QString groupName = workItem->getGroupName();
- if(groupName.isEmpty() || groupName != "All")
- {
- ensureTabExists(groupName);
- ItemWidget* groupWidget = new ItemWidget(item, true);
- widgets_[groupName].push_back(groupWidget);
-
- QWidget* scrollContent = tabs_[groupName].content;
- QLayout* groupLayout = scrollContent->layout();
- groupLayout->removeItem(tabs_[groupName].spacer);
- groupLayout->addWidget(groupWidget);
- groupLayout->addItem(tabs_[groupName].spacer);
-
- connect(groupWidget, &ItemWidget::deleteRequest, this, &ItemScrollBox::deleteRequest);
- connect(groupWidget, &ItemWidget::deleteRequest, this, &ItemScrollBox::removeItem);
-
- connect(widgets_[groupName].back(), &ItemWidget::deleteRequest, this, &ItemScrollBox::deleteRequest);
- connect(widgets_[groupName].back(), &ItemWidget::deleteRequest, this, &ItemScrollBox::removeItem);
- }
+ 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);
}
}
void ItemScrollBox::removeItem(const ItemData& item)
{
- QString key = "All";
- std::vector& widgets = widgets_[key];
- for(unsigned i = 0; i < widgets.size(); i++)
+ for(unsigned i = 0; i < widgets_.size(); i++)
{
- if(widgets[i]->controles(item))
+ if(widgets_[i]->controles(item))
{
- QWidget* tabContent = tabs_[key].content;
- if(tabContent)
- {
- QLayout* layout = tabContent->layout();
- if(layout)
- layout->removeWidget(widgets[i]);
- }
- delete widgets[i];
- widgets.erase(widgets.begin()+i);
- break;
- }
- }
-
- removeItemFromTabs(item);
- cleanupEmptyTabs();
-}
-
-void ItemScrollBox::removeItemFromTabs(const ItemData& item)
-{
- for(const QString& key : widgets_.keys())
- {
- if(key == "All")
- continue;
- std::vector& widgets = widgets_[key];
- for(unsigned i = 0; i < widgets.size(); i++)
- {
- if(widgets[i]->controles(item))
- {
- QWidget* tabContent = tabs_[key].content;
- if(tabContent)
- {
- QLayout* layout = tabContent->layout();
- if(layout)
- layout->removeWidget(widgets[i]);
- }
- delete widgets[i];
- widgets.erase(widgets.begin()+i);
- break;
- }
- }
- }
-
- cleanupEmptyTabs();
-}
-
-
-void ItemScrollBox::onItemUpdate(const ItemUpdateRequest& update)
-{
- if(!update.changes.groupName)
- return;
-
- for(ItemWidget* widget : widgets_["All"])
- {
- if(widget->controles(update.payload))
- {
- qDebug()<<"ItemUpdate with group change for item"< item = widget->getItem();
- removeItemFromTabs(update.payload);
- addItemToTabs(item);
+ ui->relayWidgetVbox->removeWidget(widgets_[i]);
+ delete widgets_[i];
+ widgets_.erase(widgets_.begin()+i);
}
}
}
-void ItemScrollBox::ensureTabExists(const QString& groupName)
-{
- if(!tabs_.contains(groupName))
- {
- Tab tab;
- tab.scroller = new QScrollArea(ui->tabWidget);
- tab.scroller->setWidgetResizable(true);
- tab.scroller->setFrameShape(QFrame::NoFrame);
- tab.scroller->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- QScroller::grabGesture(tab.scroller->viewport(), QScroller::LeftMouseButtonGesture);
- tab.content = new QWidget(tab.scroller);
- QVBoxLayout* scrollLayout = new QVBoxLayout(tab.content);
- scrollLayout->setContentsMargins(0, 0, 0, 0);
- tab.content->setLayout(scrollLayout);
- tab.content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
- tab.scroller->setWidget(tab.content);
-
- tab.spacer = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
- scrollLayout->addSpacerItem(tab.spacer);
-
- ui->tabWidget->addTab(tab.scroller, groupName);
- tabs_[groupName] = tab;
-
- if(groupName == pendingSelectedGroup_)
- {
- ui->tabWidget->setCurrentWidget(tab.scroller);
- pendingSelectedGroup_.clear();
- }
- }
-}
-
-void ItemScrollBox::cleanupEmptyTabs()
-{
- for(auto it = tabs_.begin(); it != tabs_.end(); ++it)
- {
- QString groupName = it.key();
- if(groupName == "All")
- continue;
-
- qDebug()<<__func__<layout()->count();
-
- if(it.value().content->layout()->count() <= 1)
- {
- int index = ui->tabWidget->indexOf(tabs_[groupName].scroller);
- if(index >= 0)
- ui->tabWidget->removeTab(index);
- Tab tab = tabs_.take(groupName);
- delete tab.content;
- delete tab.scroller;
- cleanupEmptyTabs();
- break;
- }
- }
-}
-
-void ItemScrollBox::store(QJsonObject& json) const
-{
- QJsonObject itemScrollBoxJson;
- int currentIndex = ui->tabWidget->currentIndex();
- if(currentIndex >= 0)
- {
- QString selectedGroup = ui->tabWidget->tabText(currentIndex);
- itemScrollBoxJson["SelectedGroup"] = selectedGroup;
- }
- json["ItemScrollBox"] = itemScrollBoxJson;
-}
-
-void ItemScrollBox::load(const QJsonObject& json)
-{
- QJsonObject itemScrollBoxJson = json["ItemScrollBox"].toObject();
- pendingSelectedGroup_ = itemScrollBoxJson["SelectedGroup"].toString();
-}
diff --git a/src/ui/itemscrollbox.h b/src/ui/itemscrollbox.h
index 3dfef8f..54d5fe8 100644
--- a/src/ui/itemscrollbox.h
+++ b/src/ui/itemscrollbox.h
@@ -4,10 +4,9 @@
#include
#include
#include
-#include
-#include
-#include
+#include
#include "itemwidget.h"
+#include "../items/relay.h"
#include "../items/item.h"
#include "../items/itemstore.h"
@@ -21,17 +20,7 @@ class ItemScrollBox : public QWidget
{
Q_OBJECT
private:
- struct Tab
- {
- QScrollArea* scroller;
- QWidget* content;
- QSpacerItem* spacer;
- };
-
- QMap tabs_;
- QMap> widgets_;
- Ui::RelayScrollBox *ui;
- QString pendingSelectedGroup_;
+ std::vector< ItemWidget* > widgets_;
signals:
void deleteRequest(const ItemData& item);
@@ -43,22 +32,13 @@ public:
void setItemStore(ItemStore* itemStore);
- void store(QJsonObject& json) const;
- void load(const QJsonObject& json);
-
public slots:
void addItem(std::weak_ptr
- item);
void removeItem(const ItemData& item);
- void onItemUpdate(const ItemUpdateRequest& update);
private:
- void ensureTabExists(const QString& groupName);
- void cleanupEmptyTabs();
-
-private:
- void addItemToTabs(std::weak_ptr
- item);
- void removeItemFromTabs(const ItemData& item);
+ Ui::RelayScrollBox *ui;
};
#endif // RELAYSCROLLBOX_H
diff --git a/src/ui/itemsettingsdialog.cpp b/src/ui/itemsettingsdialog.cpp
index 5ef701e..08417d3 100644
--- a/src/ui/itemsettingsdialog.cpp
+++ b/src/ui/itemsettingsdialog.cpp
@@ -1,22 +1,19 @@
#include "itemsettingsdialog.h"
#include "ui_itemsettingsdialog.h"
-#include "../items/itemstore.h"
#include "actorsettingsdialog.h"
#include "../actors/alarmtime.h"
#include "../actors/sensoractor.h"
#include "../actors/timeractor.h"
#include "../actors/regulator.h"
+#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/mqttitemsettingswidget.h"
-#include "../items/mqttitem.h"
-
#include
-ItemSettingsDialog::ItemSettingsDialog(std::shared_ptr
- item, bool noGroup, QWidget *parent) :
+ItemSettingsDialog::ItemSettingsDialog(std::shared_ptr
- item, QWidget *parent) :
QDialog(parent),
item_(item),
ui(new Ui::ItemSettingsDialog)
@@ -25,17 +22,9 @@ ItemSettingsDialog::ItemSettingsDialog(std::shared_ptr
- item, bool noGroup,
setModal(false);
- if(noGroup)
- ui->comboBox_Group->setEnabled(false);
-
ui->label_name->setText(item_->getName());
ui->checkBox_Override->setChecked(item_->getOverride());
-
- // Setup group combobox with editable mode for creating new groups
- ui->comboBox_Group->setEditable(true);
- ui->comboBox_Group->addItem("All");
- ui->comboBox_Group->addItems(getExistingGroups());
- ui->comboBox_Group->setCurrentText(item_->getGroupName());
+
if(std::shared_ptr relay = std::dynamic_pointer_cast(item_))
{
@@ -49,10 +38,6 @@ ItemSettingsDialog::ItemSettingsDialog(std::shared_ptr
- item, bool noGroup,
{
itemSpecificWidget_ = new SystemItemSettingsWidget(sysItem);
}
- else if(std::shared_ptr mqttItem = std::dynamic_pointer_cast(item_))
- {
- itemSpecificWidget_ = new MqttItemSettingsWidget(mqttItem);
- }
if(itemSpecificWidget_)
{
@@ -63,7 +48,6 @@ ItemSettingsDialog::ItemSettingsDialog(std::shared_ptr
- item, bool noGroup,
connect(ui->pushButton_remove, &QPushButton::clicked, this, &ItemSettingsDialog::removeActor);
connect(ui->pushButton_edit, &QPushButton::clicked, this, &ItemSettingsDialog::editActor);
connect(ui->checkBox_Override, &QPushButton::clicked, this, &ItemSettingsDialog::changeOverride);
- connect(ui->comboBox_Group, &QComboBox::currentTextChanged, this, &ItemSettingsDialog::changeGroup);
ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("Actor"));
@@ -77,29 +61,13 @@ ItemSettingsDialog::ItemSettingsDialog(std::shared_ptr
- item, bool noGroup,
ItemSettingsDialog::~ItemSettingsDialog()
{
- if(itemSpecificWidget_)
- delete itemSpecificWidget_;
+ if(itemSpecificWidget_) delete itemSpecificWidget_;
delete ui;
}
-void ItemSettingsDialog::changeGroup()
-{
- QString newGroup = ui->comboBox_Group->currentText();
- if(newGroup != item_->getGroupName())
- {
- ItemUpdateRequest update = item_->createValueUpdateRequest(ITEM_UPDATE_USER);
- update.payload.setGroupName(newGroup);
- update.changes.groupName = true;
- item_->requestUpdate(update);
- }
-}
-
void ItemSettingsDialog::changeOverride()
{
- ItemUpdateRequest update = item_->createValueUpdateRequest(ITEM_UPDATE_USER);
- update.payload.setOverride(ui->checkBox_Override->isChecked());
- update.changes.override = true;
- item_->requestUpdate(update);
+ item_->setOverride(ui->checkBox_Override->isChecked());
}
void ItemSettingsDialog::loadActorList()
@@ -152,12 +120,18 @@ void ItemSettingsDialog::addActor()
dialog = new ActorSettingsDialog(polynomalActor, this);
}
-
+ else if(ui->comboBox->currentText() == "Multi Factor")
+ {
+ std::shared_ptr polynomalActor = std::shared_ptr(new MultiFactorActor);
+ actor = polynomalActor;
+ dialog = new ActorSettingsDialog(polynomalActor, this);
+ }
if(dialog != nullptr)
{
dialog->setParent(this);
+ dialog->show();
if(dialog->exec() == QDialog::Accepted)
{
item_->addActor(actor);
@@ -188,22 +162,19 @@ void ItemSettingsDialog::editActor()
std::shared_ptr sensorActor = std::dynamic_pointer_cast(actor);
std::shared_ptr timerActor = std::dynamic_pointer_cast(actor);
std::shared_ptr polynomalActor = std::dynamic_pointer_cast(actor);
+ std::shared_ptr factorActor = std::dynamic_pointer_cast(actor);
ActorSettingsDialog* dialog;
- if(alarmTime)
- dialog = new ActorSettingsDialog(alarmTime, this);
- else if(regulator)
- dialog = new ActorSettingsDialog(regulator, this);
- else if(sensorActor)
- dialog = new ActorSettingsDialog(sensorActor, this);
- else if(timerActor)
- dialog = new ActorSettingsDialog(timerActor, this);
- else if(polynomalActor)
- dialog = new ActorSettingsDialog(polynomalActor, this);
- else
- dialog = new ActorSettingsDialog(actor, this);
-
+ if(alarmTime) dialog = new ActorSettingsDialog(alarmTime, this);
+ else if(regulator) dialog = new ActorSettingsDialog(regulator, this);
+ else if(sensorActor) dialog = new ActorSettingsDialog(sensorActor, this);
+ else if(timerActor) dialog = new ActorSettingsDialog(timerActor, this);
+ else if(polynomalActor) dialog = new ActorSettingsDialog(polynomalActor, this);
+ else if(factorActor) dialog = new ActorSettingsDialog(factorActor, this);
+ else dialog = new ActorSettingsDialog(actor, this);
+ dialog->setParent(this);
+ dialog->show();
dialog->exec();
for(int i = 0; i < ui->tableWidget->rowCount() && i < static_cast(item_->getActors().size()); ++i)
@@ -212,19 +183,5 @@ void ItemSettingsDialog::editActor()
ui->tableWidget->item(i, 1)->setText(item_->getActors()[i]->actionName());
ui->tableWidget->item(i, 2)->setText(item_->getActors()[i]->isActive() ? "Y" : "N");
}
- delete dialog;
}
}
-
-QStringList ItemSettingsDialog::getExistingGroups()
-{
- QSet uniqueGroups;
- for(const auto& item : *globalItems.getItems())
- {
- if(!item->getGroupName().isEmpty() && item->getGroupName() != "All")
- {
- uniqueGroups.insert(item->getGroupName());
- }
- }
- return uniqueGroups.values();
-}
diff --git a/src/ui/itemsettingsdialog.h b/src/ui/itemsettingsdialog.h
index 606261c..dc2a5af 100644
--- a/src/ui/itemsettingsdialog.h
+++ b/src/ui/itemsettingsdialog.h
@@ -19,10 +19,9 @@ class ItemSettingsDialog : public QDialog
private:
void loadActorList();
- QStringList getExistingGroups();
public:
- explicit ItemSettingsDialog(std::shared_ptr
- item, bool noGroup = false, QWidget *parent = nullptr);
+ explicit ItemSettingsDialog(std::shared_ptr
- item, QWidget *parent = nullptr);
~ItemSettingsDialog();
private slots:
@@ -31,7 +30,6 @@ private slots:
void addActor();
void editActor();
void changeOverride();
- void changeGroup();
private:
Ui::ItemSettingsDialog *ui;
diff --git a/src/ui/itemsettingsdialog.ui b/src/ui/itemsettingsdialog.ui
index 5820fce..7faeede 100644
--- a/src/ui/itemsettingsdialog.ui
+++ b/src/ui/itemsettingsdialog.ui
@@ -14,14 +14,14 @@
Item Settings
-
+
:/images/UVOSicon.bmp:/images/UVOSicon.bmp
-
- QFormLayout::FieldGrowthPolicy::AllNonFixedFieldsGrow
+ QFormLayout::AllNonFixedFieldsGrow
0
@@ -35,7 +35,7 @@
Name:
- Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -48,13 +48,13 @@
- Qt::LayoutDirection::LeftToRight
+ Qt::LeftToRight
TextLabel
- Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -63,20 +63,6 @@
-
- -
-
-
-
-
-
- Group:
-
-
-
- -
-
-
-
-
-
@@ -87,19 +73,19 @@
-
- QFrame::Shape::StyledPanel
+ QFrame::StyledPanel
- Qt::ScrollBarPolicy::ScrollBarAsNeeded
+ Qt::ScrollBarAsNeeded
- Qt::ScrollBarPolicy::ScrollBarAlwaysOff
+ Qt::ScrollBarAlwaysOff
false
- QAbstractItemView::EditTrigger::NoEditTriggers
+ QAbstractItemView::NoEditTriggers
false
@@ -111,13 +97,13 @@
false
- QAbstractItemView::SelectionBehavior::SelectRows
+ QAbstractItemView::SelectRows
false
- Qt::PenStyle::SolidLine
+ Qt::SolidLine
false
@@ -214,6 +200,11 @@
Timer
+ -
+
+ Multi Factor
+
+
-
@@ -234,16 +225,18 @@
-
- Qt::Orientation::Horizontal
+ Qt::Horizontal
- QDialogButtonBox::StandardButton::Ok
+ QDialogButtonBox::Ok
-
+
+
+
buttonBox
diff --git a/src/ui/itemsettingswidgets/mqttitemsettingswidget.cpp b/src/ui/itemsettingswidgets/mqttitemsettingswidget.cpp
deleted file mode 100644
index f566ad9..0000000
--- a/src/ui/itemsettingswidgets/mqttitemsettingswidget.cpp
+++ /dev/null
@@ -1,272 +0,0 @@
-#include "mqttitemsettingswidget.h"
-#include "ui_mqttitemsettingswidget.h"
-
-#include
-#include
-
-MqttItemSettingsWidget::MqttItemSettingsWidget(std::weak_ptr item, QWidget *parent) :
- QWidget(parent),
- item_(item),
- ui(new Ui::MqttItemSettingsWidget)
-{
- ui->setupUi(this);
-
- if(auto workingItem = item_.lock())
- {
- suppressUpdates_ = true;
- ui->lineEdit_topic->setText(workingItem->getTopic());
- ui->lineEdit_valueKey->setText(workingItem->getValueKey());
- ui->lineEdit_valueOn->setText(workingItem->getValueOn());
- ui->lineEdit_valueOff->setText(workingItem->getValueOff());
- ui->spinBox_min->setValue(workingItem->getValueMin());
- ui->spinBox_max->setValue(workingItem->getValueMax());
- ui->spinBox_step->setValue(workingItem->getValueStep());
-
- // Set value type combo
- switch(workingItem->getValueType())
- {
- case ITEM_VALUE_UINT:
- ui->comboBox_valueType->setCurrentIndex(1);
- break;
- case ITEM_VALUE_ENUM:
- ui->comboBox_valueType->setCurrentIndex(2);
- break;
- default:
- ui->comboBox_valueType->setCurrentIndex(0);
- break;
- }
-
- updateValueNamesFromItem();
- suppressUpdates_ = false;
- updateVisibility();
-
- // Connect expose loaded signal
- connect(workingItem.get(), &MqttItem::exposeLoaded, this, [this]() {
- if(auto item = item_.lock())
- {
- suppressUpdates_ = true;
- ui->label_status->setText("Detected!");
-
- // Update value type
- switch(item->getValueType())
- {
- case ITEM_VALUE_UINT:
- ui->comboBox_valueType->setCurrentIndex(1);
- break;
- case ITEM_VALUE_ENUM:
- ui->comboBox_valueType->setCurrentIndex(2);
- break;
- default:
- ui->comboBox_valueType->setCurrentIndex(0);
- break;
- }
-
- // Update limits
- ui->spinBox_min->setValue(item->getValueMin());
- ui->spinBox_max->setValue(item->getValueMax());
- ui->spinBox_step->setValue(item->getValueStep());
-
- // Update value on/off
- ui->lineEdit_valueOn->setText(item->getValueOn());
- ui->lineEdit_valueOff->setText(item->getValueOff());
-
- // Update value names
- updateValueNamesFromItem();
- suppressUpdates_ = false;
- updateVisibility();
- }
- });
- }
-
- // Connect signals
- connect(ui->lineEdit_topic, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setTopic);
- connect(ui->lineEdit_valueKey, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setValueKey);
- connect(ui->lineEdit_valueOn, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setValueOn);
- connect(ui->lineEdit_valueOff, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setValueOff);
- connect(ui->comboBox_valueType, QOverload::of(&QComboBox::currentIndexChanged), this, &MqttItemSettingsWidget::setValueType);
- connect(ui->spinBox_min, &QSpinBox::valueChanged, this, &MqttItemSettingsWidget::setValueMin);
- connect(ui->spinBox_max, &QSpinBox::valueChanged, this, &MqttItemSettingsWidget::setValueMax);
- connect(ui->spinBox_step, &QSpinBox::valueChanged, this, &MqttItemSettingsWidget::setValueStep);
- connect(ui->pushButton_autoDetect, &QPushButton::clicked, this, &MqttItemSettingsWidget::onAutoDetectClicked);
- connect(ui->pushButton_addValueName, &QPushButton::clicked, this, &MqttItemSettingsWidget::onAddValueName);
- connect(ui->pushButton_removeValueName, &QPushButton::clicked, this, &MqttItemSettingsWidget::onRemoveValueName);
- connect(ui->listWidget_valueNames, &QListWidget::itemChanged, this, &MqttItemSettingsWidget::onValueNamesChanged);
-}
-
-void MqttItemSettingsWidget::setTopic(const QString& topic)
-{
- if(suppressUpdates_)
- return;
- if(auto workingItem = item_.lock())
- {
- workingItem->setTopic(topic);
- }
-}
-
-void MqttItemSettingsWidget::setValueKey(const QString& valueKey)
-{
- if(suppressUpdates_)
- return;
- if(auto workingItem = item_.lock())
- {
- workingItem->setValueKey(valueKey);
- }
-}
-
-void MqttItemSettingsWidget::setValueOn(const QString& valueOn)
-{
- if(suppressUpdates_)
- return;
- if(auto workingItem = item_.lock())
- {
- workingItem->setValueOn(valueOn);
- }
-}
-
-void MqttItemSettingsWidget::setValueOff(const QString& valueOff)
-{
- if(suppressUpdates_)
- return;
- if(auto workingItem = item_.lock())
- {
- workingItem->setValueOff(valueOff);
- }
-}
-
-void MqttItemSettingsWidget::setValueType(int index)
-{
- if(suppressUpdates_)
- return;
- if(auto workingItem = item_.lock())
- {
- item_value_type_t type;
- switch(index)
- {
- case 1: type = ITEM_VALUE_UINT; break;
- case 2: type = ITEM_VALUE_ENUM; break;
- default: type = ITEM_VALUE_BOOL; break;
- }
- workingItem->setValueType(type);
- updateVisibility();
- }
-}
-
-void MqttItemSettingsWidget::setValueMin(int min)
-{
- if(suppressUpdates_)
- return;
- if(auto workingItem = item_.lock())
- {
- workingItem->setValueMin(min);
- }
-}
-
-void MqttItemSettingsWidget::setValueMax(int max)
-{
- if(suppressUpdates_)
- return;
- if(auto workingItem = item_.lock())
- {
- workingItem->setValueMax(max);
- }
-}
-
-void MqttItemSettingsWidget::setValueStep(int step)
-{
- if(suppressUpdates_)
- return;
- if(auto workingItem = item_.lock())
- {
- workingItem->setValueStep(step);
- }
-}
-
-void MqttItemSettingsWidget::onAutoDetectClicked()
-{
- if(auto workingItem = item_.lock())
- {
- ui->label_status->setText("Detecting...");
- workingItem->triggerExposeLookup();
- }
-}
-
-void MqttItemSettingsWidget::onAddValueName()
-{
- bool ok;
- QString name = QInputDialog::getText(this, "Add Value Name", "Enter value name:", QLineEdit::Normal, "", &ok);
- if(ok && !name.isEmpty())
- {
- ui->listWidget_valueNames->addItem(name);
- syncValueNamesToItem();
- }
-}
-
-void MqttItemSettingsWidget::onRemoveValueName()
-{
- delete ui->listWidget_valueNames->currentItem();
- syncValueNamesToItem();
-}
-
-void MqttItemSettingsWidget::onValueNamesChanged()
-{
- if(suppressUpdates_)
- return;
- syncValueNamesToItem();
-}
-
-void MqttItemSettingsWidget::syncValueNamesToItem()
-{
- if(suppressUpdates_)
- return;
- if(auto workingItem = item_.lock())
- {
- std::vector names;
- for(int i = 0; i < ui->listWidget_valueNames->count(); ++i)
- {
- names.push_back(ui->listWidget_valueNames->item(i)->text());
- }
- workingItem->setValueNames(names);
- }
-}
-
-void MqttItemSettingsWidget::updateVisibility()
-{
- int typeIndex = ui->comboBox_valueType->currentIndex();
-
- // Bool controls
- ui->label_valueOn->setVisible(typeIndex == 0);
- ui->lineEdit_valueOn->setVisible(typeIndex == 0);
- ui->label_valueOff->setVisible(typeIndex == 0);
- ui->lineEdit_valueOff->setVisible(typeIndex == 0);
-
- // UInt controls
- ui->label_min->setVisible(typeIndex == 1);
- ui->spinBox_min->setVisible(typeIndex == 1);
- ui->label_max->setVisible(typeIndex == 1);
- ui->spinBox_max->setVisible(typeIndex == 1);
- ui->label_step->setVisible(typeIndex == 1);
- ui->spinBox_step->setVisible(typeIndex == 1);
-
- // Enum controls
- ui->label_valueNames->setVisible(typeIndex == 2);
- ui->listWidget_valueNames->setVisible(typeIndex == 2);
- ui->pushButton_addValueName->setVisible(typeIndex == 2);
- ui->pushButton_removeValueName->setVisible(typeIndex == 2);
-}
-
-void MqttItemSettingsWidget::updateValueNamesFromItem()
-{
- if(auto workingItem = item_.lock())
- {
- ui->listWidget_valueNames->clear();
- for(const QString& name : workingItem->getValueNames())
- {
- ui->listWidget_valueNames->addItem(name);
- }
- }
-}
-
-MqttItemSettingsWidget::~MqttItemSettingsWidget()
-{
- delete ui;
-}
\ No newline at end of file
diff --git a/src/ui/itemsettingswidgets/mqttitemsettingswidget.h b/src/ui/itemsettingswidgets/mqttitemsettingswidget.h
deleted file mode 100644
index 4ad97ac..0000000
--- a/src/ui/itemsettingswidgets/mqttitemsettingswidget.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef MQTTITEMSETTINGSWIDGET_H
-#define MQTTITEMSETTINGSWIDGET_H
-
-#include
-#include
-#include "../../items/mqttitem.h"
-
-namespace Ui
-{
-class MqttItemSettingsWidget;
-}
-
-class MqttItemSettingsWidget : public QWidget
-{
- Q_OBJECT
- std::weak_ptr item_;
- bool suppressUpdates_ = false;
-
-private slots:
- void setTopic(const QString& topic);
- void setValueKey(const QString& valueKey);
- void setValueOn(const QString& valueOn);
- void setValueOff(const QString& valueOff);
- void setValueType(int index);
- void setValueMin(int min);
- void setValueMax(int max);
- void setValueStep(int step);
- void onAutoDetectClicked();
- void onAddValueName();
- void onRemoveValueName();
- void onValueNamesChanged();
-
-public:
- explicit MqttItemSettingsWidget(std::weak_ptr item, QWidget *parent = nullptr);
- ~MqttItemSettingsWidget();
-
-private:
- Ui::MqttItemSettingsWidget *ui;
- void updateVisibility();
- void updateValueNamesFromItem();
- void syncValueNamesToItem();
-};
-
-#endif // MQTTITEMSETTINGSWIDGET_H
\ No newline at end of file
diff --git a/src/ui/itemsettingswidgets/mqttitemsettingswidget.ui b/src/ui/itemsettingswidgets/mqttitemsettingswidget.ui
deleted file mode 100644
index ba0e954..0000000
--- a/src/ui/itemsettingswidgets/mqttitemsettingswidget.ui
+++ /dev/null
@@ -1,281 +0,0 @@
-
-
- MqttItemSettingsWidget
-
-
-
- 0
- 0
- 450
- 400
-
-
-
- Form
-
-
-
- -
-
-
- 0
-
-
-
-
-
- Topic:
-
-
-
- -
-
-
- e.g., 0xa4c138ef510950e3
-
-
-
-
-
-
- -
-
-
- 0
-
-
-
-
-
- Value Key:
-
-
-
- -
-
-
- state
-
-
- e.g., state, system_mode, brightness
-
-
-
-
-
-
- -
-
-
-
-
-
- Auto-detect from bridge/devices
-
-
-
- -
-
-
-
-
-
-
-
-
-
- -
-
-
- 0
-
-
-
-
-
- Value Type:
-
-
-
- -
-
-
-
-
- Bool
-
-
- -
-
- Unsigned Int
-
-
- -
-
- Enum
-
-
-
-
-
-
-
- -
-
-
- 0
-
-
-
-
-
- Value On:
-
-
-
- -
-
-
- ON
-
-
-
- -
-
-
- Value Off:
-
-
-
- -
-
-
- OFF
-
-
-
-
-
-
- -
-
-
- 0
-
-
-
-
-
- Min:
-
-
-
- -
-
-
- -999999
-
-
- 999999
-
-
- 0
-
-
-
- -
-
-
- Max:
-
-
-
- -
-
-
- -999999
-
-
- 999999
-
-
- 255
-
-
-
- -
-
-
- Step:
-
-
-
- -
-
-
- 1
-
-
- 999999
-
-
- 1
-
-
-
-
-
-
- -
-
-
- 0
-
-
-
-
-
- Value Names:
-
-
-
- -
-
-
-
- 0
- 80
-
-
-
-
- -
-
-
-
-
-
- +
-
-
-
- -
-
-
- -
-
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/ui/itemwidget.cpp b/src/ui/itemwidget.cpp
index 336ffb2..c91c5e8 100644
--- a/src/ui/itemwidget.cpp
+++ b/src/ui/itemwidget.cpp
@@ -2,15 +2,12 @@
#include "ui_itemwidget.h"
#include
-#include
#include
#include
-#include "itemsettingsdialog.h"
-ItemWidget::ItemWidget(std::weak_ptr- item, bool noGroupEdit, QWidget *parent) :
+ItemWidget::ItemWidget(std::weak_ptr
- item, QWidget *parent) :
QWidget(parent),
item_(item),
- noGroupEdit_(noGroupEdit),
ui(new Ui::ItemWidget)
{
ui->setupUi(this);
@@ -21,28 +18,15 @@ ItemWidget::ItemWidget(std::weak_ptr
- item, bool noGroupEdit, QWidget *pare
{
ui->horizontalSpacer->changeSize(0,0);
ui->checkBox->hide();
- ui->comboBox->hide();
}
else if(workingItem->getValueType() == ITEM_VALUE_NO_VALUE)
{
ui->checkBox->hide();
ui->slider->hide();
- ui->comboBox->hide();
- }
- else if(workingItem->getValueType() == ITEM_VALUE_ENUM)
- {
- ui->slider->hide();
- ui->checkBox->hide();
- QStringList list;
- for(const QString& name : workingItem->getValueNames())
- list.append(name);
- ui->comboBox->addItems(list);
- ui->comboBox->setCurrentIndex(workingItem->getValue());
}
else
{
ui->slider->hide();
- ui->comboBox->hide();
}
ui->checkBox->setChecked(workingItem->getValue());
@@ -51,20 +35,17 @@ ItemWidget::ItemWidget(std::weak_ptr
- item, bool noGroupEdit, QWidget *pare
if(workingItem->getValueType() == ITEM_VALUE_UINT)
connect(ui->slider, &QSlider::valueChanged, this, &ItemWidget::moveToValue);
- else if(workingItem->getValueType() == ITEM_VALUE_ENUM)
- connect(ui->comboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ItemWidget::moveToValue);
else
connect(ui->checkBox, &QCheckBox::toggled, this, &ItemWidget::moveToState);
connect(ui->pushButton, &QPushButton::clicked, this, &ItemWidget::showSettingsDialog);
connect(workingItem.get(), &Item::updated, this, &ItemWidget::onItemUpdated);
connect(ui->pushButton_Remove, &QPushButton::clicked, this, &ItemWidget::deleteItem);
+
}
else
{
disable();
}
-
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
}
void ItemWidget::deleteItem()
@@ -79,9 +60,7 @@ void ItemWidget::moveToValue(int value)
{
if(auto workingItem = item_.lock())
{
- ItemUpdateRequest request = workingItem->createValueUpdateRequest(ITEM_UPDATE_USER);
- request.payload.setValueData(value);
- request.changes.value = true;
+ ItemUpdateRequest request = workingItem->createValueUpdateRequest(value, ITEM_UPDATE_USER);
workingItem->requestUpdate(request);
}
else
@@ -92,7 +71,15 @@ void ItemWidget::moveToValue(int value)
void ItemWidget::moveToState(bool state)
{
- moveToValue(state);
+ if(auto workingItem = item_.lock())
+ {
+ ItemUpdateRequest request = workingItem->createValueUpdateRequest(state, ITEM_UPDATE_USER);
+ workingItem->requestUpdate(request);
+ }
+ else
+ {
+ disable();
+ }
}
void ItemWidget::disable()
@@ -100,7 +87,6 @@ void ItemWidget::disable()
ui->checkBox->setEnabled(false);
ui->label->setEnabled(false);
ui->slider->setEnabled(false);
- ui->comboBox->setEnabled(false);
ui->pushButton_Remove->setEnabled(false);
}
@@ -118,9 +104,8 @@ void ItemWidget::showSettingsDialog()
{
if(auto workingItem = item_.lock())
{
- ItemSettingsDialog dialog(workingItem, noGroupEdit_, this);
+ ItemSettingsDialog dialog(workingItem, this);
dialog.exec();
-
}
else disable();
}
@@ -132,16 +117,6 @@ std::weak_ptr
- ItemWidget::getItem()
void ItemWidget::onItemUpdated(ItemUpdateRequest update)
{
- if(update.changes.valueNames)
- {
- ui->comboBox->blockSignals(true);
- ui->comboBox->clear();
- QStringList list;
- for(const QString& name : update.payload.getValueNames())
- list.append(name);
- ui->comboBox->addItems(list);
- ui->comboBox->blockSignals(false);
- }
stateChanged(update.payload.getValue());
}
@@ -153,9 +128,6 @@ void ItemWidget::stateChanged(int state)
ui->checkBox->blockSignals(true);
ui->checkBox->setChecked(state);
ui->checkBox->blockSignals(false);
- ui->comboBox->blockSignals(true);
- ui->comboBox->setCurrentIndex(state);
- ui->comboBox->blockSignals(false);
}
ItemWidget::~ItemWidget()
diff --git a/src/ui/itemwidget.h b/src/ui/itemwidget.h
index 51c642f..90d5a97 100644
--- a/src/ui/itemwidget.h
+++ b/src/ui/itemwidget.h
@@ -3,6 +3,7 @@
#include
#include
+#include "itemsettingsdialog.h"
#include "../items/item.h"
namespace Ui
@@ -15,7 +16,6 @@ class ItemWidget : public QWidget
Q_OBJECT
private:
std::weak_ptr
- item_;
- bool noGroupEdit_;
void disable();
@@ -30,7 +30,7 @@ private slots:
void deleteItem();
public:
- explicit ItemWidget(std::weak_ptr
- item, bool noGroupEdit = 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 a1e4bf0..96b625e 100644
--- a/src/ui/itemwidget.ui
+++ b/src/ui/itemwidget.ui
@@ -59,16 +59,6 @@
- -
-
-
-
- 0
- 0
-
-
-
-
-
diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp
index f60170f..79a6b3e 100644
--- a/src/ui/mainwindow.cpp
+++ b/src/ui/mainwindow.cpp
@@ -1,7 +1,6 @@
#include "mainwindow.h"
#include
-#include
#include "ui_mainwindow.h"
#include "itemscrollbox.h"
@@ -10,12 +9,10 @@
#include "mainobject.h"
#include "programmode.h"
#include "items/poweritem.h"
-#include "sensors/mqttsensorsource.h"
MainWindow::MainWindow(MainObject * const mainObject, QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
- mainObject(mainObject),
colorChooser(this)
{
ui->setupUi(this);
@@ -27,7 +24,6 @@ MainWindow::MainWindow(MainObject * const mainObject, QWidget *parent) :
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);
- connect(&globalItems, &ItemStore::itemUpdated, ui->relayList, &ItemScrollBox::onItemUpdate);
for(size_t i = 0; i < globalItems.getItems()->size(); ++i)
ui->relayList->addItem(globalItems.getItems()->at(i));
@@ -48,9 +44,7 @@ MainWindow::MainWindow(MainObject * const mainObject, QWidget *parent) :
ui->button_color->hide();
connect(ui->pushButton_addItem, &QPushButton::clicked, this, &MainWindow::showItemCreationDialog);
- connect(ui->pushButton_addSensor, &QPushButton::clicked, this, &MainWindow::showSensorCreationDialog);
connect(ui->relayList, &ItemScrollBox::deleteRequest, &globalItems, &ItemStore::removeItem);
- connect(ui->checkBox_sensorsShowHidden, &QCheckBox::clicked, ui->sensorListView, &SensorListWidget::setShowHidden);
ui->splitter->setStretchFactor(1, 1);
}
@@ -71,7 +65,7 @@ void MainWindow::showPowerItemDialog()
}
if(powerItem)
{
- ItemSettingsDialog diag(std::shared_ptr
- (powerItem), false, this);
+ ItemSettingsDialog diag(std::shared_ptr
- (powerItem), this);
diag.show();
diag.exec();
}
@@ -85,42 +79,7 @@ void MainWindow::showItemCreationDialog()
ItemCreationDialog diag(this);
diag.show();
if(diag.exec())
- {
- ItemAddRequest request;
- request.type = ITEM_UPDATE_USER;
- request.changes = ItemFieldChanges(true);
- request.payload = diag.item;
- createdItem(request);
- }
-}
-
-void MainWindow::showSensorCreationDialog()
-{
- bool ok;
- QString topic = QInputDialog::getText(this, "Add MQTT Sensor", "Topic:", QLineEdit::Normal, "", &ok);
- if(!ok || topic.isEmpty())
- return;
-
- QString name = QInputDialog::getText(this, "Add MQTT Sensor", "Name:", QLineEdit::Normal, topic, &ok);
- if(!ok)
- return;
-
- Sensor sensor(Sensor::TYPE_DUMMY, 0, 0, name);
- QJsonObject payload;
- payload["Topic"] = topic;
- payload["Name"] = name;
-
- PrimaryMainObject* primaryMain = dynamic_cast(mainObject);
- if(primaryMain)
- {
- // Primary mode: add directly to mqttSensorSource
- primaryMain->mqttSensorSource.addSensor(topic, name);
- }
- else
- {
- // Secondary mode: send via TCP to primary
- mainObject->addSensor(sensor, Sensor::BACKEND_MQTT, payload);
- }
+ createdItem(diag.item);
}
void MainWindow::changeHeaderLableText(QString string)
@@ -132,36 +91,3 @@ void MainWindow::changeHeaderLableText(QString string)
}
ui->label_serialRecive->setText(string);
}
-
-void MainWindow::store(QJsonObject& json) const
-{
- QJsonObject mainWindowJson;
-
- QList splitterSizes = ui->splitter->sizes();
- QJsonArray splitterSizeArray;
- for(int size : splitterSizes)
- splitterSizeArray.append(size);
- mainWindowJson["SplitterSizes"] = splitterSizeArray;
-
- ui->relayList->store(mainWindowJson);
- ui->sensorListView->store(mainWindowJson);
-
- json["MainWindow"] = mainWindowJson;
-}
-
-void MainWindow::load(const QJsonObject& json)
-{
- QJsonObject mainWindowJson = json["MainWindow"].toObject();
-
- QJsonArray splitterSizes = mainWindowJson["SplitterSizes"].toArray();
- if(!splitterSizes.isEmpty())
- {
- QList sizes;
- for(const QJsonValue& size : splitterSizes)
- sizes.append(size.toInt());
- ui->splitter->setSizes(sizes);
- }
-
- ui->relayList->load(mainWindowJson);
- ui->sensorListView->load(mainWindowJson);
-}
diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h
index 780eeb0..5b04b64 100644
--- a/src/ui/mainwindow.h
+++ b/src/ui/mainwindow.h
@@ -6,7 +6,6 @@
#include
#include
#include
-#include
#include
@@ -25,19 +24,15 @@ public:
explicit MainWindow(MainObject * const mainObject, QWidget *parent = nullptr);
~MainWindow();
- void store(QJsonObject& json) const;
- void load(const QJsonObject& json);
-
private:
Ui::MainWindow *ui;
- MainObject* const mainObject;
QColorDialog colorChooser;
signals:
void sigSave();
- void createdItem(ItemAddRequest request);
+ void createdItem(std::shared_ptr
- item);
void sigSetRgb(const QColor color);
private slots:
@@ -45,7 +40,6 @@ private slots:
//RGB
void showPowerItemDialog();
void showItemCreationDialog();
- void showSensorCreationDialog();
public slots:
diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui
index 0c8fa29..baa31c8 100644
--- a/src/ui/mainwindow.ui
+++ b/src/ui/mainwindow.ui
@@ -27,7 +27,7 @@
- :/images/xyz.uvos.icon.bmp:/images/xyz.uvos.icon.bmp
+ :/images/UVOSicon.bmp:/images/UVOSicon.bmp
@@ -94,7 +94,7 @@
- 350
+ 400
0
@@ -106,13 +106,6 @@
- -
-
-
- Show Hidden
-
-
-
@@ -230,13 +223,6 @@
- -
-
-
- Add Sensor
-
-
-
-
diff --git a/src/ui/relayscrollbox.ui b/src/ui/relayscrollbox.ui
index 7ef7dc2..cb0fae2 100644
--- a/src/ui/relayscrollbox.ui
+++ b/src/ui/relayscrollbox.ui
@@ -13,15 +13,52 @@
Form
-
+
-
-
-
- false
+
+
+ QFrame::NoFrame
-
+
+ 0
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
true
+
+
+
+ 0
+ 0
+ 388
+ 288
+
+
+
+
-
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
diff --git a/src/ui/sensorlistwidget.cpp b/src/ui/sensorlistwidget.cpp
index dfd0e7c..b732362 100644
--- a/src/ui/sensorlistwidget.cpp
+++ b/src/ui/sensorlistwidget.cpp
@@ -3,197 +3,83 @@
#include
#include
#include
-#include
-#include
-#include
-#include "sensorsettingsdialog.h"
-
-SensorListWidget::SensorListWidget(const bool showHidden, QWidget *parent): QTreeWidget(parent),
+SensorListWidget::SensorListWidget(const bool showHidden, QWidget *parent): QTableWidget(parent),
showHidden_(showHidden)
{
setColumnCount(3);
- setHeaderLabels({"Sensor", "Value", "Time"});
setSelectionBehavior(QAbstractItemView::SelectRows);
- header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
- header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
- header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
+ horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
QScroller::grabGesture(this, QScroller::LeftMouseButtonGesture);
setAutoScroll(true);
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
sensorsChanged(std::vector());
-
- connect(this, &QTreeWidget::itemDoubleClicked, this, &SensorListWidget::onDoubleClick);
+ verticalHeader()->hide();
}
SensorListWidget::SensorListWidget(SensorStore& sensorStore, const bool showHidden,
- QWidget* parent): QTreeWidget (parent), showHidden_(showHidden)
+ QWidget* parent): QTableWidget (parent), showHidden_(showHidden)
{
sensorsChanged(*(sensorStore.getSensors()));
- connect(this, &QTreeWidget::itemDoubleClicked, this, &SensorListWidget::onDoubleClick);
-}
-
-void SensorListWidget::onDoubleClick(QTreeWidgetItem *item, int column)
-{
- if(item && item->type() == 1001)
- {
- Sensor sensor = static_cast(item)->getSensor();
- SensorSettingsDialog diag(sensor, this);
- if(diag.exec())
- {
- sensor.name = diag.getName();
- sensor.hidden = diag.getHidden();
- sensor.groupName = diag.getGroupName();
-
- globalSensors.sensorGotState(sensor, SENSOR_UPDATE_USER);
- }
- }
}
void SensorListWidget::sensorsChanged(std::vector sensors)
{
- QMap expandedStates;
- QList columnWidths;
-
- for(int i = 0; i < columnCount(); ++i)
- columnWidths.append(columnWidth(i));
-
- for(int i = 0; i < topLevelItemCount(); ++i)
- {
- QTreeWidgetItem* item = topLevelItem(i);
- if(item->type() != 1001)
- {
- expandedStates[item->text(0)] = item->isExpanded();
- }
- }
-
clear();
-
- QMap groupItems;
-
- QStringList headerLabels = {"Sensor", "Value", "Time"};
- setHeaderLabels(headerLabels);
-
- QList ungroupedItems;
-
- for(const Sensor& sensor : sensors)
+ setHorizontalHeaderItem(0, new QTableWidgetItem("Sensor"));
+ setHorizontalHeaderItem(1, new QTableWidgetItem("Value"));
+ setHorizontalHeaderItem(2, new QTableWidgetItem("Time"));
+ size_t listLen = 0;
+ for(size_t i = 0; i < sensors.size(); ++i)
+ if(showHidden_ || !sensors[i].hidden)
+ ++listLen;
+ setRowCount(static_cast(listLen));
+ size_t row = 0;
+ for(size_t i = 0; i < sensors.size(); ++i)
{
- if(!showHidden_ && sensor.hidden)
- continue;
+ if(showHidden_ || !sensors[i].hidden)
+ {
+ QString itemString;
+ itemString.append(QString::number(sensors[i].field));
+ itemString.append(' ');
- QString itemString = QString::number(sensor.field);
-
- if(sensor.type == Sensor::TYPE_DOOR)
- {
- if(static_cast(sensor.field))
- itemString = "\"Open\"";
- else
- itemString = "\"Closed\"";
- }
- else if(sensor.type == Sensor::TYPE_AUDIO_OUTPUT)
- {
- if(static_cast(sensor.field))
- itemString = "\"Playing\"";
- else
- itemString = "\"Silent\"";
- }
- else if(!sensor.getUnit().isEmpty())
- {
- itemString.append(" ");
- itemString.append(sensor.getUnit());
- }
-
- SensorListItem* sensorItem = new SensorListItem(sensor.name + (sensor.hidden ? " (H)" : ""), sensor);
- sensorItem->setText(0, sensor.name + (sensor.hidden ? " (H)" : ""));
- sensorItem->setText(1, itemString);
- if(sensor.type <= 128)
- sensorItem->setText(2, sensor.lastSeen.time().toString("hh:mm"));
-
- if(sensor.groupName.isEmpty())
- {
- ungroupedItems.append(sensorItem);
- }
- else
- {
- QTreeWidgetItem* groupItem;
- auto it = groupItems.find(sensor.groupName);
- if(it == groupItems.end())
+ if(sensors[i].type == Sensor::TYPE_DOOR)
{
- groupItem = new QTreeWidgetItem(this);
- groupItem->setText(0, sensor.groupName);
-
- bool wasExpanded = expandedStates.value(sensor.groupName, false);
- if(pendingGroupExpandedStates_.contains(sensor.groupName))
- wasExpanded = pendingGroupExpandedStates_.take(sensor.groupName);
- groupItem->setExpanded(wasExpanded);
- groupItems[sensor.groupName] = groupItem;
+ if(static_cast(sensors[i].field))
+ itemString.append("\"Open\"");
+ else itemString.append("\"Closed\"");
}
- else
+ else if(sensors[i].type == Sensor::TYPE_AUDIO_OUTPUT)
{
- groupItem = it.value();
+ if(static_cast(sensors[i].field))
+ itemString.append("\"Playing\"");
+ else itemString.append("\"Silent\"");
+ }
+ else if(!sensors[i].getUnit().isEmpty())
+ {
+ itemString.append(" ");
+ itemString.append(sensors[i].getUnit());
}
- groupItem->addChild(sensorItem);
- }
- }
- for(SensorListItem* item : ungroupedItems)
- {
- addTopLevelItem(item);
+ setItem(static_cast(row), 0, new SensorListItem(sensors[i].name + (sensors[i].hidden ? " (H)" : ""), sensors[i]));
+ setItem(static_cast(row), 1, new QTableWidgetItem(itemString));
+ if(sensors[i].type <= 128)
+ setItem(static_cast(row), 2, new QTableWidgetItem(sensors[i].lastSeen.time().toString("hh:mm")));
+ ++row;
+ }
}
sortItems(0, Qt::AscendingOrder);
-
- for(auto it = groupItems.begin(); it != groupItems.end(); ++it)
- {
- it.value()->sortChildren(0, Qt::AscendingOrder);
- }
-
- for(int i = 0; i < columnCount() && i < columnWidths.size(); ++i)
- setColumnWidth(i, columnWidths.at(i));
+ resizeColumnsToContents();
}
const Sensor& SensorListWidget::getSensorForIndex(const QModelIndex &index)
{
- QTreeWidgetItem* item = itemFromIndex(index);
- if(item && item->type() == 1001)
- return static_cast(item)->getSensor();
- static Sensor dummy;
- return dummy;
+ return static_cast(item(index.row(), 0))->getSensor();
}
void SensorListWidget::setShowHidden(const bool showHidden)
{
- showHidden_ = showHidden;
- sensorsChanged(*globalSensors.getSensors());
-}
-
-void SensorListWidget::store(QJsonObject& json) const
-{
- QJsonObject sensorListJson;
-
- QJsonObject groupStates;
- for(int i = 0; i < topLevelItemCount(); ++i)
- {
- QTreeWidgetItem* item = topLevelItem(i);
- if(item->type() != 1001)
- {
- groupStates[item->text(0)] = item->isExpanded();
- }
- }
- sensorListJson["GroupStates"] = groupStates;
-
- json["SensorList"] = sensorListJson;
-}
-
-void SensorListWidget::load(const QJsonObject& json)
-{
- QJsonObject sensorListJson = json["SensorList"].toObject();
-
- QJsonObject groupStates = sensorListJson["GroupStates"].toObject();
- pendingGroupExpandedStates_.clear();
- for(auto it = groupStates.begin(); it != groupStates.end(); ++it)
- {
- pendingGroupExpandedStates_[it.key()] = it.value().toBool();
- }
+ showHidden_=showHidden;
}
const Sensor& SensorListItem::getSensor()
@@ -202,8 +88,7 @@ const Sensor& SensorListItem::getSensor()
}
SensorListItem::SensorListItem(const QString& text, const Sensor& sensor):
- QTreeWidgetItem(1001), sensor(sensor)
+ QTableWidgetItem(text, 1001), sensor(sensor)
{
- setText(0, text);
}
diff --git a/src/ui/sensorlistwidget.h b/src/ui/sensorlistwidget.h
index 1c11a18..4c84d54 100644
--- a/src/ui/sensorlistwidget.h
+++ b/src/ui/sensorlistwidget.h
@@ -1,9 +1,9 @@
#pragma once
-#include
+#include
#include
#include "sensors/sensor.h"
-class SensorListItem : public QTreeWidgetItem
+class SensorListItem : public QTableWidgetItem
{
Sensor sensor;
@@ -12,30 +12,22 @@ public:
SensorListItem(const QString& text, const Sensor& sensor);
};
-class SensorListWidget : public QTreeWidget
+class SensorListWidget : public QTableWidget
{
Q_OBJECT
bool showHidden_;
- QString savedSelectedGroup_;
- QMap pendingGroupExpandedStates_;
public:
SensorListWidget(const bool showHidden = true, QWidget* parent = nullptr);
SensorListWidget(SensorStore& sensorStore, const bool showHidden = true, QWidget* parent = nullptr);
virtual ~SensorListWidget() {}
-
+ void setShowHidden(const bool showHidden);
const Sensor& getSensorForIndex(const QModelIndex &index);
- void store(QJsonObject& json) const;
- void load(const QJsonObject& json);
-
public slots:
- void setShowHidden(const bool showHidden);
void sensorsChanged(std::vector sensors);
-private slots:
- void onDoubleClick(QTreeWidgetItem *item, int column);
};
diff --git a/src/ui/sensorsettingsdialog.cpp b/src/ui/sensorsettingsdialog.cpp
deleted file mode 100644
index 7a61cd9..0000000
--- a/src/ui/sensorsettingsdialog.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include "sensorsettingsdialog.h"
-#include "ui_sensorsettingsdialog.h"
-
-SensorSettingsDialog::SensorSettingsDialog(const Sensor& sensor, QWidget* parent)
- : QDialog(parent)
- , ui(new Ui::SensorSettingsDialog)
-{
- ui->setupUi(this);
-
- ui->label_typeValue->setText(QString::number(sensor.type));
- ui->label_idValue->setText(QString::number(sensor.id));
- ui->lineEdit_Name->setText(sensor.name);
- ui->checkBox_Hidden->setChecked(sensor.hidden);
-
- // Populate group dropdown with existing groups
- std::vector groups = globalSensors.allGroups();
- for(const QString& group : groups)
- ui->comboBox_Group->addItem(group);
- // Set current group (will be empty string if no group)
- ui->comboBox_Group->setCurrentText(sensor.groupName);
-}
-
-SensorSettingsDialog::~SensorSettingsDialog()
-{
- delete ui;
-}
-
-QString SensorSettingsDialog::getName() const
-{
- return ui->lineEdit_Name->text();
-}
-
-QString SensorSettingsDialog::getGroupName() const
-{
- return ui->comboBox_Group->currentText();
-}
-
-bool SensorSettingsDialog::getHidden() const
-{
- return ui->checkBox_Hidden->isChecked();
-}
\ No newline at end of file
diff --git a/src/ui/sensorsettingsdialog.h b/src/ui/sensorsettingsdialog.h
deleted file mode 100644
index 8926dca..0000000
--- a/src/ui/sensorsettingsdialog.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef SENSORSETTINGSDIALOG_H
-#define SENSORSETTINGSDIALOG_H
-
-#include
-#include "sensors/sensor.h"
-
-namespace Ui
-{
-class SensorSettingsDialog;
-}
-
-class SensorSettingsDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit SensorSettingsDialog(const Sensor& sensor, QWidget* parent = nullptr);
- ~SensorSettingsDialog();
-
- QString getName() const;
- QString getGroupName() const;
- bool getHidden() const;
-
-private:
- Ui::SensorSettingsDialog* ui;
-};
-
-#endif // SENSORSETTINGSDIALOG_H
\ No newline at end of file
diff --git a/src/ui/sensorsettingsdialog.ui b/src/ui/sensorsettingsdialog.ui
deleted file mode 100644
index 32a75d7..0000000
--- a/src/ui/sensorsettingsdialog.ui
+++ /dev/null
@@ -1,156 +0,0 @@
-
-
- SensorSettingsDialog
-
-
-
- 0
- 0
- 400
- 180
-
-
-
- Sensor Settings
-
-
- -
-
-
- QFormLayout::AllNonFixedFieldsGrow
-
-
-
-
-
- Type:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- TextLabel
-
-
-
- -
-
-
- Id:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- TextLabel
-
-
-
- -
-
-
- Name:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
-
-
-
- -
-
-
- Group:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- true
-
-
-
- -
-
-
- Hidden:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
-
-
-
-
-
-
-
- buttonBox
- accepted()
- SensorSettingsDialog
- accept()
-
-
- 248
- 254
-
-
- 157
- 274
-
-
-
-
- buttonBox
- rejected()
- SensorSettingsDialog
- reject()
-
-
- 316
- 260
-
-
- 286
- 274
-
-
-
-
-
\ No newline at end of file
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
deleted file mode 100644
index bddc2f4..0000000
--- a/tests/CMakeLists.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-cmake_minimum_required(VERSION 4.0)
-
-# Enable testing
-enable_testing()
-
-# Find Qt packages for tests
-find_package(Qt6 COMPONENTS Core Gui Widgets Multimedia Test REQUIRED)
-
-# Add test executables - link to static library instead of compiling sources
-add_executable(test_item unit/items/test_item.cpp)
-add_executable(test_sensor unit/sensors/test_sensor.cpp)
-add_executable(test_actor unit/actors/test_actor.cpp)
-add_executable(test_itemstore unit/items/test_itemstore.cpp)
-add_executable(test_itemloadersource unit/items/test_itemloadersource.cpp)
-add_executable(test_mqttitem unit/items/test_mqttitem.cpp)
-add_executable(test_tcp unit/service/test_tcp.cpp)
-
-# Link all tests to static library
-foreach(test test_item test_sensor test_actor test_itemstore test_itemloadersource test_mqttitem test_tcp)
- target_link_libraries(${test}
- smartvos_core
- Qt6::Core
- Qt6::Gui
- Qt6::Widgets
- Qt6::Multimedia
- Qt6::Network
- Qt6::WebSockets
- Qt6::Mqtt
- Qt6::Test
- )
-
- # Include paths - the static library already has the correct include paths
- target_include_directories(${test} PRIVATE
- ${CMAKE_CURRENT_SOURCE_DIR}/../src
- ${Qt6Gui_PRIVATE_INCLUDE_DIRS}
- )
-endforeach()
-
-# Add tests to CTest
-add_test(NAME test_item COMMAND test_item)
-add_test(NAME test_sensor COMMAND test_sensor)
-add_test(NAME test_actor COMMAND test_actor)
-add_test(NAME test_itemstore COMMAND test_itemstore)
-add_test(NAME test_itemloadersource COMMAND test_itemloadersource)
-add_test(NAME test_mqttitem COMMAND test_mqttitem)
-add_test(NAME test_tcp COMMAND test_tcp)
\ No newline at end of file
diff --git a/tests/unit/actors/test_actor.cpp b/tests/unit/actors/test_actor.cpp
deleted file mode 100644
index cf42d32..0000000
--- a/tests/unit/actors/test_actor.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-#include
-#include "actors/actor.h"
-#include "actors/timeractor.h"
-#include "actors/sensoractor.h"
-
-class TestActor : public QObject
-{
- Q_OBJECT
-
-private slots:
- void initTestCase()
- {
- // Setup for all tests
- }
-
- void testActorCreation()
- {
- Actor actor;
-
- // Actor should be active by default
- QVERIFY(actor.isActive());
-
- // Actor should not be exhausted by default
- QVERIFY(!actor.isExausted());
- }
-
- void testActorActivation()
- {
- Actor actor;
-
- // Test makeActive/makeInactive
- actor.makeActive();
- QVERIFY(actor.isActive());
-
- actor.makeInactive();
- QVERIFY(!actor.isActive());
- }
-
- void testActorSetActive()
- {
- Actor actor;
-
- // Test setActive
- actor.setActive(1);
- QVERIFY(actor.isActive());
-
- actor.setActive(0);
- QVERIFY(!actor.isActive());
- }
-
- void testActorTriggerValue()
- {
- Actor actor;
-
- // Default trigger value should be 0
- QVERIFY(actor.getTriggerValue() == 0);
-
- // Set trigger value
- actor.setTriggerValue(1);
- QVERIFY(actor.getTriggerValue() == 1);
-
- actor.setTriggerValue(255);
- QVERIFY(actor.getTriggerValue() == 255);
- }
-
- void testActorActionName()
- {
- Actor actor;
-
- // Default trigger value is 0, so action name should be "off"
- QVERIFY(actor.actionName() == "off");
-
- // Set trigger value to 1
- actor.setTriggerValue(1);
- QVERIFY(actor.actionName() == "on");
-
- // Set trigger value to something else
- actor.setTriggerValue(5);
- QVERIFY(actor.actionName() == "value to 5");
- }
-
- void testActorJsonSerialization()
- {
- Actor actor;
- actor.setTriggerValue(1);
- actor.makeInactive();
-
- QJsonObject json;
- actor.store(json);
-
- // Verify JSON contents
- QVERIFY(json.contains("Active"));
- QVERIFY(json.contains("Exausted"));
- QVERIFY(json.contains("TriggerValue"));
-
- QVERIFY(json["Active"].toBool() == false);
- QVERIFY(json["Exausted"].toBool() == false);
- QVERIFY(json["TriggerValue"].toInt() == 1);
- }
-
- void testActorJsonDeserialization()
- {
- QJsonObject json;
- json["Active"] = false;
- json["Exausted"] = true;
- json["TriggerValue"] = 5;
-
- Actor actor;
- actor.load(json);
-
- QVERIFY(actor.isActive() == false);
- QVERIFY(actor.isExausted() == true);
- QVERIFY(actor.getTriggerValue() == 5);
- }
-
- void testActorCreateActor()
- {
- // Test creating different actor types
- std::shared_ptr alarmActor = Actor::createActor("Alarm");
- QVERIFY(alarmActor != nullptr);
-
- std::shared_ptr sensorActor = Actor::createActor("Sensor");
- QVERIFY(sensorActor != nullptr);
-
- std::shared_ptr timerActor = Actor::createActor("Timer");
- QVERIFY(timerActor != nullptr);
-
- std::shared_ptr regulatorActor = Actor::createActor("Regulator");
- QVERIFY(regulatorActor != nullptr);
-
- std::shared_ptr polynomalActor = Actor::createActor("Polynomal");
- QVERIFY(polynomalActor != nullptr);
-
- std::shared_ptr factorActor = Actor::createActor("MultiFactor");
- QVERIFY(factorActor != nullptr);
-
- std::shared_ptr genericActor = Actor::createActor("Actor");
- QVERIFY(genericActor != nullptr);
-
- // Test unknown type returns nullptr
- std::shared_ptr unknownActor = Actor::createActor("UnknownType");
- QVERIFY(unknownActor == nullptr);
- }
-
- void testActorLoadActor()
- {
- QJsonObject json;
- json["Type"] = "Timer";
- json["Active"] = true;
- json["Exausted"] = false;
- json["TriggerValue"] = 1;
- json["Timeout"] = 5000;
-
- std::shared_ptr actor = Actor::loadActor(json);
- QVERIFY(actor != nullptr);
-
- // Verify the actor was loaded with correct values
- QVERIFY(actor->isActive());
- QVERIFY(!actor->isExausted());
- QVERIFY(actor->getTriggerValue() == 1);
- }
-
- void testTimerActorCreation()
- {
- TimerActor actor(60);
-
- // Default timeout should be 60 seconds
- QVERIFY(actor.getTimeout() == 60);
- }
-
- void testTimerActorSetTimeout()
- {
- TimerActor actor(60);
-
- actor.setTimeout(120);
- QVERIFY(actor.getTimeout() == 120);
-
- actor.setTimeout(5);
- QVERIFY(actor.getTimeout() == 5);
- }
-
- void testTimerActorJsonSerialization()
- {
- TimerActor actor(120);
-
- QJsonObject json;
- actor.store(json);
-
- // Verify JSON contents
- QVERIFY(json.contains("Type"));
- QVERIFY(json.contains("Timeout"));
-
- QVERIFY(json["Type"].toString() == "Timer");
- QVERIFY(json["Timeout"].toInt() == 120000); // Converted to milliseconds
- }
-
- void testTimerActorJsonDeserialization()
- {
- QJsonObject json;
- json["Type"] = "Timer";
- json["Timeout"] = 30000; // 30 seconds in milliseconds
- json["Active"] = true;
- json["Exausted"] = false;
- json["TriggerValue"] = 1;
-
- TimerActor actor;
- actor.load(json, false);
-
- // Timeout should be 30 seconds
- QVERIFY(actor.getTimeout() == 30);
- }
-
- void testTimerActorGetName()
- {
- TimerActor actor(60);
-
- QString name = actor.getName();
- QVERIFY(name.contains("60"));
- }
-
- void testSensorActorCreation()
- {
- Sensor sensor(Sensor::TYPE_TEMPERATURE, 1, 25.0, "temp_sensor");
- SensorActor actor(sensor);
-
- // Verify sensor was set correctly
- QVERIFY(actor.getSensor().type == Sensor::TYPE_TEMPERATURE);
- QVERIFY(actor.getSensor().id == 1);
- }
-
- void testSensorActorDefaultCreation()
- {
- SensorActor actor;
-
- // Default sensor should be dummy
- QVERIFY(actor.getSensor().type == Sensor::TYPE_DUMMY);
- }
-
- void testSensorActorSetSensor()
- {
- SensorActor actor;
-
- Sensor newSensor(Sensor::TYPE_HUMIDITY, 2, 60.0, "humidity_sensor");
- actor.setSensor(newSensor);
-
- QVERIFY(actor.getSensor().type == Sensor::TYPE_HUMIDITY);
- QVERIFY(actor.getSensor().id == 2);
- }
-
- void testSensorActorSetThreshold()
- {
- SensorActor actor;
-
- actor.setThreshold(25.0);
- QVERIFY(actor.getThreshold() == 25.0);
- }
-
- void testSensorActorSetSlope()
- {
- SensorActor actor;
-
- actor.setSloap(SensorActor::SLOPE_UP);
- QVERIFY(actor.getSloap() == SensorActor::SLOPE_UP);
-
- actor.setSloap(SensorActor::SLOPE_DOWN);
- QVERIFY(actor.getSloap() == SensorActor::SLOPE_DOWN);
-
- actor.setSloap(SensorActor::SLOPE_BOTH);
- QVERIFY(actor.getSloap() == SensorActor::SLOPE_BOTH);
- }
-
- void testSensorActorJsonSerialization()
- {
- Sensor sensor(Sensor::TYPE_TEMPERATURE, 1, 25.0, "temp_sensor");
- SensorActor actor(sensor);
- actor.setThreshold(30.0);
- actor.setSloap(SensorActor::SLOPE_UP);
-
- QJsonObject json;
- actor.store(json);
-
- // Verify JSON contents
- QVERIFY(json.contains("Type"));
- QVERIFY(json.contains("Threshold"));
- QVERIFY(json.contains("Sloap"));
- QVERIFY(json.contains("SensorType"));
-
- QVERIFY(json["Type"].toString() == "Sensor");
- QVERIFY(json["Threshold"].toDouble() == 30.0);
- QVERIFY(json["Sloap"].toInt() == SensorActor::SLOPE_UP);
- }
-
- void testSensorActorJsonDeserialization()
- {
- QJsonObject json;
- json["Type"] = "Sensor";
- json["Threshold"] = 25.5;
- json["Sloap"] = SensorActor::SLOPE_DOWN;
- json["SensorType"] = Sensor::TYPE_HUMIDITY;
- json["SensorId"] = 3;
- json["SensorField"] = 65.0;
- json["SensorName"] = "humidity";
- json["Active"] = true;
- json["Exausted"] = false;
- json["TriggerValue"] = 1;
-
- SensorActor actor;
- actor.load(json, false);
-
- QVERIFY(actor.getThreshold() == 25.5);
- QVERIFY(actor.getSloap() == SensorActor::SLOPE_DOWN);
- }
-
- void testSensorActorGetName()
- {
- Sensor sensor(Sensor::TYPE_TEMPERATURE, 1, 25.0, "temp_sensor");
- SensorActor actor(sensor);
- actor.setThreshold(30.0);
-
- QString name = actor.getName();
- QVERIFY(name.contains("temp_sensor"));
- QVERIFY(name.contains("30"));
- }
-
- void cleanupTestCase()
- {
- // Cleanup after all tests
- }
-};
-
-QTEST_APPLESS_MAIN(TestActor)
-
-#include "test_actor.moc"
\ No newline at end of file
diff --git a/tests/unit/items/test_item.cpp b/tests/unit/items/test_item.cpp
deleted file mode 100644
index b4ad369..0000000
--- a/tests/unit/items/test_item.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-#include
-#include "items/item.h"
-#include "items/itemstore.h"
-#include "items/itemsource.h"
-#include "items/itemloadersource.h"
-
-class TestItem : public QObject
-{
- Q_OBJECT
-
-private slots:
- void initTestCase()
- {
- // Setup for all tests
- }
-
- void testItemCreation()
- {
- Item item(0, "test_item", 0);
- QCOMPARE(item.getName(), QString("test_item"));
- }
-
- void testOverrideFunctionality()
- {
- Item item(0, "test_item", 0);
-
- // Test override on/off
- item.setOverride(true);
- QVERIFY(item.getOverride());
-
- item.setOverride(false);
- QVERIFY(!item.getOverride());
- }
-
- void testItemValueTypes()
- {
- // Test default value type is BOOL
- Item item(1, "test_item", 0);
- QCOMPARE(item.getValueType(), ITEM_VALUE_BOOL);
-
- // Test setting and getting value
- item.setValueData(1);
- QCOMPARE(item.getValue(), static_cast(1));
-
- item.setValueData(0);
- QCOMPARE(item.getValue(), static_cast(0));
- }
-
- void testItemId()
- {
- Item item(42, "test_item", 0);
- QCOMPARE(item.id(), static_cast(42));
- }
-
- void testItemGroupName()
- {
- Item item(1, "test_item", 0);
- QCOMPARE(item.getGroupName(), QString("All")); // Default group
-
- item.setGroupName("Living Room");
- QCOMPARE(item.getGroupName(), QString("Living Room"));
- }
-
- void testItemHidden()
- {
- Item item(1, "test_item", 0);
- QVERIFY(!item.isHidden());
-
- item.setHidden(true);
- QVERIFY(item.isHidden());
-
- item.setHidden(false);
- QVERIFY(!item.isHidden());
- }
-
- void testItemLoaded()
- {
- Item item(1, "test_item", 0);
- QVERIFY(!item.getLoaded());
-
- item.setLoaded(true);
- QVERIFY(item.getLoaded());
- }
-
- void testItemJsonSerialization()
- {
- Item item(42, "test_item", 1);
- item.setGroupName("TestGroup");
-
- QJsonObject json;
- item.store(json);
-
- // Verify JSON contents
- QCOMPARE(json["ItemId"].toDouble(), 42.0);
- // Note: Name is only stored if changes.name is true
- // Value is only stored if changes.value is true
- }
-
- void testItemJsonDeserialization()
- {
- QJsonObject json;
- json["ItemId"] = 100;
- json["Name"] = "loaded_item";
- json["Value"] = 1;
- json["GroupName"] = "Bedroom";
-
- Item item;
- item.load(json);
-
- // Note: load() uses loadWithChanges which requires preserve=false to apply changes
- // The id should be set
- // The name should be set (since preserve defaults to false)
- }
-
- void testItemUpdateRequest()
- {
- Item item(1, "test_item", 0);
-
- // Test creating update request
- ItemUpdateRequest request = item.createValueUpdateRequest(ITEM_UPDATE_USER, false);
-
- QVERIFY(request.type == ITEM_UPDATE_USER);
- // Note: changes is not automatically set by createValueUpdateRequest
- // The caller is expected to set the changes they want
- QVERIFY(request.newActors.empty());
- }
-
- void testItemUpdateRequestWithActors()
- {
- Item item(1, "test_item", 0);
-
- // Test creating update request with actors
- ItemUpdateRequest request = item.createValueUpdateRequest(ITEM_UPDATE_USER, true);
-
- QVERIFY(request.type == ITEM_UPDATE_USER);
- // With actors=true, newActors should be populated
- // Note: changes.actors is set by the caller, not by createValueUpdateRequest
- }
-
- void testItemHasActors()
- {
- Item item(1, "test_item", 0);
-
- QVERIFY(!item.hasActors());
-
- // Note: Adding actors requires a valid Actor pointer
- }
-
- void testItemRemoveAllActors()
- {
- Item item(1, "test_item", 0);
-
- item.removeAllActors();
- QVERIFY(!item.hasActors());
- }
-
- void testItemSetActorsActive()
- {
- Item item(1, "test_item", 0);
-
- // Should not crash when no actors
- item.setActorsActive(true);
- item.setActorsActive(false);
- }
-
- void testItemDataChangeDetection()
- {
- ItemData data1(1, "item1", 0);
- ItemData data2(1, "item1", 1);
-
- // Test value change detection
- ItemFieldChanges changes(true);
- QVERIFY(data1.hasChanged(data2, changes));
-
- // Test no change
- changes = ItemFieldChanges(false);
- QVERIFY(!data1.hasChanged(data2, changes));
- }
-
- void testItemDataNameChange()
- {
- ItemData data1(1, "item1", 0);
- ItemData data2(1, "item2", 0);
-
- ItemFieldChanges changes;
- changes.name = true;
-
- QVERIFY(data1.hasChanged(data2, changes));
- }
-
- void testItemDataGroupNameChange()
- {
- ItemData data1(1, "item1", 0);
- data1.setGroupName("Group1");
-
- ItemData data2(1, "item1", 0);
- data2.setGroupName("Group2");
-
- ItemFieldChanges changes;
- changes.groupName = true;
-
- QVERIFY(data1.hasChanged(data2, changes));
- }
-
- void testItemFieldChanges()
- {
- ItemFieldChanges changes(false);
- QVERIFY(changes.isNone());
-
- changes.value = true;
- QVERIFY(!changes.isNone());
-
- ItemFieldChanges allChanges(true);
- QVERIFY(!allChanges.isNone());
- }
-
- void cleanupTestCase()
- {
- // Cleanup after all tests
- }
-};
-
-QTEST_APPLESS_MAIN(TestItem)
-
-#include "test_item.moc"
diff --git a/tests/unit/items/test_itemloadersource.cpp b/tests/unit/items/test_itemloadersource.cpp
deleted file mode 100644
index 156edc4..0000000
--- a/tests/unit/items/test_itemloadersource.cpp
+++ /dev/null
@@ -1,240 +0,0 @@
-#include
-#include "items/itemloadersource.h"
-#include "items/item.h"
-
-class TestItemLoaderSource : public QObject
-{
- Q_OBJECT
-
-private slots:
- void initTestCase()
- {
- // Setup for all tests
- }
-
- void testItemLoaderSourceCreation()
- {
- ItemLoaderSource source;
-
- // Should be created with empty JSON
- QVERIFY(true); // No crash
- }
-
- void testItemLoaderSourceCreationWithJson()
- {
- QJsonObject json;
- json["Items"] = QJsonArray();
-
- ItemLoaderSource source(json);
-
- // Should be created with JSON
- QVERIFY(true); // No crash
- }
-
- void testItemLoaderSourceRefreshEmpty()
- {
- ItemLoaderSource source;
-
- // Should not crash with empty JSON
- source.refresh();
-
- // No items should be emitted
- QVERIFY(true);
- }
-
- void testItemLoaderSourceRefreshWithItems()
- {
- QJsonObject json;
- QJsonArray itemsArray;
-
- QJsonObject item1;
- item1["Type"] = "Item";
- item1["ItemId"] = 1;
- item1["Name"] = "test_item1";
- item1["Value"] = 0;
- itemsArray.append(item1);
-
- QJsonObject item2;
- item2["Type"] = "Item";
- item2["ItemId"] = 2;
- item2["Name"] = "test_item2";
- item2["Value"] = 1;
- itemsArray.append(item2);
-
- json["Items"] = itemsArray;
-
- ItemLoaderSource source(json);
-
- // Capture the gotItems signal
- std::vector capturedItems;
- connect(&source, &ItemLoaderSource::gotItems,
- [&capturedItems](std::vector items) {
- capturedItems = items;
- });
-
- source.refresh();
-
- // Should have 2 items
- QVERIFY(capturedItems.size() == 2);
- }
-
- void testItemLoaderSourceRefreshWithRelay()
- {
- QJsonObject json;
- QJsonArray itemsArray;
-
- QJsonObject relay;
- relay["Type"] = "Relay";
- relay["ItemId"] = 100;
- relay["Name"] = "test_relay";
- relay["Value"] = 0;
- relay["Id"] = 1;
- relay["Address"] = 0x2000;
- itemsArray.append(relay);
-
- json["Items"] = itemsArray;
-
- ItemLoaderSource source(json);
-
- // Capture the gotItems signal
- std::vector capturedItems;
- connect(&source, &ItemLoaderSource::gotItems,
- [&capturedItems](std::vector items) {
- capturedItems = items;
- });
-
- source.refresh();
-
- // Should have 1 item
- QVERIFY(capturedItems.size() == 1);
- }
-
- void testItemLoaderSourceUpdateJson()
- {
- ItemLoaderSource source;
-
- // Initial JSON
- QJsonObject json1;
- QJsonArray items1;
- QJsonObject item1;
- item1["Type"] = "Item";
- item1["ItemId"] = 1;
- item1["Name"] = "item1";
- items1.append(item1);
- json1["Items"] = items1;
-
- source.updateJson(json1);
-
- // Update JSON
- QJsonObject json2;
- QJsonArray items2;
- QJsonObject item2;
- item2["Type"] = "Item";
- item2["ItemId"] = 2;
- item2["Name"] = "item2";
- items2.append(item2);
- json2["Items"] = items2;
-
- source.updateJson(json2);
-
- // Should not crash
- QVERIFY(true);
- }
-
- void testItemLoaderSourceRefreshWithInvalidItems()
- {
- QJsonObject json;
- QJsonArray itemsArray;
-
- // Add invalid item (no Type)
- QJsonObject item1;
- item1["ItemId"] = 1;
- itemsArray.append(item1);
-
- json["Items"] = itemsArray;
-
- ItemLoaderSource source(json);
-
- // Capture the gotItems signal
- std::vector capturedItems;
- connect(&source, &ItemLoaderSource::gotItems,
- [&capturedItems](std::vector items) {
- capturedItems = items;
- });
-
- source.refresh();
-
- // Should handle invalid item gracefully (may return 0 items)
- QVERIFY(capturedItems.size() == 0 || capturedItems.size() == 1);
- }
-
- void testItemLoaderSourceRefreshWithMessageItem()
- {
- QJsonObject json;
- QJsonArray itemsArray;
-
- QJsonObject messageItem;
- messageItem["Type"] = "Message";
- messageItem["ItemId"] = 200;
- messageItem["Name"] = "alert_item";
- messageItem["Value"] = 0;
- messageItem["Message"] = "Test message";
- itemsArray.append(messageItem);
-
- json["Items"] = itemsArray;
-
- ItemLoaderSource source(json);
-
- // Capture the gotItems signal
- std::vector capturedItems;
- connect(&source, &ItemLoaderSource::gotItems,
- [&capturedItems](std::vector items) {
- capturedItems = items;
- });
-
- source.refresh();
-
- // Should have 1 item
- QVERIFY(capturedItems.size() == 1);
- }
-
- void testItemLoaderSourceRefreshWithSystemItem()
- {
- QJsonObject json;
- QJsonArray itemsArray;
-
- QJsonObject systemItem;
- systemItem["Type"] = "System";
- systemItem["ItemId"] = 300;
- systemItem["Name"] = "system_item";
- systemItem["Value"] = 0;
- systemItem["OnCommand"] = "echo on";
- systemItem["OffCommand"] = "echo off";
- itemsArray.append(systemItem);
-
- json["Items"] = itemsArray;
-
- ItemLoaderSource source(json);
-
- // Capture the gotItems signal
- std::vector capturedItems;
- connect(&source, &ItemLoaderSource::gotItems,
- [&capturedItems](std::vector items) {
- capturedItems = items;
- });
-
- source.refresh();
-
- // Should have 1 item
- QVERIFY(capturedItems.size() == 1);
- }
-
- void cleanupTestCase()
- {
- // Cleanup after all tests
- }
-};
-
-QTEST_APPLESS_MAIN(TestItemLoaderSource)
-
-#include "test_itemloadersource.moc"
\ No newline at end of file
diff --git a/tests/unit/items/test_itemstore.cpp b/tests/unit/items/test_itemstore.cpp
deleted file mode 100644
index 79d16c4..0000000
--- a/tests/unit/items/test_itemstore.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-#include
-#include "items/itemstore.h"
-#include "items/item.h"
-
-class TestItemStore : public QObject
-{
- Q_OBJECT
-
-private slots:
- void initTestCase()
- {
- // Setup for all tests
- }
-
- void testItemStoreCreation()
- {
- ItemStore store;
-
- // Should start empty
- QVERIFY(store.getItems()->empty());
- }
-
- void testItemStoreAddItem()
- {
- ItemStore store;
-
- std::shared_ptr- item(new Item(1, "test_item", 0));
-
- ItemAddRequest request;
- request.type = ITEM_UPDATE_USER;
- request.payload = item;
- request.changes = ItemFieldChanges(true);
-
- store.addItem(request);
-
- // Item should be added
- QVERIFY(store.getItems()->size() == 1);
- }
-
- void testItemStoreAddMultipleItems()
- {
- ItemStore store;
-
- std::shared_ptr
- item1(new Item(1, "item1", 0));
- std::shared_ptr
- item2(new Item(2, "item2", 1));
-
- std::vector requests;
-
- ItemAddRequest request1;
- request1.type = ITEM_UPDATE_USER;
- request1.payload = item1;
- request1.changes = ItemFieldChanges(true);
- requests.push_back(request1);
-
- ItemAddRequest request2;
- request2.type = ITEM_UPDATE_USER;
- request2.payload = item2;
- request2.changes = ItemFieldChanges(true);
- requests.push_back(request2);
-
- store.addItems(requests);
-
- // Both items should be added
- QVERIFY(store.getItems()->size() == 2);
- }
-
- void testItemStoreGetItem()
- {
- ItemStore store;
-
- std::shared_ptr
- item(new Item(42, "test_item", 0));
-
- ItemAddRequest request;
- request.type = ITEM_UPDATE_USER;
- request.payload = item;
- request.changes = ItemFieldChanges(true);
-
- store.addItem(request);
-
- // Get item by id
- std::shared_ptr
- found = store.getItem(42);
- QVERIFY(found != nullptr);
- QVERIFY(found->getName() == "test_item");
-
- // Get non-existent item
- std::shared_ptr
- notFound = store.getItem(999);
- QVERIFY(notFound == nullptr);
- }
-
- void testItemStoreRemoveItem()
- {
- ItemStore store;
-
- std::shared_ptr
- item(new Item(1, "test_item", 0));
-
- ItemAddRequest request;
- request.type = ITEM_UPDATE_USER;
- request.payload = item;
- request.changes = ItemFieldChanges(true);
-
- store.addItem(request);
- QVERIFY(store.getItems()->size() == 1);
-
- // Remove item
- ItemData itemData(1, "test_item", 0);
- store.removeItem(itemData);
-
- QVERIFY(store.getItems()->empty());
- }
-
- void testItemStoreClear()
- {
- ItemStore store;
-
- // Add multiple items
- for (int i = 0; i < 5; i++) {
- std::shared_ptr
- item(new Item(i, "item" + QString::number(i), 0));
- ItemAddRequest request;
- request.type = ITEM_UPDATE_USER;
- request.payload = item;
- request.changes = ItemFieldChanges(true);
- store.addItem(request);
- }
-
- QVERIFY(store.getItems()->size() == 5);
-
- // Clear all items
- store.clear();
-
- QVERIFY(store.getItems()->empty());
- }
-
- void testItemStoreUpdateItem()
- {
- ItemStore store;
-
- std::shared_ptr
- item(new Item(1, "test_item", 0));
-
- ItemAddRequest request;
- request.type = ITEM_UPDATE_USER;
- request.payload = item;
- request.changes = ItemFieldChanges(true);
-
- store.addItem(request);
-
- // Update item value
- ItemUpdateRequest update;
- update.type = ITEM_UPDATE_USER;
- ItemData updatedData(1, "test_item", 1); // value = 1
- update.payload = updatedData;
- update.changes.value = true;
-
- store.updateItem(update);
-
- // Verify value was updated
- std::shared_ptr
- found = store.getItem(1);
- QVERIFY(found->getValue() == 1);
- }
-
- void testItemStoreUpdateMultipleItems()
- {
- ItemStore store;
-
- // Add items
- for (int i = 0; i < 3; i++) {
- std::shared_ptr
- item(new Item(i, "item" + QString::number(i), 0));
- ItemAddRequest request;
- request.type = ITEM_UPDATE_USER;
- request.payload = item;
- request.changes = ItemFieldChanges(true);
- store.addItem(request);
- }
-
- // Update multiple items
- std::vector updates;
-
- for (int i = 0; i < 3; i++) {
- ItemUpdateRequest update;
- update.type = ITEM_UPDATE_USER;
- ItemData data(i, "item" + QString::number(i), 1);
- update.payload = data;
- update.changes.value = true;
- updates.push_back(update);
- }
-
- store.updateItems(updates);
-
- // Verify all values were updated
- for (int i = 0; i < 3; i++) {
- std::shared_ptr
- found = store.getItem(i);
- QVERIFY(found->getValue() == 1);
- }
- }
-
- void testItemStoreJsonSerialization()
- {
- ItemStore store;
-
- // Add items
- for (int i = 0; i < 2; i++) {
- std::shared_ptr
- item(new Item(i, "item" + QString::number(i), i));
- item->setGroupName("TestGroup");
- ItemAddRequest request;
- request.type = ITEM_UPDATE_USER;
- request.payload = item;
- request.changes = ItemFieldChanges(true);
- store.addItem(request);
- }
-
- // Serialize to JSON
- QJsonObject json;
- store.store(json);
-
- // Verify JSON contains items array
- QVERIFY(json.contains("Items"));
- QVERIFY(json["Items"].toArray().size() == 2);
- }
-
- void testItemStoreReplaceItems()
- {
- ItemStore store;
-
- // Add initial items
- std::shared_ptr
- item1(new Item(1, "item1", 0));
- ItemAddRequest request1;
- request1.type = ITEM_UPDATE_USER;
- request1.payload = item1;
- request1.changes = ItemFieldChanges(true);
- store.addItem(request1);
-
- QVERIFY(store.getItems()->size() == 1);
-
- // Replace with new items
- std::vector> newItems;
- newItems.push_back(std::shared_ptr
- (new Item(2, "new_item1", 0)));
- newItems.push_back(std::shared_ptr
- (new Item(3, "new_item2", 1)));
-
- store.replaceItems(newItems);
-
- // Should have new items
- QVERIFY(store.getItems()->size() == 2);
-
- // Old item should be removed
- QVERIFY(store.getItem(1) == nullptr);
- }
-
- void cleanupTestCase()
- {
- // Cleanup after all tests
- }
-};
-
-QTEST_APPLESS_MAIN(TestItemStore)
-
-#include "test_itemstore.moc"
\ No newline at end of file
diff --git a/tests/unit/items/test_mqttitem.cpp b/tests/unit/items/test_mqttitem.cpp
deleted file mode 100644
index 801a63e..0000000
--- a/tests/unit/items/test_mqttitem.cpp
+++ /dev/null
@@ -1,428 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include