更新与前板的使用串口连接
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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)"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user