更新与前板的使用串口连接

This commit is contained in:
钟富强 2025-02-14 11:06:28 +08:00
parent d2bccd9c49
commit aa3e8c8223
301 changed files with 5373 additions and 512 deletions

View File

@ -44,6 +44,7 @@
<ClCompile Include="SourceCode\Network\httpClient.cpp" />
<ClCompile Include="SourceCode\Network\mdns\mdns.c" />
<ClCompile Include="SourceCode\RecvDataHandler\RecvDataHandler.cpp" />
<ClCompile Include="SourceCode\RecvDataHandler\SerialRecvDataHandler.cpp" />
<ClCompile Include="SourceCode\Widget\MainWidget.cpp">
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">input</DynamicSource>
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Filename).moc</QtMocFileName>
@ -54,10 +55,13 @@
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource>
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).moc</QtMocFileName>
</ClCompile>
<ClCompile Include="SourceCode\Widget\SerialPortHandler\SerialPortHandler.cpp" />
<ClCompile Include="SourceCode\Widget\UI_Widget\UI_Widget.cpp" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
<None Include="SourceCode\Json\JsonFile\allBoardFuncConfig.json" />
<None Include="SourceCode\Json\JsonFile\allBoardTest.json" />
<None Include="SourceCode\Json\JsonFile\backBoardFuncConfig.json" />
<None Include="SourceCode\Json\JsonFile\backBoardOneClickTest.json" />
<None Include="SourceCode\Json\JsonFile\backBoardTest.json" />
@ -71,11 +75,9 @@
<None Include="SourceCode\Json\JsonFile\frontBoardTest.json" />
<None Include="SourceCode\Json\JsonFile\frontCmd_config.json" />
<None Include="SourceCode\Json\JsonFile\frontDevInfo.json" />
<None Include="SourceCode\Json\JsonFile\funcConfig.json" />
<None Include="SourceCode\Json\JsonFile\getPic.json" />
<None Include="SourceCode\Json\JsonFile\getVideo.json" />
<None Include="SourceCode\Json\JsonFile\README.md" />
<None Include="SourceCode\Json\JsonFile\testConfig.json" />
<None Include="UI_config.ini" />
</ItemGroup>
<ItemGroup>
@ -87,6 +89,9 @@
<ClInclude Include="SourceCode\Json\readJsonFile.h" />
<ClInclude Include="SourceCode\Network\mdns\mdns.h" />
<QtMoc Include="SourceCode\Network\mdns\MdnsServiceThread.h" />
<QtMoc Include="SourceCode\Widget\SerialPortHandler\SerialPortHandler.h" />
<QtMoc Include="SourceCode\Widget\SerialPortHandler\SerialPortWorker.h" />
<QtMoc Include="SourceCode\RecvDataHandler\SerialRecvDataHandler.h" />
<ClInclude Include="SourceCode\Widget\UI_Widget\UI_Name.h" />
<QtMoc Include="SourceCode\LicenseGenerate\LicenseConfirmWindow.h" />
<ClInclude Include="SourceCode\LicenseGenerate\LicenseGenerate.h" />

View File

@ -35,6 +35,12 @@
<ClCompile Include="SourceCode\Network\mdns\mdns.c">
<Filter>Network\mdns</Filter>
</ClCompile>
<ClCompile Include="SourceCode\Widget\SerialPortHandler\SerialPortHandler.cpp">
<Filter>Widget\SerialPortHandler</Filter>
</ClCompile>
<ClCompile Include="SourceCode\RecvDataHandler\SerialRecvDataHandler.cpp">
<Filter>RecvDataHandler</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="SourceCode\Widget\MainWidget.h">
@ -70,21 +76,24 @@
<QtMoc Include="SourceCode\Network\mdns\MdnsServiceThread.h">
<Filter>Network\mdns</Filter>
</QtMoc>
<QtMoc Include="SourceCode\Widget\SerialPortHandler\SerialPortHandler.h">
<Filter>Widget\SerialPortHandler</Filter>
</QtMoc>
<QtMoc Include="SourceCode\Widget\SerialPortHandler\SerialPortWorker.h">
<Filter>Widget\SerialPortHandler</Filter>
</QtMoc>
<QtMoc Include="SourceCode\RecvDataHandler\SerialRecvDataHandler.h">
<Filter>RecvDataHandler</Filter>
</QtMoc>
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
<None Include="SourceCode\Json\JsonFile\funcConfig.json">
<Filter>Json\JsonFile</Filter>
</None>
<None Include="SourceCode\Json\JsonFile\getPic.json">
<Filter>Json\JsonFile</Filter>
</None>
<None Include="SourceCode\Json\JsonFile\getVideo.json">
<Filter>Json\JsonFile</Filter>
</None>
<None Include="SourceCode\Json\JsonFile\testConfig.json">
<Filter>Json\JsonFile</Filter>
</None>
<None Include="SourceCode\Json\JsonFile\backBoardFuncConfig.json">
<Filter>Json\JsonFile</Filter>
</None>
@ -128,6 +137,12 @@
<None Include="SourceCode\Json\JsonFile\frontCmd_config.json">
<Filter>Json\JsonFile</Filter>
</None>
<None Include="SourceCode\Json\JsonFile\allBoardTest.json">
<Filter>Json\JsonFile</Filter>
</None>
<None Include="SourceCode\Json\JsonFile\allBoardFuncConfig.json">
<Filter>Json\JsonFile</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Filter Include="Widget">
@ -160,6 +175,9 @@
<Filter Include="Widget\UI_Widget">
<UniqueIdentifier>{ca263230-ea2f-4140-82aa-19b06eca1b1e}</UniqueIdentifier>
</Filter>
<Filter Include="Widget\SerialPortHandler">
<UniqueIdentifier>{332951b9-b26b-4d33-9f92-765d7ac250c5}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="SourceCode\Media\Media.h">

View File

@ -114,5 +114,11 @@
"val": 0,
"lable": "联网测试",
"timeout": 2000
},
{
"cmd": "CHANGE_THEME",
"val": "0",
"lable": "更新主题壁纸",
"timeout": 2000
}
]

View File

@ -17,5 +17,11 @@
"SN": "123",
"lable": "write_UUID_SN",
"timeout": 0
},
{
"cmd": "BACK_CONFIRM_BURN",
"val": "0",
"lable": "Confirm_burn",
"timeout": 0
}
]

View File

@ -69,13 +69,13 @@
"cmd": "GET_IMG",
"val": 0,
"lable": "左边镜头取图",
"timeout": 0
"timeout": 3000
},
{
"cmd": "GET_IMG",
"val": 1,
"lable": "右边镜头取图",
"timeout": 0
"timeout": 3000
},
{
"cmd": "TOUCH_TEST",

View File

@ -3,7 +3,7 @@
"cmd": "FACE_ENROLL_SINGLE",
"val": 0,
"lable": "人脸单角度注册",
"timeout": 10000
"timeout": 2000
},
{
"cmd": "FACE_ENROLL",

View File

@ -1,7 +1,7 @@
[
{
"cmd": "GET_IMG",
"val": "0",
"val": 0,
"lable": "取图",
"timeout": 0
}

View File

@ -1,13 +1,13 @@
[
{
"cmd": "START_VIDEO",
"val": "1",
"val": 1,
"lable": "启动视频",
"timeout": 0
},
{
"cmd": "STOP_VIDEO",
"val": "0",
"val": 0,
"lable": "停止视频",
"timeout": 0
}

View File

@ -23,12 +23,12 @@ QJsonArray readJsonArrayFromFile(const QString& filePath)
return jsonArray;
}
QJsonArray readJson_testConfig() {
return readJsonArrayFromFile("./SourceCode/Json/JsonFile/testConfig.json");
QJsonArray readJson_allBoardTest() {
return readJsonArrayFromFile("./SourceCode/Json/JsonFile/allBoardTest.json");
}
QJsonArray readJson_funcConfig() {
return readJsonArrayFromFile("./SourceCode/Json/JsonFile/funcConfig.json");
QJsonArray readJson_allBoardFuncConfig() {
return readJsonArrayFromFile("./SourceCode/Json/JsonFile/allBoardFuncConfig.json");
}
QJsonArray readJson_frontBoardOneClickTest() {

View File

@ -23,8 +23,8 @@ QJsonArray readJson_backCmd_config();
QJsonArray readJson_factoryProductInfo();
QJsonArray readJson_testConfig();
QJsonArray readJson_funcConfig();
QJsonArray readJson_allBoardTest();
QJsonArray readJson_allBoardFuncConfig();
QJsonArray readJson_getPic();
QJsonArray readJson_getVideo();

View File

@ -220,3 +220,73 @@ void DataHandler::showPic(QSize labelSize, int lens_n,
qDebug() << "JPG image saved to" << rotatedImageFileName;
}
void SerialDataHandler::showPic(QSize labelSize, int lens_n,
int width, int height, int format, const QByteArray* valData)
{
qDebug() << "lens_n = " << lens_n;
qDebug() << "format = " << format;
qDebug() << "width = " << width;
qDebug() << "height = " << height;
qDebug() << "yuvData size = " << valData->size();
QImage image;
if (format == YUV422) {
image = convertYUV422ToQImage(*valData, width, height);
}
else if (format == YUV420) {
image = convertYUV420ToQImage(*valData, width, height);
}
else {
qWarning() << "Unsupported image format! Please use YUV422 or YUV420 format";
return;
}
QTransform transform;
transform.rotate(90); // 可以调整旋转角度
QImage rotatedImage = image.transformed(transform);
QImage scaledImage = rotatedImage.scaled(labelSize, Qt::KeepAspectRatio);
QPixmap pixmap = QPixmap::fromImage(scaledImage);
if (lens_n == 0) {
//leftLens_m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
emit updateLeftLensImage(pixmap);
}
else if (lens_n == 1) {
//rightLens_m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
emit updateRightLensImage(pixmap);
}
else {
qWarning() << "Unsupported image lens!";
}
// 生成保存图片的目录
QString saveDirPath = QDir::currentPath() + "/frontBoardImage";
QDir saveDir(saveDirPath);
if (!saveDir.exists()) {
saveDir.mkpath(saveDirPath);
}
QString currentTime = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss");
QByteArray rotatedYuvData;
if (format == YUV422) {
rotatedYuvData = convertQImageToYUV422(rotatedImage);
}
else if (format == YUV420) {
rotatedYuvData = convertQImageToYUV420(rotatedImage);
}
QString yuvFileName = saveDirPath + "/" + currentTime + ".yuv";
QFile yuvFile(yuvFileName);
if (yuvFile.open(QIODevice::WriteOnly)) {
yuvFile.write(rotatedYuvData);
yuvFile.close();
qDebug() << "YUV image saved to" << yuvFileName;
}
else {
qWarning() << "Failed to save rotated YUV image to" << yuvFileName;
}
// 额外可以保存旋转后的图像为JPG或PNG格式
QString rotatedImageFileName = saveDirPath + "/" + currentTime + ".jpg";
rotatedImage.save(rotatedImageFileName, "JPG");
qDebug() << "JPG image saved to" << rotatedImageFileName;
}

View File

@ -8,6 +8,7 @@
#include <QDebug>
#include "../RecvDataHandler/RecvDataHandler.h"
#include "../RecvDataHandler/SerialRecvDataHandler.h"
#define YUV420 1
#define YUV422 2

View File

@ -106,14 +106,14 @@ QString ClientHandler::getCurrentFuncItemData() const
{
QString data = currentFuncItem.value("val").toString();
qDebug() << "Getting current funcItem val:" << data;
return data; // 返回当前项的 "data" 字段
return data; // 返回当前项的 "val" 字段
}
QString ClientHandler::getCurrentItemLable() const
{
QString lable = currentItem.value("lable").toString();
qDebug() << "Getting current item lable:" << lable;
return lable; // 返回当前项的 "data" 字段
return lable; // 返回当前项的 "lable" 字段
}
QString ClientHandler::getCurrentFuncItemLable() const
@ -475,8 +475,6 @@ void ClientHandler::sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemInd
else {
emit sendDataToSomeClient(controlClientId, itemData.toUtf8());
}
if (jsonItem.contains("timeout")) {
int timeout = jsonItem.value("timeout").toInt();
if (timeout > 0) {
@ -553,7 +551,7 @@ void ClientHandler::sendNextItem(QJsonArray& currentOneClickedItem)
}
}
else if (isManualSend) {
emit allItemsProcessed(getClientAddress(), itemsProcessedCount);
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), itemsProcessedCount);
// 处理完毕后重置标记
isManualSend = false;
isClickedSend = false;
@ -582,7 +580,6 @@ void ClientHandler::RNDISClient3Data(QByteArray& data) {
}
void ClientHandler::RNDISClient4Data(QByteArray& data) {
//qDebug() << " RNDISClient4Data size:" << data.size();
//qDebug() << " RNDISClient4Data size:" << data.size();
isRecvVideoData = false;
isStartVideo = false;
@ -679,10 +676,10 @@ void ClientHandler::onPicRecvFinished()
void ClientHandler::onDataReceived()
{
//qDebug() << "isRecvVideoData:" << isRecvVideoData;
//qDebug() << "isPowerOnSend:" << isPowerOnSend;
//qDebug() << "isClickedSend:" << isClickedSend;
//qDebug() << "isSingleSend:" << isSingleSend;
//qDebug() << "isRecvImgData:" << isRecvImgData;
//qDebug() << "isPowerOnSend: " << isPowerOnSend;
//qDebug() << "isClickedSend: " << isClickedSend;
//qDebug() << "isSingleSend: " << isSingleSend;
//qDebug() << "isRecvImgData: " << isRecvImgData;
if (!isRecvVideoData &&
(isRecvImgData || isPowerOnSend || isClickedSend || (isSingleSend && (currentItemIndex < currentJson.size())))) {
QByteArray allData;
@ -726,7 +723,7 @@ void ClientHandler::onDataReceived()
}
else {
qDebug() << "All items processed in onDataReceived.";
emit allItemsProcessed(getClientAddress(), currentBackBoardIndex);
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), currentBackBoardIndex);
isPowerOnSend = false;
}
}
@ -736,7 +733,7 @@ void ClientHandler::onDataReceived()
}
else {
qDebug() << "All items processed in onDataReceived.";
emit allItemsProcessed(getClientAddress(), currentFrontBoardIndex);
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), currentFrontBoardIndex);
isPowerOnSend = false;
}
}
@ -748,7 +745,7 @@ void ClientHandler::onDataReceived()
}
}
else if(isClickedSend) {
emit allItemsProcessed(getClientAddress(), itemsProcessedCount);
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), itemsProcessedCount);
isClickedSend = false;
//resetCurrentItemIndex();
}
@ -850,7 +847,7 @@ void ClientHandler::onTimeout()
{
{
QMutexLocker locker(&mutex);
emit statusUpdated(getClientAddress(), false, currentJson, currentJsonItem);
emit statusUpdated(isBackBoardOrAllBoard, getClientAddress(), false, currentJson, currentJsonItem);
//qDebug() << "isSingleSend:" << isSingleSend << "isPowerOnSend:" << isPowerOnSend;
if (!isSingleSend && !isPowerOnSend) {
currentItemIndex ++;
@ -866,7 +863,7 @@ void ClientHandler::onTimeout()
sendNextItem(currentJson);
}
else if (currentItemIndex >= backBoardOneClickTest.size()) {
emit allItemsProcessed(getClientAddress(), itemsProcessedCount);
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), itemsProcessedCount);
}
}
else {
@ -874,7 +871,7 @@ void ClientHandler::onTimeout()
sendNextItem(currentJson);
}
else if (currentItemIndex >= frontBoardOneClickTest.size()) {
emit allItemsProcessed(getClientAddress(), itemsProcessedCount);
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), itemsProcessedCount);
}
}
}
@ -884,7 +881,7 @@ void ClientHandler::onTimeout()
sendDevInfoItem();
}
else {
emit allItemsProcessed(getClientAddress(), currentBackBoardIndex);
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), currentBackBoardIndex);
currentFrontBoardIndex = 0;
currentBackBoardIndex = 0;
isPowerOnSend = false;
@ -895,7 +892,7 @@ void ClientHandler::onTimeout()
sendDevInfoItem();
}
else {
emit allItemsProcessed(getClientAddress(), currentFrontBoardIndex);
emit allItemsProcessed(isBackBoardOrAllBoard, getClientAddress(), currentFrontBoardIndex);
currentFrontBoardIndex = 0;
currentBackBoardIndex = 0;
isPowerOnSend = false;

View File

@ -112,12 +112,12 @@ signals:
// 数据发送信号
void sendData(const QByteArray& data, int isBoardType);
// 状态更新信号
void statusUpdated(const QString& client, bool success, const QJsonArray& jsonArray, int itemJsonIndex);
void statusUpdated(int boardTpye, const QString& client, bool success, const QJsonArray& jsonArray, int itemJsonIndex);
void HandleInvalidOperate(const QString& text);
// 客户端断开连接信号
void clientDisconnected(ClientHandler* handler);
// json文件配置项发送完毕
void allItemsProcessed(const QString& client, int itemsProcessedCount);
void allItemsProcessed(int boardTpye, const QString& client, int itemsProcessedCount);
// 通知主线程启动定时器
void startTimeout(int timeout);
void selectClientDisconnected(int client_Id);

View File

@ -23,7 +23,7 @@ public:
QPushButton* deleteButton = new QPushButton("删除用户", this);
layout->addWidget(deleteButton);
qDebug() << "------------- DelUserWindow";
connect(deleteButton, &QPushButton::clicked, this, &DelUserWindow::onDeleteButtonClicked);
}

