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

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

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