Train_RFID/source/mainwindow.cpp

856 lines
28 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "MainWindow.h"
#include "ui_MainWindow.h"
#define DEBUG_HTTP 1
MainWindow::MainWindow(QWidget *parent)
: QWidget(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowTitle("Matrix");
btrainLeave = true;
baccredit = false;
m_sendHttpSign = false;
m_icarriageOrder = 0;
m_icot = 0;
bdir = false;
szHavdcarTime = "";
if (_access("Logs", 0) == -1) { //判断是否存在日志的文件夹,没有则创建
std::string folderPath = "Logs";
if (0 != _mkdir(folderPath.c_str()))
{
_mkdir(folderPath.c_str()); // 返回 0 表示创建成功,-1 表示失败
}
}
serial = new QSerialPort;
m_pSystemTray=new QSystemTrayIcon(this);
//读取配置文件
read_configure_file();
//设置并打开串口
// set_uart_parameter();
//串口接收数据信号槽
//connect(serial,&QSerialPort::readyRead,this,&MainWindow::rece_data_slots);
QTimer* timer = new QTimer(this);
// connect(timer, &QTimer::timeout, this, &MainWindow::rece_data_slots);
// 设置定时器的时间间隔例如50毫秒
// timer->start(10);
//最小化信号槽
connect(m_pSystemTray,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason)));
//获取系统时间
get_system_time();
QString logName = "Logs/ceshi.txt";
logtest.setFileName(logName);
logtest.open(QIODevice::ReadWrite | QIODevice::Append);
QString logNamerecv = "Logs/recv.txt";
logrecv.setFileName(logNamerecv);
logrecv.open(QIODevice::ReadWrite | QIODevice::Append);
//初始最小化
//this->showMinimized();//最小化
// 设置最大展示数据行数
this->ui->textBrowser->document()->setMaximumBlockCount(1000);
tid = std::thread(&MainWindow::get_queue_data,this);
}
MainWindow::~MainWindow()
{
serial->close();
logOut.close();
// if(tid.joinable()){
// tid.join();
// }
delete ui;
}
/**
* @brief:从queue中获取数据
* @param:空
* @return:空
*/
void MainWindow::get_queue_data(){
std::string szData = "";
while(1)
{
bool bData = false;
while(queData.size() > 0)
{
std::lock_guard<std::mutex> lk(mtx_sync_);
std::string str_temp = queData.front();
queData.pop();
szData.append(str_temp);
if(szData.size() >= 8 && szData.front() == '@' && szData.back() == '&')
{
bData = true;
break;
}
}
if(bData){
deal_str_data(szData);
szData.clear();
}
std::this_thread::sleep_for(std::chrono::microseconds(20));
}
}
/**
* @brief:解析数据
* @param:szStr:从queue中取到的字符串
* @return:空
*/
void MainWindow::deal_str_data(const std::string &szStr)
{
std::string szcarModel = "";
std::string szcarNumber = "";
get_system_time();
std::string logstr = "长度:" + std::to_string(szStr.size()) + " 数据:" + szStr;
print_log(logstr);
int apos = 0,spos = 0;
int cout = std::count(szStr.begin(),szStr.end(),'@');
if(cout > 0)
{
for (int i = 0;i < cout;i++)
{
apos = szStr.find('@',apos);
spos = szStr.find('&',spos);
if(apos == std::string::npos || spos == std::string::npos){
break;
}
std::string szdata = szStr.substr(apos,spos - apos + 1);
ui->textBrowser->append(QString::fromStdString(szdata));
apos++;
spos++;
if (szdata.size() == 9)
{
if(szdata.at(1) == '0' && bdir==true && ((c_carnum == "" || zhcarNumber == c_carnum)|| io_car=="0"))
{//火车离开了关功放
std::string logstr = "火车离开了 ... ...总共车节数 " + std::to_string(m_icarriageOrder) + " 方向:" + m_direction +" 进车完成" + io_car.toStdString();
btrainLeave = true;
m_icot =0;
m_icot2=0;
m_flag=false;
m_icarriageOrder = 0;
m_direction.clear();
m_veclabel.clear();
m_sendHttpSign = false;
judget = false;
bdir = false ;
io_car ="";
//std::string logstr = "火车离开了 ... ...总共车节数 " + std::to_string(m_icarriageOrder) + " 方向:" + m_direction;
print_log(logstr);
ui->textBrowser->append(QString::fromStdString(logstr));
break;
}
if(szdata.at(1) == '0' && bdir==false && ((zhcarNumber == c_carnum && m_direction.compare("1") && m_direction.compare("14"))||io_car=="0"))
{
std::string logstr = "火车离开了 ... ...总共车节数 " + std::to_string(m_icarriageOrder) + " 方向:" + m_direction+" 装车完成" + io_car.toStdString();
btrainLeave = true;
m_icot =0;
m_icot2=0;
m_flag=false;
m_icarriageOrder = 0;
io_car ="";
m_direction.clear();
m_veclabel.clear();
m_sendHttpSign = false;
judget = false;
print_log(logstr);
ui->textBrowser->append(QString::fromStdString(logstr));
break;
}
if(szdata.at(1) == '0' && (m_direction.size()==1) && m_icot == 1)
{
std::string logstr = " 触碰磁钢关闭 ";
btrainLeave = true;
//m_icot =0;
m_icot2=0;
m_flag=false;
m_icarriageOrder = 0;
m_direction.clear();
m_veclabel.clear();
m_sendHttpSign = false;
judget = false;
print_log(logstr);
ui->textBrowser->append(QString::fromStdString(logstr));
break;
}
if(szdata.at(1) == '8'||szdata.at(1) == '2'||szdata.at(1) == '1'||szdata.at(1) == '4')
{//磁钢数据处理
m_icot++;
if(m_flag==true)
{
m_icot2++;
}
if(judget == false)
{
auto itmp = m_direction.find(szdata.at(1));
if(itmp == std::string::npos){
m_direction.append(szdata.substr(1,1));
}
if(m_icot > 3){
bdir = Judge_direction();
if(m_direction == "8") //识别的单磁钢号为存储的最后一位时方向为false
{
bdir = false;
}
if(direction == "2")
{
bdir = true;
}
QString logs = "识别到的方向" + QString::number(bdir)+ " dir:" + QString::fromStdString(m_direction);
ui->textBrowser->append(logs);
print_log(logs.toStdString());
judget = true;
}
szHavdcarTime = szcurrentTime.substr(0, 19);
}
QString logs = QString::fromStdString("------------------------dir:" + m_direction + " 方向:" + std::to_string(bdir) + " 次数:" + std::to_string(m_icot) + " 车号:" + c_carnum+"io_car:"+io_car.toStdString()+"mv方向"+direction.toStdString());
ui->textBrowser->append(logs);
print_log(logs.toStdString());
if(m_icot > 25 && bdir==true)
{
m_flag=true;
c_carnum = szcarNumber; //获取车号
m_icarriageOrder++;
lc_carnum = m_icarriageOrder;
m_sendHttpSign = true;
m_icot = 0; //不在发送时清空 是防止装车方向最后一个为空
m_icot2= 0;
}
if(m_icot > 25 && bdir == false)
{
c_carnum = szcarNumber;
m_icot = 0;
}
//连续两节车丢标签逻辑
if(m_icot2 > 15 && bdir==true)
{
m_icarriageOrder++;
int k= m_icarriageOrder - 1 ;
if(lc_carnum == k) //连续
{
c_carnum = szcarNumber;
lc_carnum = m_icarriageOrder;
m_sendHttpSign = true;
m_icot = 0 ;
m_icot2 = 0;
}
else if(lc_carnum != k) //bu连续
{
m_icarriageOrder--;
m_sendHttpSign = false;
m_icot2 = 0;
m_flag = false;
}
}
QString log = QString::fromStdString(szcurrentTime + szdata + " 次:" + std::to_string(m_icot) + " 方向:" + m_direction +"io_car:"+io_car.toStdString()+"mv方向"+direction.toStdString()+"\r\n");
logtest.write(log.toUtf8());
logtest.flush();
}
}
else if (szdata.size() == 28)
{//车厢信息处理
btrainLeave = false; //火车没有离开
std::string logstr = "车厢数据:" + szdata;
print_log(logstr);
szcarModel = szdata.substr(2, 5); //车型
szcarModel.erase(std::remove(szcarModel.begin(), szcarModel.end(), ' '), szcarModel.end()); //删除其中的空格
szcarNumber = szdata.substr(8, 7); //车厢号
c_carnum = szcarNumber;
std::cout << "szcarModel" << szcarModel << " szcarNumber" << szcarNumber << std::endl;
bool bret = label_compare(szcarNumber); //判断车厢号是否存在
if(bret == false){
m_icot = 0;
continue;
}
m_veclabel.push_back(szcarNumber);
m_icarriageOrder++;
if(m_icarriageOrder==1 && bdir == true)
{
zhcarNumber = szcarNumber;
c_carnum ="1";
}
m_sendHttpSign = true; //有车厢信息一定上传
if(szcarModel.at(0) != 'C' && szcarModel != "")
{
m_sendHttpSign = false;
m_icarriageOrder--;
c_carnum = "";
szcarModel = "";
szcarNumber = "";
}
QString log = QString::fromStdString(szcurrentTime + "------------------------------收到车厢数据\r\n");
m_icot = 0;
m_icot2= 0;
logtest.write(log.toUtf8());
logtest.flush();
}
if(m_sendHttpSign == true && bdir == true)
{
QString log = QString::fromStdString(szcurrentTime + "发送车厢数据------------------------------方向:" + m_direction + " 车节号" + std::to_string(m_icarriageOrder) +"\r\n\r\n\r\n");
logtest.write(log.toUtf8());
logtest.flush();
m_sendHttpSign = false;
itime = 0;
deal_uart_data(szcarModel,szcarNumber);
}
}
}
}
/*
* 函数名:Logs()
* 功能:打印日志
* 参数:
* (空)
* 返回值:
* (预留)
*/
int MainWindow::debug_log_printf(std::string daystime)
{
logOut.close();
QString logName = "Logs/" + QString::fromStdString(daystime) + ".txt";
logOut.setFileName(logName);
if(!logOut.open(QIODevice::ReadWrite | QIODevice::Append))
{
return false;
}
return -1;
}
/**
* @brief:打印加输出日志
* @paramtime时间
* @paramlogstr打印字符串
* @return:空
*/
void MainWindow::print_log(std::string logstr)
{
//检查是否需要创建日志
if (szlastTime.compare(szcurrentTime.substr(0, 10))) // && btrainLeave == true
{
szlastTime = szcurrentTime.substr(0, 10);
int ret = debug_log_printf(szlastTime);
if (ret < 0)
{
std::cout << "Log file creat error" << std::endl;
}
}
QString log = QString::fromStdString(szcurrentTime + logstr + "\r\n");
logOut.write(log.toUtf8());
logOut.flush();
qDebug() << log;
}
/**
* @brief:获取系统时间
* @param
* @return:空
*/
void MainWindow::get_system_time()
{
szcurrentTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz").toStdString();
}
/**
* @brief:放倒车
* @paramlabel:车型
* @return:false 存在;true 不存在
*/
bool MainWindow::label_compare(std::string &label)
{
if (m_veclabel.size() == 0)
return true;
std::vector <std::string>::const_iterator itr = std::find(m_veclabel.begin(), m_veclabel.end(),label);
if (itr != m_veclabel.end()) {
return false;
}
return true;
}
//false 和配置方向相反
//true 和配置方向相同
bool MainWindow::Judge_direction()
{
if(!m_direction.compare(configureInfo_T.configDirection) || m_direction.at(0) == configureInfo_T.configDirection.at(0)){
return true;
}
int pos = configureInfo_T.configDirection.find(m_direction.at(0));
for(int i = 0; i < pos;i++){
auto dirpos = m_direction.find(configureInfo_T.configDirection.at(pos - 1));
if(dirpos != std::string::npos){
return false;
}
}
return true;
}
void MainWindow::rece_data_slots()
{
QByteArray data = serial->readAll(); // 读取数据
if(!data.isEmpty())
{
std::lock_guard<std::mutex> lk(mtx_sync_);
queData.push(QString(data).toStdString());
QString log = QString::fromStdString(szcurrentTime) + QString(data);
logrecv.write(log.toUtf8());
logrecv.flush();
}
data.clear();
}
/**
* @brief:解析协议1的串口数据。
* @paramszcarModel 车型
* @paramszcarNumber车厢号
* @return: 成功:true
* 失败:false
*/
bool MainWindow::deal_uart_data(std::string &szcarModel,std::string &szcarNumber)
{
print_log("进入数据发送流程");
std::string sztime = szHavdcarTime;
#if DEBUG_HTTP
int ix = 0;
do{
ix++;
std::string ord = std::to_string(m_icarriageOrder);
int ret = http_send(szcarModel, szcarNumber,ord,sztime);
if(ret == -2){
std::this_thread::sleep_for(std::chrono::milliseconds(50));
continue;
}else{
break;
}
}while(ix < 3);
#endif
std::string str = "***************************车型:" + szcarModel + " 车号:" + szcarNumber + " 车节号:" + std::to_string(m_icarriageOrder);
ui->textBrowser->append(QString::fromStdString(str));
print_log(str);
return true;
}
/**
* @brief:Http发送RFID数据
* @paramcarModel车型
* @paramcarNum车号
* @paramcatFrequency车节号
* @paramtime当前时间
* @return: 成功:true
* 失败:false
*/
int MainWindow::http_send(std::string &carriageType, std::string &carriageNumber, std::string &carriageOrder, std::string &time)
{
httplib::Client cli(configureInfo_T.ip, std::atoi(configureInfo_T.port.c_str()));
httplib::Headers header;
httplib::Params params;
Json::Value arrayObj; //构建对象
if (baccredit)
{
header.emplace("blade-auth", accreditInformation);
//header.emplace("Content-Type", "application/json");
arrayObj["comeTime"] = time;
arrayObj["carriageNumber"] = carriageNumber;
arrayObj["carriageType"] = carriageType;
arrayObj["carriageOrder"] = carriageOrder;
Json::Value trainParams;
trainParams["poundNo"] = configureInfo_T.stationTrack;
arrayObj["trainParams"] = trainParams;
Json::StreamWriterBuilder writer;
std::cout << " http send:" << arrayObj << std::endl;
std::string str = Json::writeString(writer, arrayObj);
print_log(str);
auto res = cli.Post(configureInfo_T.urlPath, header, str, "application/json");
if (res)
{
print_log(res->body.c_str());
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["success"].asString().compare("true"))
{
print_log("已经成功发送数据到Web ...");
return 0;
}
else
{
if (!root["msg"].asString().compare("请求未授权")) {
print_log("error : 发送数据到Web error 请求没有得到授权 需要请求授权.");
obtain_accredit();
return -2;
}
}
}
}
}
}
return true;
}
/**
* @brief:Http获取授权
* @param
* @return:
*/
void MainWindow::obtain_accredit()
{
httplib::Client cli(configureInfo_T.ip, std::atoi(configureInfo_T.port.c_str()));
httplib::Headers header;
httplib::Params params;
if (!baccredit) {
header.emplace("Authorization", "Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0");
params.emplace("username", "guest_01");
params.emplace("password", "d55b0f642e817eea24725d2f2a31dd08");
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["success"].asString().compare("true"))
{
baccredit = true;
accreditInformation = root["token_type"].asString();
accreditInformation.append(" ");
accreditInformation.append(root["access_token"].asString());
std::string logs = "已经成功得到授权,授权信息为:" + accreditInformation + '\n';
std::cout << logs << std::endl;
ui->textBrowser->setText(QString::fromStdString(logs));
print_log("已经成功得到授权.");
}
}
}
}
else
{
auto err = res.error();
if (err == httplib::Error::Connection) {
std::cout << " (连接出错)" << std::endl;
}
print_log("请求授权出错 error");
}
}
}
/********************************串口初始化*************************************/
/**
* @brief:设置串口
* @param
* @return:空
*/
void MainWindow::set_uart_parameter()
{
serial->setPortName(QString::fromStdString(configureInfo_T.uartName));
if(!configureInfo_T.uartBaud.compare("9600")){
serial->setBaudRate(QSerialPort::Baud9600);
}else if(!configureInfo_T.uartBaud.compare("19200")){
serial->setBaudRate(QSerialPort::Baud19200);
}else if(!configureInfo_T.uartBaud.compare("115200")){
serial->setBaudRate(QSerialPort::Baud115200);
}
serial->setParity(QSerialPort::NoParity);// 校验
serial->setDataBits(QSerialPort::Data8); //数据位
serial->setStopBits(QSerialPort::OneStop);//停止位停止位默认选择1位
serial->setFlowControl(QSerialPort::NoFlowControl);// 控制流,默认选择无
if(serial->open(QSerialPort::ReadWrite)){
#if DEBUG_HTTP
obtain_accredit(); //获取http授权
#endif
std::string logs;
logs.append("串口打开成功\n");
logs.append(" 串口号:" + configureInfo_T.uartName + "\r\n");
logs.append(" 波特率:" + configureInfo_T.uartBaud + "\r\n");
logs.append(" IP :" + configureInfo_T.ip + "\r\n");
logs.append(" 端口号:" + configureInfo_T.port + "\r\n");
logs.append(" URL :" + configureInfo_T.urlPath + "\r\n");
logs.append(" 股道号:" + configureInfo_T.stationTrack + "\r\n");
logs.append(" 方向编号:" + configureInfo_T.configDirection + "\r\n");
ui->textBrowser->append(QString::fromStdString(logs));
print_log(logs);
}else{
std::string logs;
logs.append("打开串口失败,请确认!!!");
ui->textBrowser->append(QString::fromStdString(logs));
}
}
/******************************读写配置文件****************************************/
/**
* @brief:读取配置文件,并显示在相应的位置
* @param
* @return:空
*/
void MainWindow::read_configure_file(){
std::string str;
int pos;
std::ifstream file("laneConfig.txt");
if (file.good()) {
while (std::getline(file, str)) {
pos = str.find("uartName:");
if (pos != std::string::npos) {
pos = str.find(":");
configureInfo_T.uartName = str.substr(pos + 1);
if(std::atoi(configureInfo_T.uartName.substr(3).c_str())>=10){
configureInfo_T.uartName.insert(3,"\\\\.\\");
}
std::cout<< "configureInfo_T.uartName:" << configureInfo_T.uartName << std::endl;
}
pos = str.find("uartBaud:");
if (pos != std::string::npos) {
pos = str.find(":");
configureInfo_T.uartBaud = str.substr(pos + 1);
std::cout<< "m_uartBaud:" << configureInfo_T.uartBaud << std::endl;
}
pos = str.find("IP:");
if (pos != std::string::npos) {
pos = str.find(":");
configureInfo_T.ip = str.substr(pos + 1);
std::cout<< "m_szip:" << configureInfo_T.ip << std::endl;
}
pos = str.find("Port:");
if (pos != std::string::npos) {
pos = str.find(":");
configureInfo_T.port = str.substr(pos + 1);
std::cout<< "m_iport:" << configureInfo_T.port << std::endl;
}
pos = str.find("Path:");
if (pos != std::string::npos) {
pos = str.find(":");
configureInfo_T.urlPath = str.substr(pos + 1);
std::cout<< "m_szurlPath:" << configureInfo_T.urlPath << std::endl;
}
pos = str.find("Station");
if (pos != std::string::npos) {
pos = str.find(":");
configureInfo_T.stationTrack = str.substr(pos + 1);
std::cout<< "m_szstationTrack:" << configureInfo_T.stationTrack << std::endl;
}
pos = str.find("Direction");
if (pos != std::string::npos) {
pos = str.find(":");
configureInfo_T.configDirection = str.substr(pos + 1);
std::cout<< "m_configDirection:" << configureInfo_T.configDirection << std::endl;
}
}
file.close();
}
}
/**
* @brief:将新的内容写入到配置文件中
* @param
* @return:空
*/
void MainWindow::write_configure_file(){
ofswrite.open("laneConfig.txt", std::ios::out|std::ios::binary); // append,追加
ofswrite << "uartName:" << configureInfo_T.uartName << std::endl;
ofswrite << "uartBaud:" << configureInfo_T.uartBaud << std::endl;
ofswrite << "IP:" << configureInfo_T.ip << std::endl;
ofswrite << "Port:" << configureInfo_T.port << std::endl;
ofswrite << "Path:" << configureInfo_T.urlPath << std::endl;
ofswrite << "Station:" << configureInfo_T.stationTrack << std::endl;
ofswrite.close();
}
/***************************最小化相关****************************************/
/**
* @brief:接收最小化信号
* @param
* @return:空
*/
void MainWindow::changeEvent(QEvent *event)
{
if((event->type()==QEvent::WindowStateChange)&&isMinimized())
{
hide();
m_pSystemTray->setIcon(QIcon("./logo.ico")); // 托盘时显示的图片
m_pSystemTray->setToolTip("rfid车号识别"); // 鼠标在托盘图片时的提示
m_pSystemTray->showMessage("SystemTrayIcon","",QSystemTrayIcon::Information,10000);
event->ignore();
//建立托盘操作的菜单
creat_action();
creat_menu();
m_pSystemTray->show(); // 显示图片图标
}
}
void MainWindow::closeEvent(QCloseEvent *event)
{
// QMessageBox::StandardButton button = QMessageBox::information(NULL, "提示", "确定关闭软件?",QMessageBox::Yes, QMessageBox::No);;
// if(QMessageBox::Yes == button)
// {
// close();
// }else{
// event->ignore();
// }
// 弹出对话框要求用户输入账号和密码
QString username = QInputDialog::getText(this, "关闭账号密码验证", "请输入账号:");
QString password = QInputDialog::getText(this, "关闭账号密码验证", "请输入密码:", QLineEdit::Password);
// 验证账号和密码是否正确
if (username == "admin" && password == "brt123") {
event->accept(); // 关闭窗口
} else {
QMessageBox::warning(this, "验证失败", "账号或密码不正确!");
event->ignore(); // 阻止关闭窗口
}
}
void MainWindow::creat_action()
{
m_pActionShow = new QAction("show", this);
connect(m_pActionShow, &QAction::triggered, this,&MainWindow::on_ShowMainAction);
m_pActionQuit = new QAction("exit", this);
connect(m_pActionQuit, &QAction::triggered, this, &MainWindow::on_ExitAppAction);
}
void MainWindow::creat_menu()
{
m_pTrayMennu = new QMenu(this);
//新增菜单项---显示主界面
m_pTrayMennu->addAction(m_pActionShow);
//增加分隔符
m_pTrayMennu->addSeparator();
//新增菜单项---退出程序
m_pTrayMennu->addAction(m_pActionQuit);
//把QMenu赋给QSystemTrayIcon对象
m_pSystemTray->setContextMenu(m_pTrayMennu);
}
/**
* @brief:显示
* @param
* @return:空
*/
void MainWindow::on_ShowMainAction()
{
this->show();
}
/**
* @brief:最小化
* @param
* @return:空
*/
void MainWindow::on_ExitAppAction()
{
exit(0);
}
void MainWindow::on_activatedSysTrayIcon(QSystemTrayIcon::ActivationReason reason)
{
switch(reason){
case QSystemTrayIcon::Trigger:
//单击托盘图标
this->showNormal();
break;
case QSystemTrayIcon::DoubleClick:
//双击托盘图标
//双击后显示主程序窗口
this->showNormal();
break;
default:
break;
}
}