diff --git a/.gitignore b/.gitignore index ef8fbe8..2f5056e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ # Compiled Dynamic libraries *.so *.dylib -*.dll +#*.dll # Fortran module files *.mod diff --git a/app/config/config.ini b/app/config/config.ini index 05b9b64..bebc858 100644 --- a/app/config/config.ini +++ b/app/config/config.ini @@ -16,5 +16,6 @@ username=guest_01 password=d55b0f642e817eea24725d2f2a31dd08 [socket_server] -server_ip=192.168.2.212 +server_ip=192.168.2.1 server_port=7000 +delayed_upload=4 diff --git a/lib/libcurl.dll b/lib/libcurl.dll new file mode 100644 index 0000000..95a722d Binary files /dev/null and b/lib/libcurl.dll differ diff --git a/lib/libyaml-cpp.dll b/lib/libyaml-cpp.dll new file mode 100644 index 0000000..ffea4be Binary files /dev/null and b/lib/libyaml-cpp.dll differ diff --git a/lib/libyaml-cpp.dll.a b/lib/libyaml-cpp.dll.a new file mode 100644 index 0000000..b955c95 Binary files /dev/null and b/lib/libyaml-cpp.dll.a differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 78dc96b..589a1aa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,6 +38,7 @@ QT5_WRAP_CPP(MOC_Files qt_source/mainwindow.h interface/TcpClient.h threads/UpResultThread.h + threads/ReadComThread.h ) include_directories( @@ -70,6 +71,8 @@ include_directories( interface # 串口信息处理逻辑 serial + # 线程逻辑 + threads ) diff --git a/src/ConfigUtil/ConfigUtil.h b/src/ConfigUtil/ConfigUtil.h index d4edac9..ac1993b 100644 --- a/src/ConfigUtil/ConfigUtil.h +++ b/src/ConfigUtil/ConfigUtil.h @@ -7,48 +7,9 @@ #include #include #include +#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; - // 识别结果延后X节上传,以等待Socket反馈火车运行方向 - int delayed_upload; - }; }; class ConfigUtil { diff --git a/src/common/common.cpp b/src/common/common.cpp index 28dae35..1ce3a84 100644 --- a/src/common/common.cpp +++ b/src/common/common.cpp @@ -1,6 +1,4 @@ // // Created by Mr.V on 2023/8/16. // -#include "common.h" -QString io_car = ""; -QString direction = ""; \ No newline at end of file +#include "common.h" \ No newline at end of file diff --git a/src/common/common.h b/src/common/common.h index 0593c34..49bbc85 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -20,6 +20,51 @@ namespace ai_matrix { const QString g_config_path = "./config/config.ini"; + // --- 配置文件 --- + + 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; + // 识别结果延后X节上传,以等待Socket反馈火车运行方向 + int delayed_upload; + }; + // --- 配置文件 --- + struct TrainInfo { std::string carriageType; std::string carriageNum; @@ -38,6 +83,11 @@ namespace ai_matrix { }; }; + struct RfidInfo { + QString rfid; + QString rfidTime; + }; + } diff --git a/src/qt_source/mainwindow.cpp b/src/qt_source/mainwindow.cpp index afa0054..112783e 100644 --- a/src/qt_source/mainwindow.cpp +++ b/src/qt_source/mainwindow.cpp @@ -21,7 +21,6 @@ MainWindow::MainWindow(QWidget *parent) layout()->addWidget(this->statusBar); this->setWindowTitle("Matrix_RFID 车号识别程序(勿关!!)"); - this->configPath_ = "./config/config.ini"; if (!this->mkLogDir()) { @@ -30,15 +29,7 @@ MainWindow::MainWindow(QWidget *parent) // 配置文件读取 QString errorMessage = ""; - if (!ConfigUtil::readBaseConfig(this->configPath_, 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::readBaseConfig(g_config_path, errorMessage, this->baseConfig_)) { this->logError(errorMessage); } @@ -49,27 +40,13 @@ 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();//最小化 // 设置最大展示数据行数 @@ -80,91 +57,52 @@ MainWindow::MainWindow(QWidget *parent) 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); + 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 == 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 = new UpResultThread(&this->queueTrainInfo_, this); 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::InfoSignals, this, &MainWindow::InfoSlots); connect(this->upResultThread, &UpResultThread::WarnSignals, this, &MainWindow::WarnSlots); connect(this->upResultThread, &UpResultThread::ErrorSignals, this, &MainWindow::ErrorSlots); + + ui->openComButton->click(); } MainWindow::~MainWindow() { this->logInfo("-- 程序退出 --"); - this->initParam(); delete ui; } @@ -184,16 +122,8 @@ void MainWindow::logError(const QString& message) { LogError << message.toStdString(); ui->textBrowser->append(QString("[Error] [") + this->getSystemTime() + QString::fromStdString("] ") + message); } - -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::statusInfoUpdate(const QString &info) { + this->statusInfo->setText(info); } /** @@ -212,80 +142,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,12 +158,13 @@ QList 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: 30px; background-color: rgb(255, 255, 255); color: rgb(225, 225, 225);}"); 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: 30px; background-color: rgb(255, 255, 255); color: rgb(225, 225, 225);}"); ui->comBox->setMaxVisibleItems(5); ui->comBox->setView(new QListView()); ui->comBox->addItems(this->comList); @@ -325,9 +182,6 @@ void MainWindow::initComboBox() { ui->BTBox->setCurrentText(QString::number(this->baseConfig_.baud)); 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") { - this->initParam(); - this->tcp_->close(); event->accept(); // 关闭窗口 exit(0); } else { @@ -451,33 +303,6 @@ void MainWindow::on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason reaso } /********************************串口操作*************************************/ -bool MainWindow::connectCom() -{ - this->serial_ = this->comDetect_.openCom(ui->comBox->currentText(), ui->BTBox->currentText().toInt()); - - 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->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); - return true; - } - else - { - return false; - } -} - /** * 打开串口 */ @@ -486,306 +311,78 @@ void MainWindow::openComClicked() if (ui->openComButton->text() == "打开串口") { this->auto_reconnect_serial_ = true; - this->ui->openComButton->setText("关闭串口"); - QtConcurrent::run([=](){ - while (this->auto_reconnect_serial_ && !this->isOpenCom) { - if (!this->connectCom()) - { - this->isOpenCom = false; - this->comDetect_.closeCom(); - this->logInfo("串口打开失败!10秒钟后将会重连..."); - } else { - return ; - } - QThread::sleep(10); - } - }); - - - -// this->serial_ = this->comDetect_.openCom(ui->comBox->currentText(), ui->BTBox->currentText().toInt()); -// -// 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->comDetect_.closeCom(); -// this->logInfo("串口打开失败!10秒钟后将会重连..."); -// this->ui->openComButton->setText("关闭串口"); -// -// QtConcurrent::run([=](){ -// QThread::sleep(10); -// if (this->auto_reconnect_serial_ && !this->isOpenCom) { -// ui->openComButton->click(); -// } -// }); -// } + emit openCom_signals(true); } else { - this->auto_reconnect_serial_ = false; - if (this->isOpenCom) - { - // 弹出对话框要求用户输入密码 - QString password = QInputDialog::getText(this, "密码验证", "请输入密码:", QLineEdit::Password); + // 弹出对话框要求用户输入密码 + QString password = QInputDialog::getText(this, "密码验证", "请输入密码:", QLineEdit::Password); - // 验证账号和密码是否正确 - 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);"); - } - } else { - QMessageBox::warning(this, "验证失败", "密码不正确!"); + // 验证账号和密码是否正确 + if (password == "matrix") { + this->auto_reconnect_serial_ = false; + + if (this->comDetect_.closeCom()) + { + emit openCom_signals(false); } - } - else - { - this->logInfo("串口已停止访问!"); - this->ui->openComButton->setText("打开串口"); + } 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);"); - QtConcurrent::run([=](){ - QThread::sleep(10); - if (this->auto_reconnect_serial_ && !this->isOpenCom) { - this->connectCom(); - } - }); + + this->logInfo("10秒钟后自动尝试重连串口..."); +// if (auto_reconnect_serial_) emit openCom_signals(true, 10 * 1000); } } -void MainWindow::readCom() +void MainWindow::closeComResult(const bool &success) { - 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("读取串口数据异常!"); + 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);"); } } -/** - * @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::comeTrain(const bool &success) { + this->resultTableModel_->clear(); + this->resultTableModel_ = this->getStandardItemModel(); } -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(); - - 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->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("火车离开了"); + } else { + QIcon icon("./Fail.ico"); + QPixmap m_pic = icon.pixmap(icon.actualSize(QSize(32, 32)));//size自行调整 + this->ui->upflagLabel->setPixmap(m_pic); } } @@ -809,32 +406,16 @@ void MainWindow::ErrorSlots(const QString &info) { void MainWindow::readTestInfo() { - - if (this->isOpenCom || ui->openComButton->text() == "关闭串口") + 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); } \ No newline at end of file diff --git a/src/qt_source/mainwindow.h b/src/qt_source/mainwindow.h index 73c6ac4..f585011 100644 --- a/src/qt_source/mainwindow.h +++ b/src/qt_source/mainwindow.h @@ -49,10 +49,11 @@ #include #include #include "common.h" -#include "ConfigUtil.h" + #include "ComDetect.h" -#include "TcpClient.h" -#include "../threads/UpResultThread.h" + +#include "UpResultThread.h" +#include "ReadComThread.h" QT_BEGIN_NAMESPACE @@ -73,17 +74,10 @@ public: void logWarn(const QString& message); void logError(const QString& message); // 创建日志目录 - static bool mkLogDir(); - bool mkRfidLog(); - void deleteOldFiles(const QString &path, int days); - bool rnameRfidLog(); - void saveRfidLog(const QString &value); - bool connectCom(); + bool mkLogDir(); void initParam(); - - QString getSystemTime(); // 获const 取串口列表& @@ -98,8 +92,7 @@ public: private: UpResultThread *upResultThread; - QString trainTime; - bool auto_reconnect_serial_ = false; + ReadComThread *readComThread; QString logRfidRecvName; QFile recvLog; @@ -107,15 +100,14 @@ private: QString configPath_; // ai_matrix::BaseConfig baseConfig_; 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_; // com口列表 @@ -124,25 +116,15 @@ private: QStringList vecTrain; MQueue queue_{}; // RFID读取的数据队列 MQueue queueTrainInfo_{}; // RFID读取的磁钢信息队列 - MQueue queueTmpTrainInfo_{}; // RFID临时信息队列 + 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; QLabel *statusInfo; @@ -159,19 +141,19 @@ private: 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); + private slots: 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 DebugSlots(const QString &info); void InfoSlots(const QString &info); diff --git a/src/threads/ReadComThread.cpp b/src/threads/ReadComThread.cpp new file mode 100644 index 0000000..e2ff80e --- /dev/null +++ b/src/threads/ReadComThread.cpp @@ -0,0 +1,485 @@ +// +// Created by Mr.V on 2024/4/15. +// + +#include "ReadComThread.h" + +ReadComThread::ReadComThread(MQueue *queueTrainInfo, + QObject *parent) : + QThread(parent) +{ + // 配置文件读取 + QString errorMessage = ""; + if (!ConfigUtil::readBaseConfig(g_config_path, errorMessage, this->baseConfig_)) + { + this->ErrorSignals(errorMessage); + } + if (!ConfigUtil::readSocketServerConfig(g_config_path, errorMessage, this->socketServerConfig_)) + { + this->ErrorSignals(errorMessage); + } + + this->queueTrainInfo_ = queueTrainInfo; + + this->logRfidRecvName = "./Logs/rfid_data.txt"; + this->recvLog.setFileName(logRfidRecvName); + this->recvLog.open(QIODevice::ReadWrite | QIODevice::Append); + + 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){ + this->InfoSignals(info); + this->statusInfoUpdate(info); + if (info == "链接服务端超时" + || info == "未连接Socket服务器" + || info == "链接服务端失败" + || info == "服务端断开连接" + || info == "链接服务端失败") + { + this->videoHasTrain = false; + } + }); + // 接收子线程的TCP消息内容展示 + connect(this->tcpClient, &TcpClient::getTcpInfoSignals, this, [=](const QString& info){ + this->InfoSignals(info); + }); + + emit connect_socket(this->socketServerConfig_.server_ip, this->socketServerConfig_.server_port); + + connect(this->tcpClient, &TcpClient::comeTrainSignals, this, [=](bool type) { + if (type) + { + this->InfoSignals("视频车号识别-来车了"); + this->videoHasTrain = true; + emit IdentifyType(); + } + else + { + this->InfoSignals("视频车号识别-火车离开了"); + this->videoHasTrain = false; + if (this->needIdentify) + emit IdentifyType(); + } + }); + connect(this->tcpClient, &TcpClient::getDirectionSignals, this, [=](int direction) { + if (this->iDirection == 0) + { + this->InfoSignals("获得方向判定:" + QString(direction > -1 ? (direction > 0 ? "需识别" : "待定") : "无需上传")); + this->iDirection = direction; + } + }); + } +} + +void ReadComThread::run() +{ + while (true) + { + QThread::msleep(100); + 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->serial_ = this->comDetect_.openCom(this->baseConfig_.comName, this->baseConfig_.baud); + if (this->serial_ != nullptr) + { + QString logs; + logs.append("串口打开成功\n"); + logs.append("串口号:" + this->baseConfig_.comName + "\n"); + logs.append("波特率:" + QString::number(this->baseConfig_.baud) + "\n"); + if (this->baseConfig_.havaMagnetSteel) + logs.append("磁钢顺序:" + this->baseConfig_.magnetSteelOrder); + this->isOpenCom = true; + this->InfoSignals(logs); + + connect(this->serial_,&QSerialPort::readyRead,this,&ReadComThread::readCom); // + + connect(this->serial_, &QSerialPort::errorOccurred, this, &ReadComThread::serialPort_error); + + this->openComSuccess(true); + + this->initParam(); + } + else + { + this->isOpenCom = false; + this->ErrorSignals("串口打开失败!"); + this->openComSuccess(false); + } + } + else + { + this->auto_reconnect_serial_ = false; + + if (this->comDetect_.closeCom()) + { + this->initParam(); + this->InfoSignals("串口已关闭!"); + this->closeComSuccess(true); + } + else + { + this->closeComSuccess(false); + } + } +} + +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 + { + this->ErrorSignals("等待读取超时"); + } + } catch(...) { + this->ErrorSignals("读取串口数据异常!"); + } +} + +void ReadComThread::readTestInfo(const QString &filePath) { + // 创建一个QFile对象并打开要读取的文本文件 + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + this->ErrorSignals("无法打开测试文件:" + filePath); + return; + } + this->InfoSignals("开始读取测试数据..."); + // 将文件内容读入到QStringList中 + QTextStream in(&file); + while(!in.atEnd()) { + QString line = in.readLine(); + this->queue_.push(line); + emit getRfid_signals(); + } + // 关闭文件 + file.close(); + 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); + 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->InfoSignals("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->InfoSignals("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->addResultSignals(strTrainInfo); + 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->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 ReadComThread::IdentifyTypeUpdate() { + if (this->rfidHasTrain || this->videoHasTrain) + { + if (!this->needIdentify) + { + this->InfoSignals("来车了"); + this->mkRfidLog(); + this->vecTrain.clear(); + this->needIdentify = true; + this->trainTime = this->getSystemTime(); + emit this->comeTrain(false); + + } + } + else if (!this->rfidHasTrain && !this->videoHasTrain) + { + this->initParam(); + this->InfoSignals("火车离开了"); + } +} + +void ReadComThread::upRfid(const QString &rfidInfo) +{ + if (!this->baseConfig_.upResult) return; + if (!this->needIdentify && this->baseConfig_.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()); + } + } +} + +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) { + this->ErrorSignals("创建、打开RFID原始数据日志文件失败,详细:"); + 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) { + 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)) + { + this->ErrorSignals("读取RFID原始数据,存储重命名失败!"); + return false; + } + + this->deleteOldFiles(fileInfo.path(), 3); + } catch (const std::exception &e) { + 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(); + this->ErrorSignals("串口异常退出,疑似接口松动;"); + this->openComSuccess(false); + +// this->ui->openComButton->setText("打开串口"); + +// this->ui->LEDlabel->setStyleSheet("border-radius: 16px; \ " +// "background-color: red;\ " +// "border:1px solid rgba(168, 168, 168, 105);"); + } +} + +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"); +} + diff --git a/src/threads/ReadComThread.h b/src/threads/ReadComThread.h new file mode 100644 index 0000000..1521096 --- /dev/null +++ b/src/threads/ReadComThread.h @@ -0,0 +1,108 @@ +// +// Created by Mr.V on 2024/4/15. +// + +#ifndef TRAIN_RFID_READCOMTHREAD_H +#define TRAIN_RFID_READCOMTHREAD_H +#include +#include +#include +#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 *queueTrainInfo, + QObject *parent = nullptr); + ~ReadComThread() {}; + void run() override; + +private: + MQueue *queueTrainInfo_ = nullptr; + MQueue queueTmpTrainInfo_{}; // RFID临时信息队列 + QSerialPort *serial_; //串口 + bool auto_reconnect_serial_ = false; + + ai_matrix::BaseConfig baseConfig_; + ai_matrix::SServerConfig socketServerConfig_; + + TcpClient* tcpClient; + QTcpSocket* tcp_ = nullptr; + + // Com口数据读取类 + ComDetect comDetect_; + // 打开com口标志 + bool isOpenCom = false; + + // RFID读取的数据队列 + MQueue queue_{}; + + QString logRfidRecvName; + QFile recvLog; + + QString trainTime; + // 是否是需要识别的方向 -1:不识别 0:未确定 1:识别 + int iDirection = 0; + // 整列车识别结果存储 + QStringList vecTrain; + QString rfidSourceInfo; + QString tmpRfid; //临时存储的RFID原始数据,用于防止接收的数据不完整 + + // 识别方向正确标志 + 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 readTestInfo(const QString &filePath); +}; + + +#endif //TRAIN_RFID_READCOMTHREAD_H diff --git a/src/threads/UpResultThread.cpp b/src/threads/UpResultThread.cpp index 7c88f72..ed186bd 100644 --- a/src/threads/UpResultThread.cpp +++ b/src/threads/UpResultThread.cpp @@ -5,11 +5,10 @@ #include "UpResultThread.h" -UpResultThread::UpResultThread(MQueue *queueTrainInfo, int *iDirection, QObject *parent) : +UpResultThread::UpResultThread(MQueue *queueTrainInfo, QObject *parent) : QThread(parent) { this->queueTrainInfo_ = queueTrainInfo; - this->iDirection = iDirection; // 配置文件读取 QString errorMessage = ""; diff --git a/src/threads/UpResultThread.h b/src/threads/UpResultThread.h index c82da54..2d7111e 100644 --- a/src/threads/UpResultThread.h +++ b/src/threads/UpResultThread.h @@ -19,13 +19,12 @@ class UpResultThread : public QThread{ public: ~UpResultThread() {}; - UpResultThread(MQueue *queueTrainInfo, int *iDirection, QObject *parent = nullptr); + UpResultThread(MQueue *queueTrainInfo, QObject *parent = nullptr); void run() override; private: MQueue *queueTrainInfo_ = nullptr; - int *iDirection; ai_matrix::BaseConfig baseConfig_; ai_matrix::InterfaceConfig interfaceConfig_; std::string webToken; //授权信息