// 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(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; }