1、更新socket辅助控制是否来车

2、新增测试版,直接读取生成的原始数据日志进行测试
This commit is contained in:
Mr.V 2024-03-14 21:14:36 +08:00
parent 7e2e063347
commit 4e7614f93d
13 changed files with 524 additions and 183 deletions

View File

@ -0,0 +1,20 @@
[base]
com_name=COM2
baud=19200
track_name=2
have_magnet_steel=true
magnet_steel_order=8421
up_result=false
use_socket_server=true
[interface]
http_ip=192.168.137.104
http_port=20004
token_path=/api/token_path
up_result_path=/api/train-carriage/identification/rfid-save
username=guest_01
password=d55b0f642e817eea24725d2f2a31dd08
[socket_server]
server_ip=172.24.192.1
server_port=60001

View File

@ -4,7 +4,8 @@ baud=19200
track_name=2 track_name=2
have_magnet_steel=true have_magnet_steel=true
magnet_steel_order=8421 magnet_steel_order=8421
up_result=true up_result=false
use_socket_server=true
[interface] [interface]
http_ip=192.168.137.104 http_ip=192.168.137.104
@ -13,3 +14,7 @@ token_path=/api/token_path
up_result_path=/api/train-carriage/identification/rfid-save up_result_path=/api/train-carriage/identification/rfid-save
username=guest_01 username=guest_01
password=d55b0f642e817eea24725d2f2a31dd08 password=d55b0f642e817eea24725d2f2a31dd08
[socket_server]
server_ip=172.24.192.1
server_port=60001

View File

@ -26,6 +26,7 @@ bool ConfigUtil::readBaseConfig(const QString &configFile, QString &errorMessage
config.havaMagnetSteel = mset->value("have_magnet_steel", false).toBool(); config.havaMagnetSteel = mset->value("have_magnet_steel", false).toBool();
config.magnetSteelOrder = mset->value("magnet_steel_order", "").toString(); config.magnetSteelOrder = mset->value("magnet_steel_order", "").toString();
config.upResult = mset->value("up_result", false).toBool(); config.upResult = mset->value("up_result", false).toBool();
config.useSocketServer = mset->value("use_socket_server", false).toBool();
mset->endGroup(); mset->endGroup();
} catch (const std::exception &e) { } catch (const std::exception &e) {
@ -58,4 +59,25 @@ bool ConfigUtil::readInterfaceConfig(const QString &configFile, QString &errorMe
return false; return false;
} }
return true; return true;
}
bool ConfigUtil::readSocketServerConfig(const QString &configFile, QString &errorMessage,
ai_matrix::SServerConfig &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("socket_server");
config.server_ip = mset->value("server_ip", "").toString();
config.server_port = mset->value("server_port", "").toInt();
mset->endGroup();
} catch (const std::exception &e) {
errorMessage = e.what();
return false;
}
return true;
} }

View File

@ -21,6 +21,8 @@ namespace ai_matrix {
QString magnetSteelOrder; QString magnetSteelOrder;
// 上传识别结果标志 // 上传识别结果标志
bool upResult; bool upResult;
// 使用socket来车通讯
bool useSocketServer;
}; };
struct InterfaceConfig { struct InterfaceConfig {
@ -38,6 +40,13 @@ namespace ai_matrix {
// 密码 // 密码
QString password; QString password;
}; };
struct SServerConfig {
// socket server IP
QString server_ip;
// server_port
int server_port;
};
}; };
class ConfigUtil { class ConfigUtil {
@ -47,6 +56,7 @@ public:
static bool readBaseConfig(const QString& configFile, QString &errorMessage, ai_matrix::BaseConfig &config); static bool readBaseConfig(const QString& configFile, QString &errorMessage, ai_matrix::BaseConfig &config);
static bool readInterfaceConfig(const QString& configFile, QString &errorMessage, ai_matrix::InterfaceConfig &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);
}; };

View File

@ -16,7 +16,6 @@
#include <QString> #include <QString>
#include "Log.h" #include "Log.h"
#include "StringUtil.h" #include "StringUtil.h"
extern QString io_car;
extern QString direction;
#endif //TRAIN_RFID_COMMON_H #endif //TRAIN_RFID_COMMON_H

View File

