1、识别结果单开线程进行数据上传

2、解决可能引起程序崩溃的若干问题
This commit is contained in:
Mr.V 2024-04-08 10:05:36 +08:00
parent 0be507724f
commit 6e6113c48a
8 changed files with 322 additions and 250 deletions

View File

@ -8,7 +8,7 @@ up_result=true
use_socket_server=false
[interface]
http_ip=192.168.2.108
http_ip=192.168.2.212
http_port=20004
token_path=/api/token_path
up_result_path=/api/train-carriage/identification/rfid-save
@ -16,5 +16,5 @@ username=guest_01
password=d55b0f642e817eea24725d2f2a31dd08
[socket_server]
server_ip=172.18.160.1
server_ip=192.168.2.212
server_port=7000

View File

@ -37,6 +37,7 @@ find_package(Qt5 COMPONENTS
QT5_WRAP_CPP(MOC_Files
qt_source/mainwindow.h
interface/TcpClient.h
threads/UpResultThread.h
)
include_directories(
@ -102,6 +103,8 @@ file(GLOB_RECURSE COMMON_SRCS_LISTS
ConfigUtil/*.cpp
# interface
interface/*.cpp
# threads
threads/*.cpp
#
serial/*.cpp
)

View File

@ -17,5 +17,20 @@
#include "Log.h"
#include "StringUtil.h"
namespace ai_matrix {
const QString g_config_path = "./config/config.ini";
struct TrainInfo {
std::string carriageType;
std::string carriageNum;
std::string strOrder;
std::string trainTime;
std::string collectTime;
std::string strRfidInfo;
};
}
#endif //TRAIN_RFID_COMMON_H

View File

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

View File

@ -152,42 +152,13 @@ MainWindow::MainWindow(QWidget *parent)
ui->openComButton->click();
// QThread *thread = new QThread;
// // 创建并移至线程的lambda表达式
// moveToThread(thread);
// connect(thread, &QThread::started, [=]() {
//// // 配置文件读取
//// QString errorMessage = "";
//// ai_matrix::BaseConfig baseConfig;
//// ai_matrix::InterfaceConfig interfaceConfig;
//// if (!ConfigUtil::readBaseConfig(this->configPath_, errorMessage, baseConfig))
//// {
//// this->logError(errorMessage);
//// }
//// if (!ConfigUtil::readInterfaceConfig(this->configPath_, errorMessage, interfaceConfig))
//// {
//// this->logError(errorMessage);
//// }
//
// while (true)
// {
//// if ((this->iDirection == 0 && this->queueTrainInfo_.size() <= 4) || this->iDirection < 0) continue;
// while (!this->queueTrainInfo_.isEmpty())
// {
// TrainInfo trainInfo_ = this->queueTrainInfo_.pop();
// if (!this->upWeb(trainInfo_))
// {
// //this->logError("第" + QString::fromStdString(trainInfo.strOrder) + "节,识别结果上传失败!");
// }
//
//// QThread::msleep(1000);
// }
// QThread::msleep(2000);
// }
// });
//
// connect(thread, &QThread::finished, thread, &QObject::deleteLater);
// thread->start();
this->upResultThread = new UpResultThread(&this->queueTrainInfo_, &this->iDirection, this);
this->upResultThread->start();
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);
}
MainWindow::~MainWindow()
@ -389,175 +360,6 @@ QStandardItem* MainWindow::getStandardItem(const QString &value)
return resultTableItem;
}
/******************************同 web 交互****************************************/
/**
* @brief:Http发送RFID数据
* @paramcarriageType
* @paramcarriageNumber
* @paramcarriageOrder
* @paramtime
* @paramrfidSourceInfoRFID的原始数据
* @return: :true
* :false
*/
bool MainWindow::upWeb(TrainInfo &trainInfo)
{
try {
Json::Value arrayObj; //构建对象
arrayObj["comeTime"] = trainInfo.trainTime;
arrayObj["collectTime"] = trainInfo.collectTime;
arrayObj["carriageNumber"] = trainInfo.carriageNum;
arrayObj["carriageType"] = trainInfo.carriageType;
arrayObj["carriageOrder"] = trainInfo.strOrder;
// arrayObj["steel"] = trainInfo.strRfidInfo;
Json::Value trainParams;
trainParams["poundNo"] = std::to_string(this->baseConfig_.trackName);
arrayObj["trainParams"] = trainParams;
Json::StreamWriterBuilder writer;
std::string str = Json::writeString(writer, arrayObj);
this->logInfo("" + QString::fromStdString(trainInfo.strOrder) + "发送web: " + QString::fromStdString(str));
httplib::Client cli(this->interfaceConfig_.httpIp.toStdString(), this->interfaceConfig_.httpPort);
cli.set_connection_timeout(3, 0);
cli.set_read_timeout(0, 700 * 1000);
httplib::Headers header;
httplib::Params params;
header.emplace("blade-auth", this->webToken);
//header.emplace("Content-Type", "application/json");
auto res = cli.Post(this->interfaceConfig_.upResultPath.toStdString(), header, str, "application/json");
if (res)
{
if (res->status == 200)
{
this->logInfo("" + QString::fromStdString(trainInfo.strOrder) + "web返回: " + QString::fromStdString(res->body));
Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body);
Json::Value root;
std::string errs;
bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
if (parsingSuccessful)
{
if (root["success"].asBool())
{
return true;
}
else
{
if (root["msg"].asString() == "请求未授权") {
this->logWarn("" + QString::fromStdString(trainInfo.strOrder) + "因请求未授权而上传识别结果失败重新请求token。");
if (!this->getToken()) return false;
return this->upWeb(trainInfo);
}
this->logError("" + QString::fromStdString(trainInfo.strOrder) + "节,识别结果上传失败,原因:" + QString::fromStdString(root["msg"].asString()));
}
}
else
{
this->logError("" + QString::fromStdString(trainInfo.strOrder) + "识别结果上传失败返回数据解析异常返回数据非json" + QString::fromStdString(res->body));
}
}
else
{
this->logError("" + QString::fromStdString(trainInfo.strOrder) + "节,识别结果上传失败,原因:" + QString::number(res->status) + " - " + QString::fromStdString(res->body));
if (res->status == 401) {
this->logWarn("因请求未授权而上传识别结果失败重新请求token。");
this->getToken();
return this->upWeb(trainInfo);
}
}
}
else
{
this->logError("" + QString::fromStdString(trainInfo.strOrder) + "节,上传数据失败,请检查网络,或者上传地址!");
}
}
catch (std::exception &e)
{
this->logError("" + QString::fromStdString(trainInfo.strOrder) + "节,上传识别结果失败,原因:");
this->logError(e.what());
}
return false;
}
/**
* @brief:Http获取授权
* @param
* @return:
*/
bool MainWindow::getToken()
{
try
{
httplib::Client cli(this->interfaceConfig_.httpIp.toStdString(), this->interfaceConfig_.httpPort);
cli.set_connection_timeout(0, 300 * 1000);
cli.set_read_timeout(0,300*1000);
httplib::Headers header;
httplib::Params params;
header.emplace("Authorization", "Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0");
params.emplace("username", this->interfaceConfig_.username.toStdString());
params.emplace("password", this->interfaceConfig_.password.toStdString());
params.emplace("tenantId", "000000");
params.emplace("grant_type", "password");
auto res = cli.Post("/api/blade-auth/oauth/token", header, params);
if (res)
{
if (res->status == 200)
{
Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body);
Json::Value root;
std::string errs;
bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
if (parsingSuccessful)
{
if (!root.get("token_type", "").asString().empty())
{
this->webToken = root["token_type"].asString();
this->webToken.append(" ");
this->webToken.append(root["access_token"].asString());
this->logInfo("已获取到web token");
return true;
}
else
{
this->logError("获取web token失败原因" + QString::fromStdString(res->body));
}
}
else
{
this->logError("获取web token返回数据解析异常返回数据非json。详细" + QString::fromStdString(res->body));
}
}
}
else
{
auto err = res.error();
// if (err == httplib::Error::Connection) {
// std::cout << " (连接出错)" << std::endl;
// }
this->logError("获取web token失败请检查网络或请求地址。详细" + QString::fromStdString(to_string(err)));
}
}
catch (std::exception &e)
{
this->logError("获取授权失败,原因:");
this->logError(e.what());
}
return false;
}
/***************************最小化相关****************************************/
/**
* @brief:
@ -630,26 +432,6 @@ void MainWindow::on_ShowMainAction()
this->activateWindow();
}
/**
* @brief:
* @param
* @return:
*/
void MainWindow::on_ExitAppAction()
{
// 弹出对话框要求用户输入密码
QString password = QInputDialog::getText(this, "密码验证", "请输入密码:", QLineEdit::Password);
// 验证账号和密码是否正确
if (password == "matrix") {
this->initParam();
this->tcp_->close();
exit(0);
} else {
QMessageBox::warning(this, "验证失败", "密码不正确!");
}
}
void MainWindow::on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason reason)
{
switch(reason){
@ -895,17 +677,6 @@ void MainWindow::upRfid(QString rfidInfo)
trainInfo.strRfidInfo = rfidInfo.toStdString();
this->queueTrainInfo_.push(trainInfo);
// QtConcurrent::run([=](){
if ((this->iDirection == 0 && this->queueTrainInfo_.size() <= 4) || this->iDirection < 0) return;
while (!this->queueTrainInfo_.isEmpty())
{
TrainInfo trainInfo_ = this->queueTrainInfo_.pop();
if (!this->upWeb(trainInfo_))
{
//this->logError("第" + QString::fromStdString(trainInfo.strOrder) + "节,识别结果上传失败!");
}
}
// });
}
void MainWindow::IdentifyTypeUpdate() {
@ -929,6 +700,22 @@ void MainWindow::IdentifyTypeUpdate() {
}
}
void MainWindow::DebugSlots(const QString &info) {
this->logDebug(info);
}
void MainWindow::InfoSlots(const QString &info) {
this->logInfo(info);
}
void MainWindow::WarnSlots(const QString &info) {
this->logWarn(info);
}
void MainWindow::ErrorSlots(const QString &info) {
this->logError(info);
}
// ============================= 测试 ====================================
void MainWindow::readTestInfo()

View File

@ -52,11 +52,13 @@
#include "ConfigUtil.h"
#include "ComDetect.h"
#include "TcpClient.h"
#include "../threads/UpResultThread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
using namespace ai_matrix;
class MainWindow : public QWidget
{
@ -93,14 +95,8 @@ public:
QStandardItem* getStandardItem(const QString &value);
private:
struct TrainInfo {
std::string carriageType;
std::string carriageNum;
std::string strOrder;
std::string trainTime;
std::string collectTime;
std::string strRfidInfo;
};
UpResultThread *upResultThread;
QString trainTime;
QString logRfidRecvName;
@ -142,9 +138,6 @@ private:
TcpClient* tcpClient;
bool upWeb(TrainInfo &trainInfo);
bool getToken();
private:
QTcpSocket* tcp_ = nullptr;
QStatusBar* statusBar;
@ -159,7 +152,6 @@ private:
void creat_action();
void changeEvent(QEvent *event);
void on_ShowMainAction();
void on_ExitAppAction();
void closeEvent(QCloseEvent *event);
void creat_menu();
@ -178,6 +170,11 @@ private slots:
void readTestInfo();
void IdentifyTypeUpdate();
void DebugSlots(const QString &info);
void InfoSlots(const QString &info);
void WarnSlots(const QString &info);
void ErrorSlots(const QString &info);
private:
Ui::MainWindow *ui;
};

View File

@ -0,0 +1,206 @@
//
// Created by Mr.V on 2024/4/3.
//
#include "UpResultThread.h"
UpResultThread::UpResultThread(MQueue<TrainInfo> *queueTrainInfo, int *iDirection, QObject *parent) :
QThread(parent)
{
this->queueTrainInfo_ = queueTrainInfo;
this->iDirection = iDirection;
// 配置文件读取
QString errorMessage = "";
if (!ConfigUtil::readBaseConfig(g_config_path, errorMessage, this->baseConfig_))
{
this->ErrorSignals(errorMessage);
}
if (!ConfigUtil::readInterfaceConfig(g_config_path, errorMessage, this->interfaceConfig_))
{
this->ErrorSignals(errorMessage);
}
}
void UpResultThread::run()
{
while (true)
{
// if ((*this->iDirection == 0 && this->queueTrainInfo_->size() <= 4) || *this->iDirection < 0) continue;
while (!this->queueTrainInfo_->isEmpty())
{
TrainInfo trainInfo_ = this->queueTrainInfo_->pop();
if (!this->upWeb(trainInfo_))
{
//this->logError("第" + QString::fromStdString(trainInfo.strOrder) + "节,识别结果上传失败!");
}
}
QThread::sleep(1);
}
}
/**
* @brief:Http发送RFID数据
* @paramcarriageType
* @paramcarriageNumber
* @paramcarriageOrder
* @paramtime
* @paramrfidSourceInfoRFID的原始数据
* @return: :true
* :false
*/
bool UpResultThread::upWeb(TrainInfo &trainInfo)
{
try {
Json::Value arrayObj; //构建对象
arrayObj["comeTime"] = trainInfo.trainTime;
arrayObj["collectTime"] = trainInfo.collectTime;
arrayObj["carriageNumber"] = trainInfo.carriageNum;
arrayObj["carriageType"] = trainInfo.carriageType;
arrayObj["carriageOrder"] = trainInfo.strOrder;
arrayObj["steel"] = trainInfo.strRfidInfo;
Json::Value trainParams;
trainParams["poundNo"] = std::to_string(this->baseConfig_.trackName);
arrayObj["trainParams"] = trainParams;
Json::StreamWriterBuilder writer;
std::string str = Json::writeString(writer, arrayObj);
this->InfoSignals("" + QString::fromStdString(trainInfo.strOrder) + "发送web: " + QString::fromStdString(str));
httplib::Client cli(this->interfaceConfig_.httpIp.toStdString(), this->interfaceConfig_.httpPort);
cli.set_connection_timeout(3, 0);
cli.set_read_timeout(3, 0);
httplib::Headers header;
httplib::Params params;
header.emplace("blade-auth", this->webToken);
//header.emplace("Content-Type", "application/json");
auto res = cli.Post(this->interfaceConfig_.upResultPath.toStdString(), header, str, "application/json");
if (res)
{
if (res->status == 200)
{
this->InfoSignals("" + QString::fromStdString(trainInfo.strOrder) + "web返回: " + QString::fromStdString(res->body));
Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body);
Json::Value root;
std::string errs;
bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
if (parsingSuccessful)
{
if (root["success"].asBool())
{
return true;
}
else
{
if (root["msg"].asString() == "请求未授权") {
this->WarnSignals("" + QString::fromStdString(trainInfo.strOrder) + "因请求未授权而上传识别结果失败重新请求token。");
if (!this->getToken()) return false;
return this->upWeb(trainInfo);
}
this->ErrorSignals("" + QString::fromStdString(trainInfo.strOrder) + "节,识别结果上传失败,原因:" + QString::fromStdString(root["msg"].asString()));
}
}
else
{
this->ErrorSignals("" + QString::fromStdString(trainInfo.strOrder) + "识别结果上传失败返回数据解析异常返回数据非json" + QString::fromStdString(res->body));
}
}
else
{
this->ErrorSignals("" + QString::fromStdString(trainInfo.strOrder) + "节,识别结果上传失败,原因:" + QString::number(res->status) + " - " + QString::fromStdString(res->body));
if (res->status == 401) {
this->WarnSignals("因请求未授权而上传识别结果失败重新请求token。");
this->getToken();
return this->upWeb(trainInfo);
}
}
}
else
{
this->ErrorSignals("" + QString::fromStdString(trainInfo.strOrder) + "节,上传数据失败,请检查网络,或者上传地址!");
}
}
catch (std::exception &e)
{
this->ErrorSignals("" + QString::fromStdString(trainInfo.strOrder) + "节,上传识别结果失败,原因:" + QString::fromStdString(e.what()));
}
return false;
}
/**
* @brief:Http获取授权
* @param
* @return:
*/
bool UpResultThread::getToken()
{
try
{
httplib::Client cli(this->interfaceConfig_.httpIp.toStdString(), this->interfaceConfig_.httpPort);
cli.set_connection_timeout(0, 300 * 1000);
cli.set_read_timeout(0,300*1000);
httplib::Headers header;
httplib::Params params;
header.emplace("Authorization", "Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0");
params.emplace("username", this->interfaceConfig_.username.toStdString());
params.emplace("password", this->interfaceConfig_.password.toStdString());
params.emplace("tenantId", "000000");
params.emplace("grant_type", "password");
auto res = cli.Post("/api/blade-auth/oauth/token", header, params);
if (res)
{
if (res->status == 200)
{
Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body);
Json::Value root;
std::string errs;
bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
if (parsingSuccessful)
{
if (!root.get("token_type", "").asString().empty())
{
this->webToken = root["token_type"].asString();
this->webToken.append(" ");
this->webToken.append(root["access_token"].asString());
this->InfoSignals("已获取到web token");
return true;
}
else
{
this->ErrorSignals("获取web token失败原因" + QString::fromStdString(res->body));
}
}
else
{
this->ErrorSignals("获取web token返回数据解析异常返回数据非json。详细" + QString::fromStdString(res->body));
}
}
}
else
{
auto err = res.error();
// if (err == httplib::Error::Connection) {
// std::cout << " (连接出错)" << std::endl;
// }
this->ErrorSignals("获取web token失败请检查网络或请求地址。详细" + QString::fromStdString(to_string(err)));
}
}
catch (std::exception &e)
{
this->ErrorSignals("获取授权失败,原因:" + QString::fromStdString(e.what()));
}
return false;
}

View File

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