diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h new file mode 100644 index 0000000..504f410 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORFRAMEDTO_H +#define SIGNALGENERATORFRAMEDTO_H + +#include +#include +#include + +class SignalGeneratorFrameDto : public QObject +{ + Q_OBJECT +public: + explicit SignalGeneratorFrameDto(QObject *parent = nullptr); + + QByteArray rawFrame; // 原始帧字节数组 + + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QString devCode; + + virtual QJsonObject toJSON() = 0; + +signals: + +}; + +#endif // SIGNALGENERATORFRAMEDTO_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h new file mode 100644 index 0000000..504f410 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORFRAMEDTO_H +#define SIGNALGENERATORFRAMEDTO_H + +#include +#include +#include + +class SignalGeneratorFrameDto : public QObject +{ + Q_OBJECT +public: + explicit SignalGeneratorFrameDto(QObject *parent = nullptr); + + QByteArray rawFrame; // 原始帧字节数组 + + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QString devCode; + + virtual QJsonObject toJSON() = 0; + +signals: + +}; + +#endif // SIGNALGENERATORFRAMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp new file mode 100644 index 0000000..68e4204 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp @@ -0,0 +1,20 @@ +#include "SignalGeneratorInterfaceDto.h" + +SignalGeneratorInterfaceDto::SignalGeneratorInterfaceDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorInterfaceDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("keyControl", keyControl); + dataObj.insert("timeType", timeType); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h new file mode 100644 index 0000000..504f410 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORFRAMEDTO_H +#define SIGNALGENERATORFRAMEDTO_H + +#include +#include +#include + +class SignalGeneratorFrameDto : public QObject +{ + Q_OBJECT +public: + explicit SignalGeneratorFrameDto(QObject *parent = nullptr); + + QByteArray rawFrame; // 原始帧字节数组 + + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QString devCode; + + virtual QJsonObject toJSON() = 0; + +signals: + +}; + +#endif // SIGNALGENERATORFRAMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp new file mode 100644 index 0000000..68e4204 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp @@ -0,0 +1,20 @@ +#include "SignalGeneratorInterfaceDto.h" + +SignalGeneratorInterfaceDto::SignalGeneratorInterfaceDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorInterfaceDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("keyControl", keyControl); + dataObj.insert("timeType", timeType); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h new file mode 100644 index 0000000..2ea4653 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h @@ -0,0 +1,22 @@ +#ifndef SIGNALGENERATORINTERFACEDTO_H +#define SIGNALGENERATORINTERFACEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorInterfaceDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorInterfaceDto(QObject *parent = nullptr); + + QString keyControl; // + QString timeType; // + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORINTERFACEDTO_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h new file mode 100644 index 0000000..504f410 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORFRAMEDTO_H +#define SIGNALGENERATORFRAMEDTO_H + +#include +#include +#include + +class SignalGeneratorFrameDto : public QObject +{ + Q_OBJECT +public: + explicit SignalGeneratorFrameDto(QObject *parent = nullptr); + + QByteArray rawFrame; // 原始帧字节数组 + + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QString devCode; + + virtual QJsonObject toJSON() = 0; + +signals: + +}; + +#endif // SIGNALGENERATORFRAMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp new file mode 100644 index 0000000..68e4204 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp @@ -0,0 +1,20 @@ +#include "SignalGeneratorInterfaceDto.h" + +SignalGeneratorInterfaceDto::SignalGeneratorInterfaceDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorInterfaceDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("keyControl", keyControl); + dataObj.insert("timeType", timeType); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h new file mode 100644 index 0000000..2ea4653 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h @@ -0,0 +1,22 @@ +#ifndef SIGNALGENERATORINTERFACEDTO_H +#define SIGNALGENERATORINTERFACEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorInterfaceDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorInterfaceDto(QObject *parent = nullptr); + + QString keyControl; // + QString timeType; // + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORINTERFACEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp new file mode 100644 index 0000000..61c9289 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp @@ -0,0 +1,22 @@ +#include "SignalGeneratorMJDTimeDto.h" + +SignalGeneratorMJDTimeDto::SignalGeneratorMJDTimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorMJDTimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("mjdTime", mjdTime); + dataObj.insert("mjdDay", mjdDay); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h new file mode 100644 index 0000000..504f410 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORFRAMEDTO_H +#define SIGNALGENERATORFRAMEDTO_H + +#include +#include +#include + +class SignalGeneratorFrameDto : public QObject +{ + Q_OBJECT +public: + explicit SignalGeneratorFrameDto(QObject *parent = nullptr); + + QByteArray rawFrame; // 原始帧字节数组 + + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QString devCode; + + virtual QJsonObject toJSON() = 0; + +signals: + +}; + +#endif // SIGNALGENERATORFRAMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp new file mode 100644 index 0000000..68e4204 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp @@ -0,0 +1,20 @@ +#include "SignalGeneratorInterfaceDto.h" + +SignalGeneratorInterfaceDto::SignalGeneratorInterfaceDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorInterfaceDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("keyControl", keyControl); + dataObj.insert("timeType", timeType); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h new file mode 100644 index 0000000..2ea4653 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h @@ -0,0 +1,22 @@ +#ifndef SIGNALGENERATORINTERFACEDTO_H +#define SIGNALGENERATORINTERFACEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorInterfaceDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorInterfaceDto(QObject *parent = nullptr); + + QString keyControl; // + QString timeType; // + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORINTERFACEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp new file mode 100644 index 0000000..61c9289 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp @@ -0,0 +1,22 @@ +#include "SignalGeneratorMJDTimeDto.h" + +SignalGeneratorMJDTimeDto::SignalGeneratorMJDTimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorMJDTimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("mjdTime", mjdTime); + dataObj.insert("mjdDay", mjdDay); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h new file mode 100644 index 0000000..c95e1a3 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h @@ -0,0 +1,24 @@ +#ifndef SIGNALGENERATORMJDTIMEDTO_H +#define SIGNALGENERATORMJDTIMEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorMJDTimeDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorMJDTimeDto(QObject *parent = nullptr); + + QString mjdTime; // <1> + QString mjdDay; // <2> + QString leapSec; // <3> + QString valid; // <4> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORMJDTIMEDTO_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h new file mode 100644 index 0000000..504f410 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORFRAMEDTO_H +#define SIGNALGENERATORFRAMEDTO_H + +#include +#include +#include + +class SignalGeneratorFrameDto : public QObject +{ + Q_OBJECT +public: + explicit SignalGeneratorFrameDto(QObject *parent = nullptr); + + QByteArray rawFrame; // 原始帧字节数组 + + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QString devCode; + + virtual QJsonObject toJSON() = 0; + +signals: + +}; + +#endif // SIGNALGENERATORFRAMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp new file mode 100644 index 0000000..68e4204 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp @@ -0,0 +1,20 @@ +#include "SignalGeneratorInterfaceDto.h" + +SignalGeneratorInterfaceDto::SignalGeneratorInterfaceDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorInterfaceDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("keyControl", keyControl); + dataObj.insert("timeType", timeType); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h new file mode 100644 index 0000000..2ea4653 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h @@ -0,0 +1,22 @@ +#ifndef SIGNALGENERATORINTERFACEDTO_H +#define SIGNALGENERATORINTERFACEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorInterfaceDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorInterfaceDto(QObject *parent = nullptr); + + QString keyControl; // + QString timeType; // + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORINTERFACEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp new file mode 100644 index 0000000..61c9289 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp @@ -0,0 +1,22 @@ +#include "SignalGeneratorMJDTimeDto.h" + +SignalGeneratorMJDTimeDto::SignalGeneratorMJDTimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorMJDTimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("mjdTime", mjdTime); + dataObj.insert("mjdDay", mjdDay); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h new file mode 100644 index 0000000..c95e1a3 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h @@ -0,0 +1,24 @@ +#ifndef SIGNALGENERATORMJDTIMEDTO_H +#define SIGNALGENERATORMJDTIMEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorMJDTimeDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorMJDTimeDto(QObject *parent = nullptr); + + QString mjdTime; // <1> + QString mjdDay; // <2> + QString leapSec; // <3> + QString valid; // <4> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORMJDTIMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp new file mode 100644 index 0000000..1113584 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp @@ -0,0 +1,29 @@ +#include "SignalGeneratorStatusDto.h" + +SignalGeneratorStatusDto::SignalGeneratorStatusDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorStatusDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("devStatus", devStatus); + dataObj.insert("leap", leapSec); + dataObj.insert("leapTm", leapTimestamp); + dataObj.insert("freqStatus", freqSignalStatus); + dataObj.insert("freqType", freqSignalType); + dataObj.insert("oppsStatus", oppsSignalStatus); + dataObj.insert("phaseDiff", phaseDiff); + dataObj.insert("pulseWidth", pulseWidth); + dataObj.insert("phaseAcc", phaseShiftAcc); + dataObj.insert("bacRatio", bacRatio); + dataObj.insert("bacRange", bacRange); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h new file mode 100644 index 0000000..504f410 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORFRAMEDTO_H +#define SIGNALGENERATORFRAMEDTO_H + +#include +#include +#include + +class SignalGeneratorFrameDto : public QObject +{ + Q_OBJECT +public: + explicit SignalGeneratorFrameDto(QObject *parent = nullptr); + + QByteArray rawFrame; // 原始帧字节数组 + + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QString devCode; + + virtual QJsonObject toJSON() = 0; + +signals: + +}; + +#endif // SIGNALGENERATORFRAMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp new file mode 100644 index 0000000..68e4204 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp @@ -0,0 +1,20 @@ +#include "SignalGeneratorInterfaceDto.h" + +SignalGeneratorInterfaceDto::SignalGeneratorInterfaceDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorInterfaceDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("keyControl", keyControl); + dataObj.insert("timeType", timeType); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h new file mode 100644 index 0000000..2ea4653 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h @@ -0,0 +1,22 @@ +#ifndef SIGNALGENERATORINTERFACEDTO_H +#define SIGNALGENERATORINTERFACEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorInterfaceDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorInterfaceDto(QObject *parent = nullptr); + + QString keyControl; // + QString timeType; // + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORINTERFACEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp new file mode 100644 index 0000000..61c9289 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp @@ -0,0 +1,22 @@ +#include "SignalGeneratorMJDTimeDto.h" + +SignalGeneratorMJDTimeDto::SignalGeneratorMJDTimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorMJDTimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("mjdTime", mjdTime); + dataObj.insert("mjdDay", mjdDay); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h new file mode 100644 index 0000000..c95e1a3 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h @@ -0,0 +1,24 @@ +#ifndef SIGNALGENERATORMJDTIMEDTO_H +#define SIGNALGENERATORMJDTIMEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorMJDTimeDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorMJDTimeDto(QObject *parent = nullptr); + + QString mjdTime; // <1> + QString mjdDay; // <2> + QString leapSec; // <3> + QString valid; // <4> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORMJDTIMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp new file mode 100644 index 0000000..1113584 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp @@ -0,0 +1,29 @@ +#include "SignalGeneratorStatusDto.h" + +SignalGeneratorStatusDto::SignalGeneratorStatusDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorStatusDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("devStatus", devStatus); + dataObj.insert("leap", leapSec); + dataObj.insert("leapTm", leapTimestamp); + dataObj.insert("freqStatus", freqSignalStatus); + dataObj.insert("freqType", freqSignalType); + dataObj.insert("oppsStatus", oppsSignalStatus); + dataObj.insert("phaseDiff", phaseDiff); + dataObj.insert("pulseWidth", pulseWidth); + dataObj.insert("phaseAcc", phaseShiftAcc); + dataObj.insert("bacRatio", bacRatio); + dataObj.insert("bacRange", bacRange); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h new file mode 100644 index 0000000..1c6d005 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h @@ -0,0 +1,31 @@ +#ifndef SIGNALGENERATORSTATUSDTO_H +#define SIGNALGENERATORSTATUSDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorStatusDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorStatusDto(QObject *parent = nullptr); + + QString devStatus; // <1> + QString leapSec; // <2> + QString leapTimestamp; // <3> + QString freqSignalStatus; // <4> + QString freqSignalType; // <5> + QString oppsSignalStatus; // <6> + qlonglong phaseDiff; // <7> + qlonglong pulseWidth; // <8> + qlonglong phaseShiftAcc; // <9> + qint8 bacRatio; // <10> + float bacRange; // <11> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORSTATUSDTO_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h new file mode 100644 index 0000000..504f410 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORFRAMEDTO_H +#define SIGNALGENERATORFRAMEDTO_H + +#include +#include +#include + +class SignalGeneratorFrameDto : public QObject +{ + Q_OBJECT +public: + explicit SignalGeneratorFrameDto(QObject *parent = nullptr); + + QByteArray rawFrame; // 原始帧字节数组 + + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QString devCode; + + virtual QJsonObject toJSON() = 0; + +signals: + +}; + +#endif // SIGNALGENERATORFRAMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp new file mode 100644 index 0000000..68e4204 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp @@ -0,0 +1,20 @@ +#include "SignalGeneratorInterfaceDto.h" + +SignalGeneratorInterfaceDto::SignalGeneratorInterfaceDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorInterfaceDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("keyControl", keyControl); + dataObj.insert("timeType", timeType); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h new file mode 100644 index 0000000..2ea4653 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h @@ -0,0 +1,22 @@ +#ifndef SIGNALGENERATORINTERFACEDTO_H +#define SIGNALGENERATORINTERFACEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorInterfaceDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorInterfaceDto(QObject *parent = nullptr); + + QString keyControl; // + QString timeType; // + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORINTERFACEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp new file mode 100644 index 0000000..61c9289 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp @@ -0,0 +1,22 @@ +#include "SignalGeneratorMJDTimeDto.h" + +SignalGeneratorMJDTimeDto::SignalGeneratorMJDTimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorMJDTimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("mjdTime", mjdTime); + dataObj.insert("mjdDay", mjdDay); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h new file mode 100644 index 0000000..c95e1a3 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h @@ -0,0 +1,24 @@ +#ifndef SIGNALGENERATORMJDTIMEDTO_H +#define SIGNALGENERATORMJDTIMEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorMJDTimeDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorMJDTimeDto(QObject *parent = nullptr); + + QString mjdTime; // <1> + QString mjdDay; // <2> + QString leapSec; // <3> + QString valid; // <4> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORMJDTIMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp new file mode 100644 index 0000000..1113584 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp @@ -0,0 +1,29 @@ +#include "SignalGeneratorStatusDto.h" + +SignalGeneratorStatusDto::SignalGeneratorStatusDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorStatusDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("devStatus", devStatus); + dataObj.insert("leap", leapSec); + dataObj.insert("leapTm", leapTimestamp); + dataObj.insert("freqStatus", freqSignalStatus); + dataObj.insert("freqType", freqSignalType); + dataObj.insert("oppsStatus", oppsSignalStatus); + dataObj.insert("phaseDiff", phaseDiff); + dataObj.insert("pulseWidth", pulseWidth); + dataObj.insert("phaseAcc", phaseShiftAcc); + dataObj.insert("bacRatio", bacRatio); + dataObj.insert("bacRange", bacRange); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h new file mode 100644 index 0000000..1c6d005 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h @@ -0,0 +1,31 @@ +#ifndef SIGNALGENERATORSTATUSDTO_H +#define SIGNALGENERATORSTATUSDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorStatusDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorStatusDto(QObject *parent = nullptr); + + QString devStatus; // <1> + QString leapSec; // <2> + QString leapTimestamp; // <3> + QString freqSignalStatus; // <4> + QString freqSignalType; // <5> + QString oppsSignalStatus; // <6> + qlonglong phaseDiff; // <7> + qlonglong pulseWidth; // <8> + qlonglong phaseShiftAcc; // <9> + qint8 bacRatio; // <10> + float bacRange; // <11> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORSTATUSDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp new file mode 100644 index 0000000..231977f --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp @@ -0,0 +1,24 @@ +#include "SignalGeneratorZDATimeDto.h" + +SignalGeneratorZDATimeDto::SignalGeneratorZDATimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorZDATimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("zdaTime", zdaTime); + dataObj.insert("zdaDay", zdaDay); + dataObj.insert("zdaMon", zdaMon); + dataObj.insert("zdaYear", zdaYear); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h new file mode 100644 index 0000000..504f410 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORFRAMEDTO_H +#define SIGNALGENERATORFRAMEDTO_H + +#include +#include +#include + +class SignalGeneratorFrameDto : public QObject +{ + Q_OBJECT +public: + explicit SignalGeneratorFrameDto(QObject *parent = nullptr); + + QByteArray rawFrame; // 原始帧字节数组 + + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QString devCode; + + virtual QJsonObject toJSON() = 0; + +signals: + +}; + +#endif // SIGNALGENERATORFRAMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp new file mode 100644 index 0000000..68e4204 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp @@ -0,0 +1,20 @@ +#include "SignalGeneratorInterfaceDto.h" + +SignalGeneratorInterfaceDto::SignalGeneratorInterfaceDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorInterfaceDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("keyControl", keyControl); + dataObj.insert("timeType", timeType); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h new file mode 100644 index 0000000..2ea4653 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h @@ -0,0 +1,22 @@ +#ifndef SIGNALGENERATORINTERFACEDTO_H +#define SIGNALGENERATORINTERFACEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorInterfaceDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorInterfaceDto(QObject *parent = nullptr); + + QString keyControl; // + QString timeType; // + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORINTERFACEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp new file mode 100644 index 0000000..61c9289 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp @@ -0,0 +1,22 @@ +#include "SignalGeneratorMJDTimeDto.h" + +SignalGeneratorMJDTimeDto::SignalGeneratorMJDTimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorMJDTimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("mjdTime", mjdTime); + dataObj.insert("mjdDay", mjdDay); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h new file mode 100644 index 0000000..c95e1a3 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h @@ -0,0 +1,24 @@ +#ifndef SIGNALGENERATORMJDTIMEDTO_H +#define SIGNALGENERATORMJDTIMEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorMJDTimeDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorMJDTimeDto(QObject *parent = nullptr); + + QString mjdTime; // <1> + QString mjdDay; // <2> + QString leapSec; // <3> + QString valid; // <4> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORMJDTIMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp new file mode 100644 index 0000000..1113584 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp @@ -0,0 +1,29 @@ +#include "SignalGeneratorStatusDto.h" + +SignalGeneratorStatusDto::SignalGeneratorStatusDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorStatusDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("devStatus", devStatus); + dataObj.insert("leap", leapSec); + dataObj.insert("leapTm", leapTimestamp); + dataObj.insert("freqStatus", freqSignalStatus); + dataObj.insert("freqType", freqSignalType); + dataObj.insert("oppsStatus", oppsSignalStatus); + dataObj.insert("phaseDiff", phaseDiff); + dataObj.insert("pulseWidth", pulseWidth); + dataObj.insert("phaseAcc", phaseShiftAcc); + dataObj.insert("bacRatio", bacRatio); + dataObj.insert("bacRange", bacRange); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h new file mode 100644 index 0000000..1c6d005 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h @@ -0,0 +1,31 @@ +#ifndef SIGNALGENERATORSTATUSDTO_H +#define SIGNALGENERATORSTATUSDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorStatusDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorStatusDto(QObject *parent = nullptr); + + QString devStatus; // <1> + QString leapSec; // <2> + QString leapTimestamp; // <3> + QString freqSignalStatus; // <4> + QString freqSignalType; // <5> + QString oppsSignalStatus; // <6> + qlonglong phaseDiff; // <7> + qlonglong pulseWidth; // <8> + qlonglong phaseShiftAcc; // <9> + qint8 bacRatio; // <10> + float bacRange; // <11> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORSTATUSDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp new file mode 100644 index 0000000..231977f --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp @@ -0,0 +1,24 @@ +#include "SignalGeneratorZDATimeDto.h" + +SignalGeneratorZDATimeDto::SignalGeneratorZDATimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorZDATimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("zdaTime", zdaTime); + dataObj.insert("zdaDay", zdaDay); + dataObj.insert("zdaMon", zdaMon); + dataObj.insert("zdaYear", zdaYear); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.h new file mode 100644 index 0000000..d3f145a --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORZDATIMEDTO_H +#define SIGNALGENERATORZDATIMEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorZDATimeDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorZDATimeDto(QObject *parent = nullptr); + + QString zdaTime; // <1> + QString zdaDay; // <2> + QString zdaMon; // <3> + QString zdaYear; // <4> + QString leapSec; // <5> + QString valid; // <6> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORZDATIMEDTO_H diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h new file mode 100644 index 0000000..504f410 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORFRAMEDTO_H +#define SIGNALGENERATORFRAMEDTO_H + +#include +#include +#include + +class SignalGeneratorFrameDto : public QObject +{ + Q_OBJECT +public: + explicit SignalGeneratorFrameDto(QObject *parent = nullptr); + + QByteArray rawFrame; // 原始帧字节数组 + + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QString devCode; + + virtual QJsonObject toJSON() = 0; + +signals: + +}; + +#endif // SIGNALGENERATORFRAMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp new file mode 100644 index 0000000..68e4204 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp @@ -0,0 +1,20 @@ +#include "SignalGeneratorInterfaceDto.h" + +SignalGeneratorInterfaceDto::SignalGeneratorInterfaceDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorInterfaceDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("keyControl", keyControl); + dataObj.insert("timeType", timeType); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h new file mode 100644 index 0000000..2ea4653 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h @@ -0,0 +1,22 @@ +#ifndef SIGNALGENERATORINTERFACEDTO_H +#define SIGNALGENERATORINTERFACEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorInterfaceDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorInterfaceDto(QObject *parent = nullptr); + + QString keyControl; // + QString timeType; // + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORINTERFACEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp new file mode 100644 index 0000000..61c9289 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp @@ -0,0 +1,22 @@ +#include "SignalGeneratorMJDTimeDto.h" + +SignalGeneratorMJDTimeDto::SignalGeneratorMJDTimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorMJDTimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("mjdTime", mjdTime); + dataObj.insert("mjdDay", mjdDay); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h new file mode 100644 index 0000000..c95e1a3 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h @@ -0,0 +1,24 @@ +#ifndef SIGNALGENERATORMJDTIMEDTO_H +#define SIGNALGENERATORMJDTIMEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorMJDTimeDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorMJDTimeDto(QObject *parent = nullptr); + + QString mjdTime; // <1> + QString mjdDay; // <2> + QString leapSec; // <3> + QString valid; // <4> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORMJDTIMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp new file mode 100644 index 0000000..1113584 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp @@ -0,0 +1,29 @@ +#include "SignalGeneratorStatusDto.h" + +SignalGeneratorStatusDto::SignalGeneratorStatusDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorStatusDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("devStatus", devStatus); + dataObj.insert("leap", leapSec); + dataObj.insert("leapTm", leapTimestamp); + dataObj.insert("freqStatus", freqSignalStatus); + dataObj.insert("freqType", freqSignalType); + dataObj.insert("oppsStatus", oppsSignalStatus); + dataObj.insert("phaseDiff", phaseDiff); + dataObj.insert("pulseWidth", pulseWidth); + dataObj.insert("phaseAcc", phaseShiftAcc); + dataObj.insert("bacRatio", bacRatio); + dataObj.insert("bacRange", bacRange); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h new file mode 100644 index 0000000..1c6d005 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h @@ -0,0 +1,31 @@ +#ifndef SIGNALGENERATORSTATUSDTO_H +#define SIGNALGENERATORSTATUSDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorStatusDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorStatusDto(QObject *parent = nullptr); + + QString devStatus; // <1> + QString leapSec; // <2> + QString leapTimestamp; // <3> + QString freqSignalStatus; // <4> + QString freqSignalType; // <5> + QString oppsSignalStatus; // <6> + qlonglong phaseDiff; // <7> + qlonglong pulseWidth; // <8> + qlonglong phaseShiftAcc; // <9> + qint8 bacRatio; // <10> + float bacRange; // <11> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORSTATUSDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp new file mode 100644 index 0000000..231977f --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp @@ -0,0 +1,24 @@ +#include "SignalGeneratorZDATimeDto.h" + +SignalGeneratorZDATimeDto::SignalGeneratorZDATimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorZDATimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("zdaTime", zdaTime); + dataObj.insert("zdaDay", zdaDay); + dataObj.insert("zdaMon", zdaMon); + dataObj.insert("zdaYear", zdaYear); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.h new file mode 100644 index 0000000..d3f145a --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORZDATIMEDTO_H +#define SIGNALGENERATORZDATIMEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorZDATimeDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorZDATimeDto(QObject *parent = nullptr); + + QString zdaTime; // <1> + QString zdaDay; // <2> + QString zdaMon; // <3> + QString zdaYear; // <4> + QString leapSec; // <5> + QString valid; // <6> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORZDATIMEDTO_H diff --git a/DevStatusAcq/protocol/protocol.pri b/DevStatusAcq/protocol/protocol.pri new file mode 100644 index 0000000..0589e42 --- /dev/null +++ b/DevStatusAcq/protocol/protocol.pri @@ -0,0 +1,14 @@ + +HEADERS += $$PWD/dto/SignalGeneratorFrameDto.h +HEADERS += $$PWD/dto/SignalGeneratorStatusDto.h +HEADERS += $$PWD/dto/SignalGeneratorInterfaceDto.h +HEADERS += $$PWD/dto/SignalGeneratorZDATimeDto.h +HEADERS += $$PWD/dto/SignalGeneratorMJDTimeDto.h +HEADERS += $$PWD/SignalGeneratorProtocolBM.h + +SOURCES += $$PWD/dto/SignalGeneratorFrameDto.cpp +SOURCES += $$PWD/dto/SignalGeneratorStatusDto.cpp +SOURCES += $$PWD/dto/SignalGeneratorInterfaceDto.cpp +SOURCES += $$PWD/dto/SignalGeneratorZDATimeDto.cpp +SOURCES += $$PWD/dto/SignalGeneratorMJDTimeDto.cpp +SOURCES += $$PWD/SignalGeneratorProtocolBM.cpp diff --git a/DevStatusAcq/DevStatusAcq.pro b/DevStatusAcq/DevStatusAcq.pro index ae92758..b4409bb 100644 --- a/DevStatusAcq/DevStatusAcq.pro +++ b/DevStatusAcq/DevStatusAcq.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,7 +25,18 @@ FORMS += \ DevStatusWindow.ui +include(common/common.pri) +include(protocol/protocol.pri) +include(device/device.pri) + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +INCLUDEPATH += $$PWD/include/librdkafka +DEPENDPATH += $$PWD/include/librdkafka + +unix:!macx: LIBS += -L$$PWD/lib/librdkafka/ -lrdkafka -lrdkafka++ + +DISTFILES += conf/config.ini diff --git a/DevStatusAcq/DevStatusWindow.cpp b/DevStatusAcq/DevStatusWindow.cpp index 29a4899..7ed0384 100644 --- a/DevStatusAcq/DevStatusWindow.cpp +++ b/DevStatusAcq/DevStatusWindow.cpp @@ -1,11 +1,23 @@ #include "DevStatusWindow.h" #include "ui_DevStatusWindow.h" - DevStatusWindow::DevStatusWindow(QWidget *parent) : QWidget(parent) , ui(new Ui::DevStatusWindow) { ui->setupUi(this); + + SignalGenerator * device = new SignalGenerator(this); + + // +// connect(device, &SignalGenerator::sendDataToDraw, +// this, &DevStatusWindow::drawCounterDataOnPage); + + device->setComName("COM1"); + device->setBaudRate(9600); + + device->setDevCode("3001"); + + device->initSerialPort(); } DevStatusWindow::~DevStatusWindow() diff --git a/DevStatusAcq/DevStatusWindow.h b/DevStatusAcq/DevStatusWindow.h index 2cad41c..43846b2 100644 --- a/DevStatusAcq/DevStatusWindow.h +++ b/DevStatusAcq/DevStatusWindow.h @@ -3,6 +3,8 @@ #include +#include "device/SignalGenerator.h" + QT_BEGIN_NAMESPACE namespace Ui { class DevStatusWindow; } QT_END_NAMESPACE diff --git a/DevStatusAcq/common/common.pri b/DevStatusAcq/common/common.pri new file mode 100644 index 0000000..055a2db --- /dev/null +++ b/DevStatusAcq/common/common.pri @@ -0,0 +1,12 @@ + +SOURCES += $$PWD/utils/SettingConfig.cpp +SOURCES += $$PWD/utils/QByteUtil.cpp +SOURCES += $$PWD/utils/QSerialPortUtil.cpp +SOURCES += $$PWD/utils/QLogUtil.cpp +SOURCES += $$PWD/utils/QKafkaUtil.cpp + +HEADERS += $$PWD/utils/SettingConfig.h +HEADERS += $$PWD/utils/QByteUtil.h +HEADERS += $$PWD/utils/QSerialPortUtil.h +HEADERS += $$PWD/utils/QLogUtil.h +HEADERS += $$PWD/utils/QKafkaUtil.h diff --git a/DevStatusAcq/common/utils/QByteUtil.cpp b/DevStatusAcq/common/utils/QByteUtil.cpp new file mode 100644 index 0000000..1d49a51 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.cpp @@ -0,0 +1,190 @@ +#include "QByteUtil.h" +#include + +static uchar uc = 0x00; +const int FLOAT_BYTE_LENGTH = 4; +const int DOUBLE_BYTE_LENGTH = 8; + +QByteUtil::QByteUtil(QObject *parent) : QObject(parent) +{ + +} + +QByteArray QByteUtil::appendZeroAlign(QByteArray array, int count) +{ + // 如果字节数组的长度不足cout的倍数,在字节数组的前段补0x00 + int rem = array.length() % count; + if (rem > 0) + { + array.insert(0, count - rem, uc); + } + + return array; +} + +QString QByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray QByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong QByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray QByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} + + +float QByteUtil::binToFloat(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // 如果字节数组长度超过4位,取前4位 + QString str = QByteUtil::binToHexString(bytes.mid(0, FLOAT_BYTE_LENGTH)); + int hex = str.toUInt(0, 16); + float ret = *(float*) &hex; + + return ret; +} + +QVector QByteUtil::binToFloatArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, FLOAT_BYTE_LENGTH); + + // float用4字节浮点数表示 + int length = bytes.length() / FLOAT_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 4个字节的浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * FLOAT_BYTE_LENGTH, FLOAT_BYTE_LENGTH)); + + int hex = str.toUInt(0, 16); + float fl = *(float*) &hex; + + ret.append(fl); + } + + return ret; +} + +QByteArray QByteUtil::floatToBytes(float value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < FLOAT_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::floatArrayToBytes(QVector floatArray) +{ + QByteArray ret; + for (int i = 0; i < floatArray.length(); i++) + { + ret.append(floatToBytes(floatArray.at(i))); + } + return ret; +} + + +double QByteUtil::binToDouble(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // 如果字节数组长度超过8位,取前8位 + QString str = QByteUtil::binToHexString(bytes.mid(0, DOUBLE_BYTE_LENGTH)); + qulonglong hex = str.toULongLong(0, 16); + double ret = *(double*) &hex; + + return ret; +} + +QVector QByteUtil::binToDoubleArray(QByteArray bytes) +{ + bytes = appendZeroAlign(bytes, DOUBLE_BYTE_LENGTH); + + // double用8字节浮点数表示 + int length = bytes.length() / DOUBLE_BYTE_LENGTH; + + // 返回值 + QVector ret; + + // 8个字节的双精度浮点数,转换为 + for (int i = 0; i < length; i++) + { + QString str = QByteUtil::binToHexString(bytes.mid(i * DOUBLE_BYTE_LENGTH, DOUBLE_BYTE_LENGTH)); + + qulonglong hex = str.toULongLong(0, 16); + double dl = *(double*) &hex; + + ret.append(dl); + } + + return ret; +} + +QByteArray QByteUtil::doubleToBytes(double value) +{ + uchar * hex = (uchar *) &value; + QByteArray ret; + for (int i = 0; i < DOUBLE_BYTE_LENGTH; i++) + { + ret.insert(0, hex[i]); + } + + return ret; +} + +QByteArray QByteUtil::doubleArrayToBytes(QVector doubleArray) +{ + QByteArray ret; + for (int i = 0; i < doubleArray.length(); i++) + { + ret.append(doubleToBytes(doubleArray.at(i))); + } + return ret; +} diff --git a/DevStatusAcq/common/utils/QByteUtil.h b/DevStatusAcq/common/utils/QByteUtil.h new file mode 100644 index 0000000..f02d2f9 --- /dev/null +++ b/DevStatusAcq/common/utils/QByteUtil.h @@ -0,0 +1,115 @@ +#ifndef QBYTEUTIL_H +#define QBYTEUTIL_H + +#include + +class QByteUtil : public QObject +{ + Q_OBJECT +public: + explicit QByteUtil(QObject *parent = nullptr); + + + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); + + /******** 字节数组与float互转 ********/ + /** + * @brief binToFloat + * @param bytes + * @note 4个字节转float浮点数,从左到右排序 + * @example {0x42, 0xF6, 0xE6, 0x66} 转换为 123.45 + * @return + */ + static float binToFloat(QByteArray bytes); + /** + * @brief binToFloatArray + * @param bytes + * @note 字节数组转float数组,16进制浮点数,4个字节表示1个float浮点数,从左到右排序 + * @example {0xBD, 0x1F, 0xB1, 0xDA, 0x40, 0x63, 0x02, 0x0C, 0x40, 0x49, 0x0F, 0xDA} 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToFloatArray(QByteArray bytes); + /** + * @brief floatToBytes + * @param value + * @note 单个float数转4字节数组,从左至右排序 + * @example 123.45 转换为 {0x42, 0xF6, 0xE6, 0x66} + * @return + */ + static QByteArray floatToBytes(float value); + /** + * @brief floatArrayToBytes + * @param floatArray + * @note float数组转换为字节数组,每一个float浮点数4字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 {0x3D, 0x79, 0x09, 0x6C, 0x40, 0x12, 0x7C, 0x5B, 0x3B, 0xDE, 0x9A, 0x3F} + * @return + */ + static QByteArray floatArrayToBytes(QVector floatArray); + + /******** 字节数组与double互转 ********/ + /** + * @brief binToDouble + * @param bytes + * @note 8个字节转double双精度浮点数,从左到右排序 + * @example C00921FB53D92715 转换为 -3.141592650475 + * @return + */ + static double binToDouble(QByteArray bytes); + /** + * @brief binToDoubleArray + * @param bytes + * @note 字节数组转double数组,16进制双精度浮点数,8个字节表示1个double浮点数,从左到右排序 + * @example BFA3F63C31DF761D400C604189374BC74039B2DE00D1B717 转换为 -0.038988, 3.547, 3.141593 + * @return + */ + static QVector binToDoubleArray(QByteArray bytes); + /** + * @brief doubleToBytes + * @param value + * @note 单个double数转换为8字节数组,从左到右排序 + * @example 123.45 转换为 405EDCCCCCCCCCCD + * @return + */ + static QByteArray doubleToBytes(double value); + /** + * @brief doubleArrayToBytes + * @param doubleArray + * @note double数组转换为字节数组,每个double双精度浮点数8字节,从左到右排序 + * @example 0.0608, 2.28884, 0.00679329 转换为 3FAF212D77318FC540024F8B588E368F3F7BD347E61DABB7 + * @return + */ + static QByteArray doubleArrayToBytes(QVector doubleArray); + +private: + static QByteArray appendZeroAlign(QByteArray array, int count); + +signals: + +}; + +#endif // QBYTEUTIL_H diff --git a/DevStatusAcq/common/utils/QKafkaUtil.cpp b/DevStatusAcq/common/utils/QKafkaUtil.cpp new file mode 100644 index 0000000..3f00452 --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.cpp @@ -0,0 +1,59 @@ +#include "QKafkaUtil.h" +#include + +QKafkaUtil::QKafkaUtil(QObject *parent) : QObject(parent) +{ + this->conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); +} + +void QKafkaUtil::setBrokers(QString brokers) +{ + this->brokers = brokers; +} +void QKafkaUtil::setTopic(QString topic) +{ + this->topic = topic; +} + + +int QKafkaUtil::createProducer() +{ + int result; + result = this->conf->set("bootstrap.servers", this->brokers.toStdString(), errStr); + + if (result != RdKafka::Conf::CONF_OK) + { + std::cerr << errStr << std::endl; + + return RdKafka::Conf::CONF_INVALID; // -1 + } + + this->producer = RdKafka::Producer::create(this->conf, errStr); + if (producer == 0) + { + std::cerr << "Failed to create producer: " << errStr << std::endl; + return -2; + } + + result = 1; + return result; +} + +int QKafkaUtil::produceMessage(QString message) +{ + auto retCode = producer->produce(topic.toStdString(), RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, + const_cast(message.toStdString().c_str()), message.size(), + nullptr, 0, 0, nullptr, nullptr); + + if (retCode != RdKafka::ERR_NO_ERROR) + { + std::cerr << "Failed to produce to topic " << topic.toStdString() << ": " << + RdKafka::err2str(retCode) << std::endl; + } else + { + std::cerr << "Enqueued message (" << message.size() << " bytes) " << + "for topic " << topic.toStdString() << "[" << message.toStdString() <<"]" << std::endl; + } + + return retCode; +} diff --git a/DevStatusAcq/common/utils/QKafkaUtil.h b/DevStatusAcq/common/utils/QKafkaUtil.h new file mode 100644 index 0000000..289ea6f --- /dev/null +++ b/DevStatusAcq/common/utils/QKafkaUtil.h @@ -0,0 +1,33 @@ +#ifndef QKAFKAUTIL_H +#define QKAFKAUTIL_H + +#include + +#include "include/librdkafka/rdkafkacpp.h" + +class QKafkaUtil : public QObject +{ + Q_OBJECT +public: + explicit QKafkaUtil(QObject *parent = nullptr); + + void setBrokers(QString brokers); + void setTopic(QString topic); + + int createProducer(); + int produceMessage(QString message); + +private: + QString brokers; + QString topic; + + std::string errStr; + + RdKafka::Conf * conf; + + RdKafka::Producer * producer = 0; +signals: + +}; + +#endif // QKAFKAUTIL_H diff --git a/DevStatusAcq/common/utils/QLogUtil.cpp b/DevStatusAcq/common/utils/QLogUtil.cpp new file mode 100644 index 0000000..458ac15 --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.cpp @@ -0,0 +1,36 @@ +#include "QLogUtil.h" + + +QLogUtil::QLogUtil(QObject *parent) : QObject(parent) +{ + +} + +void QLogUtil::writeRawDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile rawLogFile(filename); + rawLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + rawLogFile.write(content.toUtf8()); + rawLogFile.close(); +} + +void QLogUtil::writeChannelDataLog(QString filename, QString content) +{ + content.append("\n"); + QFile chLogFile(filename); + chLogFile.open(QIODevice::ReadWrite|QIODevice::Append|QIODevice::Text); + chLogFile.write(content.toUtf8()); + chLogFile.close(); +} + +void QLogUtil::writeDebugLog(QString message) +{ + +} + +void QLogUtil::writeInfoLog(QString message) +{ + +} + diff --git a/DevStatusAcq/common/utils/QLogUtil.h b/DevStatusAcq/common/utils/QLogUtil.h new file mode 100644 index 0000000..8da0fcd --- /dev/null +++ b/DevStatusAcq/common/utils/QLogUtil.h @@ -0,0 +1,23 @@ +#ifndef QLOGUTIL_H +#define QLOGUTIL_H + +#include +#include +#include + +class QLogUtil : public QObject +{ + Q_OBJECT +public: + explicit QLogUtil(QObject *parent = nullptr); + + static void writeRawDataLog(QString filename, QString content); + static void writeChannelDataLog(QString filename, QString content); + static void writeInfoLog(QString message); + static void writeDebugLog(QString message); + +signals: + +}; + +#endif // QLOGUTIL_H diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.cpp b/DevStatusAcq/common/utils/QSerialPortUtil.cpp new file mode 100644 index 0000000..9026fcf --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.cpp @@ -0,0 +1,69 @@ +#include "QSerialPortUtil.h" + +#include +#include +#include +#include "common/utils/QByteUtil.h" + +QSerialPortUtil::QSerialPortUtil(QObject *parent) : QObject(parent) +{ + // 其他默认配置 + serial.setDataBits(QSerialPort::Data8); + serial.setParity(QSerialPort::NoParity); + serial.setStopBits(QSerialPort::OneStop); + serial.setFlowControl(QSerialPort::NoFlowControl); +} + +void QSerialPortUtil::openSerialPort(QString portName, int baudRate) +{ + serial.setPortName(portName); // 串口名 + serial.setBaudRate(baudRate); // 波特率 + + open = serial.open(QIODevice::ReadWrite); + +// if (open == true) +// { + // 绑定信号与槽 + connect(&serial, &QSerialPort::readyRead, + this, &QSerialPortUtil::readData); + + // mock data received per second + QTimer * timer = new QTimer(this); + connect(timer, &QTimer::timeout, + this, &QSerialPortUtil::mockReceivData); + timer->start(1000 * 10); +// } +} + +void QSerialPortUtil::sendData(QByteArray data) +{ + if (this->open == true) + { + std::cout << data.toStdString() << std::endl; + serial.write(data); + } +} + +void QSerialPortUtil::readData() +{ + QByteArray buffer = serial.readAll(); + + emit dataRecieved(buffer); +} + +bool QSerialPortUtil::isOpen() +{ + return this->open; +} + +void QSerialPortUtil::mockReceivData() +{ + QByteArray buffer; + buffer.append("$GLN,0,192.168.000.126,255.255.255.000,192.168.000.001,192.168.001.126,255.255.255.000,192.168.001.001,255.255.255.255,3000,2000,2001*75").append("\r\n"); + buffer.append("$GLF,1,0,20210929,1,1,1,-0.01,20000,0,2,50,1*48").append("\r\n"); + buffer.append("$GPZDA,192157.00,01,01,2000,0,01*5C").append("\r\n"); + buffer.append("$GPMJD,192157.00,51544,0,01*73").append("\r\n"); + buffer.append("$GLC,0,0*48").append("\r\n"); + + emit dataRecieved(buffer); +} diff --git a/DevStatusAcq/common/utils/QSerialPortUtil.h b/DevStatusAcq/common/utils/QSerialPortUtil.h new file mode 100644 index 0000000..accf403 --- /dev/null +++ b/DevStatusAcq/common/utils/QSerialPortUtil.h @@ -0,0 +1,30 @@ +#ifndef QSERIALPORTUTIL_H +#define QSERIALPORTUTIL_H + +#include +#include + +class QSerialPortUtil : public QObject +{ + Q_OBJECT +public: + explicit QSerialPortUtil(QObject *parent = nullptr); + + void openSerialPort(QString portName, int baudRate); + void sendData(QByteArray data); + void readData(); + + bool isOpen(); + +private: + QSerialPort serial; + + bool open; + + void mockReceivData(); + +signals: + void dataRecieved(QByteArray data); // 收到数据的信号 +}; + +#endif // QSERIALPORTUTIL_H diff --git a/DevStatusAcq/common/utils/SettingConfig.cpp b/DevStatusAcq/common/utils/SettingConfig.cpp new file mode 100644 index 0000000..67a8dd0 --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.cpp @@ -0,0 +1,23 @@ +#include "SettingConfig.h" + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + PORT_NAMES = getProperty("com", "portNames").toString(); + BAUD_RATE = getProperty("com", "baudRate").toUInt(); + DEV_CODES = getProperty("com", "devCodes").toString(); + + NEED_KAFKA = getProperty("kafka", "needKafka").toUInt(); + KAFKA_BROKERS = getProperty("kafka", "brokers").toString(); + KAFKA_DATA_TOPIC = getProperty("kafka", "dataTopic").toString(); + + CLIENT_ID = getProperty("client", "clientId").toString(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/DevStatusAcq/common/utils/SettingConfig.h b/DevStatusAcq/common/utils/SettingConfig.h new file mode 100644 index 0000000..2d10a4d --- /dev/null +++ b/DevStatusAcq/common/utils/SettingConfig.h @@ -0,0 +1,47 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + QString PORT_NAMES; + int BAUD_RATE; + QString DEV_CODES; + + int NEED_KAFKA; + QString KAFKA_BROKERS; + QString KAFKA_DATA_TOPIC; + + QString CLIENT_ID; + +private: + SettingConfig(); + + QString filename; + QSettings * setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/DevStatusAcq/conf/config.ini b/DevStatusAcq/conf/config.ini new file mode 100644 index 0000000..4f2968b --- /dev/null +++ b/DevStatusAcq/conf/config.ini @@ -0,0 +1,12 @@ +[com] +portNames="COM3" +devCodes="9103" +baudRate=115200 + +[kafka] +needKafka=0 +brokers="111.198.10.15:12502" +dataTopic="cppTest" + +[client] +clientId="112233445566" diff --git a/DevStatusAcq/device/SignalGenerator.cpp b/DevStatusAcq/device/SignalGenerator.cpp new file mode 100644 index 0000000..135f881 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.cpp @@ -0,0 +1,103 @@ +#include "SignalGenerator.h" + +#include +#include + +SignalGenerator::SignalGenerator(QObject *parent) : QObject(parent) +{ + connect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); + + kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); + kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC); + kafkaUtil.createProducer(); +} + +SignalGenerator::~SignalGenerator() +{ + disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved, + this, &SignalGenerator::dataReceivedHandler); +} + +void SignalGenerator::setComName(QString comName) +{ + this->comName = comName; +} +void SignalGenerator::setBaudRate(int baudRate) +{ + this->baudRate = baudRate; +} +QString SignalGenerator::getDevCode() +{ + return this->devCode; +} +void SignalGenerator::setDevCode(QString devCode) +{ + this->devCode = devCode; +} + +bool SignalGenerator::isSerialOpen() +{ + return this->serialUtil.isOpen(); +} + +void SignalGenerator::initSerialPort() +{ + this->serialUtil.openSerialPort(this->comName, this->baudRate); +} + +void SignalGenerator::dataReceivedHandler(QByteArray data) +{ + this->dataBuff.append(data); + + std::cout << dataBuff.toStdString() << std::endl; + + QList frameList = SignalGeneratorProtocolBM::extractFrameList(this->dataBuff); + + if (frameList.size() > 0) + { + for (int i = 0; i < frameList.size(); i++) + { + QByteArray frameByte = frameList.at(i); + + int frameType = SignalGeneratorProtocolBM::checkFrame(frameByte); + SignalGeneratorFrameDto * sgFrameDto = SignalGeneratorProtocolBM::sgFrameFactory(frameType); + if (sgFrameDto != nullptr) + { + // ★解析成数据对象 + bool parse = SignalGeneratorProtocolBM::parseSignalGeneratorData(frameByte, sgFrameDto, frameType); + + // 解析成功 + if (parse == true) + { + QDateTime now = QDateTime::currentDateTime(); + sgFrameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz"); + sgFrameDto->milisecond = now.toMSecsSinceEpoch(); + sgFrameDto->rawFrame = frameByte; + + this->afterFramePhase(sgFrameDto); + } + + // 在此处释放内存,不影响后续显示 + // 不在此处释放内存则会导致内存持续增加 + // 具体原因不明 + delete sgFrameDto; + } + } + } +} + +void SignalGenerator::afterFramePhase(SignalGeneratorFrameDto * frameDto) +{ + std::cout << "frame type: " << typeid(* frameDto).name() << std::endl; + std::cout << frameDto->rawFrame.toStdString() << std::endl; + + // 3. 输出到中间件,执行后续处理过程 + if (SettingConfig::getInstance().NEED_KAFKA == 1) + { + QJsonObject jsonObj = frameDto->toJSON(); + jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID); + jsonObj.insert("deviceId", devCode); + kafkaUtil.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact))); + } +} diff --git a/DevStatusAcq/device/SignalGenerator.h b/DevStatusAcq/device/SignalGenerator.h new file mode 100644 index 0000000..a295955 --- /dev/null +++ b/DevStatusAcq/device/SignalGenerator.h @@ -0,0 +1,49 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "common/utils/QSerialPortUtil.h" +#include "common/utils/QKafkaUtil.h" +#include "common/utils/QByteUtil.h" +#include "common/utils/QLogUtil.h" +#include "common/utils/SettingConfig.h" + +#include "protocol/dto/SignalGeneratorFrameDto.h" +#include "protocol/SignalGeneratorProtocolBM.h" + +class SignalGenerator : public QObject +{ + Q_OBJECT +public: + explicit SignalGenerator(QObject *parent = nullptr); + ~SignalGenerator(); + + void initSerialPort(); + + void afterFramePhase(SignalGeneratorFrameDto * frameDto); + + void setComName(QString comName); + void setBaudRate(int baudRate); + QString getDevCode(); + void setDevCode(QString devCode); + + bool isSerialOpen(); + +private: + QString devCode; + QString comName; + int baudRate; + + QSerialPortUtil serialUtil; + QKafkaUtil kafkaUtil; + QByteArray dataBuff; + +signals: + void sendDataToDraw(SignalGeneratorFrameDto * frameData); + +public slots: + void dataReceivedHandler(QByteArray data); + +}; + +#endif // SIGNALGENERATOR_H diff --git a/DevStatusAcq/device/device.pri b/DevStatusAcq/device/device.pri new file mode 100644 index 0000000..1153675 --- /dev/null +++ b/DevStatusAcq/device/device.pri @@ -0,0 +1,4 @@ + +HEADERS += $$PWD/SignalGenerator.h + +SOURCES += $$PWD/SignalGenerator.cpp diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp new file mode 100644 index 0000000..bea2e6f --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.cpp @@ -0,0 +1,242 @@ +#include "SignalGeneratorProtocolBM.h" +#include + +SignalGeneratorProtocolBM::SignalGeneratorProtocolBM(QObject *parent) : QObject(parent) +{ + +} + +SignalGeneratorProtocolBM::~SignalGeneratorProtocolBM() +{ + +} + +SignalGeneratorFrameDto * SignalGeneratorProtocolBM::sgFrameFactory(int frameType) +{ + SignalGeneratorFrameDto * sgFrameData = 0; + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + sgFrameData = new SignalGeneratorInterfaceDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + sgFrameData = new SignalGeneratorStatusDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + sgFrameData = new SignalGeneratorZDATimeDto(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + sgFrameData = new SignalGeneratorMJDTimeDto(); + break; + + default: + sgFrameData = nullptr; + break; + } + + return sgFrameData; +} + +bool SignalGeneratorProtocolBM::parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + switch (frameType) { + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME : + + ((SignalGeneratorInterfaceDto *)sgFrameData)->keyControl = subList.at(0); + ((SignalGeneratorInterfaceDto *)sgFrameData)->timeType = subList.at(1); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME : + + ((SignalGeneratorStatusDto *)sgFrameData)->devStatus = subList.at(0); + ((SignalGeneratorStatusDto *)sgFrameData)->leapSec = subList.at(1); + ((SignalGeneratorStatusDto *)sgFrameData)->leapTimestamp = subList.at(2); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalStatus = subList.at(3); + ((SignalGeneratorStatusDto *)sgFrameData)->freqSignalType = subList.at(4); + ((SignalGeneratorStatusDto *)sgFrameData)->oppsSignalStatus = subList.at(5); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseDiff = subList.at(6).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->pulseWidth = subList.at(7).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->phaseShiftAcc = subList.at(8).toLongLong(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRatio = subList.at(9).toUInt(); + ((SignalGeneratorStatusDto *)sgFrameData)->bacRange = subList.at(10).toFloat(); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME : + + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaTime = subList.at(0); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaDay = subList.at(1); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaMon = subList.at(2); + ((SignalGeneratorZDATimeDto *)sgFrameData)->zdaYear = subList.at(3); + ((SignalGeneratorZDATimeDto *)sgFrameData)->leapSec = subList.at(4); + ((SignalGeneratorZDATimeDto *)sgFrameData)->valid = subList.at(5); + break; + + case SignalGeneratorProtocolBM::SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME : + + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdTime = subList.at(0); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->mjdDay = subList.at(1); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->leapSec = subList.at(2); + ((SignalGeneratorMJDTimeDto *)sgFrameData)->valid = subList.at(3); + break; + + } + + return true; +} +/* +bool SignalGeneratorProtocolBM::parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + interfaceData->keyControl = subList.at(0).toUInt(); + interfaceData->timeType = subList.at(1).toUInt(); + + return true; +} + +bool SignalGeneratorProtocolBM::parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + + + return true; +} + +bool SignalGeneratorProtocolBM::parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData) +{ + // get the raw data between ',' and '*' + int start = rawData.indexOf(SIGNAL_GENERATOR_FRAME_CONTENT_SEP); + int end = rawData.indexOf(SIGNAL_GENERATOR_FRAME_SUM_SEP); + + QByteArray content = rawData.mid(start + 1, end - start - 1); + QString contentStr = QString(content); + QStringList subList = contentStr.split(","); + + mjdData->mjdTime = subList.at(0); + + + return true; +} +*/ +QList SignalGeneratorProtocolBM::extractFrameList(QByteArray rawData) +{ + QList resultList; + if (rawData.endsWith(QByteArray("\r\n")) == true && rawData.startsWith("$") == true) + { + QByteArray ba; + for (int i = 0; i < rawData.size() - 1; i++) + { + if (rawData.at(i) != '\r') + { + ba.append(rawData.at(i)); + } else + { + if (rawData.at(i + 1) == '\n') + { + ba.append("\r\n"); + resultList.append(ba); + ba.clear(); + i++; + } else + { + ba.append(rawData.at(i)); + } + } + } + } + + return resultList; +} + +int SignalGeneratorProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧尾不是\r\n + if (SIGNAL_GENERATOR_FRAME_TAIL.toLocal8Bit() != rawData.mid(rawData.size() - SIGNAL_GENERATOR_FRAME_TAIL.size())) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } + + // 帧头不是$GL + if (SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::INTERFACE_FRAME; + } + } else if (SIGNAL_GENERATOR_STATUS_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_STATUS_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::STATUS_FRAME; + } + } else if (SIGNAL_GENERATOR_MJD_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_MJD_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::MJD_FRAME; + } + } else if (SIGNAL_GENERATOR_ZDA_FRAME_HEAD.toLocal8Bit() == rawData.mid(0, SIGNAL_GENERATOR_ZDA_FRAME_HEAD.size())) + { + // 帧长度小于最小的长度 + if (rawData.size() < SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH) + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::ZDA_FRAME; + } + } else + { + return SIGNAL_GENERATOR_FRAME_TYPE::UNKNOW_FRAME; + } +} diff --git a/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h new file mode 100644 index 0000000..016d378 --- /dev/null +++ b/DevStatusAcq/protocol/SignalGeneratorProtocolBM.h @@ -0,0 +1,75 @@ +#ifndef SIGNALGENERATORPROTOCOLBM_H +#define SIGNALGENERATORPROTOCOLBM_H + +#include +#include + +#include "dto/SignalGeneratorInterfaceDto.h" +#include "dto/SignalGeneratorStatusDto.h" +#include "dto/SignalGeneratorMJDTimeDto.h" +#include "dto/SignalGeneratorZDATimeDto.h" + +static const QString SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD = "$GLC"; // 帧头 +static const QString SIGNAL_GENERATOR_STATUS_FRAME_HEAD = "$GLF"; // 帧头 +static const QString SIGNAL_GENERATOR_MJD_FRAME_HEAD = "$GPMJD"; // 帧头 +static const QString SIGNAL_GENERATOR_ZDA_FRAME_HEAD = "$GPZDA"; // 帧头 +static const QString SIGNAL_GENERATOR_FRAME_TAIL = "\r\n"; // 帧尾 +static const QString SIGNAL_GENERATOR_FRAME_CONTENT_SEP = ","; // 帧内分隔符 +static const QString SIGNAL_GENERATOR_FRAME_SUM_SEP = "*"; // 异或和字段的分隔符 + +static const int SIGNAL_GENERATOR_FRAME_SUM_LENGTH = 2; +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT = 2; +static const int SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT = 11; +static const int SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT = 6; +static const int SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT = 4; +static const int SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE = 2; + +static const int SIGNAL_GENERATOR_INTERFACE_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_INTERFACE_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_INTERFACE_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_STATUS_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_STATUS_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_STATUS_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_ZDA_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_ZDA_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_ZDA_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; +static const int SIGNAL_GENERATOR_MJD_FRAME_MIN_LENGTH = SIGNAL_GENERATOR_MJD_FRAME_HEAD.length() + + SIGNAL_GENERATOR_FRAME_TAIL.length() + + SIGNAL_GENERATOR_MJD_FRAME_SUB_COUNT * SIGNAL_GENERATOR_FRAME_SUB_MIN_SIZE + + 1 + SIGNAL_GENERATOR_FRAME_SUM_LENGTH; + +class SignalGeneratorProtocolBM : public QObject +{ +public: + explicit SignalGeneratorProtocolBM(QObject *parent = nullptr); + ~SignalGeneratorProtocolBM(); + + // 解析数据 + static bool parseSignalGeneratorData(QByteArray rawData, SignalGeneratorFrameDto * sgFrameData, int frameType); + static SignalGeneratorFrameDto * sgFrameFactory(int frameType); +// static bool parseInterfaceData(QByteArray rawData, SignalGeneratorInterfaceDto * interfaceData); +// static bool parseStatusData(QByteArray rawData, SignalGeneratorStatusDto * statusData); +// static bool parseZDAData(QByteArray rawData, SignalGeneratorZDATimeDto * zdaData); +// static bool parseMJDData(QByteArray rawData, SignalGeneratorMJDTimeDto * mjdData); + + // + static QList extractFrameList(QByteArray rawData); + + // 检测帧格式,帧头帧尾 + static int checkFrame(QByteArray rawData); + + enum SIGNAL_GENERATOR_FRAME_TYPE + { + UNKNOW_FRAME = 0, + INTERFACE_FRAME = 1, + STATUS_FRAME = 2, + ZDA_FRAME = 3, + MJD_FRAME = 4, + NETWORK_FRAME = 5 + }; +}; + +#endif // SIGNALGENERATORPROTOCOLBM_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp new file mode 100644 index 0000000..b228e4d --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.cpp @@ -0,0 +1,6 @@ +#include "SignalGeneratorFrameDto.h" + +SignalGeneratorFrameDto::SignalGeneratorFrameDto(QObject *parent) : QObject(parent) +{ + +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h new file mode 100644 index 0000000..504f410 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorFrameDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORFRAMEDTO_H +#define SIGNALGENERATORFRAMEDTO_H + +#include +#include +#include + +class SignalGeneratorFrameDto : public QObject +{ + Q_OBJECT +public: + explicit SignalGeneratorFrameDto(QObject *parent = nullptr); + + QByteArray rawFrame; // 原始帧字节数组 + + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QString devCode; + + virtual QJsonObject toJSON() = 0; + +signals: + +}; + +#endif // SIGNALGENERATORFRAMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp new file mode 100644 index 0000000..68e4204 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.cpp @@ -0,0 +1,20 @@ +#include "SignalGeneratorInterfaceDto.h" + +SignalGeneratorInterfaceDto::SignalGeneratorInterfaceDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorInterfaceDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("keyControl", keyControl); + dataObj.insert("timeType", timeType); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h new file mode 100644 index 0000000..2ea4653 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorInterfaceDto.h @@ -0,0 +1,22 @@ +#ifndef SIGNALGENERATORINTERFACEDTO_H +#define SIGNALGENERATORINTERFACEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorInterfaceDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorInterfaceDto(QObject *parent = nullptr); + + QString keyControl; // + QString timeType; // + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORINTERFACEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp new file mode 100644 index 0000000..61c9289 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.cpp @@ -0,0 +1,22 @@ +#include "SignalGeneratorMJDTimeDto.h" + +SignalGeneratorMJDTimeDto::SignalGeneratorMJDTimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorMJDTimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("mjdTime", mjdTime); + dataObj.insert("mjdDay", mjdDay); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h new file mode 100644 index 0000000..c95e1a3 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorMJDTimeDto.h @@ -0,0 +1,24 @@ +#ifndef SIGNALGENERATORMJDTIMEDTO_H +#define SIGNALGENERATORMJDTIMEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorMJDTimeDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorMJDTimeDto(QObject *parent = nullptr); + + QString mjdTime; // <1> + QString mjdDay; // <2> + QString leapSec; // <3> + QString valid; // <4> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORMJDTIMEDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp new file mode 100644 index 0000000..1113584 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.cpp @@ -0,0 +1,29 @@ +#include "SignalGeneratorStatusDto.h" + +SignalGeneratorStatusDto::SignalGeneratorStatusDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorStatusDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("devStatus", devStatus); + dataObj.insert("leap", leapSec); + dataObj.insert("leapTm", leapTimestamp); + dataObj.insert("freqStatus", freqSignalStatus); + dataObj.insert("freqType", freqSignalType); + dataObj.insert("oppsStatus", oppsSignalStatus); + dataObj.insert("phaseDiff", phaseDiff); + dataObj.insert("pulseWidth", pulseWidth); + dataObj.insert("phaseAcc", phaseShiftAcc); + dataObj.insert("bacRatio", bacRatio); + dataObj.insert("bacRange", bacRange); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h new file mode 100644 index 0000000..1c6d005 --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorStatusDto.h @@ -0,0 +1,31 @@ +#ifndef SIGNALGENERATORSTATUSDTO_H +#define SIGNALGENERATORSTATUSDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorStatusDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorStatusDto(QObject *parent = nullptr); + + QString devStatus; // <1> + QString leapSec; // <2> + QString leapTimestamp; // <3> + QString freqSignalStatus; // <4> + QString freqSignalType; // <5> + QString oppsSignalStatus; // <6> + qlonglong phaseDiff; // <7> + qlonglong pulseWidth; // <8> + qlonglong phaseShiftAcc; // <9> + qint8 bacRatio; // <10> + float bacRange; // <11> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORSTATUSDTO_H diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp new file mode 100644 index 0000000..231977f --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.cpp @@ -0,0 +1,24 @@ +#include "SignalGeneratorZDATimeDto.h" + +SignalGeneratorZDATimeDto::SignalGeneratorZDATimeDto(QObject *parent) : SignalGeneratorFrameDto(parent) +{ + +} + +QJsonObject SignalGeneratorZDATimeDto::toJSON() +{ + QJsonObject jsonObj; + + QJsonObject dataObj; + dataObj.insert("zdaTime", zdaTime); + dataObj.insert("zdaDay", zdaDay); + dataObj.insert("zdaMon", zdaMon); + dataObj.insert("zdaYear", zdaYear); + dataObj.insert("leapSec", leapSec); + dataObj.insert("valid", valid); + + jsonObj.insert("ts", this->milisecond); + jsonObj.insert("data", dataObj); + + return jsonObj; +} diff --git a/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.h b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.h new file mode 100644 index 0000000..d3f145a --- /dev/null +++ b/DevStatusAcq/protocol/dto/SignalGeneratorZDATimeDto.h @@ -0,0 +1,26 @@ +#ifndef SIGNALGENERATORZDATIMEDTO_H +#define SIGNALGENERATORZDATIMEDTO_H + +#include +#include "protocol/dto/SignalGeneratorFrameDto.h" + +class SignalGeneratorZDATimeDto : public SignalGeneratorFrameDto +{ + Q_OBJECT +public: + explicit SignalGeneratorZDATimeDto(QObject *parent = nullptr); + + QString zdaTime; // <1> + QString zdaDay; // <2> + QString zdaMon; // <3> + QString zdaYear; // <4> + QString leapSec; // <5> + QString valid; // <6> + + QJsonObject toJSON(); + +signals: + +}; + +#endif // SIGNALGENERATORZDATIMEDTO_H diff --git a/DevStatusAcq/protocol/protocol.pri b/DevStatusAcq/protocol/protocol.pri new file mode 100644 index 0000000..0589e42 --- /dev/null +++ b/DevStatusAcq/protocol/protocol.pri @@ -0,0 +1,14 @@ + +HEADERS += $$PWD/dto/SignalGeneratorFrameDto.h +HEADERS += $$PWD/dto/SignalGeneratorStatusDto.h +HEADERS += $$PWD/dto/SignalGeneratorInterfaceDto.h +HEADERS += $$PWD/dto/SignalGeneratorZDATimeDto.h +HEADERS += $$PWD/dto/SignalGeneratorMJDTimeDto.h +HEADERS += $$PWD/SignalGeneratorProtocolBM.h + +SOURCES += $$PWD/dto/SignalGeneratorFrameDto.cpp +SOURCES += $$PWD/dto/SignalGeneratorStatusDto.cpp +SOURCES += $$PWD/dto/SignalGeneratorInterfaceDto.cpp +SOURCES += $$PWD/dto/SignalGeneratorZDATimeDto.cpp +SOURCES += $$PWD/dto/SignalGeneratorMJDTimeDto.cpp +SOURCES += $$PWD/SignalGeneratorProtocolBM.cpp diff --git a/ZXSSCJ.pro b/ZXSSCJ.pro index 87b1bd3..ec3c2e5 100644 --- a/ZXSSCJ.pro +++ b/ZXSSCJ.pro @@ -3,7 +3,7 @@ #定义了ordered表示子项目按照添加的顺序来编译 #CONFIG += ordered -SUBDIRS += CounterAcq #计数器数据采集 -SUBDIRS += PhaseCompAcq #比相仪数据采集 -#SUBDIRS += DevStatusAcq +#SUBDIRS += CounterAcq #计数器数据采集 +#SUBDIRS += PhaseCompAcq #比相仪数据采集 +SUBDIRS += DevStatusAcq #SUBDIRS += HClockAcq #氢钟状态数据采集