@ -1,93 +1,123 @@
#include "TcpClient.h" #include "TcpClient.h"
//#include "mainWindow.h" //#include "mainWindow.h"
TcpClient::TcpClient(QObject *parent) TcpClient::TcpClient(QObject *parent)
: QObject(parent) : QObject(parent)
{ {
m_heartbeatTimer = new QTimer(this); //心跳包定时器 connect(this, &TcpClient::restartSocket, this, &TcpClient::connectToServer);
connect(&m_tcpSocket, &QTcpSocket::readyRead, this, &TcpClient::onReadyRead);
connect(m_heartbeatTimer, &QTimer::timeout, this, &TcpClient::sendHeartbeat);//心跳包
connect(&m_tcpSocket, &QTcpSocket::connected, this, &TcpClient::handleConnected);
connect(&m_tcpSocket, &QTcpSocket::disconnected, this, &TcpClient::handleDisconnected);
} }
void TcpClient::connectToServer(const QString &host, int port) void TcpClient::connectToServer(QString ip, int port) {
{ try {
m_host = host;
m_port = port;
m_tcpSocket.connectToHost(host,port); // Replace with actual server IP and port
} this->ip_ = ip;
this->port_ = port;
this->tcp_ = new QTcpSocket;
this->heartbeatTimer_ = new QTimer(this); //心跳包定时器
QAbstractSocket::SocketState state = this->tcp_->state();
void TcpClient::onReadyRead() if(QAbstractSocket::UnconnectedState == state) {
{ emit sendTcpInfoSignals("未连接Socket服务器");
}
QByteArray jsonData = m_tcpSocket.readAll(); this->tcp_->connectToHost(ip, port); // Replace with actual server IP and port
// qDebug()<< jsonData <<Qt::endl;
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonData);
if ( jsonDocument.isObject()) {
QJsonObject jsonObject = jsonDocument.object();
QString t = jsonObject["cometime"].toString();
io_car = jsonObject["type"].toString();
direction = jsonObject["direction"].toString();
qDebug() << "direction" << direction << "\n";
if((io_car !="0" && io_car!="1") ||(direction != "0" && direction !="1" && direction !="2") )
{
QJsonObject jsonObject;
jsonObject["success"] ="false";
jsonObject["err_msg"] = "type or direction value is err...";
QJsonDocument jsonDocument(jsonObject);
QByteArray jsonData = jsonDocument.toJson();
m_tcpSocket.write(jsonData); if(QAbstractSocket::ConnectingState == this->tcp_->state()) {
} emit sendTcpInfoSignals("正在连接Socket服务器...");
else }
{ if (!this->tcp_->waitForConnected(2000))
QJsonObject jsonObject; {
jsonObject["success"] = "true"; emit sendTcpInfoSignals("链接服务端超时");
jsonObject["err_msg"] = ""; // 5秒后尝试重新连接
QJsonDocument jsonDocument(jsonObject); QTimer::singleShot(5000, this, [=](){
QByteArray jsonData = jsonDocument.toJson(); // this->tcp_ = new QTcpSocket;
m_tcpSocket.write(jsonData); emit sendTcpInfoSignals("重新连接Socket");
} emit restartSocket(this->ip_, this->port_);
});
return;
}
else
{
if (!this->heartbeatTimer_->isActive()) {
// 心跳包定时器启动
this->heartbeatTimer_->start(3000);
}
emit sendTcpInfoSignals("链接服务端成功");
// 连接失败
connect(this->tcp_, &QTcpSocket::errorOccurred, this, [=](QAbstractSocket::SocketError err){
emit sendTcpInfoSignals("链接服务端失败"); // 连接失败或其他错误,若服务器没有打开或连接失败,可以从这里会发出提示
});
// 断开连接
connect(this->tcp_, &QTcpSocket::disconnected, this, [=](){
emit sendTcpInfoSignals("服务端断开连接");
this->tcp_->close();
this->tcp_->deleteLater();
this->tcp_ = nullptr;
if (this->heartbeatTimer_->isActive())
{
// 停止发送心跳包
this->heartbeatTimer_->stop();
}
// // Process received JSON data // 5秒后尝试重新连接
// // ... QTimer::singleShot(5000, this, [=](){
qDebug()<< jsonData <<" "<< io_car<<" "<< direction<<" "<< t << "\n"<<Qt::endl; emit sendTcpInfoSignals("重新连接Socket");
} emit restartSocket(this->ip_, this->port_);
} });
void TcpClient::sendHeartbeat()
{
if (m_tcpSocket.state() == QAbstractSocket::ConnectedState) {
// 发送心跳包
//QByteArray heartbeatData = "matrixai"; });
// std::string head = "matrixai"; // 心跳信号
m_tcpSocket.write("matrixai"); connect(this->heartbeatTimer_, &QTimer::timeout, this, [=](){
if (this->tcp_->state() == QAbstractSocket::ConnectedState) {
// 发送心跳包
this->tcp_->write("matrixai");
}
});
// 接收到数据
connect(this->tcp_, &QTcpSocket::readyRead, this, [=](){
QByteArray jsonData = this->tcp_->readAll();
// emit sendTcpInfoSignals("--" + QString(jsonData));
jsonData.replace("}{", "}-{");
QList<QByteArray> jsonDataList = jsonData.split('-');
for (int i = 0; i < jsonDataList.size(); i++) {
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonDataList[i]);
if (jsonDocument.isObject()) {
QJsonObject jsonObject = jsonDocument.object();
if (jsonObject["type"].toString() != carType && carType == "0")
{
// 来车
emit this->comeTrainSignals(true);
come_time = jsonObject["cometime"].toString();
carType = jsonObject["type"].toString();
}
else if (jsonObject["type"].toString() != carType && carType == "1")
{
// 火车无
emit this->comeTrainSignals(false);
come_time = jsonObject["cometime"].toString();
carType = jsonObject["type"].toString();
}
}
}
});
}
this->exit_flag = false;
emit socketComplete(this->tcp_, ip, port);
} }
} catch (const std::exception &e) {
void TcpClient::reconnect() emit sendTcpInfoSignals("链接服务端失败");
{ this->exit_flag = true;
if (m_tcpSocket.state() != QAbstractSocket::ConnectedState) {
// 断线重连
m_tcpSocket.connectToHost("127.0.0.1",7000);
}
}
void TcpClient::handleConnected()
{
if (!m_heartbeatTimer->isActive()) {
// 心跳包定时器启动
m_heartbeatTimer->start(3000);
} }
} }
void TcpClient::handleDisconnected() void TcpClient::SetExitFlag(bool flag)
{ {
if (m_heartbeatTimer->isActive()) { this->exit_flag = flag;
// 停止发送心跳包 }
m_heartbeatTimer->stop();
} void TcpClient::closeConnect()
{
// 5秒后尝试重新连接 this->tcp_->close();
QTimer::singleShot(5000, this, &TcpClient::reconnect);
} }

View File

@ -12,20 +12,30 @@ class TcpClient : public QObject
public: public:
explicit TcpClient(QObject *parent = nullptr); explicit TcpClient(QObject *parent = nullptr);
void SetExitFlag(bool flag);
void closeConnect(); // 关闭连接
public slots:
void connectToServer(const QString &host, int port);
void onReadyRead();
void sendHeartbeat();
void reconnect();
void handleConnected();
void handleDisconnected();
private: private:
QTcpSocket m_tcpSocket; QTcpSocket* tcp_ = nullptr;
QTimer *m_heartbeatTimer; QTimer *heartbeatTimer_;
QString m_host; QString ip_;
int m_port; int port_;
QString carType = "0";
QString direction = "0";
QString come_time = "";
bool exit_flag = false; // 退出标记
public slots:
void connectToServer(QString ip, int port);
signals:
void comeTrainSignals(bool type);
void sendTcpInfoSignals(QString info);
void socketComplete(QTcpSocket* tcp, QString ip, quint16 port); // tcp句柄发送给主线程监管
void restartSocket(QString ip, int port); //重启Socket连接
}; };
#endif // TCPCLIENT_H #endif // TCPCLIENT_H

