Major wip refactor

Allow running without gui
Remove serialPortMultiplexer broadcast use
Add TcpServer and TcpClient
Introduce the concept of an item source
This commit is contained in:
Carl Philipp Klemm 2026-03-01 14:39:27 +01:00
parent cbeb8d49a7
commit 6d742e60db
38 changed files with 928 additions and 825 deletions

View file

@ -1,179 +1,94 @@
#include "mainobject.h"
#include "items/messageitem.h"
MainObject::MainObject(QIODevice* ioDevice, const QString& settingsPathIn, const bool masterIn, QObject *parent) :
QObject(parent),
master(masterIn),
masterIODevice(ioDevice),
ioMultiplexer(masterIODevice),
micro(ioMultiplexer.getIoDevice()),
broadCast(ioMultiplexer.getIoDevice(), masterIn),
settingsPath(settingsPathIn),
sunSensorSource(49.884450, 8.650536),
powerItem(new PowerItem),
rgbItem(new RgbItem(&micro, 5487422, "Rgb Lights")),
auxItem(new AuxItem(&micro, 5487421, "Desk Light"))
#include<QJsonObject>
#include<QJsonArray>
#include<QMessageBox>
#include "items/itemstore.h"
MainObject::MainObject(QObject *parent) :
QObject(parent)
{
qDebug()<<"Is master:"<<master;
//connect sensors subsystem
QObject::connect(&micro, &Microcontroller::gotSensorState, &globalSensors, &SensorStore::sensorGotState);
QObject::connect(&sunSensorSource, &SunSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState);
QObject::connect(&globalSensors, &SensorStore::sensorChangedState, &ocupancySensor, &OcupancySensorSource::sensorEvent);
QObject::connect(&ocupancySensor, &OcupancySensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState);
sunSensorSource.run();
//pwHandler.startLoop();
//connect item store
QObject::connect(&micro, &Microcontroller::gotRelayList, &items, &ItemStore::addItems);
QObject::connect(&micro, &Microcontroller::itemChanged, &items, &ItemStore::itemStateChanged);
//special items
QObject::connect(powerItem.get(), &PowerItem::stateChanged, &globalSensors, &SensorStore::sensorGotState);
powerItem->emmitSensor();
items.addItem(rgbItem);
items.addItem(auxItem);
MessageItem::broadCast = &broadCast;
Relay::setMicrocontroller(&micro);
connect(&broadCast, &BroadCast::gotJson, this, &MainObject::recivedJson);
QObject::connect(&broadCast, &BroadCast::gotSensorState, &globalSensors, &SensorStore::sensorGotState);
if(master)
connect(&broadCast, &BroadCast::jsonRequested, this, &MainObject::sendJson);
if(master)
{
load(getJsonObjectFromDisk(settingsPath, &noSave));
}
else
{
broadCast.requestJson();
broadCast.requestSensors();
}
#ifndef Q_OS_ANDROID
Item::secondaryFlag = !master;
#endif
}
MainObject::~MainObject()
{
}
void MainObject::store(QJsonObject &json)
void MainObject::refresh()
{
items.store(json);
QJsonObject powerObject;
powerItem->store(powerObject);
json.insert("Power", powerObject);
QJsonDocument pwrDoc(powerObject);
QJsonObject ocupancyObject;
ocupancySensor.store(ocupancyObject);
json.insert("Ocupancy", ocupancyObject);
globalItems.refresh();
}
void MainObject::load(const QJsonObject& json)
PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, QJsonObject* settings, QString host, int port, QObject *parent) :
MainObject(parent),
settings(settings),
microDevice(microDevice),
ioMultiplexer(microDevice),
micro(microDevice),
tcpServer(new TcpServer),
sunSensorSource(49.824972, 8.702194),
powerItem(new PowerItem),
rgbItem(new RgbItem(&micro, 5487422, "Rgb Lights")),
auxItem(new AuxItem(&micro, 5487421, "Desk Light"))
{
items.clear();
//connect sensors subsystem
connect(&globalSensors, &SensorStore::sensorChangedState, tcpServer, &TcpServer::sensorEvent);
connect(tcpServer, &TcpServer::gotSensor, &globalSensors, &SensorStore::sensorGotState);
connect(&sunSensorSource, &SunSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState);
connect(&micro, &Microcontroller::gotSensorState, &globalSensors, &SensorStore::sensorGotState);
globalItems.registerItemSource(tcpServer);
globalItems.registerItemSource(&micro);
load(*settings);
tcpServer->launch(QHostAddress(host), port);
}
PrimaryMainObject::~PrimaryMainObject()
{
store(*settings);
}
void PrimaryMainObject::store(QJsonObject &json)
{
globalItems.store(json);
}
void PrimaryMainObject::load(const QJsonObject& json)
{
globalItems.clear();
rgbItem->removeAllActors();
auxItem->removeAllActors();
powerItem->removeAllActors();
items.addItem(rgbItem);
items.addItem(auxItem);
items.load(json);
powerItem->load(json["Power"].toObject());
ocupancySensor.load(json["Ocupancy"].toObject());
qDebug()<<"aray size: "<<json.isEmpty();
globalItems.addItem(rgbItem);
globalItems.addItem(auxItem);
globalItems.addItem(powerItem);
globalItems.load(json);
if(json["Items"].toArray().size() >= 2)
{
rgbItem->load(json["Items"].toArray()[0].toObject());
auxItem->load(json["Items"].toArray()[1].toObject());
}
micro.requestState();
globalItems.refresh();
}
void MainObject::storeToDisk()
SecondaryMainObject::SecondaryMainObject(QString host, int port, QObject *parent) :
MainObject(parent),
tcpClient(new TcpClient)
{
if(master && !noSave)
connect(tcpClient, &TcpClient::gotSensor, &globalSensors, &SensorStore::sensorGotState);
globalItems.registerItemSource(tcpClient);
if(!tcpClient->launch(QHostAddress(host), port))
{
QJsonObject json;
store(json);
storeJsonObjectToDisk(json, settingsPath);
QMessageBox::critical(nullptr, "Error", "Could not connect to "+host+":"+QString::number(port));
exit(1);
}
}
void MainObject::recivedJson(const QJsonObject json)
SecondaryMainObject::~SecondaryMainObject()
{
if(master && !noSave)
storeJsonObjectToDisk(json, settingsPath);
load(json);
}
void MainObject::sendJson()
{
QJsonObject json;
store(json);
broadCast.sendJson(json);
}
QJsonObject MainObject::getJsonObjectFromDisk(const QString& filePath, bool* error)
{
QFile file;
#ifndef Q_OS_ANDROID
if(filePath.size() > 0) file.setFileName(filePath);
else
#endif
{
file.setFileName(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/shinterface.json");
}
file.open(QIODevice::ReadOnly);
if(!file.isOpen()) std::cerr<<"Can not open config file: "<<filePath.toLatin1().data()<<std::endl;
else
{
QJsonParseError qerror;
QJsonDocument document(QJsonDocument::fromJson(file.readAll(), &qerror));
file.close();
if(qerror.error != QJsonParseError::NoError)
{
qDebug()<<filePath<<" "<<qerror.errorString();
if(error) (*error) = true;
}
return document.object();
}
return QJsonObject();
}
bool MainObject::storeJsonObjectToDisk(const QJsonObject& json, QString filePath)
{
#ifndef Q_OS_ANDROID
if(filePath.size() == 0)
#endif
{
filePath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/shinterface.json";
}
QFile file(filePath + ".out");
qDebug()<<"config file: "<<filePath;
file.open(QIODevice::WriteOnly);
if(!file.isOpen())
{
std::cerr<<"Can not open config file: "<<filePath.toLatin1().data()<<std::endl;
return false;
}
else
{
QJsonDocument document(json);
file.write(document.toJson());
file.close();
QFile::remove(filePath);
file.rename(filePath);
return true;
}
}