Compare commits

...

15 Commits
V1.4 ... main

Author SHA1 Message Date
Mr.V 9b42aec1ad 1、新增数据转发功能,可配合Linux版RFID识别程序使用。
2、优化部分逻辑。
2024-07-27 16:01:00 +08:00
Mr.V 7080483fb8 1、新增数据转发功能,可配合Linux版RFID识别程序使用。
2、优化部分逻辑。
2024-07-27 15:48:42 +08:00
Mr.V c3cd21f50a 新增识别少于指定车厢数的异常报警 2024-05-21 17:09:07 +08:00
Mr.V 36459f12af 新增识别少于指定车厢数的异常报警 2024-05-21 17:08:53 +08:00
Mr.V 37228b3841 添加编译好的程序包 2024-05-20 14:55:11 +08:00
Mr.V b715fabdca 添加编译好的程序包 2024-05-20 14:54:17 +08:00
Mr.V 5c73baced8 信号发送代码补全 2024-05-20 14:43:51 +08:00
Mr.V b8880f4da7 重连串口问题优化 2024-04-30 14:51:41 +08:00
Mr.V 6be58c3892 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	src/ConfigUtil/ConfigUtil.h
#	src/common/common.h
2024-04-24 16:20:45 +08:00
zhangwei 9c365e2658 更新 src/qt_source/mainwindow.cpp
修改过滤条件解决部分特殊字符导致标签信息过滤
2024-04-24 16:19:41 +08:00
zhangwei 35f1e6dd81 revert 920f3fa341
revert 更新自动重连串口功能,若人为点击“打开串口”,则只要串口连接失败,就会在10秒后重新尝试连接;直到连接成功或人为点击“关闭串口”
2024-04-24 16:19:35 +08:00
Mr.V 64c2559b0f 更新自动重连串口功能,若人为点击“打开串口”,则只要串口连接失败,就会在10秒后重新尝试连接;直到连接成功或人为点击“关闭串口” 2024-04-24 16:14:33 +08:00
zhangwei 27d0b77cba 更新 src/qt_source/mainwindow.cpp
修改过滤条件解决部分特殊字符导致标签信息过滤
2024-04-18 07:09:07 +00:00
zhangwei 23c75b57de revert 920f3fa341
revert 更新自动重连串口功能,若人为点击“打开串口”,则只要串口连接失败,就会在10秒后重新尝试连接;直到连接成功或人为点击“关闭串口”
2024-04-18 07:03:30 +00:00
Mr.V 920f3fa341 更新自动重连串口功能,若人为点击“打开串口”,则只要串口连接失败,就会在10秒后重新尝试连接;直到连接成功或人为点击“关闭串口” 2024-04-15 16:28:56 +08:00
55 changed files with 2515 additions and 1180 deletions

2
.gitignore vendored
View File

@ -15,7 +15,7 @@
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
#*.dll
# Fortran module files
*.mod

View File

@ -23,30 +23,31 @@ RFID硬件车号识别程序支持识别结果上传web
### 配置文件
```python
[base]
# 串口名
com_name=COM2
# 波特率
baud=19200
# 股道名
track_name=2
# 是否有磁钢
have_magnet_steel=true
# 需要识别的磁钢顺序
magnet_steel_order=8421
# 是否上传识别结果上传接口见interface配置
up_result=true
# 是否使用socket接口获取来车状态
use_socket_server=false
run_model=0
[serial]
com_name=COM2
baud=19200
have_magnet_steel=true
magnet_steel_order=8421
[interface]
# 接口IP
http_ip=192.168.2.108
http_ip=192.168.2.212
# 接口端口
http_port=20004
# 获取token的接口地址
token_path=/api/token_path
# 上传识别结果的接口地址
up_result_path=/api/train-carriage/identification/rfid-save
# 上传报警信息的接口地址
up_warning_path=/api/blade-train/deviceInfo/save
# 接口用户名
username=guest_01
# 接口密码
@ -54,7 +55,18 @@ password=d55b0f642e817eea24725d2f2a31dd08
[socket_server]
# socket 服务端IP
server_ip=172.18.160.1
server_ip=127.0.0.1
# socket 端口
server_port=7000
# 等待信号而延迟上传的车节数
delayed_upload=4
[device_warn]
# 最少识别车节数(低于此值会报警)
min_train_size=10
[relay]
# 转发服务监听端口
listener_port=7070
```

BIN
app/D3Dcompiler_47.dll Normal file

Binary file not shown.

BIN
app/Qt5Core.dll Normal file

Binary file not shown.

BIN
app/Qt5Gui.dll Normal file

Binary file not shown.

BIN
app/Qt5Network.dll Normal file

Binary file not shown.

BIN
app/Qt5SerialPort.dll Normal file

Binary file not shown.

BIN
app/Qt5Svg.dll Normal file

Binary file not shown.

BIN
app/Qt5Widgets.dll Normal file

Binary file not shown.

BIN
app/Train_RFID.exe Normal file

Binary file not shown.

Binary file not shown.

View File

@ -1,20 +1,31 @@
[base]
com_name=COM2
baud=19200
track_name=2
have_magnet_steel=true
magnet_steel_order=8421
up_result=true
use_socket_server=false
run_model=0
[serial]
com_name=COM2
baud=19200
have_magnet_steel=true
magnet_steel_order=8421
[interface]
http_ip=192.168.2.212
http_port=20004
token_path=/api/token_path
up_result_path=/api/train-carriage/identification/rfid-save
up_warning_path=/api/blade-train/deviceInfo/save
username=guest_01
password=d55b0f642e817eea24725d2f2a31dd08
[socket_server]
server_ip=192.168.2.212
server_ip=127.0.0.1
server_port=7000
delayed_upload=4
[device_warn]
min_train_size=10
[relay]
listener_port=7070

Binary file not shown.

BIN
app/imageformats/qgif.dll Normal file

Binary file not shown.

BIN
app/imageformats/qicns.dll Normal file

Binary file not shown.

BIN
app/imageformats/qico.dll Normal file

Binary file not shown.

BIN
app/imageformats/qjpeg.dll Normal file

Binary file not shown.

BIN
app/imageformats/qsvg.dll Normal file

Binary file not shown.

BIN
app/imageformats/qtga.dll Normal file

Binary file not shown.

BIN
app/imageformats/qtiff.dll Normal file

Binary file not shown.

BIN
app/imageformats/qwbmp.dll Normal file

Binary file not shown.

BIN
app/imageformats/qwebp.dll Normal file

Binary file not shown.

BIN
app/libEGL.dll Normal file

Binary file not shown.

BIN
app/libGLESv2.dll Normal file

Binary file not shown.

BIN
app/libgcc_s_seh-1.dll Normal file

Binary file not shown.

BIN
app/libstdc++-6.dll Normal file

Binary file not shown.

BIN
app/libwinpthread-1.dll Normal file

Binary file not shown.

BIN
app/opengl32sw.dll Normal file

Binary file not shown.

BIN
app/platforms/qwindows.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/libcurl.dll Normal file

Binary file not shown.

BIN
lib/libyaml-cpp.dll Normal file

Binary file not shown.

BIN
lib/libyaml-cpp.dll.a Normal file

