Compare commits
8 commits
59b55d1868
...
9648c7c040
| Author | SHA1 | Date | |
|---|---|---|---|
| 9648c7c040 | |||
| 34769049f9 | |||
|
|
24c168cf64 | ||
|
|
219fbfb4c7 | ||
| 18cf2b01bd | |||
| 5cd7c782ce | |||
| 37c0c5d17b | |||
| 3e0ba165e8 |
41 changed files with 616 additions and 297 deletions
|
|
@ -10,7 +10,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
add_compile_options(-Wall)
|
add_compile_options(-Wall)
|
||||||
|
|
||||||
# Find Qt packages
|
# Find Qt packages
|
||||||
find_package(Qt6 COMPONENTS Core Gui Widgets Network Multimedia SerialPort Mqtt REQUIRED)
|
find_package(Qt6 COMPONENTS Core Gui Widgets Network Multimedia SerialPort Mqtt WebSockets REQUIRED)
|
||||||
|
|
||||||
# Find dependencies using pkg-config
|
# Find dependencies using pkg-config
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
@ -49,8 +49,12 @@ target_sources(SHinterface
|
||||||
src/service/service.cpp
|
src/service/service.cpp
|
||||||
src/service/tcpclient.h
|
src/service/tcpclient.h
|
||||||
src/service/tcpclient.cpp
|
src/service/tcpclient.cpp
|
||||||
|
src/service/server.h
|
||||||
|
src/service/server.cpp
|
||||||
src/service/tcpserver.h
|
src/service/tcpserver.h
|
||||||
src/service/tcpserver.cpp
|
src/service/tcpserver.cpp
|
||||||
|
src/service/websocketserver.h
|
||||||
|
src/service/websocketserver.cpp
|
||||||
|
|
||||||
src/actors/actor.h
|
src/actors/actor.h
|
||||||
src/actors/actor.cpp
|
src/actors/actor.cpp
|
||||||
|
|
@ -166,6 +170,7 @@ target_link_libraries(SHinterface
|
||||||
Qt6::Multimedia
|
Qt6::Multimedia
|
||||||
Qt6::SerialPort
|
Qt6::SerialPort
|
||||||
Qt6::Mqtt
|
Qt6::Mqtt
|
||||||
|
Qt6::WebSockets
|
||||||
${PIPEWIRE_LIBRARIES}
|
${PIPEWIRE_LIBRARIES}
|
||||||
${LIBNL3_LIBRARIES}
|
${LIBNL3_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
BIN
UVOSicon.bmp
BIN
UVOSicon.bmp
Binary file not shown.
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 112 KiB |
|
|
@ -17,14 +17,22 @@ Actor::~Actor()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actor::performAction()
|
void Actor::performValueAction(uint8_t value)
|
||||||
{
|
{
|
||||||
if(active)
|
if(active)
|
||||||
{
|
{
|
||||||
sigValue(triggerValue);
|
ItemUpdateRequest request;
|
||||||
|
request.type = ITEM_UPDATE_ACTOR;
|
||||||
|
request.payload = ItemData(QRandomGenerator::global()->generate(), "Item", value);
|
||||||
|
sigItemUpdate(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Actor::performAction()
|
||||||
|
{
|
||||||
|
performValueAction(triggerValue);
|
||||||
|
}
|
||||||
|
|
||||||
void Actor::makeActive()
|
void Actor::makeActive()
|
||||||
{
|
{
|
||||||
active = true;
|
active = true;
|
||||||
|
|
@ -86,9 +94,9 @@ uint8_t Actor::getTriggerValue()
|
||||||
return triggerValue;
|
return triggerValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actor::onValueChanged(uint8_t value)
|
void Actor::onItemUpdated(ItemUpdateRequest update)
|
||||||
{
|
{
|
||||||
(void)value;
|
(void) update;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Actor> Actor::createActor(const QString& type)
|
std::shared_ptr<Actor> Actor::createActor(const QString& type)
|
||||||
|
|
@ -112,9 +120,7 @@ std::shared_ptr<Actor> Actor::loadActor(const QJsonObject &json)
|
||||||
return actor;
|
return actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actor::setValue(uint8_t value)
|
void Actor::enactValue(uint8_t value)
|
||||||
{
|
{
|
||||||
Item::setValue(value);
|
|
||||||
setActive(value);
|
setActive(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,18 +19,19 @@ protected:
|
||||||
bool exausted = false;
|
bool exausted = false;
|
||||||
|
|
||||||
void performAction();
|
void performAction();
|
||||||
|
void performValueAction(uint8_t value);
|
||||||
|
|
||||||
|
virtual void enactValue(uint8_t value) override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void sigValue(uint8_t value);
|
void sigItemUpdate(ItemUpdateRequest update);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void makeActive();
|
virtual void makeActive();
|
||||||
virtual void makeInactive();
|
virtual void makeInactive();
|
||||||
virtual void setActive(uint8_t state);
|
virtual void setActive(uint8_t state);
|
||||||
virtual void onValueChanged(uint8_t state);
|
virtual void onItemUpdated(ItemUpdateRequest update);
|
||||||
|
|
||||||
virtual void setValue(uint8_t value);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Actor(QObject* parent = nullptr);
|
Actor(QObject* parent = nullptr);
|
||||||
|
|
@ -46,8 +47,8 @@ public:
|
||||||
|
|
||||||
static std::shared_ptr<Actor> createActor(const QString& type);
|
static std::shared_ptr<Actor> createActor(const QString& type);
|
||||||
|
|
||||||
virtual void store(QJsonObject& json);
|
virtual void store(QJsonObject& json) override;
|
||||||
virtual void load(const QJsonObject& json, const bool preserve = false);
|
virtual void load(const QJsonObject& json, const bool preserve = false) override;
|
||||||
static std::shared_ptr<Actor> loadActor(const QJsonObject& json);
|
static std::shared_ptr<Actor> loadActor(const QJsonObject& json);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,19 @@ MultiFactorActor::MultiFactorActor(Actor* factorActor, const uint preCancleMin,
|
||||||
preCancleMin_(preCancleMin)
|
preCancleMin_(preCancleMin)
|
||||||
{
|
{
|
||||||
activationTime.setMSecsSinceEpoch(0);
|
activationTime.setMSecsSinceEpoch(0);
|
||||||
if(factorActor) connect(factorActor, &Actor::sigValue, this, &MultiFactorActor::factorActorSlot);
|
if(factorActor)
|
||||||
|
connect(factorActor, &Actor::sigItemUpdate, this, &MultiFactorActor::factorActorSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiFactorActor::factorActorSlot(uint8_t value)
|
void MultiFactorActor::factorActorSlot(ItemUpdateRequest update)
|
||||||
{
|
{
|
||||||
if(value == factorDirection)
|
if(update.payload.getValue() == factorDirection)
|
||||||
{
|
{
|
||||||
activationTime = QDateTime::currentDateTime();
|
activationTime = QDateTime::currentDateTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiFactorActor::setValue(uint8_t value)
|
void MultiFactorActor::enactValue(uint8_t value)
|
||||||
{
|
{
|
||||||
if(value)
|
if(value)
|
||||||
{
|
{
|
||||||
|
|
@ -46,7 +47,7 @@ QString MultiFactorActor::getName() const
|
||||||
void MultiFactorActor::setFactorActor(std::shared_ptr<Actor> factorActor)
|
void MultiFactorActor::setFactorActor(std::shared_ptr<Actor> factorActor)
|
||||||
{
|
{
|
||||||
factorActor_=factorActor;
|
factorActor_=factorActor;
|
||||||
connect(factorActor_.get(), &Actor::sigValue, this, &MultiFactorActor::factorActorSlot);
|
connect(factorActor_.get(), &Actor::sigItemUpdate, this, &MultiFactorActor::factorActorSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiFactorActor::store(QJsonObject &json)
|
void MultiFactorActor::store(QJsonObject &json)
|
||||||
|
|
@ -73,7 +74,7 @@ void MultiFactorActor::load(const QJsonObject &json, bool preserve)
|
||||||
}
|
}
|
||||||
if(factorActor_)
|
if(factorActor_)
|
||||||
{
|
{
|
||||||
connect(factorActor_.get(), &Actor::sigValue, this, &MultiFactorActor::factorActorSlot);
|
connect(factorActor_.get(), &Actor::sigItemUpdate, this, &MultiFactorActor::factorActorSlot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,17 @@ private:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void factorActorSlot(uint8_t value);
|
void factorActorSlot(ItemUpdateRequest update);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
virtual void setValue(uint8_t value);
|
virtual void enactValue(uint8_t value) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MultiFactorActor(Actor* FactorActor = nullptr, const uint preCancleMin = 10, QObject *parent = nullptr);
|
MultiFactorActor(Actor* FactorActor = nullptr, const uint preCancleMin = 10, QObject *parent = nullptr);
|
||||||
|
|
||||||
virtual QString getName() const;
|
virtual QString getName() const override;
|
||||||
|
|
||||||
void setFactorActor(std::shared_ptr<Actor> factorActor);
|
void setFactorActor(std::shared_ptr<Actor> factorActor);
|
||||||
std::shared_ptr<Actor> getFactorActor()
|
std::shared_ptr<Actor> getFactorActor()
|
||||||
|
|
@ -52,8 +52,8 @@ public:
|
||||||
|
|
||||||
virtual ~MultiFactorActor() {}
|
virtual ~MultiFactorActor() {}
|
||||||
|
|
||||||
virtual void store(QJsonObject& json);
|
virtual void store(QJsonObject& json) override;
|
||||||
virtual void load(const QJsonObject& json, bool preserve);
|
virtual void load(const QJsonObject& json, bool preserve) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // REMINDERACTOR_H
|
#endif // REMINDERACTOR_H
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,8 @@ void PolynomalActor::sensorEvent(Sensor sensor)
|
||||||
+pow0_;
|
+pow0_;
|
||||||
if(result < 0) result = 0;
|
if(result < 0) result = 0;
|
||||||
else if(result > 254) result = 255;
|
else if(result > 254) result = 255;
|
||||||
if(result != prevValue)sigValue(static_cast<uint8_t>(result));
|
if(result != prevValue)
|
||||||
|
performValueAction(static_cast<uint8_t>(result));
|
||||||
prevValue = result;
|
prevValue = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +66,7 @@ void PolynomalActor::load(const QJsonObject& json, bool preserve)
|
||||||
pow2_ = json["Pow2"].toDouble(0);
|
pow2_ = json["Pow2"].toDouble(0);
|
||||||
pow1_ = json["Pow1"].toDouble(1);
|
pow1_ = json["Pow1"].toDouble(1);
|
||||||
pow0_ = json["Pow0"].toDouble(0);
|
pow0_ = json["Pow0"].toDouble(0);
|
||||||
sensor_.type = json["SensorType"].toInt(0);
|
sensor_.type = static_cast<Sensor::sensor_type_t>(json["SensorType"].toInt(0));
|
||||||
sensor_.id = json["SensorId"].toInt(0);
|
sensor_.id = json["SensorId"].toInt(0);
|
||||||
sensor_.field = json["SensorField"].toInt(0);
|
sensor_.field = json["SensorField"].toInt(0);
|
||||||
sensor_.name = json["SensorName"].toString("Sensor");
|
sensor_.name = json["SensorName"].toString("Sensor");
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,11 @@ void Regulator::sensorEvent(Sensor sensor)
|
||||||
timer.start(timeout_*1000);
|
timer.start(timeout_*1000);
|
||||||
if( sensor.field < setPoint_-band_ && (sensor.field < sensor_.field || sensor_.field > setPoint_-band_ || first) )
|
if( sensor.field < setPoint_-band_ && (sensor.field < sensor_.field || sensor_.field > setPoint_-band_ || first) )
|
||||||
{
|
{
|
||||||
sigValue(triggerValue);
|
performValueAction(triggerValue);
|
||||||
}
|
}
|
||||||
else if( sensor.field > setPoint_+band_ && (sensor.field > sensor_.field || sensor_.field < setPoint_+band_ || first) )
|
else if( sensor.field > setPoint_+band_ && (sensor.field > sensor_.field || sensor_.field < setPoint_+band_ || first) )
|
||||||
{
|
{
|
||||||
sigValue(!triggerValue);
|
performValueAction(!triggerValue);
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
sensor_ = sensor;
|
sensor_ = sensor;
|
||||||
|
|
@ -42,15 +42,14 @@ void Regulator::sensorEvent(Sensor sensor)
|
||||||
void Regulator::makeInactive()
|
void Regulator::makeInactive()
|
||||||
{
|
{
|
||||||
first = true;
|
first = true;
|
||||||
if(active)
|
performValueAction(!triggerValue);
|
||||||
sigValue(!triggerValue);
|
|
||||||
timer.stop();
|
timer.stop();
|
||||||
Actor::makeInactive();
|
Actor::makeInactive();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Regulator::timeout()
|
void Regulator::timeout()
|
||||||
{
|
{
|
||||||
sigValue(safeValue_);
|
performValueAction(safeValue_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Regulator::setPoint(float setPoint)
|
void Regulator::setPoint(float setPoint)
|
||||||
|
|
@ -100,7 +99,7 @@ void Regulator::load(const QJsonObject& json, bool preserve)
|
||||||
setPoint_ = json["SetPoint"].toDouble(22);
|
setPoint_ = json["SetPoint"].toDouble(22);
|
||||||
safeValue_ = json["SafeValue"].toDouble(0);
|
safeValue_ = json["SafeValue"].toDouble(0);
|
||||||
timeout_ = json["Timeout"].toDouble(1800);
|
timeout_ = json["Timeout"].toDouble(1800);
|
||||||
sensor_.type = json["SensorType"].toInt(0);
|
sensor_.type = static_cast<Sensor::sensor_type_t>(json["SensorType"].toInt(0));
|
||||||
sensor_.id = json["SensorId"].toInt(0);
|
sensor_.id = json["SensorId"].toInt(0);
|
||||||
sensor_.field = json["SensorField"].toInt(0);
|
sensor_.field = json["SensorField"].toInt(0);
|
||||||
sensor_.name = json["SensorName"].toString("Sensor");
|
sensor_.name = json["SensorName"].toString("Sensor");
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ void SensorActor::load(const QJsonObject& json, bool preserve)
|
||||||
Actor::load(json, preserve);
|
Actor::load(json, preserve);
|
||||||
sloap_ = json["Sloap"].toInt(0);
|
sloap_ = json["Sloap"].toInt(0);
|
||||||
threshold_ = json["Threshold"].toDouble(0);
|
threshold_ = json["Threshold"].toDouble(0);
|
||||||
sensor_.type = json["SensorType"].toInt(0);
|
sensor_.type = static_cast<Sensor::sensor_type_t>(json["SensorType"].toInt(0));
|
||||||
sensor_.id = json["SensorId"].toInt(0);
|
sensor_.id = json["SensorId"].toInt(0);
|
||||||
sensor_.field = json["SensorField"].toInt(0);
|
sensor_.field = json["SensorField"].toInt(0);
|
||||||
sensor_.name = json["SensorName"].toString("Sensor");
|
sensor_.name = json["SensorName"].toString("Sensor");
|
||||||
|
|
|
||||||
|
|
@ -10,5 +10,5 @@ FixedItemSource::FixedItemSource(Microcontroller* micro, QObject *parent):
|
||||||
|
|
||||||
void FixedItemSource::refresh()
|
void FixedItemSource::refresh()
|
||||||
{
|
{
|
||||||
gotItems({powerItem, rgbItem, auxItem});
|
gotItems({powerItem, rgbItem, auxItem}, ITEM_UPDATE_BACKEND);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,11 @@ uint8_t ItemData::getValue() const
|
||||||
return value_;
|
return value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ItemData::setValueData(uint8_t value)
|
||||||
|
{
|
||||||
|
value_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t ItemData::id() const
|
uint32_t ItemData::id() const
|
||||||
{
|
{
|
||||||
return itemId_;
|
return itemId_;
|
||||||
|
|
@ -79,7 +84,7 @@ bool ItemData::hasChanged(const ItemData& other)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ItemData::isHidden()
|
bool ItemData::isHidden() const
|
||||||
{
|
{
|
||||||
return hidden_;
|
return hidden_;
|
||||||
}
|
}
|
||||||
|
|
@ -126,6 +131,7 @@ void Item::store(QJsonObject &json)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
json["Actors"] = actorsArray;
|
json["Actors"] = actorsArray;
|
||||||
|
json["ValueType"] = type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::load(const QJsonObject &json, const bool preserve)
|
void Item::load(const QJsonObject &json, const bool preserve)
|
||||||
|
|
@ -144,28 +150,46 @@ void Item::load(const QJsonObject &json, const bool preserve)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::actorSetValue(uint8_t value)
|
Item& Item::operator=(const ItemData& other)
|
||||||
{
|
{
|
||||||
if(!override_ && (programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY))
|
name_ = other.getName();
|
||||||
setValue(value);
|
value_ = other.getValue();
|
||||||
|
itemId_ = other.id();
|
||||||
|
hidden_ = other.isHidden();
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::setValue(uint8_t value)
|
void Item::requestUpdate(ItemUpdateRequest update)
|
||||||
{
|
{
|
||||||
qDebug()<<__func__;
|
assert(update.type != ITEM_UPDATE_INVALID);
|
||||||
informValue(value);
|
if(update.type != ITEM_UPDATE_LOADED && value_ == update.payload.getValue())
|
||||||
if(programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY)
|
return;
|
||||||
enactValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Item::informValue(uint8_t value)
|
if(update.type == ITEM_UPDATE_ACTOR && override_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
qDebug()<<"Item Update Request for"<<getName()<<" type "<<update.type<<" value "<<update.payload.getValue();
|
||||||
|
|
||||||
|
if(update.type != ITEM_UPDATE_LOADED &&
|
||||||
|
update.type != ITEM_UPDATE_BACKEND &&
|
||||||
|
(programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY))
|
||||||
|
enactValue(update.payload.getValue());
|
||||||
|
|
||||||
|
if(update.type != ITEM_UPDATE_LOADED)
|
||||||
{
|
{
|
||||||
if(value_ != value)
|
value_ = update.payload.getValue();
|
||||||
{
|
|
||||||
value_ = value;
|
|
||||||
valueChanged(value_);
|
|
||||||
updated(*this);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name_ = update.payload.getName();
|
||||||
|
//itemId_ = update.payload.id();
|
||||||
|
hidden_ = update.payload.isHidden();
|
||||||
|
actors_.clear();
|
||||||
|
for(std::shared_ptr<Actor>& actor : update.newActors)
|
||||||
|
addActor(actor);
|
||||||
|
}
|
||||||
|
update.payload = *this;
|
||||||
|
updated(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::enactValue(uint8_t value)
|
void Item::enactValue(uint8_t value)
|
||||||
|
|
@ -178,8 +202,8 @@ void Item::addActor(std::shared_ptr<Actor> actor)
|
||||||
actor->setParent(this);
|
actor->setParent(this);
|
||||||
actors_.push_back(actor);
|
actors_.push_back(actor);
|
||||||
if(programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY)
|
if(programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY)
|
||||||
connect(actor.get(), &Actor::sigValue, this, &Item::actorSetValue);
|
connect(actor.get(), &Actor::sigItemUpdate, this, &Item::requestUpdate);
|
||||||
connect(this, &Item::valueChanged, actor.get(), &Actor::onValueChanged);
|
connect(this, &Item::updated, actor.get(), &Actor::onItemUpdated);
|
||||||
|
|
||||||
std::shared_ptr<SensorActor> sensorActor = std::dynamic_pointer_cast<SensorActor>(actor);
|
std::shared_ptr<SensorActor> sensorActor = std::dynamic_pointer_cast<SensorActor>(actor);
|
||||||
if(sensorActor)
|
if(sensorActor)
|
||||||
|
|
@ -238,41 +262,25 @@ void Item::setActorsActive(bool in)
|
||||||
in ? actors_[i]->makeActive() : actors_[i]->makeInactive();
|
in ? actors_[i]->makeActive() : actors_[i]->makeInactive();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::mergeLoaded(Item& item)
|
|
||||||
{
|
|
||||||
name_ = item.name_;
|
|
||||||
actors_.clear();
|
|
||||||
for(std::shared_ptr<Actor> actor : item.actors_)
|
|
||||||
addActor(actor);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Item> Item::loadItem(const QJsonObject& json)
|
std::shared_ptr<Item> Item::loadItem(const QJsonObject& json)
|
||||||
{
|
{
|
||||||
std::shared_ptr<Item> newItem = nullptr;
|
std::shared_ptr<Item> newItem = nullptr;
|
||||||
if(json["Type"].toString("") == "Relay")
|
if(json["Type"].toString("Item") == "Item")
|
||||||
{
|
newItem = std::shared_ptr<Item>(new Item);
|
||||||
|
else if(json["Type"].toString("") == "Relay")
|
||||||
newItem = std::shared_ptr<Relay>(new Relay);
|
newItem = std::shared_ptr<Relay>(new Relay);
|
||||||
}
|
|
||||||
else if(json["Type"].toString("") == "Message")
|
else if(json["Type"].toString("") == "Message")
|
||||||
{
|
|
||||||
newItem = std::shared_ptr<MessageItem>(new MessageItem);
|
newItem = std::shared_ptr<MessageItem>(new MessageItem);
|
||||||
}
|
|
||||||
else if(json["Type"].toString("") == "System")
|
else if(json["Type"].toString("") == "System")
|
||||||
{
|
|
||||||
newItem = std::shared_ptr<SystemItem>(new SystemItem);
|
newItem = std::shared_ptr<SystemItem>(new SystemItem);
|
||||||
}
|
|
||||||
else if(json["Type"].toString("") == "Aux")
|
else if(json["Type"].toString("") == "Aux")
|
||||||
{
|
|
||||||
newItem = std::shared_ptr<AuxItem>(new AuxItem);
|
newItem = std::shared_ptr<AuxItem>(new AuxItem);
|
||||||
}
|
|
||||||
else if(json["Type"].toString("") == "Power")
|
else if(json["Type"].toString("") == "Power")
|
||||||
{
|
|
||||||
newItem = std::shared_ptr<PowerItem>(new PowerItem);
|
newItem = std::shared_ptr<PowerItem>(new PowerItem);
|
||||||
}
|
|
||||||
else if(json["Type"].toString("") == "Rgb")
|
else if(json["Type"].toString("") == "Rgb")
|
||||||
{
|
|
||||||
newItem = std::shared_ptr<RgbItem>(new RgbItem);
|
newItem = std::shared_ptr<RgbItem>(new RgbItem);
|
||||||
}
|
else
|
||||||
|
qWarning()<<"Unable to load unkown item type: "<<json["Type"].toString();
|
||||||
if(newItem)
|
if(newItem)
|
||||||
{
|
{
|
||||||
newItem->load(json);
|
newItem->load(json);
|
||||||
|
|
@ -281,3 +289,15 @@ std::shared_ptr<Item> Item::loadItem(const QJsonObject& json)
|
||||||
return newItem;
|
return newItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,15 @@ typedef enum {
|
||||||
ITEM_VALUE_NO_VALUE
|
ITEM_VALUE_NO_VALUE
|
||||||
} item_value_type_t;
|
} item_value_type_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ITEM_UPDATE_USER = 0,
|
||||||
|
ITEM_UPDATE_ACTOR,
|
||||||
|
ITEM_UPDATE_REMOTE,
|
||||||
|
ITEM_UPDATE_LOADED,
|
||||||
|
ITEM_UPDATE_BACKEND,
|
||||||
|
ITEM_UPDATE_INVALID
|
||||||
|
} item_update_type_t;
|
||||||
|
|
||||||
class ItemData
|
class ItemData
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -46,9 +55,10 @@ public:
|
||||||
bool hasChanged(const ItemData& other);
|
bool hasChanged(const ItemData& other);
|
||||||
void setName(QString name);
|
void setName(QString name);
|
||||||
uint8_t getValue() const;
|
uint8_t getValue() const;
|
||||||
|
void setValueData(uint8_t value);
|
||||||
bool getLoaded() const;
|
bool getLoaded() const;
|
||||||
void setLoaded(bool loaded);
|
void setLoaded(bool loaded);
|
||||||
bool isHidden();
|
bool isHidden() const;
|
||||||
void setHidden(bool hidden);
|
void setHidden(bool hidden);
|
||||||
item_value_type_t getValueType();
|
item_value_type_t getValueType();
|
||||||
virtual QString getName() const;
|
virtual QString getName() const;
|
||||||
|
|
@ -56,24 +66,26 @@ public:
|
||||||
virtual void load(const QJsonObject& json, const bool preserve = false);
|
virtual void load(const QJsonObject& json, const bool preserve = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ItemUpdateRequest
|
||||||
|
{
|
||||||
|
item_update_type_t type = ITEM_UPDATE_INVALID;
|
||||||
|
ItemData payload;
|
||||||
|
std::vector<std::shared_ptr<Actor> > newActors;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item: public QObject, public ItemData
|
class Item: public QObject, public ItemData
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
std::vector< std::shared_ptr<Actor> > actors_;
|
std::vector< std::shared_ptr<Actor> > actors_;
|
||||||
|
|
||||||
bool override_ = false;
|
bool override_ = false;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void valueChanged(uint8_t value);
|
void updated(ItemUpdateRequest update);
|
||||||
void updated(ItemData data);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
virtual void actorSetValue(uint8_t value);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setValue(uint8_t value);
|
virtual void requestUpdate(ItemUpdateRequest update);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
@ -83,6 +95,7 @@ public:
|
||||||
|
|
||||||
virtual ~Item();
|
virtual ~Item();
|
||||||
|
|
||||||
|
Item& operator=(const ItemData& other);
|
||||||
std::vector< std::shared_ptr<Actor> >& getActors();
|
std::vector< std::shared_ptr<Actor> >& getActors();
|
||||||
bool hasActors();
|
bool hasActors();
|
||||||
void addActor(std::shared_ptr<Actor> actor);
|
void addActor(std::shared_ptr<Actor> actor);
|
||||||
|
|
@ -91,8 +104,9 @@ public:
|
||||||
void setActorsActive(bool in);
|
void setActorsActive(bool in);
|
||||||
void setOverride(const bool in);
|
void setOverride(const bool in);
|
||||||
bool getOverride();
|
bool getOverride();
|
||||||
void informValue(uint8_t value);
|
ItemUpdateRequest createValueUpdateRequest(uint8_t value,
|
||||||
void mergeLoaded(Item& item);
|
item_update_type_t type,
|
||||||
|
bool withActors = false);
|
||||||
|
|
||||||
virtual void store(QJsonObject& json);
|
virtual void store(QJsonObject& json);
|
||||||
virtual void load(const QJsonObject& json, const bool preserve = false);
|
virtual void load(const QJsonObject& json, const bool preserve = false);
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ void ItemLoaderSource::refresh()
|
||||||
qDebug()<<"Loaded item"<<newItem->getName();
|
qDebug()<<"Loaded item"<<newItem->getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gotItems(items);
|
gotItems(items, ITEM_UPDATE_LOADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemLoaderSource::updateJson(const QJsonObject& json)
|
void ItemLoaderSource::updateJson(const QJsonObject& json)
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@ public slots:
|
||||||
virtual void refresh() = 0;
|
virtual void refresh() = 0;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void gotItems(std::vector<std::shared_ptr<Item>> items, bool inform = true);
|
void gotItems(std::vector<std::shared_ptr<Item>> items, item_update_type_t updateType);
|
||||||
void requestReplaceItems(std::vector<std::shared_ptr<Item>> items);
|
void requestReplaceItems(std::vector<std::shared_ptr<Item>> items);
|
||||||
void updateItems(std::vector<ItemData> items, bool inform = true);
|
void updateItems(std::vector<ItemUpdateRequest> updates);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ITEMSOURCE_H
|
#endif // ITEMSOURCE_H
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ ItemStore::ItemStore(QObject *parent): QObject(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemStore::addItem(std::shared_ptr<Item> item, bool inform)
|
void ItemStore::addItem(const std::shared_ptr<Item>& item, item_update_type_t updateType)
|
||||||
{
|
{
|
||||||
std::shared_ptr<Item> matched = nullptr;
|
std::shared_ptr<Item> matched = nullptr;
|
||||||
for(unsigned i = 0; i < items_.size(); i++ )
|
for(unsigned i = 0; i < items_.size(); i++ )
|
||||||
|
|
@ -26,17 +26,19 @@ void ItemStore::addItem(std::shared_ptr<Item> item, bool inform)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(item->getLoaded())
|
ItemUpdateRequest request = item->createValueUpdateRequest(item->getValue(),
|
||||||
matched->mergeLoaded(*item);
|
updateType,
|
||||||
else if(item->getValue() != matched->getValue())
|
updateType == ITEM_UPDATE_LOADED);
|
||||||
updateItem(*item, inform);
|
request.newActors = item->getActors();
|
||||||
|
updateItem(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemStore::addItems(const std::vector<std::shared_ptr<Item>>& itemIn, bool inform)
|
void ItemStore::addItems(const std::vector<std::shared_ptr<Item>>& itemIn,
|
||||||
|
item_update_type_t updateType)
|
||||||
{
|
{
|
||||||
for(unsigned j = 0; j < itemIn.size(); j++)
|
for(unsigned j = 0; j < itemIn.size(); j++)
|
||||||
addItem(itemIn[j], inform);
|
addItem(itemIn[j], updateType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemStore::removeItem(const ItemData& item)
|
void ItemStore::removeItem(const ItemData& item)
|
||||||
|
|
@ -55,7 +57,8 @@ void ItemStore::removeItem(const ItemData& item)
|
||||||
|
|
||||||
void ItemStore::replaceItems(const std::vector<std::shared_ptr<Item>>& items)
|
void ItemStore::replaceItems(const std::vector<std::shared_ptr<Item>>& items)
|
||||||
{
|
{
|
||||||
addItems(items, true);
|
qDebug()<<__func__;
|
||||||
|
addItems(items, ITEM_UPDATE_LOADED);
|
||||||
std::vector<ItemData> deletedItems;
|
std::vector<ItemData> deletedItems;
|
||||||
for(std::shared_ptr<Item> item : items_)
|
for(std::shared_ptr<Item> item : items_)
|
||||||
{
|
{
|
||||||
|
|
@ -72,32 +75,20 @@ void ItemStore::clear()
|
||||||
items_.clear();
|
items_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ItemStore::updateItems(const std::vector<ItemUpdateRequest>& updates)
|
||||||
void ItemStore::updateItems(std::vector<ItemData> items, bool inform)
|
|
||||||
{
|
{
|
||||||
for(const ItemData& item : items)
|
for(const ItemUpdateRequest& update : updates)
|
||||||
updateItem(item, inform);
|
updateItem(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemStore::updateItem(const ItemData& item, bool inform)
|
void ItemStore::updateItem(const ItemUpdateRequest& update)
|
||||||
{
|
{
|
||||||
for(unsigned i = 0; i < items_.size(); i++ )
|
for(unsigned i = 0; i < items_.size(); i++ )
|
||||||
{
|
{
|
||||||
if(items_[i]->operator==(item))
|
if(items_[i]->operator==(update.payload))
|
||||||
{
|
{
|
||||||
if(items_[i]->hasChanged(item))
|
items_[i]->requestUpdate(update);
|
||||||
{
|
itemUpdated(update);
|
||||||
if(items_[i]->getValue() != item.getValue())
|
|
||||||
{
|
|
||||||
items_[i]->setLoaded(false);
|
|
||||||
if(inform)
|
|
||||||
items_[i]->informValue(item.getValue());
|
|
||||||
else
|
|
||||||
items_[i]->setValue(item.getValue());
|
|
||||||
}
|
|
||||||
qDebug()<<"Item"<<items_[i]->getName()<<"updated";
|
|
||||||
itemUpdated(items_[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -114,13 +105,9 @@ void ItemStore::store(QJsonObject& json)
|
||||||
json["Items"] = itemsArray;
|
json["Items"] = itemsArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemStore::itemUpdateSlot(ItemData data)
|
void ItemStore::itemUpdateSlot(ItemUpdateRequest update)
|
||||||
{
|
{
|
||||||
for(std::shared_ptr<Item>& item: items_)
|
itemUpdated(update);
|
||||||
{
|
|
||||||
if(*item == data)
|
|
||||||
itemUpdated(std::weak_ptr<Item>(item));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Item> ItemStore::getItem(uint32_t id)
|
std::shared_ptr<Item> ItemStore::getItem(uint32_t id)
|
||||||
|
|
|
||||||
|
|
@ -33,21 +33,21 @@ signals:
|
||||||
|
|
||||||
void itemDeleted(ItemData item);
|
void itemDeleted(ItemData item);
|
||||||
void itemAdded(std::weak_ptr<Item> Item);
|
void itemAdded(std::weak_ptr<Item> Item);
|
||||||
void itemUpdated(std::weak_ptr<Item> Item);
|
void itemUpdated(ItemUpdateRequest update);
|
||||||
void sigRefresh();
|
void sigRefresh();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void removeItem(const ItemData& item);
|
void removeItem(const ItemData& item);
|
||||||
void addItem(std::shared_ptr<Item> item, bool inform = true);
|
void addItem(const std::shared_ptr<Item>& item, item_update_type_t updateType);
|
||||||
void addItems(const std::vector<std::shared_ptr<Item>>& itemsIn, bool inform = true);
|
void addItems(const std::vector<std::shared_ptr<Item>>& itemsIn, item_update_type_t updateType);
|
||||||
void replaceItems(const std::vector<std::shared_ptr<Item>>& items);
|
void replaceItems(const std::vector<std::shared_ptr<Item>>& items);
|
||||||
void updateItems(std::vector<ItemData> items, bool inform = true);
|
void updateItems(const std::vector<ItemUpdateRequest>& updates);
|
||||||
void updateItem(const ItemData& item, bool inform = true);
|
void updateItem(const ItemUpdateRequest& update);
|
||||||
void refresh();
|
void refresh();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void itemUpdateSlot(ItemData data);
|
void itemUpdateSlot(ItemUpdateRequest update);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ItemStore globalItems;
|
extern ItemStore globalItems;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ PowerItem::PowerItem(uint32_t itemIdIn, QString name, uint8_t value, QObject* p
|
||||||
Item(itemIdIn, name, value, parent)
|
Item(itemIdIn, name, value, parent)
|
||||||
{
|
{
|
||||||
stateChanged(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 0, "Shutdown Imminent", true));
|
stateChanged(Sensor(Sensor::TYPE_SHUTDOWN_IMMINENT, 0, 0, "Shutdown Imminent", true));
|
||||||
PowerItem::setValue(true);
|
value_ = true;
|
||||||
hidden_ = true;
|
hidden_ = true;
|
||||||
type_ = ITEM_VALUE_NO_VALUE;
|
type_ = ITEM_VALUE_NO_VALUE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,21 +23,6 @@ void Relay::enactValue(uint8_t value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Relay::on()
|
|
||||||
{
|
|
||||||
setValue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Relay::off()
|
|
||||||
{
|
|
||||||
setValue(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Relay::toggle()
|
|
||||||
{
|
|
||||||
value_ ? off() : on();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Relay::store(QJsonObject& json)
|
void Relay::store(QJsonObject& json)
|
||||||
{
|
{
|
||||||
json["Type"] = "Relay";
|
json["Type"] = "Relay";
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
#include<stdint.h>
|
#include<stdint.h>
|
||||||
#include<QObject>
|
#include<QObject>
|
||||||
|
|
||||||
#include "sensors/sensor.h"
|
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
|
|
||||||
class Microcontroller;
|
class Microcontroller;
|
||||||
|
|
@ -21,11 +20,6 @@ private:
|
||||||
protected:
|
protected:
|
||||||
virtual void enactValue(uint8_t value) override;
|
virtual void enactValue(uint8_t value) override;
|
||||||
|
|
||||||
public slots:
|
|
||||||
void on();
|
|
||||||
void off();
|
|
||||||
void toggle();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Relay(uint8_t id = 0, QString name = "", uint16_t address = 0, bool state = false, QObject* parent = nullptr);
|
Relay(uint8_t id = 0, QString name = "", uint16_t address = 0, bool state = false, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
|
|
||||||
13
src/main.cpp
13
src/main.cpp
|
|
@ -35,7 +35,7 @@ int main(int argc, char *argv[])
|
||||||
parser.addOption(masterOption);
|
parser.addOption(masterOption);
|
||||||
QCommandLineOption hostOption(QStringList() << "H" << "host", QCoreApplication::translate("main", "Set server host ip addres"), "address", "0.0.0.0");
|
QCommandLineOption hostOption(QStringList() << "H" << "host", QCoreApplication::translate("main", "Set server host ip addres"), "address", "0.0.0.0");
|
||||||
parser.addOption(hostOption);
|
parser.addOption(hostOption);
|
||||||
QCommandLineOption portOption(QStringList() << "p" << "port", QCoreApplication::translate("main", "Set server Port"), "port", "104476");
|
QCommandLineOption portOption(QStringList() << "p" << "port", QCoreApplication::translate("main", "Set server Port"), "port", "38940");
|
||||||
parser.addOption(portOption);
|
parser.addOption(portOption);
|
||||||
QCommandLineOption settingsPathOption(QStringList()<<"c"<<"config", QCoreApplication::translate("main", "Set config file"), "configFilePath",
|
QCommandLineOption settingsPathOption(QStringList()<<"c"<<"config", QCoreApplication::translate("main", "Set config file"), "configFilePath",
|
||||||
QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/shinterface.json");
|
QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/shinterface.json");
|
||||||
|
|
@ -115,7 +115,12 @@ int main(int argc, char *argv[])
|
||||||
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::sigSetRgb, &mainObject.micro, &Microcontroller::changeRgbColor);
|
||||||
QObject::connect(w, &MainWindow::sigSave, &mainObject, [&mainObject, settingsPath](){mainObject.storeToDisk(settingsPath);});
|
QObject::connect(w, &MainWindow::sigSave, &mainObject, [&mainObject, settingsPath](){mainObject.storeToDisk(settingsPath);});
|
||||||
QObject::connect(w, &MainWindow::createdItem, &globalItems, [](std::shared_ptr<Item> item){globalItems.addItem(item, false);});
|
QObject::connect(w,
|
||||||
|
&MainWindow::createdItem,
|
||||||
|
&globalItems,
|
||||||
|
[](std::shared_ptr<Item> item) {
|
||||||
|
globalItems.addItem(item, ITEM_UPDATE_USER);
|
||||||
|
});
|
||||||
w->show();
|
w->show();
|
||||||
}
|
}
|
||||||
retVal = a.exec();
|
retVal = a.exec();
|
||||||
|
|
@ -127,7 +132,9 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
SecondaryMainObject mainObject(parser.value(hostOption), parser.value(portOption).toInt());
|
SecondaryMainObject mainObject(parser.value(hostOption), parser.value(portOption).toInt());
|
||||||
MainWindow w(&mainObject);
|
MainWindow w(&mainObject);
|
||||||
QObject::connect(&w, &MainWindow::createdItem, &globalItems, [](std::shared_ptr<Item> item){globalItems.addItem(item, false);});
|
QObject::connect(&w, &MainWindow::createdItem, &globalItems, [](std::shared_ptr<Item> item) {
|
||||||
|
globalItems.addItem(item, ITEM_UPDATE_USER);
|
||||||
|
});
|
||||||
QObject::connect(&w, &MainWindow::sigSave, mainObject.tcpClient, &TcpClient::sendItems);
|
QObject::connect(&w, &MainWindow::sigSave, mainObject.tcpClient, &TcpClient::sendItems);
|
||||||
w.show();
|
w.show();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,13 +72,15 @@ PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, const QString& sett
|
||||||
MainObject(parent),
|
MainObject(parent),
|
||||||
settingsPath(settingsPath),
|
settingsPath(settingsPath),
|
||||||
micro(microDevice),
|
micro(microDevice),
|
||||||
tcpServer(new TcpServer),
|
tcpServer(new TcpServer(this)),
|
||||||
|
webServer(new WebSocketServer("shinterface", this)),
|
||||||
sunSensorSource(49.824972, 8.702194),
|
sunSensorSource(49.824972, 8.702194),
|
||||||
fixedItems(µ)
|
fixedItems(µ)
|
||||||
{
|
{
|
||||||
//connect sensors subsystem
|
//connect sensors subsystem
|
||||||
connect(&globalSensors, &SensorStore::sensorChangedState, tcpServer, &TcpServer::sensorEvent);
|
connect(&globalSensors, &SensorStore::sensorChangedState, tcpServer, &TcpServer::sensorEvent);
|
||||||
connect(tcpServer, &TcpServer::gotSensor, &globalSensors, &SensorStore::sensorGotState);
|
connect(tcpServer, &TcpServer::gotSensor, &globalSensors, &SensorStore::sensorGotState);
|
||||||
|
connect(webServer, &WebSocketServer::gotSensor, &globalSensors, &SensorStore::sensorGotState);
|
||||||
connect(&sunSensorSource, &SunSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState);
|
connect(&sunSensorSource, &SunSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState);
|
||||||
connect(µ, &Microcontroller::gotSensorState, &globalSensors, &SensorStore::sensorGotState);
|
connect(µ, &Microcontroller::gotSensorState, &globalSensors, &SensorStore::sensorGotState);
|
||||||
connect(&mqttSensorSource, &MqttSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState);
|
connect(&mqttSensorSource, &MqttSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState);
|
||||||
|
|
@ -87,6 +89,7 @@ PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, const QString& sett
|
||||||
|
|
||||||
globalItems.registerItemSource(&fixedItems);
|
globalItems.registerItemSource(&fixedItems);
|
||||||
globalItems.registerItemSource(tcpServer);
|
globalItems.registerItemSource(tcpServer);
|
||||||
|
globalItems.registerItemSource(webServer);
|
||||||
globalItems.registerItemSource(µ);
|
globalItems.registerItemSource(µ);
|
||||||
globalItems.registerItemSource(&itemLoader);
|
globalItems.registerItemSource(&itemLoader);
|
||||||
|
|
||||||
|
|
@ -98,7 +101,9 @@ PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, const QString& sett
|
||||||
mqttSensorSource.start(mqttJson);
|
mqttSensorSource.start(mqttJson);
|
||||||
|
|
||||||
tcpServer->launch(QHostAddress(host), port);
|
tcpServer->launch(QHostAddress(host), port);
|
||||||
|
webServer->launch(QHostAddress(host), port+1);
|
||||||
connect(&globalItems, &ItemStore::itemUpdated, tcpServer, &TcpServer::itemUpdated);
|
connect(&globalItems, &ItemStore::itemUpdated, tcpServer, &TcpServer::itemUpdated);
|
||||||
|
connect(&globalItems, &ItemStore::itemUpdated, webServer, &WebSocketServer::itemUpdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimaryMainObject::~PrimaryMainObject()
|
PrimaryMainObject::~PrimaryMainObject()
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
#include "items/itemloadersource.h"
|
#include "items/itemloadersource.h"
|
||||||
#include "service/tcpclient.h"
|
#include "service/tcpclient.h"
|
||||||
#include "service/tcpserver.h"
|
#include "service/tcpserver.h"
|
||||||
|
#include "service/websocketserver.h"
|
||||||
|
|
||||||
class MainObject : public QObject
|
class MainObject : public QObject
|
||||||
{
|
{
|
||||||
|
|
@ -44,6 +45,7 @@ public:
|
||||||
|
|
||||||
Microcontroller micro;
|
Microcontroller micro;
|
||||||
TcpServer* tcpServer;
|
TcpServer* tcpServer;
|
||||||
|
WebSocketServer* webServer;
|
||||||
|
|
||||||
//sensors
|
//sensors
|
||||||
SunSensorSource sunSensorSource;
|
SunSensorSource sunSensorSource;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
#include "microcontroller.h"
|
#include "microcontroller.h"
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
void Microcontroller::relayToggle(int state, int relay)
|
void Microcontroller::relayToggle(int state, int relay)
|
||||||
{
|
{
|
||||||
char buffer[8];
|
char buffer[8];
|
||||||
|
|
@ -49,22 +46,34 @@ void Microcontroller::setAuxPwm(int duty)
|
||||||
|
|
||||||
void Microcontroller::write(const QByteArray& buffer)
|
void Microcontroller::write(const QByteArray& buffer)
|
||||||
{
|
{
|
||||||
if(_port != nullptr)
|
writeQue.enqueue(buffer);
|
||||||
|
if(!writeTimer.isActive())
|
||||||
{
|
{
|
||||||
_port->write(buffer);
|
writeTimer.setInterval(0);
|
||||||
_port->waitForBytesWritten(1000);
|
writeTimer.start();
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Microcontroller::write(char* buffer, const size_t length)
|
void Microcontroller::write(char* buffer, const size_t length)
|
||||||
{
|
{
|
||||||
if(_port != nullptr)
|
write(QByteArray(buffer, length));
|
||||||
{
|
}
|
||||||
_port->write(buffer, length);
|
|
||||||
_port->waitForBytesWritten(1000);
|
void Microcontroller::onWriteTimerTimeout()
|
||||||
|
{
|
||||||
|
writeTimer.setInterval(50);
|
||||||
|
if(connected())
|
||||||
|
{
|
||||||
|
if(!writeQue.empty())
|
||||||
|
{
|
||||||
|
QByteArray data = writeQue.dequeue();
|
||||||
|
_port->write(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeTimer.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Microcontroller::setPattern(int pattern)
|
void Microcontroller::setPattern(int pattern)
|
||||||
|
|
@ -82,8 +91,10 @@ void Microcontroller::startSunrise()
|
||||||
|
|
||||||
bool Microcontroller::connected()
|
bool Microcontroller::connected()
|
||||||
{
|
{
|
||||||
if(_port != nullptr) return _port->isOpen();
|
if(_port != nullptr)
|
||||||
else return false;
|
return _port->isOpen();
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Microcontroller::refresh()
|
void Microcontroller::refresh()
|
||||||
|
|
@ -93,13 +104,17 @@ void Microcontroller::refresh()
|
||||||
|
|
||||||
//housekeeping
|
//housekeeping
|
||||||
|
|
||||||
Microcontroller::Microcontroller(QIODevice* port)
|
Microcontroller::Microcontroller(QIODevice* port): Microcontroller()
|
||||||
{
|
{
|
||||||
setIODevice(port);
|
setIODevice(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
Microcontroller::Microcontroller()
|
Microcontroller::Microcontroller()
|
||||||
{
|
{
|
||||||
|
writeTimer.setInterval(50);
|
||||||
|
writeTimer.setSingleShot(false);
|
||||||
|
connect(&writeTimer, &QTimer::timeout, this, &Microcontroller::onWriteTimerTimeout);
|
||||||
|
qDebug()<<__func__<<writeTimer.isActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
Microcontroller::~Microcontroller()
|
Microcontroller::~Microcontroller()
|
||||||
|
|
@ -142,7 +157,7 @@ void Microcontroller::processList(const QString& buffer)
|
||||||
else if(buffer.contains("EOL"))
|
else if(buffer.contains("EOL"))
|
||||||
{
|
{
|
||||||
listMode = false;
|
listMode = false;
|
||||||
gotItems(relayList);
|
gotItems(relayList, ITEM_UPDATE_BACKEND);
|
||||||
relayList.clear();
|
relayList.clear();
|
||||||
}
|
}
|
||||||
else listMode = false;
|
else listMode = false;
|
||||||
|
|
@ -150,7 +165,10 @@ void Microcontroller::processList(const QString& buffer)
|
||||||
|
|
||||||
void Microcontroller::processRelayState(const QString& buffer)
|
void Microcontroller::processRelayState(const QString& buffer)
|
||||||
{
|
{
|
||||||
updateItems({static_cast<ItemData>(*processRelayLine(buffer))});
|
ItemUpdateRequest update;
|
||||||
|
update.type = ITEM_UPDATE_BACKEND;
|
||||||
|
update.payload = static_cast<ItemData>(*processRelayLine(buffer));
|
||||||
|
updateItems({update});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Microcontroller::processSensorState(const QString& buffer)
|
void Microcontroller::processSensorState(const QString& buffer)
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QRunnable>
|
#include <QRunnable>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QEventLoop>
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QAbstractButton>
|
#include <QByteArray>
|
||||||
|
#include <QQueue>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "items/item.h"
|
#include "items/item.h"
|
||||||
|
|
@ -32,13 +32,12 @@ private:
|
||||||
|
|
||||||
bool listMode = false;
|
bool listMode = false;
|
||||||
|
|
||||||
//uint8_t _auxState = 0;
|
|
||||||
|
|
||||||
QIODevice* _port = nullptr;
|
QIODevice* _port = nullptr;
|
||||||
|
QQueue<QByteArray> writeQue;
|
||||||
|
QTimer writeTimer;
|
||||||
|
|
||||||
std::vector< std::shared_ptr<Item> > relayList;
|
std::vector< std::shared_ptr<Item> > relayList;
|
||||||
|
|
||||||
QScopedPointer<QEventLoop> loop;
|
|
||||||
QString _buffer;
|
QString _buffer;
|
||||||
|
|
||||||
void processMicroReturn();
|
void processMicroReturn();
|
||||||
|
|
@ -75,6 +74,7 @@ public slots:
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void isReadyRead();
|
void isReadyRead();
|
||||||
|
void onWriteTimerTimeout();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void textRecived(const QString string);
|
void textRecived(const QString string);
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ SensorStore globalSensors;
|
||||||
|
|
||||||
SensorStore::SensorStore(QObject *parent): QObject(parent)
|
SensorStore::SensorStore(QObject *parent): QObject(parent)
|
||||||
{
|
{
|
||||||
sensors_.push_back(Sensor(0,1,0,"Front door"));
|
sensors_.push_back(Sensor(Sensor::TYPE_DOOR,1,0,"Front door"));
|
||||||
sensors_.push_back(Sensor(0,0,0,"Bedroom door"));
|
sensors_.push_back(Sensor(Sensor::TYPE_DOOR,0,0,"Bedroom door"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SensorStore::sensorGotState(const Sensor& sensor)
|
void SensorStore::sensorGotState(const Sensor& sensor)
|
||||||
|
|
|
||||||
|
|
@ -10,32 +10,34 @@ class Sensor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static constexpr uint8_t TYPE_DOOR = 0;
|
typedef enum {
|
||||||
static constexpr uint8_t TYPE_TEMPERATURE = 1;
|
TYPE_DOOR = 0,
|
||||||
static constexpr uint8_t TYPE_HUMIDITY = 2;
|
TYPE_TEMPERATURE,
|
||||||
static constexpr uint8_t TYPE_PRESSURE = 3;
|
TYPE_HUMIDITY,
|
||||||
static constexpr uint8_t TYPE_BRIGHTNESS = 4;
|
TYPE_PRESSURE,
|
||||||
static constexpr uint8_t TYPE_BUTTON = 5;
|
TYPE_BRIGHTNESS,
|
||||||
static constexpr uint8_t TYPE_ADC = 6;
|
TYPE_BUTTON,
|
||||||
static constexpr uint8_t TYPE_CO2 = 7;
|
TYPE_ADC,
|
||||||
static constexpr uint8_t TYPE_FORMALDEHYD= 8;
|
TYPE_CO2,
|
||||||
static constexpr uint8_t TYPE_PM25 = 9;
|
TYPE_FORMALDEHYD,
|
||||||
static constexpr uint8_t TYPE_TOTAL_VOC = 10;
|
TYPE_PM25,
|
||||||
static constexpr uint8_t TYPE_LOWBATTERY = 128;
|
TYPE_TOTAL_VOC,
|
||||||
static constexpr uint8_t TYPE_SHUTDOWN_IMMINENT = 251;
|
TYPE_LOWBATTERY = 128,
|
||||||
static constexpr uint8_t TYPE_OCUPANCY = 252;
|
TYPE_SHUTDOWN_IMMINENT = 251,
|
||||||
static constexpr uint8_t TYPE_SUN_ALTITUDE = 253;
|
TYPE_OCUPANCY,
|
||||||
static constexpr uint8_t TYPE_AUDIO_OUTPUT = 254;
|
TYPE_SUN_ALTITUDE,
|
||||||
static constexpr uint8_t TYPE_DUMMY = 255;
|
TYPE_AUDIO_OUTPUT,
|
||||||
|
TYPE_DUMMY,
|
||||||
|
} sensor_type_t;
|
||||||
|
|
||||||
uint8_t type;
|
sensor_type_t type;
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
float field;
|
float field;
|
||||||
QString name;
|
QString name;
|
||||||
QDateTime lastSeen;
|
QDateTime lastSeen;
|
||||||
bool hidden;
|
bool hidden;
|
||||||
|
|
||||||
Sensor(uint64_t typeIn, uint8_t idIn, float fieldIn = 0, QString nameIn = "", bool hiddenIn = false): type(typeIn),
|
Sensor(sensor_type_t typeIn, uint64_t idIn, float fieldIn = 0, QString nameIn = "", bool hiddenIn = false): type(typeIn),
|
||||||
id(idIn), field(fieldIn), name(nameIn), hidden(hiddenIn)
|
id(idIn), field(fieldIn), name(nameIn), hidden(hiddenIn)
|
||||||
{
|
{
|
||||||
lastSeen = QDateTime::currentDateTime();
|
lastSeen = QDateTime::currentDateTime();
|
||||||
|
|
@ -48,12 +50,14 @@ public:
|
||||||
}
|
}
|
||||||
Sensor(const QJsonObject& json)
|
Sensor(const QJsonObject& json)
|
||||||
{
|
{
|
||||||
type = json["SensorType"].toInt(0);
|
type = static_cast<sensor_type_t>(json["SensorType"].toInt(0));
|
||||||
id = json["Id"].toInt(0);
|
id = json["Id"].toInt(0);
|
||||||
field = json["Field"].toDouble(0);
|
field = json["Field"].toDouble(0);
|
||||||
name = json["Name"].toString("Sensor");
|
|
||||||
lastSeen = QDateTime::fromString(json["LastSeen"].toString(""));
|
lastSeen = QDateTime::fromString(json["LastSeen"].toString(""));
|
||||||
hidden = json["Hidden"].toBool(false);
|
hidden = json["Hidden"].toBool(false);
|
||||||
|
name = json["Name"].toString();
|
||||||
|
if(name == "")
|
||||||
|
generateName();
|
||||||
}
|
}
|
||||||
inline bool operator==(const Sensor& in) const
|
inline bool operator==(const Sensor& in) const
|
||||||
{
|
{
|
||||||
|
|
@ -72,7 +76,7 @@ public:
|
||||||
QStringList bufferList = str.split(' ');
|
QStringList bufferList = str.split(' ');
|
||||||
if(bufferList.size() >= 7)
|
if(bufferList.size() >= 7)
|
||||||
{
|
{
|
||||||
Sensor sensor(bufferList[2].toUInt(), bufferList[4].toUInt(), bufferList[6].toUInt());
|
Sensor sensor(static_cast<sensor_type_t>(bufferList[2].toUInt()), bufferList[4].toUInt(), bufferList[6].toUInt());
|
||||||
if(sensor.type == Sensor::TYPE_HUMIDITY || sensor.type == Sensor::TYPE_TEMPERATURE)
|
if(sensor.type == Sensor::TYPE_HUMIDITY || sensor.type == Sensor::TYPE_TEMPERATURE)
|
||||||
sensor.field = sensor.field/10;
|
sensor.field = sensor.field/10;
|
||||||
|
|
||||||
|
|
@ -100,6 +104,7 @@ public:
|
||||||
json["Name"] = name;
|
json["Name"] = name;
|
||||||
json["LastSeen"] = lastSeen.toString();
|
json["LastSeen"] = lastSeen.toString();
|
||||||
json["Hidden"] = hidden;
|
json["Hidden"] = hidden;
|
||||||
|
json["Unit"] = getUnit();
|
||||||
}
|
}
|
||||||
inline void generateName()
|
inline void generateName()
|
||||||
{
|
{
|
||||||
|
|
@ -119,6 +124,31 @@ public:
|
||||||
name = "Shutdown Imminent";
|
name = "Shutdown Imminent";
|
||||||
else name = "Sensor Type " + QString::number(type) + " Id " + QString::number(id);
|
else name = "Sensor Type " + QString::number(type) + " Id " + QString::number(id);
|
||||||
}
|
}
|
||||||
|
QString getUnit()
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case TYPE_TEMPERATURE:
|
||||||
|
return "°C";
|
||||||
|
case TYPE_HUMIDITY:
|
||||||
|
return "%";
|
||||||
|
case TYPE_PRESSURE:
|
||||||
|
return "hPa";
|
||||||
|
case TYPE_BRIGHTNESS:
|
||||||
|
return "lx";
|
||||||
|
case TYPE_CO2:
|
||||||
|
return "ppm";
|
||||||
|
case TYPE_FORMALDEHYD:
|
||||||
|
case TYPE_PM25:
|
||||||
|
return "µg/m³";
|
||||||
|
case TYPE_TOTAL_VOC:
|
||||||
|
return "ppb";
|
||||||
|
case TYPE_SUN_ALTITUDE:
|
||||||
|
return "°";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SensorStore: public QObject
|
class SensorStore: public QObject
|
||||||
|
|
|
||||||
104
src/service/server.cpp
Normal file
104
src/service/server.cpp
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
#include <QAbstractSocket>
|
||||||
|
#include <QWebSocket>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
#include "items/item.h"
|
||||||
|
#include "service.h"
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
Server::Server(QObject* parent)
|
||||||
|
: Service(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Server::~Server()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::processIncomeingJson(const QByteArray& jsonbytes)
|
||||||
|
{
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(jsonbytes);
|
||||||
|
QJsonObject json = doc.object();
|
||||||
|
QString type = json["MessageType"].toString();
|
||||||
|
if(type == "ItemUpdate")
|
||||||
|
{
|
||||||
|
QJsonArray data = json["Data"].toArray();
|
||||||
|
bool FullList = json["FullList"].toBool(false);
|
||||||
|
std::vector<std::shared_ptr<Item>> items;
|
||||||
|
for(QJsonValueRef itemjson : data)
|
||||||
|
{
|
||||||
|
QJsonObject jsonobject = itemjson.toObject();
|
||||||
|
std::shared_ptr<Item> item = Item::loadItem(jsonobject);
|
||||||
|
if(item)
|
||||||
|
{
|
||||||
|
qDebug()<<"Server got item"<<item->getName();
|
||||||
|
item->setLoaded(FullList);
|
||||||
|
items.push_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(FullList && !items.empty())
|
||||||
|
{
|
||||||
|
requestReplaceItems(items);
|
||||||
|
sigRequestSave();
|
||||||
|
}
|
||||||
|
else if(!items.empty())
|
||||||
|
{
|
||||||
|
gotItems(items, ITEM_UPDATE_REMOTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Service::processIncomeingJson(jsonbytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::handleSocketError()
|
||||||
|
{
|
||||||
|
QObject* obj = sender();
|
||||||
|
if (obj) {
|
||||||
|
removeClient(static_cast<QTcpSocket*>(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::handleSocketDisconnect()
|
||||||
|
{
|
||||||
|
QObject* obj = sender();
|
||||||
|
if (obj) {
|
||||||
|
removeClient(static_cast<QTcpSocket*>(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::removeClient(QTcpSocket* socket)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < clients.size(); i++)
|
||||||
|
{
|
||||||
|
if(clients[i].socket.tcpSocket == socket)
|
||||||
|
{
|
||||||
|
clients.erase(clients.begin() + i);
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::removeClient(QWebSocket* socket)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < clients.size(); i++)
|
||||||
|
{
|
||||||
|
if(clients[i].socket.webSocket == socket)
|
||||||
|
{
|
||||||
|
clients.erase(clients.begin() + i);
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::itemUpdated(ItemUpdateRequest update)
|
||||||
|
{
|
||||||
|
QJsonArray items;
|
||||||
|
QJsonObject itemjson;
|
||||||
|
update.payload.store(itemjson);
|
||||||
|
items.append(itemjson);
|
||||||
|
QJsonObject json = createMessage("ItemUpdate", items);
|
||||||
|
json["FullList"] = false;
|
||||||
|
sendJson(json);
|
||||||
|
}
|
||||||
52
src/service/server.h
Normal file
52
src/service/server.h
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef SERVER_BASE_H
|
||||||
|
#define SERVER_BASE_H
|
||||||
|
|
||||||
|
#include <QTcpServer>
|
||||||
|
#include <QWebSocket>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "service.h"
|
||||||
|
|
||||||
|
class Server : public Service
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
STATE_IDLE,
|
||||||
|
STATE_RECV_JSON,
|
||||||
|
} client_state_t;
|
||||||
|
|
||||||
|
struct Client
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
QTcpSocket* tcpSocket;
|
||||||
|
QWebSocket* webSocket;
|
||||||
|
} socket;
|
||||||
|
QByteArray buffer;
|
||||||
|
client_state_t state = STATE_IDLE;
|
||||||
|
long long recievebytes = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Client> clients;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
virtual void itemUpdated(ItemUpdateRequest update) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Server(QObject* parent = nullptr);
|
||||||
|
virtual ~Server();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void processIncomeingJson(const QByteArray& jsonbytes) override;
|
||||||
|
void handleSocketError();
|
||||||
|
void handleSocketDisconnect();
|
||||||
|
void removeClient(QTcpSocket* socket);
|
||||||
|
void removeClient(QWebSocket* socket);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void sigRequestSave();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SERVER_BASE_H
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "items/item.h"
|
#include "items/item.h"
|
||||||
#include "items/itemstore.h"
|
#include "items/itemstore.h"
|
||||||
|
|
@ -30,17 +29,7 @@ void Service::sensorEvent(Sensor sensor)
|
||||||
sendJson(json);
|
sendJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Service::itemUpdated(std::weak_ptr<Item> item)
|
void Service::itemUpdated(ItemUpdateRequest update) {}
|
||||||
{
|
|
||||||
qDebug()<<__func__;
|
|
||||||
QJsonArray items;
|
|
||||||
QJsonObject itemjson;
|
|
||||||
item.lock()->store(itemjson);
|
|
||||||
items.append(itemjson);
|
|
||||||
QJsonObject json = createMessage("ItemUpdate", items);
|
|
||||||
json["FullList"] = false;
|
|
||||||
sendJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Service::refresh()
|
void Service::refresh()
|
||||||
{
|
{
|
||||||
|
|
@ -78,7 +67,6 @@ void Service::sendItems()
|
||||||
void Service::processIncomeingJson(const QByteArray& jsonbytes)
|
void Service::processIncomeingJson(const QByteArray& jsonbytes)
|
||||||
{
|
{
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(jsonbytes);
|
QJsonDocument doc = QJsonDocument::fromJson(jsonbytes);
|
||||||
qDebug()<<"Got Json:"<<QString::fromLatin1(doc.toJson(QJsonDocument::JsonFormat::Indented));
|
|
||||||
QJsonObject json = doc.object();
|
QJsonObject json = doc.object();
|
||||||
QString type = json["MessageType"].toString();
|
QString type = json["MessageType"].toString();
|
||||||
if(type == "GetSensors")
|
if(type == "GetSensors")
|
||||||
|
|
@ -94,6 +82,7 @@ void Service::processIncomeingJson(const QByteArray& jsonbytes)
|
||||||
else if(type == "SensorUpdate")
|
else if(type == "SensorUpdate")
|
||||||
{
|
{
|
||||||
QJsonArray data = json["Data"].toArray();
|
QJsonArray data = json["Data"].toArray();
|
||||||
|
qWarning()<<"Got sensor update with no/empty sensors array";
|
||||||
for(QJsonValueRef sensorjson : data)
|
for(QJsonValueRef sensorjson : data)
|
||||||
{
|
{
|
||||||
QJsonObject jsonobject = sensorjson.toObject();
|
QJsonObject jsonobject = sensorjson.toObject();
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ signals:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void sensorEvent(Sensor sensor);
|
void sensorEvent(Sensor sensor);
|
||||||
void itemUpdated(std::weak_ptr<Item> item);
|
virtual void itemUpdated(ItemUpdateRequest update);
|
||||||
virtual void refresh() override;
|
virtual void refresh() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ void TcpClient::processIncomeingJson(const QByteArray& jsonbytes)
|
||||||
QString type = json["MessageType"].toString();
|
QString type = json["MessageType"].toString();
|
||||||
if(type == "ItemUpdate")
|
if(type == "ItemUpdate")
|
||||||
{
|
{
|
||||||
std::cout<<"Got item json:\n"<<QString::fromLatin1(jsonbytes).toStdString();
|
|
||||||
QJsonArray data = json["Data"].toArray();
|
QJsonArray data = json["Data"].toArray();
|
||||||
std::vector<std::shared_ptr<Item>> items;
|
std::vector<std::shared_ptr<Item>> items;
|
||||||
for(QJsonValueRef itemjson : data)
|
for(QJsonValueRef itemjson : data)
|
||||||
|
|
@ -42,12 +41,13 @@ void TcpClient::processIncomeingJson(const QByteArray& jsonbytes)
|
||||||
std::shared_ptr<Item> item = Item::loadItem(jsonobject);
|
std::shared_ptr<Item> item = Item::loadItem(jsonobject);
|
||||||
if(item)
|
if(item)
|
||||||
{
|
{
|
||||||
|
qDebug()<<"Client got item"<<item->getName();
|
||||||
item->setLoaded(false);
|
item->setLoaded(false);
|
||||||
items.push_back(item);
|
items.push_back(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!items.empty())
|
if(!items.empty())
|
||||||
gotItems(items, true);
|
gotItems(items, ITEM_UPDATE_REMOTE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -94,6 +94,20 @@ void TcpClient::socketReadyRead()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TcpClient::itemUpdated(ItemUpdateRequest update)
|
||||||
|
{
|
||||||
|
if(update.type == ITEM_UPDATE_USER)
|
||||||
|
{
|
||||||
|
QJsonArray items;
|
||||||
|
QJsonObject itemjson;
|
||||||
|
update.payload.store(itemjson);
|
||||||
|
items.append(itemjson);
|
||||||
|
QJsonObject json = createMessage("ItemUpdate", items);
|
||||||
|
json["FullList"] = false;
|
||||||
|
sendJson(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TcpClient::~TcpClient()
|
TcpClient::~TcpClient()
|
||||||
{
|
{
|
||||||
delete socket;
|
delete socket;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@ class TcpClient : public Service
|
||||||
long long recievebytes = 0;
|
long long recievebytes = 0;
|
||||||
QByteArray buffer;
|
QByteArray buffer;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
virtual void itemUpdated(ItemUpdateRequest update) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TcpClient(QObject* parent = nullptr);
|
TcpClient(QObject* parent = nullptr);
|
||||||
~TcpClient();
|
~TcpClient();
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
|
||||||
#include "items/item.h"
|
#include "items/item.h"
|
||||||
#include "service.h"
|
#include "server.h"
|
||||||
#include "tcpserver.h"
|
#include "tcpserver.h"
|
||||||
|
|
||||||
TcpServer::TcpServer(QObject* parent):
|
TcpServer::TcpServer(QObject* parent):
|
||||||
Service(parent),
|
Server(parent),
|
||||||
server(this)
|
server(this)
|
||||||
{
|
{
|
||||||
connect(&server, &QTcpServer::newConnection, this, &TcpServer::incomingConnection);
|
connect(&server, &QTcpServer::newConnection, this, &TcpServer::incomingConnection);
|
||||||
|
|
@ -16,50 +16,23 @@ TcpServer::TcpServer(QObject* parent):
|
||||||
|
|
||||||
void TcpServer::sendJson(const QJsonObject& json)
|
void TcpServer::sendJson(const QJsonObject& json)
|
||||||
{
|
{
|
||||||
for(auto client: clients)
|
for(auto& client: clients)
|
||||||
{
|
{
|
||||||
|
if(client.socket.tcpSocket) {
|
||||||
QByteArray jsonData = QJsonDocument(json).toJson();
|
QByteArray jsonData = QJsonDocument(json).toJson();
|
||||||
client.socket->write(QString("MSG JSON LEN " + QString::number(jsonData.size()) + "\n").toLatin1() + jsonData);
|
client.socket.tcpSocket->write(QString("MSG JSON LEN " + QString::number(jsonData.size()) + "\n").toLatin1() + jsonData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcpServer::processIncomeingJson(const QByteArray& jsonbytes)
|
void TcpServer::processIncomeingJson(const QByteArray& jsonbytes)
|
||||||
{
|
{
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(jsonbytes);
|
Server::processIncomeingJson(jsonbytes);
|
||||||
QJsonObject json = doc.object();
|
|
||||||
QString type = json["MessageType"].toString();
|
|
||||||
if(type == "ItemUpdate")
|
|
||||||
{
|
|
||||||
qDebug()<<"Got Items";
|
|
||||||
QJsonArray data = json["Data"].toArray();
|
|
||||||
bool FullList = json["FullList"].toBool(false);
|
|
||||||
std::vector<std::shared_ptr<Item>> items;
|
|
||||||
for(QJsonValueRef itemjson : data)
|
|
||||||
{
|
|
||||||
QJsonObject jsonobject = itemjson.toObject();
|
|
||||||
std::shared_ptr<Item> item = Item::loadItem(jsonobject);
|
|
||||||
item->setLoaded(FullList);
|
|
||||||
if(item)
|
|
||||||
items.push_back(item);
|
|
||||||
}
|
|
||||||
if(FullList && !items.empty())
|
|
||||||
{
|
|
||||||
requestReplaceItems(items);
|
|
||||||
sigRequestSave();
|
|
||||||
}
|
|
||||||
else if(!items.empty())
|
|
||||||
{
|
|
||||||
gotItems(items, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Service::processIncomeingJson(jsonbytes);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TcpServer::launch(const QHostAddress &address, quint16 port)
|
bool TcpServer::launch(const QHostAddress &address, quint16 port)
|
||||||
{
|
{
|
||||||
|
qInfo()<<"Tcp server launched on"<<address<<"port"<<port;
|
||||||
return server.listen(address, port);
|
return server.listen(address, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,38 +44,16 @@ void TcpServer::incomingConnection()
|
||||||
qDebug()<<"Got new client from"<<client->peerAddress().toString();
|
qDebug()<<"Got new client from"<<client->peerAddress().toString();
|
||||||
if(client)
|
if(client)
|
||||||
{
|
{
|
||||||
clients.push_back({client});
|
Client c;
|
||||||
connect(client, &QTcpSocket::errorOccurred, this, &TcpServer::socketError);
|
c.socket.tcpSocket = client;
|
||||||
connect(client, &QTcpSocket::disconnected, this, &TcpServer::socketDisconnect);
|
clients.push_back(c);
|
||||||
|
connect(client, &QTcpSocket::errorOccurred, this, [this, client]() { removeClient(client); });
|
||||||
|
connect(client, &QTcpSocket::disconnected, this, [this, client]() { removeClient(client); });
|
||||||
connect(client, &QTcpSocket::readyRead, this, &TcpServer::socketReadyRead);
|
connect(client, &QTcpSocket::readyRead, this, &TcpServer::socketReadyRead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcpServer::socketError(QAbstractSocket::SocketError socketError)
|
|
||||||
{
|
|
||||||
(void)socketError;
|
|
||||||
for(size_t i = 0; i < clients.size(); i++)
|
|
||||||
{
|
|
||||||
if(clients[i].socket == TcpServer::sender())
|
|
||||||
{
|
|
||||||
clients.erase(clients.begin()+i);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void TcpServer::socketDisconnect()
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < clients.size(); i++)
|
|
||||||
{
|
|
||||||
if(clients[i].socket == TcpServer::sender())
|
|
||||||
{
|
|
||||||
clients.erase(clients.begin()+i);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TcpServer::processComand(const QByteArray& command, Client& client)
|
void TcpServer::processComand(const QByteArray& command, Client& client)
|
||||||
{
|
{
|
||||||
if(command.startsWith("MSG JSON LEN "))
|
if(command.startsWith("MSG JSON LEN "))
|
||||||
|
|
@ -117,15 +68,15 @@ void TcpServer::socketReadyRead()
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < clients.size(); i++)
|
for(size_t i = 0; i < clients.size(); i++)
|
||||||
{
|
{
|
||||||
if(clients[i].socket == sender())
|
QTcpSocket* tcp = clients[i].socket.tcpSocket;
|
||||||
|
if(tcp && tcp == sender())
|
||||||
{
|
{
|
||||||
QByteArray newChars = clients[i].socket->readAll();
|
QByteArray newChars = tcp->readAll();
|
||||||
clients[i].buffer += newChars;
|
clients[i].buffer += newChars;
|
||||||
|
|
||||||
bool remianing = true;
|
bool remianing = true;
|
||||||
while(remianing)
|
while(remianing)
|
||||||
{
|
{
|
||||||
qDebug()<<clients[i].buffer;
|
|
||||||
remianing = false;
|
remianing = false;
|
||||||
while(clients[i].state == STATE_IDLE && clients[i].buffer.contains('\n'))
|
while(clients[i].state == STATE_IDLE && clients[i].buffer.contains('\n'))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,12 @@
|
||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "service.h"
|
#include "server.h"
|
||||||
|
|
||||||
class TcpServer : public Service
|
class TcpServer : public Server
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
struct Client
|
|
||||||
{
|
|
||||||
QTcpSocket* socket;
|
|
||||||
QByteArray buffer;
|
|
||||||
client_state_t state = STATE_IDLE;
|
|
||||||
long long recievebytes = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Client> clients;
|
|
||||||
QTcpServer server;
|
QTcpServer server;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -31,8 +22,6 @@ signals:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void incomingConnection();
|
void incomingConnection();
|
||||||
void socketError(QAbstractSocket::SocketError socketError);
|
|
||||||
void socketDisconnect();
|
|
||||||
void socketReadyRead();
|
void socketReadyRead();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
83
src/service/websocketserver.cpp
Normal file
83
src/service/websocketserver.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
#include <QWebSocketServer>
|
||||||
|
#include <vector>
|
||||||
|
#include <QWebSocket>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
#include "items/item.h"
|
||||||
|
#include "server.h"
|
||||||
|
#include "websocketserver.h"
|
||||||
|
|
||||||
|
WebSocketServer::WebSocketServer(const QString &serverName, QObject* parent)
|
||||||
|
: Server(parent),
|
||||||
|
server(serverName, QWebSocketServer::NonSecureMode, this)
|
||||||
|
{
|
||||||
|
connect(&server, &QWebSocketServer::newConnection, this, &WebSocketServer::incomingConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebSocketServer::~WebSocketServer()
|
||||||
|
{
|
||||||
|
// Clean up WebSocket clients (they need special handling)
|
||||||
|
for(auto& client : clients)
|
||||||
|
{
|
||||||
|
if(client.socket.webSocket)
|
||||||
|
{
|
||||||
|
client.socket.webSocket->close();
|
||||||
|
delete client.socket.webSocket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::sendJson(const QJsonObject& json)
|
||||||
|
{
|
||||||
|
QByteArray jsonData = QJsonDocument(json).toJson();
|
||||||
|
for(auto& client : clients)
|
||||||
|
{
|
||||||
|
if(client.socket.webSocket && client.socket.webSocket->state() == QAbstractSocket::ConnectedState)
|
||||||
|
{
|
||||||
|
client.socket.webSocket->sendTextMessage(QString::fromUtf8(jsonData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::processIncomeingJson(const QByteArray& jsonbytes)
|
||||||
|
{
|
||||||
|
// Validate JSON first (WebSockets may receive malformed data)
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(jsonbytes);
|
||||||
|
if(!doc.isObject())
|
||||||
|
{
|
||||||
|
qWarning() << "Invalid JSON received:" << QString::fromUtf8(jsonbytes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Server::processIncomeingJson(jsonbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebSocketServer::launch(const QHostAddress &address, quint16 port)
|
||||||
|
{
|
||||||
|
qInfo()<<"WebSocket server launched on"<<address<<"port"<<port;
|
||||||
|
return server.listen(address, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::incomingConnection()
|
||||||
|
{
|
||||||
|
while(server.hasPendingConnections())
|
||||||
|
{
|
||||||
|
QWebSocket* client = server.nextPendingConnection();
|
||||||
|
qDebug() << "Got new WebSocket client from" << client->peerAddress().toString();
|
||||||
|
if(client)
|
||||||
|
{
|
||||||
|
Client c;
|
||||||
|
c.socket.webSocket = client;
|
||||||
|
clients.push_back(c);
|
||||||
|
connect(client, &QWebSocket::errorOccurred, this, [this, client]() { removeClient(client); });
|
||||||
|
connect(client, &QWebSocket::disconnected, this, [this, client]() { removeClient(client); });
|
||||||
|
connect(client, &QWebSocket::textMessageReceived, this, &WebSocketServer::textMessageReceived);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::textMessageReceived(const QString &message)
|
||||||
|
{
|
||||||
|
QByteArray jsonData = message.toUtf8();
|
||||||
|
processIncomeingJson(jsonData);
|
||||||
|
}
|
||||||
32
src/service/websocketserver.h
Normal file
32
src/service/websocketserver.h
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef WEBSOCKETSERVER_SERVER_H
|
||||||
|
#define WEBSOCKETSERVER_SERVER_H
|
||||||
|
|
||||||
|
#include <QWebSocketServer>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
class WebSocketServer : public Server
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
QWebSocketServer server;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WebSocketServer(const QString &serverName, QObject* parent = nullptr);
|
||||||
|
virtual ~WebSocketServer();
|
||||||
|
virtual bool launch(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) override;
|
||||||
|
virtual void sendJson(const QJsonObject& json) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void incomingConnection();
|
||||||
|
void textMessageReceived(const QString &message);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void processIncomeingJson(const QByteArray& jsonbytes) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void sigRequestSave();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBSOCKETSERVER_SERVER_H
|
||||||
|
|
@ -38,7 +38,7 @@ ItemWidget::ItemWidget(std::weak_ptr<Item> item, QWidget *parent) :
|
||||||
else
|
else
|
||||||
connect(ui->checkBox, &QCheckBox::toggled, this, &ItemWidget::moveToState);
|
connect(ui->checkBox, &QCheckBox::toggled, this, &ItemWidget::moveToState);
|
||||||
connect(ui->pushButton, &QPushButton::clicked, this, &ItemWidget::showSettingsDialog);
|
connect(ui->pushButton, &QPushButton::clicked, this, &ItemWidget::showSettingsDialog);
|
||||||
connect(workingItem.get(), &Relay::valueChanged, this, &ItemWidget::stateChanged);
|
connect(workingItem.get(), &Item::updated, this, &ItemWidget::onItemUpdated);
|
||||||
connect(ui->pushButton_Remove, &QPushButton::clicked, this, &ItemWidget::deleteItem);
|
connect(ui->pushButton_Remove, &QPushButton::clicked, this, &ItemWidget::deleteItem);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -59,18 +59,28 @@ void ItemWidget::deleteItem()
|
||||||
void ItemWidget::moveToValue(int value)
|
void ItemWidget::moveToValue(int value)
|
||||||
{
|
{
|
||||||
if(auto workingItem = item_.lock())
|
if(auto workingItem = item_.lock())
|
||||||
workingItem->setValue(value);
|
{
|
||||||
|
ItemUpdateRequest request = workingItem->createValueUpdateRequest(value, ITEM_UPDATE_USER);
|
||||||
|
workingItem->requestUpdate(request);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
disable();
|
disable();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ItemWidget::moveToState(bool state)
|
void ItemWidget::moveToState(bool state)
|
||||||
{
|
{
|
||||||
if(auto workingItem = item_.lock())
|
if(auto workingItem = item_.lock())
|
||||||
workingItem->setValue(state);
|
{
|
||||||
|
ItemUpdateRequest request = workingItem->createValueUpdateRequest(state, ITEM_UPDATE_USER);
|
||||||
|
workingItem->requestUpdate(request);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
disable();
|
disable();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ItemWidget::disable()
|
void ItemWidget::disable()
|
||||||
{
|
{
|
||||||
|
|
@ -105,6 +115,11 @@ std::weak_ptr<Item> ItemWidget::getItem()
|
||||||
return item_;
|
return item_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ItemWidget::onItemUpdated(ItemUpdateRequest update)
|
||||||
|
{
|
||||||
|
stateChanged(update.payload.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
void ItemWidget::stateChanged(int state)
|
void ItemWidget::stateChanged(int state)
|
||||||
{
|
{
|
||||||
ui->slider->blockSignals(true);
|
ui->slider->blockSignals(true);
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void stateChanged(int state);
|
void stateChanged(int state);
|
||||||
|
void onItemUpdated(ItemUpdateRequest update);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::ItemWidget *ui;
|
Ui::ItemWidget *ui;
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,17 @@
|
||||||
<number>255</number>
|
<number>255</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="tracking">
|
<property name="tracking">
|
||||||
<bool>false</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Orientation::Horizontal</enum>
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="invertedAppearance">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="invertedControls">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>300</width>
|
<width>400</width>
|
||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,11 @@ void SensorListWidget::sensorsChanged(std::vector<Sensor> sensors)
|
||||||
itemString.append("\"Playing\"");
|
itemString.append("\"Playing\"");
|
||||||
else itemString.append("\"Silent\"");
|
else itemString.append("\"Silent\"");
|
||||||
}
|
}
|
||||||
|
else if(!sensors[i].getUnit().isEmpty())
|
||||||
|
{
|
||||||
|
itemString.append(" ");
|
||||||
|
itemString.append(sensors[i].getUnit());
|
||||||
|
}
|
||||||
|
|
||||||
setItem(static_cast<int>(row), 0, new SensorListItem(sensors[i].name + (sensors[i].hidden ? " (H)" : ""), sensors[i]));
|
setItem(static_cast<int>(row), 0, new SensorListItem(sensors[i].name + (sensors[i].hidden ? " (H)" : ""), sensors[i]));
|
||||||
setItem(static_cast<int>(row), 1, new QTableWidgetItem(itemString));
|
setItem(static_cast<int>(row), 1, new QTableWidgetItem(itemString));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue