diff --git a/CableTool/common.h b/CableTool/common.h index 009f408..c957c6a 100644 --- a/CableTool/common.h +++ b/CableTool/common.h @@ -248,6 +248,43 @@ typedef enum ADC_ENERGY_CNT } ADC_ENERGY_E; +enum WaveStateE +{ + WAVE_STATE_IDLE = 0, + WAVE_STATE_START, + WAVE_STATE_WAIT, + WAVE_STATE_READ, + WAVE_STATE_STOP, + WAVE_STATE_ADC_ERROR, + WAVE_STATE_TIMEOUT, + WAVE_STATE_COMPLETION = 255 +}; +//Q_ENUM(WaveStateE); + +/* 状态机状态. */ +enum WlStateE +{ + WL_STATE_SOFT = 0, + WL_STATE_AT_ATE, + WL_STATE_AT_QICSGP, + WL_STATE_AT_QIACT, + WL_STATE_AT_CSQ, + WL_STATE_AT_QICFGTS, + WL_STATE_AT_QICFGWT, + WL_STATE_AT_QIOPEN, + WL_STATE_WAKEUP = 128, + WL_STATE_REALDATA, + WL_STATE_PWR_FRE, + WL_STATE_UPDATE, + WL_STATE_UPDATE_RT, + WL_STATE_WAVE, + WL_STATE_WAVE_MAX, + WL_STATE_KEEPALIVE, + WL_STATE_END = 255 +}; +//Q_ENUM(WlStateE); + + typedef struct { uint16_t len; @@ -346,6 +383,41 @@ typedef struct uint8_t senValid[SENSOR_SUM]; // 传感器数据是否有效, 0 - 无效, 1 - 有效. } realData_t; +/* 设备状态信息. */ +typedef struct +{ + uint8_t energyMode; // 节能模式. + uint8_t isAdcCollect; // ADC 采集完成. + uint8_t isAdcUp; // ADC 上传完成. + uint8_t AdciCnt; // ADCi 错误计数. + uint8_t AdciState; // ADCi 状态. + uint8_t AdcCnt; // ADC 错误计数. + uint8_t AdcState; // ADC 状态. + uint8_t waveState; // 高频录波状态. + uint32_t waveTime; // 高频录波开始时间. + uint8_t waveStart; // 高频录波完成. + uint8_t waveUpStart; // 高频录波上传完成. + uint16_t waveIdx; // 高频录波续传索引. + uint8_t waveRt; // 高频录波结果. + uint8_t waveForce; // 是否强制录波. + uint8_t wlState; // 4G 状态. + uint8_t wlCnt; // 4G 错误计数. + uint16_t wlWaveIdx; // 4G 上传录波文件索引. + uint8_t isWlUpdate; // 4G 升级. + uint8_t isAdcthr; // 是否超过工频阈值. + uint8_t forceSleepUp; // 强制睡眠报文是否上传. + uint8_t isBatCharge; // 电池充电状态. + uint16_t waveAdj; // 高频校准系数. + int16_t waveMin; // 高频采样最大值. + int16_t waveMax; // 高频采样最小值. + uint32_t sysTime; // 系统运行时间. + uint16_t scMax; // 超级电容最大值. + uint16_t scMin; // 超级电容最小值. + uint32_t scMaxTime; // 超级电容最大值时间. + uint32_t scMinTime; // 超级电容最小值时间. + uint32_t scUpTime; // 超级电容充电时间. + uint32_t scDownTime; // 超级电容放电时间. +} devState; /* 高频校准信息. */ typedef struct diff --git a/CableTool/widget.cpp b/CableTool/widget.cpp index 8047632..9800b9b 100644 --- a/CableTool/widget.cpp +++ b/CableTool/widget.cpp @@ -13,6 +13,8 @@ Widget::Widget(QWidget *parent) { ui->setupUi(this); + on_btnRefresh_clicked(); + memset(rxbuf, 0, sizeof(rxbuf)); rxbufLen = 0; @@ -28,22 +30,54 @@ Widget::Widget(QWidget *parent) upFileRecvSize = 0; upFileSize = 0; isDataRefresh = false; - waveParam = 0; - is_log_up = 0; - logIndex = 0; + waveIndex = 0; + is_wave_up = 0; + + energyMode[0] = "未知"; + energyMode[1] = "正常模式"; + energyMode[2] = "节能模式"; + energyMode[3] = "休眠模式"; //usartProtocol = new Protocol; crc32_table_init(); + /* 配置校准页面表格 */ + ui->adjustTable->horizontalHeader()->setVisible(true); + ui->adjustTable->horizontalHeader()->resizeSection(0,20); + ui->adjustTable->horizontalHeader()->resizeSection(1,50); + + //如下代码设置横向表格头的间隔线,有四个方向的间隔线,不需要间隔线的可以设置为0px + ui->adjustTable->horizontalHeader()->setStyleSheet( + "QHeaderView::section{" + "border-top:0px solid #E5E5E5;" + "border-left:0px solid #E5E5E5;" + "border-right:0.5px solid #E5E5E5;" + "border-bottom: 0.5px solid #E5E5E5;" + "background-color:white;" + "padding:4px;" + "}" + ); + /* 打开配置文件, 恢复关闭前的状态. */ QString file = QCoreApplication::applicationDirPath()+"/CableTool.ini"; settings = new QSettings(file, QSettings::IniFormat, this); - searchUsablePort(); + + ui->comboBaud->setCurrentIndex(settings->value("baudBoxIndex", 6).toInt()); + filePath = settings->value("updateFile", "").toString(); + adjFilePath = settings->value("adjFile", "").toString(); + waveFilePath = settings->value("waveFile", "").toString(); + QFileInfo fileinfo = QFileInfo(filePath); + ui->fileNameEdit->setText(fileinfo.fileName()); + ui->fileNameEdit->setReadOnly(true); + ui->fileTypeBox->setCurrentIndex(settings->value("updateFileType", 0).toInt()); + ui->freChBox->setCurrentIndex(settings->value("freChIndex", 0).toInt()); + + //searchUsablePort(); } @@ -265,6 +299,60 @@ void Widget::buttonEnable(bool flag) ui->RatioParamGetButton->setEnabled(flag); } +QString Widget::devStateWaveStateGet(uint8_t state) +{ + switch(state) + { + case WAVE_STATE_IDLE: + return "空闲"; + case WAVE_STATE_START: + return "准备"; + case WAVE_STATE_WAIT: + return "等待"; + case WAVE_STATE_READ: + return "读取"; + case WAVE_STATE_STOP: + return "结束"; + case WAVE_STATE_ADC_ERROR: + case WAVE_STATE_TIMEOUT: + return "错误"; + case WAVE_STATE_COMPLETION: + return "完成"; + default: + return "未知"; + } +} + + +QString Widget::devStateWlStateGet(uint8_t state) +{ + switch(state) + { + case WL_STATE_SOFT: + case WL_STATE_AT_ATE: + case WL_STATE_AT_QICSGP: + case WL_STATE_AT_QIACT: + case WL_STATE_AT_CSQ: + case WL_STATE_AT_QIOPEN: + return "AT"; + case WL_STATE_WAKEUP: + return "联络"; + case WL_STATE_REALDATA: + return "数据"; + case WL_STATE_PWR_FRE: + return "工频"; + case WL_STATE_WAVE: + return "高频"; + case WL_STATE_UPDATE: + return "升级"; + case WL_STATE_UPDATE_RT: + return "升级回复"; + case WL_STATE_END: + return "完成"; + default: + return "未知"; + } +} void Widget::uiDevInfoRefresh() { @@ -445,6 +533,64 @@ void Widget::uiDevRealDataRefresh() ui->elec6Label->setText(temp); } +void Widget::uiDevStateRefresh() +{ + QString temp; + + if (clientDevState.energyMode < 4) + { + ui->stateEnergyLabel->setText(energyMode[clientDevState.energyMode]); + } + else + { + ui->stateEnergyLabel->setText(energyMode[0]); + } + ui->stateBatChargeLabel->setText(clientDevState.isBatCharge ? "未充电" : "充电"); + ui->stateForceSleepUpLabel->setText(clientDevState.forceSleepUp ? "是" : "否"); + ui->stateAdcColLabel->setText(clientDevState.isAdcCollect ? "完成" : "未完成"); + ui->stateAdcUpLabel->setText(clientDevState.isAdcUp ? "完成" : "未完成"); + ui->stateAdcThrLabel->setText(clientDevState.isAdcthr ? "是" : "否"); + ui->stateAdciCntLabel->setText(QString::number(clientDevState.AdciCnt)); + ui->stateAdciStLabel->setText(QString::number(clientDevState.AdciState)); + ui->stateAdcCntLabel->setText(QString::number(clientDevState.AdcCnt)); + ui->stateAdcStLabel->setText(QString::number(clientDevState.AdcState)); + + /*得到系统时间*/ + time_t cur = static_cast(clientDevState.waveTime); + tm *day; + day = localtime(&cur); + temp.sprintf("%d/%d/%d %d:%d:%d", day->tm_year + 1900, day->tm_mon+1, day->tm_mday, + day->tm_hour, day->tm_min, day->tm_sec); + ui->stateWaveTmLabel->setText(temp); + ui->stateWaveFinLabel->setText(clientDevState.waveStart ? "未完成" : "完成"); + ui->stateWaveUpLabel->setText(clientDevState.waveUpStart ? "未完成" : "完成"); + ui->stateWaveIdxLabel->setText(QString::number(clientDevState.waveIdx)); + ui->stateWaveStLabel->setText(devStateWaveStateGet(clientDevState.waveState)); + ui->stateWaveRtLabel->setText(QString::number(clientDevState.waveRt)); + ui->stateWaveForceLabel->setText(clientDevState.waveForce ? "是" : "否"); + + ui->stateWlStLabel->setText(devStateWlStateGet(clientDevState.wlState)); + ui->stateWlCntLabel->setText(QString::number(clientDevState.wlCnt)); + ui->stateWlUpLabel->setText(clientDevState.isWlUpdate ? "升级" : "未升级"); + ui->stateWlIdxLabel->setText(QString::number(clientDevState.wlWaveIdx)); + + ui->waveParamEdit->setText(QString::number(clientDevState.waveAdj)); + ui->waveFinLabel->setText(clientDevState.waveStart ? "未完成" : "完成"); + ui->waveMinEdit->setText(QString::number(clientDevState.waveMin)); + ui->waveMaxEdit->setText(QString::number(clientDevState.waveMax)); + + temp.sprintf("%dh:%dm:%ds", clientDevState.sysTime / 3600, (clientDevState.sysTime / 60) % 60, clientDevState.sysTime % 60); + ui->stateRunTimeLabel->setText(temp); + double tempSc; + tempSc = clientDevState.scMax / 1000.00; + ui->stateScMaxLabel->setText(QString::number(tempSc, 'g', 3)); + tempSc = clientDevState.scMin / 1000.00; + ui->stateScMinLabel->setText(QString::number(tempSc, 'g', 3)); + ui->stateUpTimeLabel->setText(QString::number(clientDevState.scUpTime)); + ui->stateDownTimeLabel->setText(QString::number(clientDevState.scDownTime)); +} + + void Widget::protoContact(char *data) { char *pbody = data + sizeof(proto_head_t); @@ -511,6 +657,63 @@ int Widget::protoUpdateReply(char *data, int fileType) return 0; } +int Widget::protoWaveDataUploadReply(char *data) +{ + mul_head_t *header = reinterpret_cast(data + sizeof(proto_head_t)); + + /* 数据头校验. */ + qDebug() << "recv:index:" << header->index << "waveIndex:" << waveIndex << "len:" << header->len << endl; + if (header->index != waveIndex + || header->len > UPDATE_DATA_SIZE) + { + return -1; + } + + /* 获取文件. */ + QFile file(waveFilePath); + if (0 == header->index) + { + file.remove(); + } + + if (file.open(QIODevice::WriteOnly | QIODevice::Append)) + { + file.write(data + sizeof(proto_head_t) + sizeof(mul_head_t), header->len); + file.close(); + qDebug() << "file " << header->index << header->len; + } + else + { + qDebug() << "file ERROR"; + return -1; + } + + /* 通知发包线程进入下个状态. */ + if (header->len < UPDATE_DATA_SIZE) + { + waveIndex = 0; + buttonEnable(true); + is_wave_up = false; + ui->upWaveIndexLabel->setText("下载完成"); + QMessageBox::information(this, "SUCCEED", "高频录波文件下载完成.", QMessageBox::Ok); + } + else + { + waveIndex = header->index + 1; + sendMsgDeviceWaveDataGet(); + ui->upWaveIndexLabel->setText(QString("%1 / 8000").arg(waveIndex)); + } + + return 0; +} + +int Widget::protoState(char *data) +{ + char *pbody = data + sizeof(proto_head_t); + memcpy(&clientDevState, pbody, sizeof(devState)); + uiDevStateRefresh(); + return 0; +} int Widget::paraseProtocols(char *data) { @@ -562,7 +765,7 @@ int Widget::paraseProtocols(char *data) //_debug_pkt_power_fre_get(); break; case DEBUG_PRV_DEFECT: - //_debug_pkt_wave_get(); + protoWaveDataUploadReply(data); break; case DEBUG_PRV_ADJ_INFO: //_debug_pkt_adj_get(); @@ -574,7 +777,7 @@ int Widget::paraseProtocols(char *data) //_debug_pkt_adj_auto(); break; case DEBUG_PRV_DEV_STATE: - //_debug_pkt_dev_state_get(); + protoState(data); break; case DEBUG_PRV_WAVE_COL: //_debug_pkt_wave_col(); @@ -818,6 +1021,46 @@ int Widget::sendMsgDeviceRealDataGet() return 0; } +int Widget::sendMsgDeviceWaveDataGet() +{ + char buf[2048] = {0}; + uint32_t *crc = nullptr; + proto_head_t *header = reinterpret_cast(buf); + mul_head_t *m_head = (mul_head_t*)(buf + sizeof(proto_head_t)); + + /* 初始化报文头. */ + protoHeaderInit(header, sizeof(proto_head_t) + sizeof(mul_head_t), clientDevInfo.id, DEBUG_CT_PRV_REQUEST, DEBUG_PRV_DEFECT); + m_head->index = waveIndex; + m_head->len = 0; + + /* 计算校验位. */ + crc = reinterpret_cast(buf + header->len); + *crc = crc32(buf, header->len); + + HexPrint(__FUNCTION__, buf, header->len + 4); + writeData(buf, header->len + 4); + return 0; +} + +int Widget::sendMsgDeviceStateGet() +{ + char buf[2048] = {0}; + uint32_t *crc = nullptr; + proto_head_t *header = reinterpret_cast(buf); + + /* 初始化报文头. */ + protoHeaderInit(header, sizeof(proto_head_t), clientDevInfo.id, DEBUG_CT_PRV_REQUEST, DEBUG_PRV_DEV_STATE); + + /* 计算校验位. */ + crc = reinterpret_cast(buf + header->len); + *crc = crc32(buf, header->len); + + HexPrint(__FUNCTION__, buf, header->len + 4); + writeData(buf, header->len + 4); + return 0; +} + + int Widget::sendMsgWaveCol() { char buf[2048] = {0}; @@ -1162,7 +1405,7 @@ void Widget::on_dataRefreshAutoButton_clicked() void Widget::on_stateRefreshButton_clicked() { - + sendMsgDeviceStateGet(); } void Widget::on_freRefreshButton_clicked() @@ -1274,3 +1517,52 @@ void Widget::on_historyDataButton_clicked() } } + +void Widget::on_waveButton_clicked() +{ + if (is_wave_up) + { + is_wave_up = false; + ui->waveButton->setText("下载高频数据"); + buttonEnable(true); + } + else + { + QString curPath; + if (waveFilePath.isEmpty()) + { + curPath = QCoreApplication::applicationDirPath(); + } + else + { + QFileInfo info = QFileInfo(waveFilePath); + curPath = info.path(); + } + + curPath.append("/wavefile.wave"); + QString path = QFileDialog::getSaveFileName(this, tr("下载高频数据文件"), curPath, tr("data(*.*)")); + if (path.isNull() || path.isEmpty()) + { + QMessageBox::information(this, tr("提示"), tr("下载高频数据文件失败")); + return; + } + else + { + waveFilePath = path; + settings->setValue("waveFile", waveFilePath); + } + + QString temp; + temp.sprintf("%d / 8000", waveIndex); + ui->upWaveIndexLabel->setText(temp); + waveIndex = 0; + + /* 关闭按钮. */ + buttonEnable(false); + ui->waveButton->setEnabled(true); + + is_wave_up = true; + ui->waveButton->setText("暂停高频数据"); + } +} + diff --git a/CableTool/widget.h b/CableTool/widget.h index d30c068..739aa5b 100644 --- a/CableTool/widget.h +++ b/CableTool/widget.h @@ -65,6 +65,8 @@ private slots: void on_stateLogButton_clicked(); + void on_waveButton_clicked(); + private: QString toHexadecimal(const QByteArray &byteArray); @@ -79,11 +81,17 @@ private: int protoHeaderInit(proto_head_t * header, uint16_t len, uint32_t id, uint8_t cmd_type, uint8_t cmd); void buttonEnable(bool flag); + + QString devStateWaveStateGet(uint8_t state); + + QString devStateWlStateGet(uint8_t state); void uiDevInfoRefresh(); void uiDevConfigRefresh(); void uiDevCsgConfigRefresh(); void uiDevRealDataRefresh(); + void uiDevStateRefresh(); + void protoContact(char *data); void protoConfig(char *data); @@ -93,6 +101,10 @@ private: void protoRealdata(char *data); int protoUpdateReply(char *data, int fileType); + + int protoWaveDataUploadReply(char *data); + + int protoState(char *data); int paraseProtocols(char *data); int snedMsgDeviceInfoGet(); int sendMsgDeviceInfoSet(); @@ -104,17 +116,20 @@ private: int sendMsgDeviceCsgConfigSet(); int sendMsgDeviceRealDataGet(); int sendMsgDeviceUpdate(int fileType); + int sendMsgDeviceWaveDataGet(); + + int sendMsgDeviceStateGet(); int sendMsgWaveCol(); int senMsgWaveCal(); - - Ui::form *ui; //新增的 QSerialPort *serialPort; QSettings *settings; - QString filePath; + QString filePath; + QString adjFilePath; + QString waveFilePath; //QThread *newTask; //Protocol *usartProtocol; @@ -125,6 +140,8 @@ private: devConfig clientDevConfig; csgConfig_t csgConfig; realData_t clientRealData; + devState clientDevState; + QString energyMode[4]; int isConnected; // serial connect state int64_t upFileSize; uint32_t upFileRecvSize; @@ -132,7 +149,9 @@ private: int isDataRefresh; int16_t powerFre[CFG_ADC_CH_CNT][ADC_COLLECT_CNT]; uint32_t freIndex; + uint32_t waveIndex; uint16_t waveParam; + uint8_t is_wave_up; uint8_t is_log_up; uint32_t logIndex; uint8_t is_data_up;