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