View File

@ -4,12 +4,13 @@
#include "mdns.h"
// 添加一个类来运行 mDNS 服务
// 运行 mDNS 服务
class MdnsServiceThread : public QThread {
Q_OBJECT
public:
MdnsServiceThread(const QString& hostname, const QString& serviceName, int servicePort, QObject* parent = nullptr)
MdnsServiceThread(const QString& hostname, const QString& serviceName, int servicePort, char* select_ip, QObject* parent = nullptr)
: QThread(parent),
m_select_ip(select_ip),
m_hostname(hostname),
m_serviceName(serviceName),
m_servicePort(servicePort) {}
@ -26,8 +27,9 @@ protected:
extern volatile sig_atomic_t running; // 使用全局变量控制运行状态
running = 1;
// 调用阻塞的 service_mdns 方法
int result = service_mdns(m_hostname.toStdString().c_str(), m_serviceName.toStdString().c_str(), m_servicePort);
//int result = service_mdns(m_hostname.toStdString().c_str(), m_serviceName.toStdString().c_str(), m_servicePort, "192.168.1.170");
//int result = service_mdns(m_hostname.toStdString().c_str(), m_serviceName.toStdString().c_str(), m_servicePort, "172.17.128.1");
int result = service_mdns(m_hostname.toStdString().c_str(), m_serviceName.toStdString().c_str(), m_servicePort, m_select_ip);
if (result < 0) {
qDebug() << "Failed to start mDNS service";
}
@ -37,6 +39,7 @@ protected:
}
private:
char* m_select_ip;
QString m_hostname;
QString m_serviceName;
int m_servicePort;

View File

