SL100_FactoryTestTool/FactoryTestTool/SourceCode/Widget/MainWidget.cpp

2781 lines
137 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// MainWidget.cpp
#include "MainWidget.h"
#include <QMetaType>
//#include <qrencode.h>
void onThreadFinished(QThread* thread, ClientHandler* handler, DataHandler* dataHandler)
{
qDebug() << "Thread finished. Deleting handler and thread.";
handler->deleteLater();
dataHandler->deleteLater();
thread->deleteLater();
}
bool initializeMdns() {
#ifdef _WIN32
WORD versionWanted = MAKEWORD(1, 1);
WSADATA wsaData;
if (WSAStartup(versionWanted, &wsaData)) {
qDebug() << "Failed to initialize WinSock";
return false;
}
#else
// 设置中断信号处理器
signal(SIGINT, [](int signal) {
qDebug() << "SIGINT received, cleaning up...";
// 处理退出信号的资源释放逻辑(如果需要)
});
#endif
qDebug() << "mDNS initialization completed.";
return true;
}
QVector<QString> list_network_adapters() {
QVector<QString> ipList;
#ifdef _WIN32
ULONG family = AF_UNSPEC; // Both IPv4 and IPv6
ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
ULONG buffer_size = 15000;
PIP_ADAPTER_ADDRESSES addresses = NULL;
PIP_ADAPTER_ADDRESSES current_address = NULL;
addresses = (IP_ADAPTER_ADDRESSES*)malloc(buffer_size);
if (addresses == NULL) {
qDebug() << "Failed to allocate memory.";
return ipList;
}
if (GetAdaptersAddresses(family, flags, NULL, addresses, &buffer_size) == NO_ERROR) {
current_address = addresses;
while (current_address) {
// Skip loopback interfaces
if (current_address->IfType == IF_TYPE_SOFTWARE_LOOPBACK ||
current_address->OperStatus != IfOperStatusUp) {
current_address = current_address->Next;
continue;
}
qDebug() << "Adapter:" << QString::fromWCharArray(current_address->FriendlyName);
IP_ADAPTER_UNICAST_ADDRESS* unicast = current_address->FirstUnicastAddress;
while (unicast) {
SOCKADDR* addr = unicast->Address.lpSockaddr;
char ip[INET6_ADDRSTRLEN] = { 0 };
if (addr->sa_family == AF_INET) {
struct sockaddr_in* ipv4 = (struct sockaddr_in*)addr;
inet_ntop(AF_INET, &ipv4->sin_addr, ip, sizeof(ip));
qDebug() << " IPv4:" << ip;
ipList.append(QString::fromStdString(ip));
}
else if (addr->sa_family == AF_INET6) {
struct sockaddr_in6* ipv6 = (struct sockaddr_in6*)addr;
inet_ntop(AF_INET6, &ipv6->sin6_addr, ip, sizeof(ip));
qDebug() << " IPv6:" << ip;
// IPv6 地址处理逻辑保留,但不添加到 ipList
}
unicast = unicast->Next;
}
current_address = current_address->Next;
}
}
else {
qDebug() << "Failed to get adapter addresses.";
}
free(addresses);
#else
struct ifaddrs* ifaddr = NULL;
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
return ipList;
}
struct ifaddrs* current = ifaddr;
while (current) {
if (current->ifa_addr && (current->ifa_flags & IFF_UP)) {
// Skip loopback interfaces
if (strcmp(current->ifa_name, "lo") == 0) {
current = current->ifa_next;
continue;
}
char ip[INET6_ADDRSTRLEN] = { 0 };
if (current->ifa_addr->sa_family == AF_INET) {
struct sockaddr_in* ipv4 = (struct sockaddr_in*)current->ifa_addr;
inet_ntop(AF_INET, &ipv4->sin_addr, ip, sizeof(ip));
qDebug() << "Adapter:" << current->ifa_name;
qDebug() << " IPv4:" << ip;
ipList.append(QString::fromStdString(ip));
}
else if (current->ifa_addr->sa_family == AF_INET6) {
struct sockaddr_in6* ipv6 = (struct sockaddr_in6*)current->ifa_addr;
inet_ntop(AF_INET6, &ipv6->sin6_addr, ip, sizeof(ip));
qDebug() << "Adapter:" << current->ifa_name;
qDebug() << " IPv6:" << ip;
// IPv6 地址处理逻辑保留,但不添加到 ipList
}
}
current = current->ifa_next;
}
freeifaddrs(ifaddr);
#endif
return ipList;
}
void convertYUVFolderToJPG(int width, int height, int format) {
QString folderPath = "./convert";
QDir dir(folderPath);
if (!dir.exists()) {
qWarning() << "Directory does not exist:" << folderPath;
return;
}
// 获取目录下所有 .yuv 文件
QStringList yuvFiles = dir.entryList(QStringList() << "*.yuv", QDir::Files);
if (yuvFiles.isEmpty()) {
qWarning() << "No YUV files found in" << folderPath;
return;
}
QString saveDirPath = "./converted_jpg";
QDir saveDir(saveDirPath);
if (!saveDir.exists()) {
saveDir.mkpath(saveDirPath);
}
for (const QString& yuvFileName : yuvFiles) {
QString yuvFilePath = folderPath + "/" + yuvFileName;
qDebug() << "Processing YUV file:" << yuvFilePath;
QFile yuvFile(yuvFilePath);
if (!yuvFile.open(QIODevice::ReadOnly)) {
qWarning() << "Failed to open YUV file:" << yuvFilePath;
continue;
}
QByteArray yuvData = yuvFile.readAll();
yuvFile.close();
QImage image;
if (format == YUV422) {
image = convertYUV422ToQImage(yuvData, width, height);
}
else if (format == YUV420) {
image = convertYUV420ToQImage(yuvData, width, height);
}
else {
qWarning() << "Unsupported YUV format!";
continue;
}
if (image.isNull()) {
qWarning() << "Image conversion failed for:" << yuvFilePath;
continue;
}
// 旋转图片
QTransform transform;
transform.rotate(270);
QImage rotatedImage = image.transformed(transform);
qDebug() << "Image size:" << rotatedImage.size();
qDebug() << "Is null:" << rotatedImage.isNull();
if (rotatedImage.isNull()) {
qWarning() << "Error: rotatedImage is NULL! Conversion or rotation failed.";
return;
}
// 生成 JPG 文件名
QString jpgFileName = saveDirPath + "/" + QFileInfo(yuvFileName).baseName() + ".png";
qDebug() << "Saving JPG to:" << jpgFileName;
if (!rotatedImage.save(jpgFileName, "PNG")) {
qWarning() << "Failed to save JPG image! Check write permissions and format support.";
}
else {
qDebug() << "Successfully saved JPG:" << jpgFileName;
}
}
}
// 初始化 UI 组件和服务器
MainWidget::MainWidget(QWidget* parent) :
QWidget(parent),
nextClientId(1),
nextSerialId(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)),
httpServer(new QTcpServer(this)),
mdnsThread(nullptr)
#if TEST_UDP_BROADCAST
,multicastSocket(new QUdpSocket(this)),
multicastTimer(new QTimer(this))
#endif
{
//convertYUVFolderToJPG(640, 480, 1);
QString configFilePath = QDir::currentPath() + "/UI_config.ini";
TOOL_UI = loadUIConfig(configFilePath);
leftLens_imageLabel = new QLabel(this);
rightLens_imageLabel = new QLabel(this);
leftLens_imageLabel_back = new QLabel(this);
rightLens_imageLabel_back = new QLabel(this);
leftLens_imageLabel_all = new QLabel(this);
rightLens_imageLabel_all = new QLabel(this);
videoLabel = new QLabel(this);
video_Label_back = new QLabel(this);
video_Label_all = new QLabel(this);
frontFuncConfigLineEdit = new QLineEdit(this);
backFuncConfigLineEdit = new QLineEdit(this);
licenseHwInfoEdit = new QTextEdit(this);
UuidHwInfoEdit = new QTextEdit(this);
setupUI();
// 初始化 mDNS
if (!initializeMdns()) {
qDebug() << "Failed to initialize mDNS. Exiting...";
return;
}
//list_network_adapters();
setupHttpServer();
// 打印线程池状态信息
setupTimerForThreadPoolInfo();
QThread* DataSendThread = new QThread(this);
// 必须在 DataSendThread 里创建 serialPortHandler
connect(DataSendThread, &QThread::started, this, [this]() {
serialPortHandler = new SerialPortHandler(TOOL_UI, serialComPortComboBox, serialConnectButton,
frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
frontBoardDevInfoJson, frontBoardLicenseJson,
backBoardOneClickTest, backBoardTest, backBoardFuncConfig,
backBoardDevInfoJson, backBoardUuidJson, getPicJson, getVideoJson, nullptr);
serialPortHandler->moveToThread(QThread::currentThread()); // 绑定到 DataSendThread
//qDebug() << "serialPortHandler created in thread:" << QThread::currentThread();
// 初始化 SerialPortHandler 和定时器(必须在 DataSendThread 内部)
QMetaObject::invokeMethod(serialPortHandler, "initializeSerialPort", Qt::QueuedConnection);
QMetaObject::invokeMethod(serialPortHandler, "initializeTimers", Qt::QueuedConnection);
// 连接信号和槽确保在 DataSendThread
connect(this, &MainWidget::requestDevInfo, serialPortHandler, &SerialPortHandler::sendDevInfoItem, Qt::QueuedConnection);
connect(serialPortHandler, &SerialPortHandler::startTimeout, serialPortHandler, &SerialPortHandler::OnStartTimeout, Qt::QueuedConnection);
connect(serialPortHandler, &SerialPortHandler::requestShowDialog, this, &MainWidget::onShowDialog, Qt::QueuedConnection);
connect(serialPortHandler, &SerialPortHandler::allItemsProcessed, this, &MainWidget::onAllItemsProcessed);
connect(serialPortHandler, &SerialPortHandler::serialDataReceived, this, &MainWidget::onSerialDataReceived);
connect(serialPortHandler, &SerialPortHandler::HandleInvalidOperate, this, &MainWidget::onHandleInvalidOperate);
connect(serialPortHandler, &SerialPortHandler::serialComPortDisconnected, this, [this]() {
qDebug() << "-------- nextSerialId =" << nextSerialId;
startServerButton->setStyleSheet("");
sendAllButton->setEnabled(false);
isReplyOrTimeout = true;
connectedClientsCount --;
if (connectedClientsCount <= 0) connectedClientsCount = 0;
lastClickedGetPicCamIndex = -1;
lastClickedGetPicDevIndex = -1;
lastClickedGetVideoCamIndex = -1;
lastClickedGetVideoDevIndex = -1;
updateServerButtonText();
updateGetVideoButtonState(0, connectedClientsCount, getVideoButtons);
updateGetPicButtonsState(0, connectedClientsCount);
if (serialDataHandlers.contains(nextSerialId - 1)) {
SerialDataHandler* serialDataHandler = serialDataHandlers[nextSerialId - 1];
serialDataHandlers.remove(nextSerialId - 1); // 从容器中移除
serialDataHandler->deleteLater(); // 延迟删除 serialDataHandler 对象
}
qDebug() << "Current path: " << QDir::currentPath();
QString filePath = QDir::currentPath() + "/add1.h264";
if (QFile::exists(filePath)) {
QFile file(filePath);
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "File add1.h264 cleared successfully.";
}
else {
qDebug() << "Failed to clear file add1.h264:" << file.errorString();
}
}
else {
qDebug() << "File add1.h264 does not exist.";
}
for (QPushButton* button : getVideoButtons) {
if (button) {
button->setStyleSheet("");
}
}
for (QPushButton* button : getPicButtons) {
if (button) {
button->setStyleSheet("");
}
}
});
/*connect(serialPortHandler, &SerialPortHandler::selectBmpFile, this, [=]() {
QString filePath = QFileDialog::getOpenFileName(nullptr, "选择 BMP 图片", "", "BMP Files (*.bmp);;All Files (*)");
emit serialPortHandler->bmpFileSelected(filePath);
});*/
#if UPDATE_LOGO
connect(serialPortHandler, &SerialPortHandler::selectBmpFile, this, [=]() {
QString filePath = QFileDialog::getOpenFileName(nullptr, "选择 BMP 图片", "", "BMP Files (*.bmp);;All Files (*)");
emit serialPortHandler->bmpFileSelected(filePath);
}, Qt::QueuedConnection);
#endif
//qDebug() << "MainWidget ------- Current thread:" << QThread::currentThread();
connect(serialPortHandler, &SerialPortHandler::serialComPortConnected, this, [this]() {
int serialId = nextSerialId++;
connectedClientsCount++;
isFirstSendDevInfo = true;
isReplyOrTimeout = true;
updateServerButtonText();
updateGetVideoButtonState(1, connectedClientsCount, getVideoButtons);
updateGetPicButtonsState(1, connectedClientsCount);
isBackBoardOrAllBoard = 0;
switchToTab(0);
startServerButton->setStyleSheet("background-color: green;");
sendAllButton->setEnabled(true);
QThread* DataHandlerThread = new QThread(this);
SerialDataHandler* serialDataHandler = new SerialDataHandler(videoLabel, video_Label_back, VideoResolutionEdit, VideoResolutionEdit_back,
leftLens_imageLabel->size(), &devInfoLineEdits, isBackBoardOrAllBoard,
frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
frontBoardDevInfoJson, frontBoardLicenseJson,
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
backBoardUuidJson, getPicJson, getVideoJson, nullptr);
// 将 serialDataHandler 移到线程池中的线程
serialDataHandler->moveToThread(DataHandlerThread);
connect(DataHandlerThread, &QThread::finished, serialDataHandler, &QObject::deleteLater);
connect(serialDataHandler, &SerialDataHandler::startTimeout, serialPortHandler, &SerialPortHandler::OnStartTimeout, Qt::QueuedConnection);
DataHandlerThread->start();
//qDebug() << "Thread running:" << DataHandlerThread->isRunning();
//qDebug() << "SerialPortHandler thread:" << serialPortHandler->thread();
//qDebug() << "SerialDataHandler thread:" << serialDataHandler->thread();
bool isConnected = connect(serialPortHandler, &SerialPortHandler::dataReceived, serialDataHandler, &SerialDataHandler::handleData, Qt::QueuedConnection);
//qDebug() << "-- Connection successful:" << isConnected;
// 线程结束时删除 DataHandlerThread 对象
connect(DataHandlerThread, &QThread::finished, this, [=]() {
qDebug() << "Thread finished. Deleting serialDataHandler and thread.";
serialDataHandler->deleteLater();
if (DataHandlerThread) {
DataHandlerThread->deleteLater();
}
});
connect(this, &MainWidget::openFocusWindow, serialDataHandler, &SerialDataHandler::handleOpenFocusWindow, Qt::UniqueConnection);
connect(serialPortHandler, &SerialPortHandler::statusUpdated, this, &MainWidget::onStatusUpdated, Qt::UniqueConnection);
connect(serialDataHandler, &SerialDataHandler::statusUpdated, this, &MainWidget::onStatusUpdated, Qt::UniqueConnection);
serialDataHandlers[serialId] = serialDataHandler;
connect(serialDataHandler, &SerialDataHandler::sendHeartBeatData, serialPortHandler, &SerialPortHandler::onSendHeartBeatData);
connect(serialDataHandler, &SerialDataHandler::recvNormalDataFlag, serialPortHandler, &SerialPortHandler::onRecvNormalDataFlag);
connect(serialDataHandler, &SerialDataHandler::updateLicenseHwInfoEdit, this, [this](const QString& text) {
licenseHwInfoEdit->setPlainText(text);
}, Qt::UniqueConnection);
connect(serialDataHandler, &SerialDataHandler::updateUuidHwInfoEdit, this, [this](const QString& text) {
UuidHwInfoEdit->setPlainText(text);
}, Qt::UniqueConnection);
connect(serialDataHandler, &SerialDataHandler::updateLeftLensImage, leftLens_imageLabel, &QLabel::setPixmap, Qt::UniqueConnection);
connect(serialDataHandler, &SerialDataHandler::updateRightLensImage, rightLens_imageLabel, &QLabel::setPixmap, Qt::UniqueConnection);
connect(serialDataHandler, &SerialDataHandler::updateVideoLabel, videoLabel, &QLabel::setPixmap, Qt::UniqueConnection);
connect(serialDataHandler, &SerialDataHandler::updateVideoResolution, VideoResolutionEdit, &QLineEdit::setText, Qt::UniqueConnection);
connect(serialPortHandler, &SerialPortHandler::currentSendItem, serialDataHandler, &SerialDataHandler::getCurrentSendItem);
connect(serialPortHandler, &SerialPortHandler::updateTimeout, serialDataHandler, &SerialDataHandler::onUpdateTimeout);
connect(serialPortHandler, &SerialPortHandler::startImageSharing, this, &MainWidget::onStartImageSharing);
//connect(serialPortHandler, &SerialPortHandler::startLOGOImageSharing, this, &MainWidget::onStartLOGOImageSharing);
connect(serialDataHandler, &SerialDataHandler::picRecvFinished, serialPortHandler, &SerialPortHandler::onPicRecvFinished);
connect(serialDataHandler, &SerialDataHandler::commandError, serialPortHandler, &SerialPortHandler::onCommandError);
connect(serialDataHandler, &SerialDataHandler::commandError, serialPortHandler, &SerialPortHandler::onCommandError);
// 前板有设备连接自动发送获取设备信息
//serialPortHandler->sendDevInfoItem();
});
});
connect(DataSendThread, &QThread::finished, this, [this]() {
if (serialPortHandler) {
serialPortHandler->deleteLater();
serialPortHandler = nullptr;
qDebug() << "--1-- SerialPortHandler 被销毁,所有定时器已停止";
}
});
// **确保 serialPortHandler 创建后才连接信号**
connect(DataSendThread, &QThread::started, this, &MainWidget::setupSerialPortHandlerConnections);
DataSendThread->start();
server = new QTcpServer(this);
connect(server, &QTcpServer::newConnection, this, [this]() {
while (server->hasPendingConnections()) {
QTcpSocket* socket = server->nextPendingConnection();
int clientId = nextClientId ++;
QHostAddress clientIp = socket->peerAddress();
quint16 clientPort = socket->peerPort();
QString ipString = clientIp.toString();
isReplyOrTimeout = true;
if (ipString.startsWith("::ffff:")) {
ipString = ipString.mid(7);
}
qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
qDebug() << "> A client is connected. ID:" << clientId;
qDebug() << "> Client IP:" << ipString << " Port:" << clientPort;
qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
if (ipString.startsWith("10.10.10")) {
//if (1) {
qDebug() << "The client IP address is front board !!!";
isBackBoardOrAllBoard = 0;
}
else {
onDisconnectClient(clientId - 1);
qDebug() << "The client IP address is back board or all board";
isBackBoardOrAllBoard = clientId;
}
//stopMdnsService();
connectedClientsCount ++;
updateServerButtonText();
updateGetVideoButtonState(1, connectedClientsCount, getBackVideoButtons);
switchToTab(1);
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(frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
frontBoardDevInfoJson, frontBoardLicenseJson,
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
backBoardUuidJson, getPicJson, getVideoJson, clientId, isBackBoardOrAllBoard, nullptr);
// 将 socket 移动到新的线程中,一定要先取消父对象
socket->setParent(nullptr);
socket->moveToThread(thread);
// 将 socket 传递到 handler
handler->initialize(socket);
DataHandler* dataHandler = new DataHandler(videoLabel, video_Label_back, VideoResolutionEdit, VideoResolutionEdit_back,
leftLens_imageLabel->size(), &devInfoLineEdits, isBackBoardOrAllBoard,
frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
frontBoardDevInfoJson, frontBoardLicenseJson,
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
backBoardUuidJson, getPicJson, getVideoJson, nullptr);
// 将 ClientHandler 和 DataHandler 移到线程池中的线程
handler->moveToThread(thread);
dataHandler->moveToThread(thread);
connect(handler, &ClientHandler::sendData, handler, &ClientHandler::onSendData, Qt::QueuedConnection);
connect(handler, &ClientHandler::startTimeout, this, [this, clientId](int timeout) {
this->onStartTimeout(clientId, timeout);
});
clients.append(handler);
clients_1[clientId] = handler;
clientThreads[clientId] = thread;
connect(handler, &ClientHandler::statusUpdated, this, &MainWidget::onStatusUpdated);
connect(handler, &ClientHandler::HandleInvalidOperate, this, &MainWidget::onHandleInvalidOperate);
connect(handler, &ClientHandler::clientDisconnected, this, &MainWidget::onClientDisconnected);
connect(handler, &ClientHandler::allItemsProcessed, this, &MainWidget::onAllItemsProcessed);
//connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient);
dataHandlers[clientId] = dataHandler;
connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData);
connect(handler, &ClientHandler::currentSendItem, dataHandler, &DataHandler::getCurrentSendItem);
connect(dataHandler, &DataHandler::picRecvFinished, handler, &ClientHandler::onPicRecvFinished);
connect(dataHandler, &DataHandler::commandError, handler, &ClientHandler::onCommandError);
connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated);
// 当线程结束时删除 handler
connect(thread, &QThread::finished, this, [=]() {
onThreadFinished(thread, handler, dataHandler);
});
connect(dataHandler, &DataHandler::updateLicenseHwInfoEdit, this, [this](const QString& text) {
licenseHwInfoEdit->setPlainText(text);
});
connect(dataHandler, &DataHandler::updateUuidHwInfoEdit, this, [this](const QString& text) {
UuidHwInfoEdit->setPlainText(text);
});
connect(dataHandler, &DataHandler::updateLeftLensImage, leftLens_imageLabel, &QLabel::setPixmap);
connect(dataHandler, &DataHandler::updateRightLensImage, rightLens_imageLabel, &QLabel::setPixmap);
connect(dataHandler, &DataHandler::updateVideoLabel, videoLabel, &QLabel::setPixmap);
connect(dataHandler, &DataHandler::updateVideoResolution, VideoResolutionEdit, &QLineEdit::setText);
// 启动新的线程
thread->start();
connect(handler, &ClientHandler::startReadTimer, this, &MainWidget::startClientReadTimer);
connect(handler, &ClientHandler::stopReadTimer, this, &MainWidget::stopClientReadTimer);
connect(this, &MainWidget::openFocusWindowRequested, dataHandler, &DataHandler::handleOpenFocusWindow);
// 创建和管理定时器
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(handler, &ClientHandler::startImageSharing, this, &MainWidget::onStartImageSharing);
connect(handler, &ClientHandler::startLOGOImageSharing, this, &MainWidget::onStartLOGOImageSharing);
if (isBackBoardOrAllBoard != 0) {
handler->sendDevInfoItem();
}
}
});
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);
#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()
{
stopMdnsService();
for (auto timer : clientReadTimers) {
timer->stop();
delete timer;
}
clientReadTimers.clear();
for (auto dataHandler : dataHandlers) {
dataHandler->deleteLater();
}
dataHandlers.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::setupSerialPortHandlerConnections() {
if (!serialPortHandler) return;
connect(serialPortHandler, &SerialPortHandler::requestUserInput, this, &MainWidget::showDelUserWindow);
connect(this, &MainWidget::userInputEntered, serialPortHandler, &SerialPortHandler::onUserInputReceived);
}
void MainWidget::showDelUserWindow() {
DelUserWindow dialog;
if (dialog.exec() == QDialog::Accepted) {
emit userInputEntered(dialog.getUserInput());
}
}
void MainWidget::onShowDialog()
{
//qDebug() << "------------------------onShowDialog--------------------------";
DelUserWindow dialog(this);
dialog.setWindowFlags(dialog.windowFlags() | Qt::WindowStaysOnTopHint);
dialog.activateWindow();
dialog.raise();
QString userInput;
if (dialog.exec() == QDialog::Accepted) {
userInput = dialog.getUserInput();
}
else {
userInput = "";
}
emit serialPortHandler->dialogResultReceived(userInput);
}
void MainWidget::sendLicenseData(int itemIndex, const QString text) {
QJsonObject currentItem = frontBoardLicenseJson[itemIndex].toObject();
if (!text.isEmpty() && currentItem.contains("val")) {
QJsonValue originalValue = currentItem["val"];
//qDebug() << "text:" << text;
if (originalValue.isDouble()) {
bool ok;
double doubleValue = text.toDouble(&ok);
if (ok) {
currentItem["val"] = doubleValue;
}
else {
qWarning() << "Text conversion to double failed, original value is kept.";
}
}
else if (originalValue.isString()) {
currentItem["val"] = text;
}
}
QString itemData = QJsonDocument(currentItem).toJson();
sendSerialData(itemData.toUtf8(), 0);
}
void MainWidget::sendSerialData(const QByteArray& data, bool heartBeat) {
if (serialPortHandler) {
serialPortHandler->sendData(data, heartBeat, "");
}
}
QByteArray MainWidget::hexStringToByteArray(const QString& hexString)
{
QByteArray byteArray;
for (int i = 0; i < hexString.length(); i += 2) {
byteArray.append(static_cast<char>(hexString.mid(i, 2).toUShort(nullptr, 16)));
}
return byteArray;
}
void MainWidget::onSerialDataReceived(const QByteArray& data) {
qDebug() << "Recv data:<-----" << data.toHex();
QString receiveData = data.toHex();
QString heartData = "aa55aa5538010100000000";
QString licenseData = "aa55aa552004";
if (receiveData == heartData) {
// 更新 UI 或处理数据
QByteArray payload;
payload.append(static_cast<char>(0x00)); // 构造需要发送的数据内容
bool heartBeat = true;
sendSerialData(payload, heartBeat);
}
else {
bool success = (static_cast<unsigned char>(data.at(10)) != 0x00);
if (data.mid(0, 6) == QByteArray::fromHex("aa55aa552004")) {
int dataSize = (static_cast<unsigned char>(data.at(9)) << 24) |
(static_cast<unsigned char>(data.at(8)) << 16) |
(static_cast<unsigned char>(data.at(7)) << 8) |
(static_cast<unsigned char>(data.at(6)));
int totalSize = 10 + dataSize;
QByteArray licenseData = data.mid(11, dataSize);
QString hexString = QString::fromUtf8(licenseData.toHex().data());
QByteArray actual_data = hexStringToByteArray(hexString);
qDebug() << "GET_FRONT_HW_INFO";
QStringList hexList;
QString dataStr;
if (actual_data.size() == PIX_HARDWARE_INFO_BYTES) {
for (int i = 0; i < actual_data.size(); ++i) {
hexList << QString("0x%1").arg(static_cast<unsigned char>(actual_data[i]), 2, 16, QLatin1Char('0')).toUpper().replace("0X", "0x");
}
dataStr = hexList.join(", ");
}
else
dataStr = "前板发送的 HW INFO 数据大小不正确";
QString displayText = dataStr;
//licenseHwInfoEdit->setPlainText(displayText);
//emit updateLicenseHwInfoEdit(displayText);
licenseHwInfoEdit->setPlainText(displayText);
}
else if (data.mid(0, 6) == QByteArray::fromHex("aa55aa552104")) {
qDebug() << "currentIndex :" << currentIndex;
QString label = "";
if (currentIndex >= 0 && currentIndex < frontBoardLicenseJson.size()) {
QJsonObject jsonObject = frontBoardLicenseJson.at(currentIndex).toObject();
if (jsonObject.contains("lable")) {
label = jsonObject["lable"].toString();
qDebug() << "label :" << label;
}
}
QListWidgetItem* listItem = new QListWidgetItem(QString("device ID: %1 - Item %2: %3 ---> %4")
.arg(nextSerialId - 1)
.arg(currentIndex + 1)
.arg(label)
.arg(success ? "OK" : "NG"), statusListWidget);
listItem->setBackground(success ? Qt::green : Qt::red);
statusListWidget->addItem(listItem);
statusListWidget->scrollToBottom();
}
}
}
// 处理客户端断开连接信号
void MainWidget::onClientDisconnected(ClientHandler* handler)
{
int clientId = handler->getClientId();
int preVideoId = handler->preVideoClientId;
int boardTpye = isBackBoardOrAllBoard;
if (clientTimers.contains(clientId)) {
QTimer* timer = clientTimers[clientId];
timer->stop();
delete timer;
clientTimers.remove(clientId);
}
clients.removeOne(handler);
/*
将 ClientHandler 对象的删除操作放入事件队列中,等待事件循环处理。
在事件循环执行时,会安全地删除 ClientHandler 对象,这包括释放其占用的资源和内存
*/
handler->deleteLater(); // 延迟删除 ClientHandler 对象
if (dataHandlers.contains(clientId)) {
DataHandler* dataHandler = dataHandlers[clientId];
dataHandlers.remove(clientId); // 从容器中移除
dataHandler->deleteLater(); // 延迟删除 DataHandler 对象
}
// 更新连接数并更新按键文本
connectedClientsCount--;
//qDebug() << " connectedClientsCount :" << connectedClientsCount;
if (nextClientId <= 2) nextClientId --;
deviceConnected = true;
updateServerButtonText();
updateGetVideoButtonState(0, connectedClientsCount, getBackVideoButtons);
int count = 200;
while (count--);
qDebug() << " preVideoClientId :" << preVideoId;
qDebug() << " clientId :" << clientId;
if ((boardTpye != 0) || (preVideoId == clientId)) {
qDebug() << "Current path: " << QDir::currentPath();
QString filePath = QDir::currentPath() + "/add1.h264";
if (QFile::exists(filePath)) {
QFile file(filePath);
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "File add1.h264 cleared successfully.";
}
else {
qDebug() << "Failed to clear file add1.h264:" << file.errorString();
}
}
else {
qDebug() << "File add1.h264 does not exist.";
}
}
}
void MainWidget::onDisconnectClient(int clientId)
{
for (ClientHandler* handler : clients) {
if (handler->getClientId() == clientId) {
// 断开与该客户端的连接
if (clientTimers.contains(clientId)) {
QTimer* timer = clientTimers[clientId];
timer->stop();
delete timer;
clientTimers.remove(clientId);
}
clients.removeOne(handler);
handler->deleteLater();
if (dataHandlers.contains(clientId)) {
DataHandler* dataHandler = dataHandlers[clientId];
dataHandlers.remove(clientId); // 从容器中移除
dataHandler->deleteLater(); // 延迟删除 DataHandler 对象
}
int count = 200;
int preVideoId = handler->preVideoClientId;
int boardTpye = isBackBoardOrAllBoard;
while (count--);
qDebug() << " preVideoClientId :" << preVideoId;
qDebug() << " clientId :" << clientId;
if ((boardTpye != 0) || (preVideoId == clientId)) {
qDebug() << "Current path: " << QDir::currentPath();
QString filePath = QDir::currentPath() + "/add1.h264";
if (QFile::exists(filePath)) {
QFile file(filePath);
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "File add1.h264 cleared successfully.";
}
else {
qDebug() << "Failed to clear file add1.h264:" << file.errorString();
}
}
else {
qDebug() << "File add1.h264 does not exist.";
}
}
connectedClientsCount--;
//qDebug() << " connectedClientsCount :" << connectedClientsCount;
updateServerButtonText();
break;
}
}
stopMdnsService();
//if (connectedClientsCount == 0) {
// // 启动 mDNS 服务广播
// startMdnsService();
//}
}
// 更新按键文本的函数
void MainWidget::updateServerButtonText()
{
if (deviceConnected) {
if (connectedClientsCount > 0) {
startServerButton->setText(tr("正在监听(Listening)\n%1 台设备连接").arg(connectedClientsCount));
}
else if (connectedClientsCount == 0) {
#if START_MDNS // 这里会开启多个mdns广播去掉
startMdnsService(getSelectedIp());
#endif
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::updateGetVideoButtonState(int state, int connectedDevices, const QVector<QPushButton*>& buttons)
{
if (state == 1) {
for (int i = 3; i <= 5; ++i) {
for (int j = -1; j < 2; ++j) {
int index = i * 2 + j;
qDebug() << " index :" << index;
if (index < buttons.size()) {
QPushButton* button = buttons[index];
if (index - 3 <= connectedDevices) {
button->setEnabled(true);
button->setStyleSheet("");
}
else {
button->setEnabled(false);
// 让按键变透明,但是占用布局
button->setStyleSheet("background: transparent; border: none; color: transparent;");
}
}
}
}
}
else if (state == 0) {
for (int i = 3; i <= 5; ++i) {
for (int j = 0; j < 2; ++j) {
int index = i * 2 + j;
//qDebug() << " index :" << index;
if (index < buttons.size()) {
QPushButton* button = buttons[index];
button->setEnabled(true);
button->setStyleSheet("");
}
}
}
}
}
void MainWidget::updateGetPicButtonsState(int state, int connectedDevices)
{
if (state == 1) {
for (int i = 1; i <= 5; ++i) {
for (int j = 0; j < 2; ++j) {
int index = i * 2 + j;
//qDebug() << " index :" << index;
if (index < getPicButtons.size()) {
QPushButton* button = getPicButtons[index];
if (index <= connectedDevices) {
button->setEnabled(true);
button->setStyleSheet("");
}
else {
button->setEnabled(false);
// 让按键变透明,但是占用布局
button->setStyleSheet("background: transparent; border: none; color: transparent;");
}
}
}
}
}
else if (state == 0) {
for (int i = 1; i <= 5; ++i) {
for (int j = 0; j < 2; ++j) {
int index = i * 2 + j;
//qDebug() << " index :" << index;
if (index < getPicButtons.size()) {
QPushButton* button = getPicButtons[index];
button->setEnabled(true);
button->setStyleSheet("");
}
}
}
}
}
void MainWidget::setupUI()
{
// 左侧部分 UI 元素
startServerButton = new QPushButton(TOOL_UI.START_LISTENING, this);
startServerButton->setFixedSize(190, 70);
sendAllButton = new QPushButton(TOOL_UI.ONE_CLICKED_TEST, 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();
QLabel* serialComPortLabel = new QLabel(TOOL_UI.SELECT_COM_PORT, this);
serialComPortComboBox = new QComboBox(this);
serialComPortComboBox->setFixedSize(220, 28);
// 创建一个连接按钮
serialConnectButton = new QPushButton(TOOL_UI.CONNECT_FRONT_BOARD, this);
serialConnectButton->setFixedSize(70, 28);
// 创建一个新的水平布局,并将这三个元素添加到该布局
QHBoxLayout* comPortLayout = new QHBoxLayout;
comPortLayout->addWidget(serialComPortLabel);
comPortLayout->addWidget(serialComPortComboBox);
comPortLayout->addWidget(serialConnectButton);
QLabel* ipLabel = new QLabel(TOOL_UI.SELECT_MDSN_IP, this);
ipComboBox = new QComboBox(this);
ipComboBox->setFixedSize(260, 28);
ipComboBox->clear();
// 获取网络适配器的 IPv4 地址列表
QVector<QString> ipAddresses = list_network_adapters();
for (const QString& ip : ipAddresses) {
ipComboBox->addItem(ip);
}
QHBoxLayout* ipSelectionLayout = new QHBoxLayout;
ipSelectionLayout->addWidget(ipLabel);
ipSelectionLayout->addWidget(ipComboBox);
ipSelectionLayout->addStretch();
QVBoxLayout* leftLayout = new QVBoxLayout;
leftLayout->addLayout(buttonLayout);
leftLayout->addLayout(ipSelectionLayout);
leftLayout->addLayout(comPortLayout);
leftLayout->setStretch(0, 1);
leftLayout->addWidget(statusListWidget);
leftLayout->setStretch(1, 200);
saveCheckBox = new QCheckBox("", this);
saveCheckBox->setChecked(true);
selectFileButton = new QPushButton(TOOL_UI.SAVE_LOG, this);
selectFileButton->setFixedSize(45, 28);
clearLogButton = new QPushButton(TOOL_UI.CLEAR_LOG, 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();
QWidget* leftContainer = new QWidget(this);
leftContainer->setLayout(leftLayout);
leftContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
mainTabWidget = new QTabWidget(this);
VideoResolutionEdit = new QLineEdit(this);
VideoResolutionEdit_back = new QLineEdit(this);
VideoResolutionEdit_all = new QLineEdit(this);
// 添加前板、后板、整机的布局
addDeviceAreaTab(mainTabWidget, TOOL_UI.FRONT_BOARD_NAME,
createFrontDeviceInfoGroupBox(), createLicenseGroupBox(),
frontBoardTest, frontBoardFuncConfig, "frontBoardTest", "frontBoardFuncConfig",
TOOL_UI.FRONT_TEST_ITEM, TOOL_UI.FRONT_CONFID_ITEM, leftLens_imageLabel, rightLens_imageLabel,
videoLabel, VideoResolutionEdit);
addDeviceAreaTab(mainTabWidget, TOOL_UI.BACK_BOARD_NAME,
createBackDeviceInfoGroupBox(), createBackConnectServerGroupBox(),
backBoardTest, backBoardFuncConfig, "backBoardTest", "backBoardFuncConfig",
TOOL_UI.BACK_TEST_ITEM, TOOL_UI.BACK_CONFID_ITEM, leftLens_imageLabel_back, rightLens_imageLabel_back,
video_Label_back, VideoResolutionEdit_back);
addAllDeviceAreaTab(mainTabWidget, TOOL_UI.ALL_BOARD_NAME,
allBoardTest, allBoardFuncConfig, "allBoardTest", "allBoardFuncConfig",
TOOL_UI.ALL_TEST_ITEM, TOOL_UI.ALL_CONFID_ITEM,
leftLens_imageLabel_all, rightLens_imageLabel_all, video_Label_all, VideoResolutionEdit_all);
// 右侧主布局
QVBoxLayout* rightVerticalLayout = new QVBoxLayout;
rightVerticalLayout->addWidget(mainTabWidget, 5);
// 主布局
QHBoxLayout* mainLayout = new QHBoxLayout;
mainLayout->addWidget(leftContainer, 1, Qt::AlignTop | Qt::AlignLeft);
mainLayout->addLayout(rightVerticalLayout, 3);
setLayout(mainLayout);
setWindowTitle(TOOL_UI.TOOL_VERSION);
resize(TOOL_UI.SL100_FACTORY_TOOL_W, TOOL_UI.SL100_FACTORY_TOOL_H);
// 信号槽连接
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::switchToTab(int tabIndex) {
mainTabWidget->setCurrentIndex(tabIndex);
mainTabWidget->setStyleSheet(
"QTabBar::tab:selected { background-color: green; color: black; }"
);
}
char* MainWidget::getSelectedIp() const {
QString selectedIp = ipComboBox->currentText();
qDebug() << "Selected MDns IP:" << selectedIp; // 打印当前选中的 IP
// 将 QString 转换为 std::string
std::string ipStdString = selectedIp.toStdString();
// 动态分配内存存储 char*
char* ipChar = new char[ipStdString.size() + 1];
strcpy(ipChar, ipStdString.c_str());
return ipChar;
}
void MainWidget::onStartImageSharing(int width, int height, QString img_type, std::function<void(QString)> callback) {
if (isBackBoardOrAllBoard) {
//if (1) {
imagePath = QFileDialog::getOpenFileName(this, "选择图片", QDir::homePath(), "Images (*.png *.jpg *.jpeg)");
if (imagePath.isEmpty()) {
qDebug() << "No image selected.";
return;
}
// 加载图片并获取尺寸
QImage image(imagePath);
if (image.isNull()) {
qDebug() << "Failed to load image.";
return;
}
QSize imageSize = image.size();
qDebug() << "Original image dimensions:" << imageSize.width() << "x" << imageSize.height();
// 判断是否需要裁剪
if (imageSize.width() > width || imageSize.height() > height) {
int x = (imageSize.width() - width) / 2; // 左右裁剪
int y = (imageSize.height() - height) / 2; // 上下裁剪
// 裁剪图片中间部分
image = image.copy(x, y, width, height);
qDebug() << "Cropped image dimensions:" << image.width() << "x" << image.height();
}
else if (imageSize.width() < width || imageSize.height() < height) {
isReplyOrTimeout = true;
QString info = QString("您选择的图片尺寸小于 %1 x %2请重新操作并选择正确的尺寸的图片").arg(width).arg(height);
LicenseConfirmWindow dialog(info);
dialog.exec();
callback("");
return;
}
// 保存裁剪后的图片到服务器目录
QString croppedImagePath = QCoreApplication::applicationDirPath() + QString("/%1_image.jpg").arg(img_type);
if (!image.save(croppedImagePath, "JPEG")) {
qDebug() << "Failed to save cropped image.";
return;
}
qDebug() << "Cropped image saved to:" << croppedImagePath;
// 更新服务使用裁剪后的图片路径
this->imagePath = croppedImagePath;
QString selectedIp = ipComboBox->currentText();
// 获取本地 IP 地址
QString localIP;
QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
qDebug() << "-------------------------------------------";
qDebug() << "MDns IP addresses:" << selectedIp;
/*qDebug() << "All available IP addresses:";
for (const QHostAddress& addr : addresses) {
qDebug() << addr.toString();
}*/
qDebug() << "-------------------------------------------";
for (const QHostAddress& addr : addresses) {
if (addr.protocol() == QAbstractSocket::IPv4Protocol && addr != QHostAddress::LocalHost && addr.toString() == selectedIp) {
localIP = addr.toString();
break;
}
}
if (localIP.isEmpty()) {
qDebug() << "Failed to determine local IP address.";
return;
}
// 构建下载 URL
QString downloadUrl = QString("http://%1:%2/%3_image.jpg").arg(localIP).arg(serverPort).arg(img_type);
qDebug() << "Download URL:" << downloadUrl;
// 回调返回下载地址
callback(downloadUrl);
}
else {
QFileDialog* fileDialog = new QFileDialog(this);
fileDialog->setWindowTitle("选择图片");
fileDialog->setDirectory(QDir::currentPath());
fileDialog->setNameFilter("Images (*.bmp *.png *.jpg *.jpeg);;All Files (*)");
fileDialog->setFileMode(QFileDialog::ExistingFile);
qDebug() << "--------1-------enroll image------------------";
// **当用户选择文件后,调用 lambda 处理逻辑**
connect(fileDialog, &QFileDialog::fileSelected, this, [=](const QString& imagePath) {
qDebug() << "--------2-------enroll image------------------";
if (imagePath.isEmpty()) {
qDebug() << "No image selected.";
return;
}
qDebug() << "--------imagePath:" << imagePath;
if (!QFile::exists(imagePath)) {
qDebug() << "File does not exist at path:" << imagePath;
return;
}
// 加载图片并获取尺寸
QImage image(QDir::toNativeSeparators(imagePath));
if (image.isNull()) {
qDebug() << "Failed to load image.";
return;
}
QSize imageSize = image.size();
qDebug() << "Original image dimensions:" << imageSize.width() << "x" << imageSize.height();
// 判断是否需要裁剪
if (imageSize.width() > width || imageSize.height() > height) {
int x = (imageSize.width() - width) / 2; // 左右裁剪
int y = (imageSize.height() - height) / 2; // 上下裁剪
// 裁剪图片中间部分
image = image.copy(x, y, width, height);
qDebug() << "Cropped image dimensions:" << image.width() << "x" << image.height();
}
else if (imageSize.width() < width || imageSize.height() < height) {
isReplyOrTimeout = true;
QString info = QString("您选择的图片尺寸小于 %1 x %2请重新操作并选择正确的尺寸的图片").arg(width).arg(height);
LicenseConfirmWindow dialog(info);
dialog.exec();
callback("");
return;
}
// 保存裁剪后的图片到服务器目录
QString croppedImagePath = QCoreApplication::applicationDirPath() + QString("/%1_image.jpg").arg(img_type);
if (!image.save(croppedImagePath, "JPEG")) {
qDebug() << "Failed to save cropped image.";
return;
}
qDebug() << "Cropped image saved to:" << croppedImagePath;
// 更新服务使用裁剪后的图片路径
this->imagePath = croppedImagePath;
QString selectedIp = ipComboBox->currentText();
// 获取本地 IP 地址
QString localIP;
QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
qDebug() << "-------------------------------------------";
qDebug() << "MDns IP addresses:" << selectedIp;
/*qDebug() << "All available IP addresses:";
for (const QHostAddress& addr : addresses) {
qDebug() << addr.toString();
}*/
qDebug() << "-------------------------------------------";
for (const QHostAddress& addr : addresses) {
if (addr.protocol() == QAbstractSocket::IPv4Protocol && addr != QHostAddress::LocalHost && addr.toString() == selectedIp) {
localIP = addr.toString();
break;
}
}
if (localIP.isEmpty()) {
qDebug() << "Failed to determine local IP address.";
return;
}
// 构建下载 URL
QString downloadUrl = QString("http://%1:%2/%3_image.jpg").arg(localIP).arg(serverPort).arg(img_type);
qDebug() << "Download URL:" << downloadUrl;
// 回调返回下载地址
callback(downloadUrl);
});
// **显示对话框(非阻塞)**
fileDialog->open();
}
}
void MainWidget::onStartLOGOImageSharing(int width, int height, QString img_type, std::function<void(QString)> callback) {
imagePath = QFileDialog::getOpenFileName(this, "选择图片", QDir::homePath(), "BMP Files(*.bmp);; All Files(*)");
if (imagePath.isEmpty()) {
qDebug() << "No image selected.";
return;
}
// 加载图片并获取尺寸
QImage image(imagePath);
if (image.isNull()) {
qDebug() << "Failed to load image.";
return;
}
QSize imageSize = image.size();
qDebug() << "Original image dimensions:" << imageSize.width() << "x" << imageSize.height();
// 判断图片大小
if (imageSize.width() > width || imageSize.height() > height || imageSize.width() <= 0 || imageSize.height() <= 0) {
isReplyOrTimeout = true;
QString info = QString("您选择的图片尺寸大于 %1 x %2请重新操作并选择正确的尺寸的图片").arg(width).arg(height);
LicenseConfirmWindow dialog(info);
dialog.exec();
callback("");
return;
}
// 保存裁剪后的图片到服务器目录
QString croppedImagePath = QCoreApplication::applicationDirPath() + QString("/%1_image.bmp").arg(img_type);
if (!image.save(croppedImagePath, "BMP")) {
qDebug() << "Failed to save cropped image.";
return;
}
qDebug() << "Cropped image saved to:" << croppedImagePath;
// 更新服务使用裁剪后的图片路径
this->imagePath = croppedImagePath;
QString selectedIp = ipComboBox->currentText();
// 获取本地 IP 地址
QString localIP;
QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
qDebug() << "-------------------------------------------";
qDebug() << "MDns IP addresses:" << selectedIp;
/*qDebug() << "All available IP addresses:";
for (const QHostAddress& addr : addresses) {
qDebug() << addr.toString();
}*/
qDebug() << "-------------------------------------------";
for (const QHostAddress& addr : addresses) {
if (addr.protocol() == QAbstractSocket::IPv4Protocol && addr != QHostAddress::LocalHost && addr.toString() == selectedIp) {
localIP = addr.toString();
break;
}
}
if (localIP.isEmpty()) {
qDebug() << "Failed to determine local IP address.";
return;
}
// 构建下载 URL
QString downloadUrl = QString("http://%1:%2/%3_image.bmp").arg(localIP).arg(serverPort).arg(img_type);
qDebug() << "Download URL:" << downloadUrl;
// 回调返回下载地址
callback(downloadUrl);
}
void MainWidget::setupHttpServer() {
connect(httpServer, &QTcpServer::newConnection, this, [this]() {
QTcpSocket* clientSocket = httpServer->nextPendingConnection();
connect(clientSocket, &QTcpSocket::readyRead, this, [this, clientSocket]() {
handleHttpRequest(clientSocket);
});
});
if (!httpServer->listen(QHostAddress::Any, serverPort)) {
qDebug() << "Failed to start HTTP server:" << httpServer->errorString();
}
else {
qDebug() << "HTTP server started on port" << serverPort;
}
}
void MainWidget::handleHttpRequest(QTcpSocket* clientSocket) {
QByteArray requestData = clientSocket->readAll();
qDebug() << "HTTP Request:" << requestData;
if (imagePath.isEmpty()) {
clientSocket->write("HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n");
clientSocket->disconnectFromHost();
return;
}
QFile file(imagePath);
if (!file.open(QIODevice::ReadOnly)) {
clientSocket->write("HTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\n\r\n");
clientSocket->disconnectFromHost();
return;
}
QByteArray imageData = file.readAll();
file.close();
QString response = QString("HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\nContent-Length: %1\r\n\r\n")
.arg(imageData.size());
clientSocket->write(response.toUtf8());
clientSocket->write(imageData);
clientSocket->disconnectFromHost();
}
// 服务器响应
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(int minBitStr, int maxBitStr) {
const QString possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~";
int length = QRandomGenerator::global()->bounded(minBitStr, maxBitStr); // 生成长度在minBitStr到maxBitStr之间
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;
}
// 哈希256 转 base64
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<QString, QString>& params, const QString& httpMethod, const QString& secret, const QString& request_id, const QString& timestamp) {
// 1. 按字典序排序参数
QList<QPair<QString, QString>> 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 = "1TEST_SL100_20240826SL100" + request_id + timestamp + FACTORY_ID;
QString baseString = QString::number(BATCH) + QString(LABEL) + QString(MODEL) + request_id + timestamp + QString(FACTORY_ID);
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", QByteArray(FACTORY_ID));
request.setRawHeader("label", QByteArray(LABEL));
request.setRawHeader("batch", QString::number(BATCH).toUtf8());
request.setRawHeader("model", QByteArray(MODEL));
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<QString, QString>& params, const QString& secret) {
QString request_id = generateRandomRequestID(1, 33);
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<QString, QString>& params, const QJsonObject& jsonData, const QString& secret) {
QString request_id = generateRandomRequestID(1, 33);
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<QString, QString> params = {
/*{"label", "TEST_SL100_20240826"},
{"model", "SL100"},
{"batch", "1"},*/
{"label", QStringLiteral(LABEL)},
{"model", QStringLiteral(MODEL)},
{"batch", QString::number(BATCH)},
{"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<QString, QString> 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<QString, QString> 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<QString, QString> params = {
{"id", "123456"},
{"location", "allMachine"}
};
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");
qint64 UTC_time = QDateTime::currentSecsSinceEpoch();
QMap<QString, QString> params = {
{"id", hardware_info},
{"key", license_info},
{"time", QString::number(UTC_time)}
};
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();
//frontBoardCmdConfigJson = readJson_frontCmd_config();
backBoardOneClickTest = readJson_backBoardOneClickTest();
backBoardTest = readJson_backBoardTest();
backBoardFuncConfig = readJson_backBoardFuncConfig();
backBoardDevInfoJson = readJson_backDevInfo();
backBoardUuidJson = readJson_backUuid();
//backBoardCmdConfigJson = readJson_backCmd_config();
factoryProductInfo = readJson_factoryProductInfo();
allBoardTest = readJson_allBoardTest();
allBoardFuncConfig = readJson_allBoardFuncConfig();
getPicJson = readJson_getPic();
getVideoJson = readJson_getVideo();
}
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) checkBoxState = true;
else checkBoxState = false;
}
void MainWidget::saveStatusListToFile(const QString& filePath)
{
QString actualFilePath = filePath;
if (actualFilePath.isEmpty()) {
QString defaultDirPath = QDir::currentPath() + "/TestLog";
QDir dir(defaultDirPath);
if (!dir.exists()) {
if (!dir.mkpath(defaultDirPath)) {
qWarning() << "Failed to create directory:" << defaultDirPath;
return;
}
}
QString currentTime = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss");
actualFilePath = defaultDirPath + "/" + currentTime + ".txt";
}
QFile file(actualFilePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qWarning() << "Failed to open file:" << actualFilePath;
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::onCheckSerialRecvStatus() {
}
void MainWidget::onStartTimeout(int clientId, int timeout)
{
//qDebug() << "---------------> onStartTimeout :" << clientId << "timeout :" << timeout;
if (clientId == -1) {
qDebug() << "---------------> onStartTimeout :" << clientId << "timeout :" << timeout;
/*if (timeout > 0) {
serialTimer->start(timeout);
}
else {
serialTimer->stop();
}*/
//serialPortHandler->OnStartTimeout(timeout);
}
else if (clientTimers.contains(clientId)) {
QTimer* timer = clientTimers[clientId];
if (timeout > 0) {
timer->start(timeout);
}
else {
timer->stop();
}
}
}
void MainWidget::scrollToBottom()
{
statusListWidget->scrollToBottom();
}
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)
//if (1)
{
QPushButton* button = qobject_cast<QPushButton*>(sender());
if (button) {
int index = button->property("licenseIndex").toInt();
currentIndex = index;
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") {
if (jsonObject["lable"].toString() == TOOL_UI.FRONT_GET_LICENSE_INFO) {
QString hwInfoText = licenseHwInfoEdit->toPlainText();
if ((hwInfoText.count("0x") != PIX_HARDWARE_INFO_BYTES) && (hwInfoText.count("0x") != 0)) {
isRequestSuccessful = 0;
//licenseHwInfoEdit->setPlainText("您使用了License去获取License这是不允许的!!!");
LicenseConfirmWindow dialog("您使用了License去获取License这是不允许的!!!");
dialog.exec();
return;
}
else if (hwInfoText.count("0x") == 0) {
isRequestSuccessful = 0;
//licenseHwInfoEdit->setPlainText("您使用了License去获取License这是不允许的!!!");
LicenseConfirmWindow dialog("没有检测到HWInfo无法获取License!!!");
dialog.exec();
return;
}
dataStr = hwInfoText.remove(",");
QString sendToHttpServerDataStr = dataStr.replace("0x", "").replace(" ", ""); // 去掉0x和空格
qDebug() << "sendToHttpServerDataStr:" << sendToHttpServerDataStr;
//return;
FactoryToolSendGetLicenseToHttpServer(sendToHttpServerDataStr);
while (isRequestSuccessful == 0) {
QCoreApplication::processEvents(); // 防止阻塞线程
}
qDebug() << "isRequestSuccessful:" << isRequestSuccessful;
if (isRequestSuccessful == 2) {
isRequestSuccessful = 0;
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;
isRequestSuccessful = 0;
return;
}
}
else if (licenseDataArray.contains("has")) {
qDebug() << "licenseDataArray[\"has\"].toBool():" << licenseDataArray["has"].toBool();
}
}
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("您确定要获取此授权吗?\n请确认您的hw_info是否正确并且电脑插好U盘");
if (dialog.exec() == QDialog::Accepted) {
#if !MANUAL_UPLOAD_LICENSE
if (!(licenseGenerate(hardware_info, license_info))) {
qDebug() << "从U盘获取License失败";
button->setStyleSheet("background-color: red;");
isRequestSuccessful = 0;
licenseHwInfoEdit->setPlainText("从U盘获取License失败,请检查U盘是否插入电脑!!!");
return;
}
QString licenseInfoHex = QByteArray(reinterpret_cast<char*>(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 };
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0xb8,0x86,0xd0,0x51,0xfe,0x6a,0x9e,0x58,0x52,0x4e,0xf2,0x9e,0x3e,0xfd,0x51,0x5a,0x67,0x77,0x09,0x67,0xc3,0x11,0xbd,0x12,0x8d,0x9d,0x50,0x67,0xb2,0x2c,0xcf,0xc2,0x18,0x8f,0x61,0x66,0x1b,0x43,0xfe,0x5e,0xba,0x2d,0x53,0xde,0x7c,0x9f,0x8f,0x78,0x1b,0x63,0xad,0xfb,0xe9,0xcc,0xac,0xc2,0xeb,0xcf,0xde,0xf9,0xaf,0x58,0xc3,0x89,0x24,0x29,0x39,0xd5,0x9f,0x5d,0xb2,0x4a,0xab,0x0c,0x30,0x7c,0x92,0x27,0xf6,0x48,0x1e,0x9e,0xf1,0x81,0x6d,0x4a,0xf6,0xae,0x1a,0x38,0xb8,0x68,0x59,0x5a,0x39,0xee,0xd6,0xd2,0xe4,0x62,0x6b,0x96,0x04,0x80,0x2d,0x3f,0x0c,0x7d,0x97,0xb2,0xb0,0x62,0xe1,0x0f,0x17,0xf0,0xef,0x1e,0xf3,0x6d,0xc3,0x4b,0x6c,0x4d,0x61,0xc8,0xde,0x1a};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0x60,0x0a,0xef,0xfb,0xdf,0xbd,0xf9,0x07,0x54,0x90,0x84,0x00,0xc1,0x43,0x10,0x76,0x3f,0xdd,0xf9,0xbc,0x75,0x54,0x7f,0x7d,0xa8,0xd0,0x68,0x55,0x56,0xac,0x93,0xe8,0x95,0xd9,0x86,0x3e,0x1e,0x03,0x67,0x5c,0x88,0xf9,0x3c,0xe5,0x8f,0x65,0xc2,0xe6,0x6f,0xde,0x3f,0x36,0x84,0xd5,0x7f,0x7e,0xa4,0xc3,0x15,0xa4,0xec,0x1e,0xb7,0xce,0x1b,0xcc,0x49,0x2f,0xa0,0x72,0x87,0x5b,0x76,0x5f,0xe2,0xa1,0x15,0x57,0xbf,0xd2,0xd9,0x30,0x6d,0x35,0xa6,0x68,0xb3,0x9a,0x59,0xe3,0x53,0x7d,0xc9,0xb3,0xc0,0x82,0xfc,0xa1,0xd6,0x10,0x0b,0x09,0x9b,0x2b,0xc7,0x70,0x84,0xdf,0x75,0x8c,0x58,0x05,0xe5,0xc6,0xdb,0x4a,0x71,0x72,0x18,0x5b,0x29,0x52,0xbc,0x47,0x22,0x86,0x6f,0xd2};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0xd9,0x51,0x6f,0x3e,0x03,0x96,0x25,0xea,0x18,0xa2,0xef,0xfc,0xea,0x1d,0x51,0xbe,0x16,0x22,0x7e,0x78,0x82,0x9f,0xe1,0x22,0xa1,0x69,0x3d,0x35,0x41,0xc7,0xef,0xbe,0x3e,0x9d,0x30,0x59,0xb9,0x12,0xc4,0xab,0xb9,0x85,0x9e,0x0e,0xd1,0x23,0x9b,0x6d,0xf0,0xb3,0xa8,0xc8,0x42,0x53,0xaa,0xfe,0x79,0x68,0x43,0x81,0x93,0xe5,0x28,0xdd,0x28,0x67,0x5e,0x42,0xa9,0xcf,0x13,0xdd,0xe9,0x3d,0xe1,0x24,0x3b,0xce,0xbb,0x93,0x63,0x81,0xd7,0x2b,0x7d,0x55,0xe6,0xfd,0x7f,0xd9,0x36,0x82,0xaf,0xa0,0x5d,0x92,0x8f,0x0d,0x55,0x2f,0x3f,0xe6,0xbd,0x61,0x65,0x8e,0x9f,0x90,0xf6,0x7f,0x79,0x81,0x0f,0x7b,0x2c,0x17,0x58,0x83,0xd9,0xb9,0x07,0x7b,0x7f,0x87,0x5d,0xca,0x2b,0x1e};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0x4d,0xf6,0xfb,0x4e,0x66,0x47,0xb6,0xff,0xbb,0xd6,0xff,0x21,0x44,0x17,0x72,0x30,0x12,0x3f,0x24,0x60,0x3d,0x83,0x80,0x63,0x82,0xf6,0x50,0xde,0x50,0x77,0x87,0xa5,0x96,0x82,0x7d,0xf7,0x90,0x37,0xf9,0x40,0xe1,0x09,0xfe,0xb2,0xe2,0x31,0xf9,0x05,0x1f,0x7d,0xa1,0x00,0xc6,0x6c,0x99,0x29,0xd5,0x09,0x00,0x5a,0xec,0x5c,0x2a,0x9d,0x58,0xbe,0x3e,0xcf,0xd2,0x72,0xcb,0x7d,0x07,0xb3,0x4f,0x3f,0x4d,0x79,0x17,0x4d,0x3a,0x4b,0x77,0x63,0xc9,0x1b,0xad,0x3a,0x22,0x90,0x6d,0x4b,0x82,0x63,0x48,0x88,0x47,0xc7,0xa9,0x98,0x6c,0x53,0x5d,0x83,0x68,0xb6,0xe5,0xfb,0x39,0x05,0x78,0x3f,0xde,0x19,0xfd,0x18,0xac,0x81,0x37,0x44,0xf2,0x08,0x45,0x4d,0xc6,0xf7,0xe4,0xeb};
unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0xf2,0x95,0x3b,0x4f,0xc6,0xc5,0x7d,0xff,0x28,0xa0,0xb3,0xe6,0xe2,0x46,0x9f,0xe0,0xff,0xa0,0x8a,0x08,0xc2,0xd6,0x0c,0x85,0x3f,0x0f,0xf3,0x73,0xe5,0x65,0x64,0x00,0x92,0x9d,0x33,0x53,0x55,0x9a,0xf6,0x79,0xcc,0xe1,0x07,0x35,0x0d,0x3d,0xf2,0xd7,0x1c,0x53,0x98,0x85,0x88,0xcc,0x98,0xd2,0x23,0x6b,0xcb,0x22,0x27,0x87,0x2e,0x53,0xc0,0x05,0x6b,0x0a,0xde,0x4c,0x27,0xaf,0x85,0xd1,0x95,0xe7,0xd0,0x79,0x10,0xb0,0xed,0x68,0xcb,0x0e,0xb8,0xf7,0x3e,0x93,0x68,0x2b,0x22,0x29,0xf8,0xc5,0xde,0x4e,0xa9,0x25,0xb7,0xe4,0xa1,0x79,0xa6,0x4b,0x1d,0xe5,0x59,0xcb,0xf5,0x92,0x26,0xd6,0x6c,0xa6,0x34,0xac,0x62,0x5b,0xe8,0xc3,0x3d,0xe8,0x50,0xa1,0x98,0x08,0xc2,0x22};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0xd9,0x45,0x32,0xf4,0x95,0xb6,0x6a,0x89,0xdb,0xcd,0x67,0x79,0xda,0x18,0xda,0x86,0x84,0x12,0x47,0x4f,0xd5,0x82,0x10,0xa3,0x06,0xed,0xfe,0x40,0x8e,0xa8,0x76,0x8b,0xa6,0x96,0xa5,0x94,0x7c,0xe5,0x48,0xbf,0xb7,0x26,0x4d,0x8c,0xe0,0x87,0xfb,0x92,0x90,0x33,0x47,0x71,0xf8,0xd5,0xc3,0x97,0x1f,0x51,0x27,0x9c,0xee,0x9d,0x7e,0xc7,0x02,0x0d,0x0e,0x4a,0x32,0x0e,0xce,0x14,0x03,0x20,0xee,0x92,0x6f,0x35,0x21,0x18,0x3a,0x53,0x66,0xa0,0x22,0x66,0xab,0x91,0x7d,0xad,0x2a,0x20,0x60,0x91,0x70,0x2d,0x0f,0x7d,0x45,0x90,0x73,0x9b,0x41,0x4c,0xca,0xe2,0xde,0x4c,0xdc,0x58,0xc4,0x46,0x1d,0xe6,0x0a,0x82,0x0e,0x7c,0x79,0x96,0x68,0x18,0xbf,0x9e,0x90,0xb3,0x97,0xa3};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0xe2,0xea,0xec,0x64,0xaa,0xac,0x06,0xb7,0x6e,0x8b,0x1a,0xbe,0x38,0x4a,0x75,0xdf,0xaf,0x51,0x95,0xbe,0x0f,0x8a,0x7b,0xb7,0x03,0x5b,0x14,0x17,0xf5,0x69,0x12,0x75,0xd2,0xd7,0x78,0x07,0x0f,0xc2,0xd6,0x89,0x28,0x1c,0xf4,0xa5,0x43,0x14,0x5e,0x5d,0xac,0x81,0x2e,0xc4,0xf7,0xc3,0x63,0x05,0x51,0x73,0x31,0x2c,0x1b,0x27,0x3f,0x37,0xce,0xe0,0x1b,0x4a,0x1b,0x3b,0x78,0x46,0x5d,0xe8,0x46,0xfd,0x67,0x60,0x94,0x51,0x18,0x11,0x24,0x75,0xe5,0xf9,0x37,0x85,0x7d,0x11,0xb1,0x1e,0x6e,0x32,0xce,0x2d,0x73,0x36,0x96,0xf0,0xfa,0xc8,0xf2,0x90,0xcd,0xa8,0x1e,0xf5,0x09,0xdb,0x6c,0xd4,0x98,0x9f,0x31,0x4b,0x03,0x3d,0xbc,0x04,0x60,0x10,0xcb,0x74,0xc4,0x13,0xbb,0x7c};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0x1a,0x93,0xe0,0x21,0xbd,0x3f,0xa6,0x5f,0xb4,0x96,0x28,0x38,0x69,0x9e,0xf4,0x09,0x66,0x8f,0x90,0x22,0xbb,0xa0,0x7c,0xfa,0x6d,0xc3,0xb6,0x6a,0xf6,0x71,0xa9,0xfc,0x1f,0x70,0x6a,0xc7,0xd3,0x66,0xbe,0xde,0x18,0x8b,0x2c,0xf2,0xf3,0x36,0xc8,0x9e,0xe6,0x7f,0x97,0xd6,0x54,0x28,0x17,0xac,0x27,0x47,0xa6,0xf6,0x9a,0x54,0xd1,0xd3,0x3c,0xd1,0xea,0x93,0x1e,0x43,0x65,0x4b,0xb6,0x3f,0xff,0x1f,0x7e,0xd1,0x65,0x6c,0x89,0x68,0x15,0xaf,0xd8,0x7e,0x22,0xaf,0x9c,0xdf,0xab,0xda,0x16,0xb1,0x32,0x96,0x1f,0xed,0x1e,0xcb,0xfd,0xac,0xba,0x4d,0xd1,0xc1,0xbf,0xef,0xb3,0xbf,0x4c,0x48,0x4c,0x56,0xc7,0xbf,0xa0,0x2c,0x6e,0xc8,0xd2,0xc9,0x4b,0xee,0x7b,0x09,0x30,0xd0};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0xe3,0x1d,0x65,0xdc,0xfe,0xcb,0x07,0xbc,0x4e,0xf4,0x73,0x01,0x43,0x28,0x23,0x70,0x66,0xbb,0x4e,0xe6,0xf7,0xcf,0x95,0x66,0xbd,0xfd,0x38,0x71,0x19,0x3c,0x78,0x6c,0x86,0xe0,0x20,0x9a,0x80,0x64,0xca,0x6d,0x1a,0x8b,0x04,0x81,0x62,0xd0,0x13,0x7b,0x37,0x62,0x8d,0xb5,0xec,0x64,0x4b,0x00,0xdb,0x6c,0xbd,0x53,0x20,0x5f,0x32,0x2e,0x1b,0xf4,0x04,0x95,0x78,0x51,0x77,0xe6,0xca,0x49,0x73,0x81,0xe1,0x6b,0x41,0x8e,0x6a,0x7a,0x07,0xcb,0xcc,0x68,0xb0,0x5f,0x29,0xc8,0x1d,0xa9,0x45,0x0d,0x4c,0x79,0x7e,0xfb,0x4c,0x6d,0x33,0x04,0x82,0xd6,0x18,0x6b,0xb1,0x67,0x52,0x9e,0x55,0x11,0x43,0x75,0xec,0x48,0x44,0xdc,0xcc,0x53,0x02,0xe6,0x21,0x75,0x67,0x4c,0xfe,0x4e};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0xb7,0xf8,0x7a,0x14,0x3e,0xa5,0x65,0x91,0xbe,0xc3,0xfd,0x92,0xba,0xd2,0xca,0x88,0xac,0x0f,0x09,0x34,0x94,0xfb,0x9a,0x44,0xdb,0x5d,0x1a,0x8b,0xeb,0xc9,0x45,0x2b,0xac,0x6d,0xf3,0xe9,0x68,0x0b,0x6f,0x9d,0x5f,0x9d,0x7b,0x6a,0x54,0xb5,0xa3,0x44,0x4f,0xa6,0x19,0x62,0xae,0xdd,0xd7,0x4b,0x31,0xdd,0x68,0x9f,0xaa,0x9f,0x14,0xa3,0x4a,0x55,0x2f,0x0f,0x0a,0x23,0x28,0xbb,0x83,0x72,0xc6,0xf8,0xd4,0xdd,0xc8,0x99,0xd2,0x39,0x2a,0x10,0x29,0x3f,0xb8,0x77,0x61,0x0d,0xe4,0x3e,0x5f,0x86,0x47,0x26,0x82,0x5f,0x13,0x9e,0x3b,0x01,0xcc,0x0f,0xad,0xc2,0xf1,0x9e,0x1e,0x46,0x8e,0x2d,0xfe,0x41,0xc3,0x98,0x0a,0xf7,0xac,0x96,0x76,0x74,0x21,0x24,0x8e,0x1d,0x93,0xc4};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0xac,0x4a,0xc2,0x0b,0x85,0xaa,0x5c,0x07,0x57,0x0a,0xa6,0xbb,0x0c,0xac,0xdb,0x5e,0x03,0x30,0x54,0xba,0x0b,0x3a,0xb8,0x53,0xe0,0xb4,0x0b,0x43,0x28,0x02,0xfb,0xb8,0x8c,0xd9,0xfc,0x00,0xd2,0x10,0x53,0x8b,0x9f,0x3f,0xa4,0x54,0x2e,0x02,0x82,0x93,0x09,0x66,0xfb,0x54,0xa8,0xe7,0x0b,0x4f,0xf2,0x1c,0x4f,0xf8,0x99,0x8e,0x65,0xa2,0xc4,0x43,0xc2,0x99,0x30,0xa8,0xde,0x8b,0x74,0x26,0xcd,0x40,0xd8,0xad,0x60,0x67,0x65,0x7c,0xcc,0x23,0x68,0x3a,0x0b,0xc3,0x84,0x9c,0xf5,0x29,0x27,0xed,0x4b,0xac,0x26,0x8d,0xc7,0x20,0x12,0x4b,0x39,0x2b,0x06,0xc2,0x7a,0x1c,0x90,0x20,0xc4,0x8c,0xe6,0x89,0x85,0xed,0x63,0xf8,0xc1,0xf9,0x46,0x94,0x14,0x77,0x1c,0xa8,0x9f,0xe3};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0xe9,0x69,0x3b,0x49,0xa5,0x3c,0x59,0x39,0x63,0xe8,0x5c,0x1a,0x71,0xca,0xe7,0xb2,0xfa,0x5a,0x12,0x2e,0xbd,0x03,0xc8,0x32,0x22,0x2f,0xe5,0x03,0xa0,0xfb,0xd9,0x2e,0x80,0xdb,0xca,0x06,0x26,0x19,0xca,0x5d,0xfb,0x4e,0x5b,0xf4,0xc3,0xeb,0x92,0x70,0x26,0x8e,0xd1,0xc3,0xe0,0x34,0x94,0x89,0xc6,0x8f,0xa1,0xb1,0x31,0x4f,0xee,0x84,0x7a,0x08,0x5c,0x2d,0x92,0x43,0x18,0x0e,0xc0,0xe9,0xa8,0x75,0x02,0x60,0x87,0x0e,0x5e,0x66,0x3e,0xc8,0x82,0x63,0x1b,0xff,0x22,0x8e,0xdb,0xd0,0x16,0xfc,0x7a,0xd6,0x1c,0xee,0xf3,0xb8,0xef,0xfe,0xc1,0x6d,0xa0,0x72,0x91,0xda,0x78,0x60,0x45,0xe5,0x83,0xf0,0x53,0x07,0xee,0xa5,0xfc,0xda,0xd2,0xed,0x92,0x53,0x17,0x92,0x70,0x79};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0x62,0x8e,0x87,0xbe,0x6c,0x3f,0xf7,0x88,0x32,0xa4,0x6a,0x79,0x67,0xd7,0x27,0xbb,0x19,0x46,0xbb,0x44,0x7f,0x24,0x34,0x84,0x66,0x25,0x7e,0x2c,0x84,0x34,0x84,0x77,0xf1,0xe4,0xa0,0x9c,0x81,0x0a,0x22,0x99,0x40,0x1d,0x4e,0x62,0x62,0xac,0x51,0x35,0xd9,0xd4,0x0e,0xd1,0x10,0x28,0xb8,0x5d,0x92,0xaf,0xfa,0xf5,0x26,0xc6,0x57,0xab,0x64,0xda,0xbf,0x0b,0x3f,0x19,0x70,0xa7,0x19,0x12,0x3a,0xad,0x3c,0x85,0xd2,0x97,0x5e,0xe8,0x14,0x3c,0xef,0xaa,0xf5,0x61,0xb2,0x3f,0x23,0x80,0xd9,0xf9,0x86,0x19,0xc8,0x8a,0x7c,0x34,0xee,0xa1,0xa0,0xcf,0x39,0x9c,0x4c,0xf2,0x94,0xf7,0x6f,0x07,0x62,0xdd,0x7a,0xb4,0x1b,0x06,0x76,0x2f,0x2b,0xe9,0x89,0xf5,0xda,0xe0,0x6a,0xd6};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0x77,0x7d,0x12,0xca,0x57,0x73,0x60,0x13,0xe8,0xcb,0xa7,0xe8,0x3b,0xf1,0x6b,0x2c,0xca,0xd4,0x6d,0x32,0x07,0x4f,0xd8,0x1e,0x0d,0x3d,0xe1,0xe1,0x1d,0x72,0x02,0xaf,0xd5,0xdc,0x4c,0x2b,0xef,0x89,0xbc,0xe4,0x5f,0x7e,0x12,0x94,0x4b,0xc0,0x21,0x5d,0xe3,0xc8,0x82,0xcf,0x64,0x72,0x80,0x1b,0xfc,0x2e,0x1f,0xab,0x0d,0x02,0x58,0xc0,0x07,0xb3,0x31,0xbf,0x5a,0x49,0x6a,0xb3,0xbb,0x8c,0x08,0x29,0x75,0x05,0x35,0x16,0xfb,0xd7,0x40,0xb2,0xc4,0xa7,0xd9,0xc4,0x35,0x79,0xe2,0x63,0xb1,0xde,0x5a,0x2d,0x5a,0xab,0xb7,0x85,0x46,0x2d,0x0b,0x6d,0xae,0x31,0x3e,0x3c,0xab,0x52,0xeb,0x73,0x5b,0xec,0xac,0x53,0x8b,0xf0,0xb6,0x16,0x07,0x65,0x88,0x10,0x7a,0xde,0x4a,0x52};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0x1a,0x95,0xba,0x59,0x4e,0x84,0xd3,0x94,0x8e,0xad,0xda,0x99,0xe9,0x1e,0x76,0xa9,0x56,0x1c,0x2b,0x6e,0xcf,0x91,0xe7,0x0d,0xd5,0x8c,0xff,0xfa,0x2a,0x7c,0xac,0x4b,0xea,0x63,0x7b,0x6e,0x56,0x7f,0xf8,0xc0,0x45,0x60,0x87,0xf4,0xda,0x3d,0x2a,0xa5,0xd7,0xb0,0xa2,0xd7,0x1c,0x9e,0xe6,0x08,0xb9,0x09,0xea,0xfd,0xf1,0xe0,0x4c,0x8b,0xca,0x21,0x70,0x2e,0x13,0x14,0xae,0x6f,0x66,0xb7,0x65,0xde,0x74,0x55,0xca,0x9c,0xc6,0x37,0x8d,0x73,0xd6,0x13,0x2b,0x6f,0xf5,0xb8,0x72,0x35,0x88,0x87,0x4d,0x19,0x85,0x88,0x6e,0x34,0xbc,0x95,0xab,0xc1,0x06,0x37,0x2e,0xc4,0xba,0x67,0x49,0xaf,0x27,0x27,0x18,0x9e,0x21,0x20,0x5f,0x92,0xb7,0x57,0x6f,0x36,0x40,0xe9,0xa8,0xce};
//unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0xa9,0x6b,0xba,0x4a,0x69,0x4d,0xdd,0xd7,0xd8,0x3d,0x00,0xf0,0xbb,0x73,0xb6,0xb9,0x46,0x67,0x84,0xae,0xe9,0x61,0xf1,0x35,0xd6,0x23,0xf5,0x3d,0x52,0x49,0xfe,0x67,0x65,0x96,0x0f,0x6d,0xc5,0xf6,0xb0,0xc9,0x81,0x7c,0x98,0xf4,0x6e,0x71,0xf4,0x39,0x99,0x7c,0x78,0x7a,0x98,0x6c,0x14,0x78,0xd7,0xd0,0xa3,0x48,0xcf,0x8f,0x1c,0x48,0x43,0x34,0x74,0x7f,0x60,0xcb,0x4d,0x4a,0xb0,0x2c,0x32,0xa3,0x74,0x6a,0x7e,0xcc,0x44,0x29,0x86,0xde,0x7c,0x91,0x38,0x11,0x83,0x31,0xca,0xd0,0xe5,0x65,0x22,0xc5,0xac,0xeb,0x86,0xdd,0x84,0x08,0x8c,0xf1,0x12,0xba,0x48,0xb3,0x96,0x15,0x20,0x02,0x7c,0x33,0xf2,0x26,0x09,0x9a,0x17,0x1d,0xdd,0x7d,0x21,0xaa,0x3a,0xb3,0xe2,0xba};
QString licenseInfoHex = QByteArray(reinterpret_cast<char*>(license_info_1), PIX_LICENCE_BYTES).toHex().toUpper();
#endif
qDebug() << "上报服务器 licenseInfoHex:" << licenseInfoHex;
// License上报服务器
FactoryToolSendPostLicenseToHttpServer(sendToHttpServerDataStr, licenseInfoHex);
button->setStyleSheet("background-color: green;");
QString licenseInfoStr;
printf("U盘 Get License is\n");
for (int j = 0; j < PIX_LICENCE_BYTES; ++j) {
#if !MANUAL_UPLOAD_LICENSE
printf("0x%02x, ", license_info[j]);
licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info[j]));
#else
printf("0x%02x, ", license_info_1[j]);
licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info_1[j]));
#endif
}
printf("\n");
licenseHwInfoEdit->setPlainText(licenseInfoStr);
isRequestSuccessful = 0;
}
}
else {
//if (jsonObject["lable"].toString() == "write_license") {
if (jsonObject["lable"].toString() == TOOL_UI.FRONT_WR_LICENSE_INFO) {
QString licenseInfoText = licenseHwInfoEdit->toPlainText();
qDebug() << "licenseInfoText:" << licenseInfoText;
dataStr = licenseInfoText.remove(",");
dataStr = dataStr.replace("0x", "").replace(" ", "");
QByteArray dataByteArray = QByteArray::fromHex(dataStr.toUtf8());
memcpy(license_info, dataByteArray.data(), qMin(dataByteArray.size(), PIX_LICENCE_BYTES));
QString licenseInfoStr;
for (int j = 0; j < PIX_LICENCE_BYTES; ++j) {
licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info[j]));
}
dataStr = QByteArray(reinterpret_cast<char*>(license_info), PIX_LICENCE_BYTES).toHex();
qDebug() << "license_info:" << dataStr;
dataStr = dataByteArray.toBase64();
qDebug() << "Base64 Encoded:" << dataStr;
}
/*for (ClientHandler* handler : clients) {
handler->sendLicenseItem(index, dataStr);
}*/
//sendLicenseData(index, dataStr);
serialPortHandler->sendLicenseItem(index, dataStr);
QList<QPushButton*> buttons = findChildren<QPushButton*>();
int licenseIndex_cnt = 0;
for (QPushButton* btn : buttons) {
if (btn->property("licenseIndex").isValid()) {
if (btn->property("licenseIndex").isValid()) {
btn->setStyleSheet("");
}
licenseIndex_cnt++;
if (licenseIndex_cnt >= 3) break;
}
}
}
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString(TOOL_UI.NO_DEV_CONNECT), statusListWidget);
listItem->setBackground(Qt::red);
QPushButton* button = qobject_cast<QPushButton*>(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();
if ((hwInfoText.count("0x") != PIX_HARDWARE_INFO_BYTES) && (hwInfoText.count("0x") != 0)) {
isRequestSuccessful = 0;
//licenseHwInfoEdit->setPlainText("您使用了License去获取License这是不允许的!!!");
LicenseConfirmWindow dialog("您使用了License去获取License这是不允许的!!!");
dialog.exec();
return;
}
else if (hwInfoText.count("0x") == 0) {
isRequestSuccessful = 0;
//licenseHwInfoEdit->setPlainText("您使用了License去获取License这是不允许的!!!");
LicenseConfirmWindow dialog("没有检测到HWInfo无法获取License!!!");
dialog.exec();
return;
}
dataStr = hwInfoText.remove(",");
QString sendToHttpServerDataStr = dataStr.replace("0x", "").replace(" ", ""); // 去掉0x和空格
qDebug() << "sendToHttpServerDataStr:" << sendToHttpServerDataStr;
FactoryToolSendGetLicenseToHttpServer(sendToHttpServerDataStr);
while (isRequestSuccessful == 0) {
QCoreApplication::processEvents(); // 防止阻塞线程
}
qDebug() << "isRequestSuccessful:" << isRequestSuccessful;
if (isRequestSuccessful == 2) {
isRequestSuccessful = 0;
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;
isRequestSuccessful = 0;
return;
}
}
else if (licenseDataArray.contains("has")) {
qDebug() << "licenseDataArray[\"has\"].toBool():" << licenseDataArray["has"].toBool();
}
}
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("你确定要获取此授权吗?\n请确认你的hw_info是否正确");
if (dialog.exec() == QDialog::Accepted) {
#if !MANUAL_UPLOAD_LICENSE
if (!(licenseGenerate(hardware_info, license_info))) {
qDebug() << "从U盘获取License失败";
isRequestSuccessful = 0;
licenseHwInfoEdit->setPlainText("从U盘获取License失败,请检查U盘是否插入电脑!!!");
return;
}
QString licenseInfoHex = QByteArray(reinterpret_cast<char*>(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 };
unsigned char license_info_1[PIX_LICENCE_BYTES] = { 0x6a, 0x70, 0xc0, 0x40, 0xc9, 0x20, 0xf5, 0xd2, 0x78, 0xac, 0x05, 0x80, 0xa6, 0xcf, 0x3f, 0xd5, 0x72, 0xf6, 0xc3, 0x82, 0x11, 0x0d, 0x56, 0x37, 0xb3, 0x87, 0x19, 0x13, 0x79, 0xa5, 0x9b, 0x37, 0xf2, 0xab, 0xcb, 0xa3, 0xea, 0xc4, 0x45, 0xc6, 0xae, 0xc4, 0xa4, 0x72, 0xe9, 0x36, 0x1e, 0xbe, 0x78, 0xd6, 0xcd, 0x85, 0xd, 0x63, 0x93, 0x7a, 0x84, 0x9a, 0x31, 0x99, 0xe1, 0x09, 0xc1, 0xfa, 0xbe, 0x32, 0x42, 0xc5, 0xc9, 0x89, 0x03, 0x7e, 0x81, 0xe5, 0x25, 0xf, 0x4d, 0x68, 0x9d, 0x53, 0xd1, 0x04, 0x29, 0x34, 0x53, 0x09, 0x22, 0x5, 0x29, 0xce, 0xb1, 0xc9, 0x01, 0xed, 0x2a, 0xd2, 0x16, 0xfb, 0x3c, 0x27, 0xba, 0x4a, 0x69, 0x10, 0x3a, 0x54, 0x5a, 0x8f, 0xca, 0x47, 0x8d, 0x34, 0x2b, 0x57, 0xad, 0x27, 0x9a, 0x15, 0x37, 0x86, 0x60, 0xd6, 0x34, 0xd8, 0x32, 0xee, 0x9c, 0x46 };
QString licenseInfoHex = QByteArray(reinterpret_cast<char*>(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) {
#if !MANUAL_UPLOAD_LICENSE
printf("0x%02x, ", license_info[j]);
licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info[j]));
#else
printf("0x%02x, ", license_info_1[j]);
licenseInfoStr.append(QString::asprintf("0x%02x, ", license_info_1[j]));
#endif
}
printf("\n");
licenseHwInfoEdit->setPlainText(licenseInfoStr);
isRequestSuccessful = 0;
}
}
}
}
}
}
void MainWidget::onUuidButtonClicked()
{
if (connectedClientsCount)
{
QPushButton* button = qobject_cast<QPushButton*>(sender());
if (button) {
int index = button->property("UuidIndex").toInt();
if (index >= 0 && index < backBoardUuidJson.size()) {
QJsonObject jsonObject = backBoardUuidJson[index].toObject();
QString dataStr = "";
//if (jsonObject["lable"].toString() == "get_UUID_SN") {
if (jsonObject["lable"].toString() == TOOL_UI.BACK_GET_UUIDSN) {
QString sendToHttpServerDataStr = UuidHwInfoEdit->toPlainText();
cur_mac_addr = sendToHttpServerDataStr;
qDebug() << "sendToHttpServerDataStr:" << sendToHttpServerDataStr;
// 测试随机生成8-12位字符串
// sendToHttpServerDataStr = generateRandomRequestID(8, 13);
FactoryToolSendGetUuidToHttpServer(sendToHttpServerDataStr);
while (isRequestSuccessful == 0) {
QCoreApplication::processEvents(); // 防止阻塞UI线程
}
qDebug() << "isRequestSuccessful:" << isRequestSuccessful;
if (isRequestSuccessful == 2) {
UuidHwInfoEdit->setPlainText("服务器没有回复UUID和SN !!!");
isRequestSuccessful = 0;
return;
}
else if (isRequestSuccessful == 1) {
if (licenseDataArray.contains("uuid") && licenseDataArray.contains("sn")) {
QString backBoardUuid = licenseDataArray["uuid"].toString();
QString backBoardSn = licenseDataArray["sn"].toString();
QString displayText = QString("UUID:\n%1\nSN:\n%2").arg(backBoardUuid).arg(backBoardSn);
UuidHwInfoEdit->setPlainText(displayText);
qDebug() << "HTTP Server backBoardUuid is:" << backBoardUuid;
qDebug() << "HTTP Server backBoardSn is:" << backBoardSn;
isRequestSuccessful = 0;
return;
}
else {
qDebug() << "The UUID and SN are not found from the HTTP server!!!";
UuidHwInfoEdit->setPlainText("服务器没有回复UUID和SN !!!");
isRequestSuccessful = 0;
return;
}
}
}
else {
QString backBoardUuid = "";
QString backBoardSn = "";
//if (jsonObject["lable"].toString() == "write_UUID_SN") {
if (jsonObject["lable"].toString() == TOOL_UI.BACK_WR_UUID_SN) {
QString UUIDAndSNInfoText = UuidHwInfoEdit->toPlainText();
QStringList lines = UUIDAndSNInfoText.split("\n");
bool isUuidSection = false;
bool isSnSection = false;
for (const QString& line : lines) {
QString trimmedLine = line.trimmed();
if (trimmedLine == "UUID:") {
isUuidSection = true;
isSnSection = false;
continue;
}
if (trimmedLine == "SN:") {
isUuidSection = false;
isSnSection = true;
continue;
}
if (isUuidSection) {
if (!backBoardUuid.isEmpty()) {
backBoardUuid += "\n";
}
backBoardUuid += trimmedLine;
}
if (isSnSection) {
if (!backBoardSn.isEmpty()) {
backBoardSn += "\n";
}
backBoardSn += trimmedLine;
}
}
qDebug() << "UuidHwInfoEdit backBoardUuid is:" << backBoardUuid;
qDebug() << "UuidHwInfoEdit backBoardSn is:" << backBoardSn;
cur_UUID = backBoardUuid;
}
//else if (jsonObject["lable"].toString() == "Confirm_burn") {
else if (jsonObject["lable"].toString() == TOOL_UI.BACK_CONFIRM_BURN) {
// 添加长度限制
if ((cur_mac_addr != "") && (cur_mac_addr.size() == BACK_MAC_ADDRESS_LEN) && (cur_UUID != "")) {
FactoryToolSendPostComfirmToHttpServer(cur_mac_addr, cur_UUID);
while (isRequestSuccessful == 0) {
QCoreApplication::processEvents(); // 防止阻塞UI线程
}
qDebug() << "isRequestSuccessful:" << isRequestSuccessful;
if (isRequestSuccessful == 2) {
UuidHwInfoEdit->setPlainText("服务器回复false,请重试!!!");
}
else if (isRequestSuccessful == 1) {
UuidHwInfoEdit->setPlainText("服务器已确认!!!");
}
isRequestSuccessful = 0;
}
else {
qDebug() << "cur_mac_addr:" << cur_mac_addr;
qDebug() << "cur_UUID:" << cur_UUID;
qDebug() << "cur_UUID or cur_mac_addr are empty!";
UuidHwInfoEdit->setPlainText("MAC_addr 或 UUID 是空的,请先获取再进行确认!!!");
}
return;
}
qDebug() << "onUuidButtonClicked index:" << index;
for (ClientHandler* handler : clients) {
handler->sendUuidItem(index, backBoardUuid, backBoardSn);
}
}
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString(TOOL_UI.NO_DEV_CONNECT), statusListWidget);
listItem->setBackground(Qt::red);
}
}
void MainWidget::startMdnsService(char* select_ip) {
// "SL100-FactoryTool-Mdns"
// "_myservice._tcp.local."
const char* hostname = TOOL_UI.MDNS_HOSE_NAME.toUtf8().constData();
const char* service_name = TOOL_UI.MDNS_SERVICE_NAME.toUtf8().constData();
int service_port = TOOL_UI.TCP_CONNECT_PORT;
// 如果线程已经存在且正在运行,先停止
if (mdnsThread && mdnsThread->isRunning()) {
qDebug() << "Stopping previous mDNS service thread...";
mdnsThread->stop();
mdnsThread->quit();
mdnsThread->wait();
delete mdnsThread;
}
// 创建新的线程并启动
mdnsThread = new MdnsServiceThread(hostname, service_name, service_port, select_ip, this);
connect(mdnsThread, &QThread::finished, mdnsThread, &QObject::deleteLater); // 确保线程资源释放
mdnsThread->start();
}
void MainWidget::stopMdnsService() {
if (mdnsThread) {
qDebug() << "Stopping mDNS service...";
mdnsThread->stop(); // 通知线程退出
if (mdnsThread->isRunning()) {
mdnsThread->quit(); // 退出线程事件循环
mdnsThread->wait(); // 等待线程完全退出
}
delete mdnsThread; // 释放线程资源
mdnsThread = nullptr;
qDebug() << "mDNS service stopped.";
}
else {
qDebug() << "mDNS service is not running.";
}
}
// 处理开始服务器按键点击事件
void MainWidget::onStartServerClicked()
{
if (!server->isListening()) {
//getSelectedIp();
startMdnsService(getSelectedIp());
#if TEST_UDP_BROADCAST
sendMulticastMessage();
#endif
// QHostAddress specifiedIpAddress("10.10.10.253");
quint16 specifiedPort = TOOL_UI.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 ((clientId == 0) && (isBackBoardOrAllBoard)) {
clientId = isBackBoardOrAllBoard;
}
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<QPushButton*>(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) {
if (handler->getClientId() == handler->controlClientId) {
handler->sendGetDevInfoItem(itemIndex);
break;
}
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString(TOOL_UI.NO_DEV_CONNECT), statusListWidget);
listItem->setBackground(Qt::red);
}
}
// 处理发送取图按键点击事件
void MainWidget::onSendGetPicClicked()
{
if (connectedClientsCount) {
QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("getPicIndex").toInt();
if (itemIndex < 2) {
button->setStyleSheet("background-color: green;");
lastClickedGetPicCamIndex = itemIndex;
serialPortHandler->sendGetPicItem(0, lastClickedGetPicCamIndex);
//qDebug() << "---------- 取图 ---------";
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString(TOOL_UI.NO_DEV_CONNECT), statusListWidget);
listItem->setBackground(Qt::red);
}
}
// 处理发送拉视频流按键点击事件
void MainWidget::onSendGetVideoClicked()
{
if (connectedClientsCount) {
QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = -1;
if (button) {
if (button->property(FRONT_BOARD_VIDEO_BUTTON_INDEX_PROPERTY).isValid()) {
itemIndex = button->property(FRONT_BOARD_VIDEO_BUTTON_INDEX_PROPERTY).toInt();
if (itemIndex < 4) {
if (lastClickedGetVideoCamIndex != -1 && lastClickedGetVideoCamIndex == itemIndex) {
getVideoButtons[lastClickedGetVideoCamIndex]->setStyleSheet("");
serialPortHandler->sendGetVideoItem(1, lastClickedGetVideoCamIndex);
lastClickedGetVideoCamIndex = -1;
getVideoButtons[FOCUS_WINDOWS_BUTTON]->setEnabled(false);
//qDebug() << "---------- 关闭视频 ---------";
}
else {
if(lastClickedGetVideoCamIndex != -1)
getVideoButtons[lastClickedGetVideoCamIndex]->setStyleSheet("");
button->setStyleSheet("background-color: green;");
lastClickedGetVideoCamIndex = itemIndex;
serialPortHandler->sendGetVideoItem(0, lastClickedGetVideoCamIndex);
getVideoButtons[FOCUS_WINDOWS_BUTTON]->setEnabled(true);
//qDebug() << "---------- 打开视频 ---------";
}
}
}
else if (button->property(BACK_BOARD_VIDEO_BUTTON_INDEX_PROPERTY).isValid()) {
itemIndex = button->property(BACK_BOARD_VIDEO_BUTTON_INDEX_PROPERTY).toInt();
if (itemIndex < 4) {
if (lastClickedGetVideoCamIndex != -1 && lastClickedGetVideoCamIndex == itemIndex) {
getBackVideoButtons[lastClickedGetVideoCamIndex]->setStyleSheet("");
for (ClientHandler* handler : clients) {
if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) {
qDebug() << "lens number:" << lastClickedGetVideoCamIndex;
handler->sendGetVideoItem(1, lastClickedGetVideoCamIndex);
break;
}
}
lastClickedGetVideoCamIndex = -1;
getBackVideoButtons[FOCUS_WINDOWS_BUTTON]->setEnabled(false);
//qDebug() << "---------- 关闭视频 ---------";
}
else {
if (lastClickedGetVideoCamIndex != -1)
getBackVideoButtons[lastClickedGetVideoCamIndex]->setStyleSheet("");
button->setStyleSheet("background-color: green;");
lastClickedGetVideoCamIndex = itemIndex;
serialPortHandler->sendGetVideoItem(0, lastClickedGetVideoCamIndex);
for (ClientHandler* handler : clients) {
if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) {
qDebug() << "lens number:" << lastClickedGetVideoCamIndex;
handler->sendGetVideoItem(0, lastClickedGetVideoCamIndex);
break;
}
}
getBackVideoButtons[FOCUS_WINDOWS_BUTTON]->setEnabled(true);
//qDebug() << "---------- 打开视频 ---------";
}
}
}
else if (button->property(ALL_BOARD_VIDEO_BUTTON_INDEX_PROPERTY).isValid()) {
itemIndex = button->property(ALL_BOARD_VIDEO_BUTTON_INDEX_PROPERTY).toInt();
if (itemIndex < 4) {
if (lastClickedGetVideoCamIndex != -1 && lastClickedGetVideoCamIndex == itemIndex) {
getAllVideoButtons[lastClickedGetVideoCamIndex]->setStyleSheet("");
for (ClientHandler* handler : clients) {
if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) {
qDebug() << "lens number:" << lastClickedGetVideoCamIndex;
handler->sendGetVideoItem(1, lastClickedGetVideoCamIndex);
break;
}
}
lastClickedGetVideoCamIndex = -1;
getAllVideoButtons[FOCUS_WINDOWS_BUTTON]->setEnabled(false);
//qDebug() << "---------- 关闭视频 ---------";
}
else {
if (lastClickedGetVideoCamIndex != -1)
getAllVideoButtons[lastClickedGetVideoCamIndex]->setStyleSheet("");
button->setStyleSheet("background-color: green;");
lastClickedGetVideoCamIndex = itemIndex;
serialPortHandler->sendGetVideoItem(0, lastClickedGetVideoCamIndex);
for (ClientHandler* handler : clients) {
if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) {
qDebug() << "lens number:" << lastClickedGetVideoCamIndex;
handler->sendGetVideoItem(0, lastClickedGetVideoCamIndex);
break;
}
}
getAllVideoButtons[FOCUS_WINDOWS_BUTTON]->setEnabled(true);
//qDebug() << "---------- 打开视频 ---------";
}
}
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString(TOOL_UI.NO_DEV_CONNECT), statusListWidget);
listItem->setBackground(Qt::red);
}
}
void MainWidget::onOpenFocusWindowClicked()
{
QPushButton* button = qobject_cast<QPushButton*>(sender());
if (button) {
int itemIndex = button->property("getVideoIndex").toInt();
qDebug() << "New Button clicked with itemIndex:" << itemIndex;
if (itemIndex == FOCUS_WINDOWS_BUTTON) {
if (isBackBoardOrAllBoard) {
for (ClientHandler* handler : clients) {
if (handler->getClientId() == handler->preVideoClientId) {
DataHandler* dataHandler = dataHandlers[handler->getClientId()];
if (dataHandler) {
dataHandler->handleOpenFocusWindow(itemIndex);
break;
}
}
}
}
else {
emit openFocusWindow(itemIndex);
//SerialDataHandler->handleOpenFocusWindow(itemIndex);
}
}
}
}
// 处理一键发送按键点击事件
void MainWidget::onSendAllClicked()
{
qDebug() << "Current connectedClientsCount:" << connectedClientsCount;
if (connectedClientsCount) {
QMutexLocker locker(&mutex);
isSendingAll = !isSendingAll;
if (isSendingAll) {
sendAllButton->setText("一键功能测试中...\n再次点击取消");
sendAllButton->setStyleSheet("background-color: green;");
manualSend = true;
if (isBackBoardOrAllBoard) {
for (ClientHandler* handler : clients) {
// 重置索引
handler->resetCurrentItemIndex();
handler->sendNextItem(backBoardOneClickTest);
break;
}
}
else {
// 重置索引
serialPortHandler->resetCurrentItemIndex();
serialPortHandler->sendNextItem(frontBoardOneClickTest);
}
}
else {
sendAllButton->setText("一键功能测试");
sendAllButton->setStyleSheet("background-color: white;");
manualSend = false;
if (isBackBoardOrAllBoard) {
for (ClientHandler* handler : clients) {
handler->resetCurrentItemIndex();
}
}
else {
serialPortHandler->resetCurrentItemIndex();
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString(TOOL_UI.NO_DEV_CONNECT), statusListWidget);
listItem->setBackground(Qt::red);
}
}
int readBmpFile(const QString& filePath) {
QFile file(filePath);
if (file.open(QIODevice::ReadOnly)) {
BMPHeader header;
file.read(reinterpret_cast<char*>(&header), sizeof(header));
// 确保是 BMP 文件
if (header.bfType[0] == 'B' && header.bfType[1] == 'M') {
qDebug() << "Width :" << header.biWidth;
qDebug() << "Height :" << header.biHeight;
qDebug() << "Bit Count:" << header.biBitCount;
return header.biBitCount;
}
else
return -1;
}
}
// 处理单独发送功能项按键点击事件
void MainWidget::onSendFrontFuncItemClicked()
{
if (connectedClientsCount) {
QByteArray bmpData;
QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("frontBoardFuncConfig").toInt();
if (itemIndex >= 0 && itemIndex < frontBoardFuncConfig.size()) {
QJsonObject jsonObject = frontBoardFuncConfig[itemIndex].toObject();
qDebug() << "----------------------------- " << jsonObject["cmd"].toString();
if (jsonObject["cmd"].toString() == "UPDATE_LOGO") {
// **使用非阻塞模式**
QFileDialog* fileDialog = new QFileDialog(this);
fileDialog->setWindowTitle("选择图片");
fileDialog->setDirectory(QDir::currentPath());
fileDialog->setNameFilter("BMP Files (*.bmp);;All Files (*)");
fileDialog->setFileMode(QFileDialog::ExistingFile);
// **当用户选择文件后,调用 lambda 处理逻辑**
connect(fileDialog, &QFileDialog::fileSelected, this, [=](const QString& bmpFilePath) {
if (bmpFilePath.isEmpty()) {
qDebug() << "No image selected.";
return;
}
if (readBmpFile(bmpFilePath) < 16) {
onHandleInvalidOperate("请选择大于16位深度的bmp图片");
return;
}
QByteArray bmpData;
QFile file(bmpFilePath);
if (file.open(QIODevice::ReadOnly)) {
bmpData = file.readAll();
file.close();
qDebug() << "读取 BMP 文件成功:" << bmpFilePath;
}
else {
qWarning() << "无法打开 BMP 文件:" << bmpFilePath;
return;
}
if (isReplyOrTimeout) {
QString text = frontFuncConfigLineEdit->text();
qDebug() << "Text in frontFuncConfigLineEdit:" << text;
if (bmpData.isEmpty())
qDebug() << "bmpData.isEmpty()----->1";
else
qDebug() << "bmpData.isEmpty()----->0";
serialPortHandler->sendFrontFuncItem(itemIndex, text, bmpData);
isReplyOrTimeout = false;
}
});
// **显示对话框(非阻塞)**
fileDialog->open();
}
else if (isReplyOrTimeout) {
QString text = frontFuncConfigLineEdit->text();
qDebug() << "Text in frontFuncConfigLineEdit:" << text;
serialPortHandler->sendFrontFuncItem(itemIndex, text, "");
isReplyOrTimeout = false;
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString(TOOL_UI.NO_DEV_CONNECT), statusListWidget);
listItem->setBackground(Qt::red);
}
}
void MainWidget::onSendBackFuncItemClicked()
{
if (connectedClientsCount) {
QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("backBoardFuncConfig").toInt();
for (ClientHandler* handler : clients) {
if (isReplyOrTimeout && ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId))) {
QString text = backFuncConfigLineEdit->text();
qDebug() << "Text in backFuncConfigLineEdit:" << text;
handler->sendBackFuncItem(itemIndex, text);
isReplyOrTimeout = false;
break;
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString(TOOL_UI.NO_DEV_CONNECT), statusListWidget);
listItem->setBackground(Qt::red);
}
}
// 处理单独发送项按键点击事件
void MainWidget::onSendFrontItemClicked()
{
qDebug() << "onSendFrontItemClicked isReplyOrTimeout = " << isReplyOrTimeout;
if (connectedClientsCount) {
QByteArray bmpData;
QPushButton* button = qobject_cast<QPushButton*>(sender());
button->setStyleSheet("background-color: green;");
int itemIndex = button->property("frontBoardTest").toInt();
if (itemIndex >= 0 && itemIndex < frontBoardTest.size()) {
QJsonObject jsonObject = frontBoardTest[itemIndex].toObject();
if (jsonObject["cmd"].toString() == "UPDATE_LOGO") {
// **使用非阻塞模式**
QFileDialog* fileDialog = new QFileDialog(this);
fileDialog->setWindowTitle("选择图片");
fileDialog->setDirectory(QDir::currentPath());
fileDialog->setNameFilter("BMP Files (*.bmp);;All Files (*)");
fileDialog->setFileMode(QFileDialog::ExistingFile);
// **当用户选择文件后,调用 lambda 处理逻辑**
connect(fileDialog, &QFileDialog::fileSelected, this, [=](const QString& bmpFilePath) {
if (bmpFilePath.isEmpty()) {
qDebug() << "No image selected.";
return;
}
readBmpFile(bmpFilePath);
QByteArray bmpData;
QFile file(bmpFilePath);
if (file.open(QIODevice::ReadOnly)) {
bmpData = file.readAll();
file.close();
qDebug() << "读取 BMP 文件成功:" << bmpFilePath;
}
else {
qWarning() << "无法打开 BMP 文件:" << bmpFilePath;
return;
}
if (isReplyOrTimeout) {
if (bmpData.isEmpty())
qDebug() << "bmpData.isEmpty()----->1";
else
qDebug() << "bmpData.isEmpty()----->0";
serialPortHandler->sendFrontItem(itemIndex, bmpData);
isReplyOrTimeout = false;
}
});
// **显示对话框(非阻塞)**
fileDialog->open();
}
else if (isReplyOrTimeout) {
QString text = frontFuncConfigLineEdit->text();
qDebug() << "Text in frontFuncConfigLineEdit:" << text;
serialPortHandler->sendFrontItem(itemIndex, "");
isReplyOrTimeout = false;
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString(TOOL_UI.NO_DEV_CONNECT), statusListWidget);
listItem->setBackground(Qt::red);
}
}
void MainWidget::onSendBackItemClicked()
{
qDebug() << "onSendBackItemClicked";
if (connectedClientsCount) {
if (isBackBoardOrAllBoard == 0) {
onHandleInvalidOperate("当前连接的是前板,请勿操作后板或整机页面的按键!!!");
return;
}
QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("backBoardTest").toInt();
for (ClientHandler* handler : clients) {
if (isReplyOrTimeout && ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId))) {
handler->sendBackItem(itemIndex);
isReplyOrTimeout = false;
break;
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString(TOOL_UI.NO_DEV_CONNECT), statusListWidget);
listItem->setBackground(Qt::red);
}
}
void MainWidget::onStatusUpdated(int boardTpye, const QString& client, bool success, const QJsonArray& jsonArray, int itemJsonIndex)
{
qDebug() << "----> Current thread:" << QThread::currentThread();
if (boardTpye == -2) {
qDebug() << "*********************************************";
qDebug() << "isFirstSendDevInfo = " << isFirstSendDevInfo;
//serialPortHandler->sendDevInfoItem();
if (isFirstSendDevInfo) {
emit requestDevInfo();
isFirstSendDevInfo = false;
}
return;
}
isReplyOrTimeout = true;
int clientId = -1;
QString label;
if (boardTpye == 1) {
for (ClientHandler* handler : clients) {
if (handler->getClientAddress() == client) {
clientId = handler->getClientId();
QString lable = handler->getCurrentItemLable();
lable = handler->getCurrentFuncItemLable();
break;
}
}
}
else {
clientId = nextSerialId - 1;
}
qDebug() << "itemJsonIndex :" << itemJsonIndex;
if (itemJsonIndex >= 0 && itemJsonIndex < jsonArray.size()) {
QJsonObject jsonObject = jsonArray.at(itemJsonIndex).toObject();
if (jsonObject.contains("lable")) {
label = jsonObject["lable"].toString();
qDebug() << "label :" << label;
}
if (jsonObject["cmd"] == "GET_IMG") {
getPicButtons[lastClickedGetPicCamIndex]->setStyleSheet("");
}
if (jsonObject["cmd"] == "FACE_VERIFY") {
QList<QPushButton*> buttons = findChildren<QPushButton*>();
int licenseIndex_cnt = 0;
for (QPushButton* btn : buttons) {
if (btn->property("frontBoardTest").isValid()) {
btn->setStyleSheet("");
licenseIndex_cnt++;
if (licenseIndex_cnt >= itemJsonIndex + 1) break;
}
}
}
}
QListWidgetItem* listItem = new QListWidgetItem(QString("device ID: %1 - Item %2: %3 ---> %4")
.arg(clientId)
.arg(itemJsonIndex + 1)
.arg(label)
.arg(success ? "OK" : "NG"), statusListWidget);
listItem->setBackground(success ? Qt::green : Qt::red);
statusListWidget->addItem(listItem);
statusListWidget->scrollToBottom();
}
// json文件里面的配置项都测试结束
void MainWidget::onAllItemsProcessed(int boardTpye, const QString& client, int itemsProcessedCount)
{
qDebug() << "---------------------- onAllItemsProcessed";
qDebug() << "boardTpye:" << boardTpye << "itemsProcessedCount:" << itemsProcessedCount;
isSendingAll = false;
sendAllButton->setText(TOOL_UI.ONE_CLICKED_TEST);
sendAllButton->setStyleSheet("background-color: white;");
sendAllButton->setEnabled(true);
int clientId = -1;
if (boardTpye == 1) {
for (ClientHandler* handler : clients) {
if (handler->getClientAddress() == client) {
clientId = handler->getClientId();
qDebug() << "Current clientId:" << clientId;
break;
}
else
{
//qDebug() << "" << __FUNCTION__ << "handler->getClientAddress() != client";
}
}
}
else {
clientId = nextSerialId - 1;
}
QListWidgetItem* listItem = new QListWidgetItem(QString("device ID:-%1 ---> All %2 items test completed !!!")
.arg(clientId)
.arg(itemsProcessedCount), statusListWidget);
if(checkBoxState)
saveStatusListToFile(filePathLineEdit->text());
statusListWidget->addItem(listItem);
statusListWidget->scrollToBottom();
}
void MainWidget::onHandleInvalidOperate(const QString& text)
{
QListWidgetItem* listItem = new QListWidgetItem(QString("%1").arg(text), statusListWidget);
listItem->setBackground(Qt::red);
statusListWidget->addItem(listItem);
statusListWidget->scrollToBottom();
}