Binary file not shown.

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.25)
cmake_minimum_required(VERSION 3.26)
set(PROJECT_NAME Train_RFID)
project(${PROJECT_NAME} VERSION 1.0 DESCRIPTION "火车车号识别 RFID版")
project(${PROJECT_NAME} VERSION 1.0 DESCRIPTION "RFID火车车号识别 Win版")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_AUTOMOC ON)
@ -18,7 +18,6 @@ link_directories(../lib)
link_libraries(ws2_32 wsock32)
find_package(Qt5 COMPONENTS
Core
Gui
@ -28,17 +27,15 @@ find_package(Qt5 COMPONENTS
Concurrent
REQUIRED)
#QtNetworkproQT+=network
#find_package(QT NAMES Qt5 REQUIRED COMPONENTS Core Network SerialPort )
#find_package(Qt${QT_VERSION_MAJOR} REQUIRED Network COMPONENTS Core)
#find_package(Qt5Core COMPONENTS Qt5SerialPort REQUIRED)
#mocQ_OBJECT
QT5_WRAP_CPP(MOC_Files
qt_source/mainwindow.h
qt_source/MainWindow.h
interface/TcpClient.h
threads/UpResultThread.h
)
threads/UpWarnThread.h
threads/ReadComThread.h
threads/RelayRfidThread.h
)
include_directories(
common
@ -70,17 +67,17 @@ include_directories(
interface
#
serial
# 线
threads
)
file(GLOB_RECURSE COMMON_SRCS_LISTS
# UI
qt_source/mainwindow.ui
qt_source/MainWindow.ui
# qt_source qt_source
qt_source/MainWindow.cpp
#
common/common.cpp
# qt_source qt_source
qt_source/mainwindow.cpp
# JSON
util/json/jsoncpp.cpp
# http
@ -116,10 +113,8 @@ add_executable(Train_RFID
${MOC_Files}
ico.rc
)
target_link_libraries(Train_RFID
-pthread
-lyaml-cpp
Qt5::Core
Qt5::Gui
@ -127,7 +122,7 @@ target_link_libraries(Train_RFID
Qt5::Network
Qt5::SerialPort
Qt5::Concurrent
)
)
if (WIN32 AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(DEBUG_SUFFIX)
@ -150,7 +145,7 @@ if (WIN32 AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
"${QT_INSTALL_PATH}/plugins/platforms/qwindows${DEBUG_SUFFIX}.dll"
"$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugins/platforms/")
endif ()
foreach (QT_LIB Core Gui Widgets Network SerialPort)
foreach (QT_LIB Core Gui Widgets)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${QT_INSTALL_PATH}/bin/Qt5${QT_LIB}${DEBUG_SUFFIX}.dll"

View File

@ -11,6 +11,34 @@ ConfigUtil::ConfigUtil() = default;
ConfigUtil::~ConfigUtil() = default;
bool ConfigUtil::readBaseConfig(const QString &configFile, QString &errorMessage, ai_matrix::BaseConfig &config) {
try {
if (configFile.isEmpty() || configFile.isNull())
{
errorMessage = "配置文件地址为空,读取配置文件失败!";
return false;
}
QSettings* mset = new QSettings(configFile, QSettings::IniFormat);
mset->setIniCodec(QTextCodec::codecForName("UTF-8"));
mset->beginGroup("base");
config.trackName = mset->value("track_name", 1).toInt();
config.upResult = mset->value("up_result", false).toBool();
config.useSocketServer = mset->value("use_socket_server", false).toBool();
config.runModel = mset->value("run_model", 1).toInt();
// TODO: 此节点下的参数内容弃用,转移到[serial]下
// config.comName = mset->value("com_name", "").toString();
// config.baud = mset->value("baud", 19200).toInt();
// config.havaMagnetSteel = mset->value("have_magnet_steel", false).toBool();
// config.magnetSteelOrder = mset->value("magnet_steel_order", "").toString();
mset->endGroup();
} catch (const std::exception &e) {
errorMessage = e.what();
return false;
}
return true;
}
bool ConfigUtil::writeBaseConfig(const QString &configFile, QString &errorMessage, ai_matrix::BaseConfig &config) {
try {
if (configFile.isEmpty() || configFile.isNull()) {
errorMessage = "配置文件地址为空,读取配置文件失败!";
@ -18,15 +46,34 @@ bool ConfigUtil::readBaseConfig(const QString &configFile, QString &errorMessage
}
QSettings* mset = new QSettings(configFile, QSettings::IniFormat);
mset->setIniCodec(QTextCodec::codecForName("UTF-8"));
QString mdir = "";
mset->beginGroup("base");
mset->setValue("track_name", config.trackName);
mset->setValue("up_result", config.upResult);
mset->setValue("use_socket_server", config.useSocketServer);
mset->setValue("run_model", config.runModel);
mset->endGroup();
} catch (const std::exception &e) {
errorMessage = e.what();
return false;
}
return true;
}
bool ConfigUtil::readSerialConfig(const QString &configFile, QString &errorMessage, ai_matrix::SerialConfig &config) {
try {
if (configFile.isEmpty() || configFile.isNull()) {
errorMessage = "配置文件地址为空,读取配置文件失败!";
return false;
}
QSettings* mset = new QSettings(configFile, QSettings::IniFormat);
mset->setIniCodec(QTextCodec::codecForName("UTF-8"));
mset->beginGroup("serial");
config.comName = mset->value("com_name", "").toString();
config.baud = mset->value("baud", 19200).toInt();
config.trackName = mset->value("track_name", 1).toInt();
config.havaMagnetSteel = mset->value("have_magnet_steel", false).toBool();
config.magnetSteelOrder = mset->value("magnet_steel_order", "").toString();
config.upResult = mset->value("up_result", false).toBool();
config.useSocketServer = mset->value("use_socket_server", false).toBool();
mset->endGroup();
} catch (const std::exception &e) {
@ -73,6 +120,7 @@ bool ConfigUtil::readSocketServerConfig(const QString &configFile, QString &erro
mset->beginGroup("socket_server");
config.server_ip = mset->value("server_ip", "").toString();
config.server_port = mset->value("server_port", "").toInt();
config.delayed_upload = mset->value("delayed_upload", "3").toInt();
mset->endGroup();
} catch (const std::exception &e) {
@ -80,4 +128,46 @@ bool ConfigUtil::readSocketServerConfig(const QString &configFile, QString &erro
return false;
}
return true;
}
}
bool ConfigUtil::readDeviceWarnConfig(const QString &configFile, QString &errorMessage,
ai_matrix::DeviceWarnConfig &config) {
try {
if (configFile.isEmpty() || configFile.isNull()) {
errorMessage = "配置文件地址为空,读取配置文件失败!";
return false;
}
QSettings* mset = new QSettings(configFile, QSettings::IniFormat);
mset->setIniCodec(QTextCodec::codecForName("UTF-8"));
mset->beginGroup("device_warn");
config.min_train_size = mset->value("min_train_size", 99).toInt();
mset->endGroup();
} catch (const std::exception &e) {
errorMessage = e.what();
return false;
}
return true;
}
bool ConfigUtil::readRelayConfig(const QString &configFile, QString &errorMessage,
ai_matrix::RelayConfig &config) {
try {
if (configFile.isEmpty() || configFile.isNull()) {
errorMessage = "配置文件地址为空,读取配置文件失败!";
return false;
}
QSettings* mset = new QSettings(configFile, QSettings::IniFormat);
mset->setIniCodec(QTextCodec::codecForName("UTF-8"));
mset->beginGroup("relay");
config.listener_port = mset->value("listener_port", 7010).toInt();
// config.max_connection = mset->value("max_connection", 3).toInt();
mset->endGroup();
} catch (const std::exception &e) {
errorMessage = e.what();
return false;
}
return true;
}

View File

@ -7,46 +7,9 @@
#include <string>
#include <QFileInfo>
#include <QTextCodec>
#include "common.h"
namespace ai_matrix {
struct BaseConfig {
// com口名称
QString comName;
// 波特率
int baud;
// 股道编号
int trackName;
// 是否有磁钢
bool havaMagnetSteel;
// 磁钢顺序
QString magnetSteelOrder;
// 上传识别结果标志
bool upResult;
// 使用socket来车通讯
bool useSocketServer;
};
struct InterfaceConfig {
// 接口服务器IP
QString httpIp;
// 接口服务器端口
int httpPort;
// 获取token的方法
QString tokenPath;
// 上传识别结果的方法
QString upResultPath;
// 用户名
QString username;
// 密码
QString password;
};
struct SServerConfig {
// socket server IP
QString server_ip;
// server_port
int server_port;
};
};
class ConfigUtil {
@ -55,10 +18,12 @@ public:
~ConfigUtil();
static bool readBaseConfig(const QString& configFile, QString &errorMessage, ai_matrix::BaseConfig &config);
static bool readSerialConfig(const QString& configFile, QString &errorMessage, ai_matrix::SerialConfig &config);
static bool readInterfaceConfig(const QString& configFile, QString &errorMessage, ai_matrix::InterfaceConfig &config);
static bool readSocketServerConfig(const QString& configFile, QString &errorMessage, ai_matrix::SServerConfig &config);
static bool readRelayConfig(const QString& configFile, QString &errorMessage, ai_matrix::RelayConfig &config);
static bool readDeviceWarnConfig(const QString& configFile, QString &errorMessage, ai_matrix::DeviceWarnConfig &config);
static bool writeBaseConfig(const QString& configFile, QString &errorMessage, ai_matrix::BaseConfig &config);
};

View File

@ -1,6 +1,4 @@
//
// Created by Mr.V on 2023/8/16.
//
#include "common.h"
QString io_car = "";
QString direction = "";
#include "common.h"

View File

@ -12,14 +12,101 @@
#include <QTextCodec>
#include <QMessageBox>
#include <QFile>
#include <QFileDialog>
#include <QtGui>
#include <QString>
#include <QWidget>
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort>
#include <QDebug>
#include <QWaitCondition>
#include <QObject>
#include <QTcpsocket>
#include <QDateTime>
#include <QInputDialog>
#include <QSystemTrayIcon>
#include <QCloseEvent>
#include <QAction>
#include <QCloseEvent>
#include <QTimer>
#include <QListView>
#include <QMenuBar>
#include <QStatusBar>
#include <QtConcurrent>
#include <QTcpServer>
#include "Log.h"
#include "StringUtil.h"
namespace ai_matrix {
const QString g_config_path = "./config/config.ini";
const int RELAY_MODEL = 0;
const int IDENTIFY_MODEL = 1;
// --- 配置文件 ---
struct BaseConfig {
// 股道编号
int trackName;
// 上传识别结果标志
bool upResult;
// 使用socket来车通讯
bool useSocketServer;
// 运行模式 0: 转发模式 1: 识别模式
int runModel;
};
struct SerialConfig {
// com口名称
QString comName;
// 波特率
int baud;
// 是否有磁钢
bool havaMagnetSteel;
// 磁钢顺序
QString magnetSteelOrder;
};
struct InterfaceConfig {
// 接口服务器IP
QString httpIp;
// 接口服务器端口
int httpPort;
// 获取token的方法
QString tokenPath;
// 上传识别结果的方法
QString upResultPath;
// 上传报警的方法
QString upWarningPath;
// 用户名
QString username;
// 密码
QString password;
};
struct SServerConfig {
// socket server IP
QString server_ip;
// server_port
int server_port;
// 识别结果延后X节上传以等待Socket反馈火车运行方向
int delayed_upload;
};
struct DeviceWarnConfig {
// 识别车厢结束允许的最小值(小于这个值会报警)
int min_train_size;
};
struct RelayConfig {
// 监听端口
int listener_port;
};
// --- 配置文件 ---
struct TrainInfo {
std::string carriageType;
std::string carriageNum;
@ -29,6 +116,20 @@ namespace ai_matrix {
std::string strRfidInfo;
};
struct ComeTrain {
QString trainTime;
bool needUpLoad;
ComeTrain () {
this->trainTime = "";
this->needUpLoad = false;
};
};
struct RfidInfo {
QString rfid;
QString rfidTime;
};
}

View File

@ -23,15 +23,15 @@ void TcpClient::connectToServer(QString ip, int port) {
this->tcp_->connectToHost(ip, port); // Replace with actual server IP and port
if(QAbstractSocket::ConnectingState == this->tcp_->state()) {
emit sendTcpInfoSignals("正在连接Socket服务器...");
emit sendTcpInfoSignals("正在连接辅助识别...");
}
if (!this->tcp_->waitForConnected(2000))
{
emit sendTcpInfoSignals("链接服务超时");
emit sendTcpInfoSignals("链接辅助识别服务超时");
// 5秒后尝试重新连接
QTimer::singleShot(5000, this, [=](){
// this->tcp_ = new QTcpSocket;
emit sendTcpInfoSignals("重新连接Socket");
emit sendTcpInfoSignals("重新连接辅助识别");
emit restartSocket(this->ip_, this->port_);
});
return;
@ -42,14 +42,14 @@ void TcpClient::connectToServer(QString ip, int port) {
// 心跳包定时器启动
this->heartbeatTimer_->start(3000);
}
emit sendTcpInfoSignals("链接服务成功");
emit sendTcpInfoSignals("链接辅助识别服务成功");
// 连接失败
connect(this->tcp_, &QTcpSocket::errorOccurred, this, [=](QAbstractSocket::SocketError err){
emit sendTcpInfoSignals("链接服务失败"); // 连接失败或其他错误,若服务器没有打开或连接失败,可以从这里会发出提示
emit sendTcpInfoSignals("链接辅助识别服务失败"); // 连接失败或其他错误,若服务器没有打开或连接失败,可以从这里会发出提示
});
// 断开连接
connect(this->tcp_, &QTcpSocket::disconnected, this, [=](){
emit sendTcpInfoSignals("服务断开连接");
emit sendTcpInfoSignals("辅助识别服务断开连接");
this->tcp_->close();
this->tcp_->deleteLater();
this->tcp_ = nullptr;
@ -61,7 +61,7 @@ void TcpClient::connectToServer(QString ip, int port) {
// 5秒后尝试重新连接
QTimer::singleShot(5000, this, [=](){
emit sendTcpInfoSignals("重新连接Socket");
emit sendTcpInfoSignals("重新连接辅助识别");
emit restartSocket(this->ip_, this->port_);
});

View File

@ -1,29 +1,8 @@
#include "mainwindow.h"
#include "TcpClient.h"
#include <QApplication>
#include <MainWindow.h>
#include "common.h"
void myMessageOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) {
switch (type) {
case QtDebugMsg:
// 处理debug信息
break;
case QtWarningMsg:
// 处理警告信息
break;
case QtCriticalMsg:
// 处理严重错误信息
LogError<<"严重异常";
break;
case QtFatalMsg:
// 处理致命错误信息
LogError<<"致命异常";
break;
}
}
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QDir dir("shared_key.txt");
@ -59,7 +38,6 @@ int main(int argc, char *argv[]) {
{
SetConsoleOutputCP(CP_UTF8);
QApplication::setWindowIcon(QIcon("./logo.ico"));
qInstallMessageHandler(myMessageOutput);
MainWindow w;
w.show();

View File

@ -1,27 +1,25 @@
//
// Created by Mr.V on 2024/5/6.
//
// You may need to build the project (run Qt uic code generator) to get "ui_MainWindow.h" resolved
#include <QFileDialog>
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "TcpClient.h"
#define DEBUG_HTTP 1
MainWindow::MainWindow(QWidget *parent)
: QWidget(parent)
, ui(new Ui::MainWindow)
{
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
this->statusBar = new QStatusBar();
// this->statusBar = new QStatusBar();
this->statusInfo = new QLabel("初始化完成",this);
this->statusBar->addPermanentWidget(this->statusInfo);//显示正常信息
QLabel* statusVersion = new QLabel("开启时间:" + QDateTime::currentDateTime().toString("yy.MM.dd.hh.mm"),this);
this->statusBar->addWidget(statusVersion);
this->ui->statusbar->addPermanentWidget(this->statusInfo);//显示正常信息
QLabel* statusVersion = new QLabel(" 开启时间:" + QDateTime::currentDateTime().toString("yy.MM.dd.hh.mm"),this);
this->ui->statusbar->addWidget(statusVersion);
layout()->addWidget(this->statusBar);
// layout()->addWidget(this->statusBar);
this->setWindowTitle("Matrix_RFID 车号识别程序(勿关!!)");
this->configPath_ = "./config/config.ini";
if (!this->mkLogDir())
{
@ -30,18 +28,16 @@ MainWindow::MainWindow(QWidget *parent)
// 配置文件读取
QString errorMessage = "";
if (!ConfigUtil::readBaseConfig(this->configPath_, errorMessage, this->baseConfig_))
if (!ConfigUtil::readBaseConfig(g_config_path, errorMessage, this->baseConfig_))
{
this->logError(errorMessage);
}
if (!ConfigUtil::readInterfaceConfig(this->configPath_, errorMessage, this->interfaceConfig_))
{
this->logError(errorMessage);
}
if (!ConfigUtil::readSocketServerConfig(this->configPath_, errorMessage, this->socketServerConfig_))
if (!ConfigUtil::readSerialConfig(g_config_path, errorMessage, this->serialConfig_))
{
this->logError(errorMessage);
}
// this->ui->stackedWidget->currentChanged();
this->ui->stackedWidget->setCurrentIndex(this->baseConfig_.runModel);
// 获取本机串口列表
this->getComList();
@ -49,151 +45,138 @@ MainWindow::MainWindow(QWidget *parent)
// 初始化界面上的串口打开参数
this->initComboBox();
this->serial_ = new QSerialPort;
m_pSystemTray=new QSystemTrayIcon(this);
connect(this->ui->openComButton, &QPushButton::clicked, this, &MainWindow::openComClicked);
connect(this, &MainWindow::getRfid_signals, this, &MainWindow::getQueueDataThread);
connect(this, &MainWindow::upRfid_signals, this, &MainWindow::upRfid);
connect(this->ui->testButton, &QPushButton::clicked, this, &MainWindow::readTestInfo);
// 识别状态改变
connect(this, &MainWindow::IdentifyType, this, &MainWindow::IdentifyTypeUpdate);
//最小化信号槽
// 最小化信号槽
connect(m_pSystemTray,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason)));
this->logRfidRecvName = "./Logs/rfid_data.txt";
this->recvLog.setFileName(logRfidRecvName);
this->recvLog.open(QIODevice::ReadWrite | QIODevice::Append);
//初始最小化
//this->showMinimized();//最小化
// 设置最大展示数据行数
this->ui->textBrowser->document()->setMaximumBlockCount(1000);
this->ui->Log_TextBrowser->document()->setMaximumBlockCount(1000);
this->ui->SocketLog_TextBrowser->document()->setMaximumBlockCount(1000);
this->ui->Rfid_textBrowser->document()->setMaximumBlockCount(1000);
getStandardItemModel();
this->ui->resultTable->setModel(this->resultTableModel_);
this->ui->resultTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
this->ui->resultTable->verticalHeader()->setMinimumWidth(50);
if (!this->baseConfig_.upResult)
{
QIcon icon("./Fail.ico");
QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整
this->ui->upflagLabel->setPixmap(m_pic);
}else{
QIcon icon("./Succ.ico");
QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整
this->ui->upflagLabel->setPixmap(m_pic);
}
// if (!this->baseConfig_.upResult)
// {
// QIcon icon("./Fail.ico");
// QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整
// this->ui->upflagLabel->setPixmap(m_pic);
// }else{
// QIcon icon("./Succ.ico");
// QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整
// this->ui->upflagLabel->setPixmap(m_pic);
// }
if (this->baseConfig_.useSocketServer)
{
// 创建线程
QThread *threadWork = new QThread; // 任务线程
// 初始化LED指示灯
this->upResultType(this->baseConfig_.upResult);
this->tcpClient = new TcpClient(this);
this->tcpClient->moveToThread(threadWork);
this->readComThread = new ReadComThread(&this->queueTrainInfo_, &this->queueWarn_, &this->queueRFID_, this);
this->readComThread->start();
connect(this, &MainWindow::connect_socket, this->tcpClient, &TcpClient::connectToServer);
// 子线程反馈 socket 到主线程
connect(this->tcpClient, &TcpClient::socketComplete, this, [=](QTcpSocket* tcp, QString ip, quint16 port){
this->tcp_ = tcp;
});
// 接收子线程的消息提示
connect(this->tcpClient, &TcpClient::sendTcpInfoSignals, this, [=](const QString& info){
this->logInfo(info);
this->statusInfo->setText(info);
if (info == "链接服务端超时"
|| info == "未连接Socket服务器"
|| info == "链接服务端失败"
|| info == "服务端断开连接"
|| info == "链接服务端失败")
{
this->videoHasTrain = false;
}
});
// 接收子线程的TCP消息内容展示
connect(this->tcpClient, &TcpClient::getTcpInfoSignals, this, [=](const QString& info){
this->logInfo(info);
});
emit connect_socket(this->socketServerConfig_.server_ip, this->socketServerConfig_.server_port);
connect(this->tcpClient, &TcpClient::comeTrainSignals, this, [=](bool type) {
if (type)
{
this->logInfo("视频车号识别-来车了");
this->videoHasTrain = true;
emit IdentifyType();
}
else
{
this->logInfo("视频车号识别-火车离开了");
this->videoHasTrain = false;
if (this->needIdentify)
emit IdentifyType();
}
});
connect(this->tcpClient, &TcpClient::getDirectionSignals, this, [=](int direction) {
if (this->iDirection != direction)
{
this->logInfo("获得方向判定:" + QString(direction > -1 ? (direction > 0 ? "需识别" : "待定") : "无需上传"));
this->iDirection = direction;
}
});
}
ui->openComButton->click();
this->upResultThread = new UpResultThread(&this->queueTrainInfo_, &this->iDirection, this);
this->upResultThread = new UpResultThread(&this->queueTrainInfo_, this);
this->upResultThread->start();
this->upWarnThread = new UpWarnThread(&this->queueWarn_, this);
this->upWarnThread->start();
this->relayRfidThread = new RelayRfidThread(&this->queueRFID_, this);
this->relayRfidThread->start();
connect(this->ui->identify, &QAction::triggered, this, &MainWindow::identifyModelClicked);
connect(this->ui->relay, &QAction::triggered, this, &MainWindow::relayModelClicked);
connect(this, &MainWindow::openCom_signals, this->readComThread, &ReadComThread::openCom);
connect(this, &MainWindow::readTestRfid_signals, this->readComThread, &ReadComThread::readTestInfo);
connect(this, &MainWindow::updateRunModel_ReadCom_signals, this->readComThread, &ReadComThread::updateRunModel);
connect(this->relayRfidThread, &RelayRfidThread::update_client_num, this, &MainWindow::update_client_num);
connect(this->relayRfidThread, &RelayRfidThread::ConnectInfoSignals, this, &MainWindow::ConnectInfoSignals);
connect(this->relayRfidThread, &RelayRfidThread::RfidInfoSignals, this, &MainWindow::RfidInfoSignals);
connect(this->readComThread, &ReadComThread::openComSuccess, this, &MainWindow::openComResult);
connect(this->readComThread, &ReadComThread::closeComSuccess, this, &MainWindow::closeComResult);
connect(this->readComThread, &ReadComThread::comeTrain, this, &MainWindow::comeTrain);
connect(this->readComThread, &ReadComThread::upResultType, this, &MainWindow::upResultType);
// 状态栏信息变化
connect(this->readComThread, &ReadComThread::statusInfoUpdate, this, &MainWindow::statusInfoUpdate);
connect(this->readComThread, &ReadComThread::DebugSignals, this, &MainWindow::DebugSlots);
connect(this->readComThread, &ReadComThread::InfoSignals, this, &MainWindow::InfoSlots);
connect(this->readComThread, &ReadComThread::WarnSignals, this, &MainWindow::WarnSlots);
connect(this->readComThread, &ReadComThread::ErrorSignals, this, &MainWindow::ErrorSlots);
connect(this->upResultThread, &UpResultThread::DebugSignals, this, &MainWindow::DebugSlots);
connect(this->upResultThread, &UpResultThread::InfoSignals, this, &MainWindow::InfoSlots);
connect(this->upResultThread, &UpResultThread::WarnSignals, this, &MainWindow::WarnSlots);
connect(this->upResultThread, &UpResultThread::ErrorSignals, this, &MainWindow::ErrorSlots);
connect(this->upWarnThread, &UpWarnThread::DebugSignals, this, &MainWindow::DebugSlots);
connect(this->upWarnThread, &UpWarnThread::InfoSignals, this, &MainWindow::InfoSlots);
connect(this->upWarnThread, &UpWarnThread::WarnSignals, this, &MainWindow::WarnSlots);
connect(this->upWarnThread, &UpWarnThread::ErrorSignals, this, &MainWindow::ErrorSlots);
connect(this->relayRfidThread, &RelayRfidThread::DebugSignals, this, &MainWindow::DebugSlots);
connect(this->relayRfidThread, &RelayRfidThread::InfoSignals, this, &MainWindow::InfoSlots);
connect(this->relayRfidThread, &RelayRfidThread::WarnSignals, this, &MainWindow::WarnSlots);
connect(this->relayRfidThread, &RelayRfidThread::ErrorSignals, this, &MainWindow::ErrorSlots);
ui->openComButton->click();
}
MainWindow::~MainWindow()
{
MainWindow::~MainWindow() {
this->logInfo("-- 程序退出 --");
this->initParam();
delete ui;
}
void MainWindow::logDebug(const QString& message) {
LogDebug << message.toStdString();
ui->textBrowser->append(QString("[Debug] [") + this->getSystemTime() + QString::fromStdString("] ") + message);
ui->Log_TextBrowser->append(QString("[Debug] [") + this->getSystemTime() + QString::fromStdString("] ") + message);
}
void MainWindow::logInfo(const QString& message) {
LogInfo << message.toStdString();
ui->textBrowser->append(QString("[Info] [") + this->getSystemTime() + QString::fromStdString("] ") + message);
ui->Log_TextBrowser->append(QString("[Info] [") + this->getSystemTime() + QString::fromStdString("] ") + message);
}
void MainWindow::logWarn(const QString& message) {
LogWarn << message.toStdString();
ui->textBrowser->append(QString("[Warn] [") + this->getSystemTime() + QString::fromStdString("] ") + message);
ui->Log_TextBrowser->append(QString("[Warn] [") + this->getSystemTime() + QString::fromStdString("] ") + message);
}
void MainWindow::logError(const QString& message) {
LogError << message.toStdString();
ui->textBrowser->append(QString("[Error] [") + this->getSystemTime() + QString::fromStdString("] ") + message);
ui->Log_TextBrowser->append(QString("[Error] [") + this->getSystemTime() + QString::fromStdString("] ") + message);
}
void MainWindow::statusInfoUpdate(const QString &info) {
this->statusInfo->setText(info);
}
void MainWindow::RfidInfoSignals(const QString &info) {
this->ui->Rfid_textBrowser->append(info);
}
void MainWindow::ConnectInfoSignals(const QString &info) {
this->ui->SocketLog_TextBrowser->append("- " + this->getSystemTime() + " - \n" + info);
}
void MainWindow::initParam() {
this->rfidSourceInfo = "";
this->trainTime = "";
if (this->recvLog.isOpen()) this->recvLog.close();
this->vecTrain.clear();
this->needIdentify = false;
this->rnameRfidLog();
this->queue_.clear();
this->iDirection = 0;
void MainWindow::relayModelClicked() {
this->updateRunModel(0);
}
void MainWindow::identifyModelClicked() {
this->updateRunModel(1);
}
void MainWindow::updateRunModel(int page) {
this->ui->stackedWidget->setCurrentIndex(page);
this->baseConfig_.runModel = page;
QString errorMessage = "";
if (!ConfigUtil::writeBaseConfig(g_config_path, errorMessage, this->baseConfig_))
{
this->logError(errorMessage);
}
emit this->updateRunModel_ReadCom_signals(page);
}
/**
@ -212,80 +195,6 @@ bool MainWindow::mkLogDir()
return true;
}
bool MainWindow::mkRfidLog()
{
try {
QFileInfo fileInfo(this->logRfidRecvName);
if(fileInfo.isFile())
{
return true;
}
this->recvLog.setFileName(this->logRfidRecvName);
if (!this->recvLog.isOpen())
{
this->recvLog.open(QIODevice::ReadWrite | QIODevice::Append);
}
return true;
} catch (const std::exception &e) {
this->logError("创建、打开RFID原始数据日志文件失败,详细:");
this->logError(e.what());
}
return false;
}
void MainWindow::deleteOldFiles(const QString &path, int days)
{
QDir dir(path);
foreach(QFileInfo fi, dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot))
{
if((fi.lastModified().addDays(days) < QDateTime::currentDateTime()))
{
QFile::remove(fi.absoluteFilePath());
}
}
}
bool MainWindow::rnameRfidLog()
{
try {
this->recvLog.close();
QFile logFile(this->logRfidRecvName);
QFileInfo fileInfo(logFile);
if (fileInfo.size() == 0) return false;
QString newLogFileName = fileInfo.path() + "/";
newLogFileName.append(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss"));
newLogFileName.append(".txt");
if (!logFile.rename(newLogFileName))
{
this->logError("读取RFID原始数据存储重命名失败");
return false;
}
this->deleteOldFiles(fileInfo.path(), 3);
} catch (const std::exception &e) {
this->logError("读取RFID原始数据存储重命名失败");
return false;
}
return true;
}
void MainWindow::saveRfidLog(const QString &value)
{
try {
QString logValue = value + "\n";
if (!this->recvLog.isOpen())
{
this->recvLog.open(QIODevice::ReadWrite | QIODevice::Append);
}
this->recvLog.write(logValue.toUtf8());
this->recvLog.flush();
} catch (const std::exception &e) {
this->logError("保存RFID原数据失败");
}
}
/**
*
* @return
@ -302,32 +211,30 @@ QList<QString> MainWindow::getComList() {
/**
* comboxBox
*/
void MainWindow::initComboBox() {
void MainWindow::initComboBox()
{
// ui->BTBox->setEditable(true);
ui->BTBox->setStyleSheet("QComboBox {background-color: rgb(255, 255, 255);} QComboBox QAbstractItemView::item {min-height: 30px; background-color: rgb(225, 225, 225);}");
ui->BTBox->setStyleSheet("QComboBox {background-color: rgb(255, 255, 255);} QComboBox QAbstractItemView::item {min-height: 20px; background-color: rgb(225, 255, 255); color: rgb(0, 0, 0);}");
ui->BTBox->setView(new QListView());
ui->comBox->setEditable(true);
ui->comBox->setStyleSheet("QComboBox {background-color: rgb(255, 255, 255);} QComboBox QAbstractItemView::item {min-height: 30px; background-color: rgb(225, 225, 225);}");
ui->comBox->setStyleSheet("QComboBox {background-color: rgb(255, 255, 255);} QComboBox QAbstractItemView::item {min-height: 20px; background-color: rgb(225, 255, 255); color: rgb(0, 0, 0);}");
ui->comBox->setMaxVisibleItems(5);
ui->comBox->setView(new QListView());
ui->comBox->addItems(this->comList);
if (this->baseConfig_.comName != "") {
if (ui->comBox->findText(this->baseConfig_.comName) == -1)
if (this->serialConfig_.comName != "") {
if (ui->comBox->findText(this->serialConfig_.comName) == -1)
{
ui->comBox->addItem(this->baseConfig_.comName);
ui->comBox->addItem(this->serialConfig_.comName);
}
ui->comBox->setCurrentText(this->baseConfig_.comName);
ui->comBox->setCurrentText(this->serialConfig_.comName);
}
if (ui->BTBox->findText(QString::number(this->baseConfig_.baud)) == -1)
if (ui->BTBox->findText(QString::number(this->serialConfig_.baud)) == -1)
{
ui->BTBox->addItem(QString::number(this->baseConfig_.baud));
ui->BTBox->addItem(QString::number(this->serialConfig_.baud));
}
ui->BTBox->setCurrentText(QString::number(this->baseConfig_.baud));
ui->BTBox->setCurrentText(QString::number(this->serialConfig_.baud));
ui->truckEdit->setText(QString::number(this->baseConfig_.trackName));
this->rfidHasTrain = false;
this->videoHasTrain = false;
// ui->truckEdit->setText(QString::number(this->baseConfig_.trackName));
}
/**
@ -389,8 +296,6 @@ void MainWindow::closeEvent(QCloseEvent *event)
// 验证账号和密码是否正确
if (password == "matrix") {
this->initParam();
this->tcp_->close();
event->accept(); // 关闭窗口
exit(0);
} else {
@ -458,31 +363,8 @@ void MainWindow::openComClicked()
{
if (ui->openComButton->text() == "打开串口")
{
this->serial_ = this->comDetect_.openCom(ui->comBox->currentText(), ui->BTBox->currentIndex());
if (this->serial_ != nullptr)
{
QString logs;
logs.append("串口打开成功\n");
logs.append("串口号:" + ui->comBox->currentText() + "\n");
logs.append("波特率:" + ui->BTBox->currentText() + "\n");
if (this->baseConfig_.havaMagnetSteel)
logs.append("磁钢顺序:" + this->baseConfig_.magnetSteelOrder);
this->isOpenCom = true;
this->logInfo(logs);
this->ui->openComButton->setText("关闭串口");
this->ui->LEDlabel->setStyleSheet("border-radius: 16px;\ "
"background-color: rgba(74, 221, 108, 225);\ "
"border:1px solid rgba(168, 168, 168, 105);");
connect(this->serial_,&QSerialPort::readyRead,this,&MainWindow::readCom); //
connect(this->serial_, &QSerialPort::errorOccurred, this, &MainWindow::serialPort_error);
}
else
{
this->isOpenCom = false;
this->logInfo("串口打开失败!");
}
this->auto_reconnect_serial_ = true;
emit openCom_signals(true);
}
else
{
@ -491,212 +373,66 @@ void MainWindow::openComClicked()
// 验证账号和密码是否正确
if (password == "matrix") {
if (this->comDetect_.closeCom())
{
if (this->needIdentify == true) this->needIdentify = false;
this->isOpenCom = false;
this->logInfo("串口已关闭!");
this->initParam();
this->ui->openComButton->setText("打开串口");
this->ui->LEDlabel->setStyleSheet("border-radius: 16px;\ "
"background-color: red;\ "
"border:1px solid rgba(168, 168, 168, 105);");
}
this->auto_reconnect_serial_ = false;
emit openCom_signals(false);
} else {
QMessageBox::warning(this, "验证失败", "密码不正确!");
}
}
}
/**
* 退
* @param error
*/
void MainWindow::serialPort_error(QSerialPort::SerialPortError error)
void MainWindow::openComResult(const bool &success)
{
if (error != QSerialPort::NoError)
this->ui->openComButton->setText("关闭串口");
if (success)
{
//关闭串口
this->serial_->close();
this->ui->openComButton->setText("打开串口");
this->logError("串口异常退出,疑似接口松动");
this->ui->LEDlabel->setStyleSheet("border-radius: 16px; \ "
this->ui->LEDlabel->setStyleSheet("border-radius: 16px;\ "
"background-color: rgba(74, 221, 108, 225);\ "
"border:1px solid rgba(168, 168, 168, 105);");
}
else
{
this->ui->LEDlabel->setStyleSheet("border-radius: 16px;\ "
"background-color: red;\ "
"border:1px solid rgba(168, 168, 168, 105);");
this->logInfo("10秒钟后自动尝试重连串口...");
// if (auto_reconnect_serial_) emit openCom_signals(true, 10 * 1000);
}
}
void MainWindow::closeComResult(const bool &success)
{
if (success)
{
this->ui->openComButton->setText("打开串口");
this->ui->LEDlabel->setStyleSheet("border-radius: 16px;\ "
"background-color: red;\ "
"border:1px solid rgba(168, 168, 168, 105);");
}
else
{
this->ui->LEDlabel->setStyleSheet("border-radius: 16px;\ "
"background-color: rgba(74, 221, 108, 225);\ "
"border:1px solid rgba(168, 168, 168, 105);");
}
}
void MainWindow::readCom()
{
try {
if (this->serial_->waitForReadyRead(10)) {
QByteArray data = this->serial_->readAll(); // 读取数据
if(!data.isEmpty())
{
this->queue_.push(QString(data));
emit getRfid_signals();
}
// this->serial_->clear();
data.clear();
}
else
{
this->logError("等待读取超时");
}
} catch(...) {
this->logError("读取串口数据异常!");
}
void MainWindow::comeTrain(const bool &success) {
this->resultTableModel_->clear();
this->resultTableModel_ = this->getStandardItemModel();
}
/**
* @brief:queue中获取数据
* @param:
* @return:
*/
void MainWindow::getQueueDataThread()
{
if (this->queue_.isEmpty()) return;
QString strRfidInfo = this->queue_.getTop();
this->queue_.pop();
this->saveRfidLog(strRfidInfo);
this->tmpRfid.append(strRfidInfo);
if (this->tmpRfid.right(1) != "&")
{
return;
}
this->tmpRfid = this->tmpRfid.replace("&", "");
QStringList rfidSubList = this->tmpRfid.split("@");
this->tmpRfid = "";
auto split_lambda = [=](QString strFirst, QString strOther){
if (strFirst == "0")
{
this->rfidHasTrain = false;
this->logInfo("RFID-火车离开了");
// 关功放信号
// 需要结合 “来车状态”广播消息,确认是否真的车离开了; TODO:没有真离开,则向串口发送 @on& 避免关功放
emit IdentifyType();
}
else
{
// TODO: 此处按照4个磁钢来配置可能存在一定限制; 另外逻辑需要优化
if (strOther == "000000" // 第一次检测来车时(前提是上一次功放已关闭)
&& (strFirst == this->baseConfig_.magnetSteelOrder.left(1)
|| strFirst == this->baseConfig_.magnetSteelOrder.mid(1, 1)))
{
this->rfidHasTrain = true;
this->logInfo("RFID-来车了");
emit IdentifyType();
}
}
};
for (const auto & i : rfidSubList)
{
if (i.size() == 26 || i.size() == 24)
{
// 车厢信息
QString strTrainInfo = i.left(14);
if (vecTrain.empty() || !vecTrain.contains(strTrainInfo))
{
bool isNoCarriage = false;
int carT = strTrainInfo.mid(3, 2).simplified().toInt(&isNoCarriage);
if (isNoCarriage && carT >= 10) continue;
// 因信号不稳定 增加一行过滤 出现文字中带有字母及数字以外的字符时,过滤
if (!strTrainInfo.contains(QRegExp("^[A-Z0-9\\s]+$"))) continue;
// 因信号不稳定 增加一行过滤 出现读到的数据里 空格替代了实际字符的情况
if (strTrainInfo.mid(7, 7).simplified().size() < 7) continue;
vecTrain.append(strTrainInfo);
int train_order = vecTrain.size();
this->resultTableModel_->setItem(train_order - 1, 0, new QStandardItem(strTrainInfo));
this->logInfo(QString("第%1节 %2").arg(train_order).arg(strTrainInfo));
// 将接收到的RFID使用@符拼接起来以待后续上传web
this->rfidSourceInfo.append("@" + i);
QString rfidinfo = this->rfidSourceInfo;
this->rfidSourceInfo = "";
emit upRfid_signals(rfidinfo);
}
}
else if (i.size() == 7)
{
// 不使用磁钢的情况下 过滤掉磁钢信号
if (!this->baseConfig_.havaMagnetSteel) continue;
// 磁钢信号
QString strFirst = i.left(1);
QString strOther = i.mid(1, i.size() - 1);
// 将接收到的RFID使用@符拼接起来以待后续上传web
this->rfidSourceInfo.append("@" + i);
split_lambda(strFirst, strOther);
}
else if (i.size() == 14) // 特殊情况,来车信号少了&符
{
// 不使用磁钢的情况下 过滤掉磁钢信号
if (!this->baseConfig_.havaMagnetSteel) continue;
for (int j = 0; j < i.size(); j+=7) {
QString rfid_cg = i.mid(j, 7);
QString strFirst = rfid_cg.left(1);
QString strOther = rfid_cg.mid(1, 6);
// 将接收到的RFID使用@符拼接起来以待后续上传web
this->rfidSourceInfo.append("@" + rfid_cg);
split_lambda(strFirst, strOther);
}
}
}
}
void MainWindow::upRfid(QString rfidInfo)
{
if (!this->baseConfig_.upResult) return;
if (!this->needIdentify && this->baseConfig_.havaMagnetSteel)
{
QIcon icon("./Fail.ico");
QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整
this->ui->upflagLabel->setPixmap(m_pic);
return;
}else{
void MainWindow::upResultType(const bool &type) {
if (type) {
QIcon icon("./Succ.ico");
QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整
this->ui->upflagLabel->setPixmap(m_pic);
}
QString info = this->vecTrain.back();
int order = this->vecTrain.size();
info = info.mid(1,info.size() - 1);
TrainInfo trainInfo;
trainInfo.carriageType = info.left(6).simplified().toStdString();
trainInfo.carriageNum = info.mid(6, info.size() - 6).simplified().toStdString();
trainInfo.strOrder = QString::number(order).toStdString();
trainInfo.trainTime = this->trainTime.toStdString();
trainInfo.collectTime = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz").toStdString();
trainInfo.strRfidInfo = rfidInfo.toStdString();
this->queueTrainInfo_.push(trainInfo);
}
void MainWindow::IdentifyTypeUpdate() {
if (this->rfidHasTrain || this->videoHasTrain)
{
if (!this->needIdentify)
{
this->logInfo("来车了");
this->mkRfidLog();
this->vecTrain.clear();
this->needIdentify = true;
this->trainTime = this->getSystemTime();
this->resultTableModel_->clear();
this->resultTableModel_ = this->getStandardItemModel();
}
}
else if (!this->rfidHasTrain && !this->videoHasTrain)
{
this->initParam();
this->logInfo("火车离开了");
} else {
QIcon icon("./Fail.ico");
QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整
this->ui->upflagLabel->setPixmap(m_pic);
}
}
@ -716,36 +452,27 @@ void MainWindow::ErrorSlots(const QString &info) {
this->logError(info);
}
// ============================= 转发 ====================================
void MainWindow::update_client_num(int num)
{
this->ui->SocketClientNum_Label->setText(QString::number(this->ui->SocketClientNum_Label->text().toInt() + num));
}
// ============================= 测试 ====================================
void MainWindow::readTestInfo()
{
if (this->isOpenCom)
if (this->ui->openComButton->text() == "关闭串口")
{
logWarn("请先关闭串口后进行测试操作!");
return;
}
QString filePath = QFileDialog::getOpenFileName(this, "选择一个文件", QDir::currentPath(), "(*.*)");
if(filePath.isEmpty()){
QMessageBox::warning(this, "打开文件", "选择文件不能为空");
// QMessageBox::warning(this, "打开文件", "选择文件不能为空");
return;
}
// 创建一个QFile对象并打开要读取的文本文件
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
logError("无法打开测试文件:" + filePath);
return;
}
logInfo("开始读取测试数据...");
// 将文件内容读入到QStringList中
QTextStream in(&file);
while(!in.atEnd()) {
QString line = in.readLine();
this->queue_.push(line);
emit getRfid_signals();
}
// 关闭文件
file.close();
logInfo("---读取测试数据完毕---");
}
emit this->readTestRfid_signals(filePath);
}

View File

@ -1,72 +1,54 @@
#ifndef MainWindow_H
#define MainWindow_H
//
// Created by Mr.V on 2024/5/6.
//
#include <QWidget>
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort>
#include <QDebug>
#include <QString>
#include <stdio.h>
#include <string.h>
#ifndef TRAIN_RFID_RELAY_MainWindow_H
#define TRAIN_RFID_RELAY_MainWindow_H
#include <QMainWindow>
#include <cstdio>
#include <cstring>
#include <WinSock2.h>
#include <windows.h>
#include <stdlib.h>
#include <cstdlib>
#include <string>
#include <vector>
#include <chrono>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <QWaitCondition>
#include <ctime>
#include <codecvt>
#include <Iphlpapi.h>
#include <cstdlib>
#include <QObject>
#include <QTcpsocket>
#include <direct.h>
#include <algorithm>
#include <QDateTime>
#include "httplib.h"
#include "json.h"
#include <QInputDialog>
#include <QSystemTrayIcon>
#include <QCloseEvent>
#include <QAction>
#include <QCloseEvent>
#include <qmenu.h>
#include <QFile>
#include <QDir>
#include <thread>
#include <QMessageBox>
#include <QTimer>
#include <QListView>
#include <QMenuBar>
#include <QStatusBar>
#include <QtConcurrent>
#include <queue>
#include <mutex>
#include <thread>
#include <chrono>
#include "common.h"
#include "ConfigUtil.h"
#include "ComDetect.h"
#include "UpResultThread.h"
#include "ReadComThread.h"
#include "RelayRfidThread.h"
#include "TcpClient.h"
#include "../threads/UpResultThread.h"
#include "UpWarnThread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
using namespace ai_matrix;
class MainWindow : public QWidget
{
Q_OBJECT
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
void logDebug(const QString& message);
void logInfo(const QString& message);
@ -74,16 +56,8 @@ public:
void logError(const QString& message);
// 创建日志目录
static bool mkLogDir();
bool mkRfidLog();
void deleteOldFiles(const QString &path, int days);
bool rnameRfidLog();
void saveRfidLog(const QString &value);
void initParam();
QString getSystemTime();
static QString getSystemTime();
// 获const 取串口列表&
QList<QString> getComList();
@ -95,89 +69,88 @@ public:
QStandardItem* getStandardItem(const QString &value);
private:
Ui::MainWindow *ui;
UpResultThread *upResultThread;
QString trainTime;
UpWarnThread *upWarnThread;
ReadComThread *readComThread;
RelayRfidThread *relayRfidThread;
QString logRfidRecvName;
QFile recvLog;
QString configPath_; //
ai_matrix::BaseConfig baseConfig_;
ai_matrix::SerialConfig serialConfig_;
ai_matrix::InterfaceConfig interfaceConfig_;
ai_matrix::SServerConfig socketServerConfig_;
std::string webToken; //授权信息
QSerialPort *serial_; //串口
std::string webToken; //授权信息
// 表格model
QStandardItemModel *resultTableModel_ = nullptr;
// 打开com口标志
bool isOpenCom = false;
bool auto_reconnect_serial_ = false;
// Com口数据读取类
ComDetect comDetect_;
// ComDetect comDetect_;
// com口列表
QList<QString> comList;
// 整列车识别结果存储
QStringList vecTrain;
MQueue<QString> queue_{}; // RFID读取的数据队列
MQueue<QString> queueRFID_{}; // RFID读取的数据队列
MQueue<TrainInfo> queueTrainInfo_{}; // RFID读取的磁钢信息队列
MQueue<QString> queueWarn_{}; // 报警信息队列
QString rfidSourceInfo;
QString tmpRfid; //临时存储的RFID原始数据用于防止接收的数据不完整
// 识别方向正确标志
bool needIdentify = false;
// 视频识别有火车标志使用socket服务时才有用
bool videoHasTrain = false;
// RFID识别有火车标志
bool rfidHasTrain = false;
// 是否是需要识别的方向 -1:不识别 0:未确定 1:识别
int iDirection = 0;
// 获取当前时间
QDateTime currentTime_ = QDateTime::currentDateTime();
TcpClient* tcpClient;
private:
QTcpSocket* tcp_ = nullptr;
QStatusBar* statusBar;
QStatusBar* statusBar{};
QLabel *statusInfo;
QMenu* m_pTrayMennu; //系统托盘右键菜单项
QMenu* m_pTrayMennu{}; //系统托盘右键菜单项
QSystemTrayIcon* m_pSystemTray; //系统托盘图标
//右键菜单栏选项
QAction* m_pActionShow;
QAction* m_pActionQuit;
QAction* m_pActionShow{};
QAction* m_pActionQuit{};
void creat_action();
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
void on_ShowMainAction();
void closeEvent(QCloseEvent *event);
void creat_menu();
signals:
void getRfid_signals();
void upRfid_signals(QString rfidInfo);
void connect_socket(QString ip, int port);
void IdentifyType();
void openCom_signals(const bool &type, const int &msec = 0);
void readTestRfid_signals(const QString &filePath);
void updateRunModel_ReadCom_signals(int model);
private slots:
void relayModelClicked();
void identifyModelClicked();
void updateRunModel(int page);
void openComClicked();
void readCom();
void getQueueDataThread();
void upRfid(QString rfidInfo);
void serialPort_error(QSerialPort::SerialPortError error);
void openComResult(const bool &success);
void closeComResult(const bool &success);
void upResultType(const bool &type);
void comeTrain(const bool &success);
void on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason reason);
void readTestInfo();
void IdentifyTypeUpdate();
void statusInfoUpdate(const QString &info);
void update_client_num(int num);
void RfidInfoSignals(const QString &info);
void ConnectInfoSignals(const QString &info);
void DebugSlots(const QString &info);
void InfoSlots(const QString &info);
void WarnSlots(const QString &info);
void ErrorSlots(const QString &info);
private:
Ui::MainWindow *ui;
};
#endif // MainWindow_H
#endif //TRAIN_RFID_RELAY_MainWindow_H

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
** Form generated from reading UI file 'MainWindow.ui'
**
** Created by: Qt User Interface Compiler version 5.15.2
**
@ -10,14 +10,19 @@
#define UI_MAINWINDOW_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QSpacerItem>
#include <QtWidgets/QStackedWidget>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QTableView>
#include <QtWidgets/QTextBrowser>
#include <QtWidgets/QVBoxLayout>
@ -28,53 +33,89 @@ QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QVBoxLayout *verticalLayout_3;
QAction *actionset;
QAction *actionshibiefuzhu;
QAction *actionchuankou;
QAction *identify;
QAction *relay;
QWidget *centralwidget;
QVBoxLayout *verticalLayout;
QHBoxLayout *horizontalLayout;
QLabel *label;
QComboBox *comBox;
QSpacerItem *horizontalSpacer_9;
QLabel *label_2;
QComboBox *BTBox;
QLabel *label_3;
QLineEdit *truckEdit;
QSpacerItem *horizontalSpacer;
QLabel *LEDlabel;
QPushButton *openComButton;
QLabel *LEDlabel;
QSpacerItem *horizontalSpacer_5;
QPushButton *testButton;
QSpacerItem *horizontalSpacer_2;
QHBoxLayout *horizontalLayout_2;
QVBoxLayout *verticalLayout;
QStackedWidget *stackedWidget;
QWidget *page;
QVBoxLayout *verticalLayout_7;
QVBoxLayout *verticalLayout_3;
QHBoxLayout *horizontalLayout_5;
QLabel *label_8;
QLabel *SocketClientNum_Label;
QSpacerItem *horizontalSpacer_6;
QTextBrowser *SocketLog_TextBrowser;
QHBoxLayout *horizontalLayout_3;
QLabel *label_4;
QLabel *upflagLabel;
QSpacerItem *horizontalSpacer_3;
QTextBrowser *Rfid_textBrowser;
QWidget *page_2;
QVBoxLayout *verticalLayout_6;
QHBoxLayout *horizontalLayout_6;
QVBoxLayout *verticalLayout_4;
QHBoxLayout *horizontalLayout_7;
QLabel *label_6;
QLabel *upflagLabel;
QSpacerItem *horizontalSpacer_7;
QTableView *resultTable;
QVBoxLayout *verticalLayout_2;
QHBoxLayout *horizontalLayout_4;
QLabel *label_5;
QSpacerItem *horizontalSpacer_4;
QTextBrowser *textBrowser;
QTextBrowser *Log_TextBrowser;
QMenuBar *menubar;
QMenu *menu;
QMenu *run_model;
QStatusBar *statusbar;
void setupUi(QWidget *MainWindow)
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(1000, 815);
MainWindow->setMinimumSize(QSize(1000, 815));
MainWindow->setMaximumSize(QSize(1000, 815));
MainWindow->setStyleSheet(QString::fromUtf8("background-color: rgb(217, 235, 255);"));
verticalLayout_3 = new QVBoxLayout(MainWindow);
verticalLayout_3->setObjectName(QString::fromUtf8("verticalLayout_3"));
actionset = new QAction(MainWindow);
actionset->setObjectName(QString::fromUtf8("actionset"));
actionshibiefuzhu = new QAction(MainWindow);
actionshibiefuzhu->setObjectName(QString::fromUtf8("actionshibiefuzhu"));
actionchuankou = new QAction(MainWindow);
actionchuankou->setObjectName(QString::fromUtf8("actionchuankou"));
identify = new QAction(MainWindow);
identify->setObjectName(QString::fromUtf8("identify"));
relay = new QAction(MainWindow);
relay->setObjectName(QString::fromUtf8("relay"));
centralwidget = new QWidget(MainWindow);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
verticalLayout = new QVBoxLayout(centralwidget);
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
horizontalLayout = new QHBoxLayout();
horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
label = new QLabel(MainWindow);
horizontalLayout->setContentsMargins(-1, 6, -1, -1);
label = new QLabel(centralwidget);
label->setObjectName(QString::fromUtf8("label"));
label->setMaximumSize(QSize(80, 16777215));
label->setMaximumSize(QSize(70, 16777215));
label->setStyleSheet(QString::fromUtf8("font: 75 9pt \"Arial\";"));
horizontalLayout->addWidget(label);
comBox = new QComboBox(MainWindow);
comBox = new QComboBox(centralwidget);
comBox->setObjectName(QString::fromUtf8("comBox"));
comBox->setMinimumSize(QSize(120, 40));
comBox->setMaximumSize(QSize(100, 40));
@ -82,14 +123,18 @@ public:
horizontalLayout->addWidget(comBox);
label_2 = new QLabel(MainWindow);
horizontalSpacer_9 = new QSpacerItem(40, 20, QSizePolicy::Maximum, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer_9);
label_2 = new QLabel(centralwidget);
label_2->setObjectName(QString::fromUtf8("label_2"));
label_2->setMaximumSize(QSize(80, 16777215));
label_2->setMaximumSize(QSize(70, 16777215));
label_2->setStyleSheet(QString::fromUtf8("font: 75 9pt \"Arial\";"));
horizontalLayout->addWidget(label_2);
BTBox = new QComboBox(MainWindow);
BTBox = new QComboBox(centralwidget);
BTBox->addItem(QString());
BTBox->addItem(QString());
BTBox->addItem(QString());
@ -100,34 +145,11 @@ public:
horizontalLayout->addWidget(BTBox);
label_3 = new QLabel(MainWindow);
label_3->setObjectName(QString::fromUtf8("label_3"));
label_3->setMaximumSize(QSize(80, 16777215));
horizontalLayout->addWidget(label_3);
truckEdit = new QLineEdit(MainWindow);
truckEdit->setObjectName(QString::fromUtf8("truckEdit"));
truckEdit->setMinimumSize(QSize(120, 40));
truckEdit->setMaximumSize(QSize(100, 40));
truckEdit->setStyleSheet(QString::fromUtf8("background-color: rgb(255, 255, 255);"));
horizontalLayout->addWidget(truckEdit);
horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Maximum, QSizePolicy::Minimum);
horizontalSpacer = new QSpacerItem(80, 20, QSizePolicy::Minimum, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer);
LEDlabel = new QLabel(MainWindow);
LEDlabel->setObjectName(QString::fromUtf8("LEDlabel"));
LEDlabel->setMaximumSize(QSize(32, 32));
LEDlabel->setStyleSheet(QString::fromUtf8("border-radius: 16px;\n"
"background-color: red;\n"
"border:1px solid rgba(168, 168, 168, 105);"));
horizontalLayout->addWidget(LEDlabel);
openComButton = new QPushButton(MainWindow);
openComButton = new QPushButton(centralwidget);
openComButton->setObjectName(QString::fromUtf8("openComButton"));
openComButton->setMinimumSize(QSize(120, 50));
openComButton->setMaximumSize(QSize(120, 50));
@ -136,11 +158,21 @@ public:
horizontalLayout->addWidget(openComButton);
horizontalSpacer_5 = new QSpacerItem(20, 20, QSizePolicy::Maximum, QSizePolicy::Minimum);
LEDlabel = new QLabel(centralwidget);
LEDlabel->setObjectName(QString::fromUtf8("LEDlabel"));
LEDlabel->setMinimumSize(QSize(32, 32));
LEDlabel->setMaximumSize(QSize(32, 32));
LEDlabel->setStyleSheet(QString::fromUtf8("border-radius: 16px;\n"
"background-color: red;\n"
"border:1px solid rgba(168, 168, 168, 105);"));
horizontalLayout->addWidget(LEDlabel);
horizontalSpacer_5 = new QSpacerItem(50, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer_5);
testButton = new QPushButton(MainWindow);
testButton = new QPushButton(centralwidget);
testButton->setObjectName(QString::fromUtf8("testButton"));
testButton->setMinimumSize(QSize(50, 50));
testButton->setMaximumSize(QSize(50, 50));
@ -149,57 +181,151 @@ public:
horizontalLayout->addWidget(testButton);
horizontalSpacer_2 = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Minimum);
horizontalSpacer_2 = new QSpacerItem(20, 20, QSizePolicy::Maximum, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer_2);
verticalLayout_3->addLayout(horizontalLayout);
verticalLayout->addLayout(horizontalLayout);
horizontalLayout_2 = new QHBoxLayout();
horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
verticalLayout = new QVBoxLayout();
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
stackedWidget = new QStackedWidget(centralwidget);
stackedWidget->setObjectName(QString::fromUtf8("stackedWidget"));
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(stackedWidget->sizePolicy().hasHeightForWidth());
stackedWidget->setSizePolicy(sizePolicy);
stackedWidget->setMaximumSize(QSize(400, 16777215));
stackedWidget->setStyleSheet(QString::fromUtf8("background-color: rgb(217, 235, 255);"));
page = new QWidget();
page->setObjectName(QString::fromUtf8("page"));
verticalLayout_7 = new QVBoxLayout(page);
verticalLayout_7->setObjectName(QString::fromUtf8("verticalLayout_7"));
verticalLayout_7->setContentsMargins(0, 0, 0, 0);
verticalLayout_3 = new QVBoxLayout();
verticalLayout_3->setSpacing(9);
verticalLayout_3->setObjectName(QString::fromUtf8("verticalLayout_3"));
horizontalLayout_5 = new QHBoxLayout();
horizontalLayout_5->setObjectName(QString::fromUtf8("horizontalLayout_5"));
label_8 = new QLabel(page);
label_8->setObjectName(QString::fromUtf8("label_8"));
label_8->setMinimumSize(QSize(140, 20));
label_8->setMaximumSize(QSize(140, 20));
label_8->setContextMenuPolicy(Qt::NoContextMenu);
horizontalLayout_5->addWidget(label_8);
SocketClientNum_Label = new QLabel(page);
SocketClientNum_Label->setObjectName(QString::fromUtf8("SocketClientNum_Label"));
SocketClientNum_Label->setMinimumSize(QSize(50, 0));
SocketClientNum_Label->setMaximumSize(QSize(50, 20));
QFont font;
font.setFamily(QString::fromUtf8("Arial Black"));
SocketClientNum_Label->setFont(font);
horizontalLayout_5->addWidget(SocketClientNum_Label);
horizontalSpacer_6 = new QSpacerItem(140, 20, QSizePolicy::Maximum, QSizePolicy::Minimum);
horizontalLayout_5->addItem(horizontalSpacer_6);
verticalLayout_3->addLayout(horizontalLayout_5);
SocketLog_TextBrowser = new QTextBrowser(page);
SocketLog_TextBrowser->setObjectName(QString::fromUtf8("SocketLog_TextBrowser"));
SocketLog_TextBrowser->setMaximumSize(QSize(400, 200));
SocketLog_TextBrowser->setStyleSheet(QString::fromUtf8("background-color: rgba(232, 232, 232, 100);"));
verticalLayout_3->addWidget(SocketLog_TextBrowser);
horizontalLayout_3 = new QHBoxLayout();
horizontalLayout_3->setSpacing(6);
horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3"));
label_4 = new QLabel(MainWindow);
label_4 = new QLabel(page);
label_4->setObjectName(QString::fromUtf8("label_4"));
label_4->setMinimumSize(QSize(0, 20));
label_4->setMaximumSize(QSize(100, 20));
label_4->setMinimumSize(QSize(150, 20));
label_4->setMaximumSize(QSize(150, 20));
horizontalLayout_3->addWidget(label_4);
upflagLabel = new QLabel(MainWindow);
upflagLabel->setObjectName(QString::fromUtf8("upflagLabel"));
upflagLabel->setMinimumSize(QSize(70, 20));
upflagLabel->setMaximumSize(QSize(80, 20));
horizontalLayout_3->addWidget(upflagLabel);
horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalSpacer_3 = new QSpacerItem(150, 20, QSizePolicy::Maximum, QSizePolicy::Minimum);
horizontalLayout_3->addItem(horizontalSpacer_3);
verticalLayout->addLayout(horizontalLayout_3);
verticalLayout_3->addLayout(horizontalLayout_3);
resultTable = new QTableView(MainWindow);
Rfid_textBrowser = new QTextBrowser(page);
Rfid_textBrowser->setObjectName(QString::fromUtf8("Rfid_textBrowser"));
Rfid_textBrowser->setMaximumSize(QSize(400, 16777215));
Rfid_textBrowser->setStyleSheet(QString::fromUtf8("background-color: rgba(232, 232, 232, 100);"));
verticalLayout_3->addWidget(Rfid_textBrowser);
verticalLayout_7->addLayout(verticalLayout_3);
stackedWidget->addWidget(page);
page_2 = new QWidget();
page_2->setObjectName(QString::fromUtf8("page_2"));
verticalLayout_6 = new QVBoxLayout(page_2);
verticalLayout_6->setObjectName(QString::fromUtf8("verticalLayout_6"));
verticalLayout_6->setContentsMargins(0, 0, 0, 0);
horizontalLayout_6 = new QHBoxLayout();
horizontalLayout_6->setObjectName(QString::fromUtf8("horizontalLayout_6"));
verticalLayout_4 = new QVBoxLayout();
verticalLayout_4->setObjectName(QString::fromUtf8("verticalLayout_4"));
horizontalLayout_7 = new QHBoxLayout();
horizontalLayout_7->setSpacing(6);
horizontalLayout_7->setObjectName(QString::fromUtf8("horizontalLayout_7"));
label_6 = new QLabel(page_2);
label_6->setObjectName(QString::fromUtf8("label_6"));
label_6->setMinimumSize(QSize(0, 20));
label_6->setMaximumSize(QSize(100, 20));
horizontalLayout_7->addWidget(label_6);
upflagLabel = new QLabel(page_2);
upflagLabel->setObjectName(QString::fromUtf8("upflagLabel"));
upflagLabel->setMinimumSize(QSize(50, 20));
upflagLabel->setMaximumSize(QSize(50, 20));
horizontalLayout_7->addWidget(upflagLabel);
horizontalSpacer_7 = new QSpacerItem(180, 20, QSizePolicy::Maximum, QSizePolicy::Minimum);
horizontalLayout_7->addItem(horizontalSpacer_7);
verticalLayout_4->addLayout(horizontalLayout_7);
resultTable = new QTableView(page_2);
resultTable->setObjectName(QString::fromUtf8("resultTable"));
resultTable->setMinimumSize(QSize(220, 0));
resultTable->setMaximumSize(QSize(220, 16777215));
resultTable->setMaximumSize(QSize(400, 16777215));
resultTable->setStyleSheet(QString::fromUtf8(""));
verticalLayout->addWidget(resultTable);
verticalLayout_4->addWidget(resultTable);
horizontalLayout_2->addLayout(verticalLayout);
horizontalLayout_6->addLayout(verticalLayout_4);
verticalLayout_6->addLayout(horizontalLayout_6);
stackedWidget->addWidget(page_2);
horizontalLayout_2->addWidget(stackedWidget);
verticalLayout_2 = new QVBoxLayout();
verticalLayout_2->setSpacing(9);
verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
horizontalLayout_4 = new QHBoxLayout();
horizontalLayout_4->setObjectName(QString::fromUtf8("horizontalLayout_4"));
label_5 = new QLabel(MainWindow);
label_5 = new QLabel(centralwidget);
label_5->setObjectName(QString::fromUtf8("label_5"));
label_5->setMinimumSize(QSize(50, 20));
label_5->setMaximumSize(QSize(100, 20));
@ -214,47 +340,82 @@ public:
verticalLayout_2->addLayout(horizontalLayout_4);
textBrowser = new QTextBrowser(MainWindow);
textBrowser->setObjectName(QString::fromUtf8("textBrowser"));
textBrowser->setMinimumSize(QSize(700, 0));
QFont font;
font.setFamily(QString::fromUtf8("Arial"));
font.setPointSize(9);
font.setBold(false);
font.setWeight(50);
textBrowser->setFont(font);
textBrowser->setStyleSheet(QString::fromUtf8("background-color: rgba(232, 232, 232, 100);"));
Log_TextBrowser = new QTextBrowser(centralwidget);
Log_TextBrowser->setObjectName(QString::fromUtf8("Log_TextBrowser"));
Log_TextBrowser->setMinimumSize(QSize(650, 0));
Log_TextBrowser->setStyleSheet(QString::fromUtf8("background-color: rgba(232, 232, 232, 100);"));
verticalLayout_2->addWidget(textBrowser);
verticalLayout_2->addWidget(Log_TextBrowser);
horizontalLayout_2->addLayout(verticalLayout_2);
verticalLayout_3->addLayout(horizontalLayout_2);
verticalLayout->addLayout(horizontalLayout_2);
MainWindow->setCentralWidget(centralwidget);
menubar = new QMenuBar(MainWindow);
menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 1000, 22));
menubar->setStyleSheet(QString::fromUtf8(""));
menu = new QMenu(menubar);
menu->setObjectName(QString::fromUtf8("menu"));
menu->setStyleSheet(QString::fromUtf8("background-color: rgb(155, 208, 255);"));
run_model = new QMenu(menu);
run_model->setObjectName(QString::fromUtf8("run_model"));
MainWindow->setMenuBar(menubar);
statusbar = new QStatusBar(MainWindow);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
statusbar->setMouseTracking(false);
MainWindow->setStatusBar(statusbar);
menubar->addAction(menu->menuAction());
menu->addAction(run_model->menuAction());
menu->addSeparator();
menu->addAction(actionset);
menu->addSeparator();
menu->addAction(actionshibiefuzhu);
menu->addSeparator();
menu->addAction(actionchuankou);
run_model->addAction(relay);
run_model->addAction(identify);
retranslateUi(MainWindow);
stackedWidget->setCurrentIndex(0);
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
void retranslateUi(QWidget *MainWindow)
void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr));
MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "mainwindow", nullptr));
actionset->setText(QCoreApplication::translate("MainWindow", "\346\216\245\345\217\243\350\256\276\347\275\256", nullptr));
actionshibiefuzhu->setText(QCoreApplication::translate("MainWindow", "\344\270\262\345\217\243\350\256\276\347\275\256", nullptr));
actionchuankou->setText(QCoreApplication::translate("MainWindow", "\350\257\206\345\210\253\350\276\205\345\212\251", nullptr));
identify->setText(QCoreApplication::translate("MainWindow", "\350\257\206\345\210\253\346\250\241\345\274\217", nullptr));
relay->setText(QCoreApplication::translate("MainWindow", "\350\275\254\345\217\221\346\250\241\345\274\217", nullptr));
label->setText(QCoreApplication::translate("MainWindow", "\344\270\262\345\217\243\345\217\267:", nullptr));
label_2->setText(QCoreApplication::translate("MainWindow", "\346\263\242\347\211\271\347\216\207:", nullptr));
BTBox->setItemText(0, QCoreApplication::translate("MainWindow", "9600", nullptr));
BTBox->setItemText(1, QCoreApplication::translate("MainWindow", "19200", nullptr));
BTBox->setItemText(2, QCoreApplication::translate("MainWindow", "115200", nullptr));
label_3->setText(QCoreApplication::translate("MainWindow", "\350\202\241\351\201\223\345\220\215:", nullptr));
LEDlabel->setText(QString());
openComButton->setText(QCoreApplication::translate("MainWindow", "\346\211\223\345\274\200\344\270\262\345\217\243", nullptr));
LEDlabel->setText(QString());
testButton->setText(QCoreApplication::translate("MainWindow", "\346\265\213\350\257\225", nullptr));
label_4->setText(QCoreApplication::translate("MainWindow", "\350\257\206\345\210\253\347\273\223\346\236\234:", nullptr));
upflagLabel->setText(QCoreApplication::translate("MainWindow", "\344\270\215\344\270\212\344\274\240", nullptr));
label_8->setText(QCoreApplication::translate("MainWindow", "\345\256\242\346\210\267\347\253\257\351\223\276\346\216\245\346\225\260:", nullptr));
SocketClientNum_Label->setText(QCoreApplication::translate("MainWindow", "0", nullptr));
label_4->setText(QCoreApplication::translate("MainWindow", "\350\275\254\345\217\221\344\277\241\346\201\257:", nullptr));
label_6->setText(QCoreApplication::translate("MainWindow", "\350\257\206\345\210\253\347\273\223\346\236\234:", nullptr));
upflagLabel->setText(QCoreApplication::translate("MainWindow", "\344\270\215\344\274\240", nullptr));
label_5->setText(QCoreApplication::translate("MainWindow", "\346\227\245\345\277\227:", nullptr));
menu->setTitle(QCoreApplication::translate("MainWindow", "\350\256\276\347\275\256", nullptr));
run_model->setTitle(QCoreApplication::translate("MainWindow", "\350\257\206\345\210\253\346\250\241\345\274\217", nullptr));
#if QT_CONFIG(statustip)
statusbar->setStatusTip(QString());
#endif // QT_CONFIG(statustip)
} // retranslateUi
};

View File

@ -6,90 +6,63 @@
#include "ComDetect.h"
ComDetect::ComDetect()
{
this->serial_ = new QSerialPort;
}
ComDetect::~ComDetect()
{
this->serial_->deleteLater();
}
QSerialPort* ComDetect::openCom(const QString &com, int baud)
bool ComDetect::openCom(QSerialPort *serial, const QString &com, int baud)
{
try
{
this->serial_->setPortName(com);
serial->setPortName(com);
if (baud == 9600)
{
this->serial_->setBaudRate(QSerialPort::Baud9600);
serial->setBaudRate(QSerialPort::Baud9600);
}
else if (baud == 19200)
{
this->serial_->setBaudRate(QSerialPort::Baud19200);
serial->setBaudRate(QSerialPort::Baud19200);
}
else if (baud == 115200)
{
this->serial_->setBaudRate(QSerialPort::Baud115200);
serial->setBaudRate(QSerialPort::Baud115200);
}
else
{
this->serial_->setBaudRate(QSerialPort::Baud19200);
serial->setBaudRate(QSerialPort::Baud19200);
}
this->serial_->setParity(QSerialPort::NoParity);// 校验
this->serial_->setDataBits(QSerialPort::Data8); //数据位
this->serial_->setStopBits(QSerialPort::OneStop);//停止位停止位默认选择1位
this->serial_->setFlowControl(QSerialPort::NoFlowControl);// 控制流,默认选择无
this->serial_->setReadBufferSize(1024); // 设置读取的缓冲区1024字节
serial->setParity(QSerialPort::NoParity);// 校验
serial->setDataBits(QSerialPort::Data8); //数据位
serial->setStopBits(QSerialPort::OneStop);//停止位停止位默认选择1位
serial->setFlowControl(QSerialPort::NoFlowControl);// 控制流,默认选择无
serial->setReadBufferSize(1024); // 设置读取的缓冲区1024字节
if (this->serial_->open(QSerialPort::ReadWrite))
if (serial->open(QSerialPort::ReadWrite))
{
this->serial_->clear(QSerialPort::AllDirections);
this->serial_->setDataTerminalReady(true);
return this->serial_;
serial->clear(QSerialPort::AllDirections);
serial->setDataTerminalReady(true);
return true;
}
}
catch (const std::exception &e)
{
std::cout << e.what() << std::endl;
return nullptr;
}
return nullptr;
}
bool ComDetect::closeCom()
{
this->serial_->clear();
this->serial_->close();
return true;
}
[[deprecated("建议自行定义读取函数")]] void ComDetect::readCom()
{
try {
QByteArray data = this->serial_->readAll(); // 读取数据
if(!data.isEmpty())
{
// this->queue_->push(QString(data));
}
data.clear();
} catch(...) {
}
}
bool ComDetect::writeCom(const QString &str)
{
try
{
this->serial_->write(str.toUtf8());
}
catch (...)
{
return false;
}
return true;
return false;
}
bool ComDetect::closeCom(QSerialPort *serial)
{
serial->clear();
serial->close();
return true;
}

View File

@ -16,16 +16,14 @@ public:
ComDetect();
~ComDetect();
QSerialPort* openCom(const QString &com, int baud);
bool closeCom();
bool writeCom(const QString &str);
bool openCom(QSerialPort *serial, const QString &com, int baud);
bool closeCom(QSerialPort *serial);
private:
QSerialPort *serial_{};
MQueue<QString> *queue_{};
private slots:
[[deprecated("建议自行定义读取函数")]] void readCom();
// [[deprecated("建议自行定义读取函数")]] void readCom();
};

View File

@ -0,0 +1,542 @@
//
// Created by Mr.V on 2024/4/15.
//
#include "ReadComThread.h"
ReadComThread::ReadComThread(MQueue<TrainInfo> *queueTrainInfo,
MQueue<QString> *queueWarnInfo,
MQueue<QString> *queueRFID,
QObject *parent) :
QThread(parent)
{
// 配置文件读取
QString errorMessage = "";
if (!ConfigUtil::readBaseConfig(g_config_path, errorMessage, this->baseConfig_))
{
emit this->ErrorSignals(errorMessage);
}
if (!ConfigUtil::readSerialConfig(g_config_path, errorMessage, this->serialConfig_))
{
emit this->ErrorSignals(errorMessage);
}
if (!ConfigUtil::readSocketServerConfig(g_config_path, errorMessage, this->socketServerConfig_))
{
emit this->ErrorSignals(errorMessage);
}
if (!ConfigUtil::readDeviceWarnConfig(g_config_path, errorMessage, this->deviceWarnConfig_))
{
emit this->ErrorSignals(errorMessage);
}
this->queueTrainInfo_ = queueTrainInfo;
this->queueWarnInfo_ = queueWarnInfo;
this->queueRFID_ = queueRFID;
this->logRfidRecvName = "./Logs/rfid_data.txt";
this->recvLog.setFileName(logRfidRecvName);
this->recvLog.open(QIODevice::ReadWrite | QIODevice::Append);
timer_.setSingleShot(true);
connect(&timer_, &QTimer::timeout, this, &ReadComThread::tryToReconnect);
connect(this, &ReadComThread::getRfid_signals, this, &ReadComThread::getQueueDataThread);
connect(this, &ReadComThread::IdentifyType, this, &ReadComThread::IdentifyTypeUpdate);
connect(this, &ReadComThread::upRfid_signals, this, &ReadComThread::upRfid);
if (this->baseConfig_.useSocketServer)
{
// 创建线程
QThread *threadWork = new QThread; // 任务线程
this->tcpClient = new TcpClient(this);
this->tcpClient->moveToThread(threadWork);
connect(this, &ReadComThread::connect_socket, this->tcpClient, &TcpClient::connectToServer);
// 子线程反馈 socket 到主线程
connect(this->tcpClient, &TcpClient::socketComplete, this, [=](QTcpSocket* tcp, QString ip, quint16 port){
this->tcp_ = tcp;
});
// 接收子线程的消息提示
connect(this->tcpClient, &TcpClient::sendTcpInfoSignals, this, [=](const QString& info){
emit this->InfoSignals(info);
emit this->statusInfoUpdate(info);
if (info == "链接辅助识别服务超时"
|| info == "未连接辅助识别服务"
|| info == "链接辅助识别服务失败"
|| info == "辅助识别服务断开连接"
|| info == "链接辅助识别服务失败")
{
this->videoHasTrain = false;
}
});
// 接收子线程的TCP消息内容展示
connect(this->tcpClient, &TcpClient::getTcpInfoSignals, this, [=](const QString& info){
emit this->InfoSignals(info);
});
emit connect_socket(this->socketServerConfig_.server_ip, this->socketServerConfig_.server_port);
connect(this->tcpClient, &TcpClient::comeTrainSignals, this, [=](bool type) {
if (type)
{
emit this->InfoSignals("视频车号识别-来车了");
this->videoHasTrain = true;
emit IdentifyType();
}
else
{
emit this->InfoSignals("视频车号识别-火车离开了");
this->videoHasTrain = false;
if (this->needIdentify)
emit IdentifyType();
}
});
connect(this->tcpClient, &TcpClient::getDirectionSignals, this, [=](int direction) {
if (this->iDirection == 0)
{
emit this->InfoSignals("获得方向判定:" + QString(direction > -1 ? (direction > 0 ? "需识别" : "待定") : "无需上传"));
this->iDirection = direction;
}
});
}
}
[[noreturn]] void ReadComThread::run()
{
while (true)
{
QThread::msleep(10 * 1000);
// if (this->auto_reconnect_serial_)
// {
// QThread::msleep(10 * 1000);
// if ((this->serial_ == nullptr || !this->serial_->isOpen()))
// {
// this->openCom(true, 0);
// }
//
// }
}
}
void ReadComThread::openCom(const bool &type, const int &msec)
{
QThread::msleep(msec);
if (type)
{
this->auto_reconnect_serial_ = true;
this->serial_ = new QSerialPort(this);
if (this->comDetect_->openCom(this->serial_, this->serialConfig_.comName, this->serialConfig_.baud))
{
QString logs;
logs.append("串口打开成功\n");
logs.append("串口号:" + this->serialConfig_.comName + "\n");
logs.append("波特率:" + QString::number(this->serialConfig_.baud) + "\n");
if (this->serialConfig_.havaMagnetSteel)
logs.append("磁钢顺序:" + this->serialConfig_.magnetSteelOrder);
this->isOpenCom = true;
emit this->InfoSignals(logs);
connect(this->serial_,&QSerialPort::readyRead,this,&ReadComThread::readCom); //
connect(this->serial_, &QSerialPort::errorOccurred, this, &ReadComThread::serialPort_error);
emit this->openComSuccess(true);
this->timer_.stop();
this->initParam();
}
else
{
this->comDetect_->closeCom(this->serial_);
this->isOpenCom = false;
emit this->ErrorSignals("串口打开失败!");
emit this->openComSuccess(false);
this->timer_.start(10*1000);
}
}
else
{
this->auto_reconnect_serial_ = false;
if (this->comDetect_->closeCom(this->serial_))
{
this->initParam();
emit this->InfoSignals("串口已关闭!");
emit this->closeComSuccess(true);
}
else
{
emit this->closeComSuccess(false);
}
}
}
void ReadComThread::tryToReconnect()
{
if (this->auto_reconnect_serial_)
this->openCom(true);
}
void ReadComThread::readCom()
{
try {
if (this->serial_->waitForReadyRead(10)) {
QByteArray data = this->serial_->readAll(); // 读取数据
if(!data.isEmpty())
{
this->queue_.push(QString(data));
emit getRfid_signals();
}
data.clear();
}
else
{
emit this->ErrorSignals("等待读取超时");
}
} catch(...) {
emit this->ErrorSignals("读取串口数据异常!");
}
}
void ReadComThread::readTestInfo(const QString &filePath) {
// 创建一个QFile对象并打开要读取的文本文件
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
emit this->ErrorSignals("无法打开测试文件:" + filePath);
return;
}
emit this->InfoSignals("开始读取测试数据...");
// 将文件内容读入到QStringList中
QTextStream in(&file);
while(!in.atEnd()) {
QString line = in.readLine();
this->queue_.push(line);
emit getRfid_signals();
}
// 关闭文件
file.close();
emit this->InfoSignals("---读取测试数据完毕---");
}
/**
* @brief:queue中获取数据
* @param:
* @return:
*/
void ReadComThread::getQueueDataThread()
{
if (this->queue_.isEmpty()) return;
QString strRfidInfo = this->queue_.getTop();
this->queue_.pop();
this->saveRfidLog(strRfidInfo);
auto split_lambda = [=](const QString& strFirst, const QString& strOther){
if (strFirst == "0")
{
this->rfidHasTrain = false;
emit this->InfoSignals("RFID-火车离开了");
// 关功放信号
// 需要结合 “来车状态”广播消息,确认是否真的车离开了; TODO:没有真离开,则向串口发送 @on& 避免关功放
emit IdentifyType();
}
else
{
// TODO: 此处按照4个磁钢来配置可能存在一定限制; 另外逻辑需要优化
if (strOther == "000000" // 第一次检测来车时(前提是上一次功放已关闭)
&& (strFirst == this->serialConfig_.magnetSteelOrder.left(1)
|| strFirst == this->serialConfig_.magnetSteelOrder.mid(1, 1)))
{
this->rfidHasTrain = true;
emit this->InfoSignals("RFID-来车了");
emit IdentifyType();
}
}
};
if (this->baseConfig_.runModel == ai_matrix::IDENTIFY_MODEL)
{
this->tmpRfid.append(strRfidInfo);
if (this->tmpRfid.right(1) != "&")
{
return;
}
this->tmpRfid = this->tmpRfid.replace("&", "");
QStringList rfidSubList = this->tmpRfid.split("@");
this->tmpRfid = "";
for (const auto & i : rfidSubList)
{
if (i.size() == 26 || i.size() == 24)
{
// 车厢信息
QString strTrainInfo = i.mid(1,13);
if (vecTrain.empty() || !vecTrain.contains(strTrainInfo))
{
// 判断是否是车头 车头的第14位是 K或H (慎重)
if (!i.mid(14, 1).contains(QRegExp("^[0-9]+$"))) continue;
// 过滤掉车号中有非数字的
// if (!strTrainInfo.right(7).contains(QRegExp("^[0-9]+$"))) continue;
// 因信号不稳定 增加一行过滤 出现读到的编号数据里 空格替代了实际字符的情况
// if (strTrainInfo.right(7).simplified().size() < 7) continue;
vecTrain.append(strTrainInfo);
int train_order = vecTrain.size();
// this->resultTableModel_->setItem(train_order - 1, 0, new QStandardItem(strTrainInfo));
emit this->addResultSignals(strTrainInfo);
emit this->InfoSignals(QString("第%1节 %2").arg(train_order).arg(strTrainInfo));
// 将接收到的RFID使用@符拼接起来以待后续上传web
this->rfidSourceInfo.append("@" + i);
QString rfidinfo = this->rfidSourceInfo;
this->rfidSourceInfo = "";
emit upRfid_signals(rfidinfo);
}
}
else if (i.size() == 7)
{
// 不使用磁钢的情况下 过滤掉磁钢信号
if (!this->serialConfig_.havaMagnetSteel) continue;
// 磁钢信号
QString strFirst = i.left(1);
QString strOther = i.mid(1, i.size() - 1);
// 将接收到的RFID使用@符拼接起来以待后续上传web
this->rfidSourceInfo.append("@" + i);
split_lambda(strFirst, strOther);
}
else if (i.size() == 14) // 特殊情况,来车信号少了&符
{
// 不使用磁钢的情况下 过滤掉磁钢信号
if (!this->serialConfig_.havaMagnetSteel) continue;
for (int j = 0; j < i.size(); j+=7) {
QString rfid_cg = i.mid(j, 7);
QString strFirst = rfid_cg.left(1);
QString strOther = rfid_cg.mid(1, 6);
// 将接收到的RFID使用@符拼接起来以待后续上传web
this->rfidSourceInfo.append("@" + rfid_cg);
split_lambda(strFirst, strOther);
}
}
}
}
else if (this->baseConfig_.runModel == ai_matrix::RELAY_MODEL)
{
this->queueRFID_->push(strRfidInfo);
this->tmpRfid.append(strRfidInfo);
if (this->tmpRfid.right(1) != "&")
{
return;
}
this->tmpRfid = this->tmpRfid.replace("&", "");
QStringList rfidSubList = this->tmpRfid.split("@");
this->tmpRfid = "";
for (const auto & i : rfidSubList)
{
if (i.size() == 7)
{
// 不使用磁钢的情况下 过滤掉磁钢信号
if (!this->serialConfig_.havaMagnetSteel) continue;
// 磁钢信号
QString strFirst = i.left(1);
QString strOther = i.mid(1, i.size() - 1);
split_lambda(strFirst, strOther);
}
}
}
}
void ReadComThread::IdentifyTypeUpdate() {
if (this->rfidHasTrain || this->videoHasTrain)
{
if (!this->needIdentify)
{
emit this->InfoSignals("来车了");
this->mkRfidLog();
this->vecTrain.clear();
this->needIdentify = true;
this->trainTime = this->getSystemTime();
emit this->comeTrain(false);
}
}
else if (!this->rfidHasTrain && !this->videoHasTrain)
{
if (this->vecTrain.size() < this->deviceWarnConfig_.min_train_size
&& this->iDirection > 0
&& (this->rfidSourceInfo.size() > 192 || this->vecTrain.size() > 1))
this->queueWarnInfo_->push("火车驶过疑似RFID设备故障读取到的车厢号有丢失");
this->initParam();
emit this->InfoSignals("火车离开了");
}
}
void ReadComThread::upRfid(const QString &rfidInfo)
{
if (!this->baseConfig_.upResult) return;
if (!this->needIdentify && this->serialConfig_.havaMagnetSteel)
{
emit upResultType(false);
return;
}else{
emit upResultType(true);
}
QString info = this->vecTrain.back();
int order = this->vecTrain.size();
if (order > this->socketServerConfig_.delayed_upload && this->iDirection == 0)
{
this->iDirection = 1;
}
if (!this->baseConfig_.useSocketServer) this->iDirection = 1;
TrainInfo trainInfo;
trainInfo.carriageType = info.left(6).simplified().toStdString();
trainInfo.carriageNum = info.mid(6, info.size() - 6).simplified().toStdString();
trainInfo.strOrder = QString::number(order).toStdString();
trainInfo.trainTime = this->trainTime.toStdString();
trainInfo.collectTime = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz").toStdString();
trainInfo.strRfidInfo = rfidInfo.toStdString();
this->queueTmpTrainInfo_.push(trainInfo);
if (this->iDirection < 0)
{
this->queueTmpTrainInfo_.clear();
return;
}
if (this->iDirection > 0)
{
while (!this->queueTmpTrainInfo_.isEmpty())
{
this->queueTrainInfo_->push(this->queueTmpTrainInfo_.pop());
}
}
}
void ReadComThread::updateRunModel(int model)
{
this->baseConfig_.runModel = model;
}
bool ReadComThread::mkRfidLog()
{
try {
QFileInfo fileInfo(this->logRfidRecvName);
if(fileInfo.isFile())
{
return true;
}
this->recvLog.setFileName(this->logRfidRecvName);
if (!this->recvLog.isOpen())
{
this->recvLog.open(QIODevice::ReadWrite | QIODevice::Append);
}
return true;
} catch (const std::exception &e) {
emit this->ErrorSignals("创建、打开RFID原始数据日志文件失败,详细:");
emit this->ErrorSignals(e.what());
}
return false;
}
void ReadComThread::saveRfidLog(const QString &value)
{
try {
QString logValue = value + "\n";
if (!this->recvLog.isOpen())
{
this->recvLog.open(QIODevice::ReadWrite | QIODevice::Append);
}
this->recvLog.write(logValue.toUtf8());
this->recvLog.flush();
} catch (const std::exception &e) {
emit this->ErrorSignals("保存RFID原数据失败");
}
}
bool ReadComThread::rnameRfidLog()
{
try {
this->recvLog.close();
QFile logFile(this->logRfidRecvName);
QFileInfo fileInfo(logFile);
if (fileInfo.size() == 0) return false;
QString newLogFileName = fileInfo.path() + "/";
newLogFileName.append(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss"));
newLogFileName.append(".txt");
if (!logFile.rename(newLogFileName))
{
emit this->ErrorSignals("读取RFID原始数据存储重命名失败");
return false;
}
this->deleteOldFiles(fileInfo.path(), 3);
} catch (const std::exception &e) {
emit this->ErrorSignals("读取RFID原始数据存储重命名失败");
return false;
}
return true;
}
void ReadComThread::deleteOldFiles(const QString &path, int days)
{
QDir dir(path);
foreach(QFileInfo fi, dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot))
{
if((fi.lastModified().addDays(days) < QDateTime::currentDateTime()))
{
QFile::remove(fi.absoluteFilePath());
}
}
}
/**
* 退
* @param error
*/
void ReadComThread::serialPort_error(QSerialPort::SerialPortError error)
{
if (error != QSerialPort::NoError)
{
//关闭串口
this->serial_->close();
emit this->ErrorSignals("串口异常退出,疑似接口松动;10秒后自动尝试重连...");
emit this->openComSuccess(false);
this->timer_.start(10*1000);
}
}
void ReadComThread::initParam() {
if (this->recvLog.isOpen()) this->recvLog.close();
this->rfidSourceInfo = "";
this->vecTrain.clear();
this->rnameRfidLog();
this->queue_.clear();
this->trainTime = "";
this->needIdentify = false;
this->rfidHasTrain = false;
this->videoHasTrain = false;
this->iDirection = 0;
}
/**
* @brief:
* @param
* @return:
*/
QString ReadComThread::getSystemTime()
{
return QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
}

118
src/threads/ReadComThread.h Normal file
View File

@ -0,0 +1,118 @@
//
// Created by Mr.V on 2024/4/15.
//
#ifndef TRAIN_RFID_READCOMTHREAD_H
#define TRAIN_RFID_READCOMTHREAD_H
#include <QThread>
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort>
#include "MQueue.h"
#include "common.h"
#include "ComDetect.h"
#include "TcpClient.h"
#include "ConfigUtil.h"
using namespace ai_matrix;
class ReadComThread : public QThread{
Q_OBJECT
public:
ReadComThread(MQueue<TrainInfo> *queueTrainInfo,
MQueue<QString> *queueWarnInfo,
MQueue<QString> *queueRFID,
QObject *parent = nullptr);
~ReadComThread() {};
[[noreturn]] void run() override;
private:
MQueue<TrainInfo> *queueTrainInfo_ = nullptr;
MQueue<QString> *queueRFID_ = nullptr;
MQueue<QString> *queueWarnInfo_ = nullptr;
MQueue<TrainInfo> queueTmpTrainInfo_{}; // RFID临时信息队列
QSerialPort *serial_; //串口
bool auto_reconnect_serial_ = false;
QTimer timer_;
ai_matrix::BaseConfig baseConfig_;
ai_matrix::SerialConfig serialConfig_;
ai_matrix::SServerConfig socketServerConfig_;
ai_matrix::DeviceWarnConfig deviceWarnConfig_;
TcpClient* tcpClient;
QTcpSocket* tcp_ = nullptr;
// Com口数据读取类
ComDetect *comDetect_;
// 打开com口标志
bool isOpenCom = false;
QString logRfidRecvName;
QFile recvLog;
QString trainTime;
// 是否是需要识别的方向 -1:不识别 0:未确定 1:识别
int iDirection = 0;
// 整列车识别结果存储
QStringList vecTrain;
QString rfidSourceInfo;
QString tmpRfid; //临时存储的RFID原始数据用于防止接收的数据不完整
// RFID读取的数据队列
MQueue<QString> queue_ = {};
// 识别方向正确标志
bool needIdentify = false;
// RFID识别有火车标志
bool rfidHasTrain = false;
// 视频识别有火车标志使用socket服务时才有用
bool videoHasTrain = false;
void initParam();
// 创建日志目录
bool mkRfidLog();
void deleteOldFiles(const QString &path, int days);
bool rnameRfidLog();
void saveRfidLog(const QString &value);
QString getSystemTime();
signals:
void DebugSignals(const QString &info);
void InfoSignals(const QString &info);
void WarnSignals(const QString &info);
void ErrorSignals(const QString &info);
void statusInfoUpdate(const QString &info);
void connect_socket(QString ip, int port);
void openComSuccess(const bool &success);
void closeComSuccess(const bool &success);
void upResultType(const bool &type);
void addResultSignals(const QString &trainInfo);
void comeTrain(const bool &type);
void getRfid_signals();
void upRfid_signals(const QString &rfidInfo);
void IdentifyType();
public slots:
void openCom(const bool &type, const int &msec = 0);
void readCom();
void serialPort_error(QSerialPort::SerialPortError error);
void getQueueDataThread();
void IdentifyTypeUpdate();
void upRfid(const QString &rfidInfo);
void tryToReconnect();
void updateRunModel(int model);
void readTestInfo(const QString &filePath);
};
#endif //TRAIN_RFID_READCOMTHREAD_H

View File

@ -0,0 +1,135 @@
//
// Created by Mr.V on 2024/4/3.
//
#include "RelayRfidThread.h"
RelayRfidThread::RelayRfidThread(MQueue<QString> *queueRFID, QObject *parent) :
QThread(parent)
{
this->queueRFID_ = queueRFID;
// 配置文件读取
QString errorMessage = "";
if (!ConfigUtil::readRelayConfig(g_config_path, errorMessage, this->relayConfig_))
{
emit this->ErrorSignals(errorMessage);
}
this->server_ = new QTcpServer();
//关联客户端连接信号newConnection
connect(this->server_, &QTcpServer::newConnection, this, &RelayRfidThread::newConnection); //连接客户端
//启动服务器监听
this->server_->listen(QHostAddress::Any, this->relayConfig_.listener_port);
this->server_->setMaxPendingConnections(2);
}
void RelayRfidThread::newConnection()
{
QTcpSocket *socket = new QTcpSocket();
socket = this->server_->nextPendingConnection();
this->vec_sockets_.push_back(socket);
emit this->ConnectInfoSignals("客户端" + socket->peerAddress().toString() + " 建立了链接");
emit this->update_client_num(1);
connect(socket, &QTcpSocket::readyRead, this, &RelayRfidThread::receive_info);
connect(socket, &QTcpSocket::disconnected, this, &RelayRfidThread::disconnection);
// connect(socket,
// SIGNAL(stateChanged(QAbstractSocket::SocketState)),
// this,
// SLOT(socketStateChange(QAbstractSocket::SocketState)));
}
void RelayRfidThread::receive_info() {
// try {
// //可以实现同时读取多个客户端发送过来的消息
// QTcpSocket *obj = (QTcpSocket*)sender();
// if (!obj->waitForReadyRead(100))
// {
// return;
// }
// QString msg = obj->readLine(512); //obj->readAll();
//
// if (!msg.contains("matrixai"))
// emit this->InfoSignals(obj->peerAddress().toString() + "客户端: " + msg);
// } catch (const QException &e) {
// emit this->WarnSignals("Caught exception:" + QString::fromStdString(e.what()));
// }
}
bool RelayRfidThread::send_Info(const QString &msg)
{
for(auto & socket : vec_sockets_)
{
if (socket->state() == QTcpSocket::ConnectedState)
{
socket->write(msg.toUtf8().data());
if (!socket->waitForBytesWritten(1000)) { // 等待1000毫秒
emit this->WarnSignals("" + socket->peerAddress().toString() + "转发失败:" + msg);
}
}
}
emit this->RfidInfoSignals(msg);
return true;
}
void RelayRfidThread::disconnection()
{
QTcpSocket *obj = (QTcpSocket*)sender();//掉线对象
emit this->ConnectInfoSignals("客户端" + obj->peerAddress().toString() + " 断开链接");
emit this->update_client_num(-1);
}
void RelayRfidThread::socketStateChange(QAbstractSocket::SocketState state)
{
QTcpSocket *obj = (QTcpSocket*)sender();
switch (state) {
case QAbstractSocket::UnconnectedState:
emit this->ConnectInfoSignals(obj->peerAddress().toString() + "UnconnectedState");
break;
case QAbstractSocket::ConnectedState:
emit this->ConnectInfoSignals(obj->peerAddress().toString() + "ConnectedState");
break;
case QAbstractSocket::ConnectingState:
emit this->ConnectInfoSignals(obj->peerAddress().toString() + "ConnectingState");
break;
case QAbstractSocket::HostLookupState:
emit this->ConnectInfoSignals(obj->peerAddress().toString() + "HostLookupState");
break;
case QAbstractSocket::ClosingState:
emit this->ConnectInfoSignals(obj->peerAddress().toString() + "ClosingState");
break;
case QAbstractSocket::ListeningState:
emit this->ConnectInfoSignals(obj->peerAddress().toString() + "ListeningState");
break;
case QAbstractSocket::BoundState:
emit this->ConnectInfoSignals(obj->peerAddress().toString() + "BoundState");
break;
default:
break;
}
}
[[noreturn]] void RelayRfidThread::run()
{
while (true)
{
// emit this->InfoSignals("开启监听->" + QString::number(this->relayConfig_.listener_port));
if (!queueRFID_->isEmpty())
{
QString msg = queueRFID_->getTop();
this->send_Info(msg);
queueRFID_->pop();
QThread::msleep(1);
}
else
{
QThread::msleep(20);
}
}
}

View File

@ -0,0 +1,64 @@
//
// Created by Mr.V on 2024/4/3.
//
#ifndef TRAIN_RFID_RELAYRFIDTHREAD_H
#define TRAIN_RFID_RELAYRFIDTHREAD_H
#include <QThread>
#include "common.h"
#include "MQueue.h"
#include "httplib.h"
#include "json.h"
#include "ConfigUtil.h"
using namespace ai_matrix;
class RelayRfidThread : public QThread {
Q_OBJECT
public:
~RelayRfidThread() {};
RelayRfidThread(MQueue<QString> *queueRFID, QObject *parent = nullptr);
[[noreturn]] void run() override;
private:
MQueue<QString> *queueRFID_ = nullptr;
ai_matrix::RelayConfig relayConfig_{};
QTcpServer *server_;
QVector<QTcpSocket *> vec_sockets_;
bool send_Info(const QString &msg);
bool getToken();
signals:
void DebugSignals(const QString &info);
void InfoSignals(const QString &info);
void WarnSignals(const QString &info);
void ErrorSignals(const QString &info);
void ConnectInfoSignals(const QString &info);
void update_client_num(int num);
void RfidInfoSignals(const QString &info);
private slots:
void newConnection();
void receive_info();
void disconnection();
void socketStateChange(QAbstractSocket::SocketState state);
};
#endif //TRAIN_RFID_RELAYRFIDTHREAD_H

View File

@ -5,11 +5,10 @@
#include "UpResultThread.h"
UpResultThread::UpResultThread(MQueue<TrainInfo> *queueTrainInfo, int *iDirection, QObject *parent) :
UpResultThread::UpResultThread(MQueue<TrainInfo> *queueTrainInfo, QObject *parent) :
QThread(parent)
{
this->queueTrainInfo_ = queueTrainInfo;
this->iDirection = iDirection;
// 配置文件读取
QString errorMessage = "";

View File

@ -19,13 +19,12 @@ class UpResultThread : public QThread{
public:
~UpResultThread() {};
UpResultThread(MQueue<TrainInfo> *queueTrainInfo, int *iDirection, QObject *parent = nullptr);
UpResultThread(MQueue<TrainInfo> *queueTrainInfo, QObject *parent = nullptr);
void run() override;
private:
MQueue<TrainInfo> *queueTrainInfo_ = nullptr;
int *iDirection;
ai_matrix::BaseConfig baseConfig_;
ai_matrix::InterfaceConfig interfaceConfig_;
std::string webToken; //授权信息

View File

@ -0,0 +1,204 @@
//
// Created by Mr.V on 2024/4/3.
//
#include "UpWarnThread.h"
UpWarnThread::UpWarnThread(MQueue<QString> *queueWarnInfo, QObject *parent) :
QThread(parent)
{
this->queueWarnInfo_ = queueWarnInfo;
// 配置文件读取
QString errorMessage = "";
if (!ConfigUtil::readBaseConfig(g_config_path, errorMessage, this->baseConfig_))
{
emit this->ErrorSignals(errorMessage);
}
if (!ConfigUtil::readInterfaceConfig(g_config_path, errorMessage, this->interfaceConfig_))
{
emit this->ErrorSignals(errorMessage);
}
}
void UpWarnThread::run()
{
while (true)
{
while (!this->queueWarnInfo_->isEmpty())
{
QString info = this->queueWarnInfo_->pop();
if (!this->upWarn(info))
{
}
}
QThread::sleep(1);
}
}
/**
* @brief:Http发送RFID设备异常
* @paraminfoRFID的原始数据
* @return: :true
* :false
*/
bool UpWarnThread::upWarn(const QString &info)
{
try {
Json::Value arrayObj; //构建对象
arrayObj["tainsModule"] = "2";
arrayObj["networkStatus"] = "正常";
arrayObj["devName"] = "RFID设备";
arrayObj["devSn"] = this->baseConfig_.trackName + "股道";
arrayObj["cpuData"] = "";
arrayObj["memoryUsage"] = "";
arrayObj["devRunningStatus"] = "异常";
arrayObj["devCheckResult"] = info.toStdString();
arrayObj["devIp"] = "";
arrayObj["devAccount"] = "";
Json::Value trainParams;
trainParams["poundNo"] = std::to_string(this->baseConfig_.trackName);
arrayObj["trainParams"] = trainParams;
Json::StreamWriterBuilder writer;
std::string str = Json::writeString(writer, arrayObj);
this->WarnSignals("根据RFID反馈的信号判断疑似丢失车厢磁条标签。已发送web: " + QString::fromStdString(str));
httplib::Client cli(this->interfaceConfig_.httpIp.toStdString(), this->interfaceConfig_.httpPort);
cli.set_connection_timeout(3, 0);
cli.set_read_timeout(3, 0);
httplib::Headers header;
httplib::Params params;
header.emplace("blade-auth", this->webToken);
header.emplace("charset", "utf-8");
//header.emplace("Content-Type", "application/json");
auto res = cli.Post(this->interfaceConfig_.upWarningPath.toStdString(), header, str, "application/json");
if (res)
{
if (res->status == 200)
{
emit this->InfoSignals("反馈报警信息web返回: " + QString::fromStdString(res->body));
Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body);
Json::Value root;
std::string errs;
bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
if (parsingSuccessful)
{
if (root["success"].asBool())
{
return true;
}
else
{
if (root["msg"].asString() == "请求未授权") {
emit this->WarnSignals("反馈报警信息因请求未授权而上传识别结果失败重新请求token。");
if (!this->getToken()) return false;
return this->upWarn(info);
}
emit this->ErrorSignals("报警信息上传失败,原因:" + QString::fromStdString(root["msg"].asString()));
}
}
else
{
emit this->ErrorSignals("报警信息上传失败返回数据解析异常返回数据非json" + QString::fromStdString(res->body));
}
}
else
{
emit this->ErrorSignals("报警信息上传失败,原因:" + QString::number(res->status) + " - " + QString::fromStdString(res->body));
if (res->status == 401) {
emit this->WarnSignals("报警信息上传失败重新请求token。");
this->getToken();
return this->upWarn(info);
}
}
}
else
{
emit this->ErrorSignals("报警信息,上传数据失败,请检查网络,或者上传地址!");
}
}
catch (std::exception &e)
{
emit this->ErrorSignals("报警信息,上传识别结果失败,原因:" + QString::fromStdString(e.what()));
}
return false;
}
/**
* @brief:Http获取授权
* @param
* @return:
*/
bool UpWarnThread::getToken()
{
try
{
httplib::Client cli(this->interfaceConfig_.httpIp.toStdString(), this->interfaceConfig_.httpPort);
cli.set_connection_timeout(0, 300 * 1000);
cli.set_read_timeout(0,300*1000);
httplib::Headers header;
httplib::Params params;
header.emplace("Authorization", "Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0");
params.emplace("username", this->interfaceConfig_.username.toStdString());
params.emplace("password", this->interfaceConfig_.password.toStdString());
params.emplace("tenantId", "000000");
params.emplace("grant_type", "password");
auto res = cli.Post("/api/blade-auth/oauth/token", header, params);
if (res)
{
if (res->status == 200)
{
Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body);
Json::Value root;
std::string errs;
bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
if (parsingSuccessful)
{
if (!root.get("token_type", "").asString().empty())
{
this->webToken = root["token_type"].asString();
this->webToken.append(" ");
this->webToken.append(root["access_token"].asString());
emit this->InfoSignals("已获取到web token");
return true;
}
else
{
emit this->ErrorSignals("获取web token失败原因" + QString::fromStdString(res->body));
}
}
else
{
emit this->ErrorSignals("获取web token返回数据解析异常返回数据非json。详细" + QString::fromStdString(res->body));
}
}
}
else
{
auto err = res.error();
// if (err == httplib::Error::Connection) {
// std::cout << " (连接出错)" << std::endl;
// }
emit this->ErrorSignals("获取web token失败请检查网络或请求地址。详细" + QString::fromStdString(to_string(err)));
}
}
catch (std::exception &e)
{
emit this->ErrorSignals("获取授权失败,原因:" + QString::fromStdString(e.what()));
}
return false;
}

View File

@ -0,0 +1,43 @@
//
// Created by Mr.V on 2024/4/3.
//
#ifndef TRAIN_RFID_UPWARNTHREAD_H
#define TRAIN_RFID_UPWARNTHREAD_H
#include <QThread>
#include "common.h"
#include "MQueue.h"
#include "httplib.h"
#include "json.h"
#include "ConfigUtil.h"
using namespace ai_matrix;
class UpWarnThread : public QThread{
Q_OBJECT
public:
~UpWarnThread() {};
UpWarnThread(MQueue<QString> *queueWarnInfo, QObject *parent = nullptr);
void run() override;
private:
MQueue<QString> *queueWarnInfo_ = nullptr;
ai_matrix::BaseConfig baseConfig_;
ai_matrix::InterfaceConfig interfaceConfig_;
std::string webToken; //授权信息
bool upWarn(const QString &info);
bool getToken();
signals:
void DebugSignals(const QString &info);
void InfoSignals(const QString &info);
void WarnSignals(const QString &info);
void ErrorSignals(const QString &info);
};
#endif //TRAIN_RFID_UPWARNTHREAD_H