@ -530,7 +530,7 @@ open_client_sockets(int* sockets, int max_sockets, int port) {
char buffer[128];
mdns_string_t addr = ipv4_address_to_string(buffer, sizeof(buffer), saddr,
sizeof(struct sockaddr_in));
printf("Local IPv4 address: %.*s\n", MDNS_STRING_FORMAT(addr));
printf("---Local IPv4 address: %.*s\n", MDNS_STRING_FORMAT(addr));
}
}
} else if (unicast->Address.lpSockaddr->sa_family == AF_INET6) {
@ -665,6 +665,7 @@ open_client_sockets(int* sockets, int max_sockets, int port) {
return num_sockets;
}
/*
// Open sockets to listen to incoming mDNS queries on port 5353
static int
open_service_sockets(int* sockets, int max_sockets) {
@ -720,6 +721,101 @@ open_service_sockets(int* sockets, int max_sockets) {
return num_sockets;
}
*/
static int open_service_sockets(int* sockets, int max_sockets, const char* local_ip) {
int num_sockets = 0;
if (local_ip) {
// 如果指定了 local_ip则绑定到该地址
struct sockaddr_in sock_addr_ipv4;
struct sockaddr_in6 sock_addr_ipv6;
memset(&sock_addr_ipv4, 0, sizeof(sock_addr_ipv4));
memset(&sock_addr_ipv6, 0, sizeof(sock_addr_ipv6));
if (inet_pton(AF_INET, local_ip, &sock_addr_ipv4.sin_addr)) {
sock_addr_ipv4.sin_family = AF_INET;
sock_addr_ipv4.sin_port = htons(MDNS_PORT);
#ifdef __APPLE__
sock_addr_ipv4.sin_len = sizeof(struct sockaddr_in);
#endif
int sock = mdns_socket_open_ipv4(&sock_addr_ipv4);
if (sock >= 0) {
sockets[num_sockets++] = sock;
printf("Bound to specific IPv4 address: %s\n", local_ip);
}
else {
printf("Failed to bind to IPv4 address: %s\n", local_ip);
}
}
else if (inet_pton(AF_INET6, local_ip, &sock_addr_ipv6.sin6_addr)) {
sock_addr_ipv6.sin6_family = AF_INET6;
sock_addr_ipv6.sin6_port = htons(MDNS_PORT);
#ifdef __APPLE__
sock_addr_ipv6.sin6_len = sizeof(struct sockaddr_in6);
#endif
int sock = mdns_socket_open_ipv6(&sock_addr_ipv6);
if (sock >= 0) {
sockets[num_sockets++] = sock;
printf("Bound to specific IPv6 address: %s\n", local_ip);
}
else {
printf("Failed to bind to IPv6 address: %s\n", local_ip);
}
}
else {
printf("Invalid local IP address: %s\n", local_ip);
}
}
if (num_sockets == 0) {
// 如果未指定 local_ip则绑定到所有接口
if (num_sockets < max_sockets) {
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
#ifdef _WIN32
sock_addr.sin_addr = in4addr_any;
#else
sock_addr.sin_addr.s_addr = INADDR_ANY;
#endif
sock_addr.sin_port = htons(MDNS_PORT);
#ifdef __APPLE__
sock_addr.sin_len = sizeof(struct sockaddr_in);
#endif
int sock = mdns_socket_open_ipv4(&sock_addr);
if (sock >= 0) {
sockets[num_sockets++] = sock;
printf("IPv4 socket opened successfully on port %d\n", MDNS_PORT);
}
else {
printf("Failed to open IPv4 socket on port %d\n", MDNS_PORT);
}
}
if (num_sockets < max_sockets) {
struct sockaddr_in6 sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin6_family = AF_INET6;
sock_addr.sin6_addr = in6addr_any;
sock_addr.sin6_port = htons(MDNS_PORT);
#ifdef __APPLE__
sock_addr.sin6_len = sizeof(struct sockaddr_in6);
#endif
int sock = mdns_socket_open_ipv6(&sock_addr);
if (sock >= 0) {
sockets[num_sockets++] = sock;
printf("IPv6 socket opened successfully on port %d\n", MDNS_PORT);
}
else {
printf("Failed to open IPv6 socket on port %d\n", MDNS_PORT);
}
}
}
return num_sockets;
}
// Send a DNS-SD query
static int
@ -862,10 +958,12 @@ send_mdns_query(mdns_query_t* query, size_t count, void* user_data) {
}
// Provide a mDNS service, answering incoming DNS-SD and mDNS queries
/*
int
service_mdns(const char* hostname, const char* service_name, int service_port) {
service_mdns(const char* hostname, const char* service_name, int service_port, const char* local_ip) {
int sockets[32];
int num_sockets = open_service_sockets(sockets, sizeof(sockets) / sizeof(sockets[0]));
//int num_sockets = open_service_sockets(sockets, sizeof(sockets) / sizeof(sockets[0]));
int num_sockets = open_service_sockets(sockets, sizeof(sockets) / sizeof(sockets[0]), local_ip);
if (num_sockets <= 0) {
printf("Failed to open any client sockets\n");
return -1;
@ -1037,6 +1135,183 @@ service_mdns(const char* hostname, const char* service_name, int service_port) {
mdns_socket_close(sockets[isock]);
printf("Closed socket%s\n", num_sockets ? "s" : "");
return 0;
}*/
int service_mdns(const char* hostname, const char* service_name, int service_port, const char* local_ip) {
int sockets[32];
int num_sockets = open_service_sockets(sockets, sizeof(sockets) / sizeof(sockets[0]), local_ip);
if (num_sockets <= 0) {
printf("Failed to open any client sockets\n");
return -1;
}
printf("Opened %d socket%s for mDNS service\n", num_sockets, num_sockets ? "s" : "");
size_t service_name_length = strlen(service_name);
if (!service_name_length) {
printf("Invalid service name\n");
return -1;
}
char* service_name_buffer = malloc(service_name_length + 2);
memcpy(service_name_buffer, service_name, service_name_length);
if (service_name_buffer[service_name_length - 1] != '.')
service_name_buffer[service_name_length++] = '.';
service_name_buffer[service_name_length] = 0;
service_name = service_name_buffer;
printf("Service mDNS: %s:%d\n", service_name, service_port);
printf("Hostname: %s\n", hostname);
size_t capacity = 2048;
void* buffer = malloc(capacity);
mdns_string_t service_string = (mdns_string_t){service_name, strlen(service_name)};
mdns_string_t hostname_string = (mdns_string_t){hostname, strlen(hostname)};
char service_instance_buffer[256] = {0};
snprintf(service_instance_buffer, sizeof(service_instance_buffer) - 1, "%.*s.%.*s",
MDNS_STRING_FORMAT(hostname_string), MDNS_STRING_FORMAT(service_string));
mdns_string_t service_instance_string =
(mdns_string_t){service_instance_buffer, strlen(service_instance_buffer)};
char qualified_hostname_buffer[256] = {0};
snprintf(qualified_hostname_buffer, sizeof(qualified_hostname_buffer) - 1, "%.*s.local.",
MDNS_STRING_FORMAT(hostname_string));
mdns_string_t hostname_qualified_string =
(mdns_string_t){qualified_hostname_buffer, strlen(qualified_hostname_buffer)};
service_t service = {0};
service.service = service_string;
service.hostname = hostname_string;
service.service_instance = service_instance_string;
service.hostname_qualified = hostname_qualified_string;
service.port = service_port;
if (local_ip) {
struct sockaddr_in addr_ipv4;
memset(&addr_ipv4, 0, sizeof(addr_ipv4));
addr_ipv4.sin_family = AF_INET;
if (inet_pton(AF_INET, local_ip, &addr_ipv4.sin_addr) <= 0) {
printf("Invalid local IP address: %s\n", local_ip);
free(service_name_buffer);
free(buffer);
return -1;
}
service.address_ipv4 = addr_ipv4;
} else {
service.address_ipv4 = service_address_ipv4;
}
// Setup mDNS records
service.record_ptr = (mdns_record_t){
.name = service.service,
.type = MDNS_RECORDTYPE_PTR,
.data.ptr.name = service.service_instance,
.rclass = 0,
.ttl = 120
};
service.record_srv = (mdns_record_t){
.name = service.service_instance,
.type = MDNS_RECORDTYPE_SRV,
.data.srv.name = service.hostname_qualified,
.data.srv.port = service.port,
.data.srv.priority = 0,
.data.srv.weight = 0,
.rclass = 0,
.ttl = 120
};
service.record_a = (mdns_record_t){
.name = service.hostname_qualified,
.type = MDNS_RECORDTYPE_A,
.data.a.addr = service.address_ipv4,
.rclass = 0,
.ttl = 120
};
service.record_aaaa = (mdns_record_t){
.name = service.hostname_qualified,
.type = MDNS_RECORDTYPE_AAAA,
.data.aaaa.addr = service.address_ipv6,
.rclass = 0,
.ttl = 120
};
service.txt_record[0] = (mdns_record_t){
.name = service.service_instance,
.type = MDNS_RECORDTYPE_TXT,
.data.txt.key = {MDNS_STRING_CONST("test")},
.data.txt.value = {MDNS_STRING_CONST("1")},
.rclass = 0,
.ttl = 120
};
service.txt_record[1] = (mdns_record_t){
.name = service.service_instance,
.type = MDNS_RECORDTYPE_TXT,
.data.txt.key = {MDNS_STRING_CONST("other")},
.data.txt.value = {MDNS_STRING_CONST("value")},
.rclass = 0,
.ttl = 120
};
printf("Sending announce\n");
mdns_record_t additional[5] = {0};
size_t additional_count = 0;
additional[additional_count++] = service.record_srv;
additional[additional_count++] = service.record_a;
additional[additional_count++] = service.txt_record[0];
additional[additional_count++] = service.txt_record[1];
for (int isock = 0; isock < num_sockets; ++isock)
mdns_announce_multicast(sockets[isock], buffer, capacity, service.record_ptr, 0, 0, additional, additional_count);
// Service loop
while (running) {
int nfds = 0;
fd_set readfs;
FD_ZERO(&readfs);
for (int isock = 0; isock < num_sockets; ++isock) {
if (sockets[isock] >= nfds)
nfds = sockets[isock] + 1;
FD_SET(sockets[isock], &readfs);
}
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 100000;
if (select(nfds, &readfs, 0, 0, &timeout) >= 0) {
for (int isock = 0; isock < num_sockets; ++isock) {
if (FD_ISSET(sockets[isock], &readfs)) {
mdns_socket_listen(sockets[isock], buffer, capacity, service_callback, &service);
}
FD_SET(sockets[isock], &readfs);
}
} else {
break;
}
}
printf("Sending goodbye\n");
additional_count = 0;
additional[additional_count++] = service.record_srv;
additional[additional_count++] = service.record_a;
additional[additional_count++] = service.txt_record[0];
additional[additional_count++] = service.txt_record[1];
for (int isock = 0; isock < num_sockets; ++isock)
mdns_goodbye_multicast(sockets[isock], buffer, capacity, service.record_ptr, 0, 0, additional, additional_count);
free(buffer);
free(service_name_buffer);
for (int isock = 0; isock < num_sockets; ++isock)
mdns_socket_close(sockets[isock]);
printf("Closed socket%s\n", num_sockets > 1 ? "s" : "");
return 0;
}
@ -1045,7 +1320,7 @@ service_mdns(const char* hostname, const char* service_name, int service_port) {
static int
dump_mdns(void) {
int sockets[32];
int num_sockets = open_service_sockets(sockets, sizeof(sockets) / sizeof(sockets[0]));
int num_sockets = open_service_sockets(sockets, sizeof(sockets) / sizeof(sockets[0]), "192.168.1.170");
if (num_sockets <= 0) {
printf("Failed to open any client sockets\n");
return -1;

View File

@ -177,7 +177,7 @@ struct mdns_query_t {
};
int
service_mdns(const char* hostname, const char* service_name, int service_port);
service_mdns(const char* hostname, const char* service_name, int service_port, const char* local_ip);
// mDNS/DNS-SD public API

View File

@ -176,7 +176,7 @@ void DataHandler::handleData(const QString& client, const QByteArray& recv
(msg_id != 0x0021 || clientLastMsgId.value(client, 0) != 0x0021) &&
(msg_id != START_VIDEO || clientLastMsgId.value(client, 0) != START_VIDEO)) {
//qDebug() << "Emitting statusUpdated for client:" << client << "with msg_id:" << QString::number(msg_id, 16).toUpper();
emit statusUpdated(client, success, jsonArray, itemJsonIndex);
emit statusUpdated(1, client, success, jsonArray, itemJsonIndex);
}
clientLastMsgId[client] = msg_id;
}
@ -330,7 +330,7 @@ void DataHandler::handleFrontCmd(int msg_id, const QString& client, QByteArray a
picBuffer->append(yuvData);
showPic(labelSize, lens_n, width, height, format, picBuffer);
QJsonObject currentTempItem = jsonArray[itemJsonIndex].toObject();
emit statusUpdated(client, true, jsonArray, itemJsonIndex);
emit statusUpdated(-1, client, true, jsonArray, itemJsonIndex);
picBuffer->remove(0, picSize);
}
else if (yuvData.size() + picBuffer->size() > picSize) {
@ -349,7 +349,7 @@ void DataHandler::handleFrontCmd(int msg_id, const QString& client, QByteArray a
if (!isStartVideo) {
isStartVideo = ffmpegDecoder->isStartVideo;
if (isStartVideo) {
emit statusUpdated(client, true, getVideoJson, 0);
emit statusUpdated(-1, client, true, getVideoJson, 0);
}
}
showVideo(client, actual_data);
@ -358,7 +358,7 @@ void DataHandler::handleFrontCmd(int msg_id, const QString& client, QByteArray a
case STOP_VIDEO:
{
isStartVideo = false;
emit statusUpdated(client, true, jsonArray, itemJsonIndex);
emit statusUpdated(-1, client, true, jsonArray, itemJsonIndex);
/*qDebug() << "--- STOP_VIDEO Current path: " << QDir::currentPath();
QString filePath = QDir::currentPath() + "/add1.h264";
if (QFile::exists(filePath)) {
@ -554,7 +554,7 @@ void DataHandler::handleBackCmd(int msg_id, const QString& client, QByteArray ac
if (!isStartVideo) {
isStartVideo = ffmpegDecoder->isStartVideo;
if (isStartVideo) {
emit statusUpdated(client, true, jsonArray, itemJsonIndex);
emit statusUpdated(1, client, true, jsonArray, itemJsonIndex);
}
}
QJsonObject jsonObject = jsonArray[itemJsonIndex].toObject();
@ -563,7 +563,7 @@ void DataHandler::handleBackCmd(int msg_id, const QString& client, QByteArray ac
}
else if (jsonObject["val"] == 1) {
isStartVideo = false;
emit statusUpdated(client, true, jsonArray, itemJsonIndex);
emit statusUpdated(1, client, true, jsonArray, itemJsonIndex);
qDebug() << "--- STOP_VIDEO";
if (ffmpegDecoder) {

View File

@ -50,7 +50,7 @@ public slots:
const QJsonArray& jsonArray, int itemJsonIndex);
void getCurrentSendItem(const QString& text);
signals:
void statusUpdated(const QString& clientAddress, bool success, const QJsonArray& jsonArray, int itemJsonIndex);
void statusUpdated(int boardTpye, const QString& clientAddress, bool success, const QJsonArray& jsonArray, int itemJsonIndex);
void updateLicenseHwInfoEdit(const QString& text);
void updateUuidHwInfoEdit(const QString& text);
void updateLeftLensImage(const QPixmap& pixmap);

View File

@ -0,0 +1,603 @@
// RecvDataHandler.cpp
#include "SerialRecvDataHandler.h"
#include "../Network/ClientHandler.h"
SerialDataHandler::SerialDataHandler(QLabel* videoLabel, QLabel* video_Label_back, QLineEdit* VideoResolutionEdit, QLineEdit* VideoResolutionEdit_back,
QSize labelSize, QMap<QString, QLineEdit*>* devInfoLineEdits, int isBackBoardOrAllBoard,
QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig,
QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson,
QJsonArray getPicJson, QJsonArray getVideoJson, QObject* parent)
: QObject(parent),
videoLabel(videoLabel),
video_Label_back(video_Label_back),
VideoResolutionEdit(VideoResolutionEdit),
VideoResolutionEdit_back(VideoResolutionEdit_back),
labelSize(labelSize),
devInfoLineEdits(devInfoLineEdits),
isBackBoardOrAllBoard(isBackBoardOrAllBoard),
frontBoardOneClickTest(frontBoardOneClickTest), frontBoardTest(frontBoardTest),
frontBoardFuncConfig(frontBoardFuncConfig), frontBoardDevInfoJson(frontBoardDevInfoJson),
frontBoardLicenseJson(frontBoardLicenseJson),
backBoardOneClickTest(backBoardOneClickTest), backBoardTest(backBoardTest),
backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson),
backBoardUuidJson(backBoardUuidJson), getPicJson(getPicJson), getVideoJson(getVideoJson),
buffer(new QByteArray()), picBuffer(new QByteArray()),
ffmpegDecoder(new FFmpegDecoder()) // 初始化FFmpeg解码器
{
//ffmpegDecoder->initialize(); // 初始化解码器
clearAllRecvData();
initializeMsgIdToCmdMap();
qDebug() << "SerialDataHandler thread created";
}
SerialDataHandler::~SerialDataHandler()
{
qDebug() << "DataHandler thread destroyed start......";
if (ffmpegDecoder) {
ffmpegDecoder->stopFFmpegDecoder();
ffmpegDecoder->requestInterruption();
ffmpegDecoder->wait(); // 等待解码器线程完成
delete ffmpegDecoder;
ffmpegDecoder = nullptr;
}
delete buffer;
buffer = nullptr;
qDebug() << "DataHandler thread destroyed";
}
void SerialDataHandler::handleOpenFocusWindow(int itemIndex)
{
if (ffmpegDecoder) {
ffmpegDecoder->processVideo(itemIndex); // 调用 FFmpegDecoder 的处理函数
}
}
QByteArray SerialDataHandler::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;
}
const QString filePath_1 = "/add1.h264";
// 显示视频的函数
void SerialDataHandler::showVideo(const QString& client, const QByteArray& valData)
{
QString h264filePath = QDir::currentPath() + filePath_1;
static QFile file(h264filePath);
if (!file.isOpen()) {
if (QFile::exists(h264filePath)) {
QFile::remove(h264filePath);
}
if (!file.open(QIODevice::Append | QIODevice::WriteOnly)) {
qWarning() << "无法打开H264文件:" << file.errorString();
return;
}
}
if (!valData.isEmpty()) {
file.write(valData);
file.flush(); // 刷新文件缓冲区
}
if (!start_run) {
ffmpegDecoder->initialize(); // 初始化解码器
start_run = 1;
ffmpegDecoder->decodeFile(h264filePath, isBackBoardOrAllBoard, videoLabel, video_Label_back, VideoResolutionEdit, VideoResolutionEdit_back);
}
//ffmpegDecoder->decodeFile(filePath_1, videoLabel);
}
void SerialDataHandler::updateLineEdit(int msg_id, const QByteArray& actual_data) {
QString dataStr = QString(actual_data.toHex(' '));
//licenseHwInfoEdit->setPlainText(dataStr);
emit updateLicenseHwInfoEdit(dataStr);
if (msgIdToCmdMap.contains(msg_id)) {
QString cmd = msgIdToCmdMap[msg_id];
if (devInfoLineEdits->contains(cmd)) {
QLineEdit* lineEdit = devInfoLineEdits->value(cmd);
//lineEdit->setText(dataStr);
QMetaObject::invokeMethod(lineEdit, "setText", Qt::QueuedConnection, Q_ARG(QString, dataStr));
}
}
}
void SerialDataHandler::clearAllRecvData() {
allRecvData = QByteArray();
remain = 0;
dataLen = 0;
}
void SerialDataHandler::onUpdateTimeout(bool timeoutFlag)
{
isTimeout = timeoutFlag;
}
// 前板没有回复的话不能发送下一个,但是超时了我必须发下一个
// 处理接收到的数据
void SerialDataHandler::handleData(const QString& client, const QByteArray& recvData, int msg_id,
int currentRecvItemIndex, int currentRecvFuncItemIndex, const QString& itemData,
const QString& funcItemData, const QJsonArray& jsonArray, int itemJsonIndex, bool timeoutFlag)
{
//qDebug() << "Data received from" << client << ":" << recvData;
#if 0
YUV数据
QFile file("output_2.txt");
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Failed to open file:";
file.close();
return;
}
QByteArray recvdata = file.readAll(); // 读取文件中的数据
file.close();
qDebug() << "read file data size:" << recvdata.size();
#endif
qDebug() << "---Received data size:" << recvData.size();
// 将接收到的数据追加到buffer
buffer->append(recvData);
while (buffer->size() >= 11) { // 至少需要11个字节来解析数据头
if (buffer->mid(0, 11) == QByteArray::fromHex("aa55aa5538010100000000")) {
/*for (int i = 0; i < recvData.size(); i++) {
qDebug() << "buffer->at(" << i << "):" << QString::number(static_cast<unsigned char>(buffer->at(i)), 16).toUpper();
}*/
QByteArray payload;
payload.append(static_cast<char>(0x00)); // 构造发送的数据内容
bool heartBeat = true;
emit sendHeartBeatData(payload, heartBeat);
buffer->remove(0, 11); // 移除已处理的数据
//buffer->remove(0, recvData.size()); // 移除已处理的数据
emit statusUpdated(-2, client, true, jsonArray, itemJsonIndex);
//break;
continue;
}
else if (buffer->mid(0, 10) == QByteArray::fromHex("aa55aa55390103000000")) {
buffer->remove(0, 13); // 移除已处理的数据
break;
}
else if ((buffer->mid(0, 6) == QByteArray::fromHex("aa55aa553701")) ||
(buffer->mid(0, 6) == QByteArray::fromHex("aa55aa551100")) ||
(buffer->mid(0, 6) == QByteArray::fromHex("aa55aa552100"))) {
int dataSize = (static_cast<unsigned char>(buffer->at(9)) << 24) |
(static_cast<unsigned char>(buffer->at(8)) << 16) |
(static_cast<unsigned char>(buffer->at(7)) << 8) |
(static_cast<unsigned char>(buffer->at(6)));
if (buffer->size() >= dataSize + 10)
buffer->remove(0, dataSize + 10); // 移除已处理的数据
break;
}
else if (buffer->mid(0, 4) == QByteArray::fromHex("aa55aa55")) {
emit startTimeout(0);
msg_id = (static_cast<unsigned char>(buffer->at(5)) << 8) |
(static_cast<unsigned char>(buffer->at(4)));
int dataSize = (static_cast<unsigned char>(buffer->at(9)) << 24) |
(static_cast<unsigned char>(buffer->at(8)) << 16) |
(static_cast<unsigned char>(buffer->at(7)) << 8) |
(static_cast<unsigned char>(buffer->at(6)));
qDebug() << "---Received dataSize:" << dataSize;
//qDebug() << "---Received buffer->size():" << buffer->size();
//qDebug() << "---msg_id:" << QString::number(msg_id, 16).toUpper();
// 第11字节为返回 OK/NG
bool success = (static_cast<unsigned char>(buffer->at(10)) != 0x00);
int totalSize = 10 + dataSize; // 数据头大小(10字节) + 实际数据大小
if (CurrentCommand == "GET_BACK_MAC") {
//qDebug() << "--- getCommandNameFromValue:" << msg_id;
if (!getCommandNameFromValue(msg_id)) {
//qDebug() << "--- getCommandNameFromValue:" << msg_id;
buffer->remove(0, buffer->size());
emit commandError();
break;
}
}
if (buffer->size() >= totalSize) {
//qDebug() << "--- getCommandNameFromValue:" << msg_id;
// 调试查看收到的前19个字节
/*for (int i = 0; i < 11; i++) {
qDebug() << "buffer->at(" << i << "):" << QString::number(static_cast<unsigned char>(buffer->at(i)), 16).toUpper();
}*/
QByteArray data = buffer->mid(11, dataSize);
QString hexString = QString::fromUtf8(data.toHex().data());
QByteArray actual_data = hexStringToByteArray(hexString);
buffer->remove(0, totalSize); // 移除已处理的数据
qDebug() << "-------------------------------------------- isTimeout:" << isTimeout;
if (!isTimeout)
{
if (msg_id != 0x0040 && msg_id != START_VIDEO && msg_id != GET_IMG && msg_id != VIDEO_TEST &&
msg_id != STOP_VIDEO) {
qDebug() << "--- msg_id:" << QString::number(msg_id, 16).toUpper();
qDebug() << "--- clientLastMsgId.value(client, 0):" << clientLastMsgId.value(client, 0);
qDebug() << "--- success:" << success;
//qDebug() << "--- itemJsonIndex:" << itemJsonIndex;
if ((msg_id != 0x0011 || clientLastMsgId.value(client, 0) != 0x0011) &&
(msg_id != 0x0021 || clientLastMsgId.value(client, 0) != 0x0021) &&
(msg_id != START_VIDEO || clientLastMsgId.value(client, 0) != START_VIDEO)) {
//qDebug() << "Emitting statusUpdated for client:" << client << "with msg_id:" << QString::number(msg_id, 16).toUpper();
emit statusUpdated(-1, client, success, jsonArray, itemJsonIndex);
emit recvNormalDataFlag(true);
}
clientLastMsgId[client] = msg_id;
}
handleCmd(msg_id, client, actual_data, jsonArray, itemJsonIndex);
}
}
else {
break; // 数据还不完整,等待下一次接收
}
}
else {
buffer->remove(0, 1); // 移除无效数据头
}
}
}
void SerialDataHandler::getCurrentSendItem(const QString& text) {
CurrentCommand = text;
}
// 初始化映射表
std::map<QString, int> commandValueMap_serical = {
{"FACE_ENROLL_SINGLE", FACE_ENROLL_SINGLE},
{"FACE_ENROLL", FACE_ENROLL},
{"HAND_ENROLL", HAND_ENROLL},
{"FACE_VERIFY", FACE_VERIFY},
{"HAND_VERIFY", HAND_VERIFY},
{"DEL_USER", DEL_USER},
{"DEL_ALLUSER", DEL_ALLUSER},
{"GET_USER", GET_USER},
{"GET_ALLUSER", GET_ALLUSER},
{"PASSWD_ENROLL", PASSWD_ENROLL},
{"IMG_ENROLL", IMG_ENROLL},
{"GET_IMG", GET_IMG},
{"START_VIDEO", START_VIDEO},
{"STOP_VIDEO", STOP_VIDEO},
{"TOUCH_TEST", TOUCH_TEST},
{"MIC_TEST", MIC_TEST},
{"SPK_TEST", SPK_TEST},
{"RADAR_TEST", RADAR_TEST},
{"NFC_TEST", NFC_TEST},
{"PR_SWITCH", PR_SWITCH},
{"PS_TEST", PS_TEST},
{"BACKLIGHT", BACKLIGHT},
{"IR_LED", IR_LED},
{"UART_TEST", UART_TEST},
{"PIR_TEST", PIR_TEST},
{"FACE_VERIFY_THRES", FACE_VERIFY_THRES},
{"FACE_THRES_LEVEL", FACE_THRES_LEVEL},
{"FACE_LIVE_THRES", FACE_LIVE_THRES},
{"FACE_ACC_THRES", FACE_ACC_THRES},
{"FACE_ACC_LEVEL", FACE_ACC_LEVEL},
{"FACE_DIS_RANGE", FACE_DIS_RANGE},
{"FACE_ANGLE_RANGE", FACE_ANGLE_RANGE},
{"GET_BACK_MAC", GET_BACK_MAC},
{"WRITE_BACK_UID_SN", WRITE_BACK_UID_SN}
};
bool SerialDataHandler::getCommandNameFromValue(int receivedValue) {
auto it = commandValueMap_serical.find(CurrentCommand);
if (it != commandValueMap_serical.end()) {
int expectedValue = it->second;
if (expectedValue == receivedValue) {
std::cout << "Match found: " << CurrentCommand.toStdString() << " corresponds to value " << std::hex << expectedValue << std::endl;
return true;
}
else {
std::cout << "Value mismatch: Expected " << std::hex << expectedValue << ", but received " << std::hex << receivedValue << std::endl;
return false;
}
}
else {
std::cout << "Unknown command: " << CurrentCommand.toStdString() << std::endl;
return false;
}
}
void SerialDataHandler::initializeMsgIdToCmdMap() {
msgIdToCmdMap[GET_FRONT_V851_VERSION] = "GET_FRONT_V851_VERSION";
msgIdToCmdMap[GET_FRONT_MCU_VERSION] = "GET_FRONT_MCU_VERSION";
msgIdToCmdMap[GET_FRONT_HW_VERSION] = "GET_FRONT_HW_VERSION";
msgIdToCmdMap[GET_FRONT_ALGO_VERSION] = "GET_FRONT_ALGO_VERSION";
msgIdToCmdMap[GET_FRONT_SN] = "GET_FRONT_SN";
msgIdToCmdMap[GET_BACK_V851_VERSION] = "GET_BACK_V851_VERSION";
msgIdToCmdMap[GET_BACK_806_VERSION] = "GET_BACK_806_VERSION";
msgIdToCmdMap[GET_BACK_HW_VERSION] = "GET_BACK_HW_VERSION";
}
void SerialDataHandler::handleCmd(int msg_id, const QString& client, QByteArray actual_data, const QJsonArray& jsonArray, int itemJsonIndex)
{
if (msg_id < 0x0400) {
handleFrontCmd(msg_id, client, actual_data, jsonArray, itemJsonIndex);
}
else if (msg_id < 0x0500) {
handleDevInfo(msg_id, client, actual_data);
}
else if (msg_id < 0x0800) {
//handleBackCmd(msg_id, client, actual_data, jsonArray, itemJsonIndex);
}
}
void SerialDataHandler::handleFrontCmd(int msg_id, const QString& client, QByteArray actual_data, const QJsonArray& jsonArray, int itemJsonIndex)
{
switch (msg_id) {
case FACE_ENROLL_SINGLE:
{}
break;
case FACE_ENROLL:
{}
break;
case HAND_ENROLL:
{}
break;
case FACE_VERIFY:
{}
break;
case HAND_VERIFY:
{}
break;
case DEL_USER:
{}
break;
case DEL_ALLUSER:
{}
break;
case GET_USER:
{}
break;
case GET_ALLUSER:
{}
break;
case PASSWD_ENROLL:
{}
break;
case IMG_ENROLL:
{}
break;
case GET_IMG:
{
int lens_n = static_cast<unsigned char>(actual_data[1]);
int width = (static_cast<unsigned char>(actual_data[3]) << 8) | static_cast<unsigned char>(actual_data[2]);
int height = (static_cast<unsigned char>(actual_data[5]) << 8) | static_cast<unsigned char>(actual_data[4]);
int format = static_cast<unsigned char>(actual_data[6]);
qint32 picSize = width * height * 1.5;
QByteArray yuvData = actual_data.mid(7);
qDebug() << "showPic width * height * 1.5:" << picSize;
qDebug() << "showPic picBuffer.size():" << picBuffer->size();
qDebug() << "showPic yuvData.size():" << yuvData.size();
if (yuvData.size() + picBuffer->size() == picSize) {
emit picRecvFinished();
picBuffer->append(yuvData);
showPic(labelSize, lens_n, width, height, format, picBuffer);
QJsonObject currentTempItem = jsonArray[itemJsonIndex].toObject();
emit statusUpdated(-1, client, true, jsonArray, itemJsonIndex);
picBuffer->remove(0, picSize);
}
else if (yuvData.size() + picBuffer->size() > picSize) {
picBuffer->append(yuvData);
qDebug() << "width is " << width << " height is " << height << "PIC size is" << picSize;
qDebug() << "But recv PIC size is " << picBuffer->size();
picBuffer->remove(0, picBuffer->size());
}
else {
picBuffer->append(yuvData);
}
}
break;
case START_VIDEO:
{
if (!isStartVideo) {
isStartVideo = ffmpegDecoder->isStartVideo;
if (isStartVideo) {
emit statusUpdated(-1, client, true, getVideoJson, 0);
}
}
showVideo(client, actual_data);
}
break;
case STOP_VIDEO:
{
isStartVideo = false;
emit statusUpdated(-1, client, true, jsonArray, itemJsonIndex);
/*qDebug() << "--- STOP_VIDEO 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.";
}*/
}
break;
case TOUCH_TEST:
{}
break;
case MIC_TEST:
{}
break;
case SPK_TEST:
{}
break;
case RADAR_TEST:
{}
break;
case NFC_TEST:
{}
break;
case PR_SWITCH:
{}
break;
case PS_TEST:
{}
break;
case BACKLIGHT:
{}
break;
case IR_LED:
{}
break;
case UART_TEST:
{}
break;
case PIR_TEST:
{}
break;
case FACE_VERIFY_THRES:
{}
break;
case FACE_THRES_LEVEL:
{}
break;
case FACE_LIVE_THRES:
{}
break;
case FACE_ACC_THRES:
{}
break;
case FACE_ACC_LEVEL:
{}
break;
case FACE_DIS_RANGE:
{}
break;
case FACE_ANGLE_RANGE:
{}
break;
case HAND_VERIFY_THRES:
{}
break;
case HANS_THRES_LEVEL:
{}
break;
case HAND_LIVE_THRES:
{}
break;
case USER_MAX_NUM:
{}
break;
case ADMI_USER_MAX_NUM:
{}
break;
case FACE_REPEAT:
{}
break;
case HAND_REPEAT:
{}
break;
case SET_IP:
{}
break;
case SET_PORT:
{}
break;
case SET_VOLUME:
{}
break;
case SET_BACKLIGHT:
{}
break;
case SET_RADAR_DIS:
{}
break;
case SET_UART_BARTRATE:
{}
break;
case SET_LOG_LEVEL:
{}
break;
default:
{}
break;
}
}
void SerialDataHandler::handleDevInfo(int msg_id, const QString& client, QByteArray actual_data)
{
qDebug() << "actual_data.size(): " << actual_data.size();
qDebug() << "actual_data: " << QString::fromUtf8(actual_data.toHex().data());
switch (msg_id) {
case GET_FRONT_V851_VERSION:
case GET_FRONT_MCU_VERSION:
case GET_FRONT_HW_VERSION:
case GET_FRONT_ALGO_VERSION:
case GET_FRONT_SN:
case GET_BACK_V851_VERSION:
case GET_BACK_806_VERSION:
case GET_BACK_HW_VERSION:
/*case GET_BACK_SN:
case GET_BACK_UID:*/
{
// aa55aa5503041d00000048464d3231305f4b3431343234395f423230323031305f41302e302e38
qDebug() << "GET_DEV_INFO";
QString dataStr = QString::fromUtf8(actual_data);
if (msgIdToCmdMap.contains(msg_id)) {
QString cmd = msgIdToCmdMap[msg_id];
// 删掉注释闪退,暂时还未查到原因
qDebug() << "-----------------devInfoLineEdits-------------start";
//qDebug() << "devInfoLineEdits belongs to thread:" << devInfoLineEdits->thread();
qDebug() << "Current thread:" << QThread::currentThread();
if (devInfoLineEdits->contains(cmd)) {
QLineEdit* lineEdit = devInfoLineEdits->value(cmd);
//lineEdit->setText(dataStr);
QMetaObject::invokeMethod(lineEdit, "setText", Qt::QueuedConnection, Q_ARG(QString, dataStr));
}
qDebug() << "-----------------devInfoLineEdits-------------end";
}
//qDebug() << "GET_DEV_INFO msg_id:" << QString::number(msg_id, 16).toUpper();
}
break;
case GET_FRONT_HW_INFO:
{
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);
}
break;
case GET_BACK_MAC:
{
qDebug() << "GET_BACK_MAC";
QString dataStr;
if (actual_data.size() == BACK_MAC_ADDRESS_LEN) {
for (int i = 0; i < actual_data.size(); ++i) {
char ch = static_cast<unsigned char>(actual_data[i]);
dataStr.append(ch);
}
}
else
dataStr = "后板发送的 MAC addr 数据大小不正确";
QString displayText = dataStr;
emit updateUuidHwInfoEdit(displayText);
}
break;
default:
break;
}
}

View File

@ -0,0 +1,121 @@
// SerialRecvDataHandler.h
#ifndef SERIALRECVDATAHANDLER_H
#define SERIALRECVDATAHANDLER_H
#include <QObject>
#include <QByteArray>
#include <QLabel>
#include <QGroupBox>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QPixmap>
#include <QBuffer>
#include <QImage>
#include <QVBoxLayout>
#include <QDebug>
#include <QFile>
#include <QThread>
#include <QElapsedTimer>
#include <QLineEdit>
#include <QTextEdit>
#include "../Media/Media.h"
#include "../Media/VideoDecoder/FFmpegDecoder.h"
#include "../LicenseGenerate/LicenseGenerate.h"
#include "MsgTpye.h"
#define YUV420 1
#define YUV422 2
#define BACK_MAC_ADDRESS_LEN 17
class SerialDataHandler : public QObject
{
Q_OBJECT
public:
explicit SerialDataHandler(QLabel* videoLabel, QLabel* video_Label_back, QLineEdit* VideoResolutionEdit, QLineEdit* VideoResolutionEdit_back,
QSize labelSize, QMap<QString, QLineEdit*>* devInfoLineEdits, int isBackBoardOrAllBoard,
QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig,
QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson,
QJsonArray getPicJson, QJsonArray getVideoJson, QObject* parent = nullptr);
~SerialDataHandler();
public slots:
void handleData(const QString& client, const QByteArray& data, int msg_id, int currentRecvItemIndex,
int currentRecvFuncItemIndex, const QString& itemData, const QString& funcItemData,
const QJsonArray& jsonArray, int itemJsonIndex, bool timeoutFlag);
void getCurrentSendItem(const QString& text);
void onUpdateTimeout(bool timeoutFlag);
void handleOpenFocusWindow(int itemIndex);
signals:
void statusUpdated(int boardTpye, const QString& clientAddress, bool success, const QJsonArray& jsonArray, int itemJsonIndex);
void updateLicenseHwInfoEdit(const QString& text);
void updateUuidHwInfoEdit(const QString& text);
void updateLeftLensImage(const QPixmap& pixmap);
void updateRightLensImage(const QPixmap& pixmap);
void updateVideoLabel(const QPixmap& pixmap);
void updateVideoResolution(const QString& resolutionText);
void picRecvFinished();
void commandError();
void sendHeartBeatData(const QByteArray& payload, int heartBeat);
void startTimeout(int timeout);
void recvNormalDataFlag(bool flag);
private:
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和SN参数 JSON
QJsonArray getDevInfoJson; // 获取设备信息 JSON 配置
QJsonArray getPicJson; // 发送取图指令 JSON 配置
QJsonArray getVideoJson; // 发送拉视频指令 JSON 配置
//QLabel* leftLens_m_imageLabel;
//QLabel* rightLens_m_imageLabel;
QLabel* videoLabel;
QLabel* video_Label_back;
QLineEdit* VideoResolutionEdit;
QLineEdit* VideoResolutionEdit_back;
//QTextEdit* licenseHwInfoEdit;
QByteArray allRecvData; // 完整的一帧数据
int remain = 0;
int start_run = 0;
long dataLen = 0;
int isBackBoardOrAllBoard = 0;
FFmpegDecoder* ffmpegDecoder;
QByteArray* buffer;
QByteArray* picBuffer;
QHash<QString, unsigned char> clientLastMsgId;
QMap<QString, QLineEdit*>* devInfoLineEdits;
QMap<int, QString> msgIdToCmdMap;
QSize labelSize;
bool isStartVideo = false;
bool isTimeout = false;
QString CurrentCommand = "";
bool getCommandNameFromValue(int receivedValue);
QByteArray hexStringToByteArray(const QString& hexString);
void showVideo(const QString& client, const QByteArray& valData);
void clearAllRecvData();
void handleCmd(int msg_id, const QString& client, QByteArray actual_data, const QJsonArray& jsonArray, int itemJsonIndex);
void handleFrontCmd(int msg_id, const QString& client, QByteArray actual_data, const QJsonArray& jsonArray, int itemJsonIndex);
void handleDevInfo(int msg_id, const QString& client, QByteArray actual_data);
void initializeMsgIdToCmdMap();
void updateLineEdit(int msg_id, const QByteArray& actual_data);
void showPic(QSize labelSize, int lens_n,
int width, int height, int format, const QByteArray* valData);
};
#endif // SERIALDATAHANDLER_H

File diff suppressed because it is too large Load Diff

View File

@ -46,13 +46,20 @@
#include <QSettings>
#include <QImage>
#include <QPainter>
#include <QComboBox>
#include <QVector>
#include <QSerialPortInfo>
#include <QStringList>
#include <QSerialPort>
#include <winsock2.h>
#include <iphlpapi.h>
#include "./UI_Widget/UI_Name.h"
#include "./SerialPortHandler/SerialPortHandler.h"
#include "../Json/readJsonFile.h"
#include "../RecvDataHandler/RecvDataHandler.h"
#include "../RecvDataHandler/SerialRecvDataHandler.h"
#include "../LicenseGenerate/LicenseGenerate.h"
#include "../LicenseGenerate/LicenseConfirmWindow.h"
//#include "../Network/mdns/servicemodel.h"
@ -68,20 +75,20 @@
//#include "../Network/mdns/qmdnsengine/include/message.h"
//#include "../Network/mdns/qmdnsengine/include/query.h"
#define TEST_UDP_BROADCAST 0 // 用于测试 UDP 组播实现 mdns 功能 非标准 mdns
#define MANUAL_UPLOAD_LICENSE 0 // 打开手动上传 License的功能
#define TEST_UDP_BROADCAST 0 // 用于测试 UDP 组播实现 mdns 功能 非标准 mdns
#define MANUAL_UPLOAD_LICENSE 0 // 打开手动上传 License的功能
#define START_MDNS 1
#define FOCUS_WINDOWS_BUTTON 4 // 大窗口播放视频的按键编号
#define TCP_CONNECT_PORT 12412 // TCP监听的端口
#define FOCUS_WINDOWS_BUTTON 4 // 大窗口播放视频的按键编号
#define TCP_CONNECT_PORT 12412 // TCP监听的端口
#define GET_PIC_DATA_SIZE (480 * 640 * 1.5)
#define NEW_MAP 1
#define FACTORY_ID "TEST" // 工厂ID
#define LABEL "TEST_SL100_20240826" // 出货标签
#define BATCH 1 // 出货批次
#define MODEL "SL100" // 出货型号
#define FACTORY_ID "TEST" // 工厂ID
#define LABEL "TEST_SL100_20240826" // 出货标签
#define BATCH 1 // 出货批次
#define MODEL "SL100" // 出货型号
class MainWidget : public QWidget
{
@ -93,11 +100,18 @@ public:
~MainWidget();
void startHttpServer(const QString& imagePath);
void sendLicenseData(int itemIndex, const QString text);
QByteArray hexStringToByteArray(const QString& hexString);
signals:
void openFocusWindowRequested(int itemIndex);
void serialComPortConnected();
void requestDevInfo();
void delUserDialogResult(const QString& userInput);
void openFocusWindow(int itemIndex);
private slots:
void onSerialDataReceived(const QByteArray& data);
// 发送HTTP请求
//void onSomeButtonClicked();
// 处理HTTP响应
@ -127,9 +141,9 @@ private slots:
// 处理数据接收信号
//void onDataReceived(const QString& client, const QByteArray& data);
// 处理状态更新信号
void onStatusUpdated(const QString& client, bool success, const QJsonArray& jsonArray, int itemJsonIndex);
void onStatusUpdated(int boardTpye, const QString& client, bool success, const QJsonArray& jsonArray, int itemJsonIndex);
// 处理所有项目处理完毕信号
void onAllItemsProcessed(const QString& client, int itemsProcessedCount);
void onAllItemsProcessed(int boardTpye, const QString& client, int itemsProcessedCount);
// 处理客户端断开连接
void onClientDisconnected(ClientHandler* handler);
// 启动超时定时器
@ -149,10 +163,14 @@ private slots:
void onCheckConnectionStatus();
void startClientReadTimer(int clientId);
void stopClientReadTimer(int clientId);
void onCheckSerialRecvStatus();
void onShowDialog();
#if TEST_UDP_BROADCAST
void sendMulticastMessage();
#endif
//void onIpSelectionChanged(const QString& selectedIp);
private:
UI_config TOOL_UI;
// 读取 test JSON 配置文件
@ -168,6 +186,9 @@ private:
QLabel* leftLensLabel, QLabel* rightLensLabel, QLabel* videoLabel,
QLineEdit* VideoResolutionEdit_type);
void addAllDeviceAreaTab(QTabWidget* mainTabWidget, const QString& tabName,
const QJsonArray& boardTest, const QJsonArray& boardFuncConfig,
const QString& boardTestName, const QString& boardFuncConfigName,
const QString& boardTestTitle, const QString& boardConfigTitle,
QLabel* leftLensLabel, QLabel* rightLensLabel, QLabel* videoLabel,
QLineEdit* VideoResolutionEdit_type);
QTabWidget* createMediaTabWidget(QLabel* leftLensLabel, QLabel* rightLensLabel, QLabel* videoLabel,
@ -196,6 +217,8 @@ private:
void FactoryToolSendPostComfirmToHttpServer(const QString& mac_addr, const QString& uuid);
void FactoryToolSendGetUuidToHttpServer(const QString& mac_addr);
void FactoryToolSendGetLicenseToHttpServer(const QString& hw_info);
char* getSelectedIp() const;
QTcpServer* server; // TCP 服务器
HttpClient* httpClient; // HTTP 服务器
@ -212,8 +235,8 @@ private:
QJsonArray backBoardUuidJson; // 后板UUID JSON
QJsonArray backBoardCmdConfigJson;
QJsonArray factoryProductInfo; // 整机:工厂生产信息
QJsonArray testJsonConfig; // 功能测试区 JSON 配置
QJsonArray funcJsonConfig; // 功能配置区 JSON 配置
QJsonArray allBoardTest; // 整机测试区 JSON 配置
QJsonArray allBoardFuncConfig; // 整机功能配置区 JSON 配置
QJsonArray getDevInfoJson; // 获取设备信息 JSON 配置
QJsonArray getPicJson; // 发送取图指令 JSON 配置
QJsonArray getVideoJson; // 发送拉视频指令 JSON 配置
@ -225,14 +248,17 @@ private:
QThreadPool threadPool; // 线程池
QMutex mutex; // 互斥锁
int nextClientId; // 新增的客户端编号
int nextSerialId; // 新增的客户端编号
int currentIndex = 0; // 新增的客户端编号
int connectedClientsCount = 0; // 连接客户端的数量
int isRequestSuccessful = 0; // GET请求是否成功
int isBackBoardOrAllBoard = 0;
bool manualSend; // 判断是否是手动触发的发送
bool deviceConnected = false; // 判断是否有设备连接过
bool isSendingAll; // 一键功能测试 状态
bool checkBoxState = true;
bool isReplyOrTimeout = true;
bool checkBoxState = true;
bool isReplyOrTimeout = true;
bool isFirstSendDevInfo = true;
QJsonObject licenseDataArray; // 用于保存从服务器获取的 data 字段对象
@ -243,12 +269,17 @@ private:
QVector<QPushButton*> getBackVideoButtons;
QVector<QPushButton*> getAllVideoButtons;
QList<ClientHandler*> clients; // 客户端处理器集合
QList<SerialPortHandler*> serialPorts; // 客户端处理器集合
QMap<int, QTimer*> clientTimers; // 每个客户端的定时器
QMap<int, QTimer*> serialTimers; // 每个串口端的定时器
QMap<QString, QLineEdit*> devInfoLineEdits;// msg_id 和对应的 QLineEdit 的映射关系
QMap<QString, QLineEdit*> productInfoLineEdits;
QString cur_mac_addr;
QString cur_UUID;
QCheckBox* saveCheckBox; // 保存文件复选框
QPushButton* selectFileButton; // Save Log 按键
QPushButton* serialConnectButton; // 串口连接按键
QPushButton* clearLogButton; // clear Log 按键
QLineEdit* filePathLineEdit; // 文件路径显示
QLineEdit* VideoResolutionEdit; // 视频分辨率显示
@ -272,24 +303,28 @@ private:
QTabWidget* tabWidget; // 标签页
QWidget* functionTestArea; // 功能测试区
QWidget* functionConfigArea; // 功能配置区
QComboBox* ipComboBox;
QComboBox* serialComPortComboBox;
int lastClickedGetPicCamIndex; // 记录上一次点击取图的摄像头的按键索引
int lastClickedGetPicDevIndex; // 记录上一次点击取图的设备的按键索引
int lastClickedGetVideoCamIndex; // 记录上一次点击拉视频的摄像头的按键索引
int lastClickedGetVideoDevIndex; // 记录上一次点击拉视频的设备的按键索引
//QTimer* serialTimer;
QTimer* threadStatusTimer; // 检查线程状态的定时器
QTimer* connectionStatusCheckTimer; // 检查连接状态的定时器
QMap<int, DataHandler*> dataHandlers;
QMap<int, DataHandler*> dataHandlers;
QMap<int, SerialDataHandler*> serialDataHandlers;
QMap<int, QThread*> clientThreads;
QMap<int, QTimer*> clientReadTimers;
QMap<int, ClientHandler*> clients_1;
//ServiceProvider* mServiceProvider;
QTimer* mdnsTimer;
void startMdnsService();
void startMdnsService(char* select_ip);
void stopMdnsService();
void sendSerialData(const QByteArray& data, bool heartBeat);
#if TEST_UDP_BROADCAST
QUdpSocket* multicastSocket;
QTimer* multicastTimer;
@ -302,6 +337,9 @@ private:
void setupHttpServer(); // 初始化 HTTP 服务器
void handleHttpRequest(QTcpSocket* clientSocket); // 处理 HTTP 请求
MdnsServiceThread* mdnsThread; // mDNS 线程指针
SerialPortHandler* serialPortHandler;
//QTimer* portDetectionTimer;
//QThread* thread;
};
#endif // MAINWIDGET_H

View File

@ -0,0 +1,894 @@
// SerialPortHandler.cpp
#include "SerialPortHandler.h"
SerialPortHandler::SerialPortHandler(QComboBox* comPortComboBox, QPushButton* connectButton,
QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardDevInfoJson,
QJsonArray backBoardUuidJson, QJsonArray getPicJson, QJsonArray getVideoJson, QObject* parent)
: QObject(parent), comPortComboBox(comPortComboBox), connectButton(connectButton), worker(nullptr), serialPort(nullptr),
frontBoardOneClickTest(frontBoardOneClickTest), frontBoardTest(frontBoardTest),
frontBoardFuncConfig(frontBoardFuncConfig), frontBoardDevInfoJson(frontBoardDevInfoJson),
frontBoardLicenseJson(frontBoardLicenseJson),
backBoardOneClickTest(backBoardOneClickTest), backBoardTest(backBoardTest),
backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson),
backBoardUuidJson(backBoardUuidJson), getPicJson(getPicJson), getVideoJson(getVideoJson),
currentItemIndex(0), isManualSend(false), isSingleSend(false), isClickedSend(false),
isFirstDataReceived(true),
isDataStuck(false), dataProcessingActive(false), isRecvVideoData(true),
currentFrontBoardIndex(0), currentLicenseIndex(0)
{
serialPort = new QSerialPort();
serialPort->setParent(nullptr);
serialTimer = nullptr;
//serialTimer->moveToThread(QThread::currentThread());
//connect(serialTimer, &QTimer::timeout, this, &SerialPortHandler::onTimeout);
portDetectionTimer = nullptr;
//portDetectionTimer->moveToThread(QThread::currentThread());
//connect(portDetectionTimer, &QTimer::timeout, this, &SerialPortHandler::updateAvailablePorts);
//portDetectionTimer->start(2000); // 每2秒检测一次串口
// 初始化串口端口
updateAvailablePorts();
// 连接按钮点击时的处理
connect(connectButton, &QPushButton::clicked, this, &SerialPortHandler::toggleConnection);
//connect(serialPort, &QSerialPort::errorOccurred, this, &SerialPortHandler::handleSerialError);
}
SerialPortHandler::~SerialPortHandler()
{
if (serialTimer) {
serialTimer->stop();
delete serialTimer;
serialTimer = nullptr;
}
if (portDetectionTimer) {
portDetectionTimer->stop();
delete portDetectionTimer;
portDetectionTimer = nullptr;
}
if (worker) {
worker->stop();
worker->wait(); // 确保线程已停止
delete worker;
worker = nullptr;
}
if (serialPort->isOpen()) {
serialPort->close();
}
}
void SerialPortHandler::initializeSerialPort()
{
serialPort = new QSerialPort(this); // 在目标线程中创建
serialPort->setParent(nullptr); // 保证没有父对象,避免跨线程的问题
connect(serialPort, &QSerialPort::errorOccurred, this, &SerialPortHandler::handleSerialError, Qt::QueuedConnection);
}
void SerialPortHandler::initializeTimers()
{
// 确保定时器在当前线程中创建
serialTimer = new QTimer(this);
serialTimer->setSingleShot(true);
//serialTimer->moveToThread(this->thread());
connect(serialTimer, &QTimer::timeout, this, &SerialPortHandler::onTimeout);
portDetectionTimer = new QTimer();
//portDetectionTimer->moveToThread(this->thread());
connect(portDetectionTimer, &QTimer::timeout, this, &SerialPortHandler::updateAvailablePorts);
QMetaObject::invokeMethod(portDetectionTimer, "start", Qt::QueuedConnection, Q_ARG(int, 2000));
qDebug() << "Current thread in initializeTimers:" << QThread::currentThread();
qDebug() << "SerialPortHandler thread:" << this->thread();
qDebug() << "serialTimer thread:" << serialTimer->thread();
qDebug() << "portDetectionTimer thread:" << portDetectionTimer->thread();
}
void SerialPortHandler::OnStartTimeout(int timeout)
{
qDebug() << "---------------> onStartTimeout timeout :" << timeout;
qDebug() << "Current thread:" << QThread::currentThread();
qDebug() << "serialTimer thread:" << serialTimer->thread();
// 确保在正确线程中启动或停止定时器
if (timeout > 0) {
qDebug() << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
//QMetaObject::invokeMethod(serialTimer, "start", Qt::QueuedConnection, Q_ARG(int, timeout));
QMetaObject::invokeMethod(serialTimer, "start", Qt::DirectConnection, Q_ARG(int, timeout));
}
else {
//QMetaObject::invokeMethod(serialTimer, "stop", Qt::QueuedConnection);
QMetaObject::invokeMethod(serialTimer, "stop", Qt::DirectConnection);
}
qDebug() << "---------------> onStartTimeout end ";
}
void SerialPortHandler::handleSerialError(QSerialPort::SerialPortError error)
{
if (error == QSerialPort::ResourceError) {
qDebug() << "Serial port error occurred. Disconnecting.";
disconnectPort();
emit serialComPortDisconnected();
}
}
void SerialPortHandler::onSendHeartBeatData(const QByteArray& data, bool heartBeat) {
QByteArray prefix;
QDataStream stream(&prefix, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
// 构造前缀
stream << quint32(0x55AA55AA); // 固定前缀
stream << quint16(0x0138); // 回复心跳
stream << quint32(data.size()); // 数据长度
prefix.append(data); // 将实际数据追加到前缀后
qDebug() << "Send heartBeat data:----->" << prefix.toHex();
if (serialPort->isOpen()) {
serialPort->write(prefix);
serialPort->flush(); // 确保数据立即发送
}
else {
qDebug() << "Serial port is not open!";
}
}
void SerialPortHandler::sendData(const QByteArray& data, bool heartBeat) {
QByteArray prefix;
QDataStream stream(&prefix, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
// 构造前缀
stream << quint32(0x55AA55AA); // 固定前缀
if (heartBeat) {
stream << quint16(0x0138); // 回复心跳
}
else {
stream << quint16(0x0420); // 回复产测指令
}
stream << quint32(data.size()); // 数据长度
prefix.append(data); // 将实际数据追加到前缀后
qDebug() << "heartBeat:----->" << heartBeat;
qDebug() << "Send data:----->" << prefix.toHex();
if (serialPort->isOpen()) {
serialPort->write(prefix);
serialPort->flush(); // 确保数据立即发送
}
else {
qDebug() << "Serial port is not open!";
}
}
void SerialPortHandler::handleSerialData(const QByteArray& data) {
//qDebug() << "------------------------ Received data:" << data;
//qDebug() << "Received data (HEX):" << data.toHex(' ').toUpper();
//emit serialDataReceived(data); // 转发信号给主线程或 UI
}
void SerialPortHandler::updateAvailablePorts() {
QStringList currentPorts;
foreach(const QSerialPortInfo & info, QSerialPortInfo::availablePorts()) {
currentPorts.append(info.portName());
qDebug() << "info.portName(): " << info.portName();
}
//qDebug() << "Available ports: " << currentPorts;
// 检查已连接的端口是否仍然有效
if (serialPort->isOpen()) {
QString connectedPort = serialPort->portName();
bool portStillExists = false;
foreach(const QSerialPortInfo & info, QSerialPortInfo::availablePorts()) {
if (info.portName() == connectedPort) {
portStillExists = true;
break;
}
}
// 如果已连接的端口不再有效,则断开连接
if (!portStillExists) {
qDebug() << "Connected port no longer available: " << connectedPort;
disconnectPort();
}
}
// 保存当前选择的端口(在更新串口列表前)
QString currentSelectedPort = comPortComboBox->currentText();
// 如果当前下拉框的串口与新检测到的串口不匹配,则更新下拉框
if (currentPorts != comPortList) {
comPortComboBox->clear();
comPortComboBox->addItems(currentPorts);
comPortList = currentPorts; // 更新已检测到的串口列表
}
// 如果当前连接的端口仍然有效,则保持选中该端口
if (currentPorts.contains(currentSelectedPort)) {
comPortComboBox->setCurrentText(currentSelectedPort);
}
}
void SerialPortHandler::toggleConnection() {
if (serialPort->isOpen()) {
disconnectPort();
emit serialComPortDisconnected();
}
else {
isBackBoardOrAllBoard = 0;
if(connectPort() == 1)
emit serialComPortConnected();
}
}
int SerialPortHandler::connectPort() {
int ret = 0;
QString selectedPort = comPortComboBox->currentText();
if (selectedPort.isEmpty()) {
return ret; // 如果没有选择串口,直接返回
}
serialPort->setPortName(selectedPort);
if (serialPort->open(QIODevice::ReadWrite)) {
ret = 1;
connectButton->setText("断开连接");
comPortComboBox->setEnabled(false);
// 启动工作线程并绑定 readyRead 信号
if (!worker) {
worker = new SerialPortWorker(serialPort, this);
//connect(serialPort, &QSerialPort::readyRead, worker, &SerialPortWorker::handleReadyRead);
connect(serialPort, &QSerialPort::readyRead, this, &SerialPortHandler::onDataReceived);
//connect(worker, &SerialPortWorker::serialPortdataReceived, this, &SerialPortHandler::handleSerialData);
}
worker->startWorker();
}else {
qDebug() << "Failed to open serial port";
}
return ret;
}
void SerialPortHandler::disconnectPort() {
if (worker) {
worker->stop();
disconnect(serialPort, &QSerialPort::readyRead, worker, &SerialPortWorker::handleReadyRead);
delete worker; // 释放 worker
worker = nullptr; // 确保重新连接时可以创建新的 worker
}
if (serialPort->isOpen()) {
serialPort->close();
}
connectButton->setText("连接");
comPortComboBox->setEnabled(true);
}
//void SerialPortHandler::startReadVideoDataTimer(int client_Id)
//{
// //emit startReadTimer(clientId);
// emit startReadTimer(client_Id);
// qDebug() << "------ startClientReadTimer clientId:" << clientId;
//}
//
//void SerialPortHandler::stopReadVideoDataTimer(int client_Id)
//{
// //emit stopReadTimer(clientId);
// emit stopReadTimer(client_Id);
//}
// 重置索引
void SerialPortHandler::resetCurrentItemIndex()
{
currentItemIndex = 0;
currentFuncItemIndex = 0;
itemsProcessedCount = 0;
//OnStartTimeout(0);
emit startTimeout(0);
}
void SerialPortHandler::onPicRecvFinished()
{
/*if (currentJson != getPicJson && currentJson != frontBoardTest) {
currentItemIndex++;
itemsProcessedCount++;
qDebug() << "------> onPicRecvFinished " << __FUNCTION__;
sendNextItem(currentJson);
}*/
}
void SerialPortHandler::onCommandError() {
//isCommandError = true;
}
QString SerialPortHandler::getCurrentItemData() const
{
QString data = currentItem.value("data").toString();
qDebug() << "Getting current item data:" << data;
return data; // 返回当前项的 "data" 字段
}
QString SerialPortHandler::getCurrentFuncItemData() const
{
QString data = currentFuncItem.value("val").toString();
qDebug() << "Getting current funcItem val:" << data;
return data; // 返回当前项的 "val" 字段
}
QString SerialPortHandler::getCurrentItemLable() const
{
QString lable = currentItem.value("lable").toString();
qDebug() << "Getting current item lable:" << lable;
return lable; // 返回当前项的 "lable" 字段
}
QString SerialPortHandler::getCurrentFuncItemLable() const
{
QString lable = currentFuncItem.value("lable").toString();
//qDebug() << "Getting current funcItem lable:" << lable;
return lable; // 返回当前项的 "data" 字段
}
void SerialPortHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, const QString text, const QString backBoardSn, const QString& itemType)
{
//startReadVideoDataTimer(preVideoClientId);
currentJson = jsonArray;
currentJsonItem = itemIndex;
QMutexLocker locker(&mutex);
if (itemType == "License") {
}
isSingleSend = true;
isClickedSend = true;
isRecvImgData = false;
if (jsonArray == backBoardTest) {
QJsonObject tempItem = jsonArray[itemIndex].toObject();
if (tempItem["cmd"] == "VIDEO_TEST") {
if (tempItem["val"] == 0) {
isSingleSend = false;
isClickedSend = false;
isRecvVideoData = true;
isStartVideo = true;
//startReadVideoDataTimer(isBackBoardOrAllBoard);
}
else if (tempItem["val"] == 1) {
isRecvVideoData = false;
isStartVideo = false;
//stopReadVideoDataTimer(isBackBoardOrAllBoard);
}
}
}
if (itemType == "handleVideo") {
if (itemIndex == 0) {
isSingleSend = false;
isClickedSend = false;
}
else {
//stopReadVideoDataTimer(preVideoClientId);
}
}
if (itemType == "getPic") {
isSingleSend = false;
isClickedSend = false;
isRecvImgData = true;
}
if (itemType == "Uuid") {
}
qDebug() << "itemIndex" << itemIndex;
qDebug() << "jsonArray.size()" << jsonArray.size();
if (itemIndex >= 0 && itemIndex < jsonArray.size()) {
currentItemIndex = (itemType == "test") ? itemIndex : 0;
//currentItemIndex = itemIndex;
currentFuncItemIndex = (itemType == "func") ? itemIndex : 0;
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);
if (ok) {
currentItem["val"] = doubleValue;
}
else {
qWarning() << "Text conversion to double failed, original value is kept.";
}
}
else if (originalValue.isString()) {
currentItem["val"] = text;
}
}
else if (!text.isEmpty() && currentItem.contains("UUID") && currentItem.contains("SN")) {
QJsonValue originalUUID = currentItem["UUID"];
QJsonValue originalSN = currentItem["SN"];
qDebug() << "UUID:" << text;
qDebug() << "SN:" << backBoardSn;
if (originalUUID.isDouble()) {
bool ok;
double doubleValue = text.toDouble(&ok);
if (ok) {
currentItem["UUID"] = doubleValue;
}
else {
qWarning() << "Text conversion to double failed, original value is kept.";
}
}
else if (originalUUID.isString()) {
currentItem["UUID"] = text;
}
if (originalSN.isDouble()) {
bool ok;
double doubleValue = backBoardSn.toDouble(&ok);
if (ok) {
currentItem["SN"] = doubleValue;
}
else {
qWarning() << "backBoardSn conversion to double failed, original value is kept.";
}
}
else if (originalSN.isString()) {
currentItem["SN"] = backBoardSn;
}
}
QString itemData = QJsonDocument(currentItem).toJson();
emit currentSendItem(currentItem["cmd"].toString());
isTimeout = false;
emit updateTimeout(isTimeout);
// 发送 JSON
sendData(itemData.toUtf8(), 0);
if (currentItem.contains("timeout")) {
qDebug() << "sendJsonItem currentItem.contains(\"timeout\")";
int timeout = currentItem.value("timeout").toInt();
if (timeout > 0) {
//OnStartTimeout(timeout);
emit startTimeout(timeout);
}
}
}
}
// 发送获取设备信息按键
void SerialPortHandler::sendGetDevInfoItem(int itemIndex)
{
sendJsonItem(getDevInfoJson, itemIndex, "", "", "devInfo");
}
// 发送取图按键
void SerialPortHandler::sendGetPicItem(int itemIndex, int GetPicCamIndex)
{
sendJsonItem(getPicJson, itemIndex, QString::number(GetPicCamIndex), "", "getPic");
}
// 发送拉视频按键
void SerialPortHandler::sendGetVideoItem(int itemIndex, int GetVideoCamIndex)
{
qDebug() << "sendGetVideoItem itemIndex:" << itemIndex;
isRecvVideoData = true;
isStartVideo = true;
qDebug() << " isRecvVideoData:" << isRecvVideoData;
sendJsonItem(getVideoJson, itemIndex, QString::number(GetVideoCamIndex), "", "handleVideo");
}
// 发送License处理按键
void SerialPortHandler::sendLicenseItem(int itemIndex, const QString text)
{
if (isBackBoardOrAllBoard != 0) {
emit HandleInvalidOperate("当前连接的是后板或整机,请勿操作前板页面的按键!!!");
return;
}
else {
if (itemIndex < 0 || itemIndex >= frontBoardLicenseJson.size()) {
qDebug() << "Invalid itemIndex";
return;
}
sendJsonItem(frontBoardLicenseJson, itemIndex, text, "", "License");
}
}
void SerialPortHandler::sendFrontFuncItem(int itemIndex, const QString text)
{
if (isBackBoardOrAllBoard != 0) {
emit HandleInvalidOperate("当前连接的是后板或整机,请勿操作前板页面的按键!!!");
return;
}
else
{
//qDebug() << "sendFuncItem Text:" << text;
sendJsonItem(frontBoardFuncConfig, itemIndex, text, "", "func");
}
}
//void SerialPortHandler::onDelUserDialogResult(const QString& input)
//{
// //userInput = input; // 存储用户输入
// emit DelUserDialogResultReceived(input); // 通知事件循环退出
//}
void SerialPortHandler::sendFrontItem(int itemIndex)
{
/*if (isBackBoardOrAllBoard != 0) {
emit HandleInvalidOperate("当前连接的是后板或整机,请勿操作前板页面的按键!!!");
return;
}
else*/
{
QString text = "";
QJsonObject currentItem = frontBoardTest[itemIndex].toObject();
if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "IMG_ENROLL") {
QString downloadUrl;
QEventLoop loop;
emit startImageSharing(IMG_ENROLL_W, IMG_ENROLL_H, "enroll", [&downloadUrl, &loop](QString responseUrl) {
//qDebug() << "Received response from slot:" << responseUrl;
downloadUrl = responseUrl; // 更新局部变量
loop.quit(); // 退出事件循环
});
//loop.exec(); // 等待回调执行完成
if (!downloadUrl.isEmpty()) {
qDebug() << "Image available at:" << downloadUrl;
}
text = downloadUrl;
}
else if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "DEL_USER") {
QEventLoop loop;
QString userInput = "";
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(frontBoardTest, itemIndex, text, "", "test");
}
}
void SerialPortHandler::sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemIndex)
{
qDebug() << "sendDevInfoJsonItem Current thread:" << QThread::currentThread();
QMutexLocker locker(&mutex);
isPowerOnSend = true;
qDebug() << "itemIndex" << itemIndex;
qDebug() << "jsonItem.size()" << jsonItem.size();
currentItem = jsonItem;
QString itemData = QJsonDocument(jsonItem).toJson();
//emit sendData(itemData.toUtf8());
// 发送 JSON
sendData(itemData.toUtf8(), 0);
if (jsonItem.contains("timeout")) {
int timeout = jsonItem.value("timeout").toInt();
if (timeout > 0) {
//OnStartTimeout(timeout);
emit startTimeout(timeout);
}
}
else {
// 如果没有 timeout 字段,则不设置超时处理,一直等待数据接收
}
}
void SerialPortHandler::sendDevInfoItem()
{
qDebug() << "----------- currentFrontBoardIndex:" << currentFrontBoardIndex;
qDebug() << "----------- currentFrontBoardIndex:" << currentFrontBoardIndex;
qDebug() << "----------- currentFrontBoardIndex:" << currentFrontBoardIndex;
qDebug() << "----------- currentFrontBoardIndex:" << currentFrontBoardIndex;
qDebug() << "----------- currentFrontBoardIndex:" << currentFrontBoardIndex;
currentJson = frontBoardDevInfoJson;
currentJsonItem = currentFrontBoardIndex;
if (currentFrontBoardIndex < frontBoardDevInfoJson.size()) {
sendDevInfoJsonItem(frontBoardDevInfoJson[currentFrontBoardIndex++].toObject(), 1);
}
else
isPowerOnSend = false;
}
void SerialPortHandler::sendNextItem(QJsonArray& currentOneClickedItem)
{
QMutexLocker locker(&mutex);
isClickedSend = true;
//qDebug() << "------> locker(&mutex) :" << itemsProcessedCount;
qDebug() << "------> currentItemIndex :" << currentItemIndex;
qDebug() << "------> currentOneClickedItem.size() :" << currentOneClickedItem.size();
if (currentItemIndex < currentOneClickedItem.size()) {
currentJson = currentOneClickedItem;
currentJsonItem = currentItemIndex;
currentItem = currentOneClickedItem[currentItemIndex].toObject();
QString itemData = QJsonDocument(currentItem).toJson();
//qDebug() << "Sending item index:" << currentItemIndex << "data:" << itemData;
if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "DEL_USER") {
QString userInput;
// 使用 QMetaObject::invokeMethod 将窗口操作移到主线程
QMetaObject::invokeMethod(QApplication::instance(), [&userInput]() {
DelUserWindow dialog;
if (dialog.exec() == QDialog::Accepted) {
userInput = dialog.getUserInput();
}
}, Qt::BlockingQueuedConnection); // 阻塞子线程,直到窗口操作完成
if (!userInput.isEmpty() && currentItem.contains("val")) {
currentItem["val"] = userInput;
itemData = QJsonDocument(currentItem).toJson();
}
else {
return; // 用户取消或输入无效,直接返回
}
}
isTimeout = false;
emit updateTimeout(isTimeout);
// 发送 JSON
sendData(itemData.toUtf8(), 0);
if (currentItem.contains("timeout")) {
int timeout = currentItem.value("timeout").toInt();
if (timeout > 0) {
//OnStartTimeout(timeout);
emit startTimeout(timeout);
}
}
else {
// 如果没有 timeout 字段,则不设置超时处理,一直等待数据接收
}
}
else if (isManualSend) {
emit allItemsProcessed(isBackBoardOrAllBoard, "", itemsProcessedCount);
// 处理完毕后重置标记
isManualSend = false;
isClickedSend = false;
// 重置索引
resetCurrentItemIndex();
}
}
void SerialPortHandler::onRecvNormalDataFlag(bool flag)
{
if (!(protocolDataFlag = flag)) {
return;
}
/*if (isPowerOnSend && protocolDataFlag) {
if (currentFrontBoardIndex < frontBoardDevInfoJson.size()) {
qDebug() << "-----" << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
sendDevInfoItem();
}
else {
qDebug() << "All items processed in onDataReceived.";
emit allItemsProcessed(isBackBoardOrAllBoard, "", currentFrontBoardIndex);
isPowerOnSend = false;
}
protocolDataFlag = false;
}*/
QJsonObject currentTempItem = currentJson[currentItemIndex].toObject();
if (!isSingleSend && !isPowerOnSend && (currentTempItem["cmd"] != "GET_IMG")) {
qDebug() << "------------------- onRecvNormalDataFlag ";
currentItemIndex ++;
itemsProcessedCount ++;
}
if (isSingleSend) {
if (currentTempItem["cmd"] != "GET_IMG") {
isSingleSend = false;
}
isClickedSend = false;
}
else if (isPowerOnSend) {
if (currentFrontBoardIndex < frontBoardDevInfoJson.size()) {
qDebug() << "-----" << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
sendDevInfoItem();
}
else {
qDebug() << "All items processed in onDataReceived.";
emit allItemsProcessed(isBackBoardOrAllBoard, "", currentFrontBoardIndex);
currentFrontBoardIndex = 0;
isPowerOnSend = false;
}
}
else if (isClickedSend && (currentItemIndex < currentJson.size())) {
// 判断是否是取图或者其他会接收很多数据的指令
if (currentTempItem["cmd"] != "GET_IMG") {
sendNextItem(currentJson);
}
}
else if (isClickedSend) {
emit allItemsProcessed(isBackBoardOrAllBoard, "", itemsProcessedCount);
isClickedSend = false;
//resetCurrentItemIndex();
}
protocolDataFlag = false;
}
void SerialPortHandler::onDataReceived()
{
qDebug() << "isRecvVideoData:" << isRecvVideoData;
qDebug() << "isPowerOnSend:" << isPowerOnSend;
qDebug() << "isClickedSend:" << isClickedSend;
qDebug() << "isSingleSend:" << isSingleSend;
qDebug() << "isRecvImgData:" << isRecvImgData;
#if 1
if (!isRecvVideoData &&
(isRecvImgData || isPowerOnSend || isClickedSend || (isSingleSend && (currentItemIndex < currentJson.size())))) {
QByteArray allData;
#if 1
while (serialPort->bytesAvailable() > 0) {
qint64 bytesAvailableBefore = serialPort->bytesAvailable();
//qDebug() << "Bytes available before read:" << bytesAvailableBefore << "clientId:" << clientId;
QByteArray buffer;
buffer.resize(qMin(bytesAvailableBefore, qint64(5 * 1024))); // 每次读取最多 5KB
qint64 bytesRead = serialPort->read(buffer.data(), buffer.size());
if (bytesRead > 0) {
buffer.resize(bytesRead);
allData.append(buffer);
//qint64 bytesAvailableAfter = serialPort->bytesAvailable();
}
}
#else
if (currentJson != getVideoJson)
allData = serialPort->readAll();
#endif
getCurrentItemLable();
//qDebug() << "------- currentItem.value(timeout):" << currentItem.value("timeout").toInt();
if ((currentItem.contains("timeout")) || (currentFuncItem.contains("timeout"))) {
qDebug() << "currentItem.contains(timeout):" << currentItem.contains("timeout");
//OnStartTimeout(0);
}
QJsonObject currentTempItem = currentJson[currentItemIndex].toObject();
//qDebug() << "---Received allData size:" << allData.size();
if (!allData.isEmpty()) {
emit dataReceived("", allData, 0xFF, currentItemIndex, currentFuncItemIndex, getCurrentItemLable(), "", currentJson, currentJsonItem, isTimeout);
/*if (!isSingleSend && !isPowerOnSend && (currentTempItem["cmd"] != "GET_IMG")) {
currentItemIndex ++;
itemsProcessedCount ++;
}*/
}
/*if (isSingleSend) {
if (currentTempItem["cmd"] != "GET_IMG") {
isSingleSend = false;
}
isClickedSend = false;
}
else if (isPowerOnSend && protocolDataFlag) {
if (currentFrontBoardIndex < frontBoardDevInfoJson.size()) {
qDebug() << "-----" << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
sendDevInfoItem();
}
else {
qDebug() << "All items processed in onDataReceived.";
emit allItemsProcessed(isBackBoardOrAllBoard, "", currentFrontBoardIndex);
isPowerOnSend = false;
}
protocolDataFlag = false;
}
else if (isClickedSend && (currentItemIndex < currentJson.size())) {
// 判断是否是取图或者其他会接收很多数据的指令
if (currentTempItem["cmd"] != "GET_IMG") {
sendNextItem(currentJson);
}
}
else if (isClickedSend) {
emit allItemsProcessed(isBackBoardOrAllBoard, "", itemsProcessedCount);
isClickedSend = false;
//resetCurrentItemIndex();
}*/
}
else if (isRecvVideoData && (!dataProcessingActive)) {
dataProcessingActive = true;
if ((isBackBoardOrAllBoard == 0) && !isStartVideo) {
isRecvVideoData = false;
}
QTimer::singleShot(0, this, &SerialPortHandler::processPendingData);
}
else
#endif
if (!isRecvVideoData && !isRecvImgData) {
/*if (preVideoClientId == clientId) {
qDebug() << "-----------------" << preVideoClientId << "isRecvVideoData:" << isRecvVideoData;
}*/
//getCurrentItemLable();
QByteArray AllData = serialPort->readAll();
if (isCommandError) {
isCommandError = false;
//emit dataReceived("", AllData, 0xFF, currentItemIndex, currentFuncItemIndex, "", "", currentJson, currentJsonItem);
}
emit dataReceived("", AllData, 0xFF, currentItemIndex, currentFuncItemIndex, "", "", currentJson, currentJsonItem, isTimeout);
}
}
void SerialPortHandler::processPendingData()
{
if (dataProcessingActive) {
int maxIterations = 10; // 每次处理的最大次数
QByteArray allData;
while (serialPort->bytesAvailable() > 0 && maxIterations-- > 0) {
qint64 bytesAvailableBefore = serialPort->bytesAvailable();
//qDebug() << "Bytes available before read:" << bytesAvailableBefore << "clientId:" << clientId;
// 分块读取数据,避免一次性读取过多数据
QByteArray buffer;
buffer.resize(qMin(bytesAvailableBefore, qint64(5 * 1024))); // 每次读取最多 5KB
qint64 bytesRead = serialPort->read(buffer.data(), buffer.size());
if (bytesRead > 0) {
buffer.resize(bytesRead);
//qDebug() << "buffer.data():" << buffer.data();
allData.append(buffer);
}
}
if (!allData.isEmpty()) {
emit dataReceived("", allData, 0xFF, currentItemIndex, currentFuncItemIndex, "", "", currentJson, currentJsonItem, isTimeout);
}
// 如果还有数据需要处理,继续调度处理任务
if (serialPort->bytesAvailable() > 0) {
QTimer::singleShot(0, this, &SerialPortHandler::processPendingData);
}
else {
dataProcessingActive = false;
}
}
}
void SerialPortHandler::onTimeout()
{
qDebug() << "----------- onTimeout ----------";
qDebug() << "-----" << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
//OnStartTimeout(0);
//emit startTimeout(0);
{
QMutexLocker locker(&mutex);
emit statusUpdated(isBackBoardOrAllBoard, "", false, currentJson, currentJsonItem);
//qDebug() << "isSingleSend:" << isSingleSend << "isPowerOnSend:" << isPowerOnSend;
if (!isSingleSend && !isPowerOnSend) {
qDebug() << "------------------- onTimeout ";
currentItemIndex ++;
itemsProcessedCount ++;
}
}
if (isSingleSend) {
qDebug() << "----------- isTimeout set true----------";
isTimeout = true;
emit updateTimeout(isTimeout);
isSingleSend = false;
isClickedSend = false;
}
else if (isClickedSend) {
if (isBackBoardOrAllBoard) {
if (currentItemIndex < backBoardOneClickTest.size()) {
sendNextItem(currentJson);
}
else if (currentItemIndex >= backBoardOneClickTest.size()) {
emit allItemsProcessed(isBackBoardOrAllBoard, "", itemsProcessedCount);
}
}
else {
if (currentItemIndex < frontBoardOneClickTest.size()) {
sendNextItem(currentJson);
}
else if (currentItemIndex >= frontBoardOneClickTest.size()) {
emit allItemsProcessed(isBackBoardOrAllBoard, "", itemsProcessedCount);
}
}
}
else if (isPowerOnSend) {
if (currentFrontBoardIndex < frontBoardDevInfoJson.size()) {
sendDevInfoItem();
}
else {
emit allItemsProcessed(isBackBoardOrAllBoard, "", currentFrontBoardIndex);
currentFrontBoardIndex = 0;
isPowerOnSend = false;
}
}
qDebug() << "" << __FUNCTION__ << "------> itemsProcessedCount" << itemsProcessedCount << "currentItemIndex:" << currentItemIndex;
}

