1.更新MDNS广播的服务类型命名规范,防止出现多设备打开找不到MDNS的广播的问题 2.更新区分前后板的TAG

This commit is contained in:
钟富强 2024-09-02 10:22:41 +08:00
parent e0c1e37191
commit 09c5843358
22 changed files with 501 additions and 304 deletions

View File

@ -105,6 +105,7 @@
<QtMoc Include="SourceCode\Network\mdns\servicemodel.h" /> <QtMoc Include="SourceCode\Network\mdns\servicemodel.h" />
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\abstractserver.h" /> <QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\abstractserver.h" />
<QtMoc Include="SourceCode\Network\httpClient.h" /> <QtMoc Include="SourceCode\Network\httpClient.h" />
<QtMoc Include="SourceCode\Media\VideoDecoder\FocusWindow.h" />
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\bitmap.h" /> <ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\bitmap.h" />
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\browser.h" /> <QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\browser.h" />
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\cache.h" /> <QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\cache.h" />

View File

@ -160,6 +160,9 @@
<QtMoc Include="SourceCode\Network\httpClient.h"> <QtMoc Include="SourceCode\Network\httpClient.h">
<Filter>Network</Filter> <Filter>Network</Filter>
</QtMoc> </QtMoc>
<QtMoc Include="SourceCode\Media\VideoDecoder\FocusWindow.h">
<Filter>Media\VideoDecoder</Filter>
</QtMoc>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include=".editorconfig" /> <None Include=".editorconfig" />

View File

