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();
+}
+