From 59b55d186813e3d6a9150f4a44ab61880f737fed Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Fri, 27 Mar 2026 20:11:23 +0100 Subject: [PATCH] Refactor tcpserver into multiple files --- CMakeLists.txt | 9 +- src/mainobject.h | 3 +- src/service/service.cpp | 104 ++++++++++++ src/service/service.h | 42 +++++ src/service/tcpclient.cpp | 100 +++++++++++ src/service/tcpclient.h | 33 ++++ src/service/tcpserver.cpp | 153 +++++++++++++++++ src/service/tcpserver.h | 45 +++++ src/tcpserver.cpp | 342 -------------------------------------- src/tcpserver.h | 101 ----------- 10 files changed, 486 insertions(+), 446 deletions(-) create mode 100644 src/service/service.cpp create mode 100644 src/service/service.h create mode 100644 src/service/tcpclient.cpp create mode 100644 src/service/tcpclient.h create mode 100644 src/service/tcpserver.cpp create mode 100644 src/service/tcpserver.h delete mode 100644 src/tcpserver.cpp delete mode 100644 src/tcpserver.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c24e80..924e5f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,11 +42,16 @@ target_sources(SHinterface src/sun.cpp src/programmode.h src/programmode.cpp - src/tcpserver.h - src/tcpserver.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/tcpserver.h + src/service/tcpserver.cpp + src/actors/actor.h src/actors/actor.cpp src/actors/factoractor.h diff --git a/src/mainobject.h b/src/mainobject.h index 79f5ed2..7f582d8 100644 --- a/src/mainobject.h +++ b/src/mainobject.h @@ -17,7 +17,8 @@ #include "sensors/mqttsensorsource.h" #include "items/fixeditemsource.h" #include "items/itemloadersource.h" -#include "tcpserver.h" +#include "service/tcpclient.h" +#include "service/tcpserver.h" class MainObject : public QObject { diff --git a/src/service/service.cpp b/src/service/service.cpp new file mode 100644 index 0000000..5129512 --- /dev/null +++ b/src/service/service.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include + +#include "items/item.h" +#include "items/itemstore.h" +#include "service.h" + + +Service::Service(QObject* parent): + ItemSource(parent) +{} + +QJsonObject Service::createMessage(const QString& type, const QJsonArray& data) +{ + QJsonObject json; + json["MessageType"] = type; + json["Data"] = data; + return json; +} + +void Service::sensorEvent(Sensor sensor) +{ + QJsonArray sensors; + QJsonObject sensorjson; + sensor.store(sensorjson); + sensors.append(sensorjson); + QJsonObject json = createMessage("SensorUpdate", sensors); + sendJson(json); +} + +void Service::itemUpdated(std::weak_ptr item) +{ + qDebug()<<__func__; + QJsonArray items; + QJsonObject itemjson; + item.lock()->store(itemjson); + items.append(itemjson); + QJsonObject json = createMessage("ItemUpdate", items); + json["FullList"] = false; + sendJson(json); +} + +void Service::refresh() +{ + sendJson(createMessage("GetSensors", QJsonArray())); + sendJson(createMessage("GetItems", QJsonArray())); +} + +void Service::sendSensors() +{ + QJsonArray sensors; + for(auto& sensor: *globalSensors.getSensors()) + { + QJsonObject sensorjson; + sensor.store(sensorjson); + sensors.append(sensorjson); + } + sendJson(createMessage("SensorUpdate", sensors)); +} + +void Service::sendItems() +{ + QJsonArray items; + for(auto& item: *globalItems.getItems()) + { + QJsonObject itemjson; + item->store(itemjson); + items.append(itemjson); + } + QJsonObject json = createMessage("ItemUpdate", items); + json["FullList"] = true; + sendJson(json); +} + + +void Service::processIncomeingJson(const QByteArray& jsonbytes) +{ + QJsonDocument doc = QJsonDocument::fromJson(jsonbytes); + qDebug()<<"Got Json:"< +#include + +#include "sensors/sensor.h" +#include "items/item.h" +#include "items/itemsource.h" + +class Service : public ItemSource +{ + Q_OBJECT +protected: + + typedef enum + { + STATE_IDLE, + STATE_RECV_JSON, + } client_state_t; + +signals: + void gotSensor(Sensor sensor); + +public slots: + void sensorEvent(Sensor sensor); + void itemUpdated(std::weak_ptr item); + virtual void refresh() override; + +public: + Service(QObject* parent = nullptr); + void sendSensors(); + void sendItems(); + virtual void sendJson(const QJsonObject& json) = 0; + virtual bool launch(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) = 0; + +protected: + static QJsonObject createMessage(const QString& type, const QJsonArray& data); + virtual void processIncomeingJson(const QByteArray& jsonbytes); +}; + +#endif // TCPSERVER_BASE_H diff --git a/src/service/tcpclient.cpp b/src/service/tcpclient.cpp new file mode 100644 index 0000000..d4d8dd8 --- /dev/null +++ b/src/service/tcpclient.cpp @@ -0,0 +1,100 @@ +#include +#include +#include +#include + +#include "items/item.h" +#include "service.h" +#include "tcpclient.h" + +TcpClient::TcpClient(QObject* parent): + Service(parent), + socket(new QTcpSocket(this)) +{ + connect(socket, &QTcpSocket::readyRead, this, &TcpClient::socketReadyRead); +} + +void TcpClient::sendJson(const QJsonObject& json) +{ + QByteArray jsonData = QJsonDocument(json).toJson(); + socket->write(QString("MSG JSON LEN " + QString::number(jsonData.size()) + "\n").toLatin1() + jsonData); +} + +bool TcpClient::launch(const QHostAddress &address, quint16 port) +{ + socket->connectToHost(address, port); + return socket->waitForConnected(2000); +} + +void TcpClient::processIncomeingJson(const QByteArray& jsonbytes) +{ + QJsonDocument doc = QJsonDocument::fromJson(jsonbytes); + QJsonObject json = doc.object(); + QString type = json["MessageType"].toString(); + if(type == "ItemUpdate") + { + std::cout<<"Got item json:\n"<> items; + for(QJsonValueRef itemjson : data) + { + QJsonObject jsonobject = itemjson.toObject(); + std::shared_ptr item = Item::loadItem(jsonobject); + if(item) + { + item->setLoaded(false); + items.push_back(item); + } + } + if(!items.empty()) + gotItems(items, true); + } + else + { + Service::processIncomeingJson(jsonbytes); + } +} + +void TcpClient::processComand(const QByteArray& command) +{ + if(command.startsWith("MSG JSON LEN ")) + { + state = STATE_RECV_JSON; + recievebytes = command.mid(13).toLongLong(); + } +} + +void TcpClient::socketReadyRead() +{ + buffer += socket->readAll(); + bool remianing = true; + while(remianing) + { + remianing = false; + while(state == STATE_IDLE && buffer.contains('\n')) + { + size_t newlineIndex = buffer.indexOf('\n'); + QByteArray command = buffer.left(newlineIndex); + buffer.remove(0, newlineIndex+1); + processComand(command); + remianing = true; + } + if(state == STATE_RECV_JSON) + { + if(recievebytes <= buffer.size()) + { + QByteArray json = buffer.left(recievebytes); + buffer.remove(0, recievebytes); + recievebytes = 0; + state = STATE_IDLE; + processIncomeingJson(json); + remianing = true; + } + } + } +} + +TcpClient::~TcpClient() +{ + delete socket; +} diff --git a/src/service/tcpclient.h b/src/service/tcpclient.h new file mode 100644 index 0000000..df28641 --- /dev/null +++ b/src/service/tcpclient.h @@ -0,0 +1,33 @@ +#ifndef TCPSERVER_CLIENT_H +#define TCPSERVER_CLIENT_H + +#include +#include +#include + +#include "service.h" + +class TcpClient : public Service +{ + Q_OBJECT + + QTcpSocket* socket; + client_state_t state = STATE_IDLE; + long long recievebytes = 0; + QByteArray buffer; + +public: + TcpClient(QObject* parent = nullptr); + ~TcpClient(); + virtual bool launch(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) override; + virtual void sendJson(const QJsonObject& json) override; + +protected: + virtual void processIncomeingJson(const QByteArray& jsonbytes) override; + +private slots: + void socketReadyRead(); + void processComand(const QByteArray& command); +}; + +#endif // TCPSERVER_CLIENT_H diff --git a/src/service/tcpserver.cpp b/src/service/tcpserver.cpp new file mode 100644 index 0000000..b5b780f --- /dev/null +++ b/src/service/tcpserver.cpp @@ -0,0 +1,153 @@ +#include +#include +#include +#include + +#include "items/item.h" +#include "service.h" +#include "tcpserver.h" + +TcpServer::TcpServer(QObject* parent): + Service(parent), + server(this) +{ + connect(&server, &QTcpServer::newConnection, this, &TcpServer::incomingConnection); +} + +void TcpServer::sendJson(const QJsonObject& json) +{ + for(auto client: clients) + { + QByteArray jsonData = QJsonDocument(json).toJson(); + client.socket->write(QString("MSG JSON LEN " + QString::number(jsonData.size()) + "\n").toLatin1() + jsonData); + } +} + +void TcpServer::processIncomeingJson(const QByteArray& jsonbytes) +{ + QJsonDocument doc = QJsonDocument::fromJson(jsonbytes); + QJsonObject json = doc.object(); + QString type = json["MessageType"].toString(); + if(type == "ItemUpdate") + { + qDebug()<<"Got Items"; + QJsonArray data = json["Data"].toArray(); + bool FullList = json["FullList"].toBool(false); + std::vector> items; + for(QJsonValueRef itemjson : data) + { + QJsonObject jsonobject = itemjson.toObject(); + std::shared_ptr item = Item::loadItem(jsonobject); + item->setLoaded(FullList); + if(item) + items.push_back(item); + } + if(FullList && !items.empty()) + { + requestReplaceItems(items); + sigRequestSave(); + } + else if(!items.empty()) + { + gotItems(items, false); + } + } + else + { + Service::processIncomeingJson(jsonbytes); + } +} + +bool TcpServer::launch(const QHostAddress &address, quint16 port) +{ + return server.listen(address, port); +} + +void TcpServer::incomingConnection() +{ + while(server.hasPendingConnections()) + { + QTcpSocket* client = server.nextPendingConnection(); + qDebug()<<"Got new client from"<peerAddress().toString(); + if(client) + { + clients.push_back({client}); + connect(client, &QTcpSocket::errorOccurred, this, &TcpServer::socketError); + connect(client, &QTcpSocket::disconnected, this, &TcpServer::socketDisconnect); + connect(client, &QTcpSocket::readyRead, this, &TcpServer::socketReadyRead); + } + } +} + +void TcpServer::socketError(QAbstractSocket::SocketError socketError) +{ + (void)socketError; + for(size_t i = 0; i < clients.size(); i++) + { + if(clients[i].socket == TcpServer::sender()) + { + clients.erase(clients.begin()+i); + --i; + } + } +} +void TcpServer::socketDisconnect() +{ + for(size_t i = 0; i < clients.size(); i++) + { + if(clients[i].socket == TcpServer::sender()) + { + clients.erase(clients.begin()+i); + --i; + } + } +} + +void TcpServer::processComand(const QByteArray& command, Client& client) +{ + if(command.startsWith("MSG JSON LEN ")) + { + client.state = STATE_RECV_JSON; + client.recievebytes = command.mid(13).toLongLong(); + qDebug()<<"Got command:"<readAll(); + clients[i].buffer += newChars; + + bool remianing = true; + while(remianing) + { + qDebug()< +#include + +#include "service.h" + +class TcpServer : public Service +{ + Q_OBJECT + + struct Client + { + QTcpSocket* socket; + QByteArray buffer; + client_state_t state = STATE_IDLE; + long long recievebytes = 0; + }; + + std::vector clients; + QTcpServer server; + +public: + TcpServer(QObject* parent = nullptr); + virtual bool launch(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) override; + virtual void sendJson(const QJsonObject& json) override; + +signals: + void sigRequestSave(); + +private slots: + void incomingConnection(); + void socketError(QAbstractSocket::SocketError socketError); + void socketDisconnect(); + void socketReadyRead(); + +protected: + virtual void processIncomeingJson(const QByteArray& jsonbytes) override; + +private: + void processComand(const QByteArray& command, Client& client); +}; + +#endif // TCPSERVER_SERVER_H diff --git a/src/tcpserver.cpp b/src/tcpserver.cpp deleted file mode 100644 index f49150f..0000000 --- a/src/tcpserver.cpp +++ /dev/null @@ -1,342 +0,0 @@ -#include -#include -#include -#include - -#include "items/item.h" -#include "items/itemstore.h" -#include "tcpserver.h" - - -TcpService::TcpService(QObject* parent): - ItemSource(parent) -{} - -QJsonObject TcpService::createMessage(const QString& type, const QJsonArray& data) -{ - QJsonObject json; - json["MessageType"] = type; - json["Data"] = data; - return json; -} - -void TcpService::sensorEvent(Sensor sensor) -{ - QJsonArray sensors; - QJsonObject sensorjson; - sensor.store(sensorjson); - sensors.append(sensorjson); - QJsonObject json = createMessage("SensorUpdate", sensors); - sendJson(json); -} - -void TcpService::itemUpdated(std::weak_ptr item) -{ - qDebug()<<__func__; - QJsonArray items; - QJsonObject itemjson; - item.lock()->store(itemjson); - items.append(itemjson); - QJsonObject json = createMessage("ItemUpdate", items); - json["FullList"] = false; - sendJson(json); -} - -void TcpService::refresh() -{ - sendJson(createMessage("GetSensors", QJsonArray())); - sendJson(createMessage("GetItems", QJsonArray())); -} - -void TcpService::sendSensors() -{ - QJsonArray sensors; - for(auto& sensor: *globalSensors.getSensors()) - { - QJsonObject sensorjson; - sensor.store(sensorjson); - sensors.append(sensorjson); - } - sendJson(createMessage("SensorUpdate", sensors)); -} - -void TcpService::sendItems() -{ - QJsonArray items; - for(auto& item: *globalItems.getItems()) - { - QJsonObject itemjson; - item->store(itemjson); - items.append(itemjson); - } - QJsonObject json = createMessage("ItemUpdate", items); - json["FullList"] = true; - sendJson(json); -} - - -void TcpService::processIncomeingJson(const QByteArray& jsonbytes) -{ - QJsonDocument doc = QJsonDocument::fromJson(jsonbytes); - qDebug()<<"Got Json:"<write(QString("MSG JSON LEN " + QString::number(jsonData.size()) + "\n").toLatin1() + jsonData); -} - -bool TcpClient::launch(const QHostAddress &address, quint16 port) -{ - socket->connectToHost(address, port); - return socket->waitForConnected(2000); -} - -void TcpClient::processIncomeingJson(const QByteArray& jsonbytes) -{ - QJsonDocument doc = QJsonDocument::fromJson(jsonbytes); - QJsonObject json = doc.object(); - QString type = json["MessageType"].toString(); - if(type == "ItemUpdate") - { - std::cout<<"Got item json:\n"<> items; - for(QJsonValueRef itemjson : data) - { - QJsonObject jsonobject = itemjson.toObject(); - std::shared_ptr item = Item::loadItem(jsonobject); - if(item) - { - item->setLoaded(false); - items.push_back(item); - } - } - if(!items.empty()) - gotItems(items, true); - } - else - { - TcpService::processIncomeingJson(jsonbytes); - } -} - -void TcpClient::processComand(const QByteArray& command) -{ - if(command.startsWith("MSG JSON LEN ")) - { - state = STATE_RECV_JSON; - recievebytes = command.mid(13).toLongLong(); - } -} - -void TcpClient::socketReadyRead() -{ - buffer += socket->readAll(); - bool remianing = true; - while(remianing) - { - remianing = false; - while(state == STATE_IDLE && buffer.contains('\n')) - { - size_t newlineIndex = buffer.indexOf('\n'); - QByteArray command = buffer.left(newlineIndex); - buffer.remove(0, newlineIndex+1); - processComand(command); - remianing = true; - } - if(state == STATE_RECV_JSON) - { - if(recievebytes <= buffer.size()) - { - QByteArray json = buffer.left(recievebytes); - buffer.remove(0, recievebytes); - recievebytes = 0; - state = STATE_IDLE; - processIncomeingJson(json); - remianing = true; - } - } - } -} - -TcpClient::~TcpClient() -{ - delete socket; -} - -TcpServer::TcpServer(QObject* parent): - TcpService(parent), - server(this) -{ - connect(&server, &QTcpServer::newConnection, this, &TcpServer::incomingConnection); -} - -void TcpServer::sendJson(const QJsonObject& json) -{ - for(auto client: clients) - { - QByteArray jsonData = QJsonDocument(json).toJson(); - client.socket->write(QString("MSG JSON LEN " + QString::number(jsonData.size()) + "\n").toLatin1() + jsonData); - } -} - -void TcpServer::processIncomeingJson(const QByteArray& jsonbytes) -{ - QJsonDocument doc = QJsonDocument::fromJson(jsonbytes); - QJsonObject json = doc.object(); - QString type = json["MessageType"].toString(); - if(type == "ItemUpdate") - { - qDebug()<<"Got Items"; - QJsonArray data = json["Data"].toArray(); - bool FullList = json["FullList"].toBool(false); - std::vector> items; - for(QJsonValueRef itemjson : data) - { - QJsonObject jsonobject = itemjson.toObject(); - std::shared_ptr item = Item::loadItem(jsonobject); - item->setLoaded(FullList); - if(item) - items.push_back(item); - } - if(FullList && !items.empty()) - { - requestReplaceItems(items); - sigRequestSave(); - } - else if(!items.empty()) - { - gotItems(items, false); - } - } - else - { - TcpService::processIncomeingJson(jsonbytes); - } -} - -bool TcpServer::launch(const QHostAddress &address, quint16 port) -{ - return server.listen(address, port); -} - -void TcpServer::incomingConnection() -{ - while(server.hasPendingConnections()) - { - QTcpSocket* client = server.nextPendingConnection(); - qDebug()<<"Got new client from"<peerAddress().toString(); - if(client) - { - clients.push_back({client}); - connect(client, &QTcpSocket::errorOccurred, this, &TcpServer::socketError); - connect(client, &QTcpSocket::disconnected, this, &TcpServer::socketDisconnect); - connect(client, &QTcpSocket::readyRead, this, &TcpServer::socketReadyRead); - } - } -} - -void TcpServer::socketError(QAbstractSocket::SocketError socketError) -{ - (void)socketError; - for(size_t i = 0; i < clients.size(); i++) - { - if(clients[i].socket == TcpServer::sender()) - { - clients.erase(clients.begin()+i); - --i; - } - } -} -void TcpServer::socketDisconnect() -{ - for(size_t i = 0; i < clients.size(); i++) - { - if(clients[i].socket == TcpServer::sender()) - { - clients.erase(clients.begin()+i); - --i; - } - } -} - -void TcpServer::processComand(const QByteArray& command, Client& client) -{ - if(command.startsWith("MSG JSON LEN ")) - { - client.state = STATE_RECV_JSON; - client.recievebytes = command.mid(13).toLongLong(); - qDebug()<<"Got command:"<readAll(); - clients[i].buffer += newChars; - - bool remianing = true; - while(remianing) - { - qDebug()< -#include - -#include "sensors/sensor.h" -#include "items/item.h" -#include "items/itemsource.h" - -class TcpService : public ItemSource -{ - Q_OBJECT -protected: - - typedef enum - { - STATE_IDLE, - STATE_RECV_JSON, - } client_state_t; - -signals: - void gotSensor(Sensor sensor); - -public slots: - void sensorEvent(Sensor sensor); - void itemUpdated(std::weak_ptr item); - virtual void refresh() override; - -public: - TcpService(QObject* parent = nullptr); - void sendSensors(); - void sendItems(); - virtual void sendJson(const QJsonObject& json) = 0; - virtual bool launch(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) = 0; - -protected: - static QJsonObject createMessage(const QString& type, const QJsonArray& data); - virtual void processIncomeingJson(const QByteArray& jsonbytes); -}; - -class TcpClient : public TcpService -{ - Q_OBJECT - - QTcpSocket* socket; - client_state_t state = STATE_IDLE; - long long recievebytes = 0; - QByteArray buffer; - -public: - TcpClient(QObject* parent = nullptr); - ~TcpClient(); - virtual bool launch(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) override; - virtual void sendJson(const QJsonObject& json) override; - -protected: - virtual void processIncomeingJson(const QByteArray& jsonbytes) override; - -private slots: - void socketReadyRead(); - void processComand(const QByteArray& command); -}; - -class TcpServer : public TcpService -{ - Q_OBJECT - - struct Client - { - QTcpSocket* socket; - QByteArray buffer; - client_state_t state = STATE_IDLE; - long long recievebytes = 0; - }; - - std::vector clients; - QTcpServer server; - -public: - TcpServer(QObject* parent = nullptr); - virtual bool launch(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) override; - virtual void sendJson(const QJsonObject& json) override; - -signals: - void sigRequestSave(); - -private slots: - void incomingConnection(); - void socketError(QAbstractSocket::SocketError socketError); - void socketDisconnect(); - void socketReadyRead(); - -protected: - virtual void processIncomeingJson(const QByteArray& jsonbytes) override; - -private: - void processComand(const QByteArray& command, Client& client); -}; - -#endif // TCPSERVER_H