diff --git a/FactoryTestTool/FactoryTestTool.vcxproj b/FactoryTestTool/FactoryTestTool.vcxproj index c7a3424..6742ba2 100644 --- a/FactoryTestTool/FactoryTestTool.vcxproj +++ b/FactoryTestTool/FactoryTestTool.vcxproj @@ -25,7 +25,6 @@ - @@ -42,6 +41,7 @@ + @@ -58,7 +58,6 @@ - input @@ -70,12 +69,14 @@ input %(Filename).moc + + @@ -88,9 +89,6 @@ - - - @@ -106,6 +104,7 @@ + @@ -138,8 +137,6 @@ - - {2C8A5A59-2E79-4283-A0ED-D70DB305557E} diff --git a/FactoryTestTool/FactoryTestTool.vcxproj.filters b/FactoryTestTool/FactoryTestTool.vcxproj.filters index c9b8d1a..ebd5a7a 100644 --- a/FactoryTestTool/FactoryTestTool.vcxproj.filters +++ b/FactoryTestTool/FactoryTestTool.vcxproj.filters @@ -2,9 +2,6 @@ - - Misc - Network @@ -17,9 +14,6 @@ Media - - ParseDataHandler - Json @@ -80,11 +74,14 @@ Network\mdns\qmdnsengine\src + + Widget\UI_Widget + + + Network + - - Misc - Widget @@ -160,6 +157,9 @@ Network\mdns\qmdnsengine\src + + Network + @@ -205,14 +205,14 @@ Json\JsonFile + + Json\JsonFile + {4ab5db55-c173-4ad9-9d1b-0282a1a8d091} - - {92074ed4-f066-4b63-aef0-d1be4427262c} - {8f2d3c5e-4c9e-45a5-b3fa-6e3e5d18311c} @@ -225,9 +225,6 @@ {2eb24c40-5bd1-4e6f-a721-da4e45a46eff} - - {781ddcbd-b53c-4285-b70f-4d0d73d342cd} - {fe1a433b-7d7d-460e-b6d4-50e04dd25408} @@ -249,17 +246,14 @@ {e8857e15-2519-4a60-9fd5-eff901a76ba6} + + {ca263230-ea2f-4140-82aa-19b06eca1b1e} + Media - - ParseDataHandler - - - ParseDataHandler - Json diff --git a/FactoryTestTool/SourceCode/HotPlugListener.cpp b/FactoryTestTool/SourceCode/HotPlugListener.cpp deleted file mode 100644 index dc46034..0000000 --- a/FactoryTestTool/SourceCode/HotPlugListener.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "HotPlugListener.h" - -#include -#include -#include -#include - -#include - -#include "Windows.h" -#include "Dbt.h" -#include "SetupAPI.h" - -WId HotPlugListener::win_id_ = -1; - -QList HotPlugListener::guid_list_ = -{ - { 0xe5323777, 0xf976, 0x4f5b, { 0x9b, 0x55, 0xb9, 0x46, 0x99, 0xc4, 0x6e, 0x44 } }// KSCATEGORY_VIDEO_CAMERA GUID -}; - -HotPlugListener::HotPlugListener(WId win_id, QObject* parent) : QObject(parent) -{ - if (win_id_ == -1) win_id_ = win_id; - - this->registerForDeviceNotifications(); - - qApp->installNativeEventFilter(this); -} - -bool HotPlugListener::nativeEventFilter(const QByteArray& eventType, void* message, long* result) -{ - if (!(eventType == "windows_generic_MSG" || eventType == "windows_dispatcher_MSG")) - return false; - - MSG* msg = reinterpret_cast(message); - int msg_type = msg->message; - - if (msg_type != WM_DEVICECHANGE) return false; - - PDEV_BROADCAST_HDR lpdb = reinterpret_cast(msg->lParam); - - switch (msg->wParam) - { - case DBT_DEVICEARRIVAL: - if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) - { - PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)lpdb; - - QString serial_port_name{ QString::fromWCharArray((const wchar_t*)lpdbv->dbcp_name) }; - - qInfo() - << "=========== BEGIN ===========\n" - << "File: " << __FILE__ << "\n" - << "Line: " << __LINE__ << "\n" - << "Function: " << __FUNCTION__ << "\n" - << "Time: " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") << "\n" - << "检测到串口" << serial_port_name << "接入" << "\n" - << "=========== END ===========\n"; - - emit handleSerialPortHotPlugged(); - } - else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) - { - PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)lpdb; - - qInfo() - << "=========== BEGIN ===========\n" - << "File: " << __FILE__ << "\n" - << "Line: " << __LINE__ << "\n" - << "Function: " << __FUNCTION__ << "\n" - << "Time: " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") << "\n" - << "检测到摄像头("<< QString::fromWCharArray((const wchar_t*)lpdbv->dbcp_name) <<")接入" << "\n" - << "=========== END ===========\n"; - - emit handleCameraPluggedIn(); - } - break; - - case DBT_DEVICEREMOVECOMPLETE: - if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) - { - PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)lpdb; - - QString serial_port_name{ QString::fromWCharArray((const wchar_t*)lpdbv->dbcp_name) }; - - qInfo() - << "=========== BEGIN ===========\n" - << "File: " << __FILE__ << "\n" - << "Line: " << __LINE__ << "\n" - << "Function: " << __FUNCTION__ << "\n" - << "Time: " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") << "\n" - << "检测到串口" << serial_port_name << "已移除" << "\n" - << "=========== END ===========\n"; - - emit handleSerialPortHotPlugged(); - } - else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) - { - PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)lpdb; - - qInfo() - << "=========== BEGIN ===========\n" - << "File: " << __FILE__ << "\n" - << "Line: " << __LINE__ << "\n" - << "Function: " << __FUNCTION__ << "\n" - << "Time: " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") << "\n" - << "检测到摄像头(" << QString::fromWCharArray((const wchar_t*)lpdbv->dbcp_name) << ")移除" << "\n" - << "=========== END ===========\n"; - - emit handleCameraPluggedOut(); - } - break; - - default: - break; - } - - return false; -} - -void HotPlugListener::registerForDeviceNotifications() const -{ - for (int i{ 0 }; i < guid_list_.count(); i++) - { - DEV_BROADCAST_DEVICEINTERFACE filter; - filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); - filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - filter.dbcc_classguid = guid_list_.at(i); - - auto result = RegisterDeviceNotification((HWND)win_id_, &filter, DEVICE_NOTIFY_WINDOW_HANDLE); - } -} \ No newline at end of file diff --git a/FactoryTestTool/SourceCode/HotPlugListener.h b/FactoryTestTool/SourceCode/HotPlugListener.h deleted file mode 100644 index d19e9e5..0000000 --- a/FactoryTestTool/SourceCode/HotPlugListener.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include -#include - -typedef quintptr WId; -typedef struct _GUID GUID; - -/// @brief 检测串口、UVC和UAC设备的热插拔事件,通知其他组件。以注册Windows消息的方式实现 -class HotPlugListener : public QObject, public QAbstractNativeEventFilter -{ - Q_OBJECT - -public: - - /// @brief 使构造了HotPlugListener的窗口成为消息接收窗口 - /// @param win_id 构造了HotPlugListener的窗口的WID - /// @param parent 构造了HotPlugListener的窗口 - explicit HotPlugListener(WId win_id, QObject* parent = nullptr); - - bool nativeEventFilter(const QByteArray& eventType, void* message, long* result)override; - -signals: - - void handleSerialPortHotPlugged(); - void handleCameraPluggedIn(); - void handleCameraPluggedOut(); - -private: - - static WId win_id_; - static QList guid_list_; - - void registerForDeviceNotifications() const; -}; diff --git a/FactoryTestTool/SourceCode/Json/JsonFile/backBoardFuncConfig.json b/FactoryTestTool/SourceCode/Json/JsonFile/backBoardFuncConfig.json index 4e242d8..6e7b3bf 100644 --- a/FactoryTestTool/SourceCode/Json/JsonFile/backBoardFuncConfig.json +++ b/FactoryTestTool/SourceCode/Json/JsonFile/backBoardFuncConfig.json @@ -1,8 +1,38 @@ [ { - "cmd": "V851_SPK_TEST", + "cmd": "SET_VOLUME", + "val": 50, + "lable": "音量设置", + "timeout": 0 + }, + { + "cmd": "SET_BACKLIGHT", + "val": 50, + "lable": "前屏背光亮度", + "timeout": 0 + }, + { + "cmd": "SET_UART_BARTRATE", + "val": "115200", + "lable": "串口波特率", + "timeout": 0 + }, + { + "cmd": "MOTOR_TORQUE", + "val": 10, + "lable": "电机扭力", + "timeout": 0 + }, + { + "cmd": "BACK_HEAD_FALSE_OPEN", "val": 0, - "lable": "V851²⊔SPK", - "timeout": 2000 + "lable": "回头防误开", + "timeout": 0 + }, + { + "cmd": "SET_LOG_LEVEL", + "val": 50, + "lable": "log等级设置", + "timeout": 0 } ] \ No newline at end of file diff --git a/FactoryTestTool/SourceCode/Json/JsonFile/backBoardUuid.json b/FactoryTestTool/SourceCode/Json/JsonFile/backBoardUuid.json new file mode 100644 index 0000000..27cfdfa --- /dev/null +++ b/FactoryTestTool/SourceCode/Json/JsonFile/backBoardUuid.json @@ -0,0 +1,20 @@ +[ + { + "cmd": "GET_BACK_MAC", + "val": 0, + "lable": "获取后板MAC地址", + "timeout": 0 + }, + { + "cmd": "GET_BACK_UUID", + "val": 0, + "lable": "获取UUID", + "timeout": 0 + }, + { + "cmd": "GET_BACK_SN", + "val": 0, + "lable": "获取SN", + "timeout": 0 + } +] \ No newline at end of file diff --git a/FactoryTestTool/SourceCode/Json/JsonFile/backDevInfo.json b/FactoryTestTool/SourceCode/Json/JsonFile/backDevInfo.json index fb9b018..c4382f1 100644 --- a/FactoryTestTool/SourceCode/Json/JsonFile/backDevInfo.json +++ b/FactoryTestTool/SourceCode/Json/JsonFile/backDevInfo.json @@ -17,6 +17,12 @@ "lable": "后板硬件版本:", "timeout": 2000 }, + { + "cmd": "GET_BACK_MAC", + "val": 0, + "lable": "后板MAC地址:", + "timeout": 2000 + }, { "cmd": "GET_BACK_SN", "val": 0, diff --git a/FactoryTestTool/SourceCode/Json/JsonFile/frontBoardLicense.json b/FactoryTestTool/SourceCode/Json/JsonFile/frontBoardLicense.json index 00cdeae..1b7e298 100644 --- a/FactoryTestTool/SourceCode/Json/JsonFile/frontBoardLicense.json +++ b/FactoryTestTool/SourceCode/Json/JsonFile/frontBoardLicense.json @@ -1,19 +1,19 @@ [ { "cmd": "GET_FRONT_HW_INFO", - "val": 0, + "val": "0", "lable": "get_hw_info", "timeout": 0 }, { "cmd": "GET_FRONT_LICENSE", - "val": 0, + "val": "0", "lable": "get_license", "timeout": 0 }, { "cmd": "WRITE_FRONT_LICENSE", - "val": 0, + "val": "0", "lable": "write_license", "timeout": 0 } diff --git a/FactoryTestTool/SourceCode/Json/readJsonFile.cpp b/FactoryTestTool/SourceCode/Json/readJsonFile.cpp index 9bfdc69..5fa77bc 100644 --- a/FactoryTestTool/SourceCode/Json/readJsonFile.cpp +++ b/FactoryTestTool/SourceCode/Json/readJsonFile.cpp @@ -5,12 +5,12 @@ QJsonArray readJsonArrayFromFile(const QString& filePath) QJsonArray jsonArray; QFile file(filePath); if (file.open(QIODevice::ReadOnly)) { - qDebug() << "Successfully opened" << filePath; + qDebug() << "Successfully opened" << filePath ; QByteArray data = file.readAll(); QJsonDocument doc = QJsonDocument::fromJson(data); if (!doc.isNull() && doc.isArray()) { jsonArray = doc.array(); - qDebug() << filePath << "JSON array size:" << jsonArray.size(); + qDebug() << "JSON array size:" << jsonArray.size(); } else { qDebug() << "Failed to parse JSON document from" << filePath; @@ -67,6 +67,10 @@ QJsonArray readJson_backDevInfo() { return readJsonArrayFromFile("./SourceCode/Json/JsonFile/backDevInfo.json"); } +QJsonArray readJson_backUuid() { + return readJsonArrayFromFile("./SourceCode/Json/JsonFile/backBoardUuid.json"); +} + QJsonArray readJson_getPic() { return readJsonArrayFromFile("./SourceCode/Json/JsonFile/getPic.json"); } diff --git a/FactoryTestTool/SourceCode/Json/readJsonFile.h b/FactoryTestTool/SourceCode/Json/readJsonFile.h index 1258c1c..d08a415 100644 --- a/FactoryTestTool/SourceCode/Json/readJsonFile.h +++ b/FactoryTestTool/SourceCode/Json/readJsonFile.h @@ -17,6 +17,7 @@ QJsonArray readJson_backBoardOneClickTest(); QJsonArray readJson_backBoardTest(); QJsonArray readJson_backBoardFuncConfig(); QJsonArray readJson_backDevInfo(); +QJsonArray readJson_backUuid(); QJsonArray readJson_testConfig(); QJsonArray readJson_funcConfig(); diff --git a/FactoryTestTool/SourceCode/LicenseGenerate/LicenseGenerate.cpp b/FactoryTestTool/SourceCode/LicenseGenerate/LicenseGenerate.cpp index efc366f..0a75cb3 100644 --- a/FactoryTestTool/SourceCode/LicenseGenerate/LicenseGenerate.cpp +++ b/FactoryTestTool/SourceCode/LicenseGenerate/LicenseGenerate.cpp @@ -40,7 +40,7 @@ bool licenseGenerate(const unsigned char* hardware_info, unsigned char* license_ } printf("\n"); // return 限制不调用 pix_license_generate, 防止减少license个数 - return false; + //return false; int ret = pix_license_generate(hardware_info, PIX_HARDWARE_INFO_BYTES, license_info, PIX_LICENCE_BYTES); if (ret != SDK_CODE_OK) { diff --git a/FactoryTestTool/SourceCode/Network/ClientHandler.cpp b/FactoryTestTool/SourceCode/Network/ClientHandler.cpp index 759efd9..39c7c70 100644 --- a/FactoryTestTool/SourceCode/Network/ClientHandler.cpp +++ b/FactoryTestTool/SourceCode/Network/ClientHandler.cpp @@ -4,19 +4,24 @@ #include "ImageEnrollWindow.h" #include "PasswordEnrollWindow.h" -ClientHandler::ClientHandler(QTcpSocket* socket, QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig, - QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson, QJsonArray backBoardDevInfoJson, +ClientHandler::ClientHandler(QTcpSocket* socket, + QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig, + QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson, + QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, + QJsonArray backBoardDevInfoJson, QJsonArray getPicJson, QJsonArray getVideoJson, int clientId, QObject* parent) : QObject(parent), socket(socket), frontBoardOneClickTest(frontBoardOneClickTest), frontBoardTest(frontBoardTest), frontBoardFuncConfig(frontBoardFuncConfig), frontBoardDevInfoJson(frontBoardDevInfoJson), frontBoardLicenseJson(frontBoardLicenseJson), - backBoardDevInfoJson(backBoardDevInfoJson), getPicJson(getPicJson), - getVideoJson(getVideoJson), currentItemIndex(0), clientId(clientId), + backBoardOneClickTest(backBoardOneClickTest), backBoardTest(backBoardTest), + backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson), + getPicJson(getPicJson), getVideoJson(getVideoJson), + currentItemIndex(0), clientId(clientId), isManualSend(false), isSingleSend(false), isClickedSend(false), size(0), isFirstDataReceived(true), processDataFunction(nullptr), - isDataStuck(false), dataProcessingActive(false), isRecvVideoData(false), - currentFrontBoardIndex(0), + isDataStuck(false), dataProcessingActive(false), isRecvVideoData(true), + currentFrontBoardIndex(0), currentLicenseIndex(0), currentUuidIndex(0), currentBackBoardIndex(0) { connect(socket, &QTcpSocket::readyRead, this, &ClientHandler::onDataReceived); @@ -24,30 +29,12 @@ ClientHandler::ClientHandler(QTcpSocket* socket, QJsonArray frontBoardOneClickTe qint64 bufferSize = socket->socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption).toLongLong(); - /*connect(socket, QOverload::of(&QTcpSocket::error), - this, &ClientHandler::onSocketError);*/ } ClientHandler::~ClientHandler() { qDebug() << "ClientHandler destroyed for clientId:" << clientId; - if (readTimer) { - readTimer->stop(); - delete readTimer; - } - if (threadStatusTimer) { - threadStatusTimer->stop(); - delete threadStatusTimer; - } - if (connectionCheckTimer) { - connectionCheckTimer->stop(); - delete connectionCheckTimer; - } } -//void ClientHandler::onSocketError(QAbstractSocket::SocketError socketError) { -// qWarning() << "-------------------------------Socket error:" << socketError << "clientId:" << clientId; -//} - void ClientHandler::startReadVideoDataTimer() { emit startReadTimer(clientId); @@ -127,9 +114,17 @@ void ClientHandler::start() sendNextItem(); } +void ClientHandler::sendDataToClient(const QByteArray& data) +{ + emit sendData(data); +} + void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, const QString text, const QString& itemType) { - QMutexLocker locker(&mutex); + QMutexLocker locker(&mutex); + if (itemType == "License") { + + } isSingleSend = true; isClickedSend = true; if (itemType == "handleVideo") { @@ -147,6 +142,7 @@ void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, con 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); @@ -162,7 +158,8 @@ void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, con } } QString itemData = QJsonDocument(currentItem).toJson(); - emit sendData(itemData.toUtf8()); + //emit sendData(itemData.toUtf8()); + sendDataToSomeClient(controlClientId, itemData.toUtf8()); // 设置超时处理 if (currentItem.contains("timeout")) { @@ -194,7 +191,7 @@ void ClientHandler::sendGetVideoItem(int itemIndex, int video_flag) } // 发送License处理按键 -void ClientHandler::sendLicenseItem(int itemIndex) +void ClientHandler::sendLicenseItem(int itemIndex, const QString text) { if (itemIndex < 0 || itemIndex >= frontBoardLicenseJson.size()) { qDebug() << "Invalid itemIndex"; @@ -205,23 +202,34 @@ void ClientHandler::sendLicenseItem(int itemIndex) if (label == "write_license") { LicenseConfirmWindow dialog("你确定要发送此授权项吗?"); if (dialog.exec() == QDialog::Accepted) { - sendJsonItem(frontBoardLicenseJson, itemIndex, "", "License"); + sendJsonItem(frontBoardLicenseJson, itemIndex, text, "License"); } } else { - sendJsonItem(frontBoardLicenseJson, itemIndex, "", "License"); + sendJsonItem(frontBoardLicenseJson, itemIndex, text, "License"); } } +void ClientHandler::sendUuidItem(int itemIndex, const QString text) +{ + +} + // 发送单独一个功能配置 JSON 项目 -void ClientHandler::sendFuncItem(int itemIndex, const QString text) +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::sendItem(int itemIndex) +void ClientHandler::sendFrontItem(int itemIndex) { QString text = ""; QJsonObject currentItem = frontBoardTest[itemIndex].toObject(); @@ -262,6 +270,47 @@ void ClientHandler::sendItem(int itemIndex) 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); @@ -270,7 +319,8 @@ void ClientHandler::sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemInd qDebug() << "jsonItem.size():" << jsonItem.size(); QString itemData = QJsonDocument(jsonItem).toJson(); - emit sendData(itemData.toUtf8()); + //emit sendData(itemData.toUtf8()); + sendDataToSomeClient(controlClientId, itemData.toUtf8()); if (jsonItem.contains("timeout")) { int timeout = jsonItem.value("timeout").toInt(); @@ -281,9 +331,16 @@ void ClientHandler::sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemInd else { // 如果没有 timeout 字段,则不设置超时处理,一直等待数据接收 } - } +//void ClientHandler::sendLicenseItem() +//{ +// if (currentLicenseIndex < frontBoardLicenseJson.size()) { +// +// currentLicenseIndex ++; +// } +//} + void ClientHandler::sendDevInfoItem() { // 前板 @@ -328,7 +385,8 @@ void ClientHandler::sendNextItem() } } } - emit sendData(itemData.toUtf8()); + //emit sendData(itemData.toUtf8()); + sendDataToSomeClient(controlClientId, itemData.toUtf8()); if (currentItem.contains("timeout")) { int timeout = currentItem.value("timeout").toInt(); @@ -388,6 +446,7 @@ bool ClientHandler::RNDISFirstData(QByteArray& data) { data = data.mid(11); (this->*processDataFunction)(data); setThreadPriority(QThread::HighPriority); + preVideoClientId = clientId; break; case 0x03: processDataFunction = &ClientHandler::RNDISClient3Data; @@ -396,8 +455,9 @@ bool ClientHandler::RNDISFirstData(QByteArray& data) { break; case 0x04: processDataFunction = &ClientHandler::RNDISClient4Data; - setThreadPriority(QThread::LowestPriority); + setThreadPriority(QThread::LowPriority); socket->setReadBufferSize(20 * 1024); + controlClientId = clientId; break; default: qWarning() << "Unhandled client type:" << clientType; @@ -479,9 +539,13 @@ void ClientHandler::onDataReceived() 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); @@ -502,6 +566,7 @@ void ClientHandler::onDataReceived() // 接收视频流数据 isRecvVideoData 置 0 else if (isRecvVideoData && (!dataProcessingActive)) { dataProcessingActive = true; + isRecvVideoData = false; QTimer::singleShot(0, this, &ClientHandler::processPendingData); } else { diff --git a/FactoryTestTool/SourceCode/Network/ClientHandler.h b/FactoryTestTool/SourceCode/Network/ClientHandler.h index ddbaa2a..a661d01 100644 --- a/FactoryTestTool/SourceCode/Network/ClientHandler.h +++ b/FactoryTestTool/SourceCode/Network/ClientHandler.h @@ -31,7 +31,8 @@ class ClientHandler : public QObject, public QRunnable public: explicit ClientHandler(QTcpSocket* socket, QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig, QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson, - QJsonArray backBoardDevInfoJson, QJsonArray getPicJson, QJsonArray getVideoJson, + QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardDevInfoJson, + QJsonArray getPicJson, QJsonArray getVideoJson, int clientId, QObject* parent = nullptr); ~ClientHandler(); @@ -54,13 +55,17 @@ public: // 发送拉视频流按键 void sendGetVideoItem(int itemIndex, int video_flag); // 发送License处理按键 - void sendLicenseItem(int itemIndex); + void sendLicenseItem(int itemIndex, const QString text); + void sendUuidItem(int itemIndex, const QString text); // 发送下一个功能配置 JSON 项目 - void sendFuncItem(int itemIndex, QString text); + void sendFrontFuncItem(int itemIndex, QString text); + void sendBackFuncItem(int itemIndex, QString text); // 发送下一个 JSON 项目 void sendNextItem(); // 处理发送单独指令 - void sendItem(int itemIndex); + void sendFrontItem(int itemIndex); + void sendBackItem(int itemIndex); + //void sendLicenseItem(); // 获取客户端的 ID int getClientId() const { return clientId; } // 获取当前客户端的地址 @@ -75,7 +80,7 @@ public: QString getCurrentFuncItemLable() const; // 重置索引 void resetCurrentItemIndex(); - // 处理 RingBuffer 中的数据 + void sendDataToClient(const QByteArray& data); //void processRingBufferData(); void setThreadPriority(QThread::Priority priority); @@ -98,6 +103,7 @@ signals: void selectClientDisconnected(int clientId); void startReadTimer(int clientId); void stopReadTimer(int clientId); + void sendDataToSomeClient(int clientId, const QByteArray& data); public slots: // 处理数据接收 @@ -120,6 +126,9 @@ private: QJsonArray frontBoardFuncConfig; // 前板功能配置参数 JSON QJsonArray frontBoardDevInfoJson; // 前板设备信息参数 JSON QJsonArray frontBoardLicenseJson; // 前板license信息 JSON + QJsonArray backBoardOneClickTest; // 后板一键功能测试 JSON + QJsonArray backBoardTest; // 后板单项测试 JSON + QJsonArray backBoardFuncConfig; // 后板功能配置参数 JSON QJsonArray backBoardDevInfoJson; // 后板设备信息参数 JSON QJsonArray jsonConfig; // 测试区 JSON 配置 QJsonArray funcJsonConfig; // 功能区 JSON 配置 @@ -129,6 +138,8 @@ private: int currentItemIndex; // 当前处理的测试 JSON 项目索引 int currentFuncItemIndex; // 当前处理的功能 JSON 项目索引 int clientId; // 新增的客户端编号 + int preVideoClientId = 0; + int controlClientId = 1; int itemsProcessedCount; // 跟踪处理项目的数量 QJsonObject currentItem; // 测试 json文件中当前发送的项 QJsonObject currentFuncItem; // 功能 json文件中当前发送的项 @@ -143,6 +154,8 @@ private: int size; int currentFrontBoardIndex; // 当前发送的前板设备信息项的索引 int currentBackBoardIndex; // 当前发送的后板设备信息项的索引 + int currentLicenseIndex; + int currentUuidIndex; void checkThreadStatus(); bool isFirstDataReceived; @@ -157,10 +170,6 @@ private: void sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemIndex); //void sendDevInfoItem(); - QTimer* readTimer; - QTimer* threadStatusTimer; - QTimer* connectionCheckTimer; - bool isDataStuck; bool dataProcessingActive; }; diff --git a/FactoryTestTool/SourceCode/Network/httpClient.cpp b/FactoryTestTool/SourceCode/Network/httpClient.cpp new file mode 100644 index 0000000..7e4bb5d --- /dev/null +++ b/FactoryTestTool/SourceCode/Network/httpClient.cpp @@ -0,0 +1,38 @@ +// httpClient.cpp +#include +#include "httpClient.h" + +HttpClient::HttpClient(QObject* parent) + : QObject(parent), + networkManager(new QNetworkAccessManager(this)) +{ + connect(networkManager, &QNetworkAccessManager::finished, this, &HttpClient::onNetworkReplyFinished); +} + +void HttpClient::sendPostRequest(const QNetworkRequest& request, const QByteArray& jsonData) +{ + qDebug() << "jsonData" << jsonData.data(); + networkManager->post(request, jsonData); +} + +void HttpClient::sendGetRequest(const QNetworkRequest& request) +{ + networkManager->get(request); +} + +void HttpClient::onNetworkReplyFinished(QNetworkReply* reply) +{ + if (reply->error() == QNetworkReply::NoError) { + QByteArray responseData = reply->readAll(); + QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData); + QJsonObject jsonObject = jsonResponse.object(); + qDebug() << "jsonObject: " << jsonObject; + emit requestFinished(jsonObject); + } + else { + qDebug() << "reply->error(): " << reply->error(); + qDebug() << "errorString: " << reply->errorString(); + emit requestError(reply->errorString()); + } + reply->deleteLater(); +} diff --git a/FactoryTestTool/SourceCode/Network/httpClient.h b/FactoryTestTool/SourceCode/Network/httpClient.h new file mode 100644 index 0000000..972b200 --- /dev/null +++ b/FactoryTestTool/SourceCode/Network/httpClient.h @@ -0,0 +1,34 @@ +// httpClient.h +#ifndef HTTPCLIENT_H +#define HTTPCLIENT_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +class HttpClient : public QObject +{ + Q_OBJECT +public: + explicit HttpClient(QObject* parent = nullptr); + void sendPostRequest(const QNetworkRequest& request, const QByteArray& jsonData); + void sendGetRequest(const QNetworkRequest& request); + +signals: + void requestFinished(const QJsonObject& response); + void requestError(const QString& errorString); + +private slots: + void onNetworkReplyFinished(QNetworkReply* reply); + +private: + QNetworkAccessManager* networkManager; +}; + +#endif // HTTPCLIENT_H diff --git a/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.cpp b/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.cpp index 6a78b23..34d1ca7 100644 --- a/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.cpp +++ b/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.cpp @@ -127,10 +127,11 @@ void DataHandler::handleData(const QString& client, const QByteArray& recvData, if (buffer->size() >= totalSize) { // 去掉前面 11 字节 - //QByteArray data = buffer->mid(11, dataSize); - QByteArray data = buffer->mid(10, dataSize); + QByteArray data = buffer->mid(11, dataSize); + //QByteArray data = buffer->mid(10, dataSize); QString hexString = QString::fromUtf8(data.toHex().data()); QByteArray actual_data = hexStringToByteArray(hexString); + //qDebug() << "---Received hexString:" << hexString; buffer->remove(0, totalSize); // 移除已处理的数据 // 暂时设置 NG // 同一个client仅当 msg_id 不连续为 0x11/0x21 或第一次处理时才执行 emit statusUpdated @@ -465,8 +466,20 @@ void DataHandler::handleDevInfo(int msg_id, const QString& client, QByteArray ac case GET_FRONT_HW_INFO: { qDebug() << "GET_FRONT_HW_INFO"; - QString dataStr = QString(actual_data.toHex(' ')); - QString displayText = "get_hw_info:\n" + dataStr; + //QString dataStr = QString(actual_data.toHex(' ')); + QStringList hexList; + QString dataStr; + qDebug() << "actual_data.size(): " << actual_data.size(); + qDebug() << "actual_data: " << QString::fromUtf8(actual_data.toHex().data()); + 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); } break; diff --git a/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.h b/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.h index dab9afb..d83b5dd 100644 --- a/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.h +++ b/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.h @@ -19,9 +19,10 @@ #include #include #include + #include "../Media/Media.h" -#include "../ParseDataHandler/msgID.h" #include "../Media/VideoDecoder/FFmpegDecoder.h" +#include "../LicenseGenerate/LicenseGenerate.h" #include "MsgTpye.h" #define YUV420 1 diff --git a/FactoryTestTool/SourceCode/Widget/MainWidget.cpp b/FactoryTestTool/SourceCode/Widget/MainWidget.cpp index 47472bf..66f2708 100644 --- a/FactoryTestTool/SourceCode/Widget/MainWidget.cpp +++ b/FactoryTestTool/SourceCode/Widget/MainWidget.cpp @@ -20,7 +20,8 @@ MainWidget::MainWidget(QWidget* parent) : lastClickedGetVideoCamIndex(-1), lastClickedGetVideoDevIndex(-1), mServiceProvider(new ServiceProvider(this)), - mdnsTimer(new QTimer(this)) + mdnsTimer(new QTimer(this)), + httpClient(new HttpClient(this)) #if TEST_UDP_BROADCAST ,multicastSocket(new QUdpSocket(this)), multicastTimer(new QTimer(this)) @@ -29,14 +30,22 @@ MainWidget::MainWidget(QWidget* parent) : leftLens_imageLabel = new QLabel(this); rightLens_imageLabel = new QLabel(this); videoLabel = new QLabel(this); - funcConfigLineEdit = new QLineEdit(this); + frontFuncConfigLineEdit = new QLineEdit(this); + backFuncConfigLineEdit = new QLineEdit(this); licenseHwInfoEdit = new QTextEdit(this); + UuidHwInfoEdit = new QTextEdit(this); setupUI(); // 打印线程池状态信息 setupTimerForThreadPoolInfo(); server = new QTcpServer(this); + //FactoryToolSendGetUuidToHttpServer(); + //FactoryToolSendGetLicenseToHttpServer(); + //FactoryToolSendPostComfirmToHttpServer(); + //FactoryToolSendPostTestToHttpServer(); + //FactoryToolSendPostLicenseToHttpServer(); + connect(server, &QTcpServer::newConnection, this, [this]() { // 检查是否有挂起的连接 while (server->hasPendingConnections()) { @@ -69,7 +78,8 @@ MainWidget::MainWidget(QWidget* parent) : QThread* thread = new QThread(this); ClientHandler* handler = new ClientHandler(socket, frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig, - frontBoardDevInfoJson, frontBoardLicenseJson, backBoardDevInfoJson, + frontBoardDevInfoJson, frontBoardLicenseJson, + backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson, getPicJson, getVideoJson, clientId, nullptr); // 将 ClientHandler 移动到线程池中的线程 @@ -82,7 +92,20 @@ MainWidget::MainWidget(QWidget* parent) : // 将sendData信号连接到主线程中的槽上 connect(handler, &ClientHandler::sendData, this, [socket](const QByteArray& data) { - socket->write(data); + /*socket->write(data); + socket->flush();*/ + //qDebug() << "---------------------data.size():" << data.size(); + QByteArray prefix; + QDataStream stream(&prefix, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << quint32(0x55AA55AA); + stream << quint16(0x0420); + stream << quint32(data.size()); + prefix.append(data); + + qDebug() << "Sending data:" << prefix.toHex(); + + socket->write(prefix); socket->flush(); }); @@ -106,8 +129,8 @@ MainWidget::MainWidget(QWidget* parent) : connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData); connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated); - connect(handler, &ClientHandler::startReadTimer, this, &MainWidget::startClientReadTimer); - connect(handler, &ClientHandler::stopReadTimer, this, &MainWidget::stopClientReadTimer); + connect(handler, &ClientHandler::startReadTimer, this, &MainWidget::startClientReadTimer); + connect(handler, &ClientHandler::stopReadTimer, this, &MainWidget::stopClientReadTimer); // 创建和管理定时器 QTimer* readTimer = new QTimer(this); @@ -115,9 +138,14 @@ MainWidget::MainWidget(QWidget* parent) : // readTimer->start(10); // 每 10ms 触发一次 // 将定时器存储到哈希表中,方便管理 clientReadTimers[clientId] = readTimer; + + connect(handler, &ClientHandler::sendDataToSomeClient, this, &MainWidget::sendDataToClient); } }); + connect(httpClient, &HttpClient::requestFinished, this, &MainWidget::onHttpRequestFinished); + connect(httpClient, &HttpClient::requestError, this, &MainWidget::onHttpRequestError); + threadStatusTimer = new QTimer(this); connect(threadStatusTimer, &QTimer::timeout, this, &MainWidget::onCheckThreadStatus); //threadStatusTimer->start(100); // 每100ms检查一次线程状态 @@ -196,6 +224,223 @@ MainWidget::~MainWidget() qDebug() << "MainWidget destroyed"; } +// 服务器响应 +void MainWidget::onHttpRequestFinished(const QJsonObject& response) +{ + isRequestSuccessful = 0; + if (response.contains("msg") && response["msg"].toString() == "ok") { + if (response.contains("data") && response["data"].isObject()) { + licenseDataArray = response["data"].toObject(); + isRequestSuccessful = 1; + } + } + else + isRequestSuccessful = 2; +} + +void MainWidget::onHttpRequestError(const QString& errorString) +{ + qWarning() << "HTTP request failed:" << errorString; + isRequestSuccessful = 2; +} + +QString generateRandomRequestID() { + const QString possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~"; + int length = QRandomGenerator::global()->bounded(1, 33); // 生成长度在1到32之间 + QString randomString; + for (int i = 0; i < length; ++i) { + int index = QRandomGenerator::global()->bounded(possibleCharacters.size()); + randomString.append(possibleCharacters.at(index)); + } + qDebug() << "randomString request_id:" << randomString; + return randomString; +} + +QString HmacSha256ToBase64(const QString& data, const QString& secret) { + QByteArray keyBytes = secret.toUtf8(); + QByteArray dataBytes = data.toUtf8(); + + // 使用 HMAC-SHA256 计算哈希值 + QByteArray hash = QMessageAuthenticationCode::hash(dataBytes, keyBytes, QCryptographicHash::Sha256); + qDebug() << "secret:" << secret; + qDebug() << "hash (hex):" << hash.toHex(); + qDebug() << "hash.toBase64():" << hash.toHex().toBase64(); + // 将哈希值编码为 Base64 字符串 + return hash.toHex().toBase64(); +} + +// 计算签名 +QString calculateSignature(const QMap& params, const QString& httpMethod, const QString& secret, const QString& request_id, const QString& timestamp) { + // 1. 按字典序排序参数 + QList> sortedParams; + for (auto it = params.begin(); it != params.end(); ++it) { + qDebug() << it.key() << ":" << it.value(); + sortedParams.append(qMakePair(it.key(), it.value())); + } + std::sort(sortedParams.begin(), sortedParams.end()); + qDebug() << "Sorted Params:"; + for (const auto& param : sortedParams) { + qDebug() << param.first << ":" << param.second; + } + + // 2. URL 编码参数 + QString canonicalizedQueryString; + for (auto& param : sortedParams) { + if (!canonicalizedQueryString.isEmpty()) { + canonicalizedQueryString += "&"; + } + canonicalizedQueryString += QUrl::toPercentEncoding(param.first) + "=" + QUrl::toPercentEncoding(param.second); + } + qDebug() << "URL Canonicalized Query String:" << canonicalizedQueryString; + + // 3. 构造 BaseString + //QString baseString = params["batch"] + params["label"] + params["model"] + params["request_id"] + params["timestamp"] + params["factory_id"]; + QString baseString = "240830SL100LabelSL100" + request_id + timestamp + "TEST"; + qDebug() << "baseString:" << baseString; + + // 4. 构造 stringToSign + QString stringToSign = httpMethod + "&" + baseString + "&" + canonicalizedQueryString.replace("+", "%20"); + qDebug() << "stringToSign:" << stringToSign; + // 5. 计算签名 + return HmacSha256ToBase64(stringToSign, secret); +} + +// 请求头 +void prepareRequestHeaders(QNetworkRequest& request, const QString& sign, const QString& request_id) { + request.setRawHeader("factory_id", "TEST"); + request.setRawHeader("label", "SL100Label"); + request.setRawHeader("batch", QString::number(240830).toUtf8()); + request.setRawHeader("model", "SL100"); + request.setRawHeader("timestamp", QString::number(QDateTime::currentSecsSinceEpoch()).toUtf8()); + request.setRawHeader("request_id", request_id.toUtf8()); + request.setRawHeader("sign", sign.toUtf8()); + request.setRawHeader("Content-Type", "application/json"); +} + +// GET 请求 +void sendGetRequest(HttpClient* httpClient, const QUrl& url, const QMap& params, const QString& secret) { + QString request_id = generateRandomRequestID(); + qDebug() << "request_id:" << request_id; + QUrl modifiedUrl = url; + QUrlQuery query; + for (auto it = params.begin(); it != params.end(); ++it) { + query.addQueryItem(it.key(), it.value()); + } + modifiedUrl.setQuery(query.query()); + QString sign = calculateSignature(params, "GET", secret, request_id, QString::number(QDateTime::currentSecsSinceEpoch())); + qDebug() << "sendGetRequest URL:" << modifiedUrl.toString(); + QNetworkRequest request(modifiedUrl); + prepareRequestHeaders(request, sign, request_id); + //return; + httpClient->sendGetRequest(request); +} + +// POST 请求 +void sendPostRequest(HttpClient* httpClient, const QUrl& url, const QMap& params, const QJsonObject& jsonData, const QString& secret) { + QString request_id = generateRandomRequestID(); + qDebug() << "request_id:" << request_id; + QString sign = calculateSignature(params, "POST", secret, request_id, QString::number(QDateTime::currentSecsSinceEpoch())); + qDebug() << "sendPostRequest URL:" << url.toString(); + QNetworkRequest request(url); + prepareRequestHeaders(request, sign, request_id); + QByteArray jsonDataByteArray = QJsonDocument(jsonData).toJson(); + //return; + httpClient->sendPostRequest(request, jsonDataByteArray); +} + +// GET 获取 UUID +void MainWidget::FactoryToolSendGetUuidToHttpServer(const QString& mac_addr) { + QUrl url("http://admin.hassecurity.cn/v1/getUuid"); + QMap params = { + {"label", "TEST_SL100_20240826"}, + {"model", "SL100"}, + {"batch", "1"}, + {"mac", mac_addr} + }; + + QString secret = "rCeOzwisLFLasvlt"; + sendGetRequest(httpClient, url, params, secret); +} + +// GET 查询 License +void MainWidget::FactoryToolSendGetLicenseToHttpServer(const QString& hw_info) { + QUrl url("http://admin.hassecurity.cn/v1/getAlgorithmKey"); + QMap params = { + {"id", hw_info} + }; + + QString secret = "rCeOzwisLFLasvlt"; + sendGetRequest(httpClient, url, params, secret); +} + +// POST 确认烧录 +void MainWidget::FactoryToolSendPostComfirmToHttpServer(const QString& mac_addr, const QString& uuid) { + QUrl url("http://admin.hassecurity.cn/v1/confirm"); + QMap params = { + {"mac", mac_addr}, + {"uuid", uuid} + }; + + QJsonObject jsonData = { + {"mac", mac_addr}, + {"uuid", uuid} + }; + + QString secret = "rCeOzwisLFLasvlt"; + sendPostRequest(httpClient, url, params, jsonData, secret); +} + +// POST 上报测试结果 +void MainWidget::FactoryToolSendPostTestToHttpServer() { + QUrl url("http://admin.hassecurity.cn/v1/testRecords"); + QMap params = { + {"id", "123456"}, + {"location", "allMachine"} + }; + //QString itemString = "function=faceVerify,result=false,msg=timeout"; + //QString itemString = "function=faceVerify,result=false,msg=timeout"; + QString itemString = "[{\"function\":\"faceVerify\",\"msg\":\"timeout\",\"result\":false}]"; + params["items"] = itemString; + + QJsonObject jsonItem = { + {"function", "faceVerify"}, + {"result", false}, + {"msg", "timeout"} + }; + QJsonArray itemsArray; + itemsArray.append(jsonItem); + + QJsonObject jsonData = { + {"id", "123456"}, + {"location", "allMachine"}, + {"items", itemsArray} + }; + + QString secret = "rCeOzwisLFLasvlt"; + sendPostRequest(httpClient, url, params, jsonData, secret); +} + +// POST 图语 License 上报 +void MainWidget::FactoryToolSendPostLicenseToHttpServer(const QString& hardware_info, const QString& license_info) { + QUrl url("http://admin.hassecurity.cn/v1/algorithmKey"); + QString UTC_time = QString::number(QDateTime::currentSecsSinceEpoch()); + QMap params = { + {"id", hardware_info}, + {"key", license_info}, + {"time", UTC_time}, + {"type", "TUYU"} + }; + + QJsonObject jsonData = { + {"id", hardware_info}, + {"key", license_info}, + {"time", UTC_time} + }; + + QString secret = "rCeOzwisLFLasvlt"; + sendPostRequest(httpClient, url, params, jsonData, secret); +} + void MainWidget::startClientReadTimer(int clientId) { qDebug() << "------ startClientReadTimer clientId:" << clientId; if (clientReadTimers.contains(clientId)) { @@ -285,28 +530,28 @@ void MainWidget::readJsonConfig() backBoardTest = readJson_backBoardTest(); backBoardFuncConfig = readJson_backBoardFuncConfig(); backBoardDevInfoJson = readJson_backDevInfo(); + backBoardUuidJson = readJson_backUuid(); testJsonConfig = readJson_testConfig(); funcJsonConfig = readJson_funcConfig(); - getPicJson = readJson_getPic(); - getVideoJson = readJson_getVideo(); + getPicJson = readJson_getPic(); + getVideoJson = readJson_getVideo(); } // 设置 UI void MainWidget::setupUI() { startServerButton = new QPushButton("开始监听\n(Start Listening...)", this); - startServerButton->setFixedSize(190, 70); // 设置宽度为 190 像素,高度为 70 像素 + startServerButton->setFixedSize(190, 70); sendAllButton = new QPushButton("一键功能测试", this); - sendAllButton->setFixedSize(190, 70); // 设置宽度为 190 像素,高度为 70 像素 + sendAllButton->setFixedSize(190, 70); sendAllButton->setEnabled(false); statusListWidget = new QListWidget(this); - //statusListWidget->setMinimumSize(350, 880); - statusListWidget->setMinimumSize(350, 680); - statusListWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // 设置大小策略为扩展 + statusListWidget->setMinimumSize(350, 840); + statusListWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); QHBoxLayout* buttonLayout = new QHBoxLayout; buttonLayout->addWidget(startServerButton); @@ -340,293 +585,86 @@ void MainWidget::setupUI() // 读取 JSON 配置文件 readJsonConfig(); - QGroupBox* groupBox = new QGroupBox("算法 license", this); - QHBoxLayout* buttonRowLayout = new QHBoxLayout; - for (int i = 0; i < frontBoardLicenseJson.size(); ++i) { - QJsonObject item = frontBoardLicenseJson[i].toObject(); - QString buttonText = item["lable"].toString(); - QPushButton* button = new QPushButton(buttonText, this); - button->setProperty("licenseIndex", i); - buttonRowLayout->addWidget(button); - connect(button, &QPushButton::clicked, this, &MainWidget::onLicenseButtonClicked); - } - licenseHwInfoEdit->setReadOnly(true); - licenseHwInfoEdit->setText("This is a read-only text"); - licenseHwInfoEdit->setFixedHeight(80); - - QVBoxLayout* groupBoxLayout_license = new QVBoxLayout; - groupBoxLayout_license->addLayout(buttonRowLayout); - groupBoxLayout_license->addWidget(licenseHwInfoEdit); - groupBox->setLayout(groupBoxLayout_license); - + /*QGroupBox* groupBox = createLicenseGroupBox(); leftLayout->addWidget(groupBox); - leftLayout->setStretch(3, 1); + leftLayout->setStretch(3, 1);*/ QWidget* leftContainer = new QWidget(this); leftContainer->setLayout(leftLayout); leftContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - QTabWidget* tabWidget = new QTabWidget(this); - tabWidget->setFixedSize(900, 315); // 设置 QTabWidget 的固定大小 + // 前板 + QGroupBox* frontDeviceInfoGroupBox = createFrontDeviceInfoGroupBox(); + QGroupBox* frontLicenseGroupBox = createLicenseGroupBox(); + + QHBoxLayout* frontGroupBoxLayout = new QHBoxLayout; + frontGroupBoxLayout->addWidget(frontDeviceInfoGroupBox, 1); + frontGroupBoxLayout->addWidget(frontLicenseGroupBox, 1); + + QTabWidget* frontTabWidget = new QTabWidget(this); + frontTabWidget->setFixedSize(900, 315); + QWidget* frontFunctionTestTab = createFunctionTestTab(frontBoardTest, "frontBoardTest"); + QWidget* frontFunctionConfigTab = createFunctionConfigTab(frontBoardFuncConfig, "frontBoardFuncConfig"); + frontTabWidget->addTab(frontFunctionTestTab, "前板测试项"); + frontTabWidget->addTab(frontFunctionConfigTab, "前板配置项"); - QGroupBox* frontDeviceInfoGroupBox = new QGroupBox("前板设备信息", this); - QVBoxLayout* frontDeviceInfoLayout = new QVBoxLayout(frontDeviceInfoGroupBox); + QTabWidget* mainTabWidget = new QTabWidget(this); + QWidget* frontDevAreaTab = new QWidget(this); + QVBoxLayout* frontDevLayout = new QVBoxLayout(frontDevAreaTab); + frontDevLayout->addLayout(frontGroupBoxLayout); + frontDevLayout->addWidget(frontTabWidget, 2, Qt::AlignTop | Qt::AlignLeft); + mainTabWidget->addTab(frontDevAreaTab, "前 板"); - QVBoxLayout* frontDeviceLabelsLayout = new QVBoxLayout; - for (const QJsonValue& value : frontBoardDevInfoJson) { - QJsonObject item = value.toObject(); - QString label = item["lable"].toString(); - QString cmd = item["cmd"].toString(); - QLabel* itemLabel = new QLabel(label, this); - QLineEdit* itemLineEdit = new QLineEdit(this); - itemLineEdit->setReadOnly(true); + // 后板 + QGroupBox* backDeviceInfoGroupBox1 = createBackDeviceInfoGroupBox(); + QGroupBox* BackConnectServerGroupBox = createBackConnectServerGroupBox(); - QHBoxLayout* itemLayout = new QHBoxLayout; - itemLayout->addWidget(itemLabel); - itemLayout->addWidget(itemLineEdit); + QHBoxLayout* backGroupBoxLayout = new QHBoxLayout; + backGroupBoxLayout->addWidget(backDeviceInfoGroupBox1, 1); + backGroupBoxLayout->addWidget(BackConnectServerGroupBox, 1); - frontDeviceLabelsLayout->addLayout(itemLayout); - devInfoLineEdits[cmd] = itemLineEdit; - } - frontDeviceInfoLayout->addLayout(frontDeviceLabelsLayout); - frontDeviceInfoLayout->addStretch(); + QTabWidget* backTabWidget = new QTabWidget(this); + backTabWidget->setFixedSize(900, 315); + QWidget* backFunctionTestTab = createFunctionTestTab(backBoardTest, "backBoardTest"); + QWidget* backFunctionConfigTab = createFunctionConfigTab(backBoardFuncConfig, "backBoardFuncConfig"); + backTabWidget->addTab(backFunctionTestTab, "后板测试项"); + backTabWidget->addTab(backFunctionConfigTab, "后板配置项"); - QGroupBox* backDeviceInfoGroupBox = new QGroupBox("后板设备信息", this); - QVBoxLayout* backDeviceInfoLayout = new QVBoxLayout(backDeviceInfoGroupBox); + QWidget* backDevAreaTab = new QWidget(this); + QVBoxLayout* backDevLayout = new QVBoxLayout(backDevAreaTab); + backDevLayout->addLayout(backGroupBoxLayout); + backDevLayout->addWidget(backTabWidget, 2, Qt::AlignTop | Qt::AlignLeft); + mainTabWidget->addTab(backDevAreaTab, "后 板"); - QVBoxLayout* backDeviceLabelsLayout = new QVBoxLayout; - for (const QJsonValue& value : backBoardDevInfoJson) { - QJsonObject item = value.toObject(); - QString label = item["lable"].toString(); - QString cmd = item["cmd"].toString(); - QLabel* itemLabel = new QLabel(label, this); - QLineEdit* itemLineEdit = new QLineEdit(this); - itemLineEdit->setReadOnly(true); - - QHBoxLayout* itemLayout = new QHBoxLayout; - itemLayout->addWidget(itemLabel); - itemLayout->addWidget(itemLineEdit); - - backDeviceLabelsLayout->addLayout(itemLayout); - devInfoLineEdits[cmd] = itemLineEdit; - } - backDeviceInfoLayout->addLayout(backDeviceLabelsLayout); - backDeviceInfoLayout->addStretch(); - - QHBoxLayout* groupBoxLayout = new QHBoxLayout; - groupBoxLayout->addWidget(frontDeviceInfoGroupBox, 1); - groupBoxLayout->addWidget(backDeviceInfoGroupBox, 1); - - QWidget* functionTestTab = new QWidget; - QVBoxLayout* functionTestLayout = new QVBoxLayout(functionTestTab); - functionTestTab->setLayout(functionTestLayout); - tabWidget->addTab(functionTestTab, "功能测试区"); - - QGridLayout* buttonGridLayout = new QGridLayout(); - int buttonsPerRow = 7; // 每行显示的按键数量,根据需要调整 - // 为每个 JSON 项目创建按键,并添加到 rightLayout - // 先总共放 77 个按键 - //qDebug() << "testJsonConfig.size():" << testJsonConfig.size(); - for (int i = 0; i < frontBoardTest.size() + (77 - frontBoardTest.size()); ++i) { - QJsonObject item = frontBoardTest[i].toObject(); - QString buttonText = item["lable"].toString(); - // 判断 buttonText 是否为空或者只有空白字符 - if (buttonText.isEmpty()) { - //qDebug() << "buttonText.isEmpty():" << buttonText.isEmpty(); - buttonText = QString("Send Item %1").arg(i + 1); - } - QPushButton* button = new QPushButton(buttonText, this); - button->setProperty("frontBoardTest", i); - button->setFixedSize(110, 35); // 设置按键宽度和高度 - connect(button, &QPushButton::clicked, this, &MainWidget::onSendItemClicked); - - int row = i / buttonsPerRow; - int col = i % buttonsPerRow; - buttonGridLayout->addWidget(button, row, col, Qt::AlignLeft); - - itemButtons.append(button); - } - - QWidget* buttonContainer = new QWidget; - buttonContainer->setLayout(buttonGridLayout); - - QScrollArea* scrollArea = new QScrollArea; - scrollArea->setWidget(buttonContainer); - scrollArea->setWidgetResizable(true); - - functionTestLayout->addWidget(scrollArea); - - QWidget* functionConfigTab = new QWidget; - QVBoxLayout* functionConfigLayout = new QVBoxLayout(functionConfigTab); - functionConfigTab->setLayout(functionConfigLayout); - tabWidget->addTab(functionConfigTab, "功能配置区"); - - funcConfigLineEdit->setPlaceholderText("请输入配置参数..."); - functionConfigLayout->addWidget(funcConfigLineEdit); - - QGridLayout* configButtonGridLayout = new QGridLayout(); - - for (int i = 0; i < frontBoardFuncConfig.size() + (77 - frontBoardFuncConfig.size()); ++i) { - QJsonObject item = frontBoardFuncConfig[i].toObject(); - QString buttonText = item["lable"].toString(); - // 判断 buttonText 是否为空或者只有空白字符 - if (buttonText.isEmpty()) { - //qDebug() << "buttonText.isEmpty():" << buttonText.isEmpty(); - buttonText = QString("Cfg Item %1").arg(i + 1); - } - QPushButton* button = new QPushButton(buttonText, this); - button->setProperty("frontBoardFuncConfig", i); - button->setFixedSize(110, 35); // 设置按键宽度和高度 - connect(button, &QPushButton::clicked, this, &MainWidget::onSendFuncItemClicked); - - int row = i / buttonsPerRow; - int col = i % buttonsPerRow; - configButtonGridLayout->addWidget(button, row, col, Qt::AlignLeft); - - funcItemButtons.append(button); - } - - QWidget* configButtonContainer = new QWidget; - configButtonContainer->setLayout(configButtonGridLayout); - - QScrollArea* configScrollArea = new QScrollArea; - configScrollArea->setWidget(configButtonContainer); - configScrollArea->setWidgetResizable(true); - - functionConfigLayout->addWidget(configScrollArea); + // 整机 + QWidget* allDevAreaTab = new QWidget(this); + QVBoxLayout* allDevLayout = new QVBoxLayout(allDevAreaTab); + mainTabWidget->addTab(allDevAreaTab, "整 机"); QTabWidget* tabWidget_media = new QTabWidget(this); - QWidget* imageDisplayTab = new QWidget; - QVBoxLayout* imageDisplayLayout = new QVBoxLayout(imageDisplayTab); - imageDisplayTab->setLayout(imageDisplayLayout); + QWidget* imageDisplayTab = createImageDisplayTab(); + QWidget* videoDisplayTab = createVideoDisplayTab(); tabWidget_media->addTab(imageDisplayTab, "图像显示区"); - - QVBoxLayout* imageButtonsColumnLayout = new QVBoxLayout; - for (int i = 0; i < 5; ++i) { - QHBoxLayout* imageButtonsRowLayout = new QHBoxLayout; - for (int j = 0; j < 2; ++j) { - QPushButton* button; - if (i == 0 && j == 0) { - button = new QPushButton(QString("IR"), this); - button->setFixedSize(73, 50); - imageButtonsRowLayout->addWidget(button); - button->setProperty("getPicIndex", i * 2 + j); - connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked); - getPicButtons.append(button); - continue; - } - else if (i == 0 && j == 1) { - button = new QPushButton(QString("RGB"), this); - button->setFixedSize(73, 50); - imageButtonsRowLayout->addWidget(button); - button->setProperty("getPicIndex", i * 2 + j); - connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked); - getPicButtons.append(button); - continue; - } - - button = new QPushButton(QString("Device %1").arg(i * 2 + j - 1), this); - button->setFixedSize(73, 50); - imageButtonsRowLayout->addWidget(button); - button->setProperty("getPicIndex", i * 2 + j); - connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked); - getPicButtons.append(button); - } - imageButtonsColumnLayout->addLayout(imageButtonsRowLayout); - } - - QHBoxLayout* lensesLayout = new QHBoxLayout; - leftLens_imageLabel = new QLabel(this); - rightLens_imageLabel = new QLabel(this); - lensesLayout->addWidget(leftLens_imageLabel); - lensesLayout->addWidget(rightLens_imageLabel); - - QHBoxLayout* imageAndButtonsLayout = new QHBoxLayout; - imageAndButtonsLayout->addLayout(imageButtonsColumnLayout, 1); - imageAndButtonsLayout->addLayout(lensesLayout, 4); - imageDisplayLayout->addLayout(imageAndButtonsLayout); - - QWidget* videoDisplayTab = new QWidget; - QVBoxLayout* videoDisplayLayout = new QVBoxLayout(videoDisplayTab); - videoDisplayTab->setLayout(videoDisplayLayout); - tabWidget_media->addTab(videoDisplayTab, "视频显示区"); - - QVBoxLayout* videoButtonsColumnLayout = new QVBoxLayout; - for (int i = 0; i < 6; ++i) { - QHBoxLayout* videoButtonsRowLayout = new QHBoxLayout; - for (int j = 0; j < 2; ++j) { - QPushButton* button; - if (i == 0 && j == 0) { - button = new QPushButton(QString("IR"), this); - button->setFixedSize(73, 50); - videoButtonsRowLayout->addWidget(button); - button->setProperty("getVideoIndex", i * 2 + j); - connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked); - getVideoButtons.append(button); - continue; - } - else if (i == 0 && j == 1) { - button = new QPushButton(QString("RGB"), this); - button->setFixedSize(73, 50); - videoButtonsRowLayout->addWidget(button); - button->setProperty("getVideoIndex", i * 2 + j); - connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked); - getVideoButtons.append(button); - continue; - } - - // 调价调焦窗口按键 - if (i == 1 && j == 0) { - button = new QPushButton(QString("大窗口播放视频"), this); - button->setFixedSize(150, 50); - button->setEnabled(false); - videoButtonsRowLayout->addWidget(button); - button->setProperty("getVideoIndex", i * 2 + j); - connect(button, &QPushButton::clicked, this, &MainWidget::onOpenFocusWindowClicked); - getVideoButtons.append(button); - break; // 跳出内层循环,只添加一个按键 - } - - //int adjustedIndex = (i > 1) ? i * 2 + j - 1 : i * 2 + j; - button = new QPushButton(QString("Device %1").arg(i * 2 + j - 3), this); - //button = new QPushButton(QString("Device %1").arg(adjustedIndex), this); - button->setFixedSize(73, 50); - videoButtonsRowLayout->addWidget(button); - button->setProperty("getVideoIndex", i * 2 + j + 1); - //button->setProperty("getVideoIndex", adjustedIndex); - connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked); - getVideoButtons.append(button); - } - videoButtonsColumnLayout->addLayout(videoButtonsRowLayout); - } - - QHBoxLayout* videoAndButtonsLayout = new QHBoxLayout; - videoLabel = new QLabel(this); - //videoLabel->setFixedSize(640, 480); - videoAndButtonsLayout->addLayout(videoButtonsColumnLayout, 1); - videoAndButtonsLayout->addWidget(videoLabel, 6); - videoDisplayLayout->addLayout(videoAndButtonsLayout); + tabWidget_media->addTab(videoDisplayTab, "视频显示区"); QVBoxLayout* rightVerticalLayout = new QVBoxLayout; - rightVerticalLayout->addLayout(groupBoxLayout, 2); - rightVerticalLayout->addWidget(tabWidget, 2, Qt::AlignTop | Qt::AlignLeft); - rightVerticalLayout->addWidget(tabWidget_media, 5); + rightVerticalLayout->addWidget(mainTabWidget, 5); + rightVerticalLayout->addWidget(tabWidget_media, 4); QHBoxLayout* mainLayout = new QHBoxLayout; - // 参数二:伸缩因子,leftContainer:1/3 ,rightLayout:2/3 - mainLayout->addWidget(leftContainer, 1, Qt::AlignTop | Qt::AlignLeft); // 设置 leftContainer 左上对齐 + mainLayout->addWidget(leftContainer, 1, Qt::AlignTop | Qt::AlignLeft); mainLayout->addLayout(rightVerticalLayout, 3); setLayout(mainLayout); setWindowTitle("SL100 工厂产测工具 - V0.0.1"); - resize(1340, 1000); // 设置宽度为 1440 像素,高度为 900 像素 + resize(1340, 1000); - connect(startServerButton, &QPushButton::clicked, this, &MainWidget::onStartServerClicked); - connect(sendAllButton, &QPushButton::clicked, this, &MainWidget::onSendAllClicked); - connect(statusListWidget, &QListWidget::itemChanged, this, &MainWidget::scrollToBottom); - connect(selectFileButton, &QPushButton::clicked, this, &MainWidget::onSelectFileButtonClicked); - connect(clearLogButton, &QPushButton::clicked, this, &MainWidget::onclearLogButtonClicked); - connect(saveCheckBox, &QCheckBox::stateChanged, this, &MainWidget::onSaveCheckBoxStateChanged); + connect(startServerButton, &QPushButton::clicked, this, &MainWidget::onStartServerClicked); + connect(sendAllButton, &QPushButton::clicked, this, &MainWidget::onSendAllClicked); + connect(statusListWidget, &QListWidget::itemChanged, this, &MainWidget::scrollToBottom); + connect(selectFileButton, &QPushButton::clicked, this, &MainWidget::onSelectFileButtonClicked); + connect(clearLogButton, &QPushButton::clicked, this, &MainWidget::onclearLogButtonClicked); + connect(saveCheckBox, &QCheckBox::stateChanged, this, &MainWidget::onSaveCheckBoxStateChanged); } void MainWidget::onSelectFileButtonClicked() @@ -754,6 +792,20 @@ void MainWidget::updateServerButtonText() } } +QString formatLicenseKey(const QString& licenseKey) { + QString formattedKey; + qDebug() << "licenseKey.length():" << licenseKey.length(); + for (int i = 0; i < licenseKey.length(); i += 2) { + QString byteStr = licenseKey.mid(i, 2); // 每次取两个字符 + formattedKey.append(QString("0x%1, ").arg(byteStr)); + } + if (!formattedKey.isEmpty()) { + formattedKey.chop(2); + } + + return formattedKey; +} + void MainWidget::onLicenseButtonClicked() { if (connectedClientsCount) { @@ -762,13 +814,172 @@ void MainWidget::onLicenseButtonClicked() int index = button->property("licenseIndex").toInt(); if (index >= 0 && index < frontBoardLicenseJson.size()) { QJsonObject jsonObject = frontBoardLicenseJson[index].toObject(); + unsigned char hardware_info[PIX_HARDWARE_INFO_BYTES] = { 0 }; + unsigned char license_info[PIX_LICENCE_BYTES] = { 0 }; + QString dataStr = ""; + if (jsonObject["lable"].toString() == "get_license") { + QString hwInfoText = licenseHwInfoEdit->toPlainText(); + dataStr = hwInfoText.remove(","); // 去掉所有的逗号 + QString sendToHttpServerDataStr = dataStr.replace("0x", "").replace(" ", ""); // 去掉0x和空格 +#if 1 + qDebug() << "sendToHttpServerDataStr:" << sendToHttpServerDataStr; + FactoryToolSendGetLicenseToHttpServer(sendToHttpServerDataStr); + while (isRequestSuccessful == 0) { + QCoreApplication::processEvents(); // 防止阻塞UI线程 + } + qDebug() << "isRequestSuccessful:" << isRequestSuccessful; + if (isRequestSuccessful == 2) { + return; + } + else if(isRequestSuccessful == 1) { + if (licenseDataArray.contains("has") && licenseDataArray["has"].toBool()) { + qDebug() << "Found item with 'has' = true"; + if (licenseDataArray.contains("key")) { + QString licenseKey = licenseDataArray["key"].toString(); + licenseKey = formatLicenseKey(licenseKey); + licenseHwInfoEdit->setPlainText(licenseKey); + qDebug() << "HTTP Server License is:" << licenseKey; + return; + } + } + else if (licenseDataArray.contains("has")) { + qDebug() << "licenseDataArray[\"has\"].toBool():" << licenseDataArray["has"].toBool(); + } + } +#else + QString licenseKey = "128532C1D2A8"; + licenseKey = formatLicenseKey(licenseKey); + licenseHwInfoEdit->setPlainText(licenseKey); + qDebug() << "License Key set in licenseHwInfoEdit:" << licenseKey; + return; +#endif + QByteArray dataByteArray = QByteArray::fromHex(dataStr.toUtf8()); + memcpy(hardware_info, dataByteArray.data(), qMin(dataByteArray.size(), PIX_HARDWARE_INFO_BYTES)); + //unsigned char hardware_info[PIX_HARDWARE_INFO_BYTES] = { 0x46,0x0b,0x5d,0x11,0x58,0x17,0x4d,0x5e,0x55,0x5c,0x51,0x4a,0x5a,0x07,0x59,0x4c,0x5f,0x45,0x5b,0x5f,0x5a,0x45,0x1c,0x5a,0x45,0x43,0x44,0x47,0x51,0x5e,0x44,0x30 }; + LicenseConfirmWindow dialog("你确定要获取此授权吗?"); + if (dialog.exec() == QDialog::Accepted) { +#if 0 + licenseGenerate(hardware_info, license_info); + QString licenseInfoHex = QByteArray(reinterpret_cast(license_info), PIX_LICENCE_BYTES).toHex().toUpper(); +#else + unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0x07, 0xe8, 0xf3, 0x80, 0xa8, 0x07, 0x72, 0xa1, 0x17, 0xfe, 0xda, 0x67, 0xbd, 0x4a, 0x5a, 0xb5, 0xbb, 0x8b, 0x2d, 0xb2, 0xbf, 0x89, 0x74, 0xe5, 0xb0, 0x99, 0x70, 0x74, 0x3c, 0x6f, 0xf8, 0x82, 0x79, 0xab, 0x31, 0x9c, 0xdf, 0xe8, 0x9e, 0x75, 0x8f, 0x42, 0xb3, 0xcf, 0x00, 0x60, 0xa0, 0x38, 0xa4, 0xb8, 0xbe, 0xa6, 0x5d, 0x9f, 0x8b, 0x41, 0xf3, 0x0a, 0x69, 0xf6, 0x50, 0x94, 0x3f, 0xd0, 0xa5, 0xee, 0x88, 0x20, 0x93, 0x9a, 0x1c, 0xe9, 0x64, 0xd3, 0xaf, 0x9f, 0xc7, 0x66, 0x00, 0x7d, 0x7d, 0x68, 0xf1, 0xa4, 0xe1, 0x58, 0x00, 0x1d, 0x03, 0x0d, 0x40, 0x08, 0xa4, 0xcc, 0x0b, 0xd8, 0x19, 0x70, 0x9a, 0x83, 0x81, 0xbf, 0x27, 0x35, 0xb8, 0xec, 0x59, 0xa8, 0xd0, 0x03, 0xdb, 0xf6, 0xcf, 0x83, 0xaa, 0x0e, 0xfc, 0x95, 0x29, 0x77, 0xec, 0x89, 0xc5, 0x79, 0x10, 0x40, 0xd8, 0xbb }; + QString licenseInfoHex = QByteArray(reinterpret_cast(license_info_1), PIX_LICENCE_BYTES).toHex().toUpper(); +#endif + qDebug() << "上报服务器 licenseInfoHex:" << licenseInfoHex; + // License上报服务器 + FactoryToolSendPostLicenseToHttpServer(sendToHttpServerDataStr, licenseInfoHex); + QString licenseInfoStr; + printf("U盘 Get License is\n"); + for (int j = 0; j < PIX_LICENCE_BYTES; ++j) { + //printf("0x%02x, ", license_info[j]); + //licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info[j])); + printf("0x%02x, ", license_info_1[j]); + licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info_1[j])); + } + printf("\n"); + licenseHwInfoEdit->setPlainText(licenseInfoStr); + } + } + else { +#if 0 + if (jsonObject["lable"].toString() == "write_license") { + QString hwInfoText = licenseHwInfoEdit->toPlainText(); + dataStr = hwInfoText.remove(","); // 去掉所有的逗号 + QByteArray dataByteArray = QByteArray::fromHex(dataStr.toUtf8()); + memcpy(hardware_info, dataByteArray.data(), qMin(dataByteArray.size(), PIX_HARDWARE_INFO_BYTES)); + qDebug() << "hardware_info:" << QByteArray(reinterpret_cast(hardware_info), PIX_HARDWARE_INFO_BYTES).toHex(); + licenseGenerate(hardware_info, license_info); + QString licenseInfoStr; + printf("License is\n"); + for (int j = 0; j < PIX_LICENCE_BYTES; ++j) { + printf("0x%02x, ", license_info[j]); + licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info[j])); + } + printf("\n"); + licenseHwInfoEdit->setPlainText(licenseInfoStr); + dataStr = QByteArray(reinterpret_cast(license_info), PIX_LICENCE_BYTES).toHex(); + qDebug() << "license_info:" << dataStr; + } +#else + if (jsonObject["lable"].toString() == "write_license") { + QString licenseInfoText = licenseHwInfoEdit->toPlainText(); + qDebug() << "licenseInfoText:" << licenseInfoText; + dataStr = licenseInfoText.remove(","); // 去掉所有的逗号 + dataStr = dataStr.replace("0x", "").replace(" ", ""); // 去掉0x和空格 + QByteArray dataByteArray = QByteArray::fromHex(dataStr.toUtf8()); + memcpy(license_info, dataByteArray.data(), qMin(dataByteArray.size(), PIX_LICENCE_BYTES)); + //qDebug() << "hardware_info:" << QByteArray(reinterpret_cast(hardware_info), PIX_HARDWARE_INFO_BYTES).toHex(); + //licenseGenerate(hardware_info, license_info); + QString licenseInfoStr; + for (int j = 0; j < PIX_LICENCE_BYTES; ++j) { + licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info[j])); + } + //printf("\n"); + dataStr = QByteArray(reinterpret_cast(license_info), PIX_LICENCE_BYTES).toHex(); + qDebug() << "license_info:" << dataStr; + } +#endif + for (ClientHandler* handler : clients) { + handler->sendLicenseItem(index, dataStr); + } + } + } + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +//void MainWidget::onLicenseButtonClicked() +//{ +// if (connectedClientsCount) { +// QPushButton* button = qobject_cast(sender()); +// if (button) { +// int index = button->property("licenseIndex").toInt(); +// if (index >= 0 && index < frontBoardLicenseJson.size()) { +// QJsonObject jsonObject = frontBoardLicenseJson[index].toObject(); +// //QString jsonString = QJsonDocument(jsonObject).toJson(QJsonDocument::Compact); +// //qDebug() << "license Button clicked, sending JSON:" << jsonString; +// unsigned char license_info[PIX_LICENCE_BYTES] = { 0 }; +// if (jsonObject["lable"].toString() == "get_license") { +// LicenseConfirmWindow dialog("你确定要获取此授权吗?"); +// if (dialog.exec() == QDialog::Accepted) +// licenseGenerate(license_info, license_info); +// } +// else { +// if (jsonObject["lable"].toString() == "write_license") { +// LicenseConfirmWindow dialog("你确定要发送此授权吗?"); +// if (dialog.exec() == QDialog::Accepted) +// licenseGenerate(license_info, license_info); +// } +// for (ClientHandler* handler : clients) { +// handler->sendLicenseItem(index); +// } +// } +// } +// } +// } +// else { +// QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); +// listItem->setBackground(Qt::red); +// } +//} + +void MainWidget::onUuidButtonClicked() +{ + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + if (button) { + int index = button->property("UuidIndex").toInt(); + if (index >= 0 && index < backBoardUuidJson.size()) { + QJsonObject jsonObject = backBoardUuidJson[index].toObject(); //QString jsonString = QJsonDocument(jsonObject).toJson(QJsonDocument::Compact); //qDebug() << "license Button clicked, sending JSON:" << jsonString; unsigned char license_info[PIX_LICENCE_BYTES] = { 0 }; if (jsonObject["lable"].toString() == "get_license") { - LicenseConfirmWindow dialog("你确定要获取此授权吗?"); - if (dialog.exec() == QDialog::Accepted) - licenseGenerate(license_info, license_info); + } else { if (jsonObject["lable"].toString() == "write_license") { @@ -777,7 +988,7 @@ void MainWidget::onLicenseButtonClicked() licenseGenerate(license_info, license_info); } for (ClientHandler* handler : clients) { - handler->sendLicenseItem(index); + handler->sendUuidItem(index, ""); } } } @@ -860,6 +1071,17 @@ void MainWidget::onStartServerClicked() } } +void MainWidget::sendDataToClient(int clientId, const QByteArray& data) +{ + if (clients_1.contains(clientId)) { + ClientHandler* handler = clients_1[clientId]; + handler->sendDataToClient(data); // 调用 ClientHandler 中的方法发送数据 + } + else { + qWarning() << "没有找到 ID 为" << clientId << "的客户端!"; + } +} + // 处理发送获取设备信息按键点击事件 void MainWidget::onSendGetDevInfoClicked() { @@ -1018,15 +1240,32 @@ void MainWidget::onSendAllClicked() } // 处理单独发送功能项按键点击事件 -void MainWidget::onSendFuncItemClicked() +void MainWidget::onSendFrontFuncItemClicked() { if (connectedClientsCount) { QPushButton* button = qobject_cast(sender()); int itemIndex = button->property("frontBoardFuncConfig").toInt(); for (ClientHandler* handler : clients) { - QString text = funcConfigLineEdit->text(); - qDebug() << "Text in funcConfigLineEdit:" << text; - handler->sendFuncItem(itemIndex, text); + QString text = frontFuncConfigLineEdit->text(); + qDebug() << "Text in frontFuncConfigLineEdit:" << text; + handler->sendFrontFuncItem(itemIndex, text); + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +void MainWidget::onSendBackFuncItemClicked() +{ + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + int itemIndex = button->property("backBoardFuncConfig").toInt(); + for (ClientHandler* handler : clients) { + QString text = backFuncConfigLineEdit->text(); + qDebug() << "Text in backFuncConfigLineEdit:" << text; + handler->sendBackFuncItem(itemIndex, text); } } else { @@ -1036,13 +1275,30 @@ void MainWidget::onSendFuncItemClicked() } // 处理单独发送项按键点击事件 -void MainWidget::onSendItemClicked() +void MainWidget::onSendFrontItemClicked() { + qDebug() << "onSendFrontItemClicked" ; if (connectedClientsCount) { QPushButton* button = qobject_cast(sender()); int itemIndex = button->property("frontBoardTest").toInt(); for (ClientHandler* handler : clients) { - handler->sendItem(itemIndex); + handler->sendFrontItem(itemIndex); + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +void MainWidget::onSendBackItemClicked() +{ + qDebug() << "onSendBackItemClicked"; + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + int itemIndex = button->property("backBoardTest").toInt(); + for (ClientHandler* handler : clients) { + handler->sendBackItem(itemIndex); } } else { @@ -1121,1112 +1377,3 @@ void MainWidget::onAllItemsProcessed(const QString& client, int itemsProcessedCo statusListWidget->scrollToBottom(); } - - -//#include "MainWidget.h" -// -// -//void onThreadFinished(QThread* thread, ClientHandler* handler) -//{ -// qDebug() << "Thread finished. Deleting handler and thread."; -// handler->deleteLater(); -// thread->deleteLater(); -//} -// -//// 初始化 UI 组件和服务器 -//MainWidget::MainWidget(QWidget* parent) : -// QWidget(parent), -// nextClientId(1), -// manualSend(false), -// isSendingAll(false), -// lastClickedGetPicCamIndex(-1), -// lastClickedGetPicDevIndex(-1), -// lastClickedGetVideoCamIndex(-1), -// lastClickedGetVideoDevIndex(-1), -// mServiceProvider(new ServiceProvider(this)) -//#if TEST_UDP_BROADCAST -// , multicastSocket(new QUdpSocket(this)), -// multicastTimer(new QTimer(this)) -//#endif -//{ -// leftLens_imageLabel = new QLabel(this); -// rightLens_imageLabel = new QLabel(this); -// videoLabel = new QLabel(this); -// funcConfigLineEdit = new QLineEdit(this); -// licenseHwInfoEdit = new QTextEdit(this); -// -// setupUI(); -// // 打印线程池状态信息 -// setupTimerForThreadPoolInfo(); -// server = new QTcpServer(this); -// -// connect(server, &QTcpServer::newConnection, this, [this]() { -// // 检查是否有挂起的连接 -// while (server->hasPendingConnections()) { -// QTcpSocket* socket = server->nextPendingConnection(); -// int clientId = nextClientId++; -// qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; -// qDebug() << "> A client is connected. ID:" << clientId; -// qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; -// -// // 更新连接数量并更新按键文本 -// connectedClientsCount++; -// updateServerButtonText(); -// -// // 创建新的定时器 -// QTimer* timer = new QTimer(this); -// timer->setSingleShot(true); -// clientTimers[clientId] = timer; -// -// // 连接定时器超时信号到槽函数 -// connect(timer, &QTimer::timeout, this, [this, clientId]() { -// //qDebug() << "Timeout occurred for client ID:" << clientId; -// for (ClientHandler* handler : clients) { -// if (handler->getClientId() == clientId) { -// bool invoked = QMetaObject::invokeMethod(handler, "onTimeout", Qt::DirectConnection); -// if (!invoked) { -// qWarning() << "Failed to invoke onTimeout for client ID:" << clientId; -// } -// } -// } -// }); -// -// QThread* thread = new QThread(this); -// ClientHandler* handler = new ClientHandler(socket, frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig, -// frontBoardDevInfoJson, frontBoardLicenseJson, backBoardDevInfoJson, -// getPicJson, getVideoJson, clientId, nullptr); -// -// // 将 ClientHandler 移动到线程池中的线程 -// handler->moveToThread(thread); -// -// // 当线程结束时删除 handler -// connect(thread, &QThread::finished, this, [=]() { -// onThreadFinished(thread, handler); -// }); -// -// // 将sendData信号连接到主线程中的槽上 -// connect(handler, &ClientHandler::sendData, this, [socket](const QByteArray& data) { -// socket->write(data); -// socket->flush(); -// }); -// -// connect(handler, &ClientHandler::startTimeout, this, [this, clientId](int timeout) { -// this->onStartTimeout(clientId, timeout); -// }); -// -// // 启动新的线程 -// thread->start(); -// -// clients.append(handler); -// clients_1[clientId] = handler; -// clientThreads[clientId] = thread; -// connect(handler, &ClientHandler::statusUpdated, this, &MainWidget::onStatusUpdated); -// connect(handler, &ClientHandler::clientDisconnected, this, &MainWidget::onClientDisconnected); -// connect(handler, &ClientHandler::allItemsProcessed, this, &MainWidget::onAllItemsProcessed); -// connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient); -// -// // 创建 DataHandler 对象并连接信号 -// DataHandler* dataHandler = new DataHandler(leftLens_imageLabel, rightLens_imageLabel, videoLabel, licenseHwInfoEdit, &devInfoLineEdits, this); -// connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData); -// connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated); -// -// connect(handler, &ClientHandler::startReadTimer, this, &MainWidget::startClientReadTimer); -// connect(handler, &ClientHandler::stopReadTimer, this, &MainWidget::stopClientReadTimer); -// -// // 创建和管理定时器 -// QTimer* readTimer = new QTimer(this); -// connect(readTimer, &QTimer::timeout, handler, &ClientHandler::onTimeoutRead); -// // readTimer->start(10); // 每 10ms 触发一次 -// // 将定时器存储到哈希表中,方便管理 -// clientReadTimers[clientId] = readTimer; -// } -// }); -// -// threadStatusTimer = new QTimer(this); -// connect(threadStatusTimer, &QTimer::timeout, this, &MainWidget::onCheckThreadStatus); -// //threadStatusTimer->start(100); // 每100ms检查一次线程状态 -// -// connectionStatusCheckTimer = new QTimer(this); -// connect(connectionStatusCheckTimer, &QTimer::timeout, this, &MainWidget::onCheckConnectionStatus); -// //connectionStatusCheckTimer->start(100); // 每100ms检查一次连接状态 -// -//#if TEST_UDP_BROADCAST -// // 设置组播地址 -// QHostAddress groupAddress("224.0.0.251"); -// quint16 port = 5353; -// -// // 绑定UDP套接字 -// if (!multicastSocket->bind(QHostAddress::AnyIPv4, port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) { -// qWarning() << "Failed to bind multicast socket"; -// } -// -// // 加入组播组 -// bool joined = multicastSocket->joinMulticastGroup(groupAddress); -// if (!joined) { -// qWarning() << "Failed to join multicast group"; -// } -// -// // 定期发送组播消息 -// connect(multicastTimer, &QTimer::timeout, this, &MainWidget::sendMulticastMessage); -// //multicastTimer->start(1000); // 每秒发送一次组播消息 -//#endif -//} -// -//MainWidget::~MainWidget() -//{ -//#if TEST_UDP_BROADCAST -// multicastTimer->stop(); -// multicastSocket->leaveMulticastGroup(QHostAddress("224.0.0.251")); -// multicastSocket->close(); -//#endif -// stopMdnsService(); -// for (auto timer : clientReadTimers) { -// timer->stop(); -// delete timer; -// } -// clientReadTimers.clear(); -// for (ClientHandler* handler : clients) { -// handler->deleteLater(); -// } -// server->close(); -// -// for (auto thread : clientThreads) { -// thread->quit(); -// thread->wait(); -// delete thread; -// } -// clientThreads.clear(); -// -// for (auto handler : clients_1) { -// handler->deleteLater(); -// } -// clients_1.clear(); -// -// for (auto timer : clientTimers) { -// timer->stop(); -// delete timer; -// } -// clientTimers.clear(); -// -// if (server->isListening()) { -// server->close(); -// } -// qDebug() << "MainWidget destroyed"; -//} -// -//void MainWidget::startClientReadTimer(int clientId) { -// qDebug() << "------ startClientReadTimer clientId:" << clientId; -// if (clientReadTimers.contains(clientId)) { -// clientReadTimers[clientId]->start(10); -// } -//} -// -//void MainWidget::stopClientReadTimer(int clientId) { -// qDebug() << "------ stopClientReadTimer clientId:" << clientId; -// if (clientReadTimers.contains(clientId)) { -// clientReadTimers[clientId]->stop(); -// } -//} -// -//void MainWidget::onCheckConnectionStatus() -//{ -// int activeThreadCount = clients_1.size(); -// //qDebug() << "------Number of active threads:" << activeThreadCount; -// for (auto it = clients_1.begin(); it != clients_1.end(); ++it) { -// int clientId = it.key(); -// ClientHandler* handler = it.value(); -// QTcpSocket* socket = handler->getSocket(); -// if (socket->state() != QTcpSocket::ConnectedState) { -// qCritical() << "--------------Connection lost for clientId:" << clientId << ". Socket state:" << socket->state(); -// emit handler->clientDisconnected(handler); -// } -// else { -// qDebug() << "Connection for clientId:" << clientId << "is active."; -// } -// } -//} -// -//void MainWidget::onCheckThreadStatus() -//{ -// //qDebug() << "Checking thread status..."; -// int activeThreadCount = clientThreads.size(); -// //qDebug() << "Number of active threads:" << activeThreadCount; -// for (auto it = clientThreads.begin(); it != clientThreads.end(); ++it) { -// int clientId = it.key(); -// QThread* thread = it.value(); -// ClientHandler* handler = nullptr; -// for (ClientHandler* h : clients) { -// if (h->getClientId() == clientId) { -// handler = h; -// break; -// } -// } -// if (handler && handler->isData_Stuck()) { -// qDebug() << "Thread for clientId:" << clientId << "is stuck."; -// // 处理线程卡住的情况,比如重启线程或记录更多日志 -// } -// else if (thread->isRunning()) { -// qDebug() << "isData_Stuck = :" << handler->isData_Stuck(); -// qDebug() << "Thread for clientId:" << clientId << "is running."; -// } -// else { -// qDebug() << "Thread for clientId:" << clientId << "is not running."; -// // 处理线程意外停止的情况 -// } -// } -//} -// -//// 打印线程池信息 -//void MainWidget::printThreadPoolInfo() -//{ -// QThreadPool* threadPool = QThreadPool::globalInstance(); -// //qDebug() << "Active threads:" << threadPool->activeThreadCount(); -// //qDebug() << "Max threads:" << threadPool->maxThreadCount(); -//} -// -//void MainWidget::setupTimerForThreadPoolInfo() -//{ -// QTimer* timer = new QTimer(this); -// connect(timer, &QTimer::timeout, this, &MainWidget::printThreadPoolInfo); -// timer->start(5000); // 每5秒打印一次线程池信息 -//} -// -//void MainWidget::readJsonConfig() -//{ -// frontBoardOneClickTest = readJson_frontBoardOneClickTest(); -// frontBoardTest = readJson_frontBoardTest(); -// frontBoardFuncConfig = readJson_frontBoardFuncConfig(); -// frontBoardDevInfoJson = readJson_frontDevInfo(); -// frontBoardLicenseJson = readJson_frontLicense(); -// backBoardDevInfoJson = readJson_backDevInfo(); -// testJsonConfig = readJson_testConfig(); -// funcJsonConfig = readJson_funcConfig(); -// -// getPicJson = readJson_getPic(); -// getVideoJson = readJson_getVideo(); -//} -// -//// 设置 UI -//void MainWidget::setupUI() -//{ -// startServerButton = new QPushButton("开始监听\n(Start Listening...)", this); -// startServerButton->setFixedSize(190, 70); // 设置宽度为 190 像素,高度为 70 像素 -// -// sendAllButton = new QPushButton("一键功能测试", this); -// sendAllButton->setFixedSize(190, 70); // 设置宽度为 190 像素,高度为 70 像素 -// sendAllButton->setEnabled(false); -// -// statusListWidget = new QListWidget(this); -// //statusListWidget->setMinimumSize(350, 880); -// statusListWidget->setMinimumSize(350, 680); -// statusListWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // 设置大小策略为扩展 -// -// QHBoxLayout* buttonLayout = new QHBoxLayout; -// buttonLayout->addWidget(startServerButton); -// buttonLayout->addWidget(sendAllButton); -// buttonLayout->addStretch(); -// -// QVBoxLayout* leftLayout = new QVBoxLayout; -// leftLayout->addLayout(buttonLayout); -// leftLayout->setStretch(0, 1); -// leftLayout->addWidget(statusListWidget); -// leftLayout->setStretch(1, 200); -// -// saveCheckBox = new QCheckBox("", this); -// selectFileButton = new QPushButton("Save", this); -// selectFileButton->setFixedSize(45, 28); -// clearLogButton = new QPushButton("Clear", this); -// clearLogButton->setFixedSize(55, 28); -// filePathLineEdit = new QLineEdit(this); -// filePathLineEdit->setFixedSize(250, 28); -// filePathLineEdit->setReadOnly(true); -// -// QHBoxLayout* fileLayout = new QHBoxLayout; -// fileLayout->addWidget(saveCheckBox); -// fileLayout->addWidget(selectFileButton); -// fileLayout->addWidget(filePathLineEdit); -// fileLayout->addWidget(clearLogButton); -// -// leftLayout->addLayout(fileLayout); -// leftLayout->setStretch(2, 1); -// -// // 读取 JSON 配置文件 -// readJsonConfig(); -// -// QGroupBox* groupBox = new QGroupBox("算法 license", this); -// QHBoxLayout* buttonRowLayout = new QHBoxLayout; -// for (int i = 0; i < frontBoardLicenseJson.size(); ++i) { -// QJsonObject item = frontBoardLicenseJson[i].toObject(); -// QString buttonText = item["lable"].toString(); -// QPushButton* button = new QPushButton(buttonText, this); -// button->setProperty("licenseIndex", i); -// buttonRowLayout->addWidget(button); -// connect(button, &QPushButton::clicked, this, &MainWidget::onLicenseButtonClicked); -// } -// licenseHwInfoEdit->setReadOnly(true); -// licenseHwInfoEdit->setText("This is a read-only text"); -// licenseHwInfoEdit->setFixedHeight(80); -// -// QVBoxLayout* groupBoxLayout_license = new QVBoxLayout; -// groupBoxLayout_license->addLayout(buttonRowLayout); -// groupBoxLayout_license->addWidget(licenseHwInfoEdit); -// groupBox->setLayout(groupBoxLayout_license); -// -// leftLayout->addWidget(groupBox); -// leftLayout->setStretch(3, 1); -// -// QWidget* leftContainer = new QWidget(this); -// leftContainer->setLayout(leftLayout); -// leftContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); -// -// QTabWidget* tabWidget = new QTabWidget(this); -// tabWidget->setFixedSize(900, 315); // 设置 QTabWidget 的固定大小 -// -// QGroupBox* frontDeviceInfoGroupBox = new QGroupBox("前板设备信息", this); -// QVBoxLayout* frontDeviceInfoLayout = new QVBoxLayout(frontDeviceInfoGroupBox); -// -// QVBoxLayout* frontDeviceLabelsLayout = new QVBoxLayout; -// for (const QJsonValue& value : frontBoardDevInfoJson) { -// QJsonObject item = value.toObject(); -// QString label = item["lable"].toString(); -// QString cmd = item["cmd"].toString(); -// QLabel* itemLabel = new QLabel(label, this); -// QLineEdit* itemLineEdit = new QLineEdit(this); -// itemLineEdit->setReadOnly(true); -// -// QHBoxLayout* itemLayout = new QHBoxLayout; -// itemLayout->addWidget(itemLabel); -// itemLayout->addWidget(itemLineEdit); -// -// frontDeviceLabelsLayout->addLayout(itemLayout); -// devInfoLineEdits[cmd] = itemLineEdit; -// } -// frontDeviceInfoLayout->addLayout(frontDeviceLabelsLayout); -// frontDeviceInfoLayout->addStretch(); -// -// QGroupBox* backDeviceInfoGroupBox = new QGroupBox("后板设备信息", this); -// QVBoxLayout* backDeviceInfoLayout = new QVBoxLayout(backDeviceInfoGroupBox); -// -// QVBoxLayout* backDeviceLabelsLayout = new QVBoxLayout; -// for (const QJsonValue& value : backBoardDevInfoJson) { -// QJsonObject item = value.toObject(); -// QString label = item["lable"].toString(); -// QString cmd = item["cmd"].toString(); -// QLabel* itemLabel = new QLabel(label, this); -// QLineEdit* itemLineEdit = new QLineEdit(this); -// itemLineEdit->setReadOnly(true); -// -// QHBoxLayout* itemLayout = new QHBoxLayout; -// itemLayout->addWidget(itemLabel); -// itemLayout->addWidget(itemLineEdit); -// -// backDeviceLabelsLayout->addLayout(itemLayout); -// devInfoLineEdits[cmd] = itemLineEdit; -// } -// backDeviceInfoLayout->addLayout(backDeviceLabelsLayout); -// backDeviceInfoLayout->addStretch(); -// -// QHBoxLayout* groupBoxLayout = new QHBoxLayout; -// groupBoxLayout->addWidget(frontDeviceInfoGroupBox, 1); -// groupBoxLayout->addWidget(backDeviceInfoGroupBox, 1); -// -// QWidget* functionTestTab = new QWidget; -// QVBoxLayout* functionTestLayout = new QVBoxLayout(functionTestTab); -// functionTestTab->setLayout(functionTestLayout); -// tabWidget->addTab(functionTestTab, "功能测试区"); -// -// QGridLayout* buttonGridLayout = new QGridLayout(); -// int buttonsPerRow = 7; // 每行显示的按键数量,根据需要调整 -// // 为每个 JSON 项目创建按键,并添加到 rightLayout -// // 先总共放 77 个按键 -// //qDebug() << "testJsonConfig.size():" << testJsonConfig.size(); -// for (int i = 0; i < frontBoardTest.size() + (77 - frontBoardTest.size()); ++i) { -// QJsonObject item = frontBoardTest[i].toObject(); -// QString buttonText = item["lable"].toString(); -// // 判断 buttonText 是否为空或者只有空白字符 -// if (buttonText.isEmpty()) { -// //qDebug() << "buttonText.isEmpty():" << buttonText.isEmpty(); -// buttonText = QString("Send Item %1").arg(i + 1); -// } -// QPushButton* button = new QPushButton(buttonText, this); -// button->setProperty("frontBoardTest", i); -// button->setFixedSize(110, 35); // 设置按键宽度和高度 -// connect(button, &QPushButton::clicked, this, &MainWidget::onSendItemClicked); -// -// int row = i / buttonsPerRow; -// int col = i % buttonsPerRow; -// buttonGridLayout->addWidget(button, row, col, Qt::AlignLeft); -// -// itemButtons.append(button); -// } -// -// QWidget* buttonContainer = new QWidget; -// buttonContainer->setLayout(buttonGridLayout); -// -// QScrollArea* scrollArea = new QScrollArea; -// scrollArea->setWidget(buttonContainer); -// scrollArea->setWidgetResizable(true); -// -// functionTestLayout->addWidget(scrollArea); -// -// QWidget* functionConfigTab = new QWidget; -// QVBoxLayout* functionConfigLayout = new QVBoxLayout(functionConfigTab); -// functionConfigTab->setLayout(functionConfigLayout); -// tabWidget->addTab(functionConfigTab, "功能配置区"); -// -// funcConfigLineEdit->setPlaceholderText("请输入配置参数..."); -// functionConfigLayout->addWidget(funcConfigLineEdit); -// -// QGridLayout* configButtonGridLayout = new QGridLayout(); -// -// for (int i = 0; i < frontBoardFuncConfig.size() + (77 - frontBoardFuncConfig.size()); ++i) { -// QJsonObject item = frontBoardFuncConfig[i].toObject(); -// QString buttonText = item["lable"].toString(); -// // 判断 buttonText 是否为空或者只有空白字符 -// if (buttonText.isEmpty()) { -// //qDebug() << "buttonText.isEmpty():" << buttonText.isEmpty(); -// buttonText = QString("Cfg Item %1").arg(i + 1); -// } -// QPushButton* button = new QPushButton(buttonText, this); -// button->setProperty("frontBoardFuncConfig", i); -// button->setFixedSize(110, 35); // 设置按键宽度和高度 -// connect(button, &QPushButton::clicked, this, &MainWidget::onSendFuncItemClicked); -// -// int row = i / buttonsPerRow; -// int col = i % buttonsPerRow; -// configButtonGridLayout->addWidget(button, row, col, Qt::AlignLeft); -// -// funcItemButtons.append(button); -// } -// -// QWidget* configButtonContainer = new QWidget; -// configButtonContainer->setLayout(configButtonGridLayout); -// -// QScrollArea* configScrollArea = new QScrollArea; -// configScrollArea->setWidget(configButtonContainer); -// configScrollArea->setWidgetResizable(true); -// -// functionConfigLayout->addWidget(configScrollArea); -// -// QTabWidget* tabWidget_media = new QTabWidget(this); -// QWidget* imageDisplayTab = new QWidget; -// QVBoxLayout* imageDisplayLayout = new QVBoxLayout(imageDisplayTab); -// imageDisplayTab->setLayout(imageDisplayLayout); -// tabWidget_media->addTab(imageDisplayTab, "图像显示区"); -// -// QVBoxLayout* imageButtonsColumnLayout = new QVBoxLayout; -// for (int i = 0; i < 5; ++i) { -// QHBoxLayout* imageButtonsRowLayout = new QHBoxLayout; -// for (int j = 0; j < 2; ++j) { -// QPushButton* button; -// if (i == 0 && j == 0) { -// button = new QPushButton(QString("IR"), this); -// button->setFixedSize(73, 50); -// imageButtonsRowLayout->addWidget(button); -// button->setProperty("getPicIndex", i * 2 + j); -// connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked); -// getPicButtons.append(button); -// continue; -// } -// else if (i == 0 && j == 1) { -// button = new QPushButton(QString("RGB"), this); -// button->setFixedSize(73, 50); -// imageButtonsRowLayout->addWidget(button); -// button->setProperty("getPicIndex", i * 2 + j); -// connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked); -// getPicButtons.append(button); -// continue; -// } -// -// button = new QPushButton(QString("Device %1").arg(i * 2 + j - 1), this); -// button->setFixedSize(73, 50); -// imageButtonsRowLayout->addWidget(button); -// button->setProperty("getPicIndex", i * 2 + j); -// connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked); -// getPicButtons.append(button); -// } -// imageButtonsColumnLayout->addLayout(imageButtonsRowLayout); -// } -// -// QHBoxLayout* lensesLayout = new QHBoxLayout; -// leftLens_imageLabel = new QLabel(this); -// rightLens_imageLabel = new QLabel(this); -// lensesLayout->addWidget(leftLens_imageLabel); -// lensesLayout->addWidget(rightLens_imageLabel); -// -// QHBoxLayout* imageAndButtonsLayout = new QHBoxLayout; -// imageAndButtonsLayout->addLayout(imageButtonsColumnLayout, 1); -// imageAndButtonsLayout->addLayout(lensesLayout, 4); -// imageDisplayLayout->addLayout(imageAndButtonsLayout); -// -// QWidget* videoDisplayTab = new QWidget; -// QVBoxLayout* videoDisplayLayout = new QVBoxLayout(videoDisplayTab); -// videoDisplayTab->setLayout(videoDisplayLayout); -// tabWidget_media->addTab(videoDisplayTab, "视频显示区"); -// -// QVBoxLayout* videoButtonsColumnLayout = new QVBoxLayout; -// for (int i = 0; i < 6; ++i) { -// QHBoxLayout* videoButtonsRowLayout = new QHBoxLayout; -// for (int j = 0; j < 2; ++j) { -// QPushButton* button; -// if (i == 0 && j == 0) { -// button = new QPushButton(QString("IR"), this); -// button->setFixedSize(73, 50); -// videoButtonsRowLayout->addWidget(button); -// button->setProperty("getVideoIndex", i * 2 + j); -// connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked); -// getVideoButtons.append(button); -// continue; -// } -// else if (i == 0 && j == 1) { -// button = new QPushButton(QString("RGB"), this); -// button->setFixedSize(73, 50); -// videoButtonsRowLayout->addWidget(button); -// button->setProperty("getVideoIndex", i * 2 + j); -// connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked); -// getVideoButtons.append(button); -// continue; -// } -// -// // 调价调焦窗口按键 -// if (i == 1 && j == 0) { -// button = new QPushButton(QString("大窗口播放视频"), this); -// button->setFixedSize(150, 50); -// button->setEnabled(false); -// videoButtonsRowLayout->addWidget(button); -// button->setProperty("getVideoIndex", i * 2 + j); -// connect(button, &QPushButton::clicked, this, &MainWidget::onOpenFocusWindowClicked); -// getVideoButtons.append(button); -// break; // 跳出内层循环,只添加一个按键 -// } -// -// //int adjustedIndex = (i > 1) ? i * 2 + j - 1 : i * 2 + j; -// button = new QPushButton(QString("Device %1").arg(i * 2 + j - 3), this); -// //button = new QPushButton(QString("Device %1").arg(adjustedIndex), this); -// button->setFixedSize(73, 50); -// videoButtonsRowLayout->addWidget(button); -// button->setProperty("getVideoIndex", i * 2 + j + 1); -// //button->setProperty("getVideoIndex", adjustedIndex); -// connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked); -// getVideoButtons.append(button); -// } -// videoButtonsColumnLayout->addLayout(videoButtonsRowLayout); -// } -// -// QHBoxLayout* videoAndButtonsLayout = new QHBoxLayout; -// videoLabel = new QLabel(this); -// //videoLabel->setFixedSize(640, 480); -// videoAndButtonsLayout->addLayout(videoButtonsColumnLayout, 1); -// videoAndButtonsLayout->addWidget(videoLabel, 6); -// videoDisplayLayout->addLayout(videoAndButtonsLayout); -// -// QVBoxLayout* rightVerticalLayout = new QVBoxLayout; -// rightVerticalLayout->addLayout(groupBoxLayout, 2); -// rightVerticalLayout->addWidget(tabWidget, 2, Qt::AlignTop | Qt::AlignLeft); -// rightVerticalLayout->addWidget(tabWidget_media, 5); -// -// QHBoxLayout* mainLayout = new QHBoxLayout; -// // 参数二:伸缩因子,leftContainer:1/3 ,rightLayout:2/3 -// mainLayout->addWidget(leftContainer, 1, Qt::AlignTop | Qt::AlignLeft); // 设置 leftContainer 左上对齐 -// mainLayout->addLayout(rightVerticalLayout, 3); -// -// setLayout(mainLayout); -// setWindowTitle("SL100 工厂产测工具 - V0.0.1"); -// resize(1340, 1000); // 设置宽度为 1440 像素,高度为 900 像素 -// -// connect(startServerButton, &QPushButton::clicked, this, &MainWidget::onStartServerClicked); -// connect(sendAllButton, &QPushButton::clicked, this, &MainWidget::onSendAllClicked); -// connect(statusListWidget, &QListWidget::itemChanged, this, &MainWidget::scrollToBottom); -// connect(selectFileButton, &QPushButton::clicked, this, &MainWidget::onSelectFileButtonClicked); -// connect(clearLogButton, &QPushButton::clicked, this, &MainWidget::onclearLogButtonClicked); -// connect(saveCheckBox, &QCheckBox::stateChanged, this, &MainWidget::onSaveCheckBoxStateChanged); -//} -// -//void MainWidget::onSelectFileButtonClicked() -//{ -// QString filePath = QFileDialog::getSaveFileName(this, tr("选择文件路径"), "", tr("Text Files (*.txt);;All Files (*)")); -// if (!filePath.isEmpty()) { -// filePathLineEdit->setText(filePath); -// } -//} -// -//void MainWidget::onclearLogButtonClicked() -//{ -// statusListWidget->clear(); -//} -// -//void MainWidget::onSaveCheckBoxStateChanged(int state) -//{ -// if (state == Qt::Checked) { -// saveStatusListToFile(filePathLineEdit->text()); -// } -//} -// -//void MainWidget::saveStatusListToFile(const QString& filePath) -//{ -// if (filePath.isEmpty()) { -// return; -// } -// -// QFile file(filePath); -// if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { -// return; -// } -// -// QTextStream out(&file); -// for (int i = 0; i < statusListWidget->count(); ++i) { -// QListWidgetItem* item = statusListWidget->item(i); -// out << item->text() << "\n"; -// } -// file.close(); -//} -// -//void MainWidget::onStartTimeout(int clientId, int timeout) -//{ -// //qDebug() << "---------------> onStartTimeout :" << clientId << "timeout :" << timeout; -// if (clientTimers.contains(clientId)) { -// QTimer* timer = clientTimers[clientId]; -// if (timeout > 0) { -// timer->start(timeout); -// } -// else { -// timer->stop(); -// } -// } -//} -// -//void MainWidget::scrollToBottom() -//{ -// statusListWidget->scrollToBottom(); -//} -// -//void MainWidget::onDisconnectClient(int clientId) -//{ -// for (ClientHandler* handler : clients) { -// if (handler->getClientId() == clientId) { -// // 断开与该客户端的连接 -// handler->getSocket()->disconnectFromHost(); -// handler->getSocket()->waitForDisconnected(); -// clients.removeOne(handler); -// if (clientTimers.contains(clientId)) { -// QTimer* timer = clientTimers[clientId]; -// timer->stop(); -// delete timer; -// clientTimers.remove(clientId); -// } -// handler->deleteLater(); -// // 更新连接数并更新按键文本 -// connectedClientsCount--; -// updateServerButtonText(); -// -// break; -// } -// } -// -// // 启动 mDNS 服务广播 -// startMdnsService(); -//} -// -//// 处理客户端断开连接信号 -//void MainWidget::onClientDisconnected(ClientHandler* handler) -//{ -// int clientId = handler->getClientId(); -// if (clientTimers.contains(clientId)) { -// QTimer* timer = clientTimers[clientId]; -// timer->stop(); -// delete timer; -// clientTimers.remove(clientId); -// } -// -// clients.removeOne(handler); -// /* -// 将 ClientHandler 对象的删除操作放入事件队列中,等待事件循环处理。 -// 在事件循环执行时,会安全地删除 ClientHandler 对象,这包括释放其占用的资源和内存 -// */ -// handler->deleteLater(); // 延迟删除 ClientHandler 对象 -// -// // 更新连接数并更新按键文本 -// connectedClientsCount--; -// if (nextClientId <= 2) nextClientId--; -// deviceConnected = true; -// updateServerButtonText(); -//} -// -//// 更新按键文本的函数 -//void MainWidget::updateServerButtonText() -//{ -// if (deviceConnected) { -// deviceConnected = false; -// startServerButton->setText(tr("正在监听(Listening)")); -// } -// else if (connectedClientsCount == 0) { -// startServerButton->setText(tr("开始监听\n(Start Listening...)")); -// } -// else { -// startServerButton->setText(tr("正在监听(Listening)\n%1 台设备连接").arg(connectedClientsCount)); -// } -//} -// -//void MainWidget::onLicenseButtonClicked() -//{ -// if (connectedClientsCount) { -// QPushButton* button = qobject_cast(sender()); -// if (button) { -// int index = button->property("licenseIndex").toInt(); -// if (index >= 0 && index < frontBoardLicenseJson.size()) { -// QJsonObject jsonObject = frontBoardLicenseJson[index].toObject(); -// //QString jsonString = QJsonDocument(jsonObject).toJson(QJsonDocument::Compact); -// //qDebug() << "license Button clicked, sending JSON:" << jsonString; -// unsigned char license_info[PIX_LICENCE_BYTES] = { 0 }; -// if (jsonObject["lable"].toString() == "get_license") { -// LicenseConfirmWindow dialog("你确定要获取此授权吗?"); -// if (dialog.exec() == QDialog::Accepted) -// licenseGenerate(license_info, license_info); -// } -// else { -// if (jsonObject["lable"].toString() == "write_license") { -// LicenseConfirmWindow dialog("你确定要发送此授权吗?"); -// if (dialog.exec() == QDialog::Accepted) -// licenseGenerate(license_info, license_info); -// } -// for (ClientHandler* handler : clients) { -// handler->sendLicenseItem(index); -// } -// } -// } -// } -// } -// else { -// QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); -// listItem->setBackground(Qt::red); -// } -//} -// -//void MainWidget::startMdnsService() -//{ -// QString serviceName = "My Mdns Broadcast Service"; // 替换为你想要的服务名称 -// QString serviceType = "_my-service._tcp"; // 替换为实际的服务类型 -// quint16 port = 12412; // 使用的端口号,确保与 TCP 服务器监听的端口号一致 -// mServiceProvider->startServiceBroadcast(serviceName, serviceType, port); -//} -// -//void MainWidget::stopMdnsService() -//{ -// mServiceProvider->stopServiceBroadcast(); -//} -// -//#if TEST_UDP_BROADCAST -//void MainWidget::sendMulticastMessage() -//{ -// QByteArray datagram = "Test multicast message from MainWidget"; -// QHostAddress groupAddress("224.0.0.251"); -// quint16 port = 5353; -// -// qint64 sentBytes = multicastSocket->writeDatagram(datagram, groupAddress, port); -// if (sentBytes == -1) { -// qWarning() << "Failed to send multicast message:" << multicastSocket->errorString(); -// } -// else { -// qDebug() << "Multicast message sentBytes:" << sentBytes; -// qDebug() << "Multicast message sent:" << datagram; -// } -//} -//#endif -// -//// 处理开始服务器按键点击事件 -//void MainWidget::onStartServerClicked() -//{ -// if (!server->isListening()) { -// // 启动 mDNS 服务广播 -// startMdnsService(); -//#if TEST_UDP_BROADCAST -// sendMulticastMessage(); -//#endif -// // 根据需要修改 -// // QHostAddress specifiedIpAddress("10.10.10.253"); -// quint16 specifiedPort = 12412; -// qDebug() << "" << specifiedPort; -// if (server->listen(QHostAddress::Any, specifiedPort)) { -// startServerButton->setText(tr("正在监听(Listening)")); -// // 设置按钮背景色为绿色 -// startServerButton->setStyleSheet("background-color: green;"); -// sendAllButton->setEnabled(true); -// -// // 启动 mDNS 服务广播 -// //startMdnsService(); -// } -// else { -// qDebug() << "Failed to start server. Error:" << server->errorString(); -// } -// } -// else { -// server->close(); -// startServerButton->setText(tr("开始监听\n(Start Listening...)")); -// startServerButton->setStyleSheet(""); -// sendAllButton->setEnabled(false); -// -// // 停止 mDNS 服务广播 -// //stopMdnsService(); -// } -//} -// -//// 处理发送获取设备信息按键点击事件 -//void MainWidget::onSendGetDevInfoClicked() -//{ -// if (connectedClientsCount) { -// QPushButton* button = qobject_cast(sender()); -// int itemIndex = button->property("deviceInfoIndex").toInt(); -// if (itemIndex + 1 > connectedClientsCount) { -// QListWidgetItem* listItem = new QListWidgetItem(QString("No device %1 is connected !!!").arg(itemIndex + 1), statusListWidget); -// listItem->setBackground(Qt::red); -// } -// else { -// for (ClientHandler* handler : clients) { -// handler->sendGetDevInfoItem(itemIndex); -// } -// } -// } -// else { -// QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); -// listItem->setBackground(Qt::red); -// } -//} -// -//// 处理发送取图按键点击事件 -//void MainWidget::onSendGetPicClicked() -//{ -// if (connectedClientsCount) { -// QPushButton* button = qobject_cast(sender()); -// int itemIndex = button->property("getPicIndex").toInt(); -// -// if (itemIndex < 2) { -// button->setStyleSheet("background-color: green;"); -// if (lastClickedGetPicCamIndex != -1 && lastClickedGetPicCamIndex != itemIndex) { -// getPicButtons[lastClickedGetPicCamIndex]->setStyleSheet(""); -// } -// lastClickedGetPicCamIndex = itemIndex; -// } -// else { -// if (lastClickedGetPicCamIndex == -1) { -// QListWidgetItem* listItem = new QListWidgetItem(QString("Please select IR or RGB lens to get image!!!"), statusListWidget); -// listItem->setBackground(Qt::red); -// } -// else { -// if (itemIndex - 2 >= connectedClientsCount) { -// QListWidgetItem* listItem = new QListWidgetItem(QString("No device %1 is connected !!!").arg(itemIndex - 1), statusListWidget); -// listItem->setBackground(Qt::red); -// } -// else { -// button->setStyleSheet("background-color: green;"); -// if (lastClickedGetPicDevIndex != -1 && lastClickedGetPicDevIndex != itemIndex) { -// getPicButtons[lastClickedGetPicDevIndex]->setStyleSheet(""); -// } -// lastClickedGetPicDevIndex = itemIndex; -// //QMutexLocker locker(&mutex); -// for (ClientHandler* handler : clients) { -// handler->sendGetPicItem(itemIndex - 2, lastClickedGetPicCamIndex); -// } -// } -// } -// } -// } -// else { -// QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); -// listItem->setBackground(Qt::red); -// } -//} -// -//// 处理发送拉视频流按键点击事件 -//void MainWidget::onSendGetVideoClicked() -//{ -// if (connectedClientsCount) { -// QPushButton* button = qobject_cast(sender()); -// int itemIndex = button->property("getVideoIndex").toInt(); -// -// if (itemIndex < 2) { -// button->setStyleSheet("background-color: green;"); -// if (lastClickedGetVideoCamIndex != -1 && lastClickedGetVideoCamIndex != itemIndex) { -// getVideoButtons[lastClickedGetVideoCamIndex]->setStyleSheet(""); -// } -// lastClickedGetVideoCamIndex = itemIndex; -// } -// else { -// if (lastClickedGetVideoCamIndex == -1) { -// QListWidgetItem* listItem = new QListWidgetItem(QString("Please select IR or RGB lens to get video!!!"), statusListWidget); -// listItem->setBackground(Qt::red); -// } -// else { -// if (itemIndex - 6 >= connectedClientsCount) { -// QListWidgetItem* listItem = new QListWidgetItem(QString("No device %1 is connected !!!").arg(itemIndex - 4), statusListWidget); -// listItem->setBackground(Qt::red); -// } -// else { -// button->setStyleSheet("background-color: green;"); -// if (lastClickedGetVideoDevIndex != -1 && lastClickedGetVideoDevIndex != itemIndex) { -// getVideoButtons[lastClickedGetVideoDevIndex]->setStyleSheet(""); -// } -// lastClickedGetVideoDevIndex = itemIndex; -// //QMutexLocker locker(&mutex); -// for (ClientHandler* handler : clients) { -// handler->sendGetVideoItem(itemIndex - 5, 1); -// } -// getVideoButtons[2]->setEnabled(true); -// } -// } -// } -// } -// else { -// QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); -// listItem->setBackground(Qt::red); -// } -//} -// -//void MainWidget::onOpenFocusWindowClicked() -//{ -// QPushButton* button = qobject_cast(sender()); -// if (button) { -// int itemIndex = button->property("getVideoIndex").toInt(); -// //qDebug() << "New Button clicked with itemIndex:" << itemIndex; -// if (itemIndex == 2) { -// // 创建并显示新窗口 -// NewButtonDialog dialog(this); -// dialog.exec(); -// } -// } -//} -// -//// 处理一键发送按键点击事件 -//void MainWidget::onSendAllClicked() -//{ -// if (connectedClientsCount) { -// QMutexLocker locker(&mutex); -// isSendingAll = !isSendingAll; -// if (isSendingAll) { -// sendAllButton->setText("一键功能测试中...\n再次点击取消"); -// sendAllButton->setStyleSheet("background-color: green;"); -// manualSend = true; -// for (ClientHandler* handler : clients) { -// // 重置索引 -// handler->resetCurrentItemIndex(); -// handler->sendNextItem(); -// //handler->sendDevInfoItem(); -// } -// } -// else { -// sendAllButton->setText("一键功能测试"); -// sendAllButton->setStyleSheet("background-color: white;"); -// manualSend = false; -// for (ClientHandler* handler : clients) { -// handler->resetCurrentItemIndex(); -// } -// } -// } -// else { -// QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); -// listItem->setBackground(Qt::red); -// } -//} -// -//// 处理单独发送功能项按键点击事件 -//void MainWidget::onSendFuncItemClicked() -//{ -// if (connectedClientsCount) { -// QPushButton* button = qobject_cast(sender()); -// int itemIndex = button->property("frontBoardFuncConfig").toInt(); -// for (ClientHandler* handler : clients) { -// QString text = funcConfigLineEdit->text(); -// qDebug() << "Text in funcConfigLineEdit:" << text; -// handler->sendFuncItem(itemIndex, text); -// } -// } -// else { -// QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); -// listItem->setBackground(Qt::red); -// } -//} -// -//// 处理单独发送项按键点击事件 -//void MainWidget::onSendItemClicked() -//{ -// if (connectedClientsCount) { -// QPushButton* button = qobject_cast(sender()); -// int itemIndex = button->property("frontBoardTest").toInt(); -// for (ClientHandler* handler : clients) { -// handler->sendItem(itemIndex); -// } -// } -// else { -// QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); -// listItem->setBackground(Qt::red); -// } -//} -// -//// 处理状态更新信号 -//void MainWidget::onStatusUpdated(const QString& client, int itemIndex, int FuncItemIndex, -// bool success, const QString& itemData, const QString& funcItemData) -//{ -// int clientId = -1; -// // 遍历所有的 ClientHandler,找到匹配的 client -// for (ClientHandler* handler : clients) { -// if (handler->getClientAddress() == client) { -// clientId = handler->getClientId(); -// QString lable = handler->getCurrentItemLable(); -// lable = handler->getCurrentFuncItemLable(); -// break; -// } -// else -// { -// //qDebug() << "" << __FUNCTION__ << "handler->getClientAddress() != client" ; -// } -// } -// //qDebug() << "itemIndex :" << itemIndex; -// //qDebug() << "FuncItemIndex:" << FuncItemIndex; -// if (itemIndex > 0) { -// QListWidgetItem* listItem = new QListWidgetItem(QString("device ID: %1 - Item %2: %3 ---> %4") -// .arg(clientId) -// .arg(itemIndex) -// .arg(itemData) // data 字段 -// .arg(success ? "OK" : "NG"), statusListWidget); -// -// listItem->setBackground(success ? Qt::green : Qt::red); -// statusListWidget->addItem(listItem); -// } -// else if (FuncItemIndex > 0) { -// QListWidgetItem* listItem = new QListWidgetItem(QString("device ID: %1 - funcItem %2: %3 ---> %4") -// .arg(clientId) -// .arg(FuncItemIndex) -// .arg(funcItemData) // data 字段 -// .arg(success ? "OK" : "NG"), statusListWidget); -// -// listItem->setBackground(success ? Qt::green : Qt::red); -// statusListWidget->addItem(listItem); -// } -// statusListWidget->scrollToBottom(); -//} -// -//// json文件里面的配置项都测试结束 -//void MainWidget::onAllItemsProcessed(const QString& client, int itemsProcessedCount) -//{ -// isSendingAll = false; -// sendAllButton->setText("一键功能测试"); -// sendAllButton->setStyleSheet("background-color: white;"); -// //qDebug() << "onAllItemsProcessed called for client:" << client << "itemsProcessedCount:" << itemsProcessedCount; -// int clientId = -1; -// for (ClientHandler* handler : clients) { -// if (handler->getClientAddress() == client) { -// clientId = handler->getClientId(); -// qDebug() << "Current clientId:" << clientId; -// break; -// } -// else -// { -// //qDebug() << "" << __FUNCTION__ << "handler->getClientAddress() != client"; -// } -// } -// -// QListWidgetItem* listItem = new QListWidgetItem(QString("device ID:-%1 ---> All %2 items test completed !!!") -// .arg(clientId) -// .arg(itemsProcessedCount), statusListWidget); -// statusListWidget->addItem(listItem); -// statusListWidget->scrollToBottom(); -//} diff --git a/FactoryTestTool/SourceCode/Widget/MainWidget.h b/FactoryTestTool/SourceCode/Widget/MainWidget.h index 884de3a..87dd8db 100644 --- a/FactoryTestTool/SourceCode/Widget/MainWidget.h +++ b/FactoryTestTool/SourceCode/Widget/MainWidget.h @@ -18,7 +18,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -29,6 +31,18 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "../Json/readJsonFile.h" #include "../RecvDataHandler/RecvDataHandler.h" @@ -36,6 +50,7 @@ #include "../LicenseGenerate/LicenseConfirmWindow.h" #include "../Network/mdns/servicemodel.h" #include "../Network/ClientHandler.h" +#include "../Network/httpClient.h" #include "FocusWindow.h" // 用于测试 UDP 组播实现 mdns 功能 非标准 mdns @@ -53,6 +68,12 @@ public: ~MainWidget(); private slots: + // 发送HTTP请求 + //void onSomeButtonClicked(); + // 处理HTTP响应 + void onHttpRequestFinished(const QJsonObject& response); + // 处理HTTP错误 + void onHttpRequestError(const QString& errorString); // 处理开始服务器按钮点击事件 void onStartServerClicked(); // 处理发送获取设备信息按键点击事件 @@ -62,12 +83,15 @@ private slots: // 处理发送拉视频流按键点击事件 void onSendGetVideoClicked(); void onLicenseButtonClicked(); + void onUuidButtonClicked(); // 处理一键发送按钮点击事件 void onSendAllClicked(); // 处理单独发送项按钮点击事件 - void onSendItemClicked(); + void onSendFrontItemClicked(); + void onSendBackItemClicked(); // 处理单独发送功能配置项按钮点击事件 - void onSendFuncItemClicked(); + void onSendFrontFuncItemClicked(); + void onSendBackFuncItemClicked(); // 处理数据接收信号 //void onDataReceived(const QString& client, const QByteArray& data); // 处理状态更新信号 @@ -103,16 +127,30 @@ private: void readJsonConfig(); // 设置 UI void setupUI(); + QGroupBox* createLicenseGroupBox(); + QGroupBox* createFrontDeviceInfoGroupBox(); + QGroupBox* createBackDeviceInfoGroupBox(); + QWidget* createFunctionTestTab(const QJsonArray& BoardFuncTest, const QString& propertyName); + QWidget* createFunctionConfigTab(const QJsonArray& BoardFuncConfig, const QString& propertyName); + QWidget* createImageDisplayTab(); + QWidget* createVideoDisplayTab(); + QGroupBox* createBackConnectServerGroupBox(); // 保存日志到文件 void saveStatusListToFile(const QString& filePath); // 用于更新按键文本的函数 void updateServerButtonText(); void onDisconnectClient(int clientId); void setupTimerForThreadPoolInfo(); - - bool isSendingAll; // 一键功能测试 状态 - QTcpServer* server; // TCP 服务器 - //QUdpSocket* udpSocket; + void sendDataToClient(int clientId, const QByteArray& data); + //void FactoryToolSendPostFactoryInfotoHttpServer(); + void FactoryToolSendPostTestToHttpServer(); + void FactoryToolSendPostLicenseToHttpServer(const QString& hardware_info, const QString& license_info); + void FactoryToolSendPostComfirmToHttpServer(const QString& mac_addr, const QString& uuid); + void FactoryToolSendGetUuidToHttpServer(const QString& mac_addr); + void FactoryToolSendGetLicenseToHttpServer(const QString& hw_info); + + QTcpServer* server; // TCP 服务器 + HttpClient* httpClient; // HTTP 服务器 QJsonArray frontBoardOneClickTest; // 前板一键功能测试 JSON QJsonArray frontBoardTest; // 前板单项测试 JSON QJsonArray frontBoardFuncConfig; // 前板功能配置参数 JSON @@ -122,6 +160,7 @@ private: QJsonArray backBoardTest; // 后板单项测试 JSON QJsonArray backBoardFuncConfig; // 后板功能配置参数 JSON QJsonArray backBoardDevInfoJson; // 后板设备信息参数 JSON + QJsonArray backBoardUuidJson; // 后板UUID JSON QJsonArray testJsonConfig; // 功能测试区 JSON 配置 QJsonArray funcJsonConfig; // 功能配置区 JSON 配置 QJsonArray getDevInfoJson; // 获取设备信息 JSON 配置 @@ -136,8 +175,12 @@ private: QMutex mutex; // 互斥锁 int nextClientId; // 新增的客户端编号 int connectedClientsCount = 0; // 连接客户端的数量 + int isRequestSuccessful = 0; // GET请求是否成功 bool manualSend; // 判断是否是手动触发的发送 bool deviceConnected = false; // 判断是否有设备连接过 + bool isSendingAll; // 一键功能测试 状态 + + QJsonObject licenseDataArray; // 用于保存从服务器获取的 data 字段对象 QVector itemButtons; // 项目按键集合 QVector funcItemButtons; // 功能配置项目按键集合 @@ -154,8 +197,10 @@ private: QLabel* leftLens_imageLabel; // 左边镜头图像显示 QLabel* rightLens_imageLabel; // 右边镜头图像显示 QLabel* videoLabel; // 视频显示 - QLineEdit* funcConfigLineEdit; // 功能配置编辑框 + QLineEdit* frontFuncConfigLineEdit; // 前板功能配置编辑框 + QLineEdit* backFuncConfigLineEdit; // 后板功能配置编辑框 QTextEdit* licenseHwInfoEdit; // 获取license的硬件信息 + QTextEdit* UuidHwInfoEdit; // Uuid的硬件信息 MainWidget* mainWidget; QTabWidget* tabWidget; // 标签页 QWidget* functionTestArea; // 功能测试区 diff --git a/FactoryTestTool/SourceCode/Widget/UI_Widget/UI_Widget.cpp b/FactoryTestTool/SourceCode/Widget/UI_Widget/UI_Widget.cpp new file mode 100644 index 0000000..091c401 --- /dev/null +++ b/FactoryTestTool/SourceCode/Widget/UI_Widget/UI_Widget.cpp @@ -0,0 +1,302 @@ +#include "../MainWidget.h" + +QGroupBox* MainWidget::createLicenseGroupBox() +{ + QGroupBox* groupBox = new QGroupBox("算法 license", this); + QHBoxLayout* buttonRowLayout = new QHBoxLayout; + + for (int i = 0; i < frontBoardLicenseJson.size(); ++i) { + QJsonObject item = frontBoardLicenseJson[i].toObject(); + QString buttonText = item["lable"].toString(); + QPushButton* button = new QPushButton(buttonText, this); + button->setProperty("licenseIndex", i); + buttonRowLayout->addWidget(button); + connect(button, &QPushButton::clicked, this, &MainWidget::onLicenseButtonClicked); + } + + //licenseHwInfoEdit->setReadOnly(true); + licenseHwInfoEdit->setReadOnly(false); + licenseHwInfoEdit->setPlaceholderText("1. 点击“get_hw_info”可以获取hw info并显示在此处\n2. 可将hw info输入此处, 点击“get_license”获取License并显示在此处\n3. 点击“write_license”可将License直接写入前板"); + licenseHwInfoEdit->setFixedHeight(80); + + QVBoxLayout* groupBoxLayout_license = new QVBoxLayout; + groupBoxLayout_license->addLayout(buttonRowLayout); + groupBoxLayout_license->addWidget(licenseHwInfoEdit); + groupBox->setLayout(groupBoxLayout_license); + + return groupBox; +} + +QGroupBox* MainWidget::createFrontDeviceInfoGroupBox() +{ + QGroupBox* frontDeviceInfoGroupBox = new QGroupBox("前板设备信息", this); + QFormLayout* formLayout = new QFormLayout(frontDeviceInfoGroupBox); + + for (const QJsonValue& value : frontBoardDevInfoJson) { + QJsonObject item = value.toObject(); + QString label = item["lable"].toString(); + QString cmd = item["cmd"].toString(); + QLabel* itemLabel = new QLabel(label, this); + QLineEdit* itemLineEdit = new QLineEdit(this); + itemLineEdit->setReadOnly(true); + + formLayout->addRow(itemLabel, itemLineEdit); + devInfoLineEdits[cmd] = itemLineEdit; + } + + return frontDeviceInfoGroupBox; +} + +QGroupBox* MainWidget::createBackDeviceInfoGroupBox() +{ + QGroupBox* backDeviceInfoGroupBox = new QGroupBox("后板设备信息", this); + QFormLayout* formLayout = new QFormLayout(backDeviceInfoGroupBox); + + for (const QJsonValue& value : backBoardDevInfoJson) { + QJsonObject item = value.toObject(); + QString label = item["lable"].toString(); + QString cmd = item["cmd"].toString(); + QLabel* itemLabel = new QLabel(label, this); + QLineEdit* itemLineEdit = new QLineEdit(this); + itemLineEdit->setReadOnly(true); + + formLayout->addRow(itemLabel, itemLineEdit); + devInfoLineEdits[cmd] = itemLineEdit; + } + + return backDeviceInfoGroupBox; +} + +QGroupBox* MainWidget::createBackConnectServerGroupBox() +{ + QGroupBox* BackConnectServerGroupBox = new QGroupBox("后板获取UUID", this); + QHBoxLayout* frontDeviceInfoLayout = new QHBoxLayout; + + for (int i = 0; i < backBoardUuidJson.size(); ++i) { + QJsonObject item = backBoardUuidJson[i].toObject(); + QString buttonText = item["lable"].toString(); + QPushButton* button = new QPushButton(buttonText, this); + button->setProperty("UuidIndex", i); + frontDeviceInfoLayout->addWidget(button); + connect(button, &QPushButton::clicked, this, &MainWidget::onUuidButtonClicked); + } + + UuidHwInfoEdit->setReadOnly(true); + UuidHwInfoEdit->setPlaceholderText("1. 点击“获取后板MAC地址”会将后板MAC地址显示在此处\n2. 可将后板MAC地址输入到此处,点击“获取UUID”显示在此处\n"); + UuidHwInfoEdit->setFixedHeight(80); + + QVBoxLayout* groupBoxLayout_uuid = new QVBoxLayout; + groupBoxLayout_uuid->addLayout(frontDeviceInfoLayout); + groupBoxLayout_uuid->addWidget(UuidHwInfoEdit); + BackConnectServerGroupBox->setLayout(groupBoxLayout_uuid); + + return BackConnectServerGroupBox; +} + +QWidget* MainWidget::createFunctionTestTab(const QJsonArray& BoardFuncTest, const QString& propertyName) +{ + QWidget* functionTestTab = new QWidget(this); + QVBoxLayout* functionTestLayout = new QVBoxLayout(functionTestTab); + QGridLayout* buttonGridLayout = new QGridLayout(); + int buttonsPerRow = 7; + + for (int i = 0; i < BoardFuncTest.size() + (77 - BoardFuncTest.size()); ++i) { + QJsonObject item = BoardFuncTest[i].toObject(); + QString buttonText = item["lable"].toString(); + if (buttonText.isEmpty()) { + buttonText = QString("Send Item %1").arg(i + 1); + } + QPushButton* button = new QPushButton(buttonText, this); + button->setProperty(propertyName.toUtf8().constData(), i); + button->setFixedSize(110, 35); + if (propertyName == "frontBoardTest") { + connect(button, &QPushButton::clicked, this, &MainWidget::onSendFrontItemClicked); + } + else if (propertyName == "backBoardTest") { + connect(button, &QPushButton::clicked, this, &MainWidget::onSendBackItemClicked); + } + + int row = i / buttonsPerRow; + int col = i % buttonsPerRow; + buttonGridLayout->addWidget(button, row, col, Qt::AlignLeft); + + itemButtons.append(button); + } + + QWidget* buttonContainer = new QWidget; + buttonContainer->setLayout(buttonGridLayout); + + QScrollArea* scrollArea = new QScrollArea; + scrollArea->setWidget(buttonContainer); + scrollArea->setWidgetResizable(true); + + functionTestLayout->addWidget(scrollArea); + + return functionTestTab; +} + +QWidget* MainWidget::createFunctionConfigTab(const QJsonArray& BoardFuncConfig, const QString& propertyName) +{ + QWidget* functionConfigTab = new QWidget(this); + QVBoxLayout* functionConfigLayout = new QVBoxLayout(functionConfigTab); + if (propertyName == "frontBoardFuncConfig") { + frontFuncConfigLineEdit->setPlaceholderText("请输入配置参数..."); + functionConfigLayout->addWidget(frontFuncConfigLineEdit); + } + else if (propertyName == "backBoardFuncConfig") { + backFuncConfigLineEdit->setPlaceholderText("请输入配置参数..."); + functionConfigLayout->addWidget(backFuncConfigLineEdit); + } + + QGridLayout* configButtonGridLayout = new QGridLayout(); + int buttonsPerRow = 7; // 每行显示的按键数量,根据需要调整 + for (int i = 0; i < BoardFuncConfig.size() + (77 - BoardFuncConfig.size()); ++i) { + QJsonObject item = BoardFuncConfig[i].toObject(); + QString buttonText = item["lable"].toString(); + if (buttonText.isEmpty()) { + buttonText = QString("Cfg Item %1").arg(i + 1); + } + QPushButton* button = new QPushButton(buttonText, this); + button->setProperty(propertyName.toUtf8().constData(), i); + button->setFixedSize(110, 35); + if (propertyName == "frontBoardFuncConfig") { + connect(button, &QPushButton::clicked, this, &MainWidget::onSendFrontFuncItemClicked); + } + else if (propertyName == "backBoardFuncConfig") { + connect(button, &QPushButton::clicked, this, &MainWidget::onSendBackFuncItemClicked); + } + + int row = i / buttonsPerRow; + int col = i % buttonsPerRow; + configButtonGridLayout->addWidget(button, row, col, Qt::AlignLeft); + + funcItemButtons.append(button); + } + + QWidget* configButtonContainer = new QWidget; + configButtonContainer->setLayout(configButtonGridLayout); + + QScrollArea* configScrollArea = new QScrollArea; + configScrollArea->setWidget(configButtonContainer); + configScrollArea->setWidgetResizable(true); + + functionConfigLayout->addWidget(configScrollArea); + + return functionConfigTab; +} + + +QWidget* MainWidget::createImageDisplayTab() +{ + QWidget* imageDisplayTab = new QWidget(this); + QVBoxLayout* imageDisplayLayout = new QVBoxLayout(imageDisplayTab); + + QVBoxLayout* imageButtonsColumnLayout = new QVBoxLayout; + for (int i = 0; i < 5; ++i) { + QHBoxLayout* imageButtonsRowLayout = new QHBoxLayout; + for (int j = 0; j < 2; ++j) { + QPushButton* button; + if (i == 0 && j == 0) { + button = new QPushButton(QString("IR"), this); + button->setFixedSize(73, 50); + imageButtonsRowLayout->addWidget(button); + button->setProperty("getPicIndex", i * 2 + j); + connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked); + getPicButtons.append(button); + continue; + } + else if (i == 0 && j == 1) { + button = new QPushButton(QString("RGB"), this); + button->setFixedSize(73, 50); + imageButtonsRowLayout->addWidget(button); + button->setProperty("getPicIndex", i * 2 + j); + connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked); + getPicButtons.append(button); + continue; + } + + button = new QPushButton(QString("Device %1").arg(i * 2 + j - 1), this); + button->setFixedSize(73, 50); + imageButtonsRowLayout->addWidget(button); + button->setProperty("getPicIndex", i * 2 + j); + connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked); + getPicButtons.append(button); + } + imageButtonsColumnLayout->addLayout(imageButtonsRowLayout); + } + + QHBoxLayout* lensesLayout = new QHBoxLayout; + leftLens_imageLabel = new QLabel(this); + rightLens_imageLabel = new QLabel(this); + lensesLayout->addWidget(leftLens_imageLabel); + lensesLayout->addWidget(rightLens_imageLabel); + + QHBoxLayout* imageAndButtonsLayout = new QHBoxLayout; + imageAndButtonsLayout->addLayout(imageButtonsColumnLayout, 1); + imageAndButtonsLayout->addLayout(lensesLayout, 4); + imageDisplayLayout->addLayout(imageAndButtonsLayout); + + return imageDisplayTab; +} + +QWidget* MainWidget::createVideoDisplayTab() +{ + QWidget* videoDisplayTab = new QWidget(this); + QVBoxLayout* videoDisplayLayout = new QVBoxLayout(videoDisplayTab); + + QVBoxLayout* videoButtonsColumnLayout = new QVBoxLayout; + for (int i = 0; i < 6; ++i) { + QHBoxLayout* videoButtonsRowLayout = new QHBoxLayout; + for (int j = 0; j < 2; ++j) { + QPushButton* button; + if (i == 0 && j == 0) { + button = new QPushButton(QString("IR"), this); + button->setFixedSize(73, 50); + videoButtonsRowLayout->addWidget(button); + button->setProperty("getVideoIndex", i * 2 + j); + connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked); + getVideoButtons.append(button); + continue; + } + else if (i == 0 && j == 1) { + button = new QPushButton(QString("RGB"), this); + button->setFixedSize(73, 50); + videoButtonsRowLayout->addWidget(button); + button->setProperty("getVideoIndex", i * 2 + j); + connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked); + getVideoButtons.append(button); + continue; + } + + // 调价调焦窗口按键 + if (i == 1 && j == 0) { + button = new QPushButton(QString("大窗口播放视频"), this); + button->setFixedSize(150, 50); + button->setEnabled(false); + videoButtonsRowLayout->addWidget(button); + button->setProperty("getVideoIndex", i * 2 + j); + connect(button, &QPushButton::clicked, this, &MainWidget::onOpenFocusWindowClicked); + getVideoButtons.append(button); + break; // 跳出内层循环,只添加一个按键 + } + + button = new QPushButton(QString("Device %1").arg(i * 2 + j - 3), this); + button->setFixedSize(73, 50); + videoButtonsRowLayout->addWidget(button); + button->setProperty("getVideoIndex", i * 2 + j + 1); + connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked); + getVideoButtons.append(button); + } + videoButtonsColumnLayout->addLayout(videoButtonsRowLayout); + } + + QHBoxLayout* videoAndButtonsLayout = new QHBoxLayout; + videoLabel = new QLabel(this); + videoAndButtonsLayout->addLayout(videoButtonsColumnLayout, 1); + videoAndButtonsLayout->addWidget(videoLabel, 6); + videoDisplayLayout->addLayout(videoAndButtonsLayout); + + return videoDisplayTab; +} + + diff --git a/FactoryTestTool/SourceCode/main.cpp b/FactoryTestTool/SourceCode/main.cpp index 7e85b84..8650b00 100644 --- a/FactoryTestTool/SourceCode/main.cpp +++ b/FactoryTestTool/SourceCode/main.cpp @@ -4,7 +4,24 @@ #include #include +//通过设置项目的子系统来避免生成控制台窗口。这种方法根本不会创建控制台窗口: +// +//右键点击你的项目,选择“属性”。 +//在“配置属性”下,展开“链接器”,然后选择“系统”。 +//将“子系统”设置为“Windows(/ SUBSYSTEM)”而不是“控制台(/ SUBSYSTEM)”。 +//这种方法不需要任何额外的代码,且最为简洁。如果你已经在代码中使用了WinMain而不是main函数,这个设置就是默认的。 +// +//通过这些方法,你应该可以彻底隐藏或者关闭控制台窗口。 + +// 关闭控制台窗口的函数 +void closeConsole() { + HWND hwnd = GetConsoleWindow(); + ShowWindow(hwnd, SW_HIDE); +} + int main(int argc, char* argv[]) { + //closeConsole(); // 调用函数关闭控制台窗口 + //FreeConsole(); // 关闭控制台窗口 QApplication app(argc, argv); QIcon appIcon("./app_icon.ico"); diff --git a/FactoryTestTool/add1.h264 b/FactoryTestTool/add1.h264 index a483bcf..7774d65 100644 Binary files a/FactoryTestTool/add1.h264 and b/FactoryTestTool/add1.h264 differ diff --git a/enc_temp_folder/607132b251dbd6363a3d2dcafd72eaa6/MainWidget.h b/enc_temp_folder/607132b251dbd6363a3d2dcafd72eaa6/MainWidget.h new file mode 100644 index 0000000..3a4eb8e --- /dev/null +++ b/enc_temp_folder/607132b251dbd6363a3d2dcafd72eaa6/MainWidget.h @@ -0,0 +1,231 @@ +// MainWidget.h +#pragma once +#ifndef MAINWIDGET_H +#define MAINWIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../Json/readJsonFile.h" +#include "../RecvDataHandler/RecvDataHandler.h" +#include "../LicenseGenerate/LicenseGenerate.h" +#include "../LicenseGenerate/LicenseConfirmWindow.h" +#include "../Network/mdns/servicemodel.h" +#include "../Network/ClientHandler.h" +#include "../Network/httpClient.h" +#include "FocusWindow.h" + +// 用于测试 UDP 组播实现 mdns 功能 非标准 mdns +#define TEST_UDP_BROADCAST 0 + +#define TCP_CONNECT_PORT 12412 + +class MainWidget : public QWidget +{ + Q_OBJECT + +public: + // 构造函数 + explicit MainWidget(QWidget* parent = nullptr); + ~MainWidget(); + +private slots: + // 发送HTTP请求 + //void onSomeButtonClicked(); + // 处理HTTP响应 + void onHttpRequestFinished(const QJsonObject& response); + // 处理HTTP错误 + void onHttpRequestError(const QString& errorString); + // 处理开始服务器按钮点击事件 + void onStartServerClicked(); + // 处理发送获取设备信息按键点击事件 + void onSendGetDevInfoClicked(); + // 处理发送取图按键点击事件 + void onSendGetPicClicked(); + // 处理发送拉视频流按键点击事件 + void onSendGetVideoClicked(); + void onLicenseButtonClicked(); + void onUuidButtonClicked(); + // 处理一键发送按钮点击事件 + void onSendAllClicked(); + // 处理单独发送项按钮点击事件 + void onSendFrontItemClicked(); + void onSendBackItemClicked(); + // 处理单独发送功能配置项按钮点击事件 + void onSendFrontFuncItemClicked(); + void onSendBackFuncItemClicked(); + // 处理数据接收信号 + //void onDataReceived(const QString& client, const QByteArray& data); + // 处理状态更新信号 + void onStatusUpdated(const QString& client, int itemIndex, int funcItemIndex, + bool success, const QString& itemData, const QString& funcItemData); + // 处理所有项目处理完毕信号 + void onAllItemsProcessed(const QString& client, int itemsProcessedCount); + // 处理客户端断开连接 + void onClientDisconnected(ClientHandler* handler); + // 启动超时定时器 + void onStartTimeout(int clientId, int timeout); + // 为了使滚动条在最下面,不用手动鼠标下拉 + void scrollToBottom(); + // 处理点击 Save Log 按键 + void onSelectFileButtonClicked(); + // 处理点击 Clear Log 按键 + void onclearLogButtonClicked(); + // 处理复选框的状态 + void onSaveCheckBoxStateChanged(int state); + // 处理打开调焦的大窗口 + void onOpenFocusWindowClicked(); + void printThreadPoolInfo(); + void onCheckThreadStatus(); + void onCheckConnectionStatus(); + void startClientReadTimer(int clientId); + void stopClientReadTimer(int clientId); +#if TEST_UDP_BROADCAST + void sendMulticastMessage(); +#endif + +private: + // 读取 test JSON 配置文件 + void readJsonConfig(); + // 设置 UI + void setupUI(); + QGroupBox* createLicenseGroupBox(); + QGroupBox* createFrontDeviceInfoGroupBox(); + QGroupBox* createBackDeviceInfoGroupBox(); + QWidget* createFunctionTestTab(const QJsonArray& BoardFuncTest, const QString& propertyName); + QWidget* createFunctionConfigTab(const QJsonArray& BoardFuncConfig, const QString& propertyName); + QWidget* createImageDisplayTab(); + QWidget* createVideoDisplayTab(); + QGroupBox* createBackConnectServerGroupBox(); + // 保存日志到文件 + void saveStatusListToFile(const QString& filePath); + // 用于更新按键文本的函数 + void updateServerButtonText(); + void onDisconnectClient(int clientId); + void setupTimerForThreadPoolInfo(); + void sendDataToClient(int clientId, const QByteArray& data); + //void FactoryToolSendPostFactoryInfotoHttpServer(); + void FactoryToolSendPostTestToHttpServer(); + void FactoryToolSendPostLicenseToHttpServer(const QString& hardware_info, const QString& license_info); + void FactoryToolSendPostComfirmToHttpServer(); + void FactoryToolSendGetUuidToHttpServer(); + void FactoryToolSendGetLicenseToHttpServer(const QString& hw_info); + + QTcpServer* server; // TCP 服务器 + HttpClient* httpClient; // HTTP 服务器 + QJsonArray frontBoardOneClickTest; // 前板一键功能测试 JSON + QJsonArray frontBoardTest; // 前板单项测试 JSON + QJsonArray frontBoardFuncConfig; // 前板功能配置参数 JSON + QJsonArray frontBoardDevInfoJson; // 前板设备信息参数 JSON + QJsonArray frontBoardLicenseJson; // 前板License JSON + QJsonArray backBoardOneClickTest; // 后板一键功能测试 JSON + QJsonArray backBoardTest; // 后板单项测试 JSON + QJsonArray backBoardFuncConfig; // 后板功能配置参数 JSON + QJsonArray backBoardDevInfoJson; // 后板设备信息参数 JSON + QJsonArray backBoardUuidJson; // 后板UUID JSON + QJsonArray testJsonConfig; // 功能测试区 JSON 配置 + QJsonArray funcJsonConfig; // 功能配置区 JSON 配置 + QJsonArray getDevInfoJson; // 获取设备信息 JSON 配置 + QJsonArray getPicJson; // 发送取图指令 JSON 配置 + QJsonArray getVideoJson; // 发送拉视频指令 JSON 配置 + QVBoxLayout* mainLayout; // 主布局 + QListWidget* statusListWidget; // 状态列表 + QPushButton* startServerButton; // 开始服务器按键 + QPushButton* focusWindowsButton; // 调焦窗口按键 + QPushButton* sendAllButton; // 一键发送按键 + QThreadPool threadPool; // 线程池 + QMutex mutex; // 互斥锁 + int nextClientId; // 新增的客户端编号 + int connectedClientsCount = 0; // 连接客户端的数量 + int isRequestSuccessful = 0; // GET请求是否成功 + bool manualSend; // 判断是否是手动触发的发送 + bool deviceConnected = false; // 判断是否有设备连接过 + bool isSendingAll; // 一键功能测试 状态 + + QJsonObject licenseDataArray; // 用于保存从服务器获取的 data 字段对象 + + QVector itemButtons; // 项目按键集合 + QVector funcItemButtons; // 功能配置项目按键集合 + QVector getPicButtons; // 保存两个取图的摄像头的按键的指针 + QVector getVideoButtons; // 保存拉视频设备的按键的指针 + QList clients; // 客户端处理器集合 + QMap clientTimers; // 每个客户端的定时器 + QMap devInfoLineEdits;// msg_id 和对应的 QLineEdit 的映射关系 + + QCheckBox* saveCheckBox; // 保存文件复选框 + QPushButton* selectFileButton; // Save Log 按键 + QPushButton* clearLogButton; // clear Log 按键 + QLineEdit* filePathLineEdit; // 文件路径显示 + QLabel* leftLens_imageLabel; // 左边镜头图像显示 + QLabel* rightLens_imageLabel; // 右边镜头图像显示 + QLabel* videoLabel; // 视频显示 + QLineEdit* frontFuncConfigLineEdit; // 前板功能配置编辑框 + QLineEdit* backFuncConfigLineEdit; // 后板功能配置编辑框 + QTextEdit* licenseHwInfoEdit; // 获取license的硬件信息 + QTextEdit* UuidHwInfoEdit; // Uuid的硬件信息 + MainWidget* mainWidget; + QTabWidget* tabWidget; // 标签页 + QWidget* functionTestArea; // 功能测试区 + QWidget* functionConfigArea; // 功能配置区 + + int lastClickedGetPicCamIndex; // 记录上一次点击取图的摄像头的按键索引 + int lastClickedGetPicDevIndex; // 记录上一次点击取图的设备的按键索引 + int lastClickedGetVideoCamIndex; // 记录上一次点击拉视频的摄像头的按键索引 + int lastClickedGetVideoDevIndex; // 记录上一次点击拉视频的设备的按键索引 + + + QTimer* threadStatusTimer; // 检查线程状态的定时器 + QTimer* connectionStatusCheckTimer; // 检查连接状态的定时器 + QMap clientThreads; + QMap clientReadTimers; + QMap clients_1; + + ServiceProvider* mServiceProvider; + QTimer* mdnsTimer; + void startMdnsService(); + void stopMdnsService(); +#if TEST_UDP_BROADCAST + QUdpSocket* multicastSocket; + QTimer* multicastTimer; +#endif +}; + +#endif // MAINWIDGET_H diff --git a/enc_temp_folder/a6281ae8e18e4bb4212986158077fa/MainWidget.cpp b/enc_temp_folder/a6281ae8e18e4bb4212986158077fa/MainWidget.cpp new file mode 100644 index 0000000..b60f6f8 --- /dev/null +++ b/enc_temp_folder/a6281ae8e18e4bb4212986158077fa/MainWidget.cpp @@ -0,0 +1,1383 @@ + // MainWidget.cpp +#include "MainWidget.h" + + +void onThreadFinished(QThread* thread, ClientHandler* handler) +{ + qDebug() << "Thread finished. Deleting handler and thread."; + handler->deleteLater(); + thread->deleteLater(); +} + +// 初始化 UI 组件和服务器 +MainWidget::MainWidget(QWidget* parent) : + QWidget(parent), + nextClientId(1), + manualSend(false), + isSendingAll(false), + lastClickedGetPicCamIndex(-1), + lastClickedGetPicDevIndex(-1), + lastClickedGetVideoCamIndex(-1), + lastClickedGetVideoDevIndex(-1), + mServiceProvider(new ServiceProvider(this)), + mdnsTimer(new QTimer(this)), + httpClient(new HttpClient(this)) +#if TEST_UDP_BROADCAST + ,multicastSocket(new QUdpSocket(this)), + multicastTimer(new QTimer(this)) +#endif +{ + leftLens_imageLabel = new QLabel(this); + rightLens_imageLabel = new QLabel(this); + videoLabel = new QLabel(this); + frontFuncConfigLineEdit = new QLineEdit(this); + backFuncConfigLineEdit = new QLineEdit(this); + licenseHwInfoEdit = new QTextEdit(this); + UuidHwInfoEdit = new QTextEdit(this); + + setupUI(); + // 打印线程池状态信息 + setupTimerForThreadPoolInfo(); + server = new QTcpServer(this); + + //FactoryToolSendGetUuidToHttpServer(); + //FactoryToolSendGetLicenseToHttpServer(); + //FactoryToolSendPostComfirmToHttpServer(); + //FactoryToolSendPostTestToHttpServer(); + //FactoryToolSendPostLicenseToHttpServer(); + + connect(server, &QTcpServer::newConnection, this, [this]() { + // 检查是否有挂起的连接 + while (server->hasPendingConnections()) { + QTcpSocket* socket = server->nextPendingConnection(); + int clientId = nextClientId++; + qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; + qDebug() << "> A client is connected. ID:" << clientId; + qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; + + stopMdnsService(); + connectedClientsCount++; + updateServerButtonText(); + + QTimer* timer = new QTimer(this); + timer->setSingleShot(true); + clientTimers[clientId] = timer; + + // 连接定时器超时信号到槽函数 + connect(timer, &QTimer::timeout, this, [this, clientId]() { + //qDebug() << "Timeout occurred for client ID:" << clientId; + for (ClientHandler* handler : clients) { + if (handler->getClientId() == clientId) { + bool invoked = QMetaObject::invokeMethod(handler, "onTimeout", Qt::DirectConnection); + if (!invoked) { + qWarning() << "Failed to invoke onTimeout for client ID:" << clientId; + } + } + } + }); + + QThread* thread = new QThread(this); + ClientHandler* handler = new ClientHandler(socket, frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig, + frontBoardDevInfoJson, frontBoardLicenseJson, + backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson, + getPicJson, getVideoJson, clientId, nullptr); + + // 将 ClientHandler 移动到线程池中的线程 + handler->moveToThread(thread); + + // 当线程结束时删除 handler + connect(thread, &QThread::finished, this, [=]() { + onThreadFinished(thread, handler); + }); + + // 将sendData信号连接到主线程中的槽上 + connect(handler, &ClientHandler::sendData, this, [socket](const QByteArray& data) { + /*socket->write(data); + socket->flush();*/ + //qDebug() << "---------------------data.size():" << data.size(); + QByteArray prefix; + QDataStream stream(&prefix, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << quint32(0x55AA55AA); + stream << quint16(0x0420); + stream << quint32(data.size()); + prefix.append(data); + + qDebug() << "Sending data:" << prefix.toHex(); + + socket->write(prefix); + socket->flush(); + }); + + connect(handler, &ClientHandler::startTimeout, this, [this, clientId](int timeout) { + this->onStartTimeout(clientId, timeout); + }); + + // 启动新的线程 + thread->start(); + + clients.append(handler); + clients_1[clientId] = handler; + clientThreads[clientId] = thread; + connect(handler, &ClientHandler::statusUpdated, this, &MainWidget::onStatusUpdated); + connect(handler, &ClientHandler::clientDisconnected, this, &MainWidget::onClientDisconnected); + connect(handler, &ClientHandler::allItemsProcessed, this, &MainWidget::onAllItemsProcessed); + connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient); + + // 创建 DataHandler 对象并连接信号 + DataHandler* dataHandler = new DataHandler(leftLens_imageLabel, rightLens_imageLabel, videoLabel, licenseHwInfoEdit, &devInfoLineEdits, this); + connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData); + connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated); + + connect(handler, &ClientHandler::startReadTimer, this, &MainWidget::startClientReadTimer); + connect(handler, &ClientHandler::stopReadTimer, this, &MainWidget::stopClientReadTimer); + + // 创建和管理定时器 + QTimer* readTimer = new QTimer(this); + connect(readTimer, &QTimer::timeout, handler, &ClientHandler::onTimeoutRead); + // readTimer->start(10); // 每 10ms 触发一次 + // 将定时器存储到哈希表中,方便管理 + clientReadTimers[clientId] = readTimer; + + connect(handler, &ClientHandler::sendDataToSomeClient, this, &MainWidget::sendDataToClient); + } + }); + + connect(httpClient, &HttpClient::requestFinished, this, &MainWidget::onHttpRequestFinished); + connect(httpClient, &HttpClient::requestError, this, &MainWidget::onHttpRequestError); + + threadStatusTimer = new QTimer(this); + connect(threadStatusTimer, &QTimer::timeout, this, &MainWidget::onCheckThreadStatus); + //threadStatusTimer->start(100); // 每100ms检查一次线程状态 + + connectionStatusCheckTimer = new QTimer(this); + connect(connectionStatusCheckTimer, &QTimer::timeout, this, &MainWidget::onCheckConnectionStatus); + //connectionStatusCheckTimer->start(100); // 每100ms检查一次连接状态 + + connect(mdnsTimer, &QTimer::timeout, this, &MainWidget::startMdnsService); + +#if TEST_UDP_BROADCAST + // 设置组播地址 + QHostAddress groupAddress("224.0.0.251"); + quint16 port = 5353; + + // 绑定UDP套接字 + if (!multicastSocket->bind(QHostAddress::AnyIPv4, port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) { + qWarning() << "Failed to bind multicast socket"; + } + + // 加入组播组 + bool joined = multicastSocket->joinMulticastGroup(groupAddress); + if (!joined) { + qWarning() << "Failed to join multicast group"; + } + + // 定期发送组播消息 + connect(multicastTimer, &QTimer::timeout, this, &MainWidget::sendMulticastMessage); + multicastTimer->start(1000); // 每秒发送一次组播消息 +#endif +} + +MainWidget::~MainWidget() +{ +#if TEST_UDP_BROADCAST + multicastTimer->stop(); + multicastSocket->leaveMulticastGroup(QHostAddress("224.0.0.251")); + multicastSocket->close(); +#endif + if (mdnsTimer->isActive()) { + mdnsTimer->stop(); + } + delete mdnsTimer; + stopMdnsService(); + for (auto timer : clientReadTimers) { + timer->stop(); + delete timer; + } + clientReadTimers.clear(); + for (ClientHandler* handler : clients) { + handler->deleteLater(); + } + server->close(); + + for (auto thread : clientThreads) { + thread->quit(); + thread->wait(); + delete thread; + } + clientThreads.clear(); + + for (auto handler : clients_1) { + handler->deleteLater(); + } + clients_1.clear(); + + for (auto timer : clientTimers) { + timer->stop(); + delete timer; + } + clientTimers.clear(); + + if (server->isListening()) { + server->close(); + } + qDebug() << "MainWidget destroyed"; +} + +// 服务器响应 +void MainWidget::onHttpRequestFinished(const QJsonObject& response) +{ + isRequestSuccessful = 0; + if (response.contains("msg") && response["msg"].toString() == "ok") { + if (response.contains("data") && response["data"].isObject()) { + licenseDataArray = response["data"].toObject(); + isRequestSuccessful = 1; + } + } + else + isRequestSuccessful = 2; +} + +void MainWidget::onHttpRequestError(const QString& errorString) +{ + qWarning() << "HTTP request failed:" << errorString; + isRequestSuccessful = 2; +} + +QString generateRandomRequestID() { + const QString possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~"; + int length = QRandomGenerator::global()->bounded(1, 33); // 生成长度在1到32之间 + QString randomString; + for (int i = 0; i < length; ++i) { + int index = QRandomGenerator::global()->bounded(possibleCharacters.size()); + randomString.append(possibleCharacters.at(index)); + } + qDebug() << "randomString request_id:" << randomString; + return randomString; +} + +QString HmacSha256ToBase64(const QString& data, const QString& secret) { + QByteArray keyBytes = secret.toUtf8(); + QByteArray dataBytes = data.toUtf8(); + + // 使用 HMAC-SHA256 计算哈希值 + QByteArray hash = QMessageAuthenticationCode::hash(dataBytes, keyBytes, QCryptographicHash::Sha256); + qDebug() << "secret:" << secret; + qDebug() << "hash (hex):" << hash.toHex(); + qDebug() << "hash.toBase64():" << hash.toHex().toBase64(); + // 将哈希值编码为 Base64 字符串 + return hash.toHex().toBase64(); +} + +// 计算签名 +QString calculateSignature(const QMap& params, const QString& httpMethod, const QString& secret, const QString& request_id, const QString& timestamp) { + // 1. 按字典序排序参数 + QList> sortedParams; + for (auto it = params.begin(); it != params.end(); ++it) { + qDebug() << it.key() << ":" << it.value(); + sortedParams.append(qMakePair(it.key(), it.value())); + } + std::sort(sortedParams.begin(), sortedParams.end()); + qDebug() << "Sorted Params:"; + for (const auto& param : sortedParams) { + qDebug() << param.first << ":" << param.second; + } + + // 2. URL 编码参数 + QString canonicalizedQueryString; + for (auto& param : sortedParams) { + if (!canonicalizedQueryString.isEmpty()) { + canonicalizedQueryString += "&"; + } + canonicalizedQueryString += QUrl::toPercentEncoding(param.first) + "=" + QUrl::toPercentEncoding(param.second); + } + qDebug() << "URL Canonicalized Query String:" << canonicalizedQueryString; + + // 3. 构造 BaseString + //QString baseString = params["batch"] + params["label"] + params["model"] + params["request_id"] + params["timestamp"] + params["factory_id"]; + QString baseString = "240830SL100LabelSL100" + request_id + timestamp + "TEST"; + qDebug() << "baseString:" << baseString; + + // 4. 构造 stringToSign + QString stringToSign = httpMethod + "&" + baseString + "&" + canonicalizedQueryString.replace("+", "%20"); + qDebug() << "stringToSign:" << stringToSign; + // 5. 计算签名 + return HmacSha256ToBase64(stringToSign, secret); +} + +// 请求头 +void prepareRequestHeaders(QNetworkRequest& request, const QString& sign, const QString& request_id) { + request.setRawHeader("factory_id", "TEST"); + request.setRawHeader("label", "SL100Label"); + request.setRawHeader("batch", QString::number(240830).toUtf8()); + request.setRawHeader("model", "SL100"); + request.setRawHeader("timestamp", QString::number(QDateTime::currentSecsSinceEpoch()).toUtf8()); + request.setRawHeader("request_id", request_id.toUtf8()); + request.setRawHeader("sign", sign.toUtf8()); + request.setRawHeader("Content-Type", "application/json"); +} + +// GET 请求 +void sendGetRequest(HttpClient* httpClient, const QUrl& url, const QMap& params, const QString& secret) { + QString request_id = generateRandomRequestID(); + qDebug() << "request_id:" << request_id; + QUrl modifiedUrl = url; + QUrlQuery query; + for (auto it = params.begin(); it != params.end(); ++it) { + query.addQueryItem(it.key(), it.value()); + } + modifiedUrl.setQuery(query.query()); + QString sign = calculateSignature(params, "GET", secret, request_id, QString::number(QDateTime::currentSecsSinceEpoch())); + qDebug() << "sendGetRequest URL:" << modifiedUrl.toString(); + QNetworkRequest request(modifiedUrl); + prepareRequestHeaders(request, sign, request_id); + //return; + httpClient->sendGetRequest(request); +} + +// POST 请求 +void sendPostRequest(HttpClient* httpClient, const QUrl& url, const QMap& params, const QJsonObject& jsonData, const QString& secret) { + QString request_id = generateRandomRequestID(); + qDebug() << "request_id:" << request_id; + QString sign = calculateSignature(params, "POST", secret, request_id, QString::number(QDateTime::currentSecsSinceEpoch())); + qDebug() << "sendPostRequest URL:" << url.toString(); + QNetworkRequest request(url); + prepareRequestHeaders(request, sign, request_id); + QByteArray jsonDataByteArray = QJsonDocument(jsonData).toJson(); + //return; + httpClient->sendPostRequest(request, jsonDataByteArray); +} + +// GET 获取 UUID +void MainWidget::FactoryToolSendGetUuidToHttpServer() { + QUrl url("http://admin.hassecurity.cn/v1/getUuid"); + QMap params = { + {"label", "TEST_SL100_20240826"}, + {"model", "SL100"}, + {"batch", "1"}, + {"mac", "2a:61:az:a1"} + }; + + QString secret = "rCeOzwisLFLasvlt"; + sendGetRequest(httpClient, url, params, secret); +} + +// GET 查询 License +void MainWidget::FactoryToolSendGetLicenseToHttpServer(const QString& hw_info) { + QUrl url("http://admin.hassecurity.cn/v1/getAlgorithmKey"); + QMap params = { + {"id", hw_info} + }; + + QString secret = "rCeOzwisLFLasvlt"; + sendGetRequest(httpClient, url, params, secret); +} + +// POST 确认烧录 +void MainWidget::FactoryToolSendPostComfirmToHttpServer() { + QUrl url("http://admin.hassecurity.cn/v1/confirm"); + QMap params = { + {"factory_id", "TEST"}, + {"label", "SL100Label"}, + {"batch", "240830"}, + {"model", "SL100"}, + {"timestamp", QString::number(QDateTime::currentSecsSinceEpoch())}, + {"request_id", generateRandomRequestID()} + }; + + QJsonObject jsonData = { + {"mac", "value4"}, + {"uuid", "value4"} + }; + + QString secret = "rCeOzwisLFLasvlt"; + sendPostRequest(httpClient, url, params, jsonData, secret); +} + +// POST 上报测试结果 +void MainWidget::FactoryToolSendPostTestToHttpServer() { + QUrl url("http://admin.hassecurity.cn/v1/testRecords"); + QMap params = { + {"id", "123456"}, + {"location", "allMachine"} + }; + //QString itemString = "function=faceVerify,result=false,msg=timeout"; + //QString itemString = "function=faceVerify,result=false,msg=timeout"; + QString itemString = "[{\"function\":\"faceVerify\",\"msg\":\"timeout\",\"result\":false}]"; + params["items"] = itemString; + + QJsonObject jsonItem = { + {"function", "faceVerify"}, + {"result", false}, + {"msg", "timeout"} + }; + QJsonArray itemsArray; + itemsArray.append(jsonItem); + + QJsonObject jsonData = { + {"id", "123456"}, + {"location", "allMachine"}, + {"items", itemsArray} + }; + + QString secret = "rCeOzwisLFLasvlt"; + sendPostRequest(httpClient, url, params, jsonData, secret); +} + +// POST 图语 License 上报 +void MainWidget::FactoryToolSendPostLicenseToHttpServer(const QString& hardware_info, const QString& license_info) { + QUrl url("http://admin.hassecurity.cn/v1/algorithmKey"); + QString UTC_time = QString::number(QDateTime::currentSecsSinceEpoch()); + QMap params = { + {"id", hardware_info}, + {"key", license_info}, + {"time", UTC_time}, + {"type", "TUYU"} + }; + + QJsonObject jsonData = { + {"id", hardware_info}, + {"key", license_info}, + {"time", UTC_time} + }; + + QString secret = "rCeOzwisLFLasvlt"; + sendPostRequest(httpClient, url, params, jsonData, secret); +} + +void MainWidget::startClientReadTimer(int clientId) { + qDebug() << "------ startClientReadTimer clientId:" << clientId; + if (clientReadTimers.contains(clientId)) { + clientReadTimers[clientId]->start(10); + } +} + +void MainWidget::stopClientReadTimer(int clientId) { + qDebug() << "------ stopClientReadTimer clientId:" << clientId; + if (clientReadTimers.contains(clientId)) { + clientReadTimers[clientId]->stop(); + } +} + +void MainWidget::onCheckConnectionStatus() +{ + int activeThreadCount = clients_1.size(); + //qDebug() << "------Number of active threads:" << activeThreadCount; + for (auto it = clients_1.begin(); it != clients_1.end(); ++it) { + int clientId = it.key(); + ClientHandler* handler = it.value(); + QTcpSocket* socket = handler->getSocket(); + if (socket->state() != QTcpSocket::ConnectedState) { + qCritical() << "--------------Connection lost for clientId:" << clientId << ". Socket state:" << socket->state(); + emit handler->clientDisconnected(handler); + } + else { + qDebug() << "Connection for clientId:" << clientId << "is active."; + } + } +} + +void MainWidget::onCheckThreadStatus() +{ + //qDebug() << "Checking thread status..."; + int activeThreadCount = clientThreads.size(); + //qDebug() << "Number of active threads:" << activeThreadCount; + for (auto it = clientThreads.begin(); it != clientThreads.end(); ++it) { + int clientId = it.key(); + QThread* thread = it.value(); + ClientHandler* handler = nullptr; + for (ClientHandler* h : clients) { + if (h->getClientId() == clientId) { + handler = h; + break; + } + } + if (handler && handler->isData_Stuck()) { + qDebug() << "Thread for clientId:" << clientId << "is stuck."; + // 处理线程卡住的情况,比如重启线程或记录更多日志 + } + else if (thread->isRunning()) { + qDebug() << "isData_Stuck = :" << handler->isData_Stuck(); + qDebug() << "Thread for clientId:" << clientId << "is running."; + } + else { + qDebug() << "Thread for clientId:" << clientId << "is not running."; + // 处理线程意外停止的情况 + } + } +} + +// 打印线程池信息 +void MainWidget::printThreadPoolInfo() +{ + QThreadPool* threadPool = QThreadPool::globalInstance(); + //qDebug() << "Active threads:" << threadPool->activeThreadCount(); + //qDebug() << "Max threads:" << threadPool->maxThreadCount(); +} + +void MainWidget::setupTimerForThreadPoolInfo() +{ + QTimer* timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &MainWidget::printThreadPoolInfo); + timer->start(5000); // 每5秒打印一次线程池信息 +} + +void MainWidget::readJsonConfig() +{ + frontBoardOneClickTest = readJson_frontBoardOneClickTest(); + frontBoardTest = readJson_frontBoardTest(); + frontBoardFuncConfig = readJson_frontBoardFuncConfig(); + frontBoardDevInfoJson = readJson_frontDevInfo(); + frontBoardLicenseJson = readJson_frontLicense(); + + backBoardOneClickTest = readJson_backBoardOneClickTest(); + backBoardTest = readJson_backBoardTest(); + backBoardFuncConfig = readJson_backBoardFuncConfig(); + backBoardDevInfoJson = readJson_backDevInfo(); + backBoardUuidJson = readJson_backUuid(); + + testJsonConfig = readJson_testConfig(); + funcJsonConfig = readJson_funcConfig(); + + getPicJson = readJson_getPic(); + getVideoJson = readJson_getVideo(); +} + +// 设置 UI +void MainWidget::setupUI() +{ + startServerButton = new QPushButton("开始监听\n(Start Listening...)", this); + startServerButton->setFixedSize(190, 70); + + sendAllButton = new QPushButton("一键功能测试", this); + sendAllButton->setFixedSize(190, 70); + sendAllButton->setEnabled(false); + + statusListWidget = new QListWidget(this); + statusListWidget->setMinimumSize(350, 840); + statusListWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + QHBoxLayout* buttonLayout = new QHBoxLayout; + buttonLayout->addWidget(startServerButton); + buttonLayout->addWidget(sendAllButton); + buttonLayout->addStretch(); + + QVBoxLayout* leftLayout = new QVBoxLayout; + leftLayout->addLayout(buttonLayout); + leftLayout->setStretch(0, 1); + leftLayout->addWidget(statusListWidget); + leftLayout->setStretch(1, 200); + + saveCheckBox = new QCheckBox("", this); + selectFileButton = new QPushButton("Save", this); + selectFileButton->setFixedSize(45, 28); + clearLogButton = new QPushButton("Clear", this); + clearLogButton->setFixedSize(55, 28); + filePathLineEdit = new QLineEdit(this); + filePathLineEdit->setFixedSize(250, 28); + filePathLineEdit->setReadOnly(true); + + QHBoxLayout* fileLayout = new QHBoxLayout; + fileLayout->addWidget(saveCheckBox); + fileLayout->addWidget(selectFileButton); + fileLayout->addWidget(filePathLineEdit); + fileLayout->addWidget(clearLogButton); + + leftLayout->addLayout(fileLayout); + leftLayout->setStretch(2, 1); + + // 读取 JSON 配置文件 + readJsonConfig(); + + /*QGroupBox* groupBox = createLicenseGroupBox(); + leftLayout->addWidget(groupBox); + leftLayout->setStretch(3, 1);*/ + + QWidget* leftContainer = new QWidget(this); + leftContainer->setLayout(leftLayout); + leftContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + // 前板 + QGroupBox* frontDeviceInfoGroupBox = createFrontDeviceInfoGroupBox(); + QGroupBox* frontLicenseGroupBox = createLicenseGroupBox(); + + QHBoxLayout* frontGroupBoxLayout = new QHBoxLayout; + frontGroupBoxLayout->addWidget(frontDeviceInfoGroupBox, 1); + frontGroupBoxLayout->addWidget(frontLicenseGroupBox, 1); + + QTabWidget* frontTabWidget = new QTabWidget(this); + frontTabWidget->setFixedSize(900, 315); + QWidget* frontFunctionTestTab = createFunctionTestTab(frontBoardTest, "frontBoardTest"); + QWidget* frontFunctionConfigTab = createFunctionConfigTab(frontBoardFuncConfig, "frontBoardFuncConfig"); + frontTabWidget->addTab(frontFunctionTestTab, "前板测试项"); + frontTabWidget->addTab(frontFunctionConfigTab, "前板配置项"); + + QTabWidget* mainTabWidget = new QTabWidget(this); + QWidget* frontDevAreaTab = new QWidget(this); + QVBoxLayout* frontDevLayout = new QVBoxLayout(frontDevAreaTab); + frontDevLayout->addLayout(frontGroupBoxLayout); + frontDevLayout->addWidget(frontTabWidget, 2, Qt::AlignTop | Qt::AlignLeft); + mainTabWidget->addTab(frontDevAreaTab, "前 板"); + + // 后板 + QGroupBox* backDeviceInfoGroupBox1 = createBackDeviceInfoGroupBox(); + QGroupBox* BackConnectServerGroupBox = createBackConnectServerGroupBox(); + + QHBoxLayout* backGroupBoxLayout = new QHBoxLayout; + backGroupBoxLayout->addWidget(backDeviceInfoGroupBox1, 1); + backGroupBoxLayout->addWidget(BackConnectServerGroupBox, 1); + + QTabWidget* backTabWidget = new QTabWidget(this); + backTabWidget->setFixedSize(900, 315); + QWidget* backFunctionTestTab = createFunctionTestTab(backBoardTest, "backBoardTest"); + QWidget* backFunctionConfigTab = createFunctionConfigTab(backBoardFuncConfig, "backBoardFuncConfig"); + backTabWidget->addTab(backFunctionTestTab, "后板测试项"); + backTabWidget->addTab(backFunctionConfigTab, "后板配置项"); + + QWidget* backDevAreaTab = new QWidget(this); + QVBoxLayout* backDevLayout = new QVBoxLayout(backDevAreaTab); + backDevLayout->addLayout(backGroupBoxLayout); + backDevLayout->addWidget(backTabWidget, 2, Qt::AlignTop | Qt::AlignLeft); + mainTabWidget->addTab(backDevAreaTab, "后 板"); + + // 整机 + QWidget* allDevAreaTab = new QWidget(this); + QVBoxLayout* allDevLayout = new QVBoxLayout(allDevAreaTab); + mainTabWidget->addTab(allDevAreaTab, "整 机"); + + QTabWidget* tabWidget_media = new QTabWidget(this); + QWidget* imageDisplayTab = createImageDisplayTab(); + QWidget* videoDisplayTab = createVideoDisplayTab(); + tabWidget_media->addTab(imageDisplayTab, "图像显示区"); + tabWidget_media->addTab(videoDisplayTab, "视频显示区"); + + QVBoxLayout* rightVerticalLayout = new QVBoxLayout; + rightVerticalLayout->addWidget(mainTabWidget, 5); + rightVerticalLayout->addWidget(tabWidget_media, 4); + + QHBoxLayout* mainLayout = new QHBoxLayout; + mainLayout->addWidget(leftContainer, 1, Qt::AlignTop | Qt::AlignLeft); + mainLayout->addLayout(rightVerticalLayout, 3); + + setLayout(mainLayout); + setWindowTitle("SL100 工厂产测工具 - V0.0.1"); + resize(1340, 1000); + + connect(startServerButton, &QPushButton::clicked, this, &MainWidget::onStartServerClicked); + connect(sendAllButton, &QPushButton::clicked, this, &MainWidget::onSendAllClicked); + connect(statusListWidget, &QListWidget::itemChanged, this, &MainWidget::scrollToBottom); + connect(selectFileButton, &QPushButton::clicked, this, &MainWidget::onSelectFileButtonClicked); + connect(clearLogButton, &QPushButton::clicked, this, &MainWidget::onclearLogButtonClicked); + connect(saveCheckBox, &QCheckBox::stateChanged, this, &MainWidget::onSaveCheckBoxStateChanged); +} + +void MainWidget::onSelectFileButtonClicked() +{ + QString filePath = QFileDialog::getSaveFileName(this, tr("选择文件路径"), "", tr("Text Files (*.txt);;All Files (*)")); + if (!filePath.isEmpty()) { + filePathLineEdit->setText(filePath); + } +} + +void MainWidget::onclearLogButtonClicked() +{ + statusListWidget->clear(); +} + +void MainWidget::onSaveCheckBoxStateChanged(int state) +{ + if (state == Qt::Checked) { + saveStatusListToFile(filePathLineEdit->text()); + } +} + +void MainWidget::saveStatusListToFile(const QString& filePath) +{ + if (filePath.isEmpty()) { + return; + } + + QFile file(filePath); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + + QTextStream out(&file); + for (int i = 0; i < statusListWidget->count(); ++i) { + QListWidgetItem* item = statusListWidget->item(i); + out << item->text() << "\n"; + } + file.close(); +} + +void MainWidget::onStartTimeout(int clientId, int timeout) +{ + //qDebug() << "---------------> onStartTimeout :" << clientId << "timeout :" << timeout; + if (clientTimers.contains(clientId)) { + QTimer* timer = clientTimers[clientId]; + if (timeout > 0) { + timer->start(timeout); + } + else { + timer->stop(); + } + } +} + +void MainWidget::scrollToBottom() +{ + statusListWidget->scrollToBottom(); +} + +void MainWidget::onDisconnectClient(int clientId) +{ + for (ClientHandler* handler : clients) { + if (handler->getClientId() == clientId) { + // 断开与该客户端的连接 + handler->getSocket()->disconnectFromHost(); + handler->getSocket()->waitForDisconnected(); + clients.removeOne(handler); + if (clientTimers.contains(clientId)) { + QTimer* timer = clientTimers[clientId]; + timer->stop(); + delete timer; + clientTimers.remove(clientId); + } + handler->deleteLater(); + connectedClientsCount--; + updateServerButtonText(); + + break; + } + } + + // 启动 mDNS 服务广播 + startMdnsService(); +} + +// 处理客户端断开连接信号 +void MainWidget::onClientDisconnected(ClientHandler* handler) +{ + int clientId = handler->getClientId(); + if (clientTimers.contains(clientId)) { + QTimer* timer = clientTimers[clientId]; + timer->stop(); + delete timer; + clientTimers.remove(clientId); + } + + clients.removeOne(handler); + /* + 将 ClientHandler 对象的删除操作放入事件队列中,等待事件循环处理。 + 在事件循环执行时,会安全地删除 ClientHandler 对象,这包括释放其占用的资源和内存 + */ + handler->deleteLater(); // 延迟删除 ClientHandler 对象 + + // 更新连接数并更新按键文本 + connectedClientsCount--; + if (nextClientId <= 2) nextClientId--; + deviceConnected = true; + updateServerButtonText(); +} + +// 更新按键文本的函数 +void MainWidget::updateServerButtonText() +{ + if (deviceConnected) { + deviceConnected = false; + startServerButton->setText(tr("正在监听(Listening)")); + if (connectedClientsCount == 0) startMdnsService(); + } + else if (connectedClientsCount == 0) { + startServerButton->setText(tr("开始监听\n(Start Listening...)")); + } + else { + startServerButton->setText(tr("正在监听(Listening)\n%1 台设备连接").arg(connectedClientsCount)); + } +} + +QString formatLicenseKey(const QString& licenseKey) { + QString formattedKey; + qDebug() << "licenseKey.length():" << licenseKey.length(); + for (int i = 0; i < licenseKey.length(); i += 2) { + QString byteStr = licenseKey.mid(i, 2); // 每次取两个字符 + formattedKey.append(QString("0x%1, ").arg(byteStr)); + } + if (!formattedKey.isEmpty()) { + formattedKey.chop(2); + } + + return formattedKey; +} + +void MainWidget::onLicenseButtonClicked() +{ + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + if (button) { + int index = button->property("licenseIndex").toInt(); + if (index >= 0 && index < frontBoardLicenseJson.size()) { + QJsonObject jsonObject = frontBoardLicenseJson[index].toObject(); + unsigned char hardware_info[PIX_HARDWARE_INFO_BYTES] = { 0 }; + unsigned char license_info[PIX_LICENCE_BYTES] = { 0 }; + QString dataStr = ""; + if (jsonObject["lable"].toString() == "get_license") { + QString hwInfoText = licenseHwInfoEdit->toPlainText(); + dataStr = hwInfoText.remove(","); // 去掉所有的逗号 + QString sendToHttpServerDataStr = dataStr.replace("0x", "").replace(" ", ""); // 去掉0x和空格 +#if 1 + qDebug() << "sendToHttpServerDataStr:" << sendToHttpServerDataStr; + FactoryToolSendGetLicenseToHttpServer(sendToHttpServerDataStr); + while (isRequestSuccessful == 0) { + QCoreApplication::processEvents(); // 防止阻塞UI线程 + } + qDebug() << "isRequestSuccessful:" << isRequestSuccessful; + if (isRequestSuccessful == 2) { + return; + } + else if(isRequestSuccessful == 1) { + if (licenseDataArray.contains("has") && licenseDataArray["has"].toBool()) { + qDebug() << "Found item with 'has' = true"; + if (licenseDataArray.contains("key")) { + QString licenseKey = licenseDataArray["key"].toString(); + licenseKey = formatLicenseKey(licenseKey); + licenseHwInfoEdit->setPlainText(licenseKey); + qDebug() << "HTTP Server License is:" << licenseKey; + return; + } + } + else if (licenseDataArray.contains("has")) { + qDebug() << "licenseDataArray[\"has\"].toBool():" << licenseDataArray["has"].toBool(); + } + } +#else + QString licenseKey = "128532C1D2A8"; + licenseKey = formatLicenseKey(licenseKey); + licenseHwInfoEdit->setPlainText(licenseKey); + qDebug() << "License Key set in licenseHwInfoEdit:" << licenseKey; + return; +#endif + QByteArray dataByteArray = QByteArray::fromHex(dataStr.toUtf8()); + memcpy(hardware_info, dataByteArray.data(), qMin(dataByteArray.size(), PIX_HARDWARE_INFO_BYTES)); + //unsigned char hardware_info[PIX_HARDWARE_INFO_BYTES] = { 0x46,0x0b,0x5d,0x11,0x58,0x17,0x4d,0x5e,0x55,0x5c,0x51,0x4a,0x5a,0x07,0x59,0x4c,0x5f,0x45,0x5b,0x5f,0x5a,0x45,0x1c,0x5a,0x45,0x43,0x44,0x47,0x51,0x5e,0x44,0x30 }; + LicenseConfirmWindow dialog("你确定要获取此授权吗?"); + if (dialog.exec() == QDialog::Accepted) { +#if 0 + licenseGenerate(hardware_info, license_info); + QString licenseInfoHex = QByteArray(reinterpret_cast(license_info), PIX_LICENCE_BYTES).toHex().toUpper(); +#else + unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0x07, 0xe8, 0xf3, 0x80, 0xa8, 0x07, 0x72, 0xa1, 0x17, 0xfe, 0xda, 0x67, 0xbd, 0x4a, 0x5a, 0xb5, 0xbb, 0x8b, 0x2d, 0xb2, 0xbf, 0x89, 0x74, 0xe5, 0xb0, 0x99, 0x70, 0x74, 0x3c, 0x6f, 0xf8, 0x82, 0x79, 0xab, 0x31, 0x9c, 0xdf, 0xe8, 0x9e, 0x75, 0x8f, 0x42, 0xb3, 0xcf, 0x00, 0x60, 0xa0, 0x38, 0xa4, 0xb8, 0xbe, 0xa6, 0x5d, 0x9f, 0x8b, 0x41, 0xf3, 0x0a, 0x69, 0xf6, 0x50, 0x94, 0x3f, 0xd0, 0xa5, 0xee, 0x88, 0x20, 0x93, 0x9a, 0x1c, 0xe9, 0x64, 0xd3, 0xaf, 0x9f, 0xc7, 0x66, 0x00, 0x7d, 0x7d, 0x68, 0xf1, 0xa4, 0xe1, 0x58, 0x00, 0x1d, 0x03, 0x0d, 0x40, 0x08, 0xa4, 0xcc, 0x0b, 0xd8, 0x19, 0x70, 0x9a, 0x83, 0x81, 0xbf, 0x27, 0x35, 0xb8, 0xec, 0x59, 0xa8, 0xd0, 0x03, 0xdb, 0xf6, 0xcf, 0x83, 0xaa, 0x0e, 0xfc, 0x95, 0x29, 0x77, 0xec, 0x89, 0xc5, 0x79, 0x10, 0x40, 0xd8, 0xbb }; + QString licenseInfoHex = QByteArray(reinterpret_cast(license_info_1), PIX_LICENCE_BYTES).toHex().toUpper(); +#endif + qDebug() << "上报服务器 licenseInfoHex:" << licenseInfoHex; + // License上报服务器 + FactoryToolSendPostLicenseToHttpServer(sendToHttpServerDataStr, licenseInfoHex); + QString licenseInfoStr; + printf("U盘 Get License is\n"); + for (int j = 0; j < PIX_LICENCE_BYTES; ++j) { + //printf("0x%02x, ", license_info[j]); + //licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info[j])); + printf("0x%02x, ", license_info_1[j]); + licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info_1[j])); + } + printf("\n"); + licenseHwInfoEdit->setPlainText(licenseInfoStr); + } + } + else { +#if 0 + if (jsonObject["lable"].toString() == "write_license") { + QString hwInfoText = licenseHwInfoEdit->toPlainText(); + dataStr = hwInfoText.remove(","); // 去掉所有的逗号 + QByteArray dataByteArray = QByteArray::fromHex(dataStr.toUtf8()); + memcpy(hardware_info, dataByteArray.data(), qMin(dataByteArray.size(), PIX_HARDWARE_INFO_BYTES)); + qDebug() << "hardware_info:" << QByteArray(reinterpret_cast(hardware_info), PIX_HARDWARE_INFO_BYTES).toHex(); + licenseGenerate(hardware_info, license_info); + QString licenseInfoStr; + printf("License is\n"); + for (int j = 0; j < PIX_LICENCE_BYTES; ++j) { + printf("0x%02x, ", license_info[j]); + licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info[j])); + } + printf("\n"); + licenseHwInfoEdit->setPlainText(licenseInfoStr); + dataStr = QByteArray(reinterpret_cast(license_info), PIX_LICENCE_BYTES).toHex(); + qDebug() << "license_info:" << dataStr; + } +#else + if (jsonObject["lable"].toString() == "write_license") { + QString licenseInfoText = licenseHwInfoEdit->toPlainText(); + qDebug() << "licenseInfoText:" << licenseInfoText; + dataStr = licenseInfoText.remove(","); // 去掉所有的逗号 + dataStr = dataStr.replace("0x", "").replace(" ", ""); // 去掉0x和空格 + QByteArray dataByteArray = QByteArray::fromHex(dataStr.toUtf8()); + memcpy(license_info, dataByteArray.data(), qMin(dataByteArray.size(), PIX_LICENCE_BYTES)); + //qDebug() << "hardware_info:" << QByteArray(reinterpret_cast(hardware_info), PIX_HARDWARE_INFO_BYTES).toHex(); + //licenseGenerate(hardware_info, license_info); + QString licenseInfoStr; + for (int j = 0; j < PIX_LICENCE_BYTES; ++j) { + licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info[j])); + } + //printf("\n"); + dataStr = QByteArray(reinterpret_cast(license_info), PIX_LICENCE_BYTES).toHex(); + qDebug() << "license_info:" << dataStr; + } +#endif + for (ClientHandler* handler : clients) { + handler->sendLicenseItem(index, dataStr); + } + } + } + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +//void MainWidget::onLicenseButtonClicked() +//{ +// if (connectedClientsCount) { +// QPushButton* button = qobject_cast(sender()); +// if (button) { +// int index = button->property("licenseIndex").toInt(); +// if (index >= 0 && index < frontBoardLicenseJson.size()) { +// QJsonObject jsonObject = frontBoardLicenseJson[index].toObject(); +// //QString jsonString = QJsonDocument(jsonObject).toJson(QJsonDocument::Compact); +// //qDebug() << "license Button clicked, sending JSON:" << jsonString; +// unsigned char license_info[PIX_LICENCE_BYTES] = { 0 }; +// if (jsonObject["lable"].toString() == "get_license") { +// LicenseConfirmWindow dialog("你确定要获取此授权吗?"); +// if (dialog.exec() == QDialog::Accepted) +// licenseGenerate(license_info, license_info); +// } +// else { +// if (jsonObject["lable"].toString() == "write_license") { +// LicenseConfirmWindow dialog("你确定要发送此授权吗?"); +// if (dialog.exec() == QDialog::Accepted) +// licenseGenerate(license_info, license_info); +// } +// for (ClientHandler* handler : clients) { +// handler->sendLicenseItem(index); +// } +// } +// } +// } +// } +// else { +// QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); +// listItem->setBackground(Qt::red); +// } +//} + +void MainWidget::onUuidButtonClicked() +{ + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + if (button) { + int index = button->property("UuidIndex").toInt(); + if (index >= 0 && index < backBoardUuidJson.size()) { + QJsonObject jsonObject = backBoardUuidJson[index].toObject(); + //QString jsonString = QJsonDocument(jsonObject).toJson(QJsonDocument::Compact); + //qDebug() << "license Button clicked, sending JSON:" << jsonString; + unsigned char license_info[PIX_LICENCE_BYTES] = { 0 }; + if (jsonObject["lable"].toString() == "get_license") { + + } + else { + if (jsonObject["lable"].toString() == "write_license") { + LicenseConfirmWindow dialog("你确定要发送此授权吗?"); + if (dialog.exec() == QDialog::Accepted) + licenseGenerate(license_info, license_info); + } + for (ClientHandler* handler : clients) { + handler->sendUuidItem(index, ""); + } + } + } + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +void MainWidget::startMdnsService() +{ + QDateTime currentTime = QDateTime::currentDateTime(); + QString formattedTime = currentTime.toString("yyyy-MM-dd hh:mm:ss.zzz"); + qDebug() << "[" << formattedTime << "]:" << "Start Mdns Broadcast Service"; + QString serviceName = "SL100 FactoryTool Mdns Broadcast Service"; + QString serviceType = "_SL100_FactoryTool-service._tcp"; + quint16 port = TCP_CONNECT_PORT; + mServiceProvider->startServiceBroadcast(serviceName, serviceType, port); + + if (!mdnsTimer->isActive()) { + mdnsTimer->start(1000); + } +} + +void MainWidget::stopMdnsService() +{ + if (mdnsTimer->isActive()) { + mdnsTimer->stop(); // 停止定时器 + } + mServiceProvider->stopServiceBroadcast(); +} + +#if TEST_UDP_BROADCAST +void MainWidget::sendMulticastMessage() +{ + QByteArray datagram = "--------------------------------- Test multicast message from MainWidget"; + QHostAddress groupAddress("224.0.0.251"); + quint16 port = 5353; + + qint64 sentBytes = multicastSocket->writeDatagram(datagram, groupAddress, port); + if (sentBytes == -1) { + qWarning() << "Failed to send multicast message:" << multicastSocket->errorString(); + } + else { + qDebug() << "Multicast message sentBytes:" << sentBytes; + qDebug() << "Multicast message sent:" << datagram; + } +} +#endif + +// 处理开始服务器按键点击事件 +void MainWidget::onStartServerClicked() +{ + if (!server->isListening()) { + startMdnsService(); +#if TEST_UDP_BROADCAST + sendMulticastMessage(); +#endif + // QHostAddress specifiedIpAddress("10.10.10.253"); + quint16 specifiedPort = TCP_CONNECT_PORT; + qDebug() << "" << specifiedPort; + if (server->listen(QHostAddress::Any, specifiedPort)) { + startServerButton->setText(tr("正在监听(Listening)")); + startServerButton->setStyleSheet("background-color: green;"); + sendAllButton->setEnabled(true); + } + else { + qDebug() << "Failed to start server. Error:" << server->errorString(); + } + } + else { + server->close(); + startServerButton->setText(tr("开始监听\n(Start Listening...)")); + startServerButton->setStyleSheet(""); + sendAllButton->setEnabled(false); + + stopMdnsService(); + } +} + +void MainWidget::sendDataToClient(int clientId, const QByteArray& data) +{ + if (clients_1.contains(clientId)) { + ClientHandler* handler = clients_1[clientId]; + handler->sendDataToClient(data); // 调用 ClientHandler 中的方法发送数据 + } + else { + qWarning() << "没有找到 ID 为" << clientId << "的客户端!"; + } +} + +// 处理发送获取设备信息按键点击事件 +void MainWidget::onSendGetDevInfoClicked() +{ + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + int itemIndex = button->property("deviceInfoIndex").toInt(); + if (itemIndex + 1 > connectedClientsCount) { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device %1 is connected !!!").arg(itemIndex + 1), statusListWidget); + listItem->setBackground(Qt::red); + } + else { + for (ClientHandler* handler : clients) { + handler->sendGetDevInfoItem(itemIndex); + } + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +// 处理发送取图按键点击事件 +void MainWidget::onSendGetPicClicked() +{ + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + int itemIndex = button->property("getPicIndex").toInt(); + + if (itemIndex < 2) { + button->setStyleSheet("background-color: green;"); + if (lastClickedGetPicCamIndex != -1 && lastClickedGetPicCamIndex != itemIndex) { + getPicButtons[lastClickedGetPicCamIndex]->setStyleSheet(""); + } + lastClickedGetPicCamIndex = itemIndex; + } + else { + if (lastClickedGetPicCamIndex == -1) { + QListWidgetItem* listItem = new QListWidgetItem(QString("Please select IR or RGB lens to get image!!!"), statusListWidget); + listItem->setBackground(Qt::red); + } + else { + if (itemIndex - 2 >= connectedClientsCount) { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device %1 is connected !!!").arg(itemIndex - 1), statusListWidget); + listItem->setBackground(Qt::red); + } + else { + button->setStyleSheet("background-color: green;"); + if (lastClickedGetPicDevIndex != -1 && lastClickedGetPicDevIndex != itemIndex) { + getPicButtons[lastClickedGetPicDevIndex]->setStyleSheet(""); + } + lastClickedGetPicDevIndex = itemIndex; + //QMutexLocker locker(&mutex); + for (ClientHandler* handler : clients) { + handler->sendGetPicItem(itemIndex - 2, lastClickedGetPicCamIndex); + } + } + } + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +// 处理发送拉视频流按键点击事件 +void MainWidget::onSendGetVideoClicked() +{ + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + int itemIndex = button->property("getVideoIndex").toInt(); + + if (itemIndex < 2) { + button->setStyleSheet("background-color: green;"); + if (lastClickedGetVideoCamIndex != -1 && lastClickedGetVideoCamIndex != itemIndex) { + getVideoButtons[lastClickedGetVideoCamIndex]->setStyleSheet(""); + } + lastClickedGetVideoCamIndex = itemIndex; + } + else { + if (lastClickedGetVideoCamIndex == -1) { + QListWidgetItem* listItem = new QListWidgetItem(QString("Please select IR or RGB lens to get video!!!"), statusListWidget); + listItem->setBackground(Qt::red); + } + else { + if (itemIndex - 6 >= connectedClientsCount) { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device %1 is connected !!!").arg(itemIndex - 4), statusListWidget); + listItem->setBackground(Qt::red); + } + else { + button->setStyleSheet("background-color: green;"); + if (lastClickedGetVideoDevIndex != -1 && lastClickedGetVideoDevIndex != itemIndex) { + getVideoButtons[lastClickedGetVideoDevIndex]->setStyleSheet(""); + } + lastClickedGetVideoDevIndex = itemIndex; + //QMutexLocker locker(&mutex); + for (ClientHandler* handler : clients) { + handler->sendGetVideoItem(itemIndex - 5, 1); + } + getVideoButtons[2]->setEnabled(true); + } + } + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +void MainWidget::onOpenFocusWindowClicked() +{ + QPushButton* button = qobject_cast(sender()); + if (button) { + int itemIndex = button->property("getVideoIndex").toInt(); + //qDebug() << "New Button clicked with itemIndex:" << itemIndex; + if (itemIndex == 2) { + // 创建并显示新窗口 + NewButtonDialog dialog(this); + dialog.exec(); + } + } +} + +// 处理一键发送按键点击事件 +void MainWidget::onSendAllClicked() +{ + if (connectedClientsCount) { + QMutexLocker locker(&mutex); + isSendingAll = !isSendingAll; + if (isSendingAll) { + sendAllButton->setText("一键功能测试中...\n再次点击取消"); + sendAllButton->setStyleSheet("background-color: green;"); + manualSend = true; + for (ClientHandler* handler : clients) { + // 重置索引 + handler->resetCurrentItemIndex(); + handler->sendNextItem(); + //handler->sendDevInfoItem(); + } + } + else { + sendAllButton->setText("一键功能测试"); + sendAllButton->setStyleSheet("background-color: white;"); + manualSend = false; + for (ClientHandler* handler : clients) { + handler->resetCurrentItemIndex(); + } + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +// 处理单独发送功能项按键点击事件 +void MainWidget::onSendFrontFuncItemClicked() +{ + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + int itemIndex = button->property("frontBoardFuncConfig").toInt(); + for (ClientHandler* handler : clients) { + QString text = frontFuncConfigLineEdit->text(); + qDebug() << "Text in frontFuncConfigLineEdit:" << text; + handler->sendFrontFuncItem(itemIndex, text); + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +void MainWidget::onSendBackFuncItemClicked() +{ + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + int itemIndex = button->property("backBoardFuncConfig").toInt(); + for (ClientHandler* handler : clients) { + QString text = backFuncConfigLineEdit->text(); + qDebug() << "Text in backFuncConfigLineEdit:" << text; + handler->sendBackFuncItem(itemIndex, text); + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +// 处理单独发送项按键点击事件 +void MainWidget::onSendFrontItemClicked() +{ + qDebug() << "onSendFrontItemClicked" ; + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + int itemIndex = button->property("frontBoardTest").toInt(); + for (ClientHandler* handler : clients) { + handler->sendFrontItem(itemIndex); + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +void MainWidget::onSendBackItemClicked() +{ + qDebug() << "onSendBackItemClicked"; + if (connectedClientsCount) { + QPushButton* button = qobject_cast(sender()); + int itemIndex = button->property("backBoardTest").toInt(); + for (ClientHandler* handler : clients) { + handler->sendBackItem(itemIndex); + } + } + else { + QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget); + listItem->setBackground(Qt::red); + } +} + +// 处理状态更新信号 +void MainWidget::onStatusUpdated(const QString& client, int itemIndex, int FuncItemIndex, + bool success, const QString& itemData, const QString& funcItemData) +{ + int clientId = -1; + // 遍历所有的 ClientHandler,找到匹配的 client + for (ClientHandler* handler : clients) { + if (handler->getClientAddress() == client) { + clientId = handler->getClientId(); + QString lable = handler->getCurrentItemLable(); + lable = handler->getCurrentFuncItemLable(); + break; + } + else + { + //qDebug() << "" << __FUNCTION__ << "handler->getClientAddress() != client" ; + } + } + //qDebug() << "itemIndex :" << itemIndex; + //qDebug() << "FuncItemIndex:" << FuncItemIndex; + if (itemIndex > 0) { + QListWidgetItem* listItem = new QListWidgetItem(QString("device ID: %1 - Item %2: %3 ---> %4") + .arg(clientId) + .arg(itemIndex) + .arg(itemData) // data 字段 + .arg(success ? "OK" : "NG"), statusListWidget); + + listItem->setBackground(success ? Qt::green : Qt::red); + statusListWidget->addItem(listItem); + } + else if (FuncItemIndex > 0) { + QListWidgetItem* listItem = new QListWidgetItem(QString("device ID: %1 - funcItem %2: %3 ---> %4") + .arg(clientId) + .arg(FuncItemIndex) + .arg(funcItemData) // data 字段 + .arg(success ? "OK" : "NG"), statusListWidget); + + listItem->setBackground(success ? Qt::green : Qt::red); + statusListWidget->addItem(listItem); + } + statusListWidget->scrollToBottom(); +} + +// json文件里面的配置项都测试结束 +void MainWidget::onAllItemsProcessed(const QString& client, int itemsProcessedCount) +{ + isSendingAll = false; + sendAllButton->setText("一键功能测试"); + sendAllButton->setStyleSheet("background-color: white;"); + //qDebug() << "onAllItemsProcessed called for client:" << client << "itemsProcessedCount:" << itemsProcessedCount; + int clientId = -1; + for (ClientHandler* handler : clients) { + if (handler->getClientAddress() == client) { + clientId = handler->getClientId(); + qDebug() << "Current clientId:" << clientId; + break; + } + else + { + //qDebug() << "" << __FUNCTION__ << "handler->getClientAddress() != client"; + } + } + + QListWidgetItem* listItem = new QListWidgetItem(QString("device ID:-%1 ---> All %2 items test completed !!!") + .arg(clientId) + .arg(itemsProcessedCount), statusListWidget); + statusListWidget->addItem(listItem); + statusListWidget->scrollToBottom(); +} +