Newer
Older
PhaseMeasure / PhaseDevice.cpp
tanyue on 26 Apr 2023 6 KB 20230420 增加串口配置
#include "PhaseDevice.h"
#include "common/utils/QLogUtil.h"

#include <iostream>
#include <QDateTime>
#include <QMutex>
#include <QTimer>

// 原始数据 - 补偿之前的值
QVector<QVector<QStringList>> phaseVector(PHASE_MESSURE_CHANNEL, QVector<QStringList>());

// allan方差值 - 1s ~ 10000s
QVector<QVector<double>> channelAllan(PHASE_MESSURE_CHANNEL, QVector<double>(0, 0));
QVector<QVector<double>> channelAllenSigma(PHASE_MESSURE_CHANNEL, QVector<double>(5, 0.0));

int frameCount = 0;

PhaseDevice::PhaseDevice(QObject *parent) : QObject(parent)
{
    if (SettingConfig::getInstance().NET_TYPE.toUpper() == "UDP") {
        clientUtil = new UDPClientUtil(this);
        connect(clientUtil, &UDPClientUtil::dataRecieved, this, &PhaseDevice::dataReceivedHandler);
    } else if (SettingConfig::getInstance().NET_TYPE.toUpper() == "SERIAL") {
        serialUtil = new QSerialPortUtil(this);
        serialUtil->openSerialPort(SettingConfig::getInstance().PORT_NAME, SettingConfig::getInstance().BAUD_RATE);
        connect(serialUtil, &QSerialPortUtil::dataRecieved, this, &PhaseDevice::dataReceivedHandler);
    }
}

PhaseDevice::~PhaseDevice()
{
    if (SettingConfig::getInstance().NET_TYPE.toUpper() == "UDP") {
        disconnect(clientUtil, &UDPClientUtil::dataRecieved, this, &PhaseDevice::dataReceivedHandler);
    } else if (SettingConfig::getInstance().NET_TYPE.toUpper() == "SERIAL") {
        disconnect(serialUtil, &QSerialPortUtil::dataRecieved, this, &PhaseDevice::dataReceivedHandler);
    }
}

void PhaseDevice::startWork()
{
    QString startCmd = PhaseProtocolBM::startMessure();
    if (SettingConfig::getInstance().NET_TYPE.toUpper() == "UDP") {
        clientUtil->sendData(startCmd.toLocal8Bit());
    } else if (SettingConfig::getInstance().NET_TYPE.toUpper() == "SERIAL") {
        serialUtil->sendData(startCmd.toLocal8Bit());
    }

}

void PhaseDevice::stopWork()
{
    QString stopCmd = PhaseProtocolBM::stopMessure();
    if (SettingConfig::getInstance().NET_TYPE.toUpper() == "UDP") {
        clientUtil->sendData(stopCmd.toLocal8Bit());
    } else if (SettingConfig::getInstance().NET_TYPE.toUpper() == "SERIAL") {
        serialUtil->sendData(stopCmd.toLocal8Bit());
    }
}

void PhaseDevice::dataReceivedHandler(QByteArray data)
{
    this->dataBuff.append(data);

    PhaseDataDto * phaseData = new PhaseDataDto(this);
    if (PhaseProtocolBM::checkFrame(this->dataBuff) == true)
    {
        phaseData->rawFrame = this->dataBuff;

        // ★解析成数据对象
        bool parse = PhaseProtocolBM::parseMessureData(this->dataBuff, phaseData);

        // 解析成功
        if (parse == true)
        {
            QDateTime now = QDateTime::currentDateTime();
            phaseData->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz");
            phaseData->milisecond = now.toMSecsSinceEpoch();
            this->afterFramePhase(phaseData);
        }
    } else if (this->dataBuff.size() > PHASE_FRAM_LENGTH)
    {
        std::cout << QString("%1").arg(this->dataBuff.size()).toStdString() << std::endl;
        this->dataBuff.clear();
    }

    // 在此处释放内存,不影响后续显示
    // 不在此处释放内存则会导致内存持续增加
    // 具体原因不明
    delete phaseData;
}

void PhaseDevice::afterFramePhase(PhaseDataDto * phaseData)
{
    // 1. 清空dataBuff,等待下一帧的数据
    this->dataBuff.clear();

    // 2. 输出到日志文件中
    QString date = phaseData->timestamp.mid(0, 10);

    // 2.1 原始字节数组数据
    QString filename = "rawBytes.log";
    QString content = phaseData->timestamp + " " + QByteUtil::binToHexString(phaseData->rawFrame);
    QLogUtil::writeRawDataLogByDate(date, filename, content);

    // 过滤前面几帧数据
    frameCount++;
    if (frameCount <= SettingConfig::getInstance().SKIP_HEADER)
    {
        return ;
    }

    QVector<double> vectorZero(5);
    QVector<double> vector(5);

    // 3.存+allen
    for (int i = 0; i < phaseData->channelActive.size(); i++)
    {
        if (phaseData->channelActive.at(i) == "1")
        {
            // 3.1 计算补偿的值
            double channelDelay = SettingConfig::getInstance().DELAY_ARR.at(i).toInt() * 1e-12; // 单位为ps
            phaseData->channelData[i] = phaseData->channelBeforeDelay.at(i) + channelDelay;
            phaseData->channelDataStr[i] = QString::number(phaseData->channelData.at(i), 'f', 15);

            // 3.2 将通道数据写日志
            QString chFilename = QString("CH_%1.log").arg(i + 1, 2, 10, QLatin1Char('0'));
            QString channelDataStr = QString("%1 %2")
                    .arg(phaseData->timestamp)
                    .arg(QString::number(phaseData->channelBeforeDelay.at(i), 'e', 6));
            QLogUtil::writeChannelDataLogByDate(phaseData->timestamp.mid(0, 10), chFilename, channelDataStr);

            // 3.3 将补偿前的时差数据存入数据栈, 用于计算allen方差
            QStringList valueList;
            valueList << QString::number(phaseData->milisecond) << QString::number(phaseData->channelBeforeDelay.at(i), 'e', 6);
            QMutex mutex;
            mutex.lock();
            phaseVector[i].append(valueList);
            mutex.unlock();

            // 3.4 分别计算不同时间维度的稳定度
            int size = phaseVector[i].size();
            if(size>=5)  vector[0] = DataProcessAlgorithm::calAllan(i, 1, size); else vector[0] = 0;
            if(size>=50) vector[1] = DataProcessAlgorithm::calAllan(i, 10, size); else vector[1] = 0;
            if(size>=500) vector[2] = DataProcessAlgorithm::calAllan(i, 100, size); else vector[2] = 0;
            if(size>=5000) vector[3] = DataProcessAlgorithm::calAllan(i, 1000, size); else vector[3] = 0;
            if(size>=50000) vector[4] = DataProcessAlgorithm::calAllan(i, 10000, size); else vector[4] = 0;

            // 3.5 将稳定度计算结果存入
            channelAllan[i] = vector;
        } else
        {
            channelAllan[i] = vectorZero;
        }
    }

    // 4. 在界面上简单显示相差数据结果
    emit this->sendDataToDraw(phaseData);
}