View File

@ -42,9 +42,7 @@ int main(int argc, char *argv[]) {
QApplication::setWindowIcon(QIcon("./logo.ico")); QApplication::setWindowIcon(QIcon("./logo.ico"));
MainWindow w; MainWindow w;
w.show(); w.show();
qInfo() << "111";
// TcpClient tcpClient;
// tcpClient.connectToServer("127.0.0.1",7000); //与视频车号通信ip端口
return QApplication::exec(); return QApplication::exec();
} }
return QApplication::exec(); return QApplication::exec();

View File

@ -1,7 +1,8 @@
#include <QListView> #include <QFileDialog>
#include "MainWindow.h" #include "MainWindow.h"
#include "ui_MainWindow.h" #include "ui_MainWindow.h"
#include "TcpClient.h"
#define DEBUG_HTTP 1 #define DEBUG_HTTP 1
@ -11,6 +12,14 @@ MainWindow::MainWindow(QWidget *parent)
{ {
ui->setupUi(this); ui->setupUi(this);
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);
layout()->addWidget(this->statusBar);
this->setWindowTitle("Matrix_RFID"); this->setWindowTitle("Matrix_RFID");
this->configPath_ = "./config/config.ini"; this->configPath_ = "./config/config.ini";
@ -29,6 +38,14 @@ MainWindow::MainWindow(QWidget *parent)
{ {
this->logError(errorMessage); this->logError(errorMessage);
} }
if (!ConfigUtil::readSocketServerConfig(this->configPath_, errorMessage, this->socketServerConfig_))
{
this->logError(errorMessage);
}
// 创建菜单栏
// this->initMenu();
// this->ui->testButton->setHidden(true);
// 获取本机串口列表 // 获取本机串口列表
this->getComList(); this->getComList();
@ -47,6 +64,9 @@ MainWindow::MainWindow(QWidget *parent)
connect(this, &MainWindow::upRfid_signals, this, &MainWindow::upRfid); 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))); connect(m_pSystemTray,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason)));
@ -64,8 +84,6 @@ MainWindow::MainWindow(QWidget *parent)
this->ui->resultTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); this->ui->resultTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
this->ui->resultTable->verticalHeader()->setMinimumWidth(50); this->ui->resultTable->verticalHeader()->setMinimumWidth(50);
if (!this->baseConfig_.upResult) if (!this->baseConfig_.upResult)
{ {
QIcon icon("./Fail.ico"); QIcon icon("./Fail.ico");
@ -77,6 +95,52 @@ MainWindow::MainWindow(QWidget *parent)
this->ui->upflagLabel->setPixmap(m_pic); this->ui->upflagLabel->setPixmap(m_pic);
} }
if (this->baseConfig_.useSocketServer)
{
// 创建线程
QThread *threadWork = new QThread; // 任务线程
this->tcpClient = new TcpClient(this);
this->tcpClient->moveToThread(threadWork);
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, [=](QString info){
this->logInfo(info);
this->statusInfo->setText(info);
if (info == "链接服务端超时"
|| info == "未连接Socket服务器"
|| info == "链接服务端失败"
|| info == "服务端断开连接"
|| info == "链接服务端失败")
{
this->videoHasTrain = false;
}
});
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;
emit IdentifyType();
}
});
}
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
@ -175,6 +239,7 @@ bool MainWindow::rnameRfidLog()
void MainWindow::saveRfidLog(const QString &value) void MainWindow::saveRfidLog(const QString &value)
{ {
try { try {
// QString logValue = "[" + QDateTime::currentDateTime().toString("hh:mm::ss") + "] " + value + "\n";
QString logValue = value + "\n"; QString logValue = value + "\n";
if (!this->recvLog.isOpen()) if (!this->recvLog.isOpen())
{ {
@ -226,6 +291,9 @@ void MainWindow::initComboBox() {
ui->BTBox->setCurrentText(QString::number(this->baseConfig_.baud)); ui->BTBox->setCurrentText(QString::number(this->baseConfig_.baud));
ui->truckEdit->setText(QString::number(this->baseConfig_.trackName)); ui->truckEdit->setText(QString::number(this->baseConfig_.trackName));
this->rfidHasTrain = false;
this->videoHasTrain = false;
} }
/** /**
@ -292,14 +360,14 @@ bool MainWindow::upWeb(std::string &carriageType, std::string &carriageNumber, s
Json::StreamWriterBuilder writer; Json::StreamWriterBuilder writer;
std::string str = Json::writeString(writer, arrayObj); std::string str = Json::writeString(writer, arrayObj);
this->logInfo("发送web: " + QString::fromStdString(str)); this->logInfo("" + QString::fromStdString(carriageOrder) + "节,发送web: " + QString::fromStdString(str));
auto res = cli.Post(this->interfaceConfig_.upResultPath.toStdString(), header, str, "application/json"); auto res = cli.Post(this->interfaceConfig_.upResultPath.toStdString(), header, str, "application/json");
if (res) if (res)
{ {
if (res->status == 200) if (res->status == 200)
{ {
this->logInfo("web返回: " + QString::fromStdString(res->body)); this->logInfo("" + QString::fromStdString(carriageOrder) + "节,web返回: " + QString::fromStdString(res->body));
Json::CharReaderBuilder readerBuilder; Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body); std::istringstream iss(res->body);
Json::Value root; Json::Value root;
@ -315,21 +383,21 @@ bool MainWindow::upWeb(std::string &carriageType, std::string &carriageNumber, s
{ {
if (root["msg"].asString() == "请求未授权") { if (root["msg"].asString() == "请求未授权") {
this->logWarn("因请求未授权而上传识别结果失败重新请求token。"); this->logWarn("" + QString::fromStdString(carriageOrder) + "节,因请求未授权而上传识别结果失败重新请求token。");
if (!this->getToken()) return false; if (!this->getToken()) return false;
return this->upWeb(carriageType, carriageNumber, carriageOrder, time); return this->upWeb(carriageType, carriageNumber, carriageOrder, time);
} }
this->logError("识别结果上传失败,原因:" + QString::fromStdString(root.asString())); this->logError("" + QString::fromStdString(carriageOrder) + "节,识别结果上传失败,原因:" + QString::fromStdString(root.asString()));
} }
} }
else else
{ {
this->logError("识别结果上传失败返回数据解析异常返回数据非json" + QString::fromStdString(res->body)); this->logError("" + QString::fromStdString(carriageOrder) + "节,识别结果上传失败返回数据解析异常返回数据非json" + QString::fromStdString(res->body));
} }
} }
else else
{ {
this->logError("识别结果上传失败,原因:" + QString::number(res->status) + " - " + QString::fromStdString(res->body)); this->logError("" + QString::fromStdString(carriageOrder) + "节,识别结果上传失败,原因:" + QString::number(res->status) + " - " + QString::fromStdString(res->body));
if (res->status == 401) { if (res->status == 401) {
this->logWarn("因请求未授权而上传识别结果失败重新请求token。"); this->logWarn("因请求未授权而上传识别结果失败重新请求token。");
this->getToken(); this->getToken();
@ -339,12 +407,12 @@ bool MainWindow::upWeb(std::string &carriageType, std::string &carriageNumber, s
} }
else else
{ {
this->logError("上传数据失败,请检查网络,或者上传地址!"); this->logError("" + QString::fromStdString(carriageOrder) + "节,上传数据失败,请检查网络,或者上传地址!");
} }
} }
catch (std::exception &e) catch (std::exception &e)
{ {
this->logError("上传识别结果失败,原因:"); this->logError("" + QString::fromStdString(carriageOrder) + "节,上传识别结果失败,原因:");
this->logError(e.what()); this->logError(e.what());
} }
return false; return false;
@ -429,7 +497,7 @@ void MainWindow::changeEvent(QEvent *event)
{ {
if((event->type()==QEvent::WindowStateChange)&&isMinimized()) if((event->type()==QEvent::WindowStateChange)&&isMinimized())
{ {
// hide(); this->hide();
m_pSystemTray->setIcon(QIcon("./logo.ico")); // 托盘时显示的图片 m_pSystemTray->setIcon(QIcon("./logo.ico")); // 托盘时显示的图片
m_pSystemTray->setToolTip("Rfid车号识别-股道号:" + QString::number(this->baseConfig_.trackName)); // 鼠标在托盘图片时的提示 m_pSystemTray->setToolTip("Rfid车号识别-股道号:" + QString::number(this->baseConfig_.trackName)); // 鼠标在托盘图片时的提示
m_pSystemTray->showMessage("Rfid车号识别","已隐藏至托盘",QSystemTrayIcon::Information,10000); m_pSystemTray->showMessage("Rfid车号识别","已隐藏至托盘",QSystemTrayIcon::Information,10000);
@ -449,6 +517,7 @@ void MainWindow::closeEvent(QCloseEvent *event)
// 验证账号和密码是否正确 // 验证账号和密码是否正确
if (password == "matrix") { if (password == "matrix") {
this->initParam(); this->initParam();
this->tcp_->close();
event->accept(); // 关闭窗口 event->accept(); // 关闭窗口
exit(0); exit(0);
} else { } else {
@ -486,6 +555,8 @@ void MainWindow::creat_menu()
void MainWindow::on_ShowMainAction() void MainWindow::on_ShowMainAction()
{ {
this->show(); this->show();
this->showNormal();
this->activateWindow();
} }
/** /**
@ -495,13 +566,16 @@ void MainWindow::on_ShowMainAction()
*/ */
void MainWindow::on_ExitAppAction() void MainWindow::on_ExitAppAction()
{ {
QString password = QInputDialog::getText(this, "关闭账号密码验证", "请输入密码:", QLineEdit::Password); // 弹出对话框要求用户输入账号和密码
QString password = QInputDialog::getText(this, "密码验证", "请输入密码:", QLineEdit::Password);
// 验证账号和密码是否正确 // 验证账号和密码是否正确
if (password == "123") { if (password == "matrix") {
this->initParam();
this->tcp_->close();
exit(0); exit(0);
} else { } else {
QMessageBox::warning(this, "验证失败", "账号或密码不正确!"); QMessageBox::warning(this, "验证失败", "密码不正确!");
} }
} }
@ -516,6 +590,7 @@ void MainWindow::on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason reaso
//双击托盘图标 //双击托盘图标
//双击后显示主程序窗口 //双击后显示主程序窗口
this->showNormal(); this->showNormal();
this->activateWindow();
break; break;
default: default:
break; break;
@ -549,6 +624,7 @@ void MainWindow::openComClicked()
// connect(timer, &QTimer::timeout, this, &MainWindow::readCom); // connect(timer, &QTimer::timeout, this, &MainWindow::readCom);
// timer->start(10); // timer->start(10);
connect(this->serial_, &QSerialPort::errorOccurred, this, &MainWindow::serialPort_error); connect(this->serial_, &QSerialPort::errorOccurred, this, &MainWindow::serialPort_error);
} }
else else
{ {
@ -629,21 +705,47 @@ void MainWindow::getQueueDataThread()
QStringList rfidSubList = this->tmpRfid.split("&"); QStringList rfidSubList = this->tmpRfid.split("&");
this->tmpRfid = ""; 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) for (const auto & i : rfidSubList)
{ {
if (i.size() == 26) if (i.size() == 26)
{ {
// 车厢信息 // 车厢信息
QString strTrainInfo = i.left(14); QString strTrainInfo = i.left(14);
if (vecTrain.empty() || !vecTrain.contains(strTrainInfo)) if (vecTrain.empty() || !vecTrain.contains(strTrainInfo))
{ {
bool isCarriage = false; bool isNoCarriage = false;
strTrainInfo.mid(3, 2).toInt(&isCarriage); int carT = strTrainInfo.mid(3, 2).simplified().toInt(&isNoCarriage);
if (isCarriage) continue; isNoCarriage = carT >= 10;
if (isNoCarriage) continue;
vecTrain.append(strTrainInfo); vecTrain.append(strTrainInfo);
this->resultTableModel_->setItem(vecTrain.size()-1, 0, new QStandardItem(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));
emit upRfid_signals(); emit upRfid_signals();
this->logInfo(QString("第%1节 %2").arg(vecTrain.size()).arg(strTrainInfo));
} }
} }
else if (i.size() == 7) else if (i.size() == 7)
@ -651,29 +753,13 @@ void MainWindow::getQueueDataThread()
// 磁钢信号 // 磁钢信号
QString strFirst = i.left(1); QString strFirst = i.left(1);
QString strOther = i.mid(1, i.size() - 1); QString strOther = i.mid(1, i.size() - 1);
split_lambda(strFirst, strOther);
if (strFirst == "0") }
{ else if (i.size() == 14) // 特殊情况,来车信号少了&符
// 关功放信号 {
// TODO: 需要结合 “来车状态”广播消息,确认是否真的车离开了 没有真离开,则向串口发送 @on& 避免关功放 QString strFirst = i.left(1);
this->initParam(); QString strOther = i.mid(1, 6);
this->logInfo("功放关闭"); split_lambda(strFirst, strOther);
}
else
{
// TODO: 此处按照4个磁钢来配置可能存在一定限制; 另外逻辑需要优化
if (strOther == "000000" // 第一次检测来车时(前提是上一次功放已关闭)
&& (strFirst == this->baseConfig_.magnetSteelOrder.left(1)
|| strFirst == this->baseConfig_.magnetSteelOrder.mid(1, 1)))
{
this->logInfo("来车了");
this->mkRfidLog();
this->needIdentify = true;
this->trainTime = this->getSystemTime();
this->resultTableModel_->clear();
this->resultTableModel_ = this->getStandardItemModel();
}
}
} }
} }
} }
@ -704,7 +790,60 @@ void MainWindow::upRfid()
std::string strOrder = QString::number(order).toStdString(); std::string strOrder = QString::number(order).toStdString();
if (!this->upWeb(carriageType, carriageNum, strOrder, nowTime)) if (!this->upWeb(carriageType, carriageNum, strOrder, nowTime))
{ {
this->logError("识别结果上传失败!"); this->logError("" + QString::fromStdString(strOrder) + "节,识别结果上传失败!");
} }
} }
void MainWindow::IdentifyTypeUpdate() {
if (this->rfidHasTrain || this->videoHasTrain)
{
if (!this->needIdentify)
{
this->logInfo("来车了");
this->mkRfidLog();
this->needIdentify = true;
this->trainTime = this->getSystemTime();
this->resultTableModel_->clear();
this->resultTableModel_ = this->getStandardItemModel();
}
}
else if (!this->rfidHasTrain && !this->videoHasTrain)
{
this->initParam();
this->logInfo("火车离开了");
}
}
// ============================= 测试 ====================================
void MainWindow::readTestInfo()
{
if (this->isOpenCom)
{
logWarn("请先关闭串口后进行测试操作!");
return;
}
QString filePath = QFileDialog::getOpenFileName(this, "选择一个文件", QDir::currentPath(), "(*.*)");
if(filePath.isEmpty()){
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("---读取测试数据完毕---");
}

View File

@ -40,6 +40,9 @@
#include <thread> #include <thread>
#include <QMessageBox> #include <QMessageBox>
#include <QTimer> #include <QTimer>
#include <QListView>
#include <QMenuBar>
#include <QStatusBar>
#include <queue> #include <queue>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
@ -47,6 +50,7 @@
#include "common.h" #include "common.h"
#include "ConfigUtil.h" #include "ConfigUtil.h"
#include "ComDetect.h" #include "ComDetect.h"
#include "TcpClient.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } namespace Ui { class MainWindow; }
@ -59,6 +63,14 @@ class MainWindow : public QWidget
public: public:
MainWindow(QWidget *parent = nullptr); MainWindow(QWidget *parent = nullptr);
~MainWindow(); ~MainWindow();
void logDebug(const QString& message);
void logInfo(const QString& message);
void logWarn(const QString& message);
void logError(const QString& message);
bool mkRfidLog();
bool rnameRfidLog();
void saveRfidLog(const QString &value);
void initParam(); void initParam();
@ -67,21 +79,30 @@ public:
QString getSystemTime(); QString getSystemTime();
// 获const 取串口列表&
QList<QString> getComList();
// 将所有串口const 展示在下&拉列表
void initComboBox();
// 设置菜单项
void initMenu();
// 创建日志目录
static bool mkLogDir();
// 获取QStandardItem
QStandardItemModel* getStandardItemModel();
QStandardItem* getStandardItem(const QString &value);
private: private:
QString trainTime; QString trainTime;
QString logRfidRecvName; QString logRfidRecvName;
QFile recvLog; QFile recvLog;
bool mkRfidLog();
bool rnameRfidLog();
void saveRfidLog(const QString &value);
QString configPath_; // QString configPath_; //
ai_matrix::BaseConfig baseConfig_; ai_matrix::BaseConfig baseConfig_;
ai_matrix::InterfaceConfig interfaceConfig_; ai_matrix::InterfaceConfig interfaceConfig_;
ai_matrix::SServerConfig socketServerConfig_;
std::string webToken; //授权信息 std::string webToken; //授权信息
QSerialPort *serial_; //串口 QSerialPort *serial_; //串口
// 表格model // 表格model
@ -99,23 +120,19 @@ private:
// 识别方向正确标志 // 识别方向正确标志
bool needIdentify = false; bool needIdentify = false;
// 视频识别有火车标志使用socket服务时才有用
bool videoHasTrain = false;
// RFID识别有火车标志
bool rfidHasTrain = false;
// 获取当前时间 // 获取当前时间
QDateTime currentTime_ = QDateTime::currentDateTime(); QDateTime currentTime_ = QDateTime::currentDateTime();
void logDebug(const QString& message);
void logInfo(const QString& message);
void logWarn(const QString& message);
void logError(const QString& message);
// 获const 取串口列表& TcpClient* tcpClient;
QList<QString> getComList();
// 将所有串口const 展示在下&拉列表
void initComboBox();
// 创建日志目录
static bool mkLogDir();
// 获取QStandardItem
QStandardItemModel* getStandardItemModel();
QStandardItem* getStandardItem(const QString &value);
private: private:
QTcpSocket* tcp_ = nullptr;
QStatusBar* statusBar;
QLabel *statusInfo;
QMenu* m_pTrayMennu; //系统托盘右键菜单项 QMenu* m_pTrayMennu; //系统托盘右键菜单项
QSystemTrayIcon* m_pSystemTray; //系统托盘图标 QSystemTrayIcon* m_pSystemTray; //系统托盘图标
@ -123,16 +140,18 @@ private:
//右键菜单栏选项 //右键菜单栏选项
QAction* m_pActionShow; QAction* m_pActionShow;
QAction* m_pActionQuit; QAction* m_pActionQuit;
void creat_menu();
void creat_action(); void creat_action();
void changeEvent(QEvent *event); void changeEvent(QEvent *event);
void on_ShowMainAction(); void on_ShowMainAction();
void on_ExitAppAction(); void on_ExitAppAction();
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
void creat_menu();
signals: signals:
void getRfid_signals(); void getRfid_signals();
void upRfid_signals(); void upRfid_signals();
void connect_socket(QString ip, int port);
void IdentifyType();
private slots: private slots:
void openComClicked(); void openComClicked();
void readCom(); void readCom();
@ -140,7 +159,8 @@ private slots:
void upRfid(); void upRfid();
void serialPort_error(QSerialPort::SerialPortError error); void serialPort_error(QSerialPort::SerialPortError error);
void on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason reason); void on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason reason);
void readTestInfo();
void IdentifyTypeUpdate();
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;

