UvosSmartHomeInterface/src/service/tcpclient.cpp

144 lines
3.4 KiB
C++

#include <QTcpSocket>
#include <QJsonDocument>
#include <QJsonArray>
#include <iostream>
#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")
{
QJsonArray data = json["Data"].toArray();
bool FullList = json["FullList"].toBool(false);
std::vector<std::shared_ptr<Item>> items;
std::vector<ItemFieldChanges> fieldChanges;
for(QJsonValueRef itemjson : data)
{
QJsonObject jsonobject = itemjson.toObject();
std::shared_ptr<Item> item = Item::loadItem(jsonobject);
if(item)
{
item->setLoaded(FullList);
fieldChanges.push_back(item->loadWithChanges(jsonobject));
items.push_back(item);
}
}
if(FullList && !items.empty())
{
qDebug()<<"Client replaceing items";
requestReplaceItems(items);
}
else if(!items.empty())
{
std::vector<ItemAddRequest> itemAddRequests;
qDebug()<<"Client updateing items";
for(size_t i = 0; i < items.size(); i++)
{
ItemAddRequest request;
request.type = ITEM_UPDATE_REMOTE;
request.payload = items[i];
request.changes = fieldChanges[i];
itemAddRequests.push_back(request);
qDebug()<<"Payload"<<request.payload->id();
}
gotItems(itemAddRequests);
}
}
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;
}
}
}
}
void TcpClient::itemUpdated(ItemUpdateRequest update)
{
if(update.type == ITEM_UPDATE_USER)
{
QJsonArray items;
QJsonObject itemjson;
update.payload.storeWithChanges(itemjson, update.changes);
items.append(itemjson);
QJsonObject json = createMessage("ItemUpdate", items);
json["FullList"] = false;
sendJson(json);
}
}
void TcpClient::sensorEvent(Sensor sensor, sensor_update_type_t type)
{
// Only forward user-initiated sensor updates to the server
// to prevent feedback loops with backend/remote updates
if(type == SENSOR_UPDATE_USER)
{
Service::sensorEvent(sensor, type);
}
}
TcpClient::~TcpClient()
{
delete socket;
}