qt实现实时抓取串口数据,并对数据做解密处理

效果:

        1.实时抓取串口数据,并对串口数据做解密,解密后显示在QTextEdit上。

        2.对显示的内容做特殊关键字标记处理,比如对出现的Error关键字标红

                高亮另一个版本

        3.对显示的明文进行查询,类似编辑文件中的Ctrl+F

        4.对串口抓取到的数据存储到本地

实现:

        1.在mainwindow中使用串口类子线程对象,其中mHexEdit是显示hex进制数据的自定义控件

MainWindow::~MainWindow()
{
    mSerialWork->quitWork();
    delete  mSerialWork;
}


void MainWindow::initConnect()
{
    mLastCursor = new QTextCursor(mSerialEdit->document());
    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);
}

void MainWindow::ShowStr(const QString& str)
{
    //mSerialEdit->append(str);
    // avoid append line-feed
    QTextCursor tc = mSerialEdit->textCursor();
    tc.movePosition(QTextCursor::End);
    tc.insertText(str);
    auto keywords = ParseWork::Instance().getKeywords();
    foreach (auto key, keywords.keys())
    {
        auto names = key.split("-");
        filterKeyWord(mSerialEdit, names[1], keywords[key]);
    }
}

        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;
    }
}

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt中,可以通过QThread类来创建线程,通过QSerialPort类来实现串口通信。下面是一个示例代码,演示了如何开启线程接收串口数据,并通过主线程界面实时显示。 ```cpp #include <QApplication> #include <QSerialPort> #include <QThread> #include <QTextEdit> #include <QObject> // 自定义线程类,用于接收串口数据 class SerialThread : public QThread { Q_OBJECT public: explicit SerialThread(QObject *parent = nullptr) : QThread(parent) {} protected: void run() override { QSerialPort serial; serial.setPortName("COM1"); // 设置串口号,根据实际情况修改 serial.setBaudRate(QSerialPort::Baud115200); // 设置波特率,根据实际情况修改 if (!serial.open(QIODevice::ReadOnly)) { emit error(serial.errorString()); return; } while (!isInterruptionRequested()) { if (serial.waitForReadyRead(100)) { QByteArray data = serial.readAll(); emit newData(data); } } serial.close(); } signals: void error(const QString &errorMsg); void newData(const QByteArray &data); }; // 主窗口类 class MainWindow : public QTextEdit { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr) : QTextEdit(parent) {} public slots: void handleError(const QString &errorMsg) { append("错误:" + errorMsg); } void handleNewData(const QByteArray &data) { append("接收数据:" + QString(data)); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow mainWindow; mainWindow.resize(400, 300); mainWindow.show(); SerialThread serialThread; QObject::connect(&serialThread, &SerialThread::error, &mainWindow, &MainWindow::handleError); QObject::connect(&serialThread, &SerialThread::newData, &mainWindow, &MainWindow::handleNewData); serialThread.start(); return app.exec(); } #include "main.moc" ``` 以上代码实现了一个简单的Qt应用程序,在主线程显示的文本框中实时输出从串口接收到的数据。你需要根据实际情况修改串口号和波特率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值