新增产测与服务器的HTTP连接及交互功能

This commit is contained in:
钟富强 2024-08-26 18:33:55 +08:00
parent 0a5b0db9a5
commit 07ab6b9608
24 changed files with 2825 additions and 1654 deletions

View File

@ -25,7 +25,6 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="SourceCode\HotPlugListener.cpp" />
<ClCompile Include="SourceCode\Json\readJsonFile.cpp" />
<ClCompile Include="SourceCode\LicenseGenerate\LicenseGenerate.cpp" />
<ClCompile Include="SourceCode\main.cpp" />
@ -42,6 +41,7 @@
</ClCompile>
<ClCompile Include="SourceCode\Media\VideoDecoder\RingBuffer.cpp" />
<ClCompile Include="SourceCode\Network\ClientHandler.cpp" />
<ClCompile Include="SourceCode\Network\httpClient.cpp" />
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\abstractserver.cpp" />
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\bitmap.cpp" />
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\browser.cpp" />
@ -58,7 +58,6 @@
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\server.cpp" />
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\service.cpp" />
<ClCompile Include="SourceCode\Network\mdns\servicemodel.cpp" />
<ClCompile Include="SourceCode\ParseDataHandler\parseData.cpp" />
<ClCompile Include="SourceCode\RecvDataHandler\RecvDataHandler.cpp" />
<ClCompile Include="SourceCode\Widget\MainWidget.cpp">
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">input</DynamicSource>
@ -70,12 +69,14 @@
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource>
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).moc</QtMocFileName>
</ClCompile>
<ClCompile Include="SourceCode\Widget\UI_Widget\UI_Widget.cpp" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
<None Include="SourceCode\Json\JsonFile\backBoardFuncConfig.json" />
<None Include="SourceCode\Json\JsonFile\backBoardOneClickTest.json" />
<None Include="SourceCode\Json\JsonFile\backBoardTest.json" />
<None Include="SourceCode\Json\JsonFile\backBoardUuid.json" />
<None Include="SourceCode\Json\JsonFile\backDevInfo.json" />
<None Include="SourceCode\Json\JsonFile\frontBoardFuncConfig.json" />
<None Include="SourceCode\Json\JsonFile\frontBoardLicense.json" />
@ -88,9 +89,6 @@
<None Include="SourceCode\Json\JsonFile\README.md" />
<None Include="SourceCode\Json\JsonFile\testConfig.json" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="SourceCode\HotPlugListener.h" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="SourceCode\RecvDataHandler\RecvDataHandler.h" />
<QtMoc Include="SourceCode\Network\ClientHandler.h" />
@ -106,6 +104,7 @@
<QtMoc Include="SourceCode\Network\PasswordEnrollWindow.h" />
<QtMoc Include="SourceCode\Network\mdns\servicemodel.h" />
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\abstractserver.h" />
<QtMoc Include="SourceCode\Network\httpClient.h" />
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\bitmap.h" />
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\browser.h" />
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\cache.h" />
@ -138,8 +137,6 @@
<QtMoc Include="SourceCode\Media\VideoDecoder\FFmpegDecoder.h" />
<ClInclude Include="SourceCode\Media\VideoDecoder\RingBuffer.h" />
<QtMoc Include="SourceCode\Network\DelUserWindows.h" />
<ClInclude Include="SourceCode\ParseDataHandler\msgID.h" />
<ClInclude Include="SourceCode\ParseDataHandler\parseData.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{2C8A5A59-2E79-4283-A0ED-D70DB305557E}</ProjectGuid>

View File

@ -2,9 +2,6 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="SourceCode\main.cpp" />
<ClCompile Include="SourceCode\HotPlugListener.cpp">
<Filter>Misc</Filter>
</ClCompile>
<ClCompile Include="SourceCode\Network\ClientHandler.cpp">
<Filter>Network</Filter>
</ClCompile>
@ -17,9 +14,6 @@
<ClCompile Include="SourceCode\Media\Media.cpp">
<Filter>Media</Filter>
</ClCompile>
<ClCompile Include="SourceCode\ParseDataHandler\parseData.cpp">
<Filter>ParseDataHandler</Filter>
</ClCompile>
<ClCompile Include="SourceCode\Json\readJsonFile.cpp">
<Filter>Json</Filter>
</ClCompile>
@ -80,11 +74,14 @@
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\service.cpp">
<Filter>Network\mdns\qmdnsengine\src</Filter>
</ClCompile>
<ClCompile Include="SourceCode\Widget\UI_Widget\UI_Widget.cpp">
<Filter>Widget\UI_Widget</Filter>
</ClCompile>
<ClCompile Include="SourceCode\Network\httpClient.cpp">
<Filter>Network</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="SourceCode\HotPlugListener.h">
<Filter>Misc</Filter>
</QtMoc>
<QtMoc Include="SourceCode\Widget\MainWidget.h">
<Filter>Widget</Filter>
</QtMoc>
@ -160,6 +157,9 @@
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\server_p.h">
<Filter>Network\mdns\qmdnsengine\src</Filter>
</QtMoc>
<QtMoc Include="SourceCode\Network\httpClient.h">
<Filter>Network</Filter>
</QtMoc>
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
@ -205,14 +205,14 @@
<None Include="SourceCode\Json\JsonFile\frontBoardLicense.json">
<Filter>Json\JsonFile</Filter>
</None>
<None Include="SourceCode\Json\JsonFile\backBoardUuid.json">
<Filter>Json\JsonFile</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Filter Include="Widget">
<UniqueIdentifier>{4ab5db55-c173-4ad9-9d1b-0282a1a8d091}</UniqueIdentifier>
</Filter>
<Filter Include="Misc">
<UniqueIdentifier>{92074ed4-f066-4b63-aef0-d1be4427262c}</UniqueIdentifier>
</Filter>
<Filter Include="Network">
<UniqueIdentifier>{8f2d3c5e-4c9e-45a5-b3fa-6e3e5d18311c}</UniqueIdentifier>
</Filter>
@ -225,9 +225,6 @@
<Filter Include="RecvDataHandler">
<UniqueIdentifier>{2eb24c40-5bd1-4e6f-a721-da4e45a46eff}</UniqueIdentifier>
</Filter>
<Filter Include="ParseDataHandler">
<UniqueIdentifier>{781ddcbd-b53c-4285-b70f-4d0d73d342cd}</UniqueIdentifier>
</Filter>
<Filter Include="Json\JsonFile">
<UniqueIdentifier>{fe1a433b-7d7d-460e-b6d4-50e04dd25408}</UniqueIdentifier>
</Filter>
@ -249,17 +246,14 @@
<Filter Include="Network\mdns\qmdnsengine\src">
<UniqueIdentifier>{e8857e15-2519-4a60-9fd5-eff901a76ba6}</UniqueIdentifier>
</Filter>
<Filter Include="Widget\UI_Widget">
<UniqueIdentifier>{ca263230-ea2f-4140-82aa-19b06eca1b1e}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="SourceCode\Media\Media.h">
<Filter>Media</Filter>
</ClInclude>
<ClInclude Include="SourceCode\ParseDataHandler\parseData.h">
<Filter>ParseDataHandler</Filter>
</ClInclude>
<ClInclude Include="SourceCode\ParseDataHandler\msgID.h">
<Filter>ParseDataHandler</Filter>
</ClInclude>
<ClInclude Include="SourceCode\Json\readJsonFile.h">
<Filter>Json</Filter>
</ClInclude>

View File

