// RecvDataHandler.cpp #include "SerialRecvDataHandler.h" #include "../Network/ClientHandler.h" SerialDataHandler::SerialDataHandler(QLabel* videoLabel, QLabel* video_Label_back, QLineEdit* VideoResolutionEdit, QLineEdit* VideoResolutionEdit_back, QSize labelSize, QMap* devInfoLineEdits, int isBackBoardOrAllBoard, QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig, QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson, QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson, QJsonArray getPicJson, QJsonArray getVideoJson, QObject* parent) : QObject(parent), videoLabel(videoLabel), video_Label_back(video_Label_back), VideoResolutionEdit(VideoResolutionEdit), VideoResolutionEdit_back(VideoResolutionEdit_back), labelSize(labelSize), devInfoLineEdits(devInfoLineEdits), isBackBoardOrAllBoard(isBackBoardOrAllBoard), frontBoardOneClickTest(frontBoardOneClickTest), frontBoardTest(frontBoardTest), frontBoardFuncConfig(frontBoardFuncConfig), frontBoardDevInfoJson(frontBoardDevInfoJson), frontBoardLicenseJson(frontBoardLicenseJson), backBoardOneClickTest(backBoardOneClickTest), backBoardTest(backBoardTest), backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson), backBoardUuidJson(backBoardUuidJson), getPicJson(getPicJson), getVideoJson(getVideoJson), buffer(new QByteArray()), picBuffer(new QByteArray()), ffmpegDecoder(new FFmpegDecoder()) // 初始化FFmpeg解码器 { //ffmpegDecoder->initialize(); // 初始化解码器 clearAllRecvData(); initializeMsgIdToCmdMap(); qDebug() << "SerialDataHandler thread created"; } SerialDataHandler::~SerialDataHandler() { qDebug() << "DataHandler thread destroyed start......"; if (ffmpegDecoder) { ffmpegDecoder->stopFFmpegDecoder(); ffmpegDecoder->requestInterruption(); ffmpegDecoder->wait(); // 等待解码器线程完成 delete ffmpegDecoder; ffmpegDecoder = nullptr; } delete buffer; buffer = nullptr; qDebug() << "DataHandler thread destroyed"; } void SerialDataHandler::handleOpenFocusWindow(int itemIndex) { if (ffmpegDecoder) { ffmpegDecoder->processVideo(itemIndex); // 调用 FFmpegDecoder 的处理函数 } } QByteArray SerialDataHandler::hexStringToByteArray(const QString& hexString) { QByteArray byteArray; for (int i = 0; i < hexString.length(); i += 2) { byteArray.append(static_cast(hexString.mid(i, 2).toUShort(nullptr, 16))); } return byteArray; } const QString filePath_1 = "/add1.h264"; // 显示视频的函数 void SerialDataHandler::showVideo(const QString& client, const QByteArray& valData) { QString h264filePath = QDir::currentPath() + filePath_1; static QFile file(h264filePath); if (!file.isOpen()) { if (QFile::exists(h264filePath)) { QFile::remove(h264filePath); } if (!file.open(QIODevice::Append | QIODevice::WriteOnly)) { qWarning() << "无法打开H264文件:" << file.errorString(); return; } } if (!valData.isEmpty()) { file.write(valData); file.flush(); // 刷新文件缓冲区 } if (!start_run) { ffmpegDecoder->initialize(); // 初始化解码器 start_run = 1; ffmpegDecoder->decodeFile(h264filePath, isBackBoardOrAllBoard, videoLabel, video_Label_back, VideoResolutionEdit, VideoResolutionEdit_back); } //ffmpegDecoder->decodeFile(filePath_1, videoLabel); } void SerialDataHandler::updateLineEdit(int msg_id, const QByteArray& actual_data) { QString dataStr = QString(actual_data.toHex(' ')); //licenseHwInfoEdit->setPlainText(dataStr); emit updateLicenseHwInfoEdit(dataStr); if (msgIdToCmdMap.contains(msg_id)) { QString cmd = msgIdToCmdMap[msg_id]; if (devInfoLineEdits->contains(cmd)) { QLineEdit* lineEdit = devInfoLineEdits->value(cmd); //lineEdit->setText(dataStr); QMetaObject::invokeMethod(lineEdit, "setText", Qt::QueuedConnection, Q_ARG(QString, dataStr)); } } } void SerialDataHandler::clearAllRecvData() { allRecvData = QByteArray(); remain = 0; dataLen = 0; } void SerialDataHandler::onUpdateTimeout(bool timeoutFlag) { isTimeout = timeoutFlag; } // 前板没有回复的话不能发送下一个,但是超时了我必须发下一个 // 处理接收到的数据 void SerialDataHandler::handleData(const QString& client, const QByteArray& recvData, int msg_id, int currentRecvItemIndex, int currentRecvFuncItemIndex, const QString& itemData, const QString& funcItemData, const QJsonArray& jsonArray, int itemJsonIndex, bool timeoutFlag) { //qDebug() << "Data received from" << client << ":" << recvData; #if 0 从文件中读取YUV数据 QFile file("output_2.txt"); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "Failed to open file:"; file.close(); return; } QByteArray recvdata = file.readAll(); // 读取文件中的数据 file.close(); qDebug() << "read file data size:" << recvdata.size(); #endif qDebug() << "---Received data size:" << recvData.size(); // 将接收到的数据追加到buffer buffer->append(recvData); while (buffer->size() >= 11) { // 至少需要11个字节来解析数据头 if (buffer->mid(0, 11) == QByteArray::fromHex("aa55aa5538010100000000")) { /*for (int i = 0; i < recvData.size(); i++) { qDebug() << "buffer->at(" << i << "):" << QString::number(static_cast(buffer->at(i)), 16).toUpper(); }*/ QByteArray payload; payload.append(static_cast(0x00)); // 构造发送的数据内容 bool heartBeat = true; emit sendHeartBeatData(payload, heartBeat); buffer->remove(0, 11); // 移除已处理的数据 //buffer->remove(0, recvData.size()); // 移除已处理的数据 emit statusUpdated(-2, client, true, jsonArray, itemJsonIndex); //break; continue; } else if (buffer->mid(0, 10) == QByteArray::fromHex("aa55aa55390103000000")) { buffer->remove(0, 13); // 移除已处理的数据 break; } else if ((buffer->mid(0, 6) == QByteArray::fromHex("aa55aa553701")) || (buffer->mid(0, 6) == QByteArray::fromHex("aa55aa551100")) || (buffer->mid(0, 6) == QByteArray::fromHex("aa55aa552100"))) { int dataSize = (static_cast(buffer->at(9)) << 24) | (static_cast(buffer->at(8)) << 16) | (static_cast(buffer->at(7)) << 8) | (static_cast(buffer->at(6))); if (buffer->size() >= dataSize + 10) buffer->remove(0, dataSize + 10); // 移除已处理的数据 break; } else if (buffer->mid(0, 4) == QByteArray::fromHex("aa55aa55")) { emit startTimeout(0); msg_id = (static_cast(buffer->at(5)) << 8) | (static_cast(buffer->at(4))); int dataSize = (static_cast(buffer->at(9)) << 24) | (static_cast(buffer->at(8)) << 16) | (static_cast(buffer->at(7)) << 8) | (static_cast(buffer->at(6))); qDebug() << "---Received dataSize:" << dataSize; //qDebug() << "---Received buffer->size():" << buffer->size(); //qDebug() << "---msg_id:" << QString::number(msg_id, 16).toUpper(); // 第11字节为返回 OK/NG bool success = (static_cast(buffer->at(10)) != 0x00); int totalSize = 10 + dataSize; // 数据头大小(10字节) + 实际数据大小 if (CurrentCommand == "GET_BACK_MAC") { //qDebug() << "--- getCommandNameFromValue:" << msg_id; if (!getCommandNameFromValue(msg_id)) { //qDebug() << "--- getCommandNameFromValue:" << msg_id; buffer->remove(0, buffer->size()); emit commandError(); break; } } if (buffer->size() >= totalSize) { //qDebug() << "--- getCommandNameFromValue:" << msg_id; // 调试查看收到的前19个字节 /*for (int i = 0; i < 11; i++) { qDebug() << "buffer->at(" << i << "):" << QString::number(static_cast(buffer->at(i)), 16).toUpper(); }*/ QByteArray data = buffer->mid(11, dataSize); QString hexString = QString::fromUtf8(data.toHex().data()); QByteArray actual_data = hexStringToByteArray(hexString); buffer->remove(0, totalSize); // 移除已处理的数据 qDebug() << "-------------------------------------------- isTimeout:" << isTimeout; if (!isTimeout) { if (msg_id != 0x0040 && msg_id != START_VIDEO && msg_id != GET_IMG && msg_id != VIDEO_TEST && msg_id != STOP_VIDEO) { qDebug() << "--- msg_id:" << QString::number(msg_id, 16).toUpper(); qDebug() << "--- clientLastMsgId.value(client, 0):" << clientLastMsgId.value(client, 0); qDebug() << "--- success:" << success; //qDebug() << "--- itemJsonIndex:" << itemJsonIndex; if ((msg_id != 0x0011 || clientLastMsgId.value(client, 0) != 0x0011) && (msg_id != 0x0021 || clientLastMsgId.value(client, 0) != 0x0021) && (msg_id != START_VIDEO || clientLastMsgId.value(client, 0) != START_VIDEO)) { //qDebug() << "Emitting statusUpdated for client:" << client << "with msg_id:" << QString::number(msg_id, 16).toUpper(); emit statusUpdated(-1, client, success, jsonArray, itemJsonIndex); emit recvNormalDataFlag(true); } clientLastMsgId[client] = msg_id; } handleCmd(msg_id, client, actual_data, jsonArray, itemJsonIndex); } } else { break; // 数据还不完整,等待下一次接收 } } else { buffer->remove(0, 1); // 移除无效数据头 } } } void SerialDataHandler::getCurrentSendItem(const QString& text) { CurrentCommand = text; } // 初始化映射表 std::map commandValueMap_serical = { {"FACE_ENROLL_SINGLE", FACE_ENROLL_SINGLE}, {"FACE_ENROLL", FACE_ENROLL}, {"HAND_ENROLL", HAND_ENROLL}, {"FACE_VERIFY", FACE_VERIFY}, {"HAND_VERIFY", HAND_VERIFY}, {"DEL_USER", DEL_USER}, {"DEL_ALLUSER", DEL_ALLUSER}, {"GET_USER", GET_USER}, {"GET_ALLUSER", GET_ALLUSER}, {"PASSWD_ENROLL", PASSWD_ENROLL}, {"IMG_ENROLL", IMG_ENROLL}, {"GET_IMG", GET_IMG}, {"START_VIDEO", START_VIDEO}, {"STOP_VIDEO", STOP_VIDEO}, {"TOUCH_TEST", TOUCH_TEST}, {"MIC_TEST", MIC_TEST}, {"SPK_TEST", SPK_TEST}, {"RADAR_TEST", RADAR_TEST}, {"NFC_TEST", NFC_TEST}, {"PR_SWITCH", PR_SWITCH}, {"PS_TEST", PS_TEST}, {"BACKLIGHT", BACKLIGHT}, {"IR_LED", IR_LED}, {"UART_TEST", UART_TEST}, {"PIR_TEST", PIR_TEST}, {"FACE_VERIFY_THRES", FACE_VERIFY_THRES}, {"FACE_THRES_LEVEL", FACE_THRES_LEVEL}, {"FACE_LIVE_THRES", FACE_LIVE_THRES}, {"FACE_ACC_THRES", FACE_ACC_THRES}, {"FACE_ACC_LEVEL", FACE_ACC_LEVEL}, {"FACE_DIS_RANGE", FACE_DIS_RANGE}, {"FACE_ANGLE_RANGE", FACE_ANGLE_RANGE}, {"GET_BACK_MAC", GET_BACK_MAC}, {"WRITE_BACK_UID_SN", WRITE_BACK_UID_SN} }; bool SerialDataHandler::getCommandNameFromValue(int receivedValue) { auto it = commandValueMap_serical.find(CurrentCommand); if (it != commandValueMap_serical.end()) { int expectedValue = it->second; if (expectedValue == receivedValue) { std::cout << "Match found: " << CurrentCommand.toStdString() << " corresponds to value " << std::hex << expectedValue << std::endl; return true; } else { std::cout << "Value mismatch: Expected " << std::hex << expectedValue << ", but received " << std::hex << receivedValue << std::endl; return false; } } else { std::cout << "Unknown command: " << CurrentCommand.toStdString() << std::endl; return false; } } void SerialDataHandler::initializeMsgIdToCmdMap() { msgIdToCmdMap[GET_FRONT_V851_VERSION] = "GET_FRONT_V851_VERSION"; msgIdToCmdMap[GET_FRONT_MCU_VERSION] = "GET_FRONT_MCU_VERSION"; msgIdToCmdMap[GET_FRONT_HW_VERSION] = "GET_FRONT_HW_VERSION"; msgIdToCmdMap[GET_FRONT_ALGO_VERSION] = "GET_FRONT_ALGO_VERSION"; msgIdToCmdMap[GET_FRONT_SN] = "GET_FRONT_SN"; msgIdToCmdMap[GET_BACK_V851_VERSION] = "GET_BACK_V851_VERSION"; msgIdToCmdMap[GET_BACK_806_VERSION] = "GET_BACK_806_VERSION"; msgIdToCmdMap[GET_BACK_HW_VERSION] = "GET_BACK_HW_VERSION"; } void SerialDataHandler::handleCmd(int msg_id, const QString& client, QByteArray actual_data, const QJsonArray& jsonArray, int itemJsonIndex) { if (msg_id < 0x0400) { handleFrontCmd(msg_id, client, actual_data, jsonArray, itemJsonIndex); } else if (msg_id < 0x0500) { handleDevInfo(msg_id, client, actual_data); } else if (msg_id < 0x0800) { //handleBackCmd(msg_id, client, actual_data, jsonArray, itemJsonIndex); } } void SerialDataHandler::handleFrontCmd(int msg_id, const QString& client, QByteArray actual_data, const QJsonArray& jsonArray, int itemJsonIndex) { switch (msg_id) { case FACE_ENROLL_SINGLE: {} break; case FACE_ENROLL: {} break; case HAND_ENROLL: {} break; case FACE_VERIFY: {} break; case HAND_VERIFY: {} break; case DEL_USER: {} break; case DEL_ALLUSER: {} break; case GET_USER: {} break; case GET_ALLUSER: {} break; case PASSWD_ENROLL: {} break; case IMG_ENROLL: {} break; case GET_IMG: { int lens_n = static_cast(actual_data[1]); int width = (static_cast(actual_data[3]) << 8) | static_cast(actual_data[2]); int height = (static_cast(actual_data[5]) << 8) | static_cast(actual_data[4]); int format = static_cast(actual_data[6]); qint32 picSize = width * height * 1.5; QByteArray yuvData = actual_data.mid(7); qDebug() << "showPic width * height * 1.5:" << picSize; qDebug() << "showPic picBuffer.size():" << picBuffer->size(); qDebug() << "showPic yuvData.size():" << yuvData.size(); if (yuvData.size() + picBuffer->size() == picSize) { emit picRecvFinished(); picBuffer->append(yuvData); showPic(labelSize, lens_n, width, height, format, picBuffer); QJsonObject currentTempItem = jsonArray[itemJsonIndex].toObject(); emit statusUpdated(-1, client, true, jsonArray, itemJsonIndex); picBuffer->remove(0, picSize); } else if (yuvData.size() + picBuffer->size() > picSize) { picBuffer->append(yuvData); qDebug() << "width is " << width << " height is " << height << "PIC size is" << picSize; qDebug() << "But recv PIC size is " << picBuffer->size(); picBuffer->remove(0, picBuffer->size()); } else { picBuffer->append(yuvData); } } break; case START_VIDEO: { if (!isStartVideo) { isStartVideo = ffmpegDecoder->isStartVideo; if (isStartVideo) { emit statusUpdated(-1, client, true, getVideoJson, 0); } } showVideo(client, actual_data); } break; case STOP_VIDEO: { isStartVideo = false; emit statusUpdated(-1, client, true, jsonArray, itemJsonIndex); /*qDebug() << "--- STOP_VIDEO Current path: " << QDir::currentPath(); QString filePath = QDir::currentPath() + "/add1.h264"; if (QFile::exists(filePath)) { QFile file(filePath); if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { qDebug() << "File add1.h264 cleared successfully."; } else { qDebug() << "Failed to clear file add1.h264:" << file.errorString(); } } else { qDebug() << "File add1.h264 does not exist."; }*/ } break; case TOUCH_TEST: {} break; case MIC_TEST: {} break; case SPK_TEST: {} break; case RADAR_TEST: {} break; case NFC_TEST: {} break; case PR_SWITCH: {} break; case PS_TEST: {} break; case BACKLIGHT: {} break; case IR_LED: {} break; case UART_TEST: {} break; case PIR_TEST: {} break; case FACE_VERIFY_THRES: {} break; case FACE_THRES_LEVEL: {} break; case FACE_LIVE_THRES: {} break; case FACE_ACC_THRES: {} break; case FACE_ACC_LEVEL: {} break; case FACE_DIS_RANGE: {} break; case FACE_ANGLE_RANGE: {} break; case HAND_VERIFY_THRES: {} break; case HANS_THRES_LEVEL: {} break; case HAND_LIVE_THRES: {} break; case USER_MAX_NUM: {} break; case ADMI_USER_MAX_NUM: {} break; case FACE_REPEAT: {} break; case HAND_REPEAT: {} break; case SET_IP: {} break; case SET_PORT: {} break; case SET_VOLUME: {} break; case SET_BACKLIGHT: {} break; case SET_RADAR_DIS: {} break; case SET_UART_BARTRATE: {} break; case SET_LOG_LEVEL: {} break; default: {} break; } } void SerialDataHandler::handleDevInfo(int msg_id, const QString& client, QByteArray actual_data) { qDebug() << "actual_data.size(): " << actual_data.size(); qDebug() << "actual_data: " << QString::fromUtf8(actual_data.toHex().data()); switch (msg_id) { case GET_FRONT_V851_VERSION: case GET_FRONT_MCU_VERSION: case GET_FRONT_HW_VERSION: case GET_FRONT_ALGO_VERSION: case GET_FRONT_SN: case GET_BACK_V851_VERSION: case GET_BACK_806_VERSION: case GET_BACK_HW_VERSION: /*case GET_BACK_SN: case GET_BACK_UID:*/ { // aa55aa5503041d00000048464d3231305f4b3431343234395f423230323031305f41302e302e38 qDebug() << "GET_DEV_INFO"; QString dataStr = QString::fromUtf8(actual_data); if (msgIdToCmdMap.contains(msg_id)) { QString cmd = msgIdToCmdMap[msg_id]; // 删掉注释闪退,暂时还未查到原因 qDebug() << "-----------------devInfoLineEdits-------------start"; //qDebug() << "devInfoLineEdits belongs to thread:" << devInfoLineEdits->thread(); qDebug() << "Current thread:" << QThread::currentThread(); if (devInfoLineEdits->contains(cmd)) { QLineEdit* lineEdit = devInfoLineEdits->value(cmd); //lineEdit->setText(dataStr); QMetaObject::invokeMethod(lineEdit, "setText", Qt::QueuedConnection, Q_ARG(QString, dataStr)); } qDebug() << "-----------------devInfoLineEdits-------------end"; } //qDebug() << "GET_DEV_INFO msg_id:" << QString::number(msg_id, 16).toUpper(); } break; case GET_FRONT_HW_INFO: { qDebug() << "GET_FRONT_HW_INFO"; QStringList hexList; QString dataStr; if (actual_data.size() == PIX_HARDWARE_INFO_BYTES) { for (int i = 0; i < actual_data.size(); ++i) { hexList << QString("0x%1").arg(static_cast(actual_data[i]), 2, 16, QLatin1Char('0')).toUpper().replace("0X", "0x"); } dataStr = hexList.join(", "); } else dataStr = "前板发送的 HW INFO 数据大小不正确"; QString displayText = dataStr; //licenseHwInfoEdit->setPlainText(displayText); emit updateLicenseHwInfoEdit(displayText); } break; case GET_BACK_MAC: { qDebug() << "GET_BACK_MAC"; QString dataStr; if (actual_data.size() == BACK_MAC_ADDRESS_LEN) { for (int i = 0; i < actual_data.size(); ++i) { char ch = static_cast(actual_data[i]); dataStr.append(ch); } } else dataStr = "后板发送的 MAC addr 数据大小不正确"; QString displayText = dataStr; emit updateUuidHwInfoEdit(displayText); } break; default: break; } }