Newer
Older
PhaseMeasure / PhaseDevice.cpp
TAN YUE on 29 Jan 2022 5 KB 20220129 图表功能初步
#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));

PhaseDevice::PhaseDevice(QObject *parent) : QObject(parent)
{
    clientUtil = new UDPClientUtil(this);
    connect(clientUtil, &UDPClientUtil::dataRecieved,
            this, &PhaseDevice::dataReceivedHandler);

//    QTimer * timer = new QTimer(this);
//    connect(timer, &QTimer::timeout,
//            this, &PhaseDevice::mockPhaseData);
//    timer->start(1000);
}

PhaseDevice::~PhaseDevice()
{
    disconnect(clientUtil, &UDPClientUtil::dataRecieved,
               this, &PhaseDevice::dataReceivedHandler);
}

void PhaseDevice::startWork()
{
    QString startCmd = PhaseProtocolBM::startMessure();
    clientUtil->sendData(startCmd.toLocal8Bit());
}

void PhaseDevice::stopWork()
{
    QString stopCmd = PhaseProtocolBM::stopMessure();
    clientUtil->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);

    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] %3 %4 %5")
                    .arg(phaseData->timestamp)
                    .arg(phaseData->frameId)
                    .arg(phaseData->channelDataStr.at(i))
                    .arg(QString::number(channelDelay))
                    .arg(QString::number(phaseData->rawPhaseDiffData.at(i), 'f', 0));
//            std::cout << channelDataStr.toStdString() << std::endl;

            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', 4);
            QMutex mutex;
            mutex.lock();
            phaseVector[i].append(valueList);
            mutex.unlock();

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

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

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

void PhaseDevice::mockPhaseData()
{
    QDateTime now = QDateTime::currentDateTime();

    QString frameId = now.toString("HHmmsszzz");

    QByteArray buffer;
    buffer.append(QByteUtil::hexStringToBytes(frameId.mid(0, 8)));

    for (int i = 1; i <= 16; i++)
    {
        int value = qrand() % 10000;
        buffer.append(QByteUtil::hexStringToBytes("00800000")).append(QByteUtil::ULongToBytes(value, 4));
    }

    buffer.append(QByteUtil::hexStringToBytes("EEEEEEEE"));

    this->dataReceivedHandler(buffer);
}