重连串口问题优化

This commit is contained in:
Mr.V 2024-04-30 14:51:41 +08:00
parent 6be58c3892
commit b8880f4da7
6 changed files with 179 additions and 567 deletions

View File

@ -15,13 +15,12 @@ MainWindow::MainWindow(QWidget *parent)
this->statusBar = new QStatusBar(); this->statusBar = new QStatusBar();
this->statusInfo = new QLabel("初始化完成",this); this->statusInfo = new QLabel("初始化完成",this);
this->statusBar->addPermanentWidget(this->statusInfo);//显示正常信息 this->statusBar->addPermanentWidget(this->statusInfo);//显示正常信息
QLabel* statusVersion = new QLabel("开启时间:" + QDateTime::currentDateTime().toString("yy-MM-dd hh:mm"),this); QLabel* statusVersion = new QLabel("开启时间:" + QDateTime::currentDateTime().toString("yy.MM.dd.hh.mm"),this);
this->statusBar->addWidget(statusVersion); this->statusBar->addWidget(statusVersion);
layout()->addWidget(this->statusBar); layout()->addWidget(this->statusBar);
this->setWindowTitle("Matrix_RFID 车号识别程序(勿关!!)"); this->setWindowTitle("Matrix_RFID 车号识别程序(勿关!!)");
this->configPath_ = "./config/config.ini";
if (!this->mkLogDir()) if (!this->mkLogDir())
{ {
@ -30,15 +29,7 @@ MainWindow::MainWindow(QWidget *parent)
// 配置文件读取 // 配置文件读取
QString errorMessage = ""; 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_))
{ {
this->logError(errorMessage); this->logError(errorMessage);
} }
@ -49,27 +40,13 @@ MainWindow::MainWindow(QWidget *parent)
// 初始化界面上的串口打开参数 // 初始化界面上的串口打开参数
this->initComboBox(); this->initComboBox();
this->serial_ = new QSerialPort;
m_pSystemTray=new QSystemTrayIcon(this); m_pSystemTray=new QSystemTrayIcon(this);
connect(this->ui->openComButton, &QPushButton::clicked, this, &MainWindow::openComClicked); 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->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)));
this->logRfidRecvName = "./Logs/rfid_data.txt";
this->recvLog.setFileName(logRfidRecvName);
this->recvLog.open(QIODevice::ReadWrite | QIODevice::Append);
//初始最小化 //初始最小化
//this->showMinimized();//最小化 //this->showMinimized();//最小化
// 设置最大展示数据行数 // 设置最大展示数据行数
@ -80,91 +57,52 @@ 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");
QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整 // QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整
this->ui->upflagLabel->setPixmap(m_pic); // this->ui->upflagLabel->setPixmap(m_pic);
}else{ // }else{
QIcon icon("./Succ.ico"); // QIcon icon("./Succ.ico");
QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整 // QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整
this->ui->upflagLabel->setPixmap(m_pic); // this->ui->upflagLabel->setPixmap(m_pic);
} // }
if (this->baseConfig_.useSocketServer) // 初始化LED指示灯
{ this->upResultType(this->baseConfig_.upResult);
// 创建线程
QThread *threadWork = new QThread; // 任务线程
this->tcpClient = new TcpClient(this); this->readComThread = new ReadComThread(&this->queueTrainInfo_, this);
this->tcpClient->moveToThread(threadWork); this->readComThread->start();
connect(this, &MainWindow::connect_socket, this->tcpClient, &TcpClient::connectToServer); this->upResultThread = new UpResultThread(&this->queueTrainInfo_, this);
// 子线程反馈 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 == 0)
{
this->logInfo("获得方向判定:" + QString(direction > -1 ? (direction > 0 ? "需识别" : "待定") : "无需上传"));
this->iDirection = direction;
}
});
}
ui->openComButton->click();
this->upResultThread = new UpResultThread(&this->queueTrainInfo_, &this->iDirection, this);
this->upResultThread->start(); this->upResultThread->start();
connect(this, &MainWindow::openCom_signals, this->readComThread, &ReadComThread::openCom);
connect(this, &MainWindow::readTestRfid_signals, this->readComThread, &ReadComThread::readTestInfo);
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::DebugSignals, this, &MainWindow::DebugSlots);
connect(this->upResultThread, &UpResultThread::InfoSignals, this, &MainWindow::InfoSlots); connect(this->upResultThread, &UpResultThread::InfoSignals, this, &MainWindow::InfoSlots);
connect(this->upResultThread, &UpResultThread::WarnSignals, this, &MainWindow::WarnSlots); connect(this->upResultThread, &UpResultThread::WarnSignals, this, &MainWindow::WarnSlots);
connect(this->upResultThread, &UpResultThread::ErrorSignals, this, &MainWindow::ErrorSlots); connect(this->upResultThread, &UpResultThread::ErrorSignals, this, &MainWindow::ErrorSlots);
ui->openComButton->click();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
this->logInfo("-- 程序退出 --"); this->logInfo("-- 程序退出 --");
this->initParam();
delete ui; delete ui;
} }
@ -184,16 +122,8 @@ void MainWindow::logError(const QString& message) {
LogError << message.toStdString(); LogError << message.toStdString();
ui->textBrowser->append(QString("[Error] [") + this->getSystemTime() + QString::fromStdString("] ") + message); ui->textBrowser->append(QString("[Error] [") + this->getSystemTime() + QString::fromStdString("] ") + message);
} }
void MainWindow::statusInfoUpdate(const QString &info) {
void MainWindow::initParam() { this->statusInfo->setText(info);
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;
} }
/** /**
@ -212,80 +142,6 @@ bool MainWindow::mkLogDir()
return true; 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 * @return
@ -302,12 +158,13 @@ QList<QString> MainWindow::getComList() {
/** /**
* comboxBox * comboxBox
*/ */
void MainWindow::initComboBox() { void MainWindow::initComboBox()
{
// ui->BTBox->setEditable(true); // 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: 30px; background-color: rgb(255, 255, 255); color: rgb(225, 225, 225);}");
ui->BTBox->setView(new QListView()); ui->BTBox->setView(new QListView());
ui->comBox->setEditable(true); 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: 30px; background-color: rgb(255, 255, 255); color: rgb(225, 225, 225);}");
ui->comBox->setMaxVisibleItems(5); ui->comBox->setMaxVisibleItems(5);
ui->comBox->setView(new QListView()); ui->comBox->setView(new QListView());
ui->comBox->addItems(this->comList); ui->comBox->addItems(this->comList);
@ -325,9 +182,6 @@ 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;
} }
/** /**
@ -389,8 +243,6 @@ void MainWindow::closeEvent(QCloseEvent *event)
// 验证账号和密码是否正确 // 验证账号和密码是否正确
if (password == "matrix") { if (password == "matrix") {
this->initParam();
this->tcp_->close();
event->accept(); // 关闭窗口 event->accept(); // 关闭窗口
exit(0); exit(0);
} else { } else {
@ -458,31 +310,8 @@ void MainWindow::openComClicked()
{ {
if (ui->openComButton->text() == "打开串口") if (ui->openComButton->text() == "打开串口")
{ {
this->serial_ = this->comDetect_.openCom(ui->comBox->currentText(), ui->BTBox->currentIndex()); this->auto_reconnect_serial_ = true;
if (this->serial_ != nullptr) emit openCom_signals(true);
{
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("串口打开失败!");
}
} }
else else
{ {
@ -491,232 +320,66 @@ void MainWindow::openComClicked()
// 验证账号和密码是否正确 // 验证账号和密码是否正确
if (password == "matrix") { if (password == "matrix") {
if (this->comDetect_.closeCom()) this->auto_reconnect_serial_ = false;
{
if (this->needIdentify == true) this->needIdentify = false; emit openCom_signals(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);");
}
} else { } else {
QMessageBox::warning(this, "验证失败", "密码不正确!"); QMessageBox::warning(this, "验证失败", "密码不正确!");
} }
} }
} }
/** void MainWindow::openComResult(const bool &success)
* 退
* @param error
*/
void MainWindow::serialPort_error(QSerialPort::SerialPortError error)
{ {
if (error != QSerialPort::NoError) this->ui->openComButton->setText("关闭串口");
if (success)
{ {
//关闭串口 this->ui->LEDlabel->setStyleSheet("border-radius: 16px;\ "
this->serial_->close(); "background-color: rgba(74, 221, 108, 225);\ "
this->ui->openComButton->setText("打开串口"); "border:1px solid rgba(168, 168, 168, 105);");
this->logError("串口异常退出,疑似接口松动"); }
this->ui->LEDlabel->setStyleSheet("border-radius: 16px; \ " else
{
this->ui->LEDlabel->setStyleSheet("border-radius: 16px;\ "
"background-color: red;\ " "background-color: red;\ "
"border:1px solid rgba(168, 168, 168, 105);"); "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() void MainWindow::comeTrain(const bool &success) {
{ this->resultTableModel_->clear();
try { this->resultTableModel_ = this->getStandardItemModel();
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::upResultType(const bool &type) {
* @brief:queue中获取数据 if (type) {
* @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.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));
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{
QIcon icon("./Succ.ico"); QIcon icon("./Succ.ico");
QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整 QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整
this->ui->upflagLabel->setPixmap(m_pic); this->ui->upflagLabel->setPixmap(m_pic);
} } else {
QIcon icon("./Fail.ico");
QString info = this->vecTrain.back(); QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整
int order = this->vecTrain.size(); this->ui->upflagLabel->setPixmap(m_pic);
if (order > this->socketServerConfig_.delayed_upload && this->iDirection == 0)
{
this->iDirection = 1;
}
if (!this->baseConfig_.useSocketServer) this->iDirection = 1;
// 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);
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 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("火车离开了");
} }
} }
@ -740,32 +403,16 @@ void MainWindow::ErrorSlots(const QString &info) {
void MainWindow::readTestInfo() void MainWindow::readTestInfo()
{ {
if (this->ui->openComButton->text() == "关闭串口")
if (this->isOpenCom || ui->openComButton->text() == "关闭串口")
{ {
logWarn("请先关闭串口后进行测试操作!"); logWarn("请先关闭串口后进行测试操作!");
return; return;
} }
QString filePath = QFileDialog::getOpenFileName(this, "选择一个文件", QDir::currentPath(), "(*.*)"); QString filePath = QFileDialog::getOpenFileName(this, "选择一个文件", QDir::currentPath(), "(*.*)");
if(filePath.isEmpty()){ if(filePath.isEmpty()){
QMessageBox::warning(this, "打开文件", "选择文件不能为空"); // QMessageBox::warning(this, "打开文件", "选择文件不能为空");
return; return;
} }
// 创建一个QFile对象并打开要读取的文本文件
QFile file(filePath); emit this->readTestRfid_signals(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

@ -49,10 +49,11 @@
#include <thread> #include <thread>
#include <chrono> #include <chrono>
#include "common.h" #include "common.h"
#include "ConfigUtil.h"
#include "ComDetect.h" //#include "ComDetect.h"
#include "TcpClient.h"
#include "../threads/UpResultThread.h" #include "UpResultThread.h"
#include "ReadComThread.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -62,7 +63,7 @@ using namespace ai_matrix;
class MainWindow : public QWidget class MainWindow : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
MainWindow(QWidget *parent = nullptr); MainWindow(QWidget *parent = nullptr);
@ -73,16 +74,10 @@ public:
void logWarn(const QString& message); void logWarn(const QString& message);
void logError(const QString& message); void logError(const QString& message);
// 创建日志目录 // 创建日志目录
static bool mkLogDir(); bool mkLogDir();
bool mkRfidLog();
void deleteOldFiles(const QString &path, int days);
bool rnameRfidLog();
void saveRfidLog(const QString &value);
void initParam(); void initParam();
QString getSystemTime(); QString getSystemTime();
// 获const 取串口列表& // 获const 取串口列表&
@ -97,7 +92,7 @@ public:
private: private:
UpResultThread *upResultThread; UpResultThread *upResultThread;
QString trainTime; ReadComThread *readComThread;
QString logRfidRecvName; QString logRfidRecvName;
QFile recvLog; QFile recvLog;
@ -105,41 +100,31 @@ private:
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; //授权信息
QSerialPort *serial_; //串口 std::string webToken; //授权信息
// 表格model // 表格model
QStandardItemModel *resultTableModel_ = nullptr; QStandardItemModel *resultTableModel_ = nullptr;
// 打开com口标志 // 打开com口标志
bool isOpenCom = false; bool isOpenCom = false;
bool auto_reconnect_serial_ = false;
// Com口数据读取类 // Com口数据读取类
ComDetect comDetect_; // ComDetect comDetect_;
// com口列表 // com口列表
QList<QString> comList; QList<QString> comList;
// 整列车识别结果存储 // 整列车识别结果存储
QStringList vecTrain; QStringList vecTrain;
MQueue<QString> queue_{}; // RFID读取的数据队列 MQueue<QString> queue_{}; // RFID读取的数据队列
MQueue<TrainInfo> queueTrainInfo_{}; // RFID读取的磁钢信息队列 MQueue<TrainInfo> queueTrainInfo_{}; // RFID读取的磁钢信息队列
QString rfidSourceInfo; QString rfidSourceInfo;
QString tmpRfid; //临时存储的RFID原始数据用于防止接收的数据不完整 QString tmpRfid; //临时存储的RFID原始数据用于防止接收的数据不完整
// 识别方向正确标志
bool needIdentify = false;
// 视频识别有火车标志使用socket服务时才有用
bool videoHasTrain = false;
// RFID识别有火车标志
bool rfidHasTrain = false;
// 是否是需要识别的方向 -1:不识别 0:未确定 1:识别
int iDirection = 0;
// 获取当前时间 // 获取当前时间
QDateTime currentTime_ = QDateTime::currentDateTime(); QDateTime currentTime_ = QDateTime::currentDateTime();
TcpClient* tcpClient;
private: private:
QTcpSocket* tcp_ = nullptr;
QStatusBar* statusBar; QStatusBar* statusBar;
QLabel *statusInfo; QLabel *statusInfo;
@ -156,19 +141,19 @@ private:
void creat_menu(); void creat_menu();
signals: signals:
void getRfid_signals(); void openCom_signals(const bool &type, const int &msec = 0);
void upRfid_signals(QString rfidInfo); void readTestRfid_signals(const QString &filePath);
void connect_socket(QString ip, int port);
void IdentifyType();
private slots: private slots:
void openComClicked(); void openComClicked();
void readCom(); void openComResult(const bool &success);
void getQueueDataThread(); void closeComResult(const bool &success);
void upRfid(QString rfidInfo); void upResultType(const bool &type);
void serialPort_error(QSerialPort::SerialPortError error); void comeTrain(const bool &success);
void on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason reason); void on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason reason);
void readTestInfo(); void readTestInfo();
void IdentifyTypeUpdate();
void statusInfoUpdate(const QString &info);
void DebugSlots(const QString &info); void DebugSlots(const QString &info);
void InfoSlots(const QString &info); void InfoSlots(const QString &info);

View File

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

View File

@ -25,6 +25,9 @@ ReadComThread::ReadComThread(MQueue<TrainInfo> *queueTrainInfo,
this->recvLog.setFileName(logRfidRecvName); this->recvLog.setFileName(logRfidRecvName);
this->recvLog.open(QIODevice::ReadWrite | QIODevice::Append); 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::getRfid_signals, this, &ReadComThread::getQueueDataThread);
connect(this, &ReadComThread::IdentifyType, this, &ReadComThread::IdentifyTypeUpdate); connect(this, &ReadComThread::IdentifyType, this, &ReadComThread::IdentifyTypeUpdate);
connect(this, &ReadComThread::upRfid_signals, this, &ReadComThread::upRfid); connect(this, &ReadComThread::upRfid_signals, this, &ReadComThread::upRfid);
@ -93,15 +96,18 @@ void ReadComThread::run()
{ {
while (true) while (true)
{ {
QThread::msleep(100); QThread::msleep(10 * 1000);
if (this->auto_reconnect_serial_) // if (this->auto_reconnect_serial_)
{ // {
QThread::msleep(10 * 1000); // QThread::msleep(10 * 1000);
if ((this->serial_ == nullptr || !this->serial_->isOpen())) // if ((this->serial_ == nullptr || !this->serial_->isOpen()))
{ // {
this->openCom(true, 0); // this->openCom(true, 0);
} // }
} //
// }
} }
} }
@ -111,10 +117,8 @@ void ReadComThread::openCom(const bool &type, const int &msec)
if (type) if (type)
{ {
this->auto_reconnect_serial_ = true; this->auto_reconnect_serial_ = true;
this->serial_ = new QSerialPort(this);
this->serial_ = new QSerialPort; if (this->comDetect_->openCom(this->serial_, this->baseConfig_.comName, this->baseConfig_.baud))
this->serial_ = this->comDetect_.openCom(this->baseConfig_.comName, this->baseConfig_.baud);
if (this->serial_ != nullptr)
{ {
QString logs; QString logs;
logs.append("串口打开成功\n"); logs.append("串口打开成功\n");
@ -126,25 +130,26 @@ void ReadComThread::openCom(const bool &type, const int &msec)
this->InfoSignals(logs); this->InfoSignals(logs);
connect(this->serial_,&QSerialPort::readyRead,this,&ReadComThread::readCom); // connect(this->serial_,&QSerialPort::readyRead,this,&ReadComThread::readCom); //
connect(this->serial_, &QSerialPort::errorOccurred, this, &ReadComThread::serialPort_error); connect(this->serial_, &QSerialPort::errorOccurred, this, &ReadComThread::serialPort_error);
this->openComSuccess(true); emit this->openComSuccess(true);
this->timer_.stop();
this->initParam(); this->initParam();
} }
else else
{ {
this->comDetect_->closeCom(this->serial_);
this->isOpenCom = false; this->isOpenCom = false;
this->ErrorSignals("串口打开失败!"); this->ErrorSignals("串口打开失败!");
this->openComSuccess(false); emit this->openComSuccess(false);
this->timer_.start(10*1000);
} }
} }
else else
{ {
this->auto_reconnect_serial_ = false; this->auto_reconnect_serial_ = false;
if (this->comDetect_.closeCom()) if (this->comDetect_->closeCom(this->serial_))
{ {
this->initParam(); this->initParam();
this->InfoSignals("串口已关闭!"); this->InfoSignals("串口已关闭!");
@ -152,16 +157,23 @@ void ReadComThread::openCom(const bool &type, const int &msec)
} }
else else
{ {
this->closeComSuccess(false); emit this->closeComSuccess(false);
} }
} }
} }
void ReadComThread::tryToReconnect()
{
if (this->auto_reconnect_serial_)
this->openCom(true);
}
void ReadComThread::readCom() void ReadComThread::readCom()
{ {
try { try {
if (this->serial_->waitForReadyRead(10)) { if (this->serial_->waitForReadyRead(10)) {
QByteArray data = this->serial_->readAll(); // 读取数据 QByteArray data = this->serial_->readAll(); // 读取数据
if(!data.isEmpty()) if(!data.isEmpty())
{ {
this->queue_.push(QString(data)); this->queue_.push(QString(data));
@ -449,14 +461,9 @@ void ReadComThread::serialPort_error(QSerialPort::SerialPortError error)
{ {
//关闭串口 //关闭串口
this->serial_->close(); this->serial_->close();
this->ErrorSignals("串口异常退出,疑似接口松动;"); this->ErrorSignals("串口异常退出,疑似接口松动;10秒后自动尝试重连...");
this->openComSuccess(false); emit this->openComSuccess(false);
this->timer_.start(10*1000);
// this->ui->openComButton->setText("打开串口");
// this->ui->LEDlabel->setStyleSheet("border-radius: 16px; \ "
// "background-color: red;\ "
// "border:1px solid rgba(168, 168, 168, 105);");
} }
} }

View File

@ -28,6 +28,7 @@ private:
MQueue<TrainInfo> queueTmpTrainInfo_{}; // RFID临时信息队列 MQueue<TrainInfo> queueTmpTrainInfo_{}; // RFID临时信息队列
QSerialPort *serial_; //串口 QSerialPort *serial_; //串口
bool auto_reconnect_serial_ = false; bool auto_reconnect_serial_ = false;
QTimer timer_;
ai_matrix::BaseConfig baseConfig_; ai_matrix::BaseConfig baseConfig_;
ai_matrix::SServerConfig socketServerConfig_; ai_matrix::SServerConfig socketServerConfig_;
@ -36,7 +37,7 @@ private:
QTcpSocket* tcp_ = nullptr; QTcpSocket* tcp_ = nullptr;
// Com口数据读取类 // Com口数据读取类
ComDetect comDetect_; ComDetect *comDetect_;
// 打开com口标志 // 打开com口标志
bool isOpenCom = false; bool isOpenCom = false;
@ -100,6 +101,7 @@ public slots:
void getQueueDataThread(); void getQueueDataThread();
void IdentifyTypeUpdate(); void IdentifyTypeUpdate();
void upRfid(const QString &rfidInfo); void upRfid(const QString &rfidInfo);
void tryToReconnect();
void readTestInfo(const QString &filePath); void readTestInfo(const QString &filePath);
}; };