View File

@ -0,0 +1,170 @@
// SerialPortHandler.h
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QTimer>
#include <QStringList>
#include <QComboBox>
#include <QPushButton>
#include <QDebug>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMutex>
#include <QEventLoop>
#include <QApplication>
#include "SerialPortWorker.h"
#include "../../Network/DelUserWindows.h"
#include "../../Network/ImageEnrollWindow.h"
#include "../../Network/PasswordEnrollWindow.h"
#define TEST_TCP_MOVE_TO_MAIN 0
#define GET_PIC_DATA_SIZE (480 * 640 * 1.5)
#define IMG_ENROLL_W 480
#define IMG_ENROLL_H 640
#define CHANGE_THEME_W 720
#define CHANGE_THEME_H 1280
class SerialPortHandler : public QObject {
Q_OBJECT
public:
explicit SerialPortHandler(QComboBox* comPortComboBox, QPushButton* connectButton,
QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardDevInfoJson,
QJsonArray backBoardUuidJson, QJsonArray getPicJson, QJsonArray getVideoJson,
QObject* parent = nullptr);
~SerialPortHandler();
void sendData(const QByteArray& data, bool heartBeat);
void onPicRecvFinished();
void onCommandError();
void sendDevInfoItem();
void sendJsonItem(const QJsonArray& jsonArray, int itemIndex, const QString text, const QString backBoardSn, const QString& itemType);
// 发送获取设备信息按键
void sendGetDevInfoItem(int itemIndex);
// 发送取图按键
void sendGetPicItem(int itemIndex, int GetPicCamIndex);
// 发送拉视频流按键
void sendGetVideoItem(int itemIndex, int GetVideoCamIndex);
// 发送License处理按键
void sendLicenseItem(int itemIndex, const QString text);
// 发送下一个功能配置 JSON 项目
void sendFrontFuncItem(int itemIndex, QString text);
// 处理发送单独指令
void sendFrontItem(int itemIndex);
// 发送下一个 JSON 项目
void sendNextItem(QJsonArray& currentOneClickedItem);
// 获取json文件中当前发送的 data 字段项
QString getCurrentItemData() const;
// 获取json文件中当前发送的 lable 字段项
QString getCurrentItemLable() const;
// 获取功能 json文件中当前发送的 data 字段项
QString getCurrentFuncItemData() const;
// 获取功能 json文件中当前发送的 lable 字段项
QString getCurrentFuncItemLable() const;
// 重置索引
void resetCurrentItemIndex();
public slots:
void handleSerialError(QSerialPort::SerialPortError error);
void updateAvailablePorts();
void toggleConnection();
int connectPort();
void disconnectPort();
void handleSerialData(const QByteArray& data);
// 处理数据接收
void onDataReceived();
// 处理超时
void onTimeout();
void onSendHeartBeatData(const QByteArray& data, bool heartBeat);
void processPendingData();
void OnStartTimeout(int timeout);
void initializeSerialPort();
void initializeTimers();
void onRecvNormalDataFlag(bool flag);
//void onDelUserDialogResult(const QString& input);
signals:
void serialDataReceived(const QByteArray& data);
void serialComPortConnected();
void serialComPortDisconnected();
void HandleInvalidOperate(const QString& text);
// 通知主线程启动定时器
void startTimeout(int timeout);
void currentSendItem(const QString& text);
// 状态更新信号
void statusUpdated(int boardTpye, const QString& client, bool success, const QJsonArray& jsonArray, int itemJsonIndex);
// json文件配置项发送完毕
void allItemsProcessed(int boardTpye, const QString& client, int itemsProcessedCount);
// 数据接收信号
void dataReceived(const QString& client, const QByteArray& data, unsigned char msg_id, int currentRecvItemIndex,
int currentRecvFuncItemIndex, const QString& itemData, const QString& funcItemData,
const QJsonArray& jsonArray, int itemJsonIndex, bool isTimeout);
void startImageSharing(int width, int height, QString img_type, std::function<void(QString)> callback);
void updateTimeout(bool isTimeout);
void requestShowDialog();
void dialogResultReceived(const QString& input);
private:
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和SN参数 JSON
QJsonArray jsonConfig; // 测试区 JSON 配置
QJsonArray funcJsonConfig; // 功能区 JSON 配置
QJsonArray getDevInfoJson; // 获取设备信息 JSON 配置
QJsonArray getPicJson; // 发送取图指令 JSON 配置
QJsonArray getVideoJson; // 发送拉视频指令 JSON 配置
QJsonArray currentJson; // 当前处理的json
int currentJsonItem = -1;
int currentItemIndex; // 当前处理的测试 JSON 项目索引
int currentFuncItemIndex; // 当前处理的功能 JSON 项目索引
int isBackBoardOrAllBoard = -1;
int itemsProcessedCount; // 跟踪处理项目的数量
QJsonObject currentItem; // 测试 json文件中当前发送的项
QJsonObject currentFuncItem; // 功能 json文件中当前发送的项
QMutex mutex; // 互斥锁,用于线程安全
bool isManualSend; // 判断是否是手动触发的发送
bool isSingleSend; // 单独点击按键发送的标志
bool isClickedSend; // 点击按键发送的标志,没有点击不接收数据
bool isRecvVideoData;
bool isRecvImgData = false;
bool isStartVideo = false;
bool isPowerOnSend = false; // 上电发送设备信息
bool isCommandError = false;
bool isFirstDataReceived;
bool isDataStuck;
bool dataProcessingActive;
bool protocolDataFlag = false;
bool isTimeout = false;
int currentFrontBoardIndex; // 当前发送的前板设备信息项的索引
int currentLicenseIndex;
QComboBox* comPortComboBox;
QPushButton* connectButton;
QSerialPort* serialPort;
QTimer* portDetectionTimer;
QTimer* serialTimer;
QStringList comPortList; // 当前已检测到的串口列表
SerialPortWorker* worker;
void sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemIndex);
};

