767 lines
28 KiB
C++
767 lines
28 KiB
C++
// 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<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::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;
|
||
}
|