// ClientHandler.cpp #include "ClientHandler.h" #include "../LicenseGenerate/LicenseConfirmWindow.h" #include "ImageEnrollWindow.h" #include "PasswordEnrollWindow.h" #if TEST_TCP_MOVE_TO_MAIN ClientHandler::ClientHandler(QTcpSocket* socket, 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), socket(socket), #else 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), #endif 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) { #if TEST_TCP_MOVE_TO_MAIN connect(socket, &QTcpSocket::readyRead, this, &ClientHandler::onDataReceived); connect(socket, &QTcpSocket::disconnected, this, &ClientHandler::onDisconnected); qint64 bufferSize = socket->socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption).toLongLong(); #endif } #if !TEST_TCP_MOVE_TO_MAIN void ClientHandler::initialize(QTcpSocket* socket) { this->socket = socket; connect(socket, &QTcpSocket::readyRead, this, &ClientHandler::onDataReceived); connect(socket, &QTcpSocket::disconnected, this, &ClientHandler::onDisconnected); // 其他的 socket 操作都将在这个线程中进行 } #endif ClientHandler::~ClientHandler() { 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); socket->deleteLater(); } 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; // 返回当前项的 "data" 字段 } QString ClientHandler::getCurrentItemLable() const { QString lable = currentItem.value("lable").toString(); //qDebug() << "Getting current item lable:" << lable; return lable; // 返回当前项的 "data" 字段 } 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::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, const QString text, const QString& itemType) { currentJson = jsonArray; currentJsonItem = itemIndex; QMutexLocker locker(&mutex); if (itemType == "License") { } isSingleSend = true; isClickedSend = true; isRecvImgData = false; if (itemType == "handleVideo") { if (itemIndex == 0) { isSingleSend = false; isClickedSend = false; } else { stopReadVideoDataTimer(preVideoClientId); } } if (itemType == "getPic") { isSingleSend = false; isClickedSend = false; isRecvImgData = true; } //qDebug() << "itemIndex:" << itemIndex; //qDebug() << "jsonArray.size():" << jsonArray.size(); if (itemIndex >= 0 && itemIndex < jsonArray.size()) { currentItemIndex = (itemType == "test") ? itemIndex : 0; currentFuncItemIndex = (itemType == "func") ? itemIndex : 0; QJsonObject 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; } } QString itemData = QJsonDocument(currentItem).toJson(); //emit sendData(itemData.toUtf8()); emit sendDataToSomeClient(controlClientId, itemData.toUtf8()); // 设置超时处理 if (currentItem.contains("timeout")) { int timeout = currentItem.value("timeout").toInt(); if (timeout > 0) { emit startTimeout(timeout); } } } } // 发送获取设备信息按键 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 (itemIndex < 0 || itemIndex >= frontBoardLicenseJson.size()) { qDebug() << "Invalid itemIndex"; return; } sendJsonItem(frontBoardLicenseJson, itemIndex, text, "License"); } void ClientHandler::sendUuidItem(int itemIndex, const QString text) { } // 发送单独一个功能配置 JSON 项目 void ClientHandler::sendFrontFuncItem(int itemIndex, const QString text) { //qDebug() << "sendFuncItem Text:" << text; sendJsonItem(frontBoardFuncConfig, itemIndex, text, "func"); } void ClientHandler::sendBackFuncItem(int itemIndex, const QString text) { //qDebug() << "sendFuncItem Text:" << text; sendJsonItem(backBoardFuncConfig, itemIndex, text, "func"); } // 发送单独一个测试配置 JSON 项目 void ClientHandler::sendFrontItem(int itemIndex) { QString text = ""; QJsonObject currentItem = frontBoardTest[itemIndex].toObject(); if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "IMG_ENROLL") { ImageEnrollWindow dialog; if (dialog.exec() == QDialog::Accepted) { text = dialog.getFilePath(); QByteArray imageData = dialog.getImageData(); if (!imageData.isEmpty()) { text = QString::fromUtf8(imageData); } } else { return; } } 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) { QString text = ""; QJsonObject currentItem = backBoardTest[itemIndex].toObject(); if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "IMG_ENROLL") { ImageEnrollWindow dialog; if (dialog.exec() == QDialog::Accepted) { text = dialog.getFilePath(); QByteArray imageData = dialog.getImageData(); if (!imageData.isEmpty()) { text = QString::fromUtf8(imageData); } } else { return; } } 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(backBoardTest, itemIndex, text, "test"); } void ClientHandler::sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemIndex) { QMutexLocker locker(&mutex); isPowerOnSend = true; qDebug() << "itemIndex:" << itemIndex; qDebug() << "jsonItem.size():" << jsonItem.size(); QString itemData = QJsonDocument(jsonItem).toJson(); //emit sendData(itemData.toUtf8()); 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 (1) { qDebug() << "frontBoardDevInfoJson.size():" << frontBoardDevInfoJson.size(); if (currentFrontBoardIndex < frontBoardDevInfoJson.size()) { sendDevInfoJsonItem(frontBoardDevInfoJson[currentFrontBoardIndex].toObject(), 1); currentFrontBoardIndex ++; } else isPowerOnSend = false; } // 后板 else { if (currentBackBoardIndex < backBoardDevInfoJson.size()) { sendDevInfoJsonItem(backBoardDevInfoJson[currentBackBoardIndex ++].toObject(), 1); } else isPowerOnSend = false; } } // 发送下一个 JSON 项目 void ClientHandler::sendNextItem() { //qDebug() << "------> start mutex :" << __FUNCTION__; QMutexLocker locker(&mutex); isClickedSend = true; qDebug() << "------> locker(&mutex) :" << itemsProcessedCount; if (currentItemIndex < frontBoardOneClickTest.size()) { currentJson = frontBoardOneClickTest; currentJsonItem = currentItemIndex; currentItem = frontBoardOneClickTest[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) { //qDebug() << "用户确认删除,关闭窗口"; QString userInput = dialog.getUserInput(); if (!userInput.isEmpty() && currentItem.contains("val")) { currentItem["val"] = userInput; itemData = QJsonDocument(currentItem).toJson(); } } } //emit sendData(itemData.toUtf8()); emit sendDataToSomeClient(controlClientId, itemData.toUtf8()); if (currentItem.contains("timeout")) { int timeout = currentItem.value("timeout").toInt(); if (timeout > 0) { qDebug() << "------> sendNextItem :" << itemsProcessedCount; emit startTimeout(timeout); } } else { // 如果没有 timeout 字段,则不设置超时处理,一直等待数据接收 } } else if (isManualSend) { emit allItemsProcessed(getClientAddress(), itemsProcessedCount); // 处理完毕后重置标记 isManualSend = false; isClickedSend = false; // 重置索引,可以再次一键功能测试 resetCurrentItemIndex(); } //qDebug() << "------> end mutex :" << __FUNCTION__; } 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(); //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::onDataReceived() { //qDebug() << "isRecvVideoData:" << isRecvVideoData; //qDebug() << "isPowerOnSend:" << isPowerOnSend; //qDebug() << "isClickedSend:" << isClickedSend; //qDebug() << "isSingleSend:" << isSingleSend; //qDebug() << "isRecvImgData:" << isRecvImgData; if (!isRecvVideoData && (isRecvImgData || isPowerOnSend || isClickedSend || (isSingleSend && (currentItemIndex < frontBoardTest.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(); } } if ((currentItem.contains("timeout")) || (currentFuncItem.contains("timeout"))) { emit startTimeout(0); } if (!allData.isEmpty()) { emit dataReceived(getClientAddress(), allData, 0xFF, currentItemIndex, currentFuncItemIndex, getCurrentItemLable(), "", currentJson, currentJsonItem); if (!isSingleSend && !isPowerOnSend) { currentItemIndex ++; itemsProcessedCount ++; } } if (isSingleSend) { isSingleSend = false; isClickedSend = false; } else if (isPowerOnSend && currentFrontBoardIndex < frontBoardDevInfoJson.size()) { sendDevInfoItem(); } else if (isPowerOnSend && currentBackBoardIndex < backBoardDevInfoJson.size()) { sendDevInfoItem(); } /*else if (isPowerOnSend) { qDebug() << "All items processed in onDataReceived."; emit allItemsProcessed(getClientAddress(), currentFrontBoardIndex); isPowerOnSend = false; }*/ else if (isClickedSend && (currentItemIndex < frontBoardOneClickTest.size())) { //qDebug() << "-------- start sendNextItem"; sendNextItem(); } else if(isClickedSend) { //qDebug() << "All items processed in onDataReceived."; emit allItemsProcessed(getClientAddress(), itemsProcessedCount); isClickedSend = false; //resetCurrentItemIndex(); } //qDebug() << "" << __FUNCTION__ << "------> itemsProcessedCount :" << itemsProcessedCount; } // 接收视频流数据 isRecvVideoData 置 0 else if (isRecvVideoData && (!dataProcessingActive)) { dataProcessingActive = true; if (!isStartVideo) { isRecvVideoData = false; } QTimer::singleShot(0, this, &ClientHandler::processPendingData); } else if(!isRecvVideoData && !isRecvImgData){ if (preVideoClientId == clientId) { qDebug() << "-----------------" << preVideoClientId << "isRecvVideoData:" << isRecvVideoData; } socket->readAll(); //QByteArray data = socket->readAll(); //qDebug() << "Received data:" << data; } } 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 (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() { //qDebug() << "------> start mutex :" << __FUNCTION__; { QMutexLocker locker(&mutex); // 获取当前项的 "data" 字段 //QString itemData = currentItem.value("data").toString(); //emit statusUpdated(socket->peerAddress().toString(), currentItemIndex, false, itemData); emit statusUpdated(getClientAddress(), currentItemIndex + 1, currentFuncItemIndex + 1, false, getCurrentItemLable(), getCurrentFuncItemLable(), currentJson, currentJsonItem); if (!isSingleSend && !isPowerOnSend) { currentItemIndex ++; itemsProcessedCount ++; } } if (isSingleSend) { isSingleSend = false; } else if (isPowerOnSend && currentFrontBoardIndex < frontBoardDevInfoJson.size()) { sendDevInfoItem(); } else if (isClickedSend && (currentItemIndex < frontBoardOneClickTest.size())) { //qDebug() << "------> onTimeout"; sendNextItem(); } else if(isClickedSend) { qDebug() << "All items processed in onTimeout."; emit allItemsProcessed(getClientAddress(), itemsProcessedCount); //resetCurrentItemIndex(); } else if (isPowerOnSend) { qDebug() << "All items processed in onTimeout."; emit allItemsProcessed(getClientAddress(), currentFrontBoardIndex); //resetCurrentItemIndex(); } //qDebug() << "------> end mutex :" << __FUNCTION__; qDebug() << "" << __FUNCTION__ << "------> itemsProcessedCount :" << itemsProcessedCount; }