效果:
1.实时抓取串口数据,并对串口数据做解密,解密后显示在QTextEdit上。
2.对显示的内容做特殊关键字标记处理,比如对出现的Error关键字标红
3.对显示的明文进行查询,类似编辑文件中的Ctrl+F
4.对串口抓取到的数据存储到本地
实现:
1.在mainwindow中使用串口类子线程对象,其中mHexEdit是显示hex进制数据的自定义控件
MainWindow::~MainWindow()
{
mSerialWork->quitWork();
delete mSerialWork;
}
void MainWindow::initConnect()
{
mSerialWork = new SerialWorker;
connect(mSerialWork, &SerialWorker::readData, this, [&](const QByteArray &data){
mHexEdit->appenData(data);
});
connect(mSerialWork,&SerialWorker::sendparserslt, this, [&](const QString& data){
mSerialEdit->append(data); //mSerialEdit是普通的QTextEdit控件
});
}
//dict是解密用的字典文件, serial是串口的属性,比如波特率、停止位等
void MainWindow::startWork(bool start, const QString &dict, const QVariantMap &serial)
{
if(!start)
{
mPortList->setEnabled(true);
mSerialWork->startWork(0, "", false);
return;
}
auto port = mPortList->currentItem();
if(nullptr== port)
{
QMessageBox::warning(this, tr("Warning"),
tr("Please select a serial port"));
return;
}
if(dict.isEmpty())
return;
QVariantMap data = serial;
data["port"] = port->text();
dicUartParseFilePath = dict;
mSerialWork->setProperty(data);
mHexEdit->setData(QByteArray());
mSerialEdit->clear();
mSerialWork->startWork(mProductType, dicUartParseFilePath);
}
void MainWindow::saveHexDataToLocal(const QString& path)
{
const auto& data = mHexEdit->data();
if(data.isEmpty())
return;
bool ret = false;
QString result = tr("Save serial port data failed!");
auto lastPath = ParseWork::Instance().getLogFilePath();
if(path.isEmpty())
return;
QFile file(path);
if(file.open(QIODevice::WriteOnly|QIODevice::Truncate))
{
ret = true;
file.write(data);
file.close();
result = tr("Save serial port data successful!");
}
statusMessage(ret, result);
ParseWork::Instance().setLogFilePath(path);
}
2.关于SerialWorker的具体实现,部分无用代码需自己删减
#ifndef SERIALWORKER_H
#define SERIALWORKER_H
#include "parse/parsework.h"
#include "utils/utility.h"
#include <QObject>
class QThread;
class QSerialPort;
class SerialWorker : public QObject
{
Q_OBJECT
public:
explicit SerialWorker(QObject *parent = nullptr);
~SerialWorker();
void setProperty(const QVariantMap& data);
void setPortName(const QString& name);
void setBaudrate(qint32 rate);
void setDataBit(ushort);
void setStopBit(ushort bit);
void setParity(ushort parity);
void startWork(uint product, const QString& dictPath, bool start=true);
void quitWork();
signals:
void openStatus(bool open);
void readData(const QByteArray& data);
void sendparserslt(QString parseStr);
private slots:
void readSerialData();
private:
QThread* mThread;
QSerialPort* mSerialPort;
QString mPortName;
qint32 mBaudrate;
ushort mDataBit;
ushort mStopBit;
ushort mParity;
uint mProductType;
QString mDictPath;
private:
unsigned long long dataHasParsedSize = 0;
deque<unsigned char> parsedatalist;
unsigned int curFileLen = 0; //base on the current file len to split file
std::ofstream *outputBinFile = NULL;
FILE *outputTxtFile = NULL;
unsigned long saveFileNum = 1;
string subFolderName;
unsigned int singleFileSize = 20;
public:
string CreateSaveFolder();
bool CreateTextFile(string subFolderName);
bool CreateBinaryFile(string subFolderName);
string GetProjectName(ProjectItem project);
};
#endif // SERIALWORKER_H
#include "serialworker.h"
#include <QDebug>
#include <QThread>
#include <QSerialPort>
#include <QVariantMap>
#define GET_ENUM_NAME(value) case value:return (#value);
unsigned int parsedcnt = 0;
SerialWorker::SerialWorker(QObject *parent)
: QObject(parent)
{
mSerialPort = new QSerialPort(this);
mThread = new QThread;
moveToThread(mThread);
connect(mSerialPort, &QSerialPort::readyRead, this, &SerialWorker::readSerialData);
mThread->start();
}
SerialWorker::~SerialWorker()
{
quitWork();
delete mThread;
delete mSerialPort;
}
void SerialWorker::setProperty(const QVariantMap &data)
{
if(data.isEmpty())
return;
mPortName = data["port"].toString();
mBaudrate = data["buadrate"].toLongLong();
mParity = data["pority"].toUInt();
mDataBit = data["dataBit"].toUInt();
mStopBit = data["stopBit"].toUInt();
}
void SerialWorker::setPortName(const QString &name)
{
mPortName = name;
}
void SerialWorker::setBaudrate(qint32 rate)
{
mBaudrate = rate;
}
void SerialWorker::setDataBit(ushort bit)
{
mDataBit = bit;
}
void SerialWorker::setStopBit(ushort bit)
{
mStopBit = bit;
}
void SerialWorker::setParity(ushort parity)
{
mParity = parity;
}
void SerialWorker::startWork(uint product, const QString& dictPath, bool start)
{
if(!start)
{
mSerialPort->flush();
mSerialPort->close();
return;
}
curFileLen = 0;
parsedatalist.clear();
subFolderName.clear();
dataHasParsedSize = 0;
mDictPath = dictPath;
mProductType = product;
QSerialPort::BaudRate baudrate = (QSerialPort::BaudRate)mBaudrate;
mSerialPort->setBaudRate(baudrate,QSerialPort::AllDirections);
QSerialPort::DataBits dataBits = (QSerialPort::DataBits)mDataBit;
mSerialPort->setDataBits(dataBits);
mSerialPort->setFlowControl(QSerialPort::NoFlowControl);
QSerialPort::Parity parity = (QSerialPort::Parity)mParity;
QSerialPort::StopBits stopBits = (QSerialPort::StopBits)mStopBit;
mSerialPort->setPortName(mPortName);
mSerialPort->setBaudRate(baudrate,QSerialPort::AllDirections);
mSerialPort->setDataBits(dataBits);
mSerialPort->setParity(parity);
mSerialPort->setStopBits(stopBits);
mSerialPort->setFlowControl(QSerialPort::NoFlowControl);
if(start && !mSerialPort->isOpen())
{
mSerialPort->open(QIODevice::ReadWrite);
}
string folderPath = CreateSaveFolder();
CreateTextFile(folderPath);
CreateBinaryFile(folderPath);
openStatus(mSerialPort->isOpen());
}
void SerialWorker::quitWork()
{
saveFileNum = 1; //reset file number
dataHasParsedSize += parsedatalist.size();
for(uint i=0;i<parsedatalist.size();i++)
{
outputBinFile->write((char *)&parsedatalist.at(i),1);
}
if(outputBinFile)
{
outputBinFile->close();
outputBinFile = NULL;
}
if(outputTxtFile)
{
fclose(outputTxtFile);
outputTxtFile = NULL;
}
parsedatalist.clear();
parsedcnt = 0;
mSerialPort->close();
mThread->quit();
mThread->wait();
}
void SerialWorker::readSerialData()
{
const auto& data = mSerialPort->readAll();
for(int i=0;i<data.size();i++)
{
parsedatalist.push_back(data.at(i));
}
QString parseStr;
int value1 = parsedatalist.size();
switch (mProductType)
{
case TypeO:
ParseWork::Instance().ParseTypeOSerialData(parsedatalist,
mDictPath,parseStr, outputTxtFile,outputBinFile);
case TypeT:
ParseWork::Instance().ParseTypeTSerialData(parsedatalist,
mDictPath,parseStr, outputTxtFile,outputBinFile);
default:
break;
}
if(parseStr.size())
{
emit sendparserslt(parseStr);
}
int value2 = parsedatalist.size();
parsedcnt += (value1 - value2);
if(parsedcnt >= (saveFileNum * singleFileSize * 1024 * 1024))
{
saveFileNum++;
CreateTextFile(subFolderName);
CreateBinaryFile(subFolderName);
}
emit readData(data);
}
string SerialWorker::CreateSaveFolder()
{
string stCurrentTime = GetCurrentTimeStamp();
std::string comName = mPortName.toStdString();
string folderName = "SaveInfo_" + comName + "_" +stCurrentTime;
string rootdir = get_current_directory();
string path = rootdir + "/" + folderName;
bool result = CreateFolder(path);
if (result)
return path;
else
return "";
}
bool SerialWorker::CreateTextFile(string subFolderName)
{
if(outputTxtFile)
{
fclose(outputTxtFile);
outputTxtFile = NULL;
}
string project = GetProjectName((ProjectItem)mProductType);
char buf[128] = {0};
sprintf(buf, "/%s_RS232Log_%ld.txt", project.c_str(), saveFileNum);
string saveFileName;
saveFileName = subFolderName + buf;
outputTxtFile = fopen(saveFileName.data(), "w+");
if(outputTxtFile)
{
qDebug()<<"txt file create successfully";
}
else
{
qDebug()<<"txt file create fail";
}
return true;
}
bool SerialWorker::CreateBinaryFile(string subFolderName)
{
if(outputBinFile)
{
delete outputBinFile;
outputBinFile = NULL;
}
string project = GetProjectName((ProjectItem)mProductType);
char buf[100] = {0};
sprintf(buf, "/%s_RS232Log_%ld.bin", project.c_str(), saveFileNum);
string saveFileName;
saveFileName = subFolderName + buf;
outputBinFile = new std::ofstream(saveFileName, std::ios::out | std::ios::binary | std::ios::app);
if(outputBinFile)
{
qDebug()<<"raw data file create successfully";
}
else
{
qDebug()<<"raw data file create fail";
}
return true;
}
string SerialWorker::GetProjectName(ProjectItem project)
{
switch (project)
{
GET_ENUM_NAME(PE500 );
GET_ENUM_NAME(SQ_UFS_2_2);
default:
return "";
break;
}
}
标签:qt,mSerialPort,void,QSerialPort,抓取,SerialWorker,串口,data,string
From: https://blog.csdn.net/weixin_43935710/article/details/137541093