View File

@ -35,7 +35,7 @@
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>100</width> <width>80</width>
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
@ -70,7 +70,7 @@
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>100</width> <width>80</width>
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
@ -120,7 +120,7 @@
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>100</width> <width>80</width>
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
@ -139,7 +139,7 @@
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>120</width> <width>100</width>
<height>40</height> <height>40</height>
</size> </size>
</property> </property>
@ -205,6 +205,45 @@ border: 2px solid rgb(134, 134, 134);</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="testButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 255, 255);
border: 2px solid rgb(134, 134, 134);</string>
</property>
<property name="text">
<string>测试</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_2"> <spacer name="horizontalSpacer_2">
<property name="orientation"> <property name="orientation">
@ -309,23 +348,43 @@ border: 2px solid rgb(134, 134, 134);</string>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QLabel" name="label_5"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="minimumSize"> <item>
<size> <widget class="QLabel" name="label_5">
<width>700</width> <property name="minimumSize">
<height>20</height> <size>
</size> <width>50</width>
</property> <height>20</height>
<property name="maximumSize"> </size>
<size> </property>
<width>700</width> <property name="maximumSize">
<height>20</height> <size>
</size> <width>100</width>
</property> <height>20</height>
<property name="text"> </size>
<string>日志:</string> </property>
</property> <property name="contextMenuPolicy">
</widget> <enum>Qt::NoContextMenu</enum>
</property>
<property name="text">
<string>日志:</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item> </item>
<item> <item>
<widget class="QTextBrowser" name="textBrowser"> <widget class="QTextBrowser" name="textBrowser">

