2781 lines
137 KiB
C++
2781 lines
137 KiB
C++
// 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();
|
||
}
|
||
|