@ -1,132 +0,0 @@
#include "HotPlugListener.h"
#include <QApplication>
#include <QDebug>
#include <QDateTime>
#include <QWindow>
#include <guiddef.h>
#include "Windows.h"
#include "Dbt.h"
#include "SetupAPI.h"
WId HotPlugListener::win_id_ = -1;
QList<GUID> HotPlugListener::guid_list_ =
{
{ 0xe5323777, 0xf976, 0x4f5b, { 0x9b, 0x55, 0xb9, 0x46, 0x99, 0xc4, 0x6e, 0x44 } }// KSCATEGORY_VIDEO_CAMERA GUID
};
HotPlugListener::HotPlugListener(WId win_id, QObject* parent) : QObject(parent)
{
if (win_id_ == -1) win_id_ = win_id;
this->registerForDeviceNotifications();
qApp->installNativeEventFilter(this);
}
bool HotPlugListener::nativeEventFilter(const QByteArray& eventType, void* message, long* result)
{
if (!(eventType == "windows_generic_MSG" || eventType == "windows_dispatcher_MSG"))
return false;
MSG* msg = reinterpret_cast<MSG*>(message);
int msg_type = msg->message;
if (msg_type != WM_DEVICECHANGE) return false;
PDEV_BROADCAST_HDR lpdb = reinterpret_cast<PDEV_BROADCAST_HDR>(msg->lParam);
switch (msg->wParam)
{
case DBT_DEVICEARRIVAL:
if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT)
{
PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)lpdb;
QString serial_port_name{ QString::fromWCharArray((const wchar_t*)lpdbv->dbcp_name) };
qInfo()
<< "=========== BEGIN ===========\n"
<< "File: " << __FILE__ << "\n"
<< "Line: " << __LINE__ << "\n"
<< "Function: " << __FUNCTION__ << "\n"
<< "Time: " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") << "\n"
<< "检测到串口" << serial_port_name << "接入" << "\n"
<< "=========== END ===========\n";
emit handleSerialPortHotPlugged();
}
else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)lpdb;
qInfo()
<< "=========== BEGIN ===========\n"
<< "File: " << __FILE__ << "\n"
<< "Line: " << __LINE__ << "\n"
<< "Function: " << __FUNCTION__ << "\n"
<< "Time: " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") << "\n"
<< "检测到摄像头("<< QString::fromWCharArray((const wchar_t*)lpdbv->dbcp_name) <<")接入" << "\n"
<< "=========== END ===========\n";
emit handleCameraPluggedIn();
}
break;
case DBT_DEVICEREMOVECOMPLETE:
if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT)
{
PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)lpdb;
QString serial_port_name{ QString::fromWCharArray((const wchar_t*)lpdbv->dbcp_name) };
qInfo()
<< "=========== BEGIN ===========\n"
<< "File: " << __FILE__ << "\n"
<< "Line: " << __LINE__ << "\n"
<< "Function: " << __FUNCTION__ << "\n"
<< "Time: " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") << "\n"
<< "检测到串口" << serial_port_name << "已移除" << "\n"
<< "=========== END ===========\n";
emit handleSerialPortHotPlugged();
}
else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)lpdb;
qInfo()
<< "=========== BEGIN ===========\n"
<< "File: " << __FILE__ << "\n"
<< "Line: " << __LINE__ << "\n"
<< "Function: " << __FUNCTION__ << "\n"
<< "Time: " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") << "\n"
<< "检测到摄像头(" << QString::fromWCharArray((const wchar_t*)lpdbv->dbcp_name) << ")移除" << "\n"
<< "=========== END ===========\n";
emit handleCameraPluggedOut();
}
break;
default:
break;
}
return false;
}
void HotPlugListener::registerForDeviceNotifications() const
{
for (int i{ 0 }; i < guid_list_.count(); i++)
{
DEV_BROADCAST_DEVICEINTERFACE filter;
filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
filter.dbcc_classguid = guid_list_.at(i);
auto result = RegisterDeviceNotification((HWND)win_id_, &filter, DEVICE_NOTIFY_WINDOW_HANDLE);
}
}

View File

@ -1,34 +0,0 @@
#pragma once
#include <QObject>
#include <QAbstractNativeEventFilter>
typedef quintptr WId;
typedef struct _GUID GUID;
/// @brief 检测串口、UVC和UAC设备的热插拔事件通知其他组件。以注册Windows消息的方式实现
class HotPlugListener : public QObject, public QAbstractNativeEventFilter
{
Q_OBJECT
public:
/// @brief 使构造了HotPlugListener的窗口成为消息接收窗口
/// @param win_id 构造了HotPlugListener的窗口的WID
/// @param parent 构造了HotPlugListener的窗口
explicit HotPlugListener(WId win_id, QObject* parent = nullptr);
bool nativeEventFilter(const QByteArray& eventType, void* message, long* result)override;
signals:
void handleSerialPortHotPlugged();
void handleCameraPluggedIn();
void handleCameraPluggedOut();
private:
static WId win_id_;
static QList<GUID> guid_list_;
void registerForDeviceNotifications() const;
};

View File

@ -1,8 +1,38 @@
[
{
"cmd": "V851_SPK_TEST",
"cmd": "SET_VOLUME",
"val": 50,
"lable": "音量设置",
"timeout": 0
},
{
"cmd": "SET_BACKLIGHT",
"val": 50,
"lable": "前屏背光亮度",
"timeout": 0
},
{
"cmd": "SET_UART_BARTRATE",
"val": "115200",
"lable": "串口波特率",
"timeout": 0
},
{
"cmd": "MOTOR_TORQUE",
"val": 10,
"lable": "电机扭力",
"timeout": 0
},
{
"cmd": "BACK_HEAD_FALSE_OPEN",
"val": 0,
"lable": "V851²⊔SPK",
"timeout": 2000
"lable": "回头防误开",
"timeout": 0
},
{
"cmd": "SET_LOG_LEVEL",
"val": 50,
"lable": "log等级设置",
"timeout": 0
}
]

View File

@ -0,0 +1,20 @@
[
{
"cmd": "GET_BACK_MAC",
"val": 0,
"lable": "获取后板MAC地址",
"timeout": 0
},
{
"cmd": "GET_BACK_UUID",
"val": 0,
"lable": "获取UUID",
"timeout": 0
},
{
"cmd": "GET_BACK_SN",
"val": 0,
"lable": "获取SN",
"timeout": 0
}
]

View File