View File

@ -39,6 +39,8 @@ public:
QSpacerItem *horizontalSpacer; QSpacerItem *horizontalSpacer;
QLabel *LEDlabel; QLabel *LEDlabel;
QPushButton *openComButton; QPushButton *openComButton;
QSpacerItem *horizontalSpacer_5;
QPushButton *testButton;
QSpacerItem *horizontalSpacer_2; QSpacerItem *horizontalSpacer_2;
QHBoxLayout *horizontalLayout_2; QHBoxLayout *horizontalLayout_2;
QVBoxLayout *verticalLayout; QVBoxLayout *verticalLayout;
@ -48,7 +50,9 @@ public:
QSpacerItem *horizontalSpacer_3; QSpacerItem *horizontalSpacer_3;
QTableView *resultTable; QTableView *resultTable;
QVBoxLayout *verticalLayout_2; QVBoxLayout *verticalLayout_2;
QHBoxLayout *horizontalLayout_4;
QLabel *label_5; QLabel *label_5;
QSpacerItem *horizontalSpacer_4;
QTextBrowser *textBrowser; QTextBrowser *textBrowser;
void setupUi(QWidget *MainWindow) void setupUi(QWidget *MainWindow)
@ -65,7 +69,7 @@ public:
horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
label = new QLabel(MainWindow); label = new QLabel(MainWindow);
label->setObjectName(QString::fromUtf8("label")); label->setObjectName(QString::fromUtf8("label"));
label->setMaximumSize(QSize(100, 16777215)); label->setMaximumSize(QSize(80, 16777215));
label->setStyleSheet(QString::fromUtf8("font: 75 9pt \"Arial\";")); label->setStyleSheet(QString::fromUtf8("font: 75 9pt \"Arial\";"));
horizontalLayout->addWidget(label); horizontalLayout->addWidget(label);
@ -80,7 +84,7 @@ public:
label_2 = new QLabel(MainWindow); label_2 = new QLabel(MainWindow);
label_2->setObjectName(QString::fromUtf8("label_2")); label_2->setObjectName(QString::fromUtf8("label_2"));
label_2->setMaximumSize(QSize(100, 16777215)); label_2->setMaximumSize(QSize(80, 16777215));
label_2->setStyleSheet(QString::fromUtf8("font: 75 9pt \"Arial\";")); label_2->setStyleSheet(QString::fromUtf8("font: 75 9pt \"Arial\";"));
horizontalLayout->addWidget(label_2); horizontalLayout->addWidget(label_2);
@ -98,14 +102,14 @@ public:
label_3 = new QLabel(MainWindow); label_3 = new QLabel(MainWindow);
label_3->setObjectName(QString::fromUtf8("label_3")); label_3->setObjectName(QString::fromUtf8("label_3"));
label_3->setMaximumSize(QSize(100, 16777215)); label_3->setMaximumSize(QSize(80, 16777215));
horizontalLayout->addWidget(label_3); horizontalLayout->addWidget(label_3);
truckEdit = new QLineEdit(MainWindow); truckEdit = new QLineEdit(MainWindow);
truckEdit->setObjectName(QString::fromUtf8("truckEdit")); truckEdit->setObjectName(QString::fromUtf8("truckEdit"));
truckEdit->setMinimumSize(QSize(120, 40)); truckEdit->setMinimumSize(QSize(120, 40));
truckEdit->setMaximumSize(QSize(120, 40)); truckEdit->setMaximumSize(QSize(100, 40));
truckEdit->setStyleSheet(QString::fromUtf8("background-color: rgb(255, 255, 255);")); truckEdit->setStyleSheet(QString::fromUtf8("background-color: rgb(255, 255, 255);"));
horizontalLayout->addWidget(truckEdit); horizontalLayout->addWidget(truckEdit);
@ -132,6 +136,19 @@ public:
horizontalLayout->addWidget(openComButton); horizontalLayout->addWidget(openComButton);
horizontalSpacer_5 = new QSpacerItem(20, 20, QSizePolicy::Maximum, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer_5);
testButton = new QPushButton(MainWindow);
testButton->setObjectName(QString::fromUtf8("testButton"));
testButton->setMinimumSize(QSize(50, 50));
testButton->setMaximumSize(QSize(50, 50));
testButton->setStyleSheet(QString::fromUtf8("background-color: rgb(255, 255, 255);\n"
"border: 2px solid rgb(134, 134, 134);"));
horizontalLayout->addWidget(testButton);
horizontalSpacer_2 = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Minimum); horizontalSpacer_2 = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer_2); horizontalLayout->addItem(horizontalSpacer_2);
@ -155,7 +172,7 @@ public:
upflagLabel = new QLabel(MainWindow); upflagLabel = new QLabel(MainWindow);
upflagLabel->setObjectName(QString::fromUtf8("upflagLabel")); upflagLabel->setObjectName(QString::fromUtf8("upflagLabel"));
upflagLabel->setMinimumSize(QSize(60, 20)); upflagLabel->setMinimumSize(QSize(70, 20));
upflagLabel->setMaximumSize(QSize(80, 20)); upflagLabel->setMaximumSize(QSize(80, 20));
horizontalLayout_3->addWidget(upflagLabel); horizontalLayout_3->addWidget(upflagLabel);
@ -180,12 +197,22 @@ public:
verticalLayout_2 = new QVBoxLayout(); verticalLayout_2 = new QVBoxLayout();
verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2")); 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(MainWindow);
label_5->setObjectName(QString::fromUtf8("label_5")); label_5->setObjectName(QString::fromUtf8("label_5"));
label_5->setMinimumSize(QSize(700, 20)); label_5->setMinimumSize(QSize(50, 20));
label_5->setMaximumSize(QSize(700, 20)); label_5->setMaximumSize(QSize(100, 20));
label_5->setContextMenuPolicy(Qt::NoContextMenu);
verticalLayout_2->addWidget(label_5); horizontalLayout_4->addWidget(label_5);
horizontalSpacer_4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_4->addItem(horizontalSpacer_4);
verticalLayout_2->addLayout(horizontalLayout_4);
textBrowser = new QTextBrowser(MainWindow); textBrowser = new QTextBrowser(MainWindow);
textBrowser->setObjectName(QString::fromUtf8("textBrowser")); textBrowser->setObjectName(QString::fromUtf8("textBrowser"));
@ -224,6 +251,7 @@ public:
label_3->setText(QCoreApplication::translate("MainWindow", "\350\202\241\351\201\223\345\220\215:", nullptr)); label_3->setText(QCoreApplication::translate("MainWindow", "\350\202\241\351\201\223\345\220\215:", nullptr));
LEDlabel->setText(QString()); LEDlabel->setText(QString());
openComButton->setText(QCoreApplication::translate("MainWindow", "\346\211\223\345\274\200\344\270\262\345\217\243", nullptr)); openComButton->setText(QCoreApplication::translate("MainWindow", "\346\211\223\345\274\200\344\270\262\345\217\243", nullptr));
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)); 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)); upflagLabel->setText(QCoreApplication::translate("MainWindow", "\344\270\215\344\270\212\344\274\240", nullptr));
label_5->setText(QCoreApplication::translate("MainWindow", "\346\227\245\345\277\227:", nullptr)); label_5->setText(QCoreApplication::translate("MainWindow", "\346\227\245\345\277\227:", nullptr));

View File

@ -60,6 +60,7 @@ QSerialPort* ComDetect::openCom(const QString &com, int baud)
bool ComDetect::closeCom() bool ComDetect::closeCom()
{ {
this->serial_->clear();
this->serial_->close(); this->serial_->close();
return true; return true;
} }