1.更新MDNS广播的服务类型命名规范,防止出现多设备打开找不到MDNS的广播的问题 2.更新区分前后板的TAG
This commit is contained in:
parent
e0c1e37191
commit
09c5843358
|
@ -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" />
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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; // 用于解码单帧的标签
|
||||||
|
|
|
@ -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); // 设置对话框的大小
|
||||||
|
}
|
||||||
|
};
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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; // 跟踪处理项目的数量
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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); // 设置对话框的大小
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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.
Loading…
Reference in New Issue