@ -15,7 +15,7 @@ FFmpegDecoder::FFmpegDecoder(QObject* parent) :
{ {
av_log_set_level(AV_LOG_QUIET); // 设置日志级别为安静模式 av_log_set_level(AV_LOG_QUIET); // 设置日志级别为安静模式
avformat_network_init(); // 初始化网络 avformat_network_init(); // 初始化网络
//qDebug() << "FFmpegDecoder created"; qDebug() << "FFmpegDecoder created";
} }
FFmpegDecoder::~FFmpegDecoder() FFmpegDecoder::~FFmpegDecoder()
@ -31,16 +31,54 @@ FFmpegDecoder::~FFmpegDecoder()
qDebug() << "FFmpegDecoder destroyed"; 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() void FFmpegDecoder::initialize()
{ {
// 初始化FFmpeg库 // 初始化FFmpeg库
avformat_network_init(); avformat_network_init();
} }
void FFmpegDecoder::stopFFmpegDecoder()
{
mutex.lock();
abort = true;
condition.wakeOne(); // 唤醒等待的线程
mutex.unlock();
}
void FFmpegDecoder::decodeFile(const QString& filePath, QLabel* videoDisplayLabel) void FFmpegDecoder::decodeFile(const QString& filePath, QLabel* videoDisplayLabel)
{ {
QMutexLocker locker(&mutex); QMutexLocker locker(&mutex);
this->filePath = filePath; this->filePath = filePath;
this->videoLabel = videoDisplayLabel; this->videoLabel = videoDisplayLabel;
if (!isRunning()) { if (!isRunning()) {
qDebug() << "Starting decoder thread"; qDebug() << "Starting decoder thread";
@ -55,7 +93,7 @@ void FFmpegDecoder::run()
QFile file(filePath); QFile file(filePath);
qint64 fileSize = 0; qint64 fileSize = 0;
while (true) { while (!isInterruptionRequested()) {
mutex.lock(); mutex.lock();
while (!restart && !abort) { while (!restart && !abort) {
condition.wait(&mutex); condition.wait(&mutex);
@ -65,14 +103,12 @@ void FFmpegDecoder::run()
qDebug() << "Decoder thread aborting"; qDebug() << "Decoder thread aborting";
break; break;
} }
restart = false;
QLabel* currentVideoLabel = videoLabel; QLabel* currentVideoLabel = videoLabel;
QSize labelSize = currentVideoLabel->size(); QSize labelSize = currentVideoLabel->size();
mutex.unlock(); mutex.unlock();
if (labelSize.width() <= 0 || labelSize.height() <= 0) { if (labelSize.width() < 740 || labelSize.height() < 357) {
// 自动调整 QLabel 大小 labelSize = QSize(740, 357);
labelSize = QSize(800, 600); // 例如设置为默认大小
currentVideoLabel->setFixedSize(labelSize); currentVideoLabel->setFixedSize(labelSize);
qDebug() << "Adjusting video label size to: Width =" << labelSize.width() << ", Height =" << labelSize.height(); qDebug() << "Adjusting video label size to: Width =" << labelSize.width() << ", Height =" << labelSize.height();
} }
@ -88,14 +124,18 @@ void FFmpegDecoder::run()
file.close(); file.close();
continue; continue;
} }
restart = false;
while (!abort) { while (!abort) {
qint64 currentFileSize = file.size(); qint64 currentFileSize = file.size();
//qDebug() << "Decoder thread currentFileSize:" << currentFileSize;
//qDebug() << "Decoder thread fileSize:" << fileSize;
if (currentFileSize > fileSize) { if (currentFileSize > fileSize) {
fileSize = currentFileSize; fileSize = currentFileSize;
file.seek(fileSize); // 设置文件读取位置到末尾 file.seek(fileSize); // 设置文件读取位置到末尾
//qDebug() << "---------------1---------------";
// 读取并处理数据包 // 读取并处理数据包
while (av_read_frame(formatContext, packet) >= 0) { while (av_read_frame(formatContext, packet) >= 0) {
//qDebug() << "---------------2---------------";
if (packet->stream_index == videoStreamIndex) { if (packet->stream_index == videoStreamIndex) {
int ret = avcodec_send_packet(codecContext, packet); int ret = avcodec_send_packet(codecContext, packet);
if (ret < 0) { if (ret < 0) {
@ -103,6 +143,7 @@ void FFmpegDecoder::run()
av_packet_unref(packet); av_packet_unref(packet);
continue; continue;
} }
//qDebug() << "---------------3---------------";
while (ret >= 0) { while (ret >= 0) {
ret = avcodec_receive_frame(codecContext, frame); ret = avcodec_receive_frame(codecContext, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
@ -113,28 +154,31 @@ void FFmpegDecoder::run()
qWarning() << "Error during decoding"; qWarning() << "Error during decoding";
break; break;
} }
//qDebug() << "---------------4---------------";
qDebug() << "H264 video resolution: Width =" << frame->width << ", Height =" << frame->height;
QImage img = avFrameToQImage(frame); QImage img = avFrameToQImage(frame);
//qDebug() << "---------------5---------------";
QImage scaledImage = img.scaled(labelSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); QImage scaledImage = img.scaled(labelSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
//qDebug() << "---------------6---------------";
currentVideoLabel->setPixmap(QPixmap::fromImage(scaledImage)); currentVideoLabel->setPixmap(QPixmap::fromImage(scaledImage));
QThread::msleep(10); // Simulate 25 FPS frame rate QThread::msleep(10); // Simulate 25 FPS frame rate
//qDebug() << "---------------7---------------";
} }
} }
av_packet_unref(packet); av_packet_unref(packet);
//qDebug() << "---------------8---------------";
} }
} }
//qDebug() << "---------------9---------------";
mutex.lock(); mutex.lock();
if (restart) { if (restart) {
restart = false; restart = false;
mutex.unlock(); mutex.unlock();
break; break;
} }
//qDebug() << "---------------10---------------";
mutex.unlock(); mutex.unlock();
} }
//qDebug() << "---------------11---------------";
cleanup(); cleanup();
file.close(); file.close();
@ -148,6 +192,10 @@ void FFmpegDecoder::run()
bool FFmpegDecoder::initializeFFmpeg(const QString& filePath) 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) { if (avformat_open_input(&formatContext, filePath.toStdString().c_str(), nullptr, nullptr) != 0) {
qWarning() << "Failed to open file with FFmpeg:" << filePath; qWarning() << "Failed to open file with FFmpeg:" << filePath;
return false; return false;
@ -227,6 +275,8 @@ QImage FFmpegDecoder::avFrameToQImage(AVFrame* frame)
{ {
int width = frame->width; int width = frame->width;
int height = frame->height; int height = frame->height;
qDebug() << "H264 video resolution: Width =" << frame->width << ", Height =" << frame->height;
AVPixelFormat pixFmt = (AVPixelFormat)frame->format; AVPixelFormat pixFmt = (AVPixelFormat)frame->format;
if (!swsContext) { if (!swsContext) {

View File

@ -14,8 +14,10 @@
#include <QWaitCondition> #include <QWaitCondition>
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include <QDir>
#include "RingBuffer.h" #include "RingBuffer.h"
#include "FocusWindow.h"
extern "C" { extern "C" {
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
@ -38,9 +40,10 @@ public:
void initialize(); void initialize();
void decodeFile(const QString& filePath, QLabel* videoLabel); void decodeFile(const QString& filePath, QLabel* videoLabel);
void decodeSingleFrame(const QByteArray& data, QLabel* videoLabel); // 添加 videoLabel 参数 void decodeSingleFrame(const QByteArray& data, QLabel* videoLabel); // 添加 videoLabel 参数
void FFmpegDecoder::processVideo(int itemIndex);
bool initializeFFmpeg(const QString& filePath); bool initializeFFmpeg(const QString& filePath);
void cleanup(); void cleanup();
void stopFFmpegDecoder();
protected: protected:
void run() override; void run() override;
@ -48,19 +51,19 @@ protected:
private: private:
QImage avFrameToQImage(AVFrame* frame); QImage avFrameToQImage(AVFrame* frame);
QMutex mutex; QMutex mutex;
QWaitCondition condition; QWaitCondition condition;
QString filePath; QString filePath;
QLabel* videoLabel; QLabel* videoLabel;
bool abort; bool abort;
bool restart; bool restart;
AVFormatContext* formatContext; AVFormatContext* formatContext;
AVCodecContext* codecContext; AVCodecContext* codecContext;
AVFrame* frame; AVFrame* frame;
AVPacket* packet; AVPacket* packet;
SwsContext* swsContext; SwsContext* swsContext;
int videoStreamIndex; int videoStreamIndex;
RingBuffer* ringBuffer; RingBuffer* ringBuffer;
//QLabel* singleFrameLabel; // 用于解码单帧的标签 //QLabel* singleFrameLabel; // 用于解码单帧的标签

View File

@ -0,0 +1,26 @@
#include <QDialog>
#include <QVBoxLayout>
#include <QLabel>
#include <QPushButton>
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); // 设置对话框的大小
}
};

View File

@ -9,7 +9,7 @@ ClientHandler::ClientHandler(QTcpSocket* socket,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson, QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig,
QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson, 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), : QObject(parent), socket(socket),
frontBoardOneClickTest(frontBoardOneClickTest), frontBoardTest(frontBoardTest), frontBoardOneClickTest(frontBoardOneClickTest), frontBoardTest(frontBoardTest),
frontBoardFuncConfig(frontBoardFuncConfig), frontBoardDevInfoJson(frontBoardDevInfoJson), frontBoardFuncConfig(frontBoardFuncConfig), frontBoardDevInfoJson(frontBoardDevInfoJson),
@ -17,7 +17,7 @@ ClientHandler::ClientHandler(QTcpSocket* socket,
backBoardOneClickTest(backBoardOneClickTest), backBoardTest(backBoardTest), backBoardOneClickTest(backBoardOneClickTest), backBoardTest(backBoardTest),
backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson), backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson),
backBoardUuidJson(backBoardUuidJson), getPicJson(getPicJson), getVideoJson(getVideoJson), backBoardUuidJson(backBoardUuidJson), getPicJson(getPicJson), getVideoJson(getVideoJson),
currentItemIndex(0), clientId(clientId), currentItemIndex(0), clientId(clientId), isBackBoardOrAllBoard(isBackBoardOrAllBoard),
isManualSend(false), isSingleSend(false), isClickedSend(false), size(0), isManualSend(false), isSingleSend(false), isClickedSend(false), size(0),
isFirstDataReceived(true), processDataFunction(nullptr), isFirstDataReceived(true), processDataFunction(nullptr),
isDataStuck(false), dataProcessingActive(false), isRecvVideoData(true), isDataStuck(false), dataProcessingActive(false), isRecvVideoData(true),
@ -35,6 +35,37 @@ ClientHandler::~ClientHandler() {
qDebug() << "ClientHandler destroyed for clientId:" << clientId; 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) void ClientHandler::startReadVideoDataTimer(int client_Id)
{ {
//emit startReadTimer(clientId); //emit startReadTimer(clientId);
@ -94,31 +125,9 @@ QString ClientHandler::getClientAddress() const
return socket->peerAddress().toString() + ":" + QString::number(socket->peerPort()); 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) 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) 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); setThreadPriority(QThread::LowPriority);
socket->setReadBufferSize(20 * 1024); socket->setReadBufferSize(20 * 1024);
controlClientId = clientId; controlClientId = clientId;
// 前板有设备连接自动发送获取设备信息
//sendDevInfoItem();
break; break;
default: default:
qWarning() << "Unhandled client type:" << clientType; 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() void ClientHandler::onTimeout()
{ {

View File

@ -33,7 +33,7 @@ public:
QJsonArray frontBoardFuncConfig, QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson, QJsonArray frontBoardFuncConfig, QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardDevInfoJson, QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardDevInfoJson,
QJsonArray backBoardUuidJson, QJsonArray getPicJson, QJsonArray getVideoJson, QJsonArray backBoardUuidJson, QJsonArray getPicJson, QJsonArray getVideoJson,
int clientId, QObject* parent = nullptr); int clientId, int isBackBoardOrAllBoard, QObject* parent = nullptr);
~ClientHandler(); ~ClientHandler();
int preVideoClientId = 0; int preVideoClientId = 0;
@ -92,7 +92,7 @@ signals:
const QJsonArray& jsonArray, int itemJsonIndex); const QJsonArray& jsonArray, int itemJsonIndex);
void handleData(QByteArray& data); 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, void statusUpdated(const QString& client, int itemIndex, int funcItemIndex,
bool success, const QString& itemData, const QString& funcItemData, bool success, const QString& itemData, const QString& funcItemData,
@ -144,6 +144,7 @@ private:
int currentItemIndex; // 当前处理的测试 JSON 项目索引 int currentItemIndex; // 当前处理的测试 JSON 项目索引
int currentFuncItemIndex; // 当前处理的功能 JSON 项目索引 int currentFuncItemIndex; // 当前处理的功能 JSON 项目索引
int clientId; // 新增的客户端编号 int clientId; // 新增的客户端编号
int isBackBoardOrAllBoard;
int itemsProcessedCount; // 跟踪处理项目的数量 int itemsProcessedCount; // 跟踪处理项目的数量

View File

@ -27,6 +27,8 @@
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#define BUILD_SHARED_LIBS
#define QMDNSENGINE_LIBRARY
#if defined(BUILD_SHARED_LIBS) #if defined(BUILD_SHARED_LIBS)
# if defined(QMDNSENGINE_LIBRARY) # if defined(QMDNSENGINE_LIBRARY)
# define QMDNSENGINE_EXPORT Q_DECL_EXPORT # define QMDNSENGINE_EXPORT Q_DECL_EXPORT

View File

@ -339,7 +339,10 @@ void toPacket(const Message &message, QByteArray &packet)
{ {
quint16 offset = 0; quint16 offset = 0;
quint16 flags = (message.isResponse() ? 0x8400 : 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<quint16>(packet, offset, message.transactionId()); writeInteger<quint16>(packet, offset, message.transactionId());
writeInteger<quint16>(packet, offset, flags); writeInteger<quint16>(packet, offset, flags);
writeInteger<quint16>(packet, offset, message.queries().length()); writeInteger<quint16>(packet, offset, message.queries().length());

View File

@ -71,7 +71,6 @@ void ProberPrivate::assertRecord()
message.addQuery(query); message.addQuery(query);
message.addRecord(proposedRecord); message.addRecord(proposedRecord);
server->sendMessageToAll(message); server->sendMessageToAll(message);
// Wait two seconds to confirm it is unique // Wait two seconds to confirm it is unique
timer.stop(); timer.stop();
timer.start(2 * 1000); timer.start(2 * 1000);
@ -80,14 +79,15 @@ void ProberPrivate::assertRecord()
void ProberPrivate::onMessageReceived(const Message &message) void ProberPrivate::onMessageReceived(const Message &message)
{ {
// If the response matches the proposed record, increment the suffix and // If the response matches the proposed record, increment the suffix and
// try with the new name // try with the new name
//if (confirmed || !message.isResponse()) {
if (confirmed || !message.isResponse()) { if (confirmed) {
return; return;
} }
const auto records = message.records(); const auto records = message.records();
for (const Record &record : records) { for (const Record &record : records) {
if (record.name() == proposedRecord.name() && record.type() == proposedRecord.type()) { if (record.name() == proposedRecord.name() && record.type() == proposedRecord.type()) {
qDebug() << "Conflict detected for name:" << proposedRecord.name() << "with type:" << record.type();
++suffix; ++suffix;
assertRecord(); assertRecord();
} }

View File

@ -79,8 +79,8 @@ void ProviderPrivate::confirm()
delete prober; delete prober;
} }
prober = new Prober(server, srvProposed, this); 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 // If existing records were confirmed, indicate that they are no
// longer valid // longer valid
if (confirmed) { if (confirmed) {
@ -128,7 +128,7 @@ void ProviderPrivate::onMessageReceived(const Message &message)
if (!confirmed || message.isResponse()) { if (!confirmed || message.isResponse()) {
return; return;
} }
//qDebug() << "Failed to start server. Error:" << server->errorString();
bool sendBrowsePtr = false; bool sendBrowsePtr = false;
bool sendPtr = false; bool sendPtr = false;
bool sendSrv = false; bool sendSrv = false;
@ -227,13 +227,16 @@ void Provider::update(const Service &service)
return; return;
} }
bool registered = d->hostname->isRegistered(); bool registered = d->hostname->isRegistered();
//qDebug() << "Hostname registered:" << registered;
if(registered) { if(registered) {
// 不确认服务名称,直接进行广播
d->publish();
//if (d->hostname->isRegistered()) { //if (d->hostname->isRegistered()) {
if (!d->confirmed || fqName != d->srvRecord.name()) { /*if (!d->confirmed || fqName != d->srvRecord.name()) {
qDebug() << "confirm()";
d->confirm(); d->confirm();
} else { } else {
qDebug() << "publish()";
d->publish(); d->publish();
} }*/
} }
} }

View File

@ -129,8 +129,6 @@ void Server::sendMessageToAll(const Message &message)
{ {
QByteArray packet; QByteArray packet;
toPacket(message, packet); toPacket(message, packet);
//qDebug() << "MdnsMsg :" << packet.toHex();
qDebug() << "MdnsPort:" << MdnsPort;
qint64 sentBytes = d->ipv4Socket.writeDatagram(packet, MdnsIpv4Address, MdnsPort); qint64 sentBytes = d->ipv4Socket.writeDatagram(packet, MdnsIpv4Address, MdnsPort);
qDebug() << "ipv4Socket sentBytes:" << sentBytes; qDebug() << "ipv4Socket sentBytes:" << sentBytes;
sentBytes = d->ipv6Socket.writeDatagram(packet, MdnsIpv6Address, MdnsPort); sentBytes = d->ipv6Socket.writeDatagram(packet, MdnsIpv6Address, MdnsPort);

View File

@ -1,4 +1,4 @@
// #include "servicemodel.cpp" // servicemodel.cpp
#include "servicemodel.h" #include "servicemodel.h"
Q_DECLARE_METATYPE(QMdnsEngine::Service) Q_DECLARE_METATYPE(QMdnsEngine::Service)

View File

@ -1,3 +1,4 @@
// servicemodel.h
#ifndef SERVICEMODEL_H #ifndef SERVICEMODEL_H
#define SERVICEMODEL_H #define SERVICEMODEL_H
@ -7,7 +8,8 @@
#include "qmdnsengine/include/hostname.h" #include "qmdnsengine/include/hostname.h"
#include "qmdnsengine/include/provider.h" #include "qmdnsengine/include/provider.h"
#include "qmdnsengine/include/service.h" #include "qmdnsengine/include/service.h"
#include "qmdnsengine/include/message.h"
#include "qmdnsengine/include/query.h"
class ServiceProvider : public QObject class ServiceProvider : public QObject
{ {

View File

@ -27,11 +27,14 @@ DataHandler::DataHandler(QLabel* leftLens_imageLabel, QLabel* rightLens_imageLab
ffmpegDecoder->initialize(); // 初始化解码器 ffmpegDecoder->initialize(); // 初始化解码器
clearAllRecvData(); clearAllRecvData();
initializeMsgIdToCmdMap(); initializeMsgIdToCmdMap();
qDebug() << "DataHandler created";
} }
DataHandler::~DataHandler() DataHandler::~DataHandler()
{ {
qDebug() << "---1--- DataHandler destroyed";
if (ffmpegDecoder) { if (ffmpegDecoder) {
ffmpegDecoder->stopFFmpegDecoder();
ffmpegDecoder->requestInterruption(); ffmpegDecoder->requestInterruption();
ffmpegDecoder->wait(); // 等待解码器线程完成 ffmpegDecoder->wait(); // 等待解码器线程完成
delete ffmpegDecoder; delete ffmpegDecoder;
@ -39,6 +42,14 @@ DataHandler::~DataHandler()
} }
delete buffer; delete buffer;
buffer = nullptr; buffer = nullptr;
qDebug() << "---2--- DataHandler destroyed";
}
void DataHandler::handleOpenFocusWindow(int itemIndex)
{
if (ffmpegDecoder) {
ffmpegDecoder->processVideo(itemIndex); // 调用 FFmpegDecoder 的处理函数
}
} }
QByteArray DataHandler::hexStringToByteArray(const QString& hexString) QByteArray DataHandler::hexStringToByteArray(const QString& hexString)
@ -50,16 +61,17 @@ QByteArray DataHandler::hexStringToByteArray(const QString& hexString)
return byteArray; return byteArray;
} }
const QString filePath_1 = "add1.h264"; const QString filePath_1 = "/add1.h264";
// 显示视频的函数 // 显示视频的函数
void DataHandler::showVideo(const QString& client, const QByteArray& valData) 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 (!file.isOpen()) {
if (QFile::exists(filePath_1)) { if (QFile::exists(h264filePath)) {
QFile::remove(filePath_1); QFile::remove(h264filePath);
} }
if (!file.open(QIODevice::Append | QIODevice::WriteOnly)) { if (!file.open(QIODevice::Append | QIODevice::WriteOnly)) {
qWarning() << "无法打开H264文件:" << file.errorString(); qWarning() << "无法打开H264文件:" << file.errorString();
@ -74,7 +86,7 @@ void DataHandler::showVideo(const QString& client, const QByteArray& valData)
if (!start_run) { if (!start_run) {
start_run = 1; start_run = 1;
ffmpegDecoder->decodeFile(filePath_1, videoLabel); ffmpegDecoder->decodeFile(h264filePath, videoLabel);
} }
//ffmpegDecoder->decodeFile(filePath_1, videoLabel); //ffmpegDecoder->decodeFile(filePath_1, videoLabel);
} }

View File

@ -46,7 +46,7 @@ public slots:
void handleData(const QString& client, const QByteArray& data, int msg_id, int currentRecvItemIndex, void handleData(const QString& client, const QByteArray& data, int msg_id, int currentRecvItemIndex,
int currentRecvFuncItemIndex, const QString& itemData, const QString& funcItemData, int currentRecvFuncItemIndex, const QString& itemData, const QString& funcItemData,
const QJsonArray& jsonArray, int itemJsonIndex); const QJsonArray& jsonArray, int itemJsonIndex);
void handleOpenFocusWindow(int itemIndex);
signals: signals:
void statusUpdated(const QString& clientAddress, int currentItemIndex, int currentFuncItemIndex, void statusUpdated(const QString& clientAddress, int currentItemIndex, int currentFuncItemIndex,
bool success, const QString& currentItemLabel, const QString& currentFuncItemLabel, bool success, const QString& currentItemLabel, const QString& currentFuncItemLabel,

View File

@ -8,10 +8,11 @@ class NewButtonDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
NewButtonDialog(QWidget* parent = nullptr) : QDialog(parent) NewButtonDialog(QWidget* parent = nullptr, const QSize& labelSize = QSize(480, 640)) : QDialog(parent)
{ {
QVBoxLayout* layout = new QVBoxLayout(this); QVBoxLayout* layout = new QVBoxLayout(this);
QLabel* label = new QLabel("This is a new window opened by clicking the new button.", this); QLabel* label = new QLabel("This is a new window opened by clicking the new button.", this);
label->setFixedSize(labelSize); // 设置QLabel的固定大小
layout->addWidget(label); layout->addWidget(label);
QPushButton* closeButton = new QPushButton("Close", this); QPushButton* closeButton = new QPushButton("Close", this);
@ -20,6 +21,6 @@ public:
setLayout(layout); setLayout(layout);
setWindowTitle("SL100 视频播放窗口"); setWindowTitle("SL100 视频播放窗口");
resize(480, 640); // 设置对话框的大小 //resize(500, 700); // 设置对话框的大小
} }
}; };

View File

@ -1,7 +1,6 @@
// MainWidget.cpp // MainWidget.cpp
#include "MainWidget.h" #include "MainWidget.h"
void onThreadFinished(QThread* thread, ClientHandler* handler) void onThreadFinished(QThread* thread, ClientHandler* handler)
{ {
qDebug() << "Thread finished. Deleting handler and thread."; qDebug() << "Thread finished. Deleting handler and thread.";
@ -27,36 +26,79 @@ MainWidget::MainWidget(QWidget* parent) :
multicastTimer(new QTimer(this)) multicastTimer(new QTimer(this))
#endif #endif
{ {
leftLens_imageLabel = new QLabel(this); leftLens_imageLabel = new QLabel(this);
rightLens_imageLabel = new QLabel(this); rightLens_imageLabel = new QLabel(this);
videoLabel = new QLabel(this); videoLabel = new QLabel(this);
frontFuncConfigLineEdit = new QLineEdit(this); frontFuncConfigLineEdit = new QLineEdit(this);
backFuncConfigLineEdit = new QLineEdit(this); backFuncConfigLineEdit = new QLineEdit(this);
licenseHwInfoEdit = new QTextEdit(this); licenseHwInfoEdit = new QTextEdit(this);
UuidHwInfoEdit = 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(); setupUI();
// 打印线程池状态信息 // 打印线程池状态信息
setupTimerForThreadPoolInfo(); setupTimerForThreadPoolInfo();
server = new QTcpServer(this); 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(); connect(this, &MainWidget::openFocusWindowRequested, dataHandler, &DataHandler::handleOpenFocusWindow);
//FactoryToolSendGetLicenseToHttpServer(); connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated);
//FactoryToolSendPostComfirmToHttpServer(); */
//FactoryToolSendPostTestToHttpServer();
//FactoryToolSendPostLicenseToHttpServer();
connect(server, &QTcpServer::newConnection, this, [this]() { connect(server, &QTcpServer::newConnection, this, [this]() {
// 检查是否有挂起的连接 // 检查是否有挂起的连接
while (server->hasPendingConnections()) { while (server->hasPendingConnections()) {
QTcpSocket* socket = server->nextPendingConnection(); 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() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
qDebug() << "> A client is connected. ID:" << clientId; qDebug() << "> A client is connected. ID:" << clientId;
qDebug() << "> Client IP:" << ipString << " Port:" << clientPort;
qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; 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(); stopMdnsService();
connectedClientsCount++; connectedClientsCount ++;
updateServerButtonText(); updateServerButtonText();
QTimer* timer = new QTimer(this); 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, ClientHandler* handler = new ClientHandler(socket, frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
frontBoardDevInfoJson, frontBoardLicenseJson, frontBoardDevInfoJson, frontBoardLicenseJson,
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson, backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
backBoardUuidJson, getPicJson, getVideoJson, clientId, nullptr); backBoardUuidJson, getPicJson, getVideoJson, clientId, isBackBoardOrAllBoard, nullptr);
// 将 ClientHandler 移动到线程池中的线程 // 将 ClientHandler 移动到线程池中的线程
handler->moveToThread(thread); handler->moveToThread(thread);
@ -91,7 +133,7 @@ MainWidget::MainWidget(QWidget* parent) :
}); });
// 将sendData信号连接到主线程中的槽上 // 将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->write(data);
socket->flush();*/ socket->flush();*/
//qDebug() << "---------------------data.size():" << data.size(); //qDebug() << "---------------------data.size():" << data.size();
@ -99,7 +141,12 @@ MainWidget::MainWidget(QWidget* parent) :
QDataStream stream(&prefix, QIODevice::WriteOnly); QDataStream stream(&prefix, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian); stream.setByteOrder(QDataStream::LittleEndian);
stream << quint32(0x55AA55AA); stream << quint32(0x55AA55AA);
stream << quint16(0x0420); if (isBoardType != 0) {
stream << quint16(0x0421);
}
else {
stream << quint16(0x0420);
}
stream << quint32(data.size()); stream << quint32(data.size());
prefix.append(data); prefix.append(data);
@ -124,15 +171,20 @@ MainWidget::MainWidget(QWidget* parent) :
connect(handler, &ClientHandler::allItemsProcessed, this, &MainWidget::onAllItemsProcessed); connect(handler, &ClientHandler::allItemsProcessed, this, &MainWidget::onAllItemsProcessed);
connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient); connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient);
#if 1
// 创建 DataHandler 对象并连接信号 // 创建 DataHandler 对象并连接信号
DataHandler* dataHandler = new DataHandler(leftLens_imageLabel, rightLens_imageLabel, videoLabel, licenseHwInfoEdit, &devInfoLineEdits, DataHandler* dataHandler = new DataHandler(leftLens_imageLabel, rightLens_imageLabel, videoLabel, licenseHwInfoEdit, &devInfoLineEdits,
frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig, frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
frontBoardDevInfoJson, frontBoardLicenseJson, frontBoardDevInfoJson, frontBoardLicenseJson,
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson, backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
backBoardUuidJson, getPicJson, getVideoJson, this); backBoardUuidJson, getPicJson, getVideoJson, this);
connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData); dataHandlers[clientId] = dataHandler;
connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated); 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::startReadTimer, this, &MainWidget::startClientReadTimer);
connect(handler, &ClientHandler::stopReadTimer, this, &MainWidget::stopClientReadTimer); connect(handler, &ClientHandler::stopReadTimer, this, &MainWidget::stopClientReadTimer);
@ -157,7 +209,6 @@ MainWidget::MainWidget(QWidget* parent) :
connectionStatusCheckTimer = new QTimer(this); connectionStatusCheckTimer = new QTimer(this);
connect(connectionStatusCheckTimer, &QTimer::timeout, this, &MainWidget::onCheckConnectionStatus); connect(connectionStatusCheckTimer, &QTimer::timeout, this, &MainWidget::onCheckConnectionStatus);
//connectionStatusCheckTimer->start(100); // 每100ms检查一次连接状态 //connectionStatusCheckTimer->start(100); // 每100ms检查一次连接状态
connect(mdnsTimer, &QTimer::timeout, this, &MainWidget::startMdnsService); connect(mdnsTimer, &QTimer::timeout, this, &MainWidget::startMdnsService);
#if TEST_UDP_BROADCAST #if TEST_UDP_BROADCAST
@ -199,6 +250,12 @@ MainWidget::~MainWidget()
delete timer; delete timer;
} }
clientReadTimers.clear(); clientReadTimers.clear();
for (auto dataHandler : dataHandlers) {
dataHandler->deleteLater();
}
dataHandlers.clear();
for (ClientHandler* handler : clients) { for (ClientHandler* handler : clients) {
handler->deleteLater(); handler->deleteLater();
} }
@ -228,6 +285,206 @@ MainWidget::~MainWidget()
qDebug() << "MainWidget destroyed"; 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) void MainWidget::onHttpRequestFinished(const QJsonObject& response)
{ {
@ -546,131 +803,6 @@ void MainWidget::readJsonConfig()
getVideoJson = readJson_getVideo(); 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() void MainWidget::onSelectFileButtonClicked()
{ {
QString filePath = QFileDialog::getSaveFileName(this, tr("选择文件路径"), "", tr("Text Files (*.txt);;All Files (*)")); QString filePath = QFileDialog::getSaveFileName(this, tr("选择文件路径"), "", tr("Text Files (*.txt);;All Files (*)"));
@ -754,75 +886,14 @@ void MainWidget::onDisconnectClient(int clientId)
clientTimers.remove(clientId); clientTimers.remove(clientId);
} }
handler->deleteLater(); handler->deleteLater();
connectedClientsCount--; connectedClientsCount --;
updateServerButtonText(); updateServerButtonText();
break; break;
} }
} }
if (connectedClientsCount == 0) {
// 启动 mDNS 服务广播 // 启动 mDNS 服务广播
startMdnsService(); 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));
} }
} }
@ -1026,7 +1097,7 @@ void MainWidget::startMdnsService()
QString formattedTime = currentTime.toString("yyyy-MM-dd hh:mm:ss.zzz"); QString formattedTime = currentTime.toString("yyyy-MM-dd hh:mm:ss.zzz");
qDebug() << "[" << formattedTime << "]:" << "Start Mdns Broadcast Service"; qDebug() << "[" << formattedTime << "]:" << "Start Mdns Broadcast Service";
QString serviceName = "SL100 FactoryTool 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; quint16 port = TCP_CONNECT_PORT;
mServiceProvider->startServiceBroadcast(serviceName, serviceType, port); mServiceProvider->startServiceBroadcast(serviceName, serviceType, port);
@ -1086,13 +1157,15 @@ void MainWidget::onStartServerClicked()
startServerButton->setText(tr("开始监听\n(Start Listening...)")); startServerButton->setText(tr("开始监听\n(Start Listening...)"));
startServerButton->setStyleSheet(""); startServerButton->setStyleSheet("");
sendAllButton->setEnabled(false); sendAllButton->setEnabled(false);
stopMdnsService(); stopMdnsService();
} }
} }
void MainWidget::sendDataToClient(int clientId, const QByteArray& data) void MainWidget::sendDataToClient(int clientId, const QByteArray& data)
{ {
if ((clientId == 0) && (isBackBoardOrAllBoard)) {
clientId = isBackBoardOrAllBoard;
}
if (clients_1.contains(clientId)) { if (clients_1.contains(clientId)) {
ClientHandler* handler = clients_1[clientId]; ClientHandler* handler = clients_1[clientId];
handler->sendDataToClient(data); // 调用 ClientHandler 中的方法发送数据 handler->sendDataToClient(data); // 调用 ClientHandler 中的方法发送数据
@ -1232,9 +1305,7 @@ void MainWidget::onOpenFocusWindowClicked()
int itemIndex = button->property("getVideoIndex").toInt(); int itemIndex = button->property("getVideoIndex").toInt();
//qDebug() << "New Button clicked with itemIndex:" << itemIndex; //qDebug() << "New Button clicked with itemIndex:" << itemIndex;
if (itemIndex == 2) { if (itemIndex == 2) {
// 创建并显示新窗口 emit openFocusWindowRequested(itemIndex); // 发送信号
NewButtonDialog dialog(this);
dialog.exec();
} }
} }
} }
@ -1301,7 +1372,7 @@ void MainWidget::onSendBackFuncItemClicked()
QPushButton* button = qobject_cast<QPushButton*>(sender()); QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("backBoardFuncConfig").toInt(); int itemIndex = button->property("backBoardFuncConfig").toInt();
for (ClientHandler* handler : clients) { for (ClientHandler* handler : clients) {
if (handler->getClientId() == handler->controlClientId) { if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) {
QString text = backFuncConfigLineEdit->text(); QString text = backFuncConfigLineEdit->text();
qDebug() << "Text in backFuncConfigLineEdit:" << text; qDebug() << "Text in backFuncConfigLineEdit:" << text;
handler->sendBackFuncItem(itemIndex, text); handler->sendBackFuncItem(itemIndex, text);
@ -1342,7 +1413,7 @@ void MainWidget::onSendBackItemClicked()
QPushButton* button = qobject_cast<QPushButton*>(sender()); QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("backBoardTest").toInt(); int itemIndex = button->property("backBoardTest").toInt();
for (ClientHandler* handler : clients) { for (ClientHandler* handler : clients) {
if (handler->getClientId() == handler->controlClientId) { if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) {
handler->sendBackItem(itemIndex); handler->sendBackItem(itemIndex);
break; break;
} }

View File

@ -54,8 +54,16 @@
#include "FocusWindow.h" #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 TEST_UDP_BROADCAST 0 // 用于测试 UDP 组播实现 mdns 功能 非标准 mdns
#define MANUAL_UPLOAD_LICENSE 0 // 打开手动上传 License的功能 #define MANUAL_UPLOAD_LICENSE 0 // 打开手动上传 License的功能
#define START_MDNS 1
#define TCP_CONNECT_PORT 12412 // TCP监听的端口 #define TCP_CONNECT_PORT 12412 // TCP监听的端口
@ -68,6 +76,9 @@ public:
explicit MainWidget(QWidget* parent = nullptr); explicit MainWidget(QWidget* parent = nullptr);
~MainWidget(); ~MainWidget();
signals:
void openFocusWindowRequested(int itemIndex);
private slots: private slots:
// 发送HTTP请求 // 发送HTTP请求
//void onSomeButtonClicked(); //void onSomeButtonClicked();
@ -178,6 +189,7 @@ private:
int nextClientId; // 新增的客户端编号 int nextClientId; // 新增的客户端编号
int connectedClientsCount = 0; // 连接客户端的数量 int connectedClientsCount = 0; // 连接客户端的数量
int isRequestSuccessful = 0; // GET请求是否成功 int isRequestSuccessful = 0; // GET请求是否成功
int isBackBoardOrAllBoard = 0;
bool manualSend; // 判断是否是手动触发的发送 bool manualSend; // 判断是否是手动触发的发送
bool deviceConnected = false; // 判断是否有设备连接过 bool deviceConnected = false; // 判断是否有设备连接过
bool isSendingAll; // 一键功能测试 状态 bool isSendingAll; // 一键功能测试 状态
@ -217,6 +229,7 @@ private:
QTimer* threadStatusTimer; // 检查线程状态的定时器 QTimer* threadStatusTimer; // 检查线程状态的定时器
QTimer* connectionStatusCheckTimer; // 检查连接状态的定时器 QTimer* connectionStatusCheckTimer; // 检查连接状态的定时器
QMap<int, DataHandler*> dataHandlers;
QMap<int, QThread*> clientThreads; QMap<int, QThread*> clientThreads;
QMap<int, QTimer*> clientReadTimers; QMap<int, QTimer*> clientReadTimers;
QMap<int, ClientHandler*> clients_1; QMap<int, ClientHandler*> clients_1;

View File

@ -23,7 +23,7 @@ int main(int argc, char* argv[]) {
//closeConsole(); // 调用函数关闭控制台窗口 //closeConsole(); // 调用函数关闭控制台窗口
//FreeConsole(); // 关闭控制台窗口 //FreeConsole(); // 关闭控制台窗口
QApplication app(argc, argv); QApplication app(argc, argv);
qDebug() << "Current working directory:" << QDir::currentPath();
QIcon appIcon("./app_icon.ico"); QIcon appIcon("./app_icon.ico");
app.setWindowIcon(appIcon); app.setWindowIcon(appIcon);

View File

@ -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 !!!

Binary file not shown.