View File

@ -0,0 +1,46 @@
#ifndef SERIALPORTWORKER_H
#define SERIALPORTWORKER_H
#include <QThread>
#include <QSerialPort>
#include <QByteArray>
class SerialPortWorker : public QThread {
Q_OBJECT
public:
explicit SerialPortWorker(QSerialPort* serialPort, QObject* parent = nullptr)
: QThread(parent), serialPort(serialPort), running(true) {}
~SerialPortWorker() override {
stop(); // 确保线程退出
}
void startWorker() {
running = true;
}
void stop() {
running = false;
if (serialPort->isOpen()) {
serialPort->close();
}
}
signals:
void serialPortdataReceived(const QByteArray& data);
public slots:
void handleReadyRead() {
if (running && serialPort->isOpen()) {
QByteArray data = serialPort->readAll();
emit serialPortdataReceived(data);
}
}
private:
QSerialPort* serialPort;
bool running;
};
#endif // SERIALPORTWORKER_H

View File

@ -28,7 +28,9 @@ struct UI_config {
QString BACK_TEST_ITEM; // "后板测试项"
QString BACK_CONFID_ITEM; // "后板配置项"
QString IMAGE_DISPLAY_TAB; // "图像显示区"
QString VIDEO_DISPLAY_TAB; // "视频显示区"
QString VIDEO_DISPLAY_TAB; // "视频显示区"
QString ALL_TEST_ITEM; // "整机测试项"
QString ALL_CONFID_ITEM; // "整机配置项"
QString LEFT_LENS; // "左边镜头"
QString RIGHT_LENS; // "右边镜头"
QString CAT_EYE_LENS_RGB; // "猫眼镜头(RGB)"

View File

@ -42,11 +42,11 @@ UI_config loadConfig(const QString& filePath)
UI_config config;
QMap<QString, QString> settings = parseIniFile(filePath);
// 可直接修改 UI_config.ini 文件
// 如果删除 UI_config.ini 文件中的 Labels 项,则使用如下代码的默认命名配置
// 如果删除 UI_config.ini 文件中的 Labels 项,则使用如下代码的默认命名配置
// Labels 项 默认命名配置
config.SL100_FACTORY_TOOL_W = settings.value("Window/width", "1340").toInt();
config.SL100_FACTORY_TOOL_H = settings.value("Window/height", "900").toInt();
config.TOOL_VERSION = settings.value("Labels/tool_version", "SL100 工厂产测工具 - V0.0.10");
config.TOOL_VERSION = settings.value("Labels/tool_version", "SL100 工厂产测工具 - V0.0.16");
config.START_LISTENING = settings.value("Labels/start_listening", "开始监听\n(Start Listening...)");
config.ONE_CLICKED_TEST = settings.value("Labels/one_clicked_test", "一键功能测试");
config.FRONT_BOARD_NAME = settings.value("Labels/front_board_name", "前 板");
@ -65,6 +65,8 @@ UI_config loadConfig(const QString& filePath)
config.BACK_CONFID_ITEM = settings.value("Labels/back_config_item", "后板配置项");
config.IMAGE_DISPLAY_TAB = settings.value("Labels/image_display_tab", "图像显示区");
config.VIDEO_DISPLAY_TAB = settings.value("Labels/video_display_tab", "视频显示区");
config.ALL_TEST_ITEM = settings.value("Labels/all_test_item", "整机测试项");
config.ALL_CONFID_ITEM = settings.value("Labels/all_config_item", "整机配置项");
config.LEFT_LENS = settings.value("Labels/left_lens", "左边镜头");
config.RIGHT_LENS = settings.value("Labels/right_lens", "右边镜头");
config.CAT_EYE_LENS_RGB = settings.value("Labels/cat_eye_lens_rgb", "猫眼镜头(RGB)");
@ -498,6 +500,9 @@ void MainWidget::addDeviceAreaTab(QTabWidget* mainTabWidget, const QString& tabN
// 创建整机区域布局
void MainWidget::addAllDeviceAreaTab(QTabWidget* mainTabWidget, const QString& tabName,
const QJsonArray& boardTest, const QJsonArray& boardFuncConfig,
const QString& boardTestName, const QString& boardFuncConfigName,
const QString& boardTestTitle, const QString& boardConfigTitle,
QLabel* leftLensLabel, QLabel* rightLensLabel, QLabel* video_Label,
QLineEdit* VideoResolutionEdit_type)
{
@ -506,9 +511,9 @@ void MainWidget::addAllDeviceAreaTab(QTabWidget* mainTabWidget, const QString& t
QGroupBox* allProductInfoGroupBox = new QGroupBox(TOOL_UI.ALL_PRODUCT_INFO, this);
QFormLayout* formLayout = new QFormLayout(allProductInfoGroupBox);
for (const QJsonValue& value : factoryProductInfo) {
QJsonObject item = value.toObject();
QString label = item["lable"].toString();
QString cmd = item["cmd"].toString();
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(false);
@ -516,13 +521,23 @@ void MainWidget::addAllDeviceAreaTab(QTabWidget* mainTabWidget, const QString& t
formLayout->addRow(itemLabel, itemLineEdit);
productInfoLineEdits[cmd] = itemLineEdit;
}
QTabWidget* boardTabWidget = new QTabWidget(this);
boardTabWidget->setFixedSize(900, 315);
QWidget* functionTestTab = createFunctionTestTab(boardTest, boardTestName);
QWidget* functionConfigTab = createFunctionConfigTab(boardFuncConfig, boardFuncConfigName);
boardTabWidget->addTab(functionTestTab, boardTestTitle);
boardTabWidget->addTab(functionConfigTab, boardConfigTitle);
groupBoxLayout->addWidget(allProductInfoGroupBox, 1);
groupBoxLayout->addWidget(allDeviceInfoGroupBox, 1);
QTabWidget* mediaTabWidget = createMediaTabWidget(leftLensLabel, rightLensLabel, video_Label, VideoResolutionEdit_type, tabName);
QWidget* allDevAreaTab = new QWidget(this);
QVBoxLayout* allDevLayout = new QVBoxLayout(allDevAreaTab);
allDevLayout->addLayout(groupBoxLayout, 5);
allDevLayout->addWidget(mediaTabWidget, 3);
allDevLayout->addLayout(groupBoxLayout, 2);
allDevLayout->addWidget(boardTabWidget, 4);
allDevLayout->addWidget(mediaTabWidget, 4);
mainTabWidget->addTab(allDevAreaTab, tabName);
}

View File

@ -1,5 +1,7 @@
#include "./Widget/MainWidget.h"
#include <QApplication>
#include <QItemSelection>
#include <QItemSelectionModel>
#include <windows.h>
#include <iostream>
#include <QDebug>
@ -22,6 +24,11 @@ int main(int argc, char* argv[]) {
//closeConsole(); // 调用函数关闭控制台窗口
//FreeConsole(); // 关闭控制台窗口
QApplication app(argc, argv);
// **注册 QItemSelection 和 SelectionFlags 以支持 QueuedConnection**
qRegisterMetaType<QItemSelection>("QItemSelection");
qRegisterMetaType<QItemSelectionModel::SelectionFlags>("QItemSelectionModel::SelectionFlags");
qDebug() << "Current working directory:" << QDir::currentPath();
//QIcon appIcon("./app_icon.ico");
//app.setWindowIcon(appIcon);

View File

@ -1,8 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!
device ID: 2 - Item 1: 后板V851版本: ---> NG
device ID: 2 - Item 2: 后板806版本: ---> NG
device ID: 2 - Item 3: 后板硬件版本: ---> NG
device ID:-2 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,8 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!
device ID: 2 - Item 1: 后板V851版本: ---> NG
device ID: 2 - Item 2: 后板806版本: ---> NG
device ID: 2 - Item 3: 后板硬件版本: ---> NG
device ID:-2 ---> All 3 items test completed !!!

View File

@ -1,12 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!
device ID: 2 - Item 1: 后板V851版本: ---> NG
device ID: 2 - Item 2: 后板806版本: ---> NG
device ID: 2 - Item 3: 后板硬件版本: ---> NG
device ID:-2 ---> All 3 items test completed !!!
device ID: 3 - Item 1: 后板V851版本: ---> NG
device ID: 3 - Item 2: 后板806版本: ---> NG
device ID: 3 - Item 3: 后板硬件版本: ---> NG
device ID:-3 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,8 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!
device ID: 2 - Item 1: 后板V851版本: ---> NG
device ID: 2 - Item 2: 后板806版本: ---> NG
device ID: 2 - Item 3: 后板硬件版本: ---> NG
device ID:-2 ---> All 3 items test completed !!!

View File

@ -1,12 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!
device ID: 2 - Item 1: 后板V851版本: ---> NG
device ID: 2 - Item 2: 后板806版本: ---> NG
device ID: 2 - Item 3: 后板硬件版本: ---> NG
device ID:-2 ---> All 3 items test completed !!!
device ID: 3 - Item 1: 后板V851版本: ---> NG
device ID: 3 - Item 2: 后板806版本: ---> NG
device ID: 3 - Item 3: 后板硬件版本: ---> NG
device ID:-3 ---> All 3 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 2 - Item 1: 前板V851版本: ---> OK
device ID: 2 - Item 2: 前板MCU版本: ---> OK
device ID: 2 - Item 3: 前板硬件版本: ---> OK
device ID: 2 - Item 4: 算法版本: ---> OK
device ID: 2 - Item 5: SN号: ---> OK
device ID:-2 ---> All 5 items test completed !!!

View File

@ -1,8 +0,0 @@
device ID: 1 - Item 0: ---> NG
device ID: 1 - Item 1: 进入产测模式 ---> NG
device ID: 1 - Item 2: 前板V851版本: ---> NG
device ID: 1 - Item 3: 前板MCU版本: ---> NG
device ID: 1 - Item 4: 前板硬件版本: ---> NG
device ID: 1 - Item 5: 算法版本: ---> NG
device ID: 1 - Item 6: SN号: ---> NG
device ID:-1 ---> All 6 items test completed !!!

View File

@ -1,7 +0,0 @@
device ID: 1 - Item 1: 进入产测模式 ---> OK
device ID: 1 - Item 2: 前板V851版本: ---> NG
device ID: 1 - Item 3: 前板MCU版本: ---> NG
device ID: 1 - Item 4: 前板硬件版本: ---> NG
device ID: 1 - Item 5: 算法版本: ---> NG
device ID: 1 - Item 6: SN号: ---> NG
device ID:-1 ---> All 6 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,6 +0,0 @@
device ID: 1 - Item 1: 前板V851版本: ---> NG
device ID: 1 - Item 2: 前板MCU版本: ---> NG
device ID: 1 - Item 3: 前板硬件版本: ---> NG
device ID: 1 - Item 4: 算法版本: ---> NG
device ID: 1 - Item 5: SN号: ---> NG
device ID:-1 ---> All 5 items test completed !!!

View File

@ -1,4 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -1,8 +0,0 @@
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!
device ID: 1 - Item 1: 后板V851版本: ---> NG
device ID: 1 - Item 2: 后板806版本: ---> NG
device ID: 1 - Item 3: 后板硬件版本: ---> NG
device ID:-1 ---> All 3 items test completed !!!

View File

@ -0,0 +1,6 @@
device ID: 1 - Item 1: 前板V851版本: ---> OK
device ID: 1 - Item 2: 前板MCU版本: ---> OK
device ID: 1 - Item 3: 前板硬件版本: ---> OK
device ID: 1 - Item 4: 算法版本: ---> OK
device ID: 1 - Item 5: SN号: ---> OK
device ID:-1 ---> All 5 items test completed !!!

View File

@ -0,0 +1,6 @@
device ID: 1 - Item 1: 前板V851版本: ---> OK
device ID: 1 - Item 2: 前板MCU版本: ---> OK
device ID: 1 - Item 3: 前板硬件版本: ---> OK
device ID: 1 - Item 4: 算法版本: ---> OK
device ID: 1 - Item 5: SN号: ---> OK
device ID:-1 ---> All 5 items test completed !!!

View File

@ -0,0 +1,6 @@
device ID: 1 - Item 1: 前板V851版本: ---> OK
device ID: 1 - Item 2: 前板MCU版本: ---> OK
device ID: 1 - Item 3: 前板硬件版本: ---> OK
device ID: 1 - Item 4: 算法版本: ---> OK
device ID: 1 - Item 5: SN号: ---> OK
device ID:-1 ---> All 5 items test completed !!!

View File

@ -0,0 +1,6 @@
device ID: 1 - Item 1: 前板V851版本: ---> OK
device ID: 1 - Item 2: 前板MCU版本: ---> OK
device ID: 1 - Item 3: 前板硬件版本: ---> OK
device ID: 1 - Item 4: 算法版本: ---> OK
device ID: 1 - Item 5: SN号: ---> OK
device ID:-1 ---> All 5 items test completed !!!

View File

@ -0,0 +1,6 @@
device ID: 1 - Item 1: 前板V851版本: ---> OK
device ID: 1 - Item 2: 前板MCU版本: ---> OK
device ID: 1 - Item 3: 前板硬件版本: ---> OK
device ID: 1 - Item 4: 算法版本: ---> OK
device ID: 1 - Item 5: SN号: ---> OK
device ID:-1 ---> All 5 items test completed !!!

View File

@ -0,0 +1,6 @@
device ID: 1 - Item 1: 前板V851版本: ---> OK
device ID: 1 - Item 2: 前板MCU版本: ---> OK
device ID: 1 - Item 3: 前板硬件版本: ---> OK
device ID: 1 - Item 4: 算法版本: ---> OK
device ID: 1 - Item 5: SN号: ---> OK
device ID:-1 ---> All 5 items test completed !!!

View File

@ -0,0 +1,6 @@
device ID: 1 - Item 1: 前板V851版本: ---> OK
device ID: 1 - Item 2: 前板MCU版本: ---> OK
device ID: 1 - Item 3: 前板硬件版本: ---> OK
device ID: 1 - Item 4: 算法版本: ---> OK
device ID: 1 - Item 5: SN号: ---> OK
device ID:-1 ---> All 5 items test completed !!!

View File

@ -0,0 +1,6 @@
device ID: 1 - Item 1: 前板V851版本: ---> OK
device ID: 1 - Item 2: 前板MCU版本: ---> OK
device ID: 1 - Item 3: 前板硬件版本: ---> OK
device ID: 1 - Item 4: 算法版本: ---> OK
device ID: 1 - Item 5: SN号: ---> OK
device ID:-1 ---> All 5 items test completed !!!

View File

@ -0,0 +1,6 @@
device ID: 1 - Item 1: 前板V851版本: ---> OK
device ID: 1 - Item 2: 前板MCU版本: ---> OK
device ID: 1 - Item 3: 前板硬件版本: ---> OK
device ID: 1 - Item 4: 算法版本: ---> OK
device ID: 1 - Item 5: SN号: ---> OK
device ID:-1 ---> All 5 items test completed !!!

Some files were not shown because too many files have changed in this diff Show More