#include "CounterDevice.h" #include <iostream> #include <QDateTime> #include <QDebug> CounterDevice::CounterDevice(QObject *parent) : QObject(parent) { connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, this, &CounterDevice::dataReceivedHandler); kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); kafkaUtil.createProducer(); } CounterDevice::~CounterDevice() { disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, this, &CounterDevice::dataReceivedHandler); } void CounterDevice::setComName(QString comName) { this->comName = comName; } void CounterDevice::setBaudRate(int baudRate) { this->baudRate = baudRate; } QString CounterDevice::getDevCode() { return this->devCode; } void CounterDevice::setDevCode(QString devCode) { this->devCode = devCode; } void CounterDevice::setDeviceId(QString deviceId) { this->deviceId = deviceId; } QString CounterDevice::getDeviceName() { return deviceName; } void CounterDevice::setDeviceName(QString deviceName) { this->deviceName = deviceName; } int CounterDevice::getFormColIndex() { return this->formColIndex; } void CounterDevice::setFormColIndex(int idx) { this->formColIndex = idx; } int CounterDevice::getIsUse() { return this->isUse; } void CounterDevice::setIsUse(int isUse) { this->isUse = isUse; } bool CounterDevice::isSerialOpen() { return this->serialUtil.isOpen(); } void CounterDevice::initSerialPort() { int master = SettingConfig::getInstance().MASTER; QStringList comNameList = this->comName.split(","); if (comNameList.isEmpty() == true) { return; } // 如果是主程序则打开主串口 备程序则打开备串口 if (master == 1) { this->serialUtil.openSerialPort(comNameList.at(0), this->baudRate); } else { this->serialUtil.openSerialPort(comNameList.at(1), this->baudRate); } } void CounterDevice::dataReceivedHandler(QByteArray data) { this->dataBuff.append(data); QDateTime now = QDateTime::currentDateTime(); CounterDataDto * counterData = new CounterDataDto(this); if (CounterProtocolXH::checkFrame(this->dataBuff) == true) { counterData->rawFrame = this->dataBuff; // ★解析成数据对象 bool parse = CounterProtocolXH::parseMessureData(this->dataBuff, counterData); // 解析成功 if (parse == true) { this->dataBuff.clear(); counterData->devCode = this->devCode; counterData->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); counterData->milisecond = now.toMSecsSinceEpoch(); this->afterFramePhase(counterData); } // 到达拟合计算时间点时 触发 if (now.time().second() == SettingConfig::getInstance().RESIDUAL_CALC_SEC) { this->calcResidualClockData(now.currentSecsSinceEpoch() - SettingConfig::getInstance().RESIDUAL_CALC_SEC); } } else if (this->dataBuff.size() > COUNTER_FRAME_MIN_LENGTH) { std::cout << QString("clear buffer: %1").arg(this->dataBuff.size()).toStdString() << std::endl; this->dataBuff.clear(); } // 在此处释放内存,不影响后续显示 // 不在此处释放内存则会导致内存持续增加 // 具体原因不明 delete counterData; } void CounterDevice::afterFramePhase(CounterDataDto * counterData) { // 0. 输出到日志文件中 QString date = counterData->timestamp.mid(0, 10); // 1. 原始字节数组数据 QString filename = "raw_" + devCode + ".log"; QString content = counterData->timestamp + " " + counterData->rawFrame; QLogUtil::writeRawDataLogByDate(date, filename, content); QJsonArray messageArray; QString msgLogFilename = "msg_" + devCode + ".log"; CounterChannel * refChanPtr = ConstCache::getInstance().channelMap.value(QString("%1-%2").arg(deviceId).arg(counterData->channelRefId)); this->refChannelNo = counterData->channelRefId; double refDelay = 0.0; if (refChanPtr != nullptr && refChanPtr->getDelays().isEmpty() == false) { refDelay = refChanPtr->getDelays().toDouble(); } // 2. 各个通道的clock diff数据 for (int i = 1; i <= counterData->channelActiveArray.size(); i++) { if (counterData->channelActiveArray.at(i-1).toUInt() == 1) { if (counterData->channelRefId != i) { QString chFilename("%1_CH_%2.log"); chFilename = chFilename.arg(devCode); if (i < 10) { chFilename = chFilename.arg(QString("0%1").arg(i)); } else { chFilename = chFilename.arg(i); } QString channelDataStr = QString("%1 [%2] %3").arg(counterData->timestamp).arg(counterData->frameId).arg(counterData->channelDataArray.at(i-1)); // 写通道数据日志 QLogUtil::writeChannelDataLogByDate(date, chFilename, channelDataStr); } // 加到hisDataList中 用于绘制图表 CounterChannel * channelPtr = ConstCache::getInstance().channelMap.value(QString("%1-%2").arg(deviceId).arg(i)); if (channelPtr != nullptr && channelPtr->isActive() == true) { // 通道时延值 并计算 减去时延值的测量值 double delay = channelPtr->getDelays().isEmpty() == false ? channelPtr->getDelays().toDouble() : 0.0; double valueMinusDelay = counterData->channelDataArray.at(i-1).toDouble() - (delay * 1E-9) + (refDelay * 1E-9); channelPtr->appendHisData(QString::number(counterData->milisecond), QString::number(valueMinusDelay, 'f', 12)); QJsonObject jsonObj = counterData->toJSON(i - 1); jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); jsonObj.insert("master", SettingConfig::getInstance().MASTER); jsonObj.insert("deviceId", deviceId); messageArray.append(jsonObj); } } } // 3. 输出到中间件,执行后续处理过程 QJsonObject statusObj = counterData->toStatusJSON(); statusObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); statusObj.insert("master", SettingConfig::getInstance().MASTER); statusObj.insert("deviceId", deviceId); if (SettingConfig::getInstance().NEED_KAFKA == 1) { kafkaUtil.produceMessage(QString(QJsonDocument(messageArray).toJson(QJsonDocument::Compact))); kafkaUtil.produceMessage(SettingConfig::getInstance().KAFKA_STATUS_TOPIC, QString(QJsonDocument(statusObj).toJson(QJsonDocument::Compact))); QLogUtil::writeChannelDataLogByDate(date, msgLogFilename, QString(QJsonDocument(messageArray).toJson(QJsonDocument::Compact))); } // 4. 在界面上简单显示相差数据结果 emit this->sendDataToDraw(messageArray); } void CounterDevice::calcResidualClockData(qlonglong tm) { qDebug() << devCode << " start: " << QDateTime::currentMSecsSinceEpoch(); QString date = QDateTime::fromSecsSinceEpoch(tm).toString("yyyy-MM-dd"); QJsonArray messageArray; QString msgLogFilename = "MINUTE_msg_" + devCode + ".log"; for (int j = 1; j <= 16; j++) { QString channelKey = QString("%1-%2").arg(deviceId).arg(j); if (ConstCache::getInstance().channelMap.contains(channelKey)) { CounterChannel * channelPtr = ConstCache::getInstance().channelMap.value(channelKey); QList<QStringList> minuteDataList = channelPtr->getHisData().mid(channelPtr->getHisData().size() - 60, 60); QVector<double> timeVec; QVector<double> dataVec; for (int k = 0; k < minuteDataList.size(); k++) { qlonglong tmData = ((QString) minuteDataList.at(k).at(0)).toLongLong() / 1000; if (abs(tmData - tm) <= SettingConfig::getInstance().RESIDUAL_CALC_SEC) { timeVec.append(tmData - tm); dataVec.append(((QString) minuteDataList.at(k).at(1)).toDouble()); } } LinearRegression lineReg; lineReg.xArray = timeVec.data(); lineReg.yArray = dataVec.data(); lineReg.calcLineRegParams(timeVec.size()); double value = lineReg.slope * 0 + lineReg.intercept; if (j != this->refChannelNo) { // 写入通道的拟合数据日志 QString chFilename("MINUTE_%1_CH_%2.log"); chFilename = chFilename.arg(devCode).arg(j, 2, 10, QLatin1Char('0')); QString channelDataStr = QString("%1 %2").arg(QDateTime::fromSecsSinceEpoch(tm).toString("yyyy-MM-dd HH:mm:ss")).arg(QString::number(value, 'f', 12)); // 写日志 QLogUtil::writeChannelDataLogByDate(date, chFilename, channelDataStr); } // 生成json对象 QJsonObject jsonObj; QJsonObject dataObj; dataObj.insert("channelRefNo", this->refChannelNo); dataObj.insert("dataValue", QString::number(value, 'f', 12)); dataObj.insert("rawValue", QString::number(value, 'f', 12)); dataObj.insert("frameId", QDateTime::fromSecsSinceEpoch(tm).toString("HHmmss")); jsonObj.insert("data", dataObj); jsonObj.insert("channelNo", j); jsonObj.insert("ts", tm * 1000); jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); jsonObj.insert("master", SettingConfig::getInstance().MASTER); jsonObj.insert("deviceId", deviceId); messageArray.append(jsonObj); } } QLogUtil::writeChannelDataLogByDate(date, msgLogFilename, QString(QJsonDocument(messageArray).toJson(QJsonDocument::Compact))); qDebug() << devCode << " end: " << QDateTime::currentMSecsSinceEpoch(); }