diff --git a/FactoryTestTool/FactoryTestTool.vcxproj b/FactoryTestTool/FactoryTestTool.vcxproj index 6742ba2..15f2471 100644 --- a/FactoryTestTool/FactoryTestTool.vcxproj +++ b/FactoryTestTool/FactoryTestTool.vcxproj @@ -105,6 +105,7 @@ + diff --git a/FactoryTestTool/FactoryTestTool.vcxproj.filters b/FactoryTestTool/FactoryTestTool.vcxproj.filters index ebd5a7a..dbe674a 100644 --- a/FactoryTestTool/FactoryTestTool.vcxproj.filters +++ b/FactoryTestTool/FactoryTestTool.vcxproj.filters @@ -160,6 +160,9 @@ Network + + Media\VideoDecoder + diff --git a/FactoryTestTool/SourceCode/Media/VideoDecoder/FFmpegDecoder.cpp b/FactoryTestTool/SourceCode/Media/VideoDecoder/FFmpegDecoder.cpp index 270f516..0e3b4ec 100644 --- a/FactoryTestTool/SourceCode/Media/VideoDecoder/FFmpegDecoder.cpp +++ b/FactoryTestTool/SourceCode/Media/VideoDecoder/FFmpegDecoder.cpp @@ -15,7 +15,7 @@ FFmpegDecoder::FFmpegDecoder(QObject* parent) : { av_log_set_level(AV_LOG_QUIET); // 设置日志级别为安静模式 avformat_network_init(); // 初始化网络 - //qDebug() << "FFmpegDecoder created"; + qDebug() << "FFmpegDecoder created"; } FFmpegDecoder::~FFmpegDecoder() @@ -31,16 +31,54 @@ FFmpegDecoder::~FFmpegDecoder() qDebug() << "FFmpegDecoder destroyed"; } +void FFmpegDecoder::processVideo(int itemIndex) +{ +#if 0 + int width = 720; + int height = 1280; +#elif 1 + int width = 640; + int height = 480; +#else + int width = 480; + int height = 640; +#endif + if (width * 16 == height * 9) { + FocusWindowDialog* dialog = new FocusWindowDialog(nullptr, QSize(540, 960)); + dialog->exec(); + } + else if (width * 9 == height * 16) { + FocusWindowDialog* dialog = new FocusWindowDialog(nullptr, QSize(960, 540)); + dialog->exec(); + } + else if (width * 4 == height * 3) { + FocusWindowDialog* dialog = new FocusWindowDialog(nullptr, QSize(480, 640)); + dialog->exec(); + } + else if (width * 3 == height * 4) { + FocusWindowDialog* dialog = new FocusWindowDialog(nullptr, QSize(640, 480)); + dialog->exec(); + } +} + void FFmpegDecoder::initialize() { // 初始化FFmpeg库 avformat_network_init(); } +void FFmpegDecoder::stopFFmpegDecoder() +{ + mutex.lock(); + abort = true; + condition.wakeOne(); // 唤醒等待的线程 + mutex.unlock(); +} + void FFmpegDecoder::decodeFile(const QString& filePath, QLabel* videoDisplayLabel) { QMutexLocker locker(&mutex); - this->filePath = filePath; + this->filePath = filePath; this->videoLabel = videoDisplayLabel; if (!isRunning()) { qDebug() << "Starting decoder thread"; @@ -55,7 +93,7 @@ void FFmpegDecoder::run() QFile file(filePath); qint64 fileSize = 0; - while (true) { + while (!isInterruptionRequested()) { mutex.lock(); while (!restart && !abort) { condition.wait(&mutex); @@ -65,14 +103,12 @@ void FFmpegDecoder::run() qDebug() << "Decoder thread aborting"; break; } - restart = false; QLabel* currentVideoLabel = videoLabel; QSize labelSize = currentVideoLabel->size(); mutex.unlock(); - if (labelSize.width() <= 0 || labelSize.height() <= 0) { - // 自动调整 QLabel 大小 - labelSize = QSize(800, 600); // 例如设置为默认大小 + if (labelSize.width() < 740 || labelSize.height() < 357) { + labelSize = QSize(740, 357); currentVideoLabel->setFixedSize(labelSize); qDebug() << "Adjusting video label size to: Width =" << labelSize.width() << ", Height =" << labelSize.height(); } @@ -88,14 +124,18 @@ void FFmpegDecoder::run() file.close(); continue; } + restart = false; while (!abort) { qint64 currentFileSize = file.size(); + //qDebug() << "Decoder thread currentFileSize:" << currentFileSize; + //qDebug() << "Decoder thread fileSize:" << fileSize; if (currentFileSize > fileSize) { fileSize = currentFileSize; file.seek(fileSize); // 设置文件读取位置到末尾 - + //qDebug() << "---------------1---------------"; // 读取并处理数据包 while (av_read_frame(formatContext, packet) >= 0) { + //qDebug() << "---------------2---------------"; if (packet->stream_index == videoStreamIndex) { int ret = avcodec_send_packet(codecContext, packet); if (ret < 0) { @@ -103,6 +143,7 @@ void FFmpegDecoder::run() av_packet_unref(packet); continue; } + //qDebug() << "---------------3---------------"; while (ret >= 0) { ret = avcodec_receive_frame(codecContext, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { @@ -113,28 +154,31 @@ void FFmpegDecoder::run() qWarning() << "Error during decoding"; break; } - - qDebug() << "H264 video resolution: Width =" << frame->width << ", Height =" << frame->height; - + //qDebug() << "---------------4---------------"; QImage img = avFrameToQImage(frame); + //qDebug() << "---------------5---------------"; QImage scaledImage = img.scaled(labelSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + //qDebug() << "---------------6---------------"; currentVideoLabel->setPixmap(QPixmap::fromImage(scaledImage)); QThread::msleep(10); // Simulate 25 FPS frame rate + //qDebug() << "---------------7---------------"; } } av_packet_unref(packet); + //qDebug() << "---------------8---------------"; } } - + //qDebug() << "---------------9---------------"; mutex.lock(); if (restart) { restart = false; mutex.unlock(); break; } + //qDebug() << "---------------10---------------"; mutex.unlock(); } - + //qDebug() << "---------------11---------------"; cleanup(); file.close(); @@ -148,6 +192,10 @@ void FFmpegDecoder::run() bool FFmpegDecoder::initializeFFmpeg(const QString& filePath) { + if (!QFile::exists(filePath)) { + qWarning() << "FFmpeg File does not exist:" << filePath; + return false; + } if (avformat_open_input(&formatContext, filePath.toStdString().c_str(), nullptr, nullptr) != 0) { qWarning() << "Failed to open file with FFmpeg:" << filePath; return false; @@ -227,6 +275,8 @@ QImage FFmpegDecoder::avFrameToQImage(AVFrame* frame) { int width = frame->width; int height = frame->height; + qDebug() << "H264 video resolution: Width =" << frame->width << ", Height =" << frame->height; + AVPixelFormat pixFmt = (AVPixelFormat)frame->format; if (!swsContext) { diff --git a/FactoryTestTool/SourceCode/Media/VideoDecoder/FFmpegDecoder.h b/FactoryTestTool/SourceCode/Media/VideoDecoder/FFmpegDecoder.h index 54219fa..908f654 100644 --- a/FactoryTestTool/SourceCode/Media/VideoDecoder/FFmpegDecoder.h +++ b/FactoryTestTool/SourceCode/Media/VideoDecoder/FFmpegDecoder.h @@ -14,8 +14,10 @@ #include #include #include +#include #include "RingBuffer.h" +#include "FocusWindow.h" extern "C" { #include @@ -38,9 +40,10 @@ public: void initialize(); void decodeFile(const QString& filePath, QLabel* videoLabel); void decodeSingleFrame(const QByteArray& data, QLabel* videoLabel); // 添加 videoLabel 参数 - + void FFmpegDecoder::processVideo(int itemIndex); bool initializeFFmpeg(const QString& filePath); void cleanup(); + void stopFFmpegDecoder(); protected: void run() override; @@ -48,19 +51,19 @@ protected: private: QImage avFrameToQImage(AVFrame* frame); - QMutex mutex; - QWaitCondition condition; - QString filePath; - QLabel* videoLabel; - bool abort; - bool restart; + QMutex mutex; + QWaitCondition condition; + QString filePath; + QLabel* videoLabel; + bool abort; + bool restart; AVFormatContext* formatContext; - AVCodecContext* codecContext; - AVFrame* frame; - AVPacket* packet; - SwsContext* swsContext; - int videoStreamIndex; + AVCodecContext* codecContext; + AVFrame* frame; + AVPacket* packet; + SwsContext* swsContext; + int videoStreamIndex; RingBuffer* ringBuffer; //QLabel* singleFrameLabel; // 用于解码单帧的标签 diff --git a/FactoryTestTool/SourceCode/Media/VideoDecoder/FocusWindow.h b/FactoryTestTool/SourceCode/Media/VideoDecoder/FocusWindow.h new file mode 100644 index 0000000..2686b0f --- /dev/null +++ b/FactoryTestTool/SourceCode/Media/VideoDecoder/FocusWindow.h @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +class FocusWindowDialog : public QDialog +{ + Q_OBJECT + +public: + FocusWindowDialog(QWidget* parent = nullptr, const QSize& labelSize = QSize(480, 640)) : QDialog(parent) + { + QVBoxLayout* layout = new QVBoxLayout(this); + QLabel* label = new QLabel("1111 This is a new window opened by clicking the new button.", this); + label->setFixedSize(labelSize); // 设置QLabel的固定大小 + layout->addWidget(label); + + QPushButton* closeButton = new QPushButton("Close", this); + layout->addWidget(closeButton); + connect(closeButton, &QPushButton::clicked, this, &FocusWindowDialog::accept); + + setLayout(layout); + setWindowTitle("SL100 视频播放窗口"); + //resize(500, 700); // 设置对话框的大小 + } +}; diff --git a/FactoryTestTool/SourceCode/Network/ClientHandler.cpp b/FactoryTestTool/SourceCode/Network/ClientHandler.cpp index 2371a26..c6ed2c8 100644 --- a/FactoryTestTool/SourceCode/Network/ClientHandler.cpp +++ b/FactoryTestTool/SourceCode/Network/ClientHandler.cpp @@ -9,7 +9,7 @@ ClientHandler::ClientHandler(QTcpSocket* socket, QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson, QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson, - QJsonArray getPicJson, QJsonArray getVideoJson, int clientId, QObject* parent) + QJsonArray getPicJson, QJsonArray getVideoJson, int clientId, int isBackBoardOrAllBoard, QObject* parent) : QObject(parent), socket(socket), frontBoardOneClickTest(frontBoardOneClickTest), frontBoardTest(frontBoardTest), frontBoardFuncConfig(frontBoardFuncConfig), frontBoardDevInfoJson(frontBoardDevInfoJson), @@ -17,7 +17,7 @@ ClientHandler::ClientHandler(QTcpSocket* socket, backBoardOneClickTest(backBoardOneClickTest), backBoardTest(backBoardTest), backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson), backBoardUuidJson(backBoardUuidJson), getPicJson(getPicJson), getVideoJson(getVideoJson), - currentItemIndex(0), clientId(clientId), + currentItemIndex(0), clientId(clientId), isBackBoardOrAllBoard(isBackBoardOrAllBoard), isManualSend(false), isSingleSend(false), isClickedSend(false), size(0), isFirstDataReceived(true), processDataFunction(nullptr), isDataStuck(false), dataProcessingActive(false), isRecvVideoData(true), @@ -35,6 +35,37 @@ ClientHandler::~ClientHandler() { qDebug() << "ClientHandler destroyed for clientId:" << clientId; } +// 实现 QRunnable 的 run 函数,在线程池中执行 +void ClientHandler::run() +{ + start(); +} + +// 重置索引 +void ClientHandler::resetCurrentItemIndex() +{ + currentItemIndex = 0; + currentFuncItemIndex = 0; + itemsProcessedCount = 0; + emit startTimeout(0); +} + +// 开始处理客户端 +void ClientHandler::start() +{ + resetCurrentItemIndex(); // 初始化计数器和索引 + sendNextItem(); +} + +// 处理客户端断开连接 +void ClientHandler::onDisconnected() { + qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; + qDebug() << "> A device is disconnected. ID:" << clientId; + qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; + emit clientDisconnected(this); + socket->deleteLater(); +} + void ClientHandler::startReadVideoDataTimer(int client_Id) { //emit startReadTimer(clientId); @@ -94,31 +125,9 @@ QString ClientHandler::getClientAddress() const return socket->peerAddress().toString() + ":" + QString::number(socket->peerPort()); } -// 实现 QRunnable 的 run 函数,在线程池中执行 -void ClientHandler::run() -{ - start(); -} - -// 重置索引 -void ClientHandler::resetCurrentItemIndex() -{ - currentItemIndex = 0; - currentFuncItemIndex = 0; - itemsProcessedCount = 0; - emit startTimeout(0); -} - -// 开始处理客户端 -void ClientHandler::start() -{ - resetCurrentItemIndex(); // 初始化计数器和索引 - sendNextItem(); -} - void ClientHandler::sendDataToClient(const QByteArray& data) { - emit sendData(data); + emit sendData(data, isBackBoardOrAllBoard); } void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, const QString text, const QString& itemType) @@ -470,6 +479,8 @@ bool ClientHandler::RNDISFirstData(QByteArray& data) { setThreadPriority(QThread::LowPriority); socket->setReadBufferSize(20 * 1024); controlClientId = clientId; + // 前板有设备连接自动发送获取设备信息 + //sendDevInfoItem(); break; default: qWarning() << "Unhandled client type:" << clientType; @@ -671,15 +682,6 @@ void ClientHandler::processPendingData() } } -// 处理客户端断开连接 -void ClientHandler::onDisconnected() { - qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; - qDebug() << "> A device is disconnected. ID:" << clientId; - qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; - emit clientDisconnected(this); - socket->deleteLater(); -} - // 处理超时 void ClientHandler::onTimeout() { diff --git a/FactoryTestTool/SourceCode/Network/ClientHandler.h b/FactoryTestTool/SourceCode/Network/ClientHandler.h index 26959c8..9539721 100644 --- a/FactoryTestTool/SourceCode/Network/ClientHandler.h +++ b/FactoryTestTool/SourceCode/Network/ClientHandler.h @@ -33,7 +33,7 @@ public: QJsonArray frontBoardFuncConfig, QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson, QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson, QJsonArray getPicJson, QJsonArray getVideoJson, - int clientId, QObject* parent = nullptr); + int clientId, int isBackBoardOrAllBoard, QObject* parent = nullptr); ~ClientHandler(); int preVideoClientId = 0; @@ -92,7 +92,7 @@ signals: const QJsonArray& jsonArray, int itemJsonIndex); void handleData(QByteArray& data); // 数据发送信号 - void sendData(const QByteArray& data); + void sendData(const QByteArray& data, int isBoardType); // 状态更新信号 void statusUpdated(const QString& client, int itemIndex, int funcItemIndex, bool success, const QString& itemData, const QString& funcItemData, @@ -144,6 +144,7 @@ private: int currentItemIndex; // 当前处理的测试 JSON 项目索引 int currentFuncItemIndex; // 当前处理的功能 JSON 项目索引 int clientId; // 新增的客户端编号 + int isBackBoardOrAllBoard; int itemsProcessedCount; // 跟踪处理项目的数量 diff --git a/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/include/qmdnsengine_export.h b/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/include/qmdnsengine_export.h index 03d7334..93343e1 100644 --- a/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/include/qmdnsengine_export.h +++ b/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/include/qmdnsengine_export.h @@ -27,6 +27,8 @@ #include +#define BUILD_SHARED_LIBS +#define QMDNSENGINE_LIBRARY #if defined(BUILD_SHARED_LIBS) # if defined(QMDNSENGINE_LIBRARY) # define QMDNSENGINE_EXPORT Q_DECL_EXPORT diff --git a/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/dns.cpp b/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/dns.cpp index f25bcbd..a17bfcd 100644 --- a/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/dns.cpp +++ b/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/dns.cpp @@ -339,7 +339,10 @@ void toPacket(const Message &message, QByteArray &packet) { quint16 offset = 0; quint16 flags = (message.isResponse() ? 0x8400 : 0) | - (message.isTruncated() ? 0x200 : 0); + (message.isTruncated() ? 0x200 : 0); + + qDebug() << "Flags set in toPacket:" << QString::number(flags, 16); + writeInteger(packet, offset, message.transactionId()); writeInteger(packet, offset, flags); writeInteger(packet, offset, message.queries().length()); diff --git a/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/prober.cpp b/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/prober.cpp index 3a58f58..60ecb5a 100644 --- a/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/prober.cpp +++ b/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/prober.cpp @@ -71,7 +71,6 @@ void ProberPrivate::assertRecord() message.addQuery(query); message.addRecord(proposedRecord); server->sendMessageToAll(message); - // Wait two seconds to confirm it is unique timer.stop(); timer.start(2 * 1000); @@ -80,14 +79,15 @@ void ProberPrivate::assertRecord() void ProberPrivate::onMessageReceived(const Message &message) { // If the response matches the proposed record, increment the suffix and - // try with the new name - - if (confirmed || !message.isResponse()) { + // try with the new name + //if (confirmed || !message.isResponse()) { + if (confirmed) { return; } const auto records = message.records(); for (const Record &record : records) { if (record.name() == proposedRecord.name() && record.type() == proposedRecord.type()) { + qDebug() << "Conflict detected for name:" << proposedRecord.name() << "with type:" << record.type(); ++suffix; assertRecord(); } diff --git a/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/provider.cpp b/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/provider.cpp index e1ed2a5..7c24e2d 100644 --- a/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/provider.cpp +++ b/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/provider.cpp @@ -79,8 +79,8 @@ void ProviderPrivate::confirm() delete prober; } prober = new Prober(server, srvProposed, this); - connect(prober, &Prober::nameConfirmed, [this](const QByteArray &name) { + connect(prober, &Prober::nameConfirmed, [this](const QByteArray &name) { // If existing records were confirmed, indicate that they are no // longer valid if (confirmed) { @@ -128,7 +128,7 @@ void ProviderPrivate::onMessageReceived(const Message &message) if (!confirmed || message.isResponse()) { return; } - + //qDebug() << "Failed to start server. Error:" << server->errorString(); bool sendBrowsePtr = false; bool sendPtr = false; bool sendSrv = false; @@ -227,13 +227,16 @@ void Provider::update(const Service &service) return; } bool registered = d->hostname->isRegistered(); - //qDebug() << "Hostname registered:" << registered; if(registered) { + // 不确认服务名称,直接进行广播 + d->publish(); //if (d->hostname->isRegistered()) { - if (!d->confirmed || fqName != d->srvRecord.name()) { + /*if (!d->confirmed || fqName != d->srvRecord.name()) { + qDebug() << "confirm()"; d->confirm(); } else { + qDebug() << "publish()"; d->publish(); - } + }*/ } } diff --git a/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/server.cpp b/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/server.cpp index b295a15..5369600 100644 --- a/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/server.cpp +++ b/FactoryTestTool/SourceCode/Network/mdns/qmdnsengine/src/server.cpp @@ -129,8 +129,6 @@ void Server::sendMessageToAll(const Message &message) { QByteArray packet; toPacket(message, packet); - //qDebug() << "MdnsMsg :" << packet.toHex(); - qDebug() << "MdnsPort:" << MdnsPort; qint64 sentBytes = d->ipv4Socket.writeDatagram(packet, MdnsIpv4Address, MdnsPort); qDebug() << "ipv4Socket sentBytes:" << sentBytes; sentBytes = d->ipv6Socket.writeDatagram(packet, MdnsIpv6Address, MdnsPort); diff --git a/FactoryTestTool/SourceCode/Network/mdns/servicemodel.cpp b/FactoryTestTool/SourceCode/Network/mdns/servicemodel.cpp index 38f05ae..de3d148 100644 --- a/FactoryTestTool/SourceCode/Network/mdns/servicemodel.cpp +++ b/FactoryTestTool/SourceCode/Network/mdns/servicemodel.cpp @@ -1,4 +1,4 @@ -// #include "servicemodel.cpp" +// servicemodel.cpp #include "servicemodel.h" Q_DECLARE_METATYPE(QMdnsEngine::Service) diff --git a/FactoryTestTool/SourceCode/Network/mdns/servicemodel.h b/FactoryTestTool/SourceCode/Network/mdns/servicemodel.h index 0db827b..ed1d958 100644 --- a/FactoryTestTool/SourceCode/Network/mdns/servicemodel.h +++ b/FactoryTestTool/SourceCode/Network/mdns/servicemodel.h @@ -1,3 +1,4 @@ +// servicemodel.h #ifndef SERVICEMODEL_H #define SERVICEMODEL_H @@ -7,7 +8,8 @@ #include "qmdnsengine/include/hostname.h" #include "qmdnsengine/include/provider.h" #include "qmdnsengine/include/service.h" - +#include "qmdnsengine/include/message.h" +#include "qmdnsengine/include/query.h" class ServiceProvider : public QObject { diff --git a/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.cpp b/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.cpp index 04551c3..d7eac15 100644 --- a/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.cpp +++ b/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.cpp @@ -27,11 +27,14 @@ DataHandler::DataHandler(QLabel* leftLens_imageLabel, QLabel* rightLens_imageLab ffmpegDecoder->initialize(); // 初始化解码器 clearAllRecvData(); initializeMsgIdToCmdMap(); + qDebug() << "DataHandler created"; } DataHandler::~DataHandler() { + qDebug() << "---1--- DataHandler destroyed"; if (ffmpegDecoder) { + ffmpegDecoder->stopFFmpegDecoder(); ffmpegDecoder->requestInterruption(); ffmpegDecoder->wait(); // 等待解码器线程完成 delete ffmpegDecoder; @@ -39,6 +42,14 @@ DataHandler::~DataHandler() } delete buffer; buffer = nullptr; + qDebug() << "---2--- DataHandler destroyed"; +} + +void DataHandler::handleOpenFocusWindow(int itemIndex) +{ + if (ffmpegDecoder) { + ffmpegDecoder->processVideo(itemIndex); // 调用 FFmpegDecoder 的处理函数 + } } QByteArray DataHandler::hexStringToByteArray(const QString& hexString) @@ -50,16 +61,17 @@ QByteArray DataHandler::hexStringToByteArray(const QString& hexString) return byteArray; } -const QString filePath_1 = "add1.h264"; +const QString filePath_1 = "/add1.h264"; // 显示视频的函数 void DataHandler::showVideo(const QString& client, const QByteArray& valData) { - static QFile file(filePath_1); + QString h264filePath = QDir::currentPath() + filePath_1; + static QFile file(h264filePath); if (!file.isOpen()) { - if (QFile::exists(filePath_1)) { - QFile::remove(filePath_1); + if (QFile::exists(h264filePath)) { + QFile::remove(h264filePath); } if (!file.open(QIODevice::Append | QIODevice::WriteOnly)) { qWarning() << "无法打开H264文件:" << file.errorString(); @@ -74,7 +86,7 @@ void DataHandler::showVideo(const QString& client, const QByteArray& valData) if (!start_run) { start_run = 1; - ffmpegDecoder->decodeFile(filePath_1, videoLabel); + ffmpegDecoder->decodeFile(h264filePath, videoLabel); } //ffmpegDecoder->decodeFile(filePath_1, videoLabel); } diff --git a/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.h b/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.h index f3d6c71..fe0e1e0 100644 --- a/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.h +++ b/FactoryTestTool/SourceCode/RecvDataHandler/RecvDataHandler.h @@ -46,7 +46,7 @@ public slots: void handleData(const QString& client, const QByteArray& data, int msg_id, int currentRecvItemIndex, int currentRecvFuncItemIndex, const QString& itemData, const QString& funcItemData, const QJsonArray& jsonArray, int itemJsonIndex); - + void handleOpenFocusWindow(int itemIndex); signals: void statusUpdated(const QString& clientAddress, int currentItemIndex, int currentFuncItemIndex, bool success, const QString& currentItemLabel, const QString& currentFuncItemLabel, diff --git a/FactoryTestTool/SourceCode/Widget/FocusWindow.h b/FactoryTestTool/SourceCode/Widget/FocusWindow.h index 600f50a..cdf5a7c 100644 --- a/FactoryTestTool/SourceCode/Widget/FocusWindow.h +++ b/FactoryTestTool/SourceCode/Widget/FocusWindow.h @@ -8,10 +8,11 @@ class NewButtonDialog : public QDialog Q_OBJECT public: - NewButtonDialog(QWidget* parent = nullptr) : QDialog(parent) + NewButtonDialog(QWidget* parent = nullptr, const QSize& labelSize = QSize(480, 640)) : QDialog(parent) { QVBoxLayout* layout = new QVBoxLayout(this); QLabel* label = new QLabel("This is a new window opened by clicking the new button.", this); + label->setFixedSize(labelSize); // 设置QLabel的固定大小 layout->addWidget(label); QPushButton* closeButton = new QPushButton("Close", this); @@ -20,6 +21,6 @@ public: setLayout(layout); setWindowTitle("SL100 视频播放窗口"); - resize(480, 640); // 设置对话框的大小 + //resize(500, 700); // 设置对话框的大小 } }; diff --git a/FactoryTestTool/SourceCode/Widget/MainWidget.cpp b/FactoryTestTool/SourceCode/Widget/MainWidget.cpp index 2ff610d..a6f40f7 100644 --- a/FactoryTestTool/SourceCode/Widget/MainWidget.cpp +++ b/FactoryTestTool/SourceCode/Widget/MainWidget.cpp @@ -1,7 +1,6 @@ // MainWidget.cpp #include "MainWidget.h" - void onThreadFinished(QThread* thread, ClientHandler* handler) { qDebug() << "Thread finished. Deleting handler and thread."; @@ -27,36 +26,79 @@ MainWidget::MainWidget(QWidget* parent) : multicastTimer(new QTimer(this)) #endif { - leftLens_imageLabel = new QLabel(this); - rightLens_imageLabel = new QLabel(this); - videoLabel = new QLabel(this); + leftLens_imageLabel = new QLabel(this); + rightLens_imageLabel = new QLabel(this); + videoLabel = new QLabel(this); frontFuncConfigLineEdit = new QLineEdit(this); - backFuncConfigLineEdit = new QLineEdit(this); - licenseHwInfoEdit = new QTextEdit(this); - UuidHwInfoEdit = new QTextEdit(this); + backFuncConfigLineEdit = new QLineEdit(this); + licenseHwInfoEdit = new QTextEdit(this); + UuidHwInfoEdit = new QTextEdit(this); + + + + // 创建 mDNS 服务的 Server 和 Hostname 对象 + QMdnsEngine::Server myserver; + QMdnsEngine::Hostname hostname(&myserver); + + // 创建服务提供者(Provider) + QMdnsEngine::Provider provider(&myserver, &hostname); + + // 定义要广播的服务 + QMdnsEngine::Service service; + service.setName("Test Service"); + service.setType("_test._tcp"); // 服务类型,包括 _tcp 或 _udp + service.setPort(12345); // 服务使用的端口号 + + // 启动服务广播 + provider.update(service); + + qDebug() << "mDNS service started. Broadcasting service:" + << service.name() << service.type() << "on port" << service.port(); + + setupUI(); // 打印线程池状态信息 setupTimerForThreadPoolInfo(); server = new QTcpServer(this); + /* + // 创建 DataHandler 对象并连接信号 + DataHandler* dataHandler = new DataHandler(leftLens_imageLabel, rightLens_imageLabel, videoLabel, licenseHwInfoEdit, &devInfoLineEdits, + frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig, + frontBoardDevInfoJson, frontBoardLicenseJson, + backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson, + backBoardUuidJson, getPicJson, getVideoJson, this); - //FactoryToolSendGetUuidToHttpServer(); - //FactoryToolSendGetLicenseToHttpServer(); - //FactoryToolSendPostComfirmToHttpServer(); - //FactoryToolSendPostTestToHttpServer(); - //FactoryToolSendPostLicenseToHttpServer(); - + connect(this, &MainWidget::openFocusWindowRequested, dataHandler, &DataHandler::handleOpenFocusWindow); + connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated); + */ connect(server, &QTcpServer::newConnection, this, [this]() { // 检查是否有挂起的连接 while (server->hasPendingConnections()) { QTcpSocket* socket = server->nextPendingConnection(); - int clientId = nextClientId++; + int clientId = nextClientId ++; + QHostAddress clientIp = socket->peerAddress(); + quint16 clientPort = socket->peerPort(); + QString ipString = clientIp.toString(); + if (ipString.startsWith("::ffff:")) { + ipString = ipString.mid(7); + } qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; qDebug() << "> A client is connected. ID:" << clientId; + qDebug() << "> Client IP:" << ipString << " Port:" << clientPort; qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; + if (ipString.startsWith("10.10.10")) { + qDebug() << "The client IP address is front board !!!"; + isBackBoardOrAllBoard = 0; + } + else { + qDebug() << "The client IP address is back board or all board"; + isBackBoardOrAllBoard = clientId; + } + stopMdnsService(); - connectedClientsCount++; + connectedClientsCount ++; updateServerButtonText(); QTimer* timer = new QTimer(this); @@ -76,11 +118,11 @@ MainWidget::MainWidget(QWidget* parent) : } }); - QThread* thread = new QThread(this); + QThread* thread = new QThread(this); ClientHandler* handler = new ClientHandler(socket, frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig, frontBoardDevInfoJson, frontBoardLicenseJson, backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson, - backBoardUuidJson, getPicJson, getVideoJson, clientId, nullptr); + backBoardUuidJson, getPicJson, getVideoJson, clientId, isBackBoardOrAllBoard, nullptr); // 将 ClientHandler 移动到线程池中的线程 handler->moveToThread(thread); @@ -91,7 +133,7 @@ MainWidget::MainWidget(QWidget* parent) : }); // 将sendData信号连接到主线程中的槽上 - connect(handler, &ClientHandler::sendData, this, [socket](const QByteArray& data) { + connect(handler, &ClientHandler::sendData, this, [socket](const QByteArray& data, int isBoardType) { /*socket->write(data); socket->flush();*/ //qDebug() << "---------------------data.size():" << data.size(); @@ -99,7 +141,12 @@ MainWidget::MainWidget(QWidget* parent) : QDataStream stream(&prefix, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::LittleEndian); stream << quint32(0x55AA55AA); - stream << quint16(0x0420); + if (isBoardType != 0) { + stream << quint16(0x0421); + } + else { + stream << quint16(0x0420); + } stream << quint32(data.size()); prefix.append(data); @@ -124,15 +171,20 @@ MainWidget::MainWidget(QWidget* parent) : connect(handler, &ClientHandler::allItemsProcessed, this, &MainWidget::onAllItemsProcessed); connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient); +#if 1 // 创建 DataHandler 对象并连接信号 DataHandler* dataHandler = new DataHandler(leftLens_imageLabel, rightLens_imageLabel, videoLabel, licenseHwInfoEdit, &devInfoLineEdits, frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig, frontBoardDevInfoJson, frontBoardLicenseJson, backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson, backBoardUuidJson, getPicJson, getVideoJson, this); - connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData); - connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated); - + dataHandlers[clientId] = dataHandler; + connect(this, &MainWidget::openFocusWindowRequested, dataHandler, &DataHandler::handleOpenFocusWindow); + connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData); + connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated); +#else + connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData); +#endif connect(handler, &ClientHandler::startReadTimer, this, &MainWidget::startClientReadTimer); connect(handler, &ClientHandler::stopReadTimer, this, &MainWidget::stopClientReadTimer); @@ -157,7 +209,6 @@ MainWidget::MainWidget(QWidget* parent) : connectionStatusCheckTimer = new QTimer(this); connect(connectionStatusCheckTimer, &QTimer::timeout, this, &MainWidget::onCheckConnectionStatus); //connectionStatusCheckTimer->start(100); // 每100ms检查一次连接状态 - connect(mdnsTimer, &QTimer::timeout, this, &MainWidget::startMdnsService); #if TEST_UDP_BROADCAST @@ -199,6 +250,12 @@ MainWidget::~MainWidget() delete timer; } clientReadTimers.clear(); + + for (auto dataHandler : dataHandlers) { + dataHandler->deleteLater(); + } + dataHandlers.clear(); + for (ClientHandler* handler : clients) { handler->deleteLater(); } @@ -228,6 +285,206 @@ MainWidget::~MainWidget() qDebug() << "MainWidget destroyed"; } +// 处理客户端断开连接信号 +void MainWidget::onClientDisconnected(ClientHandler* handler) +{ + int clientId = handler->getClientId(); + qDebug() << " preVideoClientId :" << handler->preVideoClientId; + qDebug() << " clientId :" << clientId; + if (handler->preVideoClientId == clientId) { + qDebug() << "Current path: " << QDir::currentPath(); + QString filePath = QDir::currentPath() + "/add1.h264"; + if (QFile::exists(filePath)) { + QFile file(filePath); + if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + qDebug() << "File add1.h264 cleared successfully."; + } + else { + qDebug() << "Failed to clear file add1.h264:" << file.errorString(); + } + } + else { + qDebug() << "File add1.h264 does not exist."; + } + } + if (clientTimers.contains(clientId)) { + QTimer* timer = clientTimers[clientId]; + timer->stop(); + delete timer; + clientTimers.remove(clientId); + } + + clients.removeOne(handler); + /* + 将 ClientHandler 对象的删除操作放入事件队列中,等待事件循环处理。 + 在事件循环执行时,会安全地删除 ClientHandler 对象,这包括释放其占用的资源和内存 + */ + handler->deleteLater(); // 延迟删除 ClientHandler 对象 + + qDebug() << "-----------dataHandlers-----------"; + if (dataHandlers.contains(clientId)) { + DataHandler* dataHandler = dataHandlers[clientId]; + dataHandlers.remove(clientId); // 从容器中移除 + dataHandler->deleteLater(); // 延迟删除 DataHandler 对象 + } + + // 更新连接数并更新按键文本 + connectedClientsCount--; + qDebug() << " connectedClientsCount :" << connectedClientsCount; + if (nextClientId <= 2) nextClientId--; + deviceConnected = true; + + updateServerButtonText(); +} + +// 更新按键文本的函数 +void MainWidget::updateServerButtonText() +{ + if (deviceConnected) { + if (connectedClientsCount > 0) { + startServerButton->setText(tr("正在监听(Listening)\n%1 台设备连接").arg(connectedClientsCount)); + } + else if (connectedClientsCount == 0) { +#if START_MDNS // 这里会开启多个mdns广播,去掉 + startMdnsService(); +#endif + deviceConnected = false; + startServerButton->setText(tr("正在监听(Listening)")); + } + } + else if (connectedClientsCount == 0) { + startServerButton->setText(tr("开始监听\n(Start Listening...)")); + } + else { + startServerButton->setText(tr("正在监听(Listening)\n%1 台设备连接").arg(connectedClientsCount)); + } +} + +// 设置 UI +void MainWidget::setupUI() +{ + startServerButton = new QPushButton("开始监听\n(Start Listening...)", this); + startServerButton->setFixedSize(190, 70); + + sendAllButton = new QPushButton("一键功能测试", this); + sendAllButton->setFixedSize(190, 70); + sendAllButton->setEnabled(false); + + statusListWidget = new QListWidget(this); + statusListWidget->setMinimumSize(350, 840); + statusListWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + QHBoxLayout* buttonLayout = new QHBoxLayout; + buttonLayout->addWidget(startServerButton); + buttonLayout->addWidget(sendAllButton); + buttonLayout->addStretch(); + + QVBoxLayout* leftLayout = new QVBoxLayout; + leftLayout->addLayout(buttonLayout); + leftLayout->setStretch(0, 1); + leftLayout->addWidget(statusListWidget); + leftLayout->setStretch(1, 200); + + saveCheckBox = new QCheckBox("", this); + saveCheckBox->setChecked(true); + selectFileButton = new QPushButton("Save", this); + selectFileButton->setFixedSize(45, 28); + clearLogButton = new QPushButton("Clear", this); + clearLogButton->setFixedSize(55, 28); + filePathLineEdit = new QLineEdit(this); + filePathLineEdit->setFixedSize(250, 28); + filePathLineEdit->setReadOnly(true); + + QHBoxLayout* fileLayout = new QHBoxLayout; + fileLayout->addWidget(saveCheckBox); + fileLayout->addWidget(selectFileButton); + fileLayout->addWidget(filePathLineEdit); + fileLayout->addWidget(clearLogButton); + + leftLayout->addLayout(fileLayout); + leftLayout->setStretch(2, 1); + + // 读取 JSON 配置文件 + readJsonConfig(); + + QWidget* leftContainer = new QWidget(this); + leftContainer->setLayout(leftLayout); + leftContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + // 前板 + QGroupBox* frontDeviceInfoGroupBox = createFrontDeviceInfoGroupBox(); + QGroupBox* frontLicenseGroupBox = createLicenseGroupBox(); + + QHBoxLayout* frontGroupBoxLayout = new QHBoxLayout; + frontGroupBoxLayout->addWidget(frontDeviceInfoGroupBox, 1); + frontGroupBoxLayout->addWidget(frontLicenseGroupBox, 1); + + QTabWidget* frontTabWidget = new QTabWidget(this); + frontTabWidget->setFixedSize(900, 315); + QWidget* frontFunctionTestTab = createFunctionTestTab(frontBoardTest, "frontBoardTest"); + QWidget* frontFunctionConfigTab = createFunctionConfigTab(frontBoardFuncConfig, "frontBoardFuncConfig"); + frontTabWidget->addTab(frontFunctionTestTab, "前板测试项"); + frontTabWidget->addTab(frontFunctionConfigTab, "前板配置项"); + + QTabWidget* mainTabWidget = new QTabWidget(this); + QWidget* frontDevAreaTab = new QWidget(this); + QVBoxLayout* frontDevLayout = new QVBoxLayout(frontDevAreaTab); + frontDevLayout->addLayout(frontGroupBoxLayout); + frontDevLayout->addWidget(frontTabWidget, 2, Qt::AlignTop | Qt::AlignLeft); + mainTabWidget->addTab(frontDevAreaTab, "前 板"); + + // 后板 + QGroupBox* backDeviceInfoGroupBox1 = createBackDeviceInfoGroupBox(); + QGroupBox* BackConnectServerGroupBox = createBackConnectServerGroupBox(); + + QHBoxLayout* backGroupBoxLayout = new QHBoxLayout; + backGroupBoxLayout->addWidget(backDeviceInfoGroupBox1, 1); + backGroupBoxLayout->addWidget(BackConnectServerGroupBox, 1); + + QTabWidget* backTabWidget = new QTabWidget(this); + backTabWidget->setFixedSize(900, 315); + QWidget* backFunctionTestTab = createFunctionTestTab(backBoardTest, "backBoardTest"); + QWidget* backFunctionConfigTab = createFunctionConfigTab(backBoardFuncConfig, "backBoardFuncConfig"); + backTabWidget->addTab(backFunctionTestTab, "后板测试项"); + backTabWidget->addTab(backFunctionConfigTab, "后板配置项"); + + QWidget* backDevAreaTab = new QWidget(this); + QVBoxLayout* backDevLayout = new QVBoxLayout(backDevAreaTab); + backDevLayout->addLayout(backGroupBoxLayout); + backDevLayout->addWidget(backTabWidget, 2, Qt::AlignTop | Qt::AlignLeft); + mainTabWidget->addTab(backDevAreaTab, "后 板"); + + // 整机 + QWidget* allDevAreaTab = new QWidget(this); + QVBoxLayout* allDevLayout = new QVBoxLayout(allDevAreaTab); + mainTabWidget->addTab(allDevAreaTab, "整 机"); + + QTabWidget* tabWidget_media = new QTabWidget(this); + QWidget* imageDisplayTab = createImageDisplayTab(); + QWidget* videoDisplayTab = createVideoDisplayTab(); + tabWidget_media->addTab(imageDisplayTab, "图像显示区"); + tabWidget_media->addTab(videoDisplayTab, "视频显示区"); + + QVBoxLayout* rightVerticalLayout = new QVBoxLayout; + rightVerticalLayout->addWidget(mainTabWidget, 5); + rightVerticalLayout->addWidget(tabWidget_media, 4); + + QHBoxLayout* mainLayout = new QHBoxLayout; + mainLayout->addWidget(leftContainer, 1, Qt::AlignTop | Qt::AlignLeft); + mainLayout->addLayout(rightVerticalLayout, 3); + + setLayout(mainLayout); + setWindowTitle("SL100 工厂产测工具 - V0.0.1"); + resize(1340, 900); + + connect(startServerButton, &QPushButton::clicked, this, &MainWidget::onStartServerClicked); + connect(sendAllButton, &QPushButton::clicked, this, &MainWidget::onSendAllClicked); + connect(statusListWidget, &QListWidget::itemChanged, this, &MainWidget::scrollToBottom); + connect(selectFileButton, &QPushButton::clicked, this, &MainWidget::onSelectFileButtonClicked); + connect(clearLogButton, &QPushButton::clicked, this, &MainWidget::onclearLogButtonClicked); + connect(saveCheckBox, &QCheckBox::stateChanged, this, &MainWidget::onSaveCheckBoxStateChanged); +} + // 服务器响应 void MainWidget::onHttpRequestFinished(const QJsonObject& response) { @@ -546,131 +803,6 @@ void MainWidget::readJsonConfig() getVideoJson = readJson_getVideo(); } -// 设置 UI -void MainWidget::setupUI() -{ - startServerButton = new QPushButton("开始监听\n(Start Listening...)", this); - startServerButton->setFixedSize(190, 70); - - sendAllButton = new QPushButton("一键功能测试", this); - sendAllButton->setFixedSize(190, 70); - sendAllButton->setEnabled(false); - - statusListWidget = new QListWidget(this); - statusListWidget->setMinimumSize(350, 840); - statusListWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - - QHBoxLayout* buttonLayout = new QHBoxLayout; - buttonLayout->addWidget(startServerButton); - buttonLayout->addWidget(sendAllButton); - buttonLayout->addStretch(); - - QVBoxLayout* leftLayout = new QVBoxLayout; - leftLayout->addLayout(buttonLayout); - leftLayout->setStretch(0, 1); - leftLayout->addWidget(statusListWidget); - leftLayout->setStretch(1, 200); - - saveCheckBox = new QCheckBox("", this); - saveCheckBox->setChecked(true); - selectFileButton = new QPushButton("Save", this); - selectFileButton->setFixedSize(45, 28); - clearLogButton = new QPushButton("Clear", this); - clearLogButton->setFixedSize(55, 28); - filePathLineEdit = new QLineEdit(this); - filePathLineEdit->setFixedSize(250, 28); - filePathLineEdit->setReadOnly(true); - - QHBoxLayout* fileLayout = new QHBoxLayout; - fileLayout->addWidget(saveCheckBox); - fileLayout->addWidget(selectFileButton); - fileLayout->addWidget(filePathLineEdit); - fileLayout->addWidget(clearLogButton); - - leftLayout->addLayout(fileLayout); - leftLayout->setStretch(2, 1); - - // 读取 JSON 配置文件 - readJsonConfig(); - - QWidget* leftContainer = new QWidget(this); - leftContainer->setLayout(leftLayout); - leftContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - - // 前板 - QGroupBox* frontDeviceInfoGroupBox = createFrontDeviceInfoGroupBox(); - QGroupBox* frontLicenseGroupBox = createLicenseGroupBox(); - - QHBoxLayout* frontGroupBoxLayout = new QHBoxLayout; - frontGroupBoxLayout->addWidget(frontDeviceInfoGroupBox, 1); - frontGroupBoxLayout->addWidget(frontLicenseGroupBox, 1); - - QTabWidget* frontTabWidget = new QTabWidget(this); - frontTabWidget->setFixedSize(900, 315); - QWidget* frontFunctionTestTab = createFunctionTestTab(frontBoardTest, "frontBoardTest"); - QWidget* frontFunctionConfigTab = createFunctionConfigTab(frontBoardFuncConfig, "frontBoardFuncConfig"); - frontTabWidget->addTab(frontFunctionTestTab, "前板测试项"); - frontTabWidget->addTab(frontFunctionConfigTab, "前板配置项"); - - QTabWidget* mainTabWidget = new QTabWidget(this); - QWidget* frontDevAreaTab = new QWidget(this); - QVBoxLayout* frontDevLayout = new QVBoxLayout(frontDevAreaTab); - frontDevLayout->addLayout(frontGroupBoxLayout); - frontDevLayout->addWidget(frontTabWidget, 2, Qt::AlignTop | Qt::AlignLeft); - mainTabWidget->addTab(frontDevAreaTab, "前 板"); - - // 后板 - QGroupBox* backDeviceInfoGroupBox1 = createBackDeviceInfoGroupBox(); - QGroupBox* BackConnectServerGroupBox = createBackConnectServerGroupBox(); - - QHBoxLayout* backGroupBoxLayout = new QHBoxLayout; - backGroupBoxLayout->addWidget(backDeviceInfoGroupBox1, 1); - backGroupBoxLayout->addWidget(BackConnectServerGroupBox, 1); - - QTabWidget* backTabWidget = new QTabWidget(this); - backTabWidget->setFixedSize(900, 315); - QWidget* backFunctionTestTab = createFunctionTestTab(backBoardTest, "backBoardTest"); - QWidget* backFunctionConfigTab = createFunctionConfigTab(backBoardFuncConfig, "backBoardFuncConfig"); - backTabWidget->addTab(backFunctionTestTab, "后板测试项"); - backTabWidget->addTab(backFunctionConfigTab, "后板配置项"); - - QWidget* backDevAreaTab = new QWidget(this); - QVBoxLayout* backDevLayout = new QVBoxLayout(backDevAreaTab); - backDevLayout->addLayout(backGroupBoxLayout); - backDevLayout->addWidget(backTabWidget, 2, Qt::AlignTop | Qt::AlignLeft); - mainTabWidget->addTab(backDevAreaTab, "后 板"); - - // 整机 - QWidget* allDevAreaTab = new QWidget(this); - QVBoxLayout* allDevLayout = new QVBoxLayout(allDevAreaTab); - mainTabWidget->addTab(allDevAreaTab, "整 机"); - - QTabWidget* tabWidget_media = new QTabWidget(this); - QWidget* imageDisplayTab = createImageDisplayTab(); - QWidget* videoDisplayTab = createVideoDisplayTab(); - tabWidget_media->addTab(imageDisplayTab, "图像显示区"); - tabWidget_media->addTab(videoDisplayTab, "视频显示区"); - - QVBoxLayout* rightVerticalLayout = new QVBoxLayout; - rightVerticalLayout->addWidget(mainTabWidget, 5); - rightVerticalLayout->addWidget(tabWidget_media, 4); - - QHBoxLayout* mainLayout = new QHBoxLayout; - mainLayout->addWidget(leftContainer, 1, Qt::AlignTop | Qt::AlignLeft); - mainLayout->addLayout(rightVerticalLayout, 3); - - setLayout(mainLayout); - setWindowTitle("SL100 工厂产测工具 - V0.0.1"); - resize(1340, 900); - - connect(startServerButton, &QPushButton::clicked, this, &MainWidget::onStartServerClicked); - connect(sendAllButton, &QPushButton::clicked, this, &MainWidget::onSendAllClicked); - connect(statusListWidget, &QListWidget::itemChanged, this, &MainWidget::scrollToBottom); - connect(selectFileButton, &QPushButton::clicked, this, &MainWidget::onSelectFileButtonClicked); - connect(clearLogButton, &QPushButton::clicked, this, &MainWidget::onclearLogButtonClicked); - connect(saveCheckBox, &QCheckBox::stateChanged, this, &MainWidget::onSaveCheckBoxStateChanged); -} - void MainWidget::onSelectFileButtonClicked() { QString filePath = QFileDialog::getSaveFileName(this, tr("选择文件路径"), "", tr("Text Files (*.txt);;All Files (*)")); @@ -754,75 +886,14 @@ void MainWidget::onDisconnectClient(int clientId) clientTimers.remove(clientId); } handler->deleteLater(); - connectedClientsCount--; + connectedClientsCount --; updateServerButtonText(); - break; } } - - // 启动 mDNS 服务广播 - startMdnsService(); -} - -// 处理客户端断开连接信号 -void MainWidget::onClientDisconnected(ClientHandler* handler) -{ - int clientId = handler->getClientId(); - qDebug() << " preVideoClientId :" << handler->preVideoClientId; - qDebug() << " clientId :" << clientId; - if (handler->preVideoClientId == clientId) { - qDebug() << "Current path: " << QDir::currentPath(); - QString filePath = QDir::currentPath() + "/add1.h264"; - if (QFile::exists(filePath)) { - QFile file(filePath); - if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { // 使用 Truncate 模式打开文件以清空内容 - qDebug() << "File add1.h264 cleared successfully."; - } - else { - qDebug() << "Failed to clear file add1.h264:" << file.errorString(); - } - } - else { - qDebug() << "File add1.h264 does not exist."; - } - } - if (clientTimers.contains(clientId)) { - QTimer* timer = clientTimers[clientId]; - timer->stop(); - delete timer; - clientTimers.remove(clientId); - } - - clients.removeOne(handler); - /* - 将 ClientHandler 对象的删除操作放入事件队列中,等待事件循环处理。 - 在事件循环执行时,会安全地删除 ClientHandler 对象,这包括释放其占用的资源和内存 - */ - handler->deleteLater(); // 延迟删除 ClientHandler 对象 - - // 更新连接数并更新按键文本 - connectedClientsCount--; - qDebug() << " connectedClientsCount :" << connectedClientsCount; - if (nextClientId <= 2) nextClientId--; - deviceConnected = true; - - updateServerButtonText(); -} - -// 更新按键文本的函数 -void MainWidget::updateServerButtonText() -{ - if (deviceConnected) { - deviceConnected = false; - startServerButton->setText(tr("正在监听(Listening)")); - if (connectedClientsCount == 0) startMdnsService(); - } - else if (connectedClientsCount == 0) { - startServerButton->setText(tr("开始监听\n(Start Listening...)")); - } - else { - startServerButton->setText(tr("正在监听(Listening)\n%1 台设备连接").arg(connectedClientsCount)); + if (connectedClientsCount == 0) { + // 启动 mDNS 服务广播 + startMdnsService(); } } @@ -1026,7 +1097,7 @@ void MainWidget::startMdnsService() QString formattedTime = currentTime.toString("yyyy-MM-dd hh:mm:ss.zzz"); qDebug() << "[" << formattedTime << "]:" << "Start Mdns Broadcast Service"; QString serviceName = "SL100 FactoryTool Mdns Broadcast Service"; - QString serviceType = "_SL100_FactoryTool-service._tcp"; + QString serviceType = "_myservice._tcp.local"; quint16 port = TCP_CONNECT_PORT; mServiceProvider->startServiceBroadcast(serviceName, serviceType, port); @@ -1086,13 +1157,15 @@ void MainWidget::onStartServerClicked() startServerButton->setText(tr("开始监听\n(Start Listening...)")); startServerButton->setStyleSheet(""); sendAllButton->setEnabled(false); - stopMdnsService(); } } void MainWidget::sendDataToClient(int clientId, const QByteArray& data) { + if ((clientId == 0) && (isBackBoardOrAllBoard)) { + clientId = isBackBoardOrAllBoard; + } if (clients_1.contains(clientId)) { ClientHandler* handler = clients_1[clientId]; handler->sendDataToClient(data); // 调用 ClientHandler 中的方法发送数据 @@ -1232,9 +1305,7 @@ void MainWidget::onOpenFocusWindowClicked() int itemIndex = button->property("getVideoIndex").toInt(); //qDebug() << "New Button clicked with itemIndex:" << itemIndex; if (itemIndex == 2) { - // 创建并显示新窗口 - NewButtonDialog dialog(this); - dialog.exec(); + emit openFocusWindowRequested(itemIndex); // 发送信号 } } } @@ -1301,7 +1372,7 @@ void MainWidget::onSendBackFuncItemClicked() QPushButton* button = qobject_cast(sender()); int itemIndex = button->property("backBoardFuncConfig").toInt(); for (ClientHandler* handler : clients) { - if (handler->getClientId() == handler->controlClientId) { + if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) { QString text = backFuncConfigLineEdit->text(); qDebug() << "Text in backFuncConfigLineEdit:" << text; handler->sendBackFuncItem(itemIndex, text); @@ -1342,7 +1413,7 @@ void MainWidget::onSendBackItemClicked() QPushButton* button = qobject_cast(sender()); int itemIndex = button->property("backBoardTest").toInt(); for (ClientHandler* handler : clients) { - if (handler->getClientId() == handler->controlClientId) { + if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) { handler->sendBackItem(itemIndex); break; } diff --git a/FactoryTestTool/SourceCode/Widget/MainWidget.h b/FactoryTestTool/SourceCode/Widget/MainWidget.h index 970bf71..6329a95 100644 --- a/FactoryTestTool/SourceCode/Widget/MainWidget.h +++ b/FactoryTestTool/SourceCode/Widget/MainWidget.h @@ -54,8 +54,16 @@ #include "FocusWindow.h" +#include "../Network/mdns/qmdnsengine/include/server.h" +#include "../Network/mdns/qmdnsengine/include/hostname.h" +#include "../Network/mdns/qmdnsengine/include/provider.h" +#include "../Network/mdns/qmdnsengine/include/service.h" +#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 START_MDNS 1 #define TCP_CONNECT_PORT 12412 // TCP监听的端口 @@ -68,6 +76,9 @@ public: explicit MainWidget(QWidget* parent = nullptr); ~MainWidget(); +signals: + void openFocusWindowRequested(int itemIndex); + private slots: // 发送HTTP请求 //void onSomeButtonClicked(); @@ -178,6 +189,7 @@ private: int nextClientId; // 新增的客户端编号 int connectedClientsCount = 0; // 连接客户端的数量 int isRequestSuccessful = 0; // GET请求是否成功 + int isBackBoardOrAllBoard = 0; bool manualSend; // 判断是否是手动触发的发送 bool deviceConnected = false; // 判断是否有设备连接过 bool isSendingAll; // 一键功能测试 状态 @@ -217,6 +229,7 @@ private: QTimer* threadStatusTimer; // 检查线程状态的定时器 QTimer* connectionStatusCheckTimer; // 检查连接状态的定时器 + QMap dataHandlers; QMap clientThreads; QMap clientReadTimers; QMap clients_1; diff --git a/FactoryTestTool/SourceCode/main.cpp b/FactoryTestTool/SourceCode/main.cpp index 8650b00..67efc08 100644 --- a/FactoryTestTool/SourceCode/main.cpp +++ b/FactoryTestTool/SourceCode/main.cpp @@ -23,7 +23,7 @@ int main(int argc, char* argv[]) { //closeConsole(); // 调用函数关闭控制台窗口 //FreeConsole(); // 关闭控制台窗口 QApplication app(argc, argv); - + qDebug() << "Current working directory:" << QDir::currentPath(); QIcon appIcon("./app_icon.ico"); app.setWindowIcon(appIcon); diff --git a/FactoryTestTool/TestLog/20240829_191522.txt b/FactoryTestTool/TestLog/20240829_191522.txt new file mode 100644 index 0000000..ad7ea84 --- /dev/null +++ b/FactoryTestTool/TestLog/20240829_191522.txt @@ -0,0 +1,6 @@ +device ID: 1 - Item 0: ---> NG +device ID: 1 - Item 0: ---> NG +device ID: 1 - Item 0: ---> NG +device ID: 1 - Item 0: ---> NG +device ID: 1 - Item 0: ---> NG +device ID:-1 ---> All 5 items test completed !!! diff --git a/FactoryTestTool/add1.h264 b/FactoryTestTool/add1.h264 index 231a279..e69de29 100644 Binary files a/FactoryTestTool/add1.h264 and b/FactoryTestTool/add1.h264 differ