@ -17,6 +17,12 @@
"lable": "后板硬件版本:",
"timeout": 2000
},
{
"cmd": "GET_BACK_MAC",
"val": 0,
"lable": "后板MAC地址:",
"timeout": 2000
},
{
"cmd": "GET_BACK_SN",
"val": 0,

View File

@ -1,19 +1,19 @@
[
{
"cmd": "GET_FRONT_HW_INFO",
"val": 0,
"val": "0",
"lable": "get_hw_info",
"timeout": 0
},
{
"cmd": "GET_FRONT_LICENSE",
"val": 0,
"val": "0",
"lable": "get_license",
"timeout": 0
},
{
"cmd": "WRITE_FRONT_LICENSE",
"val": 0,
"val": "0",
"lable": "write_license",
"timeout": 0
}

View File

@ -5,12 +5,12 @@ QJsonArray readJsonArrayFromFile(const QString& filePath)
QJsonArray jsonArray;
QFile file(filePath);
if (file.open(QIODevice::ReadOnly)) {
qDebug() << "Successfully opened" << filePath;
qDebug() << "Successfully opened" << filePath ;
QByteArray data = file.readAll();
QJsonDocument doc = QJsonDocument::fromJson(data);
if (!doc.isNull() && doc.isArray()) {
jsonArray = doc.array();
qDebug() << filePath << "JSON array size:" << jsonArray.size();
qDebug() << "JSON array size:" << jsonArray.size();
}
else {
qDebug() << "Failed to parse JSON document from" << filePath;
@ -67,6 +67,10 @@ QJsonArray readJson_backDevInfo() {
return readJsonArrayFromFile("./SourceCode/Json/JsonFile/backDevInfo.json");
}
QJsonArray readJson_backUuid() {
return readJsonArrayFromFile("./SourceCode/Json/JsonFile/backBoardUuid.json");
}
QJsonArray readJson_getPic() {
return readJsonArrayFromFile("./SourceCode/Json/JsonFile/getPic.json");
}

View File

@ -17,6 +17,7 @@ QJsonArray readJson_backBoardOneClickTest();
QJsonArray readJson_backBoardTest();
QJsonArray readJson_backBoardFuncConfig();
QJsonArray readJson_backDevInfo();
QJsonArray readJson_backUuid();
QJsonArray readJson_testConfig();
QJsonArray readJson_funcConfig();

View File

@ -40,7 +40,7 @@ bool licenseGenerate(const unsigned char* hardware_info, unsigned char* license_
}
printf("\n");
// return 限制不调用 pix_license_generate, 防止减少license个数
return false;
//return false;
int ret = pix_license_generate(hardware_info, PIX_HARDWARE_INFO_BYTES,
license_info, PIX_LICENCE_BYTES);
if (ret != SDK_CODE_OK) {

View File

@ -4,19 +4,24 @@
#include "ImageEnrollWindow.h"
#include "PasswordEnrollWindow.h"
ClientHandler::ClientHandler(QTcpSocket* socket, QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson, QJsonArray backBoardDevInfoJson,
ClientHandler::ClientHandler(QTcpSocket* socket,
QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig,
QJsonArray backBoardDevInfoJson,
QJsonArray getPicJson, QJsonArray getVideoJson, int clientId, QObject* parent)
: QObject(parent), socket(socket),
frontBoardOneClickTest(frontBoardOneClickTest), frontBoardTest(frontBoardTest),
frontBoardFuncConfig(frontBoardFuncConfig), frontBoardDevInfoJson(frontBoardDevInfoJson),
frontBoardLicenseJson(frontBoardLicenseJson),
backBoardDevInfoJson(backBoardDevInfoJson), getPicJson(getPicJson),
getVideoJson(getVideoJson), currentItemIndex(0), clientId(clientId),
backBoardOneClickTest(backBoardOneClickTest), backBoardTest(backBoardTest),
backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson),
getPicJson(getPicJson), getVideoJson(getVideoJson),
currentItemIndex(0), clientId(clientId),
isManualSend(false), isSingleSend(false), isClickedSend(false), size(0),
isFirstDataReceived(true), processDataFunction(nullptr),
isDataStuck(false), dataProcessingActive(false), isRecvVideoData(false),
currentFrontBoardIndex(0),
isDataStuck(false), dataProcessingActive(false), isRecvVideoData(true),
currentFrontBoardIndex(0), currentLicenseIndex(0), currentUuidIndex(0),
currentBackBoardIndex(0)
{
connect(socket, &QTcpSocket::readyRead, this, &ClientHandler::onDataReceived);
@ -24,30 +29,12 @@ ClientHandler::ClientHandler(QTcpSocket* socket, QJsonArray frontBoardOneClickTe
qint64 bufferSize = socket->socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption).toLongLong();
/*connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
this, &ClientHandler::onSocketError);*/
}
ClientHandler::~ClientHandler() {
qDebug() << "ClientHandler destroyed for clientId:" << clientId;
if (readTimer) {
readTimer->stop();
delete readTimer;
}
if (threadStatusTimer) {
threadStatusTimer->stop();
delete threadStatusTimer;
}
if (connectionCheckTimer) {
connectionCheckTimer->stop();
delete connectionCheckTimer;
}
}
//void ClientHandler::onSocketError(QAbstractSocket::SocketError socketError) {
// qWarning() << "-------------------------------Socket error:" << socketError << "clientId:" << clientId;
//}
void ClientHandler::startReadVideoDataTimer()
{
emit startReadTimer(clientId);
@ -127,9 +114,17 @@ void ClientHandler::start()
sendNextItem();
}
void ClientHandler::sendDataToClient(const QByteArray& data)
{
emit sendData(data);
}
void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, const QString text, const QString& itemType)
{
QMutexLocker locker(&mutex);
QMutexLocker locker(&mutex);
if (itemType == "License") {
}
isSingleSend = true;
isClickedSend = true;
if (itemType == "handleVideo") {
@ -147,6 +142,7 @@ void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, con
QJsonObject currentItem = jsonArray[itemIndex].toObject();
if (!text.isEmpty() && currentItem.contains("val")) {
QJsonValue originalValue = currentItem["val"];
qDebug() << "text:" << text;
if (originalValue.isDouble()) {
bool ok;
double doubleValue = text.toDouble(&ok);
@ -162,7 +158,8 @@ void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, con
}
}
QString itemData = QJsonDocument(currentItem).toJson();
emit sendData(itemData.toUtf8());
//emit sendData(itemData.toUtf8());
sendDataToSomeClient(controlClientId, itemData.toUtf8());
// 设置超时处理
if (currentItem.contains("timeout")) {
@ -194,7 +191,7 @@ void ClientHandler::sendGetVideoItem(int itemIndex, int video_flag)
}
// 发送License处理按键
void ClientHandler::sendLicenseItem(int itemIndex)
void ClientHandler::sendLicenseItem(int itemIndex, const QString text)
{
if (itemIndex < 0 || itemIndex >= frontBoardLicenseJson.size()) {
qDebug() << "Invalid itemIndex";
@ -205,23 +202,34 @@ void ClientHandler::sendLicenseItem(int itemIndex)
if (label == "write_license") {
LicenseConfirmWindow dialog("你确定要发送此授权项吗?");
if (dialog.exec() == QDialog::Accepted) {
sendJsonItem(frontBoardLicenseJson, itemIndex, "", "License");
sendJsonItem(frontBoardLicenseJson, itemIndex, text, "License");
}
}
else {
sendJsonItem(frontBoardLicenseJson, itemIndex, "", "License");
sendJsonItem(frontBoardLicenseJson, itemIndex, text, "License");
}
}
void ClientHandler::sendUuidItem(int itemIndex, const QString text)
{
}
// 发送单独一个功能配置 JSON 项目
void ClientHandler::sendFuncItem(int itemIndex, const QString text)
void ClientHandler::sendFrontFuncItem(int itemIndex, const QString text)
{
//qDebug() << "sendFuncItem Text:" << text;
sendJsonItem(frontBoardFuncConfig, itemIndex, text, "func");
}
void ClientHandler::sendBackFuncItem(int itemIndex, const QString text)
{
//qDebug() << "sendFuncItem Text:" << text;
sendJsonItem(backBoardFuncConfig, itemIndex, text, "func");
}
// 发送单独一个测试配置 JSON 项目
void ClientHandler::sendItem(int itemIndex)
void ClientHandler::sendFrontItem(int itemIndex)
{
QString text = "";
QJsonObject currentItem = frontBoardTest[itemIndex].toObject();
@ -262,6 +270,47 @@ void ClientHandler::sendItem(int itemIndex)
sendJsonItem(frontBoardTest, itemIndex, text, "test");
}
void ClientHandler::sendBackItem(int itemIndex)
{
QString text = "";
QJsonObject currentItem = backBoardTest[itemIndex].toObject();
if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "IMG_ENROLL") {
ImageEnrollWindow dialog;
if (dialog.exec() == QDialog::Accepted) {
text = dialog.getFilePath();
QByteArray imageData = dialog.getImageData();
if (!imageData.isEmpty()) {
text = QString::fromUtf8(imageData);
}
}
else {
return;
}
}
else if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "DEL_USER") {
DelUserWindow dialog;
if (dialog.exec() == QDialog::Accepted) {
QString userInput = dialog.getUserInput();
if (!userInput.isEmpty() && currentItem.contains("val")) {
text = userInput;
}
}
else {
return;
}
}
else if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "PASSWD_ENROLL") {
PasswordEnrollWindow dialog;
if (dialog.exec() == QDialog::Accepted) {
text = dialog.getPassword();
}
else {
return;
}
}
sendJsonItem(backBoardTest, itemIndex, text, "test");
}
void ClientHandler::sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemIndex)
{
QMutexLocker locker(&mutex);
@ -270,7 +319,8 @@ void ClientHandler::sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemInd
qDebug() << "jsonItem.size()" << jsonItem.size();
QString itemData = QJsonDocument(jsonItem).toJson();
emit sendData(itemData.toUtf8());
//emit sendData(itemData.toUtf8());
sendDataToSomeClient(controlClientId, itemData.toUtf8());
if (jsonItem.contains("timeout")) {
int timeout = jsonItem.value("timeout").toInt();
@ -281,9 +331,16 @@ void ClientHandler::sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemInd
else {
// 如果没有 timeout 字段,则不设置超时处理,一直等待数据接收
}
}
//void ClientHandler::sendLicenseItem()
//{
// if (currentLicenseIndex < frontBoardLicenseJson.size()) {
//
// currentLicenseIndex ++;
// }
//}
void ClientHandler::sendDevInfoItem()
{
// 前板
@ -328,7 +385,8 @@ void ClientHandler::sendNextItem()
}
}
}
emit sendData(itemData.toUtf8());
//emit sendData(itemData.toUtf8());
sendDataToSomeClient(controlClientId, itemData.toUtf8());
if (currentItem.contains("timeout")) {
int timeout = currentItem.value("timeout").toInt();
@ -388,6 +446,7 @@ bool ClientHandler::RNDISFirstData(QByteArray& data) {
data = data.mid(11);
(this->*processDataFunction)(data);
setThreadPriority(QThread::HighPriority);
preVideoClientId = clientId;
break;
case 0x03:
processDataFunction = &ClientHandler::RNDISClient3Data;
@ -396,8 +455,9 @@ bool ClientHandler::RNDISFirstData(QByteArray& data) {
break;
case 0x04:
processDataFunction = &ClientHandler::RNDISClient4Data;
setThreadPriority(QThread::LowestPriority);
setThreadPriority(QThread::LowPriority);
socket->setReadBufferSize(20 * 1024);
controlClientId = clientId;
break;
default:
qWarning() << "Unhandled client type:" << clientType;
@ -479,9 +539,13 @@ void ClientHandler::onDataReceived()
isSingleSend = false; // 重置标志
isClickedSend = false;
}
else if (isPowerOnSend && currentFrontBoardIndex < frontBoardDevInfoJson.size()) {
sendDevInfoItem();
}
else if (isPowerOnSend && currentBackBoardIndex < backBoardDevInfoJson.size()) {
sendDevInfoItem();
}
/*else if (isPowerOnSend) {
qDebug() << "All items processed in onDataReceived.";
emit allItemsProcessed(getClientAddress(), currentFrontBoardIndex);
@ -502,6 +566,7 @@ void ClientHandler::onDataReceived()
// 接收视频流数据 isRecvVideoData 置 0
else if (isRecvVideoData && (!dataProcessingActive)) {
dataProcessingActive = true;
isRecvVideoData = false;
QTimer::singleShot(0, this, &ClientHandler::processPendingData);
}
else {

View File

@ -31,7 +31,8 @@ class ClientHandler : public QObject, public QRunnable
public:
explicit ClientHandler(QTcpSocket* socket, QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest,
QJsonArray frontBoardFuncConfig, QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardDevInfoJson, QJsonArray getPicJson, QJsonArray getVideoJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardDevInfoJson,
QJsonArray getPicJson, QJsonArray getVideoJson,
int clientId, QObject* parent = nullptr);
~ClientHandler();
@ -54,13 +55,17 @@ public:
// 发送拉视频流按键
void sendGetVideoItem(int itemIndex, int video_flag);
// 发送License处理按键
void sendLicenseItem(int itemIndex);
void sendLicenseItem(int itemIndex, const QString text);
void sendUuidItem(int itemIndex, const QString text);
// 发送下一个功能配置 JSON 项目
void sendFuncItem(int itemIndex, QString text);
void sendFrontFuncItem(int itemIndex, QString text);
void sendBackFuncItem(int itemIndex, QString text);
// 发送下一个 JSON 项目
void sendNextItem();
// 处理发送单独指令
void sendItem(int itemIndex);
void sendFrontItem(int itemIndex);
void sendBackItem(int itemIndex);
//void sendLicenseItem();
// 获取客户端的 ID
int getClientId() const { return clientId; }
// 获取当前客户端的地址
@ -75,7 +80,7 @@ public:
QString getCurrentFuncItemLable() const;
// 重置索引
void resetCurrentItemIndex();
// 处理 RingBuffer 中的数据
void sendDataToClient(const QByteArray& data);
//void processRingBufferData();
void setThreadPriority(QThread::Priority priority);
@ -98,6 +103,7 @@ signals:
void selectClientDisconnected(int clientId);
void startReadTimer(int clientId);
void stopReadTimer(int clientId);
void sendDataToSomeClient(int clientId, const QByteArray& data);
public slots:
// 处理数据接收
@ -120,6 +126,9 @@ private:
QJsonArray frontBoardFuncConfig; // 前板功能配置参数 JSON
QJsonArray frontBoardDevInfoJson; // 前板设备信息参数 JSON
QJsonArray frontBoardLicenseJson; // 前板license信息 JSON
QJsonArray backBoardOneClickTest; // 后板一键功能测试 JSON
QJsonArray backBoardTest; // 后板单项测试 JSON
QJsonArray backBoardFuncConfig; // 后板功能配置参数 JSON
QJsonArray backBoardDevInfoJson; // 后板设备信息参数 JSON
QJsonArray jsonConfig; // 测试区 JSON 配置
QJsonArray funcJsonConfig; // 功能区 JSON 配置
@ -129,6 +138,8 @@ private:
int currentItemIndex; // 当前处理的测试 JSON 项目索引
int currentFuncItemIndex; // 当前处理的功能 JSON 项目索引
int clientId; // 新增的客户端编号
int preVideoClientId = 0;
int controlClientId = 1;
int itemsProcessedCount; // 跟踪处理项目的数量
QJsonObject currentItem; // 测试 json文件中当前发送的项
QJsonObject currentFuncItem; // 功能 json文件中当前发送的项
@ -143,6 +154,8 @@ private:
int size;
int currentFrontBoardIndex; // 当前发送的前板设备信息项的索引
int currentBackBoardIndex; // 当前发送的后板设备信息项的索引
int currentLicenseIndex;
int currentUuidIndex;
void checkThreadStatus();
bool isFirstDataReceived;
@ -157,10 +170,6 @@ private:
void sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemIndex);
//void sendDevInfoItem();
QTimer* readTimer;
QTimer* threadStatusTimer;
QTimer* connectionCheckTimer;
bool isDataStuck;
bool dataProcessingActive;
};

View File

@ -0,0 +1,38 @@
// httpClient.cpp
#include <QDebug>
#include "httpClient.h"
HttpClient::HttpClient(QObject* parent)
: QObject(parent),
networkManager(new QNetworkAccessManager(this))
{
connect(networkManager, &QNetworkAccessManager::finished, this, &HttpClient::onNetworkReplyFinished);
}
void HttpClient::sendPostRequest(const QNetworkRequest& request, const QByteArray& jsonData)
{
qDebug() << "jsonData" << jsonData.data();
networkManager->post(request, jsonData);
}
void HttpClient::sendGetRequest(const QNetworkRequest& request)
{
networkManager->get(request);
}
void HttpClient::onNetworkReplyFinished(QNetworkReply* reply)
{
if (reply->error() == QNetworkReply::NoError) {
QByteArray responseData = reply->readAll();
QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
QJsonObject jsonObject = jsonResponse.object();
qDebug() << "jsonObject: " << jsonObject;
emit requestFinished(jsonObject);
}
else {
qDebug() << "reply->error(): " << reply->error();
qDebug() << "errorString: " << reply->errorString();
emit requestError(reply->errorString());
}
reply->deleteLater();
}

View File

@ -0,0 +1,34 @@
// httpClient.h
#ifndef HTTPCLIENT_H
#define HTTPCLIENT_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QUrlQuery>
class HttpClient : public QObject
{
Q_OBJECT
public:
explicit HttpClient(QObject* parent = nullptr);
void sendPostRequest(const QNetworkRequest& request, const QByteArray& jsonData);
void sendGetRequest(const QNetworkRequest& request);
signals:
void requestFinished(const QJsonObject& response);
void requestError(const QString& errorString);
private slots:
void onNetworkReplyFinished(QNetworkReply* reply);
private:
QNetworkAccessManager* networkManager;
};
#endif // HTTPCLIENT_H

View File

@ -127,10 +127,11 @@ void DataHandler::handleData(const QString& client, const QByteArray& recvData,
if (buffer->size() >= totalSize) {
// 去掉前面 11 字节
//QByteArray data = buffer->mid(11, dataSize);
QByteArray data = buffer->mid(10, dataSize);
QByteArray data = buffer->mid(11, dataSize);
//QByteArray data = buffer->mid(10, dataSize);
QString hexString = QString::fromUtf8(data.toHex().data());
QByteArray actual_data = hexStringToByteArray(hexString);
//qDebug() << "---Received hexString:" << hexString;
buffer->remove(0, totalSize); // 移除已处理的数据
// 暂时设置 NG
// 同一个client仅当 msg_id 不连续为 0x11/0x21 或第一次处理时才执行 emit statusUpdated
@ -465,8 +466,20 @@ void DataHandler::handleDevInfo(int msg_id, const QString& client, QByteArray ac
case GET_FRONT_HW_INFO:
{
qDebug() << "GET_FRONT_HW_INFO";
QString dataStr = QString(actual_data.toHex(' '));
QString displayText = "get_hw_info:\n" + dataStr;
//QString dataStr = QString(actual_data.toHex(' '));
QStringList hexList;
QString dataStr;
qDebug() << "actual_data.size(): " << actual_data.size();
qDebug() << "actual_data: " << QString::fromUtf8(actual_data.toHex().data());
if (actual_data.size() == PIX_HARDWARE_INFO_BYTES) {
for (int i = 0; i < actual_data.size(); ++i) {
hexList << QString("0x%1").arg(static_cast<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);
}
break;

View File

@ -19,9 +19,10 @@
#include <QElapsedTimer>
#include <QLineEdit>
#include <QTextEdit>
#include "../Media/Media.h"
#include "../ParseDataHandler/msgID.h"
#include "../Media/VideoDecoder/FFmpegDecoder.h"
#include "../LicenseGenerate/LicenseGenerate.h"
#include "MsgTpye.h"
#define YUV420 1

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,9 @@
#include <QTabWidget>
#include <QTimer>
#include <QGroupBox>
#include <QFormLayout>
#include <QLabel>
#include <QStackedLayout>
#include <QJsonDocument>
#include <QFile>
#include <QDebug>
@ -29,6 +31,18 @@
#include <QTextStream>
#include <QScrollArea>
#include <QDateTime>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrl>
#include <QMap>
#include <QList>
#include <QPair>
#include <QTextCodec>
#include <QCryptographicHash>
#include <QRandomGenerator>
#include <QMessageAuthenticationCode>
#include <QCoreApplication>
#include "../Json/readJsonFile.h"
#include "../RecvDataHandler/RecvDataHandler.h"
@ -36,6 +50,7 @@
#include "../LicenseGenerate/LicenseConfirmWindow.h"
#include "../Network/mdns/servicemodel.h"
#include "../Network/ClientHandler.h"
#include "../Network/httpClient.h"
#include "FocusWindow.h"
// 用于测试 UDP 组播实现 mdns 功能 非标准 mdns
@ -53,6 +68,12 @@ public:
~MainWidget();
private slots:
// 发送HTTP请求
//void onSomeButtonClicked();
// 处理HTTP响应
void onHttpRequestFinished(const QJsonObject& response);
// 处理HTTP错误
void onHttpRequestError(const QString& errorString);
// 处理开始服务器按钮点击事件
void onStartServerClicked();
// 处理发送获取设备信息按键点击事件
@ -62,12 +83,15 @@ private slots:
// 处理发送拉视频流按键点击事件
void onSendGetVideoClicked();
void onLicenseButtonClicked();
void onUuidButtonClicked();
// 处理一键发送按钮点击事件
void onSendAllClicked();
// 处理单独发送项按钮点击事件
void onSendItemClicked();
void onSendFrontItemClicked();
void onSendBackItemClicked();
// 处理单独发送功能配置项按钮点击事件
void onSendFuncItemClicked();
void onSendFrontFuncItemClicked();
void onSendBackFuncItemClicked();
// 处理数据接收信号
//void onDataReceived(const QString& client, const QByteArray& data);
// 处理状态更新信号
@ -103,16 +127,30 @@ private:
void readJsonConfig();
// 设置 UI
void setupUI();
QGroupBox* createLicenseGroupBox();
QGroupBox* createFrontDeviceInfoGroupBox();
QGroupBox* createBackDeviceInfoGroupBox();
QWidget* createFunctionTestTab(const QJsonArray& BoardFuncTest, const QString& propertyName);
QWidget* createFunctionConfigTab(const QJsonArray& BoardFuncConfig, const QString& propertyName);
QWidget* createImageDisplayTab();
QWidget* createVideoDisplayTab();
QGroupBox* createBackConnectServerGroupBox();
// 保存日志到文件
void saveStatusListToFile(const QString& filePath);
// 用于更新按键文本的函数
void updateServerButtonText();
void onDisconnectClient(int clientId);
void setupTimerForThreadPoolInfo();
bool isSendingAll; // 一键功能测试 状态
QTcpServer* server; // TCP 服务器
//QUdpSocket* udpSocket;
void sendDataToClient(int clientId, const QByteArray& data);
//void FactoryToolSendPostFactoryInfotoHttpServer();
void FactoryToolSendPostTestToHttpServer();
void FactoryToolSendPostLicenseToHttpServer(const QString& hardware_info, const QString& license_info);
void FactoryToolSendPostComfirmToHttpServer(const QString& mac_addr, const QString& uuid);
void FactoryToolSendGetUuidToHttpServer(const QString& mac_addr);
void FactoryToolSendGetLicenseToHttpServer(const QString& hw_info);
QTcpServer* server; // TCP 服务器
HttpClient* httpClient; // HTTP 服务器
QJsonArray frontBoardOneClickTest; // 前板一键功能测试 JSON
QJsonArray frontBoardTest; // 前板单项测试 JSON
QJsonArray frontBoardFuncConfig; // 前板功能配置参数 JSON
@ -122,6 +160,7 @@ private:
QJsonArray backBoardTest; // 后板单项测试 JSON
QJsonArray backBoardFuncConfig; // 后板功能配置参数 JSON
QJsonArray backBoardDevInfoJson; // 后板设备信息参数 JSON
QJsonArray backBoardUuidJson; // 后板UUID JSON
QJsonArray testJsonConfig; // 功能测试区 JSON 配置
QJsonArray funcJsonConfig; // 功能配置区 JSON 配置
QJsonArray getDevInfoJson; // 获取设备信息 JSON 配置
@ -136,8 +175,12 @@ private:
QMutex mutex; // 互斥锁
int nextClientId; // 新增的客户端编号
int connectedClientsCount = 0; // 连接客户端的数量
int isRequestSuccessful = 0; // GET请求是否成功
bool manualSend; // 判断是否是手动触发的发送
bool deviceConnected = false; // 判断是否有设备连接过
bool isSendingAll; // 一键功能测试 状态
QJsonObject licenseDataArray; // 用于保存从服务器获取的 data 字段对象
QVector<QPushButton*> itemButtons; // 项目按键集合
QVector<QPushButton*> funcItemButtons; // 功能配置项目按键集合
@ -154,8 +197,10 @@ private:
QLabel* leftLens_imageLabel; // 左边镜头图像显示
QLabel* rightLens_imageLabel; // 右边镜头图像显示
QLabel* videoLabel; // 视频显示
QLineEdit* funcConfigLineEdit; // 功能配置编辑框
QLineEdit* frontFuncConfigLineEdit; // 前板功能配置编辑框
QLineEdit* backFuncConfigLineEdit; // 后板功能配置编辑框
QTextEdit* licenseHwInfoEdit; // 获取license的硬件信息
QTextEdit* UuidHwInfoEdit; // Uuid的硬件信息
MainWidget* mainWidget;
QTabWidget* tabWidget; // 标签页
QWidget* functionTestArea; // 功能测试区

View File

@ -0,0 +1,302 @@
#include "../MainWidget.h"
QGroupBox* MainWidget::createLicenseGroupBox()
{
QGroupBox* groupBox = new QGroupBox("算法 license", this);
QHBoxLayout* buttonRowLayout = new QHBoxLayout;
for (int i = 0; i < frontBoardLicenseJson.size(); ++i) {
QJsonObject item = frontBoardLicenseJson[i].toObject();
QString buttonText = item["lable"].toString();
QPushButton* button = new QPushButton(buttonText, this);
button->setProperty("licenseIndex", i);
buttonRowLayout->addWidget(button);
connect(button, &QPushButton::clicked, this, &MainWidget::onLicenseButtonClicked);
}
//licenseHwInfoEdit->setReadOnly(true);
licenseHwInfoEdit->setReadOnly(false);
licenseHwInfoEdit->setPlaceholderText("1. 点击“get_hw_info”可以获取hw info并显示在此处\n2. 可将hw info输入此处, 点击“get_license”获取License并显示在此处\n3. 点击“write_license”可将License直接写入前板");
licenseHwInfoEdit->setFixedHeight(80);
QVBoxLayout* groupBoxLayout_license = new QVBoxLayout;
groupBoxLayout_license->addLayout(buttonRowLayout);
groupBoxLayout_license->addWidget(licenseHwInfoEdit);
groupBox->setLayout(groupBoxLayout_license);
return groupBox;
}
QGroupBox* MainWidget::createFrontDeviceInfoGroupBox()
{
QGroupBox* frontDeviceInfoGroupBox = new QGroupBox("前板设备信息", this);
QFormLayout* formLayout = new QFormLayout(frontDeviceInfoGroupBox);
for (const QJsonValue& value : frontBoardDevInfoJson) {
QJsonObject item = value.toObject();
QString label = item["lable"].toString();
QString cmd = item["cmd"].toString();
QLabel* itemLabel = new QLabel(label, this);
QLineEdit* itemLineEdit = new QLineEdit(this);
itemLineEdit->setReadOnly(true);
formLayout->addRow(itemLabel, itemLineEdit);
devInfoLineEdits[cmd] = itemLineEdit;
}
return frontDeviceInfoGroupBox;
}
QGroupBox* MainWidget::createBackDeviceInfoGroupBox()
{
QGroupBox* backDeviceInfoGroupBox = new QGroupBox("后板设备信息", this);
QFormLayout* formLayout = new QFormLayout(backDeviceInfoGroupBox);
for (const QJsonValue& value : backBoardDevInfoJson) {
QJsonObject item = value.toObject();
QString label = item["lable"].toString();
QString cmd = item["cmd"].toString();
QLabel* itemLabel = new QLabel(label, this);
QLineEdit* itemLineEdit = new QLineEdit(this);
itemLineEdit->setReadOnly(true);
formLayout->addRow(itemLabel, itemLineEdit);
devInfoLineEdits[cmd] = itemLineEdit;
}
return backDeviceInfoGroupBox;
}
QGroupBox* MainWidget::createBackConnectServerGroupBox()
{
QGroupBox* BackConnectServerGroupBox = new QGroupBox("后板获取UUID", this);
QHBoxLayout* frontDeviceInfoLayout = new QHBoxLayout;
for (int i = 0; i < backBoardUuidJson.size(); ++i) {
QJsonObject item = backBoardUuidJson[i].toObject();
QString buttonText = item["lable"].toString();
QPushButton* button = new QPushButton(buttonText, this);
button->setProperty("UuidIndex", i);
frontDeviceInfoLayout->addWidget(button);
connect(button, &QPushButton::clicked, this, &MainWidget::onUuidButtonClicked);
}
UuidHwInfoEdit->setReadOnly(true);
UuidHwInfoEdit->setPlaceholderText("1. 点击“获取后板MAC地址”会将后板MAC地址显示在此处\n2. 可将后板MAC地址输入到此处点击“获取UUID”显示在此处\n");
UuidHwInfoEdit->setFixedHeight(80);
QVBoxLayout* groupBoxLayout_uuid = new QVBoxLayout;
groupBoxLayout_uuid->addLayout(frontDeviceInfoLayout);
groupBoxLayout_uuid->addWidget(UuidHwInfoEdit);
BackConnectServerGroupBox->setLayout(groupBoxLayout_uuid);
return BackConnectServerGroupBox;
}
QWidget* MainWidget::createFunctionTestTab(const QJsonArray& BoardFuncTest, const QString& propertyName)
{
QWidget* functionTestTab = new QWidget(this);
QVBoxLayout* functionTestLayout = new QVBoxLayout(functionTestTab);
QGridLayout* buttonGridLayout = new QGridLayout();
int buttonsPerRow = 7;
for (int i = 0; i < BoardFuncTest.size() + (77 - BoardFuncTest.size()); ++i) {
QJsonObject item = BoardFuncTest[i].toObject();
QString buttonText = item["lable"].toString();
if (buttonText.isEmpty()) {
buttonText = QString("Send Item %1").arg(i + 1);
}
QPushButton* button = new QPushButton(buttonText, this);
button->setProperty(propertyName.toUtf8().constData(), i);
button->setFixedSize(110, 35);
if (propertyName == "frontBoardTest") {
connect(button, &QPushButton::clicked, this, &MainWidget::onSendFrontItemClicked);
}
else if (propertyName == "backBoardTest") {
connect(button, &QPushButton::clicked, this, &MainWidget::onSendBackItemClicked);
}
int row = i / buttonsPerRow;
int col = i % buttonsPerRow;
buttonGridLayout->addWidget(button, row, col, Qt::AlignLeft);
itemButtons.append(button);
}
QWidget* buttonContainer = new QWidget;
buttonContainer->setLayout(buttonGridLayout);
QScrollArea* scrollArea = new QScrollArea;
scrollArea->setWidget(buttonContainer);
scrollArea->setWidgetResizable(true);
functionTestLayout->addWidget(scrollArea);
return functionTestTab;
}
QWidget* MainWidget::createFunctionConfigTab(const QJsonArray& BoardFuncConfig, const QString& propertyName)
{
QWidget* functionConfigTab = new QWidget(this);
QVBoxLayout* functionConfigLayout = new QVBoxLayout(functionConfigTab);
if (propertyName == "frontBoardFuncConfig") {
frontFuncConfigLineEdit->setPlaceholderText("请输入配置参数...");
functionConfigLayout->addWidget(frontFuncConfigLineEdit);
}
else if (propertyName == "backBoardFuncConfig") {
backFuncConfigLineEdit->setPlaceholderText("请输入配置参数...");
functionConfigLayout->addWidget(backFuncConfigLineEdit);
}
QGridLayout* configButtonGridLayout = new QGridLayout();
int buttonsPerRow = 7; // 每行显示的按键数量,根据需要调整
for (int i = 0; i < BoardFuncConfig.size() + (77 - BoardFuncConfig.size()); ++i) {
QJsonObject item = BoardFuncConfig[i].toObject();
QString buttonText = item["lable"].toString();
if (buttonText.isEmpty()) {
buttonText = QString("Cfg Item %1").arg(i + 1);
}
QPushButton* button = new QPushButton(buttonText, this);
button->setProperty(propertyName.toUtf8().constData(), i);
button->setFixedSize(110, 35);
if (propertyName == "frontBoardFuncConfig") {
connect(button, &QPushButton::clicked, this, &MainWidget::onSendFrontFuncItemClicked);
}
else if (propertyName == "backBoardFuncConfig") {
connect(button, &QPushButton::clicked, this, &MainWidget::onSendBackFuncItemClicked);
}
int row = i / buttonsPerRow;
int col = i % buttonsPerRow;
configButtonGridLayout->addWidget(button, row, col, Qt::AlignLeft);
funcItemButtons.append(button);
}
QWidget* configButtonContainer = new QWidget;
configButtonContainer->setLayout(configButtonGridLayout);
QScrollArea* configScrollArea = new QScrollArea;
configScrollArea->setWidget(configButtonContainer);
configScrollArea->setWidgetResizable(true);
functionConfigLayout->addWidget(configScrollArea);
return functionConfigTab;
}
QWidget* MainWidget::createImageDisplayTab()
{
QWidget* imageDisplayTab = new QWidget(this);
QVBoxLayout* imageDisplayLayout = new QVBoxLayout(imageDisplayTab);
QVBoxLayout* imageButtonsColumnLayout = new QVBoxLayout;
for (int i = 0; i < 5; ++i) {
QHBoxLayout* imageButtonsRowLayout = new QHBoxLayout;
for (int j = 0; j < 2; ++j) {
QPushButton* button;
if (i == 0 && j == 0) {
button = new QPushButton(QString("IR"), this);
button->setFixedSize(73, 50);
imageButtonsRowLayout->addWidget(button);
button->setProperty("getPicIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked);
getPicButtons.append(button);
continue;
}
else if (i == 0 && j == 1) {
button = new QPushButton(QString("RGB"), this);
button->setFixedSize(73, 50);
imageButtonsRowLayout->addWidget(button);
button->setProperty("getPicIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked);
getPicButtons.append(button);
continue;
}
button = new QPushButton(QString("Device %1").arg(i * 2 + j - 1), this);
button->setFixedSize(73, 50);
imageButtonsRowLayout->addWidget(button);
button->setProperty("getPicIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked);
getPicButtons.append(button);
}
imageButtonsColumnLayout->addLayout(imageButtonsRowLayout);
}
QHBoxLayout* lensesLayout = new QHBoxLayout;
leftLens_imageLabel = new QLabel(this);
rightLens_imageLabel = new QLabel(this);
lensesLayout->addWidget(leftLens_imageLabel);
lensesLayout->addWidget(rightLens_imageLabel);
QHBoxLayout* imageAndButtonsLayout = new QHBoxLayout;
imageAndButtonsLayout->addLayout(imageButtonsColumnLayout, 1);
imageAndButtonsLayout->addLayout(lensesLayout, 4);
imageDisplayLayout->addLayout(imageAndButtonsLayout);
return imageDisplayTab;
}
QWidget* MainWidget::createVideoDisplayTab()
{
QWidget* videoDisplayTab = new QWidget(this);
QVBoxLayout* videoDisplayLayout = new QVBoxLayout(videoDisplayTab);
QVBoxLayout* videoButtonsColumnLayout = new QVBoxLayout;
for (int i = 0; i < 6; ++i) {
QHBoxLayout* videoButtonsRowLayout = new QHBoxLayout;
for (int j = 0; j < 2; ++j) {
QPushButton* button;
if (i == 0 && j == 0) {
button = new QPushButton(QString("IR"), this);
button->setFixedSize(73, 50);
videoButtonsRowLayout->addWidget(button);
button->setProperty("getVideoIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked);
getVideoButtons.append(button);
continue;
}
else if (i == 0 && j == 1) {
button = new QPushButton(QString("RGB"), this);
button->setFixedSize(73, 50);
videoButtonsRowLayout->addWidget(button);
button->setProperty("getVideoIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked);
getVideoButtons.append(button);
continue;
}
// 调价调焦窗口按键
if (i == 1 && j == 0) {
button = new QPushButton(QString("大窗口播放视频"), this);
button->setFixedSize(150, 50);
button->setEnabled(false);
videoButtonsRowLayout->addWidget(button);
button->setProperty("getVideoIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onOpenFocusWindowClicked);
getVideoButtons.append(button);
break; // 跳出内层循环,只添加一个按键
}
button = new QPushButton(QString("Device %1").arg(i * 2 + j - 3), this);
button->setFixedSize(73, 50);
videoButtonsRowLayout->addWidget(button);
button->setProperty("getVideoIndex", i * 2 + j + 1);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked);
getVideoButtons.append(button);
}
videoButtonsColumnLayout->addLayout(videoButtonsRowLayout);
}
QHBoxLayout* videoAndButtonsLayout = new QHBoxLayout;
videoLabel = new QLabel(this);
videoAndButtonsLayout->addLayout(videoButtonsColumnLayout, 1);
videoAndButtonsLayout->addWidget(videoLabel, 6);
videoDisplayLayout->addLayout(videoAndButtonsLayout);
return videoDisplayTab;
}

View File

@ -4,7 +4,24 @@
#include <iostream>
#include <QDebug>
//通过设置项目的子系统来避免生成控制台窗口。这种方法根本不会创建控制台窗口:
//
//右键点击你的项目,选择“属性”。
//在“配置属性”下,展开“链接器”,然后选择“系统”。
//将“子系统”设置为“Windows(/ SUBSYSTEM)”而不是“控制台(/ SUBSYSTEM)”。
//这种方法不需要任何额外的代码且最为简洁。如果你已经在代码中使用了WinMain而不是main函数这个设置就是默认的。
//
//通过这些方法,你应该可以彻底隐藏或者关闭控制台窗口。
// 关闭控制台窗口的函数
void closeConsole() {
HWND hwnd = GetConsoleWindow();
ShowWindow(hwnd, SW_HIDE);
}
int main(int argc, char* argv[]) {
//closeConsole(); // 调用函数关闭控制台窗口
//FreeConsole(); // 关闭控制台窗口
QApplication app(argc, argv);
QIcon appIcon("./app_icon.ico");

Binary file not shown.

View File

@ -0,0 +1,231 @@
// MainWidget.h
#pragma once
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include <QTcpServer>
#include <QJsonArray>
#include <QListWidget>
#include <QCheckBox>
#include <QPushButton>
#include <QVBoxLayout>
#include <QThreadPool>
#include <QMutex>
#include <QFileDialog>
#include <QLineEdit>
#include <QTextEdit>
#include <QTabWidget>
#include <QTimer>
#include <QGroupBox>
#include <QFormLayout>
#include <QLabel>
#include <QStackedLayout>
#include <QJsonDocument>
#include <QFile>
#include <QDebug>
#include <QHBoxLayout>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QNetworkInterface>
#include <QTextStream>
#include <QScrollArea>
#include <QDateTime>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrl>
#include <QMap>
#include <QList>
#include <QPair>
#include <QTextCodec>
#include <QCryptographicHash>
#include <QRandomGenerator>
#include <QMessageAuthenticationCode>
#include <QCoreApplication>
#include "../Json/readJsonFile.h"
#include "../RecvDataHandler/RecvDataHandler.h"
#include "../LicenseGenerate/LicenseGenerate.h"
#include "../LicenseGenerate/LicenseConfirmWindow.h"
#include "../Network/mdns/servicemodel.h"
#include "../Network/ClientHandler.h"
#include "../Network/httpClient.h"
#include "FocusWindow.h"
// 用于测试 UDP 组播实现 mdns 功能 非标准 mdns
#define TEST_UDP_BROADCAST 0
#define TCP_CONNECT_PORT 12412
class MainWidget : public QWidget
{
Q_OBJECT
public:
// 构造函数
explicit MainWidget(QWidget* parent = nullptr);
~MainWidget();
private slots:
// 发送HTTP请求
//void onSomeButtonClicked();
// 处理HTTP响应
void onHttpRequestFinished(const QJsonObject& response);
// 处理HTTP错误
void onHttpRequestError(const QString& errorString);
// 处理开始服务器按钮点击事件
void onStartServerClicked();
// 处理发送获取设备信息按键点击事件
void onSendGetDevInfoClicked();
// 处理发送取图按键点击事件
void onSendGetPicClicked();
// 处理发送拉视频流按键点击事件
void onSendGetVideoClicked();
void onLicenseButtonClicked();
void onUuidButtonClicked();
// 处理一键发送按钮点击事件
void onSendAllClicked();
// 处理单独发送项按钮点击事件
void onSendFrontItemClicked();
void onSendBackItemClicked();
// 处理单独发送功能配置项按钮点击事件
void onSendFrontFuncItemClicked();
void onSendBackFuncItemClicked();
// 处理数据接收信号
//void onDataReceived(const QString& client, const QByteArray& data);
// 处理状态更新信号
void onStatusUpdated(const QString& client, int itemIndex, int funcItemIndex,
bool success, const QString& itemData, const QString& funcItemData);
// 处理所有项目处理完毕信号
void onAllItemsProcessed(const QString& client, int itemsProcessedCount);
// 处理客户端断开连接
void onClientDisconnected(ClientHandler* handler);
// 启动超时定时器
void onStartTimeout(int clientId, int timeout);
// 为了使滚动条在最下面,不用手动鼠标下拉
void scrollToBottom();
// 处理点击 Save Log 按键
void onSelectFileButtonClicked();
// 处理点击 Clear Log 按键
void onclearLogButtonClicked();
// 处理复选框的状态
void onSaveCheckBoxStateChanged(int state);
// 处理打开调焦的大窗口
void onOpenFocusWindowClicked();
void printThreadPoolInfo();
void onCheckThreadStatus();
void onCheckConnectionStatus();
void startClientReadTimer(int clientId);
void stopClientReadTimer(int clientId);
#if TEST_UDP_BROADCAST
void sendMulticastMessage();
#endif
private:
// 读取 test JSON 配置文件
void readJsonConfig();
// 设置 UI
void setupUI();
QGroupBox* createLicenseGroupBox();
QGroupBox* createFrontDeviceInfoGroupBox();
QGroupBox* createBackDeviceInfoGroupBox();
QWidget* createFunctionTestTab(const QJsonArray& BoardFuncTest, const QString& propertyName);
QWidget* createFunctionConfigTab(const QJsonArray& BoardFuncConfig, const QString& propertyName);
QWidget* createImageDisplayTab();
QWidget* createVideoDisplayTab();
QGroupBox* createBackConnectServerGroupBox();
// 保存日志到文件
void saveStatusListToFile(const QString& filePath);
// 用于更新按键文本的函数
void updateServerButtonText();
void onDisconnectClient(int clientId);
void setupTimerForThreadPoolInfo();
void sendDataToClient(int clientId, const QByteArray& data);
//void FactoryToolSendPostFactoryInfotoHttpServer();
void FactoryToolSendPostTestToHttpServer();
void FactoryToolSendPostLicenseToHttpServer(const QString& hardware_info, const QString& license_info);
void FactoryToolSendPostComfirmToHttpServer();
void FactoryToolSendGetUuidToHttpServer();
void FactoryToolSendGetLicenseToHttpServer(const QString& hw_info);
QTcpServer* server; // TCP 服务器
HttpClient* httpClient; // HTTP 服务器
QJsonArray frontBoardOneClickTest; // 前板一键功能测试 JSON
QJsonArray frontBoardTest; // 前板单项测试 JSON
QJsonArray frontBoardFuncConfig; // 前板功能配置参数 JSON
QJsonArray frontBoardDevInfoJson; // 前板设备信息参数 JSON
QJsonArray frontBoardLicenseJson; // 前板License JSON
QJsonArray backBoardOneClickTest; // 后板一键功能测试 JSON
QJsonArray backBoardTest; // 后板单项测试 JSON
QJsonArray backBoardFuncConfig; // 后板功能配置参数 JSON
QJsonArray backBoardDevInfoJson; // 后板设备信息参数 JSON
QJsonArray backBoardUuidJson; // 后板UUID JSON
QJsonArray testJsonConfig; // 功能测试区 JSON 配置
QJsonArray funcJsonConfig; // 功能配置区 JSON 配置
QJsonArray getDevInfoJson; // 获取设备信息 JSON 配置
QJsonArray getPicJson; // 发送取图指令 JSON 配置
QJsonArray getVideoJson; // 发送拉视频指令 JSON 配置
QVBoxLayout* mainLayout; // 主布局
QListWidget* statusListWidget; // 状态列表
QPushButton* startServerButton; // 开始服务器按键
QPushButton* focusWindowsButton; // 调焦窗口按键
QPushButton* sendAllButton; // 一键发送按键
QThreadPool threadPool; // 线程池
QMutex mutex; // 互斥锁
int nextClientId; // 新增的客户端编号
int connectedClientsCount = 0; // 连接客户端的数量
int isRequestSuccessful = 0; // GET请求是否成功
bool manualSend; // 判断是否是手动触发的发送
bool deviceConnected = false; // 判断是否有设备连接过
bool isSendingAll; // 一键功能测试 状态
QJsonObject licenseDataArray; // 用于保存从服务器获取的 data 字段对象
QVector<QPushButton*> itemButtons; // 项目按键集合
QVector<QPushButton*> funcItemButtons; // 功能配置项目按键集合
QVector<QPushButton*> getPicButtons; // 保存两个取图的摄像头的按键的指针
QVector<QPushButton*> getVideoButtons; // 保存拉视频设备的按键的指针
QList<ClientHandler*> clients; // 客户端处理器集合
QMap<int, QTimer*> clientTimers; // 每个客户端的定时器
QMap<QString, QLineEdit*> devInfoLineEdits;// msg_id 和对应的 QLineEdit 的映射关系
QCheckBox* saveCheckBox; // 保存文件复选框
QPushButton* selectFileButton; // Save Log 按键
QPushButton* clearLogButton; // clear Log 按键
QLineEdit* filePathLineEdit; // 文件路径显示
QLabel* leftLens_imageLabel; // 左边镜头图像显示
QLabel* rightLens_imageLabel; // 右边镜头图像显示
QLabel* videoLabel; // 视频显示
QLineEdit* frontFuncConfigLineEdit; // 前板功能配置编辑框
QLineEdit* backFuncConfigLineEdit; // 后板功能配置编辑框
QTextEdit* licenseHwInfoEdit; // 获取license的硬件信息
QTextEdit* UuidHwInfoEdit; // Uuid的硬件信息
MainWidget* mainWidget;
QTabWidget* tabWidget; // 标签页
QWidget* functionTestArea; // 功能测试区
QWidget* functionConfigArea; // 功能配置区
int lastClickedGetPicCamIndex; // 记录上一次点击取图的摄像头的按键索引
int lastClickedGetPicDevIndex; // 记录上一次点击取图的设备的按键索引
int lastClickedGetVideoCamIndex; // 记录上一次点击拉视频的摄像头的按键索引
int lastClickedGetVideoDevIndex; // 记录上一次点击拉视频的设备的按键索引
QTimer* threadStatusTimer; // 检查线程状态的定时器
QTimer* connectionStatusCheckTimer; // 检查连接状态的定时器
QMap<int, QThread*> clientThreads;
QMap<int, QTimer*> clientReadTimers;
QMap<int, ClientHandler*> clients_1;
ServiceProvider* mServiceProvider;
QTimer* mdnsTimer;
void startMdnsService();
void stopMdnsService();
#if TEST_UDP_BROADCAST
QUdpSocket* multicastSocket;
QTimer* multicastTimer;
#endif
};
#endif // MAINWIDGET_H

File diff suppressed because it is too large Load Diff