SL100_FactoryTestTool/FactoryTestTool/SourceCode/Network/ClientHandler.cpp

921 lines
35 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ClientHandler.cpp
#include "ClientHandler.h"
#include "../LicenseGenerate/LicenseConfirmWindow.h"
#include "ImageEnrollWindow.h"
#include "PasswordEnrollWindow.h"
ClientHandler::ClientHandler(QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig,
QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson,
QJsonArray getPicJson, QJsonArray getVideoJson, int clientId, int isBackBoardOrAllBoard, QObject* parent)
: QObject(parent),
frontBoardOneClickTest(frontBoardOneClickTest), frontBoardTest(frontBoardTest),
frontBoardFuncConfig(frontBoardFuncConfig), frontBoardDevInfoJson(frontBoardDevInfoJson),
frontBoardLicenseJson(frontBoardLicenseJson),
backBoardOneClickTest(backBoardOneClickTest), backBoardTest(backBoardTest),
backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson),
backBoardUuidJson(backBoardUuidJson), getPicJson(getPicJson), getVideoJson(getVideoJson),
currentItemIndex(0), clientId(clientId), isBackBoardOrAllBoard(isBackBoardOrAllBoard),
isManualSend(false), isSingleSend(false), isClickedSend(false), size(0),
isFirstDataReceived(true), processDataFunction(nullptr),
isDataStuck(false), dataProcessingActive(false), isRecvVideoData(true),
currentFrontBoardIndex(0), currentLicenseIndex(0), currentUuidIndex(0),
currentBackBoardIndex(0)
{
}
void ClientHandler::initialize(QTcpSocket* socket)
{
this->socket = socket;
connect(socket, &QTcpSocket::readyRead, this, &ClientHandler::onDataReceived);
connect(socket, &QTcpSocket::disconnected, this, &ClientHandler::onDisconnected);
// 其他的 socket 操作都将在这个线程中进行
}
ClientHandler::~ClientHandler()
{
socket->deleteLater();
qDebug() << "ClientHandler destroyed for clientId:" << clientId;
}
// 实现 QRunnable 的 run 函数,在线程池中执行
void ClientHandler::run()
{
start();
}
// 重置索引
void ClientHandler::resetCurrentItemIndex()
{
currentItemIndex = 0;
currentFuncItemIndex = 0;
itemsProcessedCount = 0;
emit startTimeout(0);
}
// 开始处理客户端
void ClientHandler::start()
{
resetCurrentItemIndex(); // 初始化计数器和索引
//sendNextItem();
}
// 处理客户端断开连接
void ClientHandler::onDisconnected() {
qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
qDebug() << "> A device is disconnected. ID:" << clientId;
qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
emit clientDisconnected(this);
}
void ClientHandler::startReadVideoDataTimer(int client_Id)
{
//emit startReadTimer(clientId);
emit startReadTimer(client_Id);
qDebug() << "------ startClientReadTimer clientId:" << clientId;
}
void ClientHandler::stopReadVideoDataTimer(int client_Id)
{
//emit stopReadTimer(clientId);
emit stopReadTimer(client_Id);
}
qint64 getFreeMemory() {
QStorageInfo storage = QStorageInfo::root();
return storage.bytesAvailable();
}
void ClientHandler::checkConnectionStatus()
{
if (socket->state() != QTcpSocket::ConnectedState) {
qCritical() << "Connection lost for clientId:" << clientId << ". Socket state:" << socket->state();
emit clientDisconnected(this);
}
}
QString ClientHandler::getCurrentItemData() const
{
QString data = currentItem.value("data").toString();
qDebug() << "Getting current item data:" << data;
return data; // 返回当前项的 "data" 字段
}
QString ClientHandler::getCurrentFuncItemData() const
{
QString data = currentFuncItem.value("val").toString();
qDebug() << "Getting current funcItem val:" << data;
return data; // 返回当前项的 "val" 字段
}
QString ClientHandler::getCurrentItemLable() const
{
QString lable = currentItem.value("lable").toString();
qDebug() << "Getting current item lable:" << lable;
return lable; // 返回当前项的 "lable" 字段
}
QString ClientHandler::getCurrentFuncItemLable() const
{
QString lable = currentFuncItem.value("lable").toString();
//qDebug() << "Getting current funcItem lable:" << lable;
return lable; // 返回当前项的 "data" 字段
}
QString ClientHandler::getClientAddress() const
{
return socket->peerAddress().toString() + ":" + QString::number(socket->peerPort());
}
#if !TEST_TCP_MOVE_TO_MAIN
void ClientHandler::onSendData(const QByteArray& data, int isBoardType)
{
qDebug() << "Sending data isBoardType:" << isBoardType;
QByteArray prefix;
QDataStream stream(&prefix, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << quint32(0x55AA55AA);
if (isBoardType != 0) {
stream << quint16(0x0421);
}
else {
stream << quint16(0x0420);
}
stream << quint32(data.size());
prefix.append(data);
qDebug() << "Sending data:" << prefix.toHex();
socket->write(prefix);
socket->flush();
}
#endif
void ClientHandler::sendDataToClient(const QByteArray& data)
{
emit sendData(data, isBackBoardOrAllBoard);
}
void ClientHandler::onCommandError() {
isCommandError = true;
}
void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, const QString text, const QString backBoardSn, const QString& itemType)
{
startReadVideoDataTimer(preVideoClientId);
currentJson = jsonArray;
currentJsonItem = itemIndex;
QMutexLocker locker(&mutex);
if (itemType == "License") {
}
isSingleSend = true;
isClickedSend = true;
isRecvImgData = false;
if (jsonArray == backBoardTest) {
QJsonObject tempItem = jsonArray[itemIndex].toObject();
if (tempItem["cmd"] == "VIDEO_TEST") {
if (tempItem["val"] == 0) {
isSingleSend = false;
isClickedSend = false;
isRecvVideoData = true;
isStartVideo = true;
startReadVideoDataTimer(isBackBoardOrAllBoard);
}
else if (tempItem["val"] == 1) {
isRecvVideoData = false;
isStartVideo = false;
stopReadVideoDataTimer(isBackBoardOrAllBoard);
}
}
}
if (itemType == "handleVideo") {
if (itemIndex == 0) {
isSingleSend = false;
isClickedSend = false;
}
else {
stopReadVideoDataTimer(preVideoClientId);
}
}
if (itemType == "getPic") {
isSingleSend = false;
isClickedSend = false;
isRecvImgData = true;
}
if (itemType == "Uuid") {
}
qDebug() << "itemIndex" << itemIndex;
qDebug() << "jsonArray.size()" << jsonArray.size();
if (itemIndex >= 0 && itemIndex < jsonArray.size()) {
currentItemIndex = (itemType == "test") ? itemIndex : 0;
currentFuncItemIndex = (itemType == "func") ? itemIndex : 0;
currentItem = jsonArray[itemIndex].toObject();
if (!text.isEmpty() && currentItem.contains("val")) {
QJsonValue originalValue = currentItem["val"];
qDebug() << "text:" << text;
if (originalValue.isDouble()) {
bool ok;
double doubleValue = text.toDouble(&ok);
if (ok) {
currentItem["val"] = doubleValue;
}
else {
qWarning() << "Text conversion to double failed, original value is kept.";
}
}
else if (originalValue.isString()) {
currentItem["val"] = text;
}
}
else if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "CHANGE_THEME") {
QString downloadUrl;
QEventLoop loop;
emit startImageSharing(CHANGE_THEME_W, CHANGE_THEME_H, "theme", [&downloadUrl, &loop](QString responseUrl) {
//qDebug() << "Received response from slot:" << responseUrl;
downloadUrl = responseUrl; // 更新局部变量
loop.quit(); // 退出事件循环
});
//loop.exec(); // 等待回调执行完成
if (!downloadUrl.isEmpty()) {
qDebug() << "Image available at:" << downloadUrl;
}
else {
return;
}
currentItem["val"] = downloadUrl;
}
else if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "UPDATE_LOGO") {
QString downloadUrl;
QEventLoop loop;
emit startLOGOImageSharing(CHANGE_THEME_W, CHANGE_THEME_H, "theme", [&downloadUrl, &loop](QString responseUrl) {
//qDebug() << "Received response from slot:" << responseUrl;
downloadUrl = responseUrl; // 更新局部变量
loop.quit(); // 退出事件循环
});
//loop.exec(); // 等待回调执行完成
if (!downloadUrl.isEmpty()) {
qDebug() << "Image available at:" << downloadUrl;
}
else {
return;
}
currentItem["val"] = downloadUrl;
}
else if (!text.isEmpty() && currentItem.contains("UUID") && currentItem.contains("SN")) {
QJsonValue originalUUID = currentItem["UUID"];
QJsonValue originalSN = currentItem["SN"];
qDebug() << "UUID:" << text;
qDebug() << "SN:" << backBoardSn;
if (originalUUID.isDouble()) {
bool ok;
double doubleValue = text.toDouble(&ok);
if (ok) {
currentItem["UUID"] = doubleValue;
}
else {
qWarning() << "Text conversion to double failed, original value is kept.";
}
}
else if (originalUUID.isString()) {
currentItem["UUID"] = text;
}
if (originalSN.isDouble()) {
bool ok;
double doubleValue = backBoardSn.toDouble(&ok);
if (ok) {
currentItem["SN"] = doubleValue;
}
else {
qWarning() << "backBoardSn conversion to double failed, original value is kept.";
}
}
else if (originalSN.isString()) {
currentItem["SN"] = backBoardSn;
}
}
QString itemData = QJsonDocument(currentItem).toJson();
emit currentSendItem(currentItem["cmd"].toString());
if (isBackBoardOrAllBoard) {
emit sendDataToSomeClient(isBackBoardOrAllBoard, itemData.toUtf8());
}
else {
emit sendDataToSomeClient(controlClientId, itemData.toUtf8());
}
if (currentItem.contains("timeout")) {
qDebug() << "sendJsonItem currentItem.contains(\"timeout\")";
int timeout = currentItem.value("timeout").toInt();
if (timeout > 0) {
emit startTimeout(timeout);
}
}
}
}
void ClientHandler::sendBackFuncItem(int itemIndex, const QString text)
{
if (isBackBoardOrAllBoard == 0) {
emit HandleInvalidOperate("当前连接的是前板,请勿操作后板或整机页面的按键!!!");
return;
}
else {
//qDebug() << "sendFuncItem Text:" << text;
sendJsonItem(backBoardFuncConfig, itemIndex, text, "", "func");
}
}
void ClientHandler::sendFrontItem(int itemIndex)
{
if (isBackBoardOrAllBoard != 0) {
emit HandleInvalidOperate("当前连接的是后板或整机,请勿操作前板页面的按键!!!");
return;
}
else {
QString text = "";
QJsonObject currentItem = frontBoardTest[itemIndex].toObject();
if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "IMG_ENROLL") {
QString downloadUrl;
QEventLoop loop;
emit startImageSharing(IMG_ENROLL_W, IMG_ENROLL_H, "enroll", [&downloadUrl, &loop](QString responseUrl) {
//qDebug() << "Received response from slot:" << responseUrl;
downloadUrl = responseUrl; // 更新局部变量
loop.quit(); // 退出事件循环
});
//loop.exec(); // 等待回调执行完成
if (!downloadUrl.isEmpty()) {
qDebug() << "Image available at:" << downloadUrl;
}
text = downloadUrl;
}
else if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "DEL_USER") {
DelUserWindow dialog;
if (dialog.exec() == QDialog::Accepted) {
QString userInput = dialog.getUserInput();
if (!userInput.isEmpty() && currentItem.contains("val")) {
text = userInput;
}
}
else {
return;
}
}
else if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "PASSWD_ENROLL") {
PasswordEnrollWindow dialog;
if (dialog.exec() == QDialog::Accepted) {
text = dialog.getPassword();
}
else {
return;
}
}
sendJsonItem(frontBoardTest, itemIndex, text, "", "test");
}
}
void ClientHandler::sendBackItem(int itemIndex)
{
if (isBackBoardOrAllBoard == 0) {
emit HandleInvalidOperate("当前连接的是前板,请勿操作后板或整机页面的按键!!!");
return;
}
else {
QString text = "";
QJsonObject currentItem = backBoardTest[itemIndex].toObject();
if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "DEL_USER") {
DelUserWindow dialog;
if (dialog.exec() == QDialog::Accepted) {
QString userInput = dialog.getUserInput();
if (!userInput.isEmpty() && currentItem.contains("val")) {
text = userInput;
}
}
else {
return;
}
}
else if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "PASSWD_ENROLL") {
PasswordEnrollWindow dialog;
if (dialog.exec() == QDialog::Accepted) {
text = dialog.getPassword();
}
else {
return;
}
}
isRecvVideoData = false;
sendJsonItem(backBoardTest, itemIndex, text, "", "test");
}
}
// 发送获取设备信息按键
void ClientHandler::sendGetDevInfoItem(int itemIndex)
{
sendJsonItem(getDevInfoJson, itemIndex, "", "", "devInfo");
}
// 发送取图按键
void ClientHandler::sendGetPicItem(int itemIndex, int GetPicCamIndex)
{
sendJsonItem(getPicJson, itemIndex, QString::number(GetPicCamIndex), "", "getPic");
}
// 发送拉视频按键
void ClientHandler::sendGetVideoItem(int itemIndex, int GetVideoCamIndex)
{
qDebug() << "sendGetVideoItem itemIndex:" << itemIndex;
if(isBackBoardOrAllBoard) {
sendJsonItem(getVideoJson, itemIndex, QString::number(GetVideoCamIndex), "", "handleVideo");
}
else {
sendJsonItem(getVideoJson, itemIndex, QString::number(GetVideoCamIndex), "", "handleVideo");
}
}
// 发送License处理按键
void ClientHandler::sendLicenseItem(int itemIndex, const QString text)
{
if (isBackBoardOrAllBoard != 0) {
emit HandleInvalidOperate("当前连接的是后板或整机,请勿操作前板页面的按键!!!");
return;
}
else {
if (itemIndex < 0 || itemIndex >= frontBoardLicenseJson.size()) {
qDebug() << "Invalid itemIndex";
return;
}
sendJsonItem(frontBoardLicenseJson, itemIndex, text, "", "License");
}
}
void ClientHandler::sendUuidItem(int itemIndex, const QString backBoardUuid, const QString backBoardSn)
{
qDebug() << "ClientHandler::sendUuidItem itemIndex:" << itemIndex;
if (isBackBoardOrAllBoard == 0) {
emit HandleInvalidOperate("当前连接的是前板,请勿操作后板或整机页面的按键!!!");
return;
}
else {
if (itemIndex < 0 || itemIndex >= backBoardUuidJson.size()) {
qDebug() << "Invalid itemIndex";
return;
}
sendJsonItem(backBoardUuidJson, itemIndex, backBoardUuid, backBoardSn, "Uuid");
}
}
void ClientHandler::sendFrontFuncItem(int itemIndex, const QString text)
{
if (isBackBoardOrAllBoard != 0) {
emit HandleInvalidOperate("当前连接的是后板或整机,请勿操作前板页面的按键!!!");
return;
}
else {
//qDebug() << "sendFuncItem Text:" << text;
sendJsonItem(frontBoardFuncConfig, itemIndex, text, "", "func");
}
}
void ClientHandler::sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemIndex)
{
QMutexLocker locker(&mutex);
isPowerOnSend = true;
qDebug() << "itemIndex" << itemIndex;
qDebug() << "jsonItem.size()" << jsonItem.size();
currentItem = jsonItem;
QString itemData = QJsonDocument(jsonItem).toJson();
//emit sendData(itemData.toUtf8());
if (isBackBoardOrAllBoard) {
emit sendDataToSomeClient(isBackBoardOrAllBoard, itemData.toUtf8());
}
else {
emit sendDataToSomeClient(controlClientId, itemData.toUtf8());
}
if (jsonItem.contains("timeout")) {
int timeout = jsonItem.value("timeout").toInt();
if (timeout > 0) {
emit startTimeout(timeout);
}
}
else {
// 如果没有 timeout 字段,则不设置超时处理,一直等待数据接收
}
}
void ClientHandler::sendDevInfoItem()
{
if (isBackBoardOrAllBoard) {
currentJson = backBoardDevInfoJson;
currentJsonItem = currentBackBoardIndex;
if (currentBackBoardIndex < backBoardDevInfoJson.size()) {
isRecvVideoData = false;
sendDevInfoJsonItem(backBoardDevInfoJson[currentBackBoardIndex ++].toObject(), 1);
}
else {
isRecvVideoData = true;
isPowerOnSend = false;
}
}
else {
currentJson = frontBoardDevInfoJson;
currentJsonItem = currentFrontBoardIndex;
if (currentFrontBoardIndex < frontBoardDevInfoJson.size()) {
sendDevInfoJsonItem(frontBoardDevInfoJson[currentFrontBoardIndex ++].toObject(), 1);
}
else
isPowerOnSend = false;
}
}
void ClientHandler::sendNextItem(QJsonArray& currentOneClickedItem)
{
QMutexLocker locker(&mutex);
isClickedSend = true;
//qDebug() << "------> locker(&mutex) :" << itemsProcessedCount;
//qDebug() << "------> currentItemIndex :" << currentItemIndex;
//qDebug() << "------> currentOneClickedItem.size() :" << currentOneClickedItem.size();
if (currentItemIndex < currentOneClickedItem.size()) {
currentJson = currentOneClickedItem;
currentJsonItem = currentItemIndex;
currentItem = currentOneClickedItem[currentItemIndex].toObject();
QString itemData = QJsonDocument(currentItem).toJson();
//qDebug() << "Sending item index:" << currentItemIndex << "data:" << itemData;
if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "DEL_USER") {
DelUserWindow dialog;
if (dialog.exec() == QDialog::Accepted) {
QString userInput = dialog.getUserInput();
if (!userInput.isEmpty() && currentItem.contains("val")) {
currentItem["val"] = userInput;
itemData = QJsonDocument(currentItem).toJson();
}
}
}
if (isBackBoardOrAllBoard) {
emit sendDataToSomeClient(isBackBoardOrAllBoard, itemData.toUtf8());
}
else {
emit sendDataToSomeClient(controlClientId, itemData.toUtf8());
}
if (currentItem.contains("timeout")) {
int timeout = currentItem.value("timeout").toInt();
if (timeout > 0) {
emit startTimeout(timeout);
}
}
else {
// 如果没有 timeout 字段,则不设置超时处理,一直等待数据接收
}
}
else if (isManualSend) {
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), itemsProcessedCount);
// 处理完毕后重置标记
isManualSend = false;
isClickedSend = false;
// 重置索引
resetCurrentItemIndex();
}
}
void ClientHandler::RNDISClient1Data(QByteArray& data) {
//qDebug() << " RNDISClient1Data size:" << data.size();
isRecvVideoData = false;
isStartVideo = false;
}
void ClientHandler::RNDISClient2Data(QByteArray& data) {
//qDebug() << " RNDISClient2Data size:" << data.size();
isRecvVideoData = true;
isStartVideo = true;
//qDebug() << " isRecvVideoData:" << isRecvVideoData;
}
void ClientHandler::RNDISClient3Data(QByteArray& data) {
//qDebug() << " RNDISClient3Data size:" << data.size();
isRecvVideoData = false;
isStartVideo = false;
}
void ClientHandler::RNDISClient4Data(QByteArray& data) {
//qDebug() << " RNDISClient4Data size:" << data.size();
isRecvVideoData = false;
isStartVideo = false;
}
bool ClientHandler::RNDISFirstData(QByteArray& data) {
//int clientType = data.at(0); // 根据实际数据格式提取标识
bool ret = true;
unsigned char clientType = static_cast<unsigned char>(data[10]);
//qDebug() << " clientType :" << clientType;
QByteArray tmpdata = data.left(11);
//qDebug() << " clientType :" << clientType << " tmpdata :" << tmpdata.toHex().data();
switch (clientType) {
case 0x01:
processDataFunction = &ClientHandler::RNDISClient1Data;
setThreadPriority(QThread::LowestPriority);
socket->setReadBufferSize(20 * 1024);
break;
case 0x02:
qDebug() << " clientId :" << clientId;
processDataFunction = &ClientHandler::RNDISClient2Data;
socket->setReadBufferSize(100 * 1024);
data = data.mid(11);
(this->*processDataFunction)(data);
setThreadPriority(QThread::HighPriority);
preVideoClientId = clientId;
//qDebug() << " clientType :" << clientType << " preVideoClientId :" << preVideoClientId << " tmpdata :" << tmpdata.toHex().data();
startReadVideoDataTimer(preVideoClientId);
break;
case 0x03:
processDataFunction = &ClientHandler::RNDISClient3Data;
setThreadPriority(QThread::LowPriority);
socket->setReadBufferSize(20 * 1024);
break;
case 0x04:
processDataFunction = &ClientHandler::RNDISClient4Data;
setThreadPriority(QThread::LowPriority);
socket->setReadBufferSize(20 * 1024);
controlClientId = clientId;
// 前板有设备连接自动发送获取设备信息
sendDevInfoItem();
break;
default:
qWarning() << "Unhandled client type:" << clientType;
ret = false;
break;
}
return ret;
}
void ClientHandler::onTimeoutRead()
{
onDataReceived();
}
void ClientHandler::checkThreadStatus()
{
if (!QThread::currentThread()->isRunning()) {
qCritical() << "Thread for clientId:" << clientId << "is not running!";
}
else {
qDebug() << "Thread for clientId:" << clientId << "is running normally.";
}
}
// 检查数据是否卡住
bool ClientHandler::isData_Stuck() const
{
return isDataStuck;
}
void ClientHandler::setThreadPriority(QThread::Priority priority) {
QThread* thread = QThread::currentThread();
if (thread) {
thread->setPriority(priority);
//qDebug() << "Thread priority set to" << priority << "for clientId:" << clientId;
}
else {
qWarning() << "Failed to set thread priority. Current thread is null.";
}
}
void ClientHandler::onPicRecvFinished()
{
if (currentJson != getPicJson && currentJson != frontBoardTest) {
currentItemIndex ++;
itemsProcessedCount ++;
qDebug() << "------> onPicRecvFinished " << __FUNCTION__;
sendNextItem(currentJson);
}
}
void ClientHandler::onDataReceived()
{
//qDebug() << "isRecvVideoData:" << isRecvVideoData;
//qDebug() << "isPowerOnSend: " << isPowerOnSend;
//qDebug() << "isClickedSend: " << isClickedSend;
//qDebug() << "isSingleSend: " << isSingleSend;
//qDebug() << "isRecvImgData: " << isRecvImgData;
if (!isRecvVideoData &&
(isRecvImgData || isPowerOnSend || isClickedSend || (isSingleSend && (currentItemIndex < currentJson.size())))) {
QByteArray allData;
while (socket->bytesAvailable() > 0) {
qint64 bytesAvailableBefore = socket->bytesAvailable();
//qDebug() << "Bytes available before read:" << bytesAvailableBefore << "clientId:" << clientId;
QByteArray buffer;
buffer.resize(qMin(bytesAvailableBefore, qint64(5 * 1024))); // 每次读取最多 5KB
qint64 bytesRead = socket->read(buffer.data(), buffer.size());
if (bytesRead > 0) {
buffer.resize(bytesRead);
allData.append(buffer);
qint64 bytesAvailableAfter = socket->bytesAvailable();
}
}
getCurrentItemLable();
//qDebug() << "------- currentItem.value(timeout):" << currentItem.value("timeout").toInt();
if ((currentItem.contains("timeout")) || (currentFuncItem.contains("timeout"))) {
//qDebug() << "currentItem.contains(timeout):" << currentItem.contains("timeout");
emit startTimeout(0);
}
QJsonObject currentTempItem = currentJson[currentItemIndex].toObject();
//qDebug() << "---Received allData size:" << allData.size();
if (!allData.isEmpty()) {
emit dataReceived(getClientAddress(), allData, 0xFF, currentItemIndex, currentFuncItemIndex, getCurrentItemLable(), "", currentJson, currentJsonItem);
if (!isSingleSend && !isPowerOnSend && (currentTempItem["cmd"] != "GET_IMG")) {
currentItemIndex ++;
itemsProcessedCount ++;
}
}
if (isSingleSend) {
if (currentTempItem["cmd"] != "GET_IMG") {
isSingleSend = false;
}
isClickedSend = false;
}
else if (isPowerOnSend) {
if (isBackBoardOrAllBoard) {
if (currentBackBoardIndex < backBoardDevInfoJson.size()) {
sendDevInfoItem();
}
else {
qDebug() << "All items processed in onDataReceived.";
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), currentBackBoardIndex);
isPowerOnSend = false;
}
}
else {
if (currentFrontBoardIndex < frontBoardDevInfoJson.size()) {
sendDevInfoItem();
}
else {
qDebug() << "All items processed in onDataReceived.";
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), currentFrontBoardIndex);
isPowerOnSend = false;
}
}
}
else if (isClickedSend && (currentItemIndex < currentJson.size())) {
// 判断是否是取图或者其他会接收很多数据的指令
if (currentTempItem["cmd"] != "GET_IMG") {
sendNextItem(currentJson);
}
}
else if(isClickedSend) {
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), itemsProcessedCount);
isClickedSend = false;
//resetCurrentItemIndex();
}
}
else if (isRecvVideoData && (!dataProcessingActive)) {
dataProcessingActive = true;
if ((isBackBoardOrAllBoard == 0) && !isStartVideo) {
isRecvVideoData = false;
}
QTimer::singleShot(0, this, &ClientHandler::processPendingData);
}
else if(!isRecvVideoData && !isRecvImgData){
if (preVideoClientId == clientId) {
qDebug() << "-----------------" << preVideoClientId << "isRecvVideoData:" << isRecvVideoData;
}
QByteArray AllData = socket->readAll();
if (isCommandError) {
isCommandError = false;
emit dataReceived(getClientAddress(), AllData, 0xFF, currentItemIndex, currentFuncItemIndex, "", "", currentJson, currentJsonItem);
}
//qDebug() << "--------- AllData.size():" << AllData.size();
}
}
void ClientHandler::processPendingData()
{
if (dataProcessingActive) {
try {
int maxIterations = 10; // 每次处理的最大次数
QByteArray allData;
while (socket->bytesAvailable() > 0 && maxIterations-- > 0) {
qint64 bytesAvailableBefore = socket->bytesAvailable();
//qDebug() << "Bytes available before read:" << bytesAvailableBefore << "clientId:" << clientId;
RETRY:
// 分块读取数据,避免一次性读取过多数据
QByteArray buffer;
buffer.resize(qMin(bytesAvailableBefore, qint64(5 * 1024))); // 每次读取最多 5KB
qint64 bytesRead = socket->read(buffer.data(), buffer.size());
if (bytesRead > 0) {
buffer.resize(bytesRead);
//qDebug() << "buffer.data():" << buffer.data();
allData.append(buffer);
qint64 bytesAvailableAfter = socket->bytesAvailable();
/*qDebug() << "--1--Received data size:" << buffer.size() << "clientId:" << clientId
<< "at" << QDateTime::currentDateTime().toString(Qt::ISODate)
<< "bytesAvailable after read:" << bytesAvailableAfter; */
if ((isBackBoardOrAllBoard == 0) && isFirstDataReceived) {
RNDISFirstData(buffer);
isFirstDataReceived = false;
}
if (bytesAvailableAfter > 9 * 1024) {
goto RETRY;
}
// 检查是否bytesAvailable没有变化避免无限循环
if (bytesAvailableBefore == bytesAvailableAfter) {
qCritical() << "Bytes available did not change after read, possible infinite loop for clientId:" << clientId;
break;
}
}
else {
qCritical() << "Failed to read data for clientId:" << clientId << ", bytesRead:" << bytesRead
<< ", socket error:" << socket->errorString();
break;
}
// 检查socket状态
if (socket->state() != QTcpSocket::ConnectedState) {
qCritical() << "Socket disconnected for clientId:" << clientId;
break;
}
}
if (!allData.isEmpty()) {
emit dataReceived(getClientAddress(), allData, 0xFF, currentItemIndex, currentFuncItemIndex, "", "", currentJson, currentJsonItem);
}
// 如果还有数据需要处理,继续调度处理任务
if (socket->bytesAvailable() > 0) {
QTimer::singleShot(0, this, &ClientHandler::processPendingData);
}
else {
dataProcessingActive = false;
}
//qDebug() << "Exiting processPendingData for clientId:" << clientId;
}
catch (const std::exception& e) {
qCritical() << "Exception caught in processPendingData for clientId:" << clientId << " - " << e.what();
dataProcessingActive = false;
}
catch (...) {
qCritical() << "Unknown exception caught in processPendingData for clientId:" << clientId;
dataProcessingActive = false;
}
}
}
void ClientHandler::onTimeout()
{
{
QMutexLocker locker(&mutex);
emit statusUpdated(isBackBoardOrAllBoard, getClientAddress(), false, currentJson, currentJsonItem);
//qDebug() << "isSingleSend:" << isSingleSend << "isPowerOnSend:" << isPowerOnSend;
if (!isSingleSend && !isPowerOnSend) {
currentItemIndex ++;
itemsProcessedCount ++;
}
}
if (isSingleSend) {
isSingleSend = false;
}
else if (isClickedSend) {
if (isBackBoardOrAllBoard) {
if (currentItemIndex < backBoardOneClickTest.size()) {
sendNextItem(currentJson);
}
else if (currentItemIndex >= backBoardOneClickTest.size()) {
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), itemsProcessedCount);
}
}
else {
if (currentItemIndex < frontBoardOneClickTest.size()) {
sendNextItem(currentJson);
}
else if (currentItemIndex >= frontBoardOneClickTest.size()) {
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), itemsProcessedCount);
}
}
}
else if (isPowerOnSend) {
if (isBackBoardOrAllBoard) {
if (currentBackBoardIndex < backBoardDevInfoJson.size()) {
sendDevInfoItem();
}
else {
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), currentBackBoardIndex);
currentFrontBoardIndex = 0;
currentBackBoardIndex = 0;
isPowerOnSend = false;
}
}
else {
if (currentFrontBoardIndex < frontBoardDevInfoJson.size()) {
sendDevInfoItem();
}
else {
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), currentFrontBoardIndex);
currentFrontBoardIndex = 0;
currentBackBoardIndex = 0;
isPowerOnSend = false;
}
}
}
qDebug() << "" << __FUNCTION__ << "------> itemsProcessedCount " << itemsProcessedCount;
}