From: penglei <1624952103@qq.com> Date: Wed, 26 Nov 2025 12:46:17 +0000 (+0800) Subject: ln产测工具 初始版本 X-Git-Url: http://git.snicker.com.cn/sitemap.xml?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=mirrors%2Ffactory_tool.git ln产测工具 初始版本 --- diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index b893ae5..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -project(LANGUAGES CXX) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) - -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(RC_ICONS windows.ico) -# QtCreator supports the following variables for Android, which are identical to qmake Android variables. -# Check http://doc.qt.io/qt-5/deployment-android.html for more information. -# They need to be set before the find_package(Qt5 ...) call. - -#if(ANDROID) -# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") -# if (ANDROID_ABI STREQUAL "armeabi-v7a") -# set(ANDROID_EXTRA_LIBS -# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so -# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so) -# endif() -#endif() - -find_package(Qt5 COMPONENTS Widgets LinguistTools REQUIRED) - -set(TS_FILES untitled_zh_CN.ts) -include_directories(${CMAKE_SOURCE_DIR}) -if(ANDROID) - add_library(SHARED - main.cpp - mainwindow.cpp - mainwindow.h - mainwindow.ui - ${TS_FILES} - ) -else() - add_executable( - WIN32 - main.cpp - mainwindow.cpp - mainwindow.h - mainwindow.ui - mythread.h - mythread.cpp - custom.h - custom.cpp - Demoqrc.qrc - demopng.rc - at_data.cpp - at_data.h - result_thread.cpp - result_thread.h - common.h - ${TS_FILES} - ) -endif() - -target_link_libraries( PRIVATE - Qt5::Widgets - ${CMAKE_SOURCE_DIR}/lib/libwireless_tools.dll) -target_link_libraries( PRIVATE - Qt5::Widgets - ${CMAKE_SOURCE_DIR}/lib/libsecurec.a) - -qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES}) diff --git a/Demoqrc.qrc b/Demoqrc.qrc deleted file mode 100644 index 7f18d42..0000000 --- a/Demoqrc.qrc +++ /dev/null @@ -1,8 +0,0 @@ - - - icon/windows.png - icon/windows.ico - icon/FAIL.ico - icon/succ.ico - - diff --git a/Library_global.h b/Library_global.h deleted file mode 100644 index b110ebe..0000000 --- a/Library_global.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. - */ -#ifndef LIBRARY_GLOBAL_H -#define LIBRARY_GLOBAL_H - -#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || \ - defined(_WIN32) || defined(__WIN32__) || defined(__NT__) - -#define Q_DECL_EXPORT __declspec(dllexport) -#define Q_DECL_IMPORT __declspec(dllimport) -#else -#define Q_DECL_EXPORT __attribute__((visibility("default"))) -#define Q_DECL_IMPORT __attribute__((visibility("default"))) -#endif - -#if defined(LIBRARY_LIBRARY) -#define LIBRARY_EXPORT Q_DECL_EXPORT -#else -#define LIBRARY_EXPORT Q_DECL_IMPORT -#endif - -namespace uapi { -struct FileInfo { - unsigned short sn; - unsigned char name_len; - unsigned char is_dir; - unsigned int file_size; - char name[0xFF]; -}; - -struct FileListResult { - unsigned int lsInfoNumber; - FileInfo lsInfo[0]; -}; - -struct FileTransmitDataCount { - unsigned int total_size; - unsigned int transmited_size; -}; - -struct TransmitResult { - bool finishResult; -}; - -struct AtReceiveData { - unsigned int dataLength; - unsigned char *data; -}; - -struct SerialPortReceiveData { - unsigned int dataLength; - unsigned char *data; -}; -enum InfoType { - INFO_SERIALPORT, // 单板段数据 - INFO_FILE_TRANSMIT_RESULT, - INFO_FILE_LIST_RESULT, - INFO_AT_RECEIVE, -}; -enum ConnectMode { - MODE_SERIALPORT, - MODE_BLUETOOTH -}; -enum ErrorCode{ - ERROR_FAIL = -1, - ERROR_SUCC = 0x0, -}; -} - -#endif // LIBRARY_GLOBAL_H diff --git a/README.md b/README.md deleted file mode 100644 index 4bd4606..0000000 --- a/README.md +++ /dev/null @@ -1,32 +0,0 @@ -## 项目名称 -> 请介绍一下你的项目吧 - - - -## 运行条件 -> 列出运行该项目所必须的条件和相关依赖 -* 条件一 -* 条件二 -* 条件三 - - - -## 运行说明 -> 说明如何运行和使用你的项目,建议给出具体的步骤说明 -* 操作一 -* 操作二 -* 操作三 - - - -## 测试说明 -> 如果有测试相关内容需要说明,请填写在这里 - - - -## 技术架构 -> 使用的技术框架或系统架构图等相关说明,请填写在这里 - - -## 协作者 -> 高效的协作会激发无尽的创造力,将他们的名字记录在这里吧 diff --git a/Setting.ini b/Setting.ini deleted file mode 100644 index e3f6e21..0000000 --- a/Setting.ini +++ /dev/null @@ -1,22 +0,0 @@ -[Uart_setting] -uart_com=COM41 -uart_baud=18 -spp_addr= - -[Download_Setting] -download_board_path=/user/ -download_local_path= - -[Upload_Setting] -upload_board_path= -upload_local_path= - -[At_Setting] -at_mediamusicplay= -at_mediaaudiorecord= -at_fsrm= -at_delay_ms= -at_spp_addr= -custom_module_id= -custom_cmd_id= -custom_payload= diff --git a/at_data.cpp b/at_data.cpp deleted file mode 100644 index 1d76e0d..0000000 --- a/at_data.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include - -At_Process::At_Process(QObject *parent) -{ - Q_UNUSED(parent); - phy_type_list<<"01"<<"02"; - ble_pattern_type_list<<"02 "<<"00 "<<"01 "; - br_pattern_type_list<<"03 "<<"04 "<<"09 "; - packet_type_list<<"04 01 "<<"0B 01 "<<"0F 01 "<<"04 00 "<<"0A 00 "<<"0E 00 "<<"08 00 "<<"0B 00 "<<"0F 00 "; - br_len_array<<27<<183<<339<<54<<367<<679<<83<<552<<1021; - board_cmd_map.insert(BT_MODE_BR_TX,"AT^BTTX="); - board_cmd_map.insert(BT_MODE_BR_RX,"AT^BTRX="); - board_cmd_map.insert(BT_MODE_BLE_TX,"AT^BLETX="); - board_cmd_map.insert(BT_MODE_BLE_RX,"AT^BLERX="); - board_cmd_map.insert(BT_MODE_BTDUTMODE, "AT^BTDUTMODE="); - board_cmd_map.insert(DONGLE_MODE_SPPCONN,"AT+SPPCONN="); - board_cmd_map.insert(DONGLE_MODE_AT,"AT"); - board_cmd_map.insert(DONGLE_MODE_ADDR,"AT+ADDR"); - board_cmd_map.insert(BT_MODE_BTLO,"AT^BTLO="); - board_cmd_map.insert(BT_MODE_BTPWR,"AT^BTPWR="); - -} -At_Process::~At_Process(){} -QString At_Process::at_get_packet_type(int packet_type_index) -{ - return packet_type_list.at(packet_type_index); -} -int At_Process::at_get_packet_len(int packet_type_index) -{ - return br_len_array.at(packet_type_index); -} -QString At_Process::at_get_br_pattern_type(int pattern_type_index) -{ - return br_pattern_type_list.at(pattern_type_index); -} -QString At_Process::at_get_ble_pattern_type(int pattern_type_index) -{ - return ble_pattern_type_list.at(pattern_type_index); -} - -QString At_Process::at_get_ble_phy_type(int phy_type_index) -{ - return phy_type_list.at(phy_type_index); -} -QString At_Process::at_get_cmd_board(at_mode_board mode) -{ - return board_cmd_map[mode]; -} -QString At_Process::at_get_switch_format(QString br_switch) -{ - QString str; - if(br_switch.contains("OFF")){ - str="00"; - }else if(br_switch.contains("ON")){ - str="01 "; - } - return str; -} -QString At_Process::at_get_br_format(at_mode_board mode,QString br_switch,QString channel, int packet_type_index, QString payload_len, int pattern_type) -{ - QString str; - str += at_get_switch_format(br_switch); - if(br_switch.contains("ON")){ - str += QString("%1 ").arg(channel.toUInt(), 2, 16, QLatin1Char('0')); - str += at_get_packet_type(packet_type_index); - QString str_temp = QString("%1").arg(payload_len.toUInt(), 4, 16, QLatin1Char('0')); - str.insert(9, str_temp.mid(0, 2)+" "); - str.insert(9, str_temp.mid(2, 2)+" "); - str += at_get_br_pattern_type(pattern_type); - if(mode==BT_MODE_BR_TX){ - str.insert(3, "02 "); - } - } - return str; -} - -QString At_Process::at_get_ble_format(at_mode_board mode,QString br_switch,QString channel,int pattern_type_index, QString payload_len, int phy_index) -{ - QString str=NULL; - str += at_get_switch_format(br_switch); - if(br_switch.contains("ON")){ - str += QString("%1 ").arg(channel.toUInt(), 2, 16, QLatin1Char('0')); - if(mode==BT_MODE_BLE_TX){ - str+= at_get_ble_pattern_type(pattern_type_index); - str+= QString("%1 ").arg(payload_len.toUInt(), 2, 16, QLatin1Char('0')); - } - str+=at_get_ble_phy_type(phy_index); - } - return str; -} - - -bool At_Process::at_send_cmd_board(at_mode_board mode,QString format) -{ -// char *buf=nullptr; - uint32_t buf_len=0; - bool ret=false; - QString str=at_get_cmd_board(mode); - str+=format; - str+="\r\n"; - std::string bufstr = str.toStdString(); - const char* buf = bufstr.c_str(); - buf_len = strlen(buf); - if(uapi_uart_tx_data((void*)buf, buf_len)){ - ret=true; - } - return ret; -} - -bool At_Process::at_send_cmd_string(at_module_id module_id, at_cmd_id cmd_id,QString format) -{ - char *buf = nullptr; - uint32_t buf_len=0; - bool ret=false; - QByteArray arr = format.toLatin1(); - buf = arr.data(); - buf_len = arr.size(); - if (uapi_at_send(module_id, cmd_id, (uint8_t *)buf, buf_len, at_callback) == SUCC) { - at_set_id(module_id, cmd_id); - ret=true; - } - return ret; -} - -void At_Process::at_set_id(at_module_id at_module_id_temp, at_cmd_id at_cmd_id_temp) -{ - at_module_id_save = at_module_id_temp; - at_cmd_id_save = at_cmd_id_temp; -} - -void At_Process::at_get_id(at_module_id *at_module_id, at_cmd_id *at_cmd_id) -{ - *at_module_id = at_module_id_save; - *at_cmd_id = at_cmd_id_save; -} diff --git a/at_data.h b/at_data.h deleted file mode 100644 index 8323390..0000000 --- a/at_data.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef AT_DATA_H -#define AT_DATA_H - -#include -#include -#include -#include -#include - -struct at_media_command { - uint8_t cmd[2]; - uint8_t payload[0]; -}; - -enum at_br_packet_type -{ - PACKET_DH1, - PACKET_DH3, - PACKET_DH5, - PACKET_2DH1, - PACKET_2DH3, - PACKET_2DH5, - PACKET_3DH1, - PACKET_3DH3, - PACKET_3DH5, -}; - -enum at_ble_phy -{ - PHY_1M, - PHY_2M, -}; - -enum at_pattern_type -{ - PATTERN_TYPE_1, - PATTERN_TYPE_2, - PATTERN_TYPE_3, -}; - -enum at_mode_board -{ - BT_MODE_BR_TX, - BT_MODE_BR_RX, - BT_MODE_BLE_TX, - BT_MODE_BLE_RX, - BT_MODE_BTDUTMODE, - BT_MODE_BTLO, - BT_MODE_BTPWR, - DONGLE_MODE_SPPCONN, - DONGLE_MODE_AT, - DONGLE_MODE_ADDR, - MODE_MAX, -}; - -enum at_module_id -{ - MODULE_MCU =0x08, - MODULE_BT =0x09, - MODULE_AUDIO =0x0A, -}; - -enum at_cmd_id -{ - AUDIO_CMD = 0x00, - MCU_CMD_FSRM = 0x09, - MCU_CMD_STACKINFO = 0x0D, - MCU_CMD_CHECK_CONNECTED=0x40, - MCU_CMD_RETURN_VALUE=0x41, - BT_CMD_SETTXPOWER = 0x7A, - BT_CMD_DUTMODE = 0x7D, - BT_CMD_GET_RX = 0x83, - BT_CMD_BR_TX, - BT_CMD_BR_RX, - BT_CMD_BLE_TX, - BT_CMD_BLE_RX, - BT_CMD_DELAY_MS, - BT_CMD_DONGLE_MAC, - BT_CMD_RX_RESULT = 0xFF, -}; - - -class At_Process -{ -public: - At_Process(QObject *parent = 0); - ~At_Process(); - QString at_get_br_format(at_mode_board bt_mode,QString br_switch,QString channel, int packet_type, QString payload_len, int pattern_type); - QString at_get_ble_format(at_mode_board bt_mode,QString br_switch,QString channel,int pattern_type_index , QString payload_len, int phy_index); - bool at_send_cmd_string(at_module_id module_id, at_cmd_id cmd_id,QString format); - bool at_send_cmd_board(at_mode_board bt_mode,QString format); - void at_get_id(at_module_id *at_module_id, at_cmd_id *at_cmd_id); - int at_get_packet_len(int packet_type); - QString at_get_switch_format(QString br_switch); -private: - at_module_id at_module_id_save; - at_cmd_id at_cmd_id_save; - QStringList phy_type_list; - QStringList ble_pattern_type_list; - QStringList br_pattern_type_list; - QStringList packet_type_list; - QVector br_len_array; - QMap board_cmd_map; -private: - QString at_get_cmd_board(at_mode_board bt_mode); - QString at_get_ble_phy_type(int phy_type_index); - QString at_get_ble_pattern_type(int pattern_type); - QString at_get_br_pattern_type(int pattern_type); - QString at_get_packet_type(int packet_type); - void at_set_id(at_module_id at_module_id, at_cmd_id at_cmd_id); -}; -#endif // AT_DATA_H diff --git a/common.h b/common.h deleted file mode 100644 index c9ed230..0000000 --- a/common.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -#include -#include - -typedef uint8_t* u8Piont; -typedef void* vPiont; - -Q_DECLARE_METATYPE(u8Piont); -Q_DECLARE_METATYPE(vPiont); - -#define MESSAGE_INFO_COLOR(STRING) "" STRING "" " " -#define CHECK_DONGLE_CONNECTED - -#endif // COMMON_H diff --git a/custom.cpp b/custom.cpp deleted file mode 100644 index 542ed25..0000000 --- a/custom.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include - -MyComboBox::MyComboBox(QWidget *paraent) : QComboBox(paraent) {} -MyComboBox::~MyComboBox() {} - -void MyComboBox::mousePressEvent(QMouseEvent *e) -{ - if (e->button() == Qt::LeftButton) { - emit mouse_clicked(true); - } - QComboBox::mousePressEvent(e); -} - -void MyComboBox::ChangeItem(QString str) -{ - for(int i=0;icount();i++ ){ - if(this->itemText(i).contains(str)){ - this->setCurrentIndex(i); - break; - } - } -} - -MyLineEdit::MyLineEdit(QWidget *parent):QLineEdit(parent) -{ - -} - -void MyLineEdit::keyPressEvent(QKeyEvent *event) -{ - qDebug()<key(); - if(event->key()==Qt::Key_Up){ - int current_data=this->text().toInt()+1; - const QIntValidator *validator=(QIntValidator *)this->validator(); - if(current_data <= validator->top()){ - this->setText(QString::number(current_data,10)); - } - }else if(event->key()==Qt::Key_Down){ - int current_data=this->text().toInt()-1; - const QIntValidator *validator=(QIntValidator *)this->validator(); - if(current_data >= validator->bottom()){ - this->setText(QString::number(current_data,10)); - } - }else{ - QLineEdit::keyPressEvent(event);//执行 - } - event->ignore();//输出后,才将继续执行主窗口的keypressEvent事件 -} diff --git a/custom.h b/custom.h deleted file mode 100644 index dca637f..0000000 --- a/custom.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef MYCOMBOBOX_H -#define MYCOMBOBOX_H -#include -#include -#include -#include -#include -#include - -// 自定义 QComboBox 类,实现 clicked 信号 -class MyComboBox : public QComboBox -{ - Q_OBJECT - public: - explicit MyComboBox(QWidget *paraent = 0); - ~MyComboBox(); - void ChangeItem(QString str); - protected: - virtual void mousePressEvent(QMouseEvent *e) override; - signals: - void mouse_clicked(bool); -}; - -// 自定义MyLineEdit类,实现 up down按键自动加减值 -class MyLineEdit : public QLineEdit -{ - Q_OBJECT -public: - explicit MyLineEdit(QWidget *parent=0); -protected: - void keyPressEvent(QKeyEvent *event); -}; - -class MyValidator : public QIntValidator -{ - Q_OBJECT -public: - explicit MyValidator(QObject * parent = 0):QIntValidator(parent) - { - } - MyValidator(int bottom, int top, QObject * parent):QIntValidator(bottom, top, parent) - { - } - virtual void setRange(int bottom, int top) - { - QIntValidator::setRange(bottom, top); - } - ~MyValidator() - { - } - virtual State validate(QString &str, int &n) const - { - if(str.contains("+")){ - return Invalid; - } - if(n > 1 && str.startsWith("0")){ - return Invalid; - } - if(str.toInt()top()){ - return Invalid; - } - return QIntValidator::validate(str, n); - } -// virtual void fixup(QString &s) const -// { -// s = QString("%1").arg(bottom()); -// } -}; - -#endif // MYCOMBOBOX_H diff --git a/debug/at_data.obj b/debug/at_data.obj deleted file mode 100644 index 2b32fa7..0000000 Binary files a/debug/at_data.obj and /dev/null differ diff --git a/debug/custom.obj b/debug/custom.obj deleted file mode 100644 index 1df2882..0000000 Binary files a/debug/custom.obj and /dev/null differ diff --git a/debug/factory_tool.exe b/debug/factory_tool.exe deleted file mode 100644 index 9e8ace8..0000000 Binary files a/debug/factory_tool.exe and /dev/null differ diff --git a/debug/factory_tool.ilk b/debug/factory_tool.ilk deleted file mode 100644 index b647048..0000000 Binary files a/debug/factory_tool.ilk and /dev/null differ diff --git a/debug/factory_tool.pdb b/debug/factory_tool.pdb deleted file mode 100644 index c21528e..0000000 Binary files a/debug/factory_tool.pdb and /dev/null differ diff --git a/debug/factory_tool.vc.pdb b/debug/factory_tool.vc.pdb deleted file mode 100644 index 192ebff..0000000 Binary files a/debug/factory_tool.vc.pdb and /dev/null differ diff --git a/debug/main.obj b/debug/main.obj deleted file mode 100644 index c684f34..0000000 Binary files a/debug/main.obj and /dev/null differ diff --git a/debug/mainwindow.obj b/debug/mainwindow.obj deleted file mode 100644 index 3fe4735..0000000 Binary files a/debug/mainwindow.obj and /dev/null differ diff --git a/debug/moc_custom.obj b/debug/moc_custom.obj deleted file mode 100644 index 7bf1955..0000000 Binary files a/debug/moc_custom.obj and /dev/null differ diff --git a/debug/moc_mainwindow.obj b/debug/moc_mainwindow.obj deleted file mode 100644 index a37458f..0000000 Binary files a/debug/moc_mainwindow.obj and /dev/null differ diff --git a/debug/mythread.obj b/debug/mythread.obj deleted file mode 100644 index 74e3a86..0000000 Binary files a/debug/mythread.obj and /dev/null differ diff --git a/debug/result_thread.obj b/debug/result_thread.obj deleted file mode 100644 index 5cedc10..0000000 Binary files a/debug/result_thread.obj and /dev/null differ diff --git a/debug/wrtm_class.obj b/debug/wrtm_class.obj deleted file mode 100644 index dd9534d..0000000 Binary files a/debug/wrtm_class.obj and /dev/null differ diff --git a/demopng.rc b/demopng.rc deleted file mode 100644 index 4b0ae81..0000000 --- a/demopng.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON DISCARDABLE "icon/windows.ico" diff --git a/factory_tool.pro b/factory_tool.pro index 4b23984..b9290e6 100644 --- a/factory_tool.pro +++ b/factory_tool.pro @@ -1,52 +1,29 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2024-03-04T16:59:50 -# -#------------------------------------------------- - -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -TARGET = factory_tool -TEMPLATE = app - - -SOURCES += main.cpp\ - mainwindow.cpp \ - at_data.cpp \ - custom.cpp \ - mythread.cpp \ - result_thread.cpp \ - wrtm_class.cpp - -HEADERS += mainwindow.h \ - Library_global.h \ - at_data.h \ - common.h \ - custom.h \ - info.h \ - interface.h \ - mythread.h \ - result_thread.h \ - header.h - -FORMS += mainwindow.ui - -DISTFILES += \ - CMakeLists.txt \ - readme.txt \ - untitled_zh_CN.ts - -INCLUDEPATH += $$PWD/. -DEPENDPATH += $$PWD/. - - -LIBS += -L$$PWD/lib/ -LIBS += libsecurec.a -LIBS += -ldiag -LIBS += -lAdvapi32 - - -INCLUDEPATH += $$PWD/lib -DEPENDPATH += $$PWD/lib +QT += core gui serialport + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = LeiNiaoFactoryTool +TEMPLATE = app + +# 设置编码为UTF-8 +QMAKE_CXXFLAGS += -finput-charset=UTF-8 -fexec-charset=UTF-8 +CONFIG += utf8_source +CODECFORTR = UTF-8 +CODECFORSRC = UTF-8 + +# 源文件列表 +SOURCES += \ + main.cpp \ + mainwindow.cpp + +# 头文件列表 +HEADERS += \ + mainwindow.h + +# UI 文件列表(关键:必须包含 mainwindow.ui) +FORMS += \ + mainwindow.ui + +# 确保 MOC 正确处理 Qt 元对象系统 +MOC_DIR += moc +UI_DIR += ui # 指定 UI 生成文件的输出目录 diff --git a/header.h b/header.h deleted file mode 100644 index e70123a..0000000 --- a/header.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef HEADER_H -#define HEADER_H -#include - -//#ifdef __cplusplus -//extern "C" { -//#endif -/*-----------------------业务处理-------------------------------*/ -typedef enum { - FAIL = 0x0, - SUCC = 0x1, -} uapi_errcode; - -typedef struct { - uint32_t total_size; // 当前传输文件总大小 - uint32_t transmited_size; // 当前文件已传输大小 -} uapi_transmit_progress; - -typedef struct { - uint16_t sn; // 序号 - uint8_t name_len; // 文件(夹)名长度 - uint8_t is_dir; // 是否是文件夹 - uint32_t file_size; // 文件大小 - uint8_t name[0xFF]; // 文件(夹)名 -} uapi_ls_info_t; - -typedef uint32_t (*uart_rx_function)(void *buf, uint32_t len); // uart RX 回调函数 -typedef uint32_t (*at_result_callback)(void *buf, uint32_t len); // AT 命令返回值回调函数,入参buf包括 mould_id + cmd_id + payload -typedef uint32_t (*transmit_ls_result)(uint32_t size, uapi_ls_info_t *buff); // transmit get list回调函数,入参 size 为文件(夹)的数量,buff 为文件(夹)的信息 -typedef uint32_t (*transmit_result_hook)(bool is_finished, uintptr_t usr_data); // 传输结果回调函数,is_finished 为传输结束标志,usr_data 预留接口,目前为NULL - -uapi_errcode uapi_uart_open(const char *com, uint32_t baud); // 打开uart口, com 格式为 "\\\\.\\COM47", baud 为波特率 -uapi_errcode uapi_uart_tx_data(void *buf, uint32_t buf_len); // uart TX 发送数据buf -uapi_errcode uapi_uart_set_rts_dtr(int rts_flag, int dtr_flag); // uart 设置rts和dtr开关 -uapi_errcode uapi_uart_callback_register(uart_rx_function callback); // uart 注册回调函数 -uapi_errcode uapi_uart_close(void); // 关闭uart口 -uapi_errcode uapi_uart_set_currentMode(int mode); //0 SERIALPORT(单板) 1 BLUETOOTH(整机) - - -uapi_errcode uapi_at_send(uint8_t module_id, uint8_t cmd_id, uint8_t *pkt, uint32_t pkt_size, at_result_callback callback); // at命令发送接口,module_id及cmd_id请参考《Sparta 产线 测试指南》10.2ç«  -uapi_errcode uapi_file_download(char* board_file_path, char* local_file_path, transmit_result_hook handler); // 文件下载接口,参数分别为板端文件地址(详细到文件后缀),pc端存储路径(详细到文件夹),传输结果回调函数 -uapi_errcode uapi_file_upload(char* board_file_path,char* local_file_path, transmit_result_hook handler); // 文件上传接口,参数分别为板端文件地址(详细到文件后缀),pc端存储路径(详细到文件后缀),传输结果回调函数 -uapi_errcode uapi_ls_send(char *path, uint32_t path_len, transmit_ls_result callback); // 查询文件列表接口,参数为板端文件路径(详细到文件夹),路径长度,get list回调函数 -uapi_errcode uapi_file_delete(char *board_file_path, uint32_t board_file_path_len); // 删除指定文件接口,参数为板端文件地址(详细到文件后缀),文件路径长度 -uapi_errcode uapi_file_transmit_stop(void); // 停止文件下载接口 -uapi_errcode uapi_transmit_process(uapi_transmit_progress *data); // 获取文件传输进度,入参 data 更新为正在传输的文件的总大小和已传输大小 - -//#ifdef __cplusplus -//} -//#endif -#endif diff --git a/icon/FAIL.ico b/icon/FAIL.ico deleted file mode 100644 index abdb54e..0000000 Binary files a/icon/FAIL.ico and /dev/null differ diff --git a/icon/succ.ico b/icon/succ.ico deleted file mode 100644 index 61fb14f..0000000 Binary files a/icon/succ.ico and /dev/null differ diff --git a/icon/windows.ico b/icon/windows.ico deleted file mode 100644 index 4bb7bc8..0000000 Binary files a/icon/windows.ico and /dev/null differ diff --git a/icon/windows.png b/icon/windows.png deleted file mode 100644 index f0cc3a0..0000000 Binary files a/icon/windows.png and /dev/null differ diff --git a/info.h b/info.h deleted file mode 100644 index d1152e3..0000000 --- a/info.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. - */ -#ifndef INFO_H -#define INFO_H - -namespace uapi { -class Info { -public: - virtual ~Info() {}; - virtual void onReadEvent(int eventType, void *data) = 0; -}; -} -#endif // INFO_H diff --git a/interface.h b/interface.h deleted file mode 100644 index 404bc43..0000000 --- a/interface.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef INTERFACE_H -#define INTERFACE_H -#include "info.h" -#include "Library_global.h" - -class Application; - -class LIBRARY_EXPORT Interface -{ -public: - Interface(); - ~Interface(); - int SerialPortInit(int byteSize, int parity, int stopBits); - int SerialPortSetRtsDtr(bool rtsFlag, bool DtrFlag); - int SerialPortOpen(const char *portName,int baud); - int SerialPortClose(void); - int SerialPortWrite(const unsigned char *data,unsigned int len); - int FileDownload(const char *boardFilePath, const char *localFilePath); - int FileGetList(const char *boardPath, unsigned int boardPathLen); - int FileUpload(const char *boardFilePath, char *localFilePath); // boardFilePath包含文件名+后缀 - int FileDelete(const char *boardFilePath, unsigned int boardFilePathLen); - int FileTransmitStop(void); - int FileTransmitProgress(uapi::FileTransmitDataCount *data); // 获取文件总大小和已传输大小到data中 - int AtMessageSend(unsigned char moduleId, unsigned char cmdId, const unsigned char *data, unsigned int dataLen); - int InfoEventConnect(uapi::Info *event); // 连接读取事件,返回event type和data - int SetCurrentMode(uapi::ConnectMode mode); // 设置当前连接类型(单板段or整机段) -private: - Application *applicationHandle; -}; - -#endif // INTERFACE_H diff --git a/lib/advapi32.dll b/lib/advapi32.dll deleted file mode 100644 index e3234fc..0000000 Binary files a/lib/advapi32.dll and /dev/null differ diff --git a/lib/diag.dll b/lib/diag.dll deleted file mode 100644 index 94d923f..0000000 Binary files a/lib/diag.dll and /dev/null differ diff --git a/lib/diag.lib b/lib/diag.lib deleted file mode 100644 index ea31049..0000000 Binary files a/lib/diag.lib and /dev/null differ diff --git a/lib/libsecurec.a b/lib/libsecurec.a deleted file mode 100644 index 94ff990..0000000 Binary files a/lib/libsecurec.a and /dev/null differ diff --git a/main.cpp b/main.cpp index 177bfa0..c264415 100644 --- a/main.cpp +++ b/main.cpp @@ -1,10 +1,35 @@ -#include "mainwindow.h" -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindow w; - w.show(); - return a.exec(); -} +#include "mainwindow.h" + +#include +#include +#ifdef _WIN32 +#include +#include +#include +#endif + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + +#ifdef _WIN32 + // Windows特定的控制台编码设置 + SetConsoleOutputCP(CP_UTF8); + SetConsoleCP(CP_UTF8); + // 设置标准输出为UTF-8模式 + _setmode(_fileno(stdout), _O_U8TEXT); + _setmode(_fileno(stderr), _O_U8TEXT); +#endif + + // 设置字符编码为UTF-8,解决中文乱码问题 + QTextCodec *codec = QTextCodec::codecForName("UTF-8"); + QTextCodec::setCodecForLocale(codec); + #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + QTextCodec::setCodecForCStrings(codec); + QTextCodec::setCodecForTr(codec); + #endif + + MainWindow w; + w.show(); + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp index 0ccf2cf..15c091b 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,1085 +1,4687 @@ -#include "mainwindow.h" -#include "./ui_mainwindow.h" -// 初始化线程、状态寄存器、配置信息 -MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) -{ - ui->setupUi(this); - result_thread = new Result_Thread(this); - result_thread->start(); - result_thread->pause(); - at_handler = new At_Process(this); - ui_setting_read(); - at_set_bt_format(); -} - -// 结束线程 -MainWindow::~MainWindow() -{ - if (spp_timer_handle != NULL) { - spp_timer_handle->stop(); - spp_timer_handle = NULL; - } - if (spp_connected_handle != NULL) { - spp_connected_handle->stop(); - spp_connected_handle = NULL; - } - ui_setting_save(); - result_thread->stop(); - result_thread->wait(); - if (transmit_timer_handle != NULL) { - transmit_timer_handle->stop(); - transmit_timer_handle = NULL; - } - if (ui->pbtn_open_uart->isChecked()) { - if (uapi_uart_close() == TRUE) { - } - } - delete result_thread; - delete at_handler; - delete ui; -} - -void MainWindow::ui_display(QString str,bool inOrOut) -{ -// QTime Time= QTime::currentTime();//获取系统当前的时间 -// QString str_time = Time.toString("[hh:mm:ss ");//格式化时间 - ui->txtb_dispaly->moveCursor(QTextCursor::End); - if(inOrOut){ - ui->txtb_dispaly->setTextColor(QColor(127, 255, 0)); - }else{ - ui->txtb_dispaly->setTextColor(Qt::red); - } -// if(inOrOut){ -// str_time.append("IN] : "); -// }else{ -// str_time.append("OUT] : "); -// } -// str.prepend(str_time); -// str+="\r\n"; - ui->txtb_dispaly->insertPlainText(str); - ui->txtb_dispaly->moveCursor(QTextCursor::End); -} - -void MainWindow::ui_tab_mainwindow_complete() -{ - if (ui->stkw_stage->currentIndex() == PAGE_COMPLETE) { - ui->action_complete->setChecked(true); - return; - } - ui->stkw_stage->setCurrentIndex(PAGE_COMPLETE); - ui->ledit_spp_addr->setEnabled(true); - ui->connected_flag->setStyleSheet("QPushButton{background-color: rgb(255, 0, 0);}"); - if (spp_connected_handle != NULL) { - spp_connected_handle->start(1500); - } - if (ui->action_board->isChecked()) { - ui->action_board->setChecked(false); - } - if(ui->pbtn_open_uart->isChecked()){ - uart_close(); - } -} -void MainWindow::ui_tab_mainwindow_board() -{ - if (ui->stkw_stage->currentIndex() == PAGE_BOARD) { - ui->action_board->setChecked(true); - return; - } - ui->stkw_stage->setCurrentIndex(PAGE_BOARD); - ui->ledit_spp_addr->setEnabled(false); - ui->connected_flag->setStyleSheet("QPushButton{background-color: rgb(240, 240, 240);}"); - if (spp_connected_handle != NULL) { - spp_connected_handle->stop(); - } - dongle_is_connected = false; - if (ui->action_complete->isChecked()) { - ui->action_complete->setChecked(false); - } - if(ui->pbtn_open_uart->isChecked()){ - uart_close(); - } - -} -void MainWindow::ui_save_windows() -{ - QString fname = QFileDialog::getExistingDirectory(this, "请选择文件"); - QFile file(fname+"/save.txt"); - if (!file.open(QFile::WriteOnly | QFile::Text)) //检测文件是否打开 - { - QMessageBox::information(this, "Error Message", "Please Select a Text File!"); - return; - } - - QTextStream out(&file); //分行写入文件 - out << ui->txtb_dispaly->toPlainText(); //这里的File_edit就是之前声明的Textedit控件的名字 -} -// 存储config配置文件 -void MainWindow::ui_setting_save() -{ - QSettings *settings = new QSettings("Setting.ini", QSettings::IniFormat); - - // 写入第一组数据 - settings->beginGroup("Uart_setting"); - settings->setValue("uart_com", ui->cbox_uart_com_select->currentText()); - settings->setValue("uart_baud", ui->cbox_uart_baud_select->currentIndex()); - settings->setValue("spp_addr", ui->ledit_spp_addr->text()); - settings->sync(); - settings->endGroup(); - // 写入第二组数据 - settings->beginGroup("Download_Setting"); - settings->setValue("download_board_path", ui->ledit_formboad_bordpath->text()); - settings->setValue("download_local_path", ui->ledit_frombord_savefilepath->text()); - settings->sync(); - settings->endGroup(); - - settings->beginGroup("Upload_Setting"); - settings->setValue("upload_board_path", ui->ledit_toboard_boardpath->text()); - settings->setValue("upload_local_path", ui->ledit_toboard_filepath->text()); - settings->sync(); - settings->endGroup(); - - settings->beginGroup("At_Setting"); - settings->setValue("at_mediamusicplay", ui->ledit_at_mediamusicplay->text()); - settings->setValue("at_mediaaudiorecord", ui->ledit_at_mediaaudiorecord->text()); - settings->setValue("at_fsrm", ui->ledit_at_fsrm->text()); - settings->setValue("at_delay_ms", ui->ledit_delay_ms->text()); - settings->setValue("at_spp_addr", ui->ledit_dongle_mac->text()); - settings->setValue("custom_module_id", ui->ledit_at_custom_moduleId->text()); - settings->setValue("custom_cmd_id", ui->ledit_at_custom_CmdId->text()); - settings->setValue("custom_payload", ui->ledit_at_custom_Payload->text()); - settings->sync(); - settings->endGroup(); - - delete settings; - settings = nullptr; -} -// 读取config配置 -void MainWindow::ui_setting_read() -{ - uart_com_select(); - QSettings *settings = new QSettings("Setting.ini", QSettings::IniFormat); - ui->cbox_uart_com_select->ChangeItem(settings->value("Uart_setting/uart_com").toString()); - ui->cbox_uart_baud_select->setCurrentIndex(settings->value("Uart_setting/uart_baud").toInt()); - ui->ledit_spp_addr->setText(settings->value("Uart_setting/spp_addr").toString()); - ui->tbw_stage_complete->setEnabled(true); - ui->ledit_formboad_bordpath->setText(settings->value("Download_Setting/download_board_path").toString()); - ui->ledit_frombord_savefilepath->setText(settings->value("Download_Setting/download_local_path").toString()); - ui->ledit_toboard_boardpath->setText(settings->value("Upload_Setting/upload_board_path").toString()); - ui->ledit_toboard_filepath->setText(settings->value("Upload_Setting/upload_local_path").toString()); - ui->ledit_at_mediamusicplay->setText(settings->value("At_Setting/at_mediamusicplay").toString()); - ui->ledit_at_mediaaudiorecord->setText(settings->value("At_Setting/at_mediaaudiorecord").toString()); - ui->ledit_at_fsrm->setText(settings->value("At_Setting/at_fsrm").toString()); - ui->ledit_delay_ms->setText(settings->value("At_Setting/at_delay_ms").toString()); - ui->ledit_dongle_mac->setText(settings->value("At_Setting/at_spp_addr").toString()); - ui->ledit_at_custom_moduleId->setText(settings->value("At_Setting/custom_module_id").toString()); - ui->ledit_at_custom_CmdId->setText(settings->value("At_Setting/custom_cmd_id").toString()); - ui->ledit_at_custom_Payload->setText(settings->value("At_Setting/custom_payload").toString()); - ui->tbw_stage_complete->setEnabled(false); - ui->ledit_btlo_channel->setText("0"); - ui->ledit_btpwr_powerchip->setText("2"); -} - - -/* --------------------------------uart操作--------------------------- */ -void MainWindow::uart_process() -{ - if (ui->pbtn_open_uart->isChecked()) { - QString str_com = ui->cbox_uart_com_select->currentText(); - QString str_uart_baud = ui->cbox_uart_baud_select->currentText(); - uart_open(str_com,str_uart_baud); - } else { - uart_close(); - } -} -void MainWindow::uart_open(QString com,QString com_baud) -{ - char buf[15] = {0}; - uint32_t band = com_baud.toUInt(); - com.replace("COM", ""); - int comNumber = com.toInt(); - if (comNumber < COM_NUMBER) { - (void)sprintf_s(buf, "COM%d", comNumber); - } else { - (void)sprintf_s(buf, "\\\\.\\COM%d", comNumber); - } - if (uapi_uart_open(buf, band)) { - uapi_uart_callback_register(uart_callback); - result_thread->resume(); - - if(ui->stkw_stage->currentIndex() == PAGE_COMPLETE){ - ui->tbw_stage_complete->setEnabled(true); - ui->pbtn_spp_connect->setEnabled(true); -// uapi_uart_set_currentMode(1); - }else if(ui->stkw_stage->currentIndex() == PAGE_BOARD){ - ui->tbw_stage_board->setEnabled(true); -// uapi_uart_set_currentMode(0); - } - - ui->pbtn_open_uart->setText("关闭串口"); - ui_display("open uart success.\r\n",false); - if(!ui->pbtn_open_uart->isChecked()){ - ui->pbtn_open_uart->setChecked(true); - } - } else { - ui_display("open uart fail.\r\n",false); - QMessageBox::warning(this, tr("SerialPort"), tr("Open SerialPort failed"), QMessageBox::Ok); - ui->pbtn_open_uart->setChecked(false); - } -} -void MainWindow::uart_close() -{ - if (uapi_uart_close() == TRUE) { - result_thread->pause(); -// ui_display("close uart success.\r\n",false); - ui->tbw_stage_complete->setEnabled(false); - ui->tbw_stage_board->setEnabled(false); - ui->pbtn_spp_connect->setEnabled(false); - ui->pbtn_open_uart->setText("打开串口"); - if(ui->pbtn_open_uart->isChecked()){ - ui->pbtn_open_uart->setChecked(false); - } - if (spp_connected_handle != NULL) { - spp_connected_handle->stop(); - spp_connected_handle = NULL; - } - if (spp_timer_handle != NULL) { - spp_timer_handle->stop(); - spp_timer_handle = NULL; - } - } else { -// ui_display("close uart fail.\r\n",false); - } -} -void MainWindow::uart_send_data() -{ - QString str; - int buf_len = 0; - char* buf = nullptr; - if(ui->stkw_stage->currentIndex() == PAGE_COMPLETE){ - str = ui->tedit_input_data->toPlainText(); - }else{ - str = ui->tedit_input_data_board->toPlainText(); - } - uapi_uart_callback_register(uart_callback); - if (ui->ckbox_hex_send->isChecked()) { - QByteArray array = str.toLatin1(); - QByteArray hex_bytes = QByteArray::fromHex(array.data()); - buf_len = hex_bytes.size(); - buf = hex_bytes.data(); - str=str.toUpper(); - uapi_uart_tx_data(buf, buf_len); - } else { - if ((ui->stkw_stage->currentIndex() == PAGE_COMPLETE &&ui->ckbox_word_wrap->isChecked())|| - (ui->stkw_stage->currentIndex() ==PAGE_BOARD && ui->ckbox_word_wrap_board->isChecked())) { - str+="\r\n"; - } - std::string bufstr = str.toStdString(); - buf =(char*) bufstr.c_str(); - buf_len = strlen(buf); - uapi_uart_tx_data(buf, buf_len); - } - - - - ui_display(str,false); -} - -// uart收到的数据进行回显到显示栏 -void MainWindow::uart_rx_dispaly(int buf_len, u8Piont buf) -{ - uart_rx_flag = true; - if (uart_rx_Ignoring_display) { - QString str((char *)buf); - if(str.contains("ADDR")){ - ui->ledit_dongle_mac->setText(str.mid(str.indexOf("=",0)+1,12)); - } - return; - } - QString str; - QByteArray data((const char*)buf, buf_len); - if (ui->ckbox_Hex_Display->isChecked()) { - for (int i = 0; i < data.size(); i++) { - str += QString("%1 ").arg((quint8)data.at(i), 2, 16, QChar('0')); - } - str=str.toUpper(); - } else { - for (int i = 0; i < data.size(); i++) { - str += QString(data.at(i)); - } - } - ui_display(str,true); - free(buf); -} - -void MainWindow::uart_check_dtr_rts() -{ - bool rts = false, dtr = false; - if (ui->ckbox_rts->isChecked()) { - rts = true; - } - if (ui->ckbox_dtr->isChecked()) { - dtr = true; - } - if (uapi_uart_set_rts_dtr(rts, dtr) == TRUE) { -// ui_display("set rts dtr success.\r\n",false); - } -} - -void MainWindow::uart_com_select() -{ - ui->cbox_uart_com_select->clear(); - QStringList strlist = uart_get_enable_comm_or_port(); - qSort(strlist.begin(), strlist.end(),[](const QString& s1, const QString& s2){ - QString a1=s1;QString a2=s2; - return a1.replace("COM","").toInt() < a2.replace("COM","").toInt(); }); - ui->cbox_uart_com_select->addItems(strlist); -} -void MainWindow::uart_com_switch(QString com) -{ - QString str_uart_baud = ui->cbox_uart_baud_select->currentText(); - if(ui->pbtn_open_uart->isChecked()){ - uart_close(); - uart_open(com,str_uart_baud); - } -} -void MainWindow::uart_baud_switch(QString baud) -{ - QString str_com = ui->cbox_uart_com_select->currentText(); - if(ui->pbtn_open_uart->isChecked()){ - uart_close(); - uart_open(str_com,baud); - } -} -// nIndex为索引号 bValue选择返回值为key还是value,默认为value -QString MainWindow::uart_get_comm_or_port(int nIndex, bool bValue) -{ - QString strCommRet = QObject::tr(""); - HKEY hKey; - if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_READ, &hKey) != 0) { - QMessageBox::warning(this, tr("Register"), tr("can't open register"),QMessageBox::Ok); - return QObject::tr(""); // 无法打开注册表 - } - QString strKeyMsg; // 键名 - QString strValueMsg; // 键值 - TCHAR portName[256]; // 键名数组 - TCHAR commName[256]; // 键值数组 - ulong nKeySize = sizeof(portName); - ulong nValueSize = sizeof(commName); - ulong nType; - memset(commName,0,sizeof(commName)); - memset(portName,0,sizeof(portName)); - if (::RegEnumValue(hKey, nIndex, portName, &nKeySize, 0, &nType, (BYTE *)commName, &nValueSize) == 0) { // 列举键名 - // 读取键名 - for (uint i = 0; i < nKeySize; i++) { - if (portName[i] != 0x00) - strKeyMsg.append(portName[i]); - } - // 读取键值 - for (uint j = 0; j < nValueSize; j++) { - if (commName[j] != 0x00) - strValueMsg.append(commName[j]); - } - if (bValue) - strCommRet = strValueMsg; - else - strCommRet = strKeyMsg; - } else { - ::RegCloseKey(hKey); // 关闭注册表 - return QObject::tr(""); // 无可用串口 - } - return strCommRet; -} - -QStringList MainWindow::uart_get_enable_comm_or_port() -{ - QStringList CommPortList; - QString strCommPath = QObject::tr("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM"); - QSettings *settings = new QSettings(strCommPath, QSettings::NativeFormat); - QStringList keyList = settings->allKeys(); - if (!keyList.isEmpty()) { - for (int i = 0; i < keyList.count(); i++) - CommPortList.append(uart_get_comm_or_port(i, true)); - } - return CommPortList; -} - -/* ------------------------------------------------------------------- */ -void MainWindow::spp_connected_callback() -{ - at_handler->at_send_cmd_string(MODULE_MCU,MCU_CMD_CHECK_CONNECTED,NULL); - dongle_connected_times++; - if (dongle_connected_times > 5) { - ui_display("Dongle has been disconnected.\r\n",false); - dongle_is_connected = false; - } - if (dongle_is_connected == true) { - ui->connected_flag->setStyleSheet("QPushButton{background-color: rgb(0, 255, 64);}"); - uapi_uart_set_currentMode(1);//设置整机模式,通过蓝牙透传指令 - } else { - ui->connected_flag->setStyleSheet("QPushButton{background-color: rgb(255, 0, 0);}"); - } -} - -void MainWindow::spp_timer_callback() -{ - bool final_ret = false; - if (dongle_try_count > 5) { - ui_display("\r\nNo device, check the dongle is connected.\r\n",false); - final_ret = true; - } - if (uart_rx_flag == false) { - at_handler->at_send_cmd_string(MODULE_MCU,MCU_CMD_CHECK_CONNECTED,NULL); - dongle_try_count++; - } else if (spp_try_count % 3 == 0) { // 每3次重新发送一次连接AT命令 - QString str = ui->ledit_spp_addr->text(); - at_handler->at_send_cmd_board(DONGLE_MODE_SPPCONN,str); - } else if (spp_try_count > 10) { // 循环10次还有数据上报则表示连接失败 - ui_display("\r\nconnect fail.\r\n",false); - final_ret = true; - } - if (dongle_is_connected == true) { - final_ret = true; - ui_display("\r\nDongle has been connected.\r\n",false); - if (spp_connected_handle == NULL) { - spp_connected_handle = new QTimer(this); - connect(spp_connected_handle, SIGNAL(timeout()), this, SLOT(spp_connected_callback())); - spp_connected_handle->start(1500); - } - } - if (final_ret == false) { - at_handler->at_send_cmd_board(DONGLE_MODE_AT,NULL); - spp_try_count++; - uart_rx_flag = false; - ui_display(".",false); - } else { - spp_timer_handle->stop(); - spp_timer_handle = NULL; - uart_rx_Ignoring_display = false; - ui->pbtn_spp_connect->setEnabled(true); - } -} - -void MainWindow::spp_connect() -{ - uart_rx_Ignoring_display = true; - dongle_is_connected = false; - dongle_try_count = 0; - spp_try_count = 0; - uapi_uart_callback_register(uart_callback); - at_handler->at_send_cmd_board(DONGLE_MODE_ADDR,NULL); - ui_display("spp connectting...",false); - spp_timer_handle = new QTimer(this); - connect(spp_timer_handle, SIGNAL(timeout()), this, SLOT(spp_timer_callback())); - // spp查询定时器周期为1500ms - spp_timer_handle->start(1500); - ui->pbtn_spp_connect->setEnabled(false); -} - -/* ------------------------------------------------------------------------ */ -/* -------------------------业务处理部分------------------------------------- */ - -void MainWindow::transmit_ls_rx_diaplay(int transmit_ls_size, vPiont transmit_ls_buff) -{ - if(transmit_ls_size>0){ - ui_display("文件名 大小\r\n",true); - } - uapi_ls_info_t *transmit_ls_buff_temp = (uapi_ls_info_t *)transmit_ls_buff; - for (int i = 0; i < transmit_ls_size; i++) { - QString strName = QString::fromUtf8((char *)(transmit_ls_buff_temp[i].name)); - QString strFileLen = QString::number(transmit_ls_buff_temp[i].file_size,10); - if (transmit_ls_buff_temp[i].is_dir) { - strName.append("/"); - } - ui_display(strName+" "+strFileLen+"\r\n",true); - ui->cbox_fromborad_filelist->addItem(strName,strFileLen); - } - free(transmit_ls_buff); -} - -void MainWindow::transmit_rx_display(bool transmit_result_flag) -{ - uint32_t total_size=0; - uint32_t current_size=0; - transmit_get_data_count(&total_size,¤t_size); - uint32_t value = transmit_result_flag ? total_size : 0; - if (transmit_timer_handle) { - transmit_timer_handle->stop(); - transmit_timer_handle = NULL; - } - if (transmit_download_or_upload == TRANSMIT_UPLOAD) { - ui->pbar_toboard->setValue(value); - ui->pbtn_toboard_Upload->setEnabled(true); - } - if (transmit_download_or_upload == TRANSMIT_DOWNLOAD) { - ui->pbar_fromboard->setValue(value); - ui->pbtn_fromboard_download->setEnabled(true); - } - if (transmit_result_flag) { - ui_display("download or upload file success.\r\n",false); - } else { - ui_display("download or upload file fail.\r\n",false); - } - transmit_download_or_upload = TRANSMIT_IDLE; - ui->pbtn_fromboard_delete->setEnabled(true); - ui->pbtn_fromboard_getfilelist->setEnabled(true); -} - -void MainWindow::transmit_fromboard_name_change() -{ - ui->cbox_fromborad_filelist->clear(); -} - -void MainWindow::transmit_fromboard_selectfilepath() -{ - QString fname = QFileDialog::getExistingDirectory(this, "请选择文件"); - ui->ledit_frombord_savefilepath->setText(fname); -} - -void MainWindow::transmit_fromboard_getfilelist() -{ - QString str = ui->ledit_formboad_bordpath->text(); - if (str.isEmpty()) { - QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok); - return; - } - ui->cbox_fromborad_filelist->clear(); - - std::string bufstr = str.toStdString(); - char* buf =(char*) bufstr.c_str(); - - int ret = uapi_ls_send(buf, strlen(buf), ls_callback); - if (ret == FAIL) { - QMessageBox::warning(this, tr("ls"), tr("ls fail!\r\n"), QMessageBox::Ok); - } - tansmit_fromborad_borad_list.push_back(str); - QCompleter *com = new QCompleter(tansmit_fromborad_borad_list, this); - com->setCaseSensitivity(Qt::CaseInsensitive); - delete ui->ledit_formboad_bordpath->completer(); - ui->ledit_formboad_bordpath->setCompleter(com); -} - -void MainWindow::transmit_fromboard_download() -{ - QString str_savepath = ui->ledit_frombord_savefilepath->text(); - QString str_file_path = ui->ledit_formboad_bordpath->text(); - QString str_file_name = ui->cbox_fromborad_filelist->currentText(); - if (str_savepath.isEmpty() || str_file_path.isEmpty() || str_file_name.isEmpty()) { - QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok); - return; - } - if (str_file_name.contains("/")) { - QMessageBox::warning(this, tr("Board File Name"), tr("请选择正确的文件!"), QMessageBox::Ok); - return; - } - qDebug()<cbox_fromborad_filelist->currentData().toInt(); - if(ui->cbox_fromborad_filelist->currentData().toInt()==0){ - QMessageBox::warning(this, tr("Board File Name"), tr("filesize 0"), QMessageBox::Ok); - return; - } - if(!str_file_path.endsWith("/")){ - str_file_path.append("/"); - } - str_file_path.append(str_file_name); - std::string buf_temp = str_file_path.toStdString(); -// QByteArray buf_temp = str_file_path.toUtf8() ; - char *str_file_buff = (char *)buf_temp.c_str(); - std::string buf_temp2 = str_savepath.toStdString(); -// QByteArray buf_temp2 = str_file_path.toUtf8(); - char *str_save_buff = (char *)buf_temp2.c_str(); - int ret = uapi_file_download(str_file_buff, str_save_buff, transmit_callback); - if (ret == FAIL) { - QMessageBox::warning(this, tr("Downloade"), tr("文件下载启动失败!"), QMessageBox::Ok); - return; - } - transmit_progress_start(); - transmit_download_or_upload = TRANSMIT_DOWNLOAD; - transmit_fromborad_local_list.push_back(str_savepath); - QCompleter *com = new QCompleter(transmit_fromborad_local_list, this); - com->setCaseSensitivity(Qt::CaseInsensitive); - delete ui->ledit_frombord_savefilepath->completer(); - ui->ledit_frombord_savefilepath->setCompleter(com); - ui->pbtn_fromboard_download->setEnabled(false); - ui->pbtn_fromboard_delete->setEnabled(false); - ui->pbtn_fromboard_getfilelist->setEnabled(false); -} - -void MainWindow::transmit_fromboard_delete() -{ - QString str_file_path = ui->ledit_formboad_bordpath->text(); - QString str_file_name = ui->cbox_fromborad_filelist->currentText(); - if (str_file_path.isEmpty() || str_file_name.isEmpty()) { - QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok); - return; - } - if (str_file_name.contains("/")) { - str_file_name.chop(1); - } else { - str_file_path.append("/"); - } - str_file_path.append(str_file_name); - - std::string bufstr = str_file_path.toStdString(); - char* str_file_buff =(char*) bufstr.c_str(); - -// char *str_file_buff = (char *)str_file_path.toUtf8().data();//.toStdString().c_str(); - int buflen = strlen(str_file_buff); - int ret = uapi_file_delete(str_file_buff, buflen); // ls - if (ret == FAIL) { - QMessageBox::warning(this, tr("delete"), tr("delete file fail!\r\n"), QMessageBox::Ok); - } - ui->cbox_fromborad_filelist->removeItem(ui->cbox_fromborad_filelist->currentIndex()); -} - -void MainWindow::transmit_fromboard_stop() -{ - if (transmit_timer_handle) { - transmit_timer_handle->stop(); - transmit_timer_handle = NULL; - } - transmit_download_or_upload = TRANSMIT_IDLE; - ui->pbar_fromboard->setValue(0); - ui->pbtn_fromboard_download->setEnabled(true); - ui->pbtn_fromboard_delete->setEnabled(true); - ui->pbtn_fromboard_getfilelist->setEnabled(true); - uapi_file_transmit_stop(); -} - -void MainWindow::transmit_toboard_choosefile() -{ - QString fname = QFileDialog::getOpenFileName(this, "请选择文件"); - ui->ledit_toboard_filepath->setText(fname); -} - -void MainWindow::transmit_toboard_upload() -{ - QString board_file_path = ui->ledit_toboard_boardpath->text(); - QString local_file_path = ui->ledit_toboard_filepath->text(); - if (board_file_path.isEmpty() || local_file_path.isEmpty()) { - QMessageBox::warning(this, tr("File Path"), tr("File Path Empty!"), QMessageBox::Ok); - return; - } - - std::string bufboard_file_path = board_file_path.toStdString(); - char* buf_board_file_path =(char*) bufboard_file_path.c_str(); - - std::string buflocal_file_path = local_file_path.toStdString(); - char* buf_local_file_path =(char*) buflocal_file_path.c_str(); - -// char *buf_board_file_path = (char *)board_file_path.toUtf8().data();//.toStdString().c_str(); -// char *buf_local_file_path = (char *)local_file_path.toUtf8().data();//.toStdString().c_str(); - int ret = uapi_file_upload(buf_board_file_path, buf_local_file_path, transmit_callback); - if (ret == FAIL) { - QMessageBox::warning(this, tr("Upload"), tr("文件上传启动失败!\r\n"), QMessageBox::Ok); - return; - } - transmit_progress_start(); - transmit_download_or_upload = TRANSMIT_UPLOAD; - transmit_toboard_local_list.push_back(local_file_path); - transmit_toboard_borad_list.push_back(board_file_path); - QCompleter *com1 = new QCompleter(transmit_toboard_local_list, this); - com1->setCaseSensitivity(Qt::CaseInsensitive); - delete ui->ledit_toboard_filepath->completer(); - ui->ledit_toboard_filepath->setCompleter(com1); - QCompleter *com2 = new QCompleter(transmit_toboard_borad_list, this); - com2->setCaseSensitivity(Qt::CaseInsensitive); - delete ui->ledit_toboard_boardpath->completer(); - ui->ledit_toboard_boardpath->setCompleter(com2); - ui->pbtn_toboard_Upload->setEnabled(false); -} - -void MainWindow::transmit_toboard_stop() -{ - if (transmit_timer_handle) { - transmit_timer_handle->stop(); - transmit_timer_handle = NULL; - } - transmit_download_or_upload = TRANSMIT_IDLE; - ui->pbar_toboard->setValue(0); - ui->pbtn_toboard_Upload->setEnabled(true); - uapi_file_transmit_stop(); -} - -void MainWindow::transmit_update_progress() -{ - uint32_t total_size=0; - uint32_t current_size=0; - transmit_get_data_count(&total_size,¤t_size); - if (transmit_download_or_upload == TRANSMIT_UPLOAD) { - ui->pbar_toboard->setMaximum(total_size); - ui->pbar_toboard->setValue(current_size); - } - if (transmit_download_or_upload == TRANSMIT_DOWNLOAD) { - ui->pbar_fromboard->setMaximum(total_size); - ui->pbar_fromboard->setValue(current_size); - } -} -void MainWindow::transmit_progress_start() -{ - transmit_timer_handle = new QTimer(this); - connect(transmit_timer_handle, SIGNAL(timeout()), this, SLOT(transmit_update_progress())); - // 进度条更新时间为60ms - transmit_timer_handle->start(60); -} -void MainWindow::at_check_send_status(bool flag) -{ - if(flag){ - ui_display("at cmd send success.\r\n",false); - }else{ - QMessageBox::warning(this, tr("AT"), tr("AT send fail!\r\n"), QMessageBox::Ok); - ui_display("at cmd send fail.\r\n",false); - } -} - -void MainWindow::dongle_suspend() -{ - if(ui->stkw_stage->currentIndex() == PAGE_COMPLETE){ - ui->tbw_stage_complete->setEnabled(false); - ui->pbtn_spp_connect->setEnabled(true); - }else if(ui->stkw_stage->currentIndex() == PAGE_BOARD){ - ui->tbw_stage_board->setEnabled(false); - } -} - -void MainWindow::dongle_resume() -{ - if(ui->stkw_stage->currentIndex() == PAGE_COMPLETE){ - ui->tbw_stage_complete->setEnabled(true); - ui->pbtn_spp_connect->setEnabled(true); - }else if(ui->stkw_stage->currentIndex() == PAGE_BOARD){ - ui->tbw_stage_board->setEnabled(true); - } -} - -void MainWindow::at_rx_display(int at_buf_len, u8Piont at_buf) -{ - Q_UNUSED(at_buf_len); - at_module_id at_module_id_temp; - at_cmd_id at_cmd_id_temp; - at_handler->at_get_id(&at_module_id_temp, &at_cmd_id_temp); - if (at_buf[0] == MODULE_BT && at_buf[1] == BT_CMD_RX_RESULT) { // 耦合测试RxCount - uint32_t rx_count = at_buf[2] + (at_buf[3] << 8); - ui->ledit_display_rx_count->setText(QString::number(rx_count)); - } else if (at_buf[0] == MODULE_MCU && at_buf[1] == MCU_CMD_CHECK_CONNECTED) { // Dongle是否已连接 - dongle_is_connected = true; - dongle_connected_times = 0; - dongle_resume(); - } else if (at_buf[0] == MODULE_MCU && at_buf[1] == MCU_CMD_RETURN_VALUE) { - for (int i = 0; i < 40; i++) { - qDebug("buf[%d] is %d.\r\n", i, at_buf[i]); - } - ui_display("cmd executed " + (QString)(at_buf[2] == 0 ? "Succ!" : "Fail!") + "\r\n",false); - if (at_buf[3] != 0) { - QByteArray data((const char*)&at_buf[4], at_buf[3]); - ui_display(QString(data),false); - } - } else if (at_buf[0] == at_module_id_temp && at_buf[1] == at_cmd_id_temp) { - ui_display("at receive success.\r\n",false); - } else { - ui_display("at receive fail.\r\n",false); - } - free(at_buf); -} - -void MainWindow::at_stackinfo_send() -{ - at_check_send_status(at_handler->at_send_cmd_string(MODULE_MCU,MCU_CMD_STACKINFO,NULL)); -} - -void MainWindow::at_fsrm_send() -{ - QString str = ui->ledit_at_fsrm->text(); - if (str.isEmpty()) { - QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok); - return; - } - at_check_send_status(at_handler->at_send_cmd_string(MODULE_MCU,MCU_CMD_FSRM,str)); -} - -void MainWindow::at_mediamusicplay_send() -{ - uint8_t media_buf_cmd[2] = {0x00, 0x00}; - QString str = ui->ledit_at_mediamusicplay->text(); - if (str.isEmpty()) { - QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok); - return; - } - QString media_sub_str; - QByteArray data((const char*)media_buf_cmd, 2); - for (int i = 0; i < data.size(); i++) { - media_sub_str += QString(data.at(i)); - } - str.prepend(media_sub_str); - at_check_send_status(at_handler->at_send_cmd_string(MODULE_AUDIO,AUDIO_CMD,str)); -} - -void MainWindow::at_mediamusicstop_send() -{ - uint8_t media_buf_cmd[2] = {0x00, 0x03}; - QString media_sub_str; - QByteArray data((const char*)media_buf_cmd, 2); - for (int i = 0; i < data.size(); i++) { - media_sub_str += QString(data.at(i)); - } - at_check_send_status(at_handler->at_send_cmd_string(MODULE_AUDIO,AUDIO_CMD,media_sub_str)); -} - -void MainWindow::at_mediaaudiorecord_send() -{ - uint8_t media_buf_cmd[2] = {0x01, 0x00}; - QString str = ui->ledit_at_mediaaudiorecord->text(); - if (str.isEmpty()) { - QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok); - return; - } - QString media_sub_str; - QByteArray data((const char*)media_buf_cmd, 2); - for (int i = 0; i < data.size(); i++) { - media_sub_str += QString(data.at(i)); - } - str.prepend(media_sub_str); - at_check_send_status(at_handler->at_send_cmd_string(MODULE_AUDIO,AUDIO_CMD,str)); -} - -/* ----------------------- 耦合测试设置 ------------------------------------------------- */ -void MainWindow::at_bt_delay_ms_complete() -{ - QString str = ui->ledit_delay_ms->text(); - at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_DELAY_MS,str)); -} - -void MainWindow::at_set_dongle_addr_complete() -{ - QString str = ui->ledit_dongle_mac->text(); - if (str.isEmpty() || str.size() != 12) { - QMessageBox::warning(this, tr("File Path"), tr("MAC地址为空!"), QMessageBox::Ok); - return; - } - at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_DONGLE_MAC,str)); -} -void MainWindow::at_set_bt_format() -{ - ui->ledit_br_rx_channel_complete->setValidator(new MyValidator(0,78,this)); - ui->ledit_br_tx_channel_complete->setValidator(new MyValidator(0,78,this)); - ui->ledit_ble_rx_channel_complete->setValidator(new MyValidator(0,39,this)); - ui->ledit_ble_tx_channel_complete->setValidator(new MyValidator(0,39,this)); - ui->ledit_br_rx_PayloadLen_complete->setValidator(new MyValidator(0,27,this)); - ui->ledit_br_tx_PayloadLen_complete->setValidator(new MyValidator(0,27,this)); - ui->ledit_ble_tx_PayloadLen_complete->setValidator(new MyValidator(0,255,this)); - - ui->ledit_br_rx_channel_board->setValidator(new MyValidator(0,78,this)); - ui->ledit_br_tx_channel_board->setValidator(new MyValidator(0,78,this)); - ui->ledit_ble_rx_channel_board->setValidator(new MyValidator(0,39,this)); - ui->ledit_ble_tx_channel_board->setValidator(new MyValidator(0,39,this)); - ui->ledit_br_rx_PayloadLen_board->setValidator(new MyValidator(0,27,this)); - ui->ledit_br_tx_PayloadLen_board->setValidator(new MyValidator(0,27,this)); - ui->ledit_ble_tx_PayloadLen_board->setValidator(new MyValidator(0,255,this)); - ui->ledit_btlo_channel->setValidator(new MyValidator(0,78,this)); -} - -void MainWindow::at_check_bt_len(int packtype_index) -{ - QComboBox *cbox = qobject_cast(sender()); - int len=at_handler->at_get_packet_len(packtype_index); - QString name = cbox->objectName(); - if(name == "cbox_br_tx_PacketType_complete"){ - const MyValidator *validator=(MyValidator *)ui->ledit_br_tx_PayloadLen_complete->validator(); - delete validator; - ui->ledit_br_tx_PayloadLen_complete->setPlaceholderText("Length(0-"+QString::number(len)+")"); - ui->ledit_br_tx_PayloadLen_complete->setValidator(new MyValidator(0,len,this)); - }else if(name == "cbox_br_rx_PacketType_complete"){ - const MyValidator *validator=(MyValidator *)ui->ledit_br_rx_PayloadLen_complete->validator(); - delete validator; - ui->ledit_br_rx_PayloadLen_complete->setPlaceholderText("Length(0-"+QString::number(len)+")"); - ui->ledit_br_rx_PayloadLen_complete->setValidator(new MyValidator(0,len,this)); - }else if(name == "cbox_br_tx_PacketType_board"){ - const MyValidator *validator=(MyValidator *)ui->ledit_br_tx_PayloadLen_board->validator(); - delete validator; - ui->ledit_br_tx_PayloadLen_board->setPlaceholderText("Length(0-"+QString::number(len)+")"); - ui->ledit_br_tx_PayloadLen_board->setValidator(new MyValidator(0,len,this)); - }else if(name == "cbox_br_rx_PacketType_board"){ - const MyValidator *validator=(MyValidator *)ui->ledit_br_rx_PayloadLen_board->validator(); - delete validator; - ui->ledit_br_rx_PayloadLen_board->setPlaceholderText("Length(0-"+QString::number(len)+")"); - ui->ledit_br_rx_PayloadLen_board->setValidator(new MyValidator(0,len,this)); - } -} - -/* -----------------------耦合测试-整机段------------------------------------------------ */ -void MainWindow::at_get_rx_count_complete() -{ - at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_GET_RX, NULL)); -} - -void MainWindow::at_bt_tx_complete() -{ - QString br_tx_switch = ui->cbox_br_tx_on_or_off_complete->currentText(); - QString channel = ui->ledit_br_tx_channel_complete->text(); - int packet_type_index = ui->cbox_br_tx_PacketType_complete->currentIndex(); - QString payload_len = ui->ledit_br_tx_PayloadLen_complete->text(); - int pattern_type_index = ui->cbox_br_tx_pattern_type_complete->currentIndex(); - QString format=at_handler->at_get_br_format(BT_MODE_BR_TX,br_tx_switch,channel,packet_type_index,payload_len,pattern_type_index); - if(format==NULL){ - QMessageBox::warning(this, tr("AT"), tr("length错误!"), QMessageBox::Ok); - } - at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_BR_TX,format)); - dongle_is_connected = false; - dongle_suspend(); -} - -void MainWindow::at_bt_rx_complete() -{ - QString br_tx_switch = ui->cbox_br_tx_on_or_off_complete->currentText(); - QString channel = ui->ledit_br_rx_channel_complete->text(); - int packet_type_index = ui->cbox_br_rx_PacketType_complete->currentIndex(); - QString payload_len = ui->ledit_br_rx_PayloadLen_complete->text(); - int pattern_type_index = ui->cbox_br_rx_pattern_type_complete->currentIndex(); - QString format=at_handler->at_get_br_format(BT_MODE_BR_RX,br_tx_switch,channel,packet_type_index,payload_len,pattern_type_index); - if(format==NULL){ - QMessageBox::warning(this, tr("AT"), tr("length错误!"), QMessageBox::Ok); - } - at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_BR_RX,format)); - dongle_is_connected = false; - dongle_suspend(); -} - -void MainWindow::at_ble_tx_complete() -{ - QString br_tx_switch = ui->cbox_ble_tx_on_or_off_complete->currentText(); - QString channel = ui->ledit_ble_tx_channel_complete->text(); - int pattern_type_index = ui->cbox_ble_tx_pattern_type_complete->currentIndex(); - QString payload_len = ui->ledit_ble_tx_PayloadLen_complete->text(); - int phy_type_index = ui->cbox_ble_tx_PacketType_complete->currentIndex(); - QString format=at_handler->at_get_ble_format(BT_MODE_BLE_TX,br_tx_switch,channel,pattern_type_index,payload_len,phy_type_index); - at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_BLE_TX,format)); - dongle_is_connected = false; - dongle_suspend(); -} - -void MainWindow::at_ble_rx_complete() -{ - QString br_tx_switch = ui->cbox_ble_rx_on_or_off_complete->currentText(); - QString channel = ui->ledit_ble_rx_channel_complete->text(); - int phy_type_index = ui->cbox_ble_rx_PacketType_complete->currentIndex(); - QString format=at_handler->at_get_ble_format(BT_MODE_BLE_RX,br_tx_switch,channel,0,0,phy_type_index); - at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_BLE_RX,format)); - dongle_is_connected = false; - dongle_suspend(); -} - -void MainWindow::at_custom_send() -{ - QString moduleId = ui->ledit_at_custom_moduleId->text(); - QString cmdId = ui->ledit_at_custom_CmdId->text(); - QString payload = ui->ledit_at_custom_Payload->text(); - bool ok; - at_check_send_status(at_handler->at_send_cmd_string((at_module_id)moduleId.toUInt(&ok,16),(at_cmd_id)cmdId.toUInt(&ok,16),payload)); -} -/* -----------------------传导测试-单板段------------------------------------------------ */ -void MainWindow::at_bt_tx_board() -{ - QString br_tx_switch = ui->cbox_br_tx_on_or_off_board->currentText(); - if (br_tx_switch.contains("ON") && bt_test_switch == true) { - QMessageBox::warning(this, tr("操作错误"), tr("应先关闭射频测试项!"), QMessageBox::Ok); - } - bt_test_switch = br_tx_switch.contains("ON") ? true : false; - QString channel = ui->ledit_br_tx_channel_board->text(); - int packet_type_index = ui->cbox_br_tx_PacketType_board->currentIndex(); - QString payload_len = ui->ledit_br_tx_PayloadLen_board->text(); - int pattern_type_index = ui->cbox_br_tx_pattern_type_board->currentIndex(); - QString format=at_handler->at_get_br_format(BT_MODE_BR_TX,br_tx_switch,channel,packet_type_index,payload_len,pattern_type_index); - if(format==NULL){ - QMessageBox::warning(this, tr("AT"), tr("length错误!"), QMessageBox::Ok); - } - at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BR_TX,format)); -} -void MainWindow::at_bt_rx_board() -{ - QString br_rx_switch = ui->cbox_br_rx_on_or_off_board->currentText(); - if (br_rx_switch.contains("ON") && bt_test_switch == true) { - QMessageBox::warning(this, tr("操作错误"), tr("应先关闭射频测试项!"), QMessageBox::Ok); - } - bt_test_switch = br_rx_switch.contains("ON") ? true : false; - QString channel = ui->ledit_br_rx_channel_board->text(); - int packet_type_index = ui->cbox_br_rx_PacketType_board->currentIndex(); - QString payload_len = ui->ledit_br_rx_PayloadLen_board->text(); - int pattern_type_index = ui->cbox_br_rx_pattern_type_board->currentIndex(); - QString format=at_handler->at_get_br_format(BT_MODE_BR_RX,br_rx_switch,channel,packet_type_index,payload_len,pattern_type_index); - if(format==NULL){ - QMessageBox::warning(this, tr("AT"), tr("length错误!"), QMessageBox::Ok); - } - at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BR_RX,format)); -} -void MainWindow::at_ble_tx_board() -{ - QString ble_tx_switch = ui->cbox_ble_tx_on_or_off_board->currentText(); - if (ble_tx_switch.contains("ON") && bt_test_switch == true) { - QMessageBox::warning(this, tr("操作错误"), tr("应先关闭射频测试项!"), QMessageBox::Ok); - } - bt_test_switch = ble_tx_switch.contains("ON") ? true : false; - QString channel = ui->ledit_ble_tx_channel_board->text(); - int pattern_type_index = ui->cbox_ble_tx_pattern_type_board->currentIndex(); - QString payload_len = ui->ledit_ble_tx_PayloadLen_board->text(); - int phy_type_index = ui->cbox_ble_tx_PacketType_board->currentIndex(); - QString format=at_handler->at_get_ble_format(BT_MODE_BLE_TX,ble_tx_switch,channel,pattern_type_index,payload_len,phy_type_index); - at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BLE_TX,format)); -} -void MainWindow::at_ble_rx_board() -{ - QString ble_rx_switch = ui->cbox_ble_rx_on_or_off_board->currentText(); - if (ble_rx_switch.contains("ON") && bt_test_switch == true) { - QMessageBox::warning(this, tr("操作错误"), tr("应先关闭射频测试项!"), QMessageBox::Ok); - } - bt_test_switch = ble_rx_switch.contains("ON") ? true : false; - QString channel = ui->ledit_ble_rx_channel_board->text(); - int phy_type_index = ui->cbox_ble_rx_PacketType_board->currentIndex(); - QString format=at_handler->at_get_ble_format(BT_MODE_BLE_RX,ble_rx_switch,channel,0,0,phy_type_index); - at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BLE_RX,format)); -} - -void MainWindow::at_bt_dutmode_board() -{ - QString bt_dutmode_switch = ui->cbox_btdutmode_on_or_off_board->currentText(); - if (bt_dutmode_switch.contains("ON") && bt_test_switch == true) { - QMessageBox::warning(this, tr("操作错误"), tr("应先关闭射频测试项!"), QMessageBox::Ok); - } - bt_test_switch = bt_dutmode_switch.contains("ON") ? true : false; - QString format=at_handler->at_get_switch_format(bt_dutmode_switch); - at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BTDUTMODE,format)); -} -void MainWindow::at_bt_btlo_board() -{ - QString format; - format += ui->ledit_btlo_channel->text()+","; - format += "7,"; - if(ui->cbox_btlo_on_or_off_board->currentText().contains("ON")){ - format+="1"; - }else{ - format+="2"; - } - at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BTLO,format)); -} - -void MainWindow::at_bt_btpwr_board() -{ - QString format; - format += ui->ledit_btpwr_powerchip->text()+","; - if(ui->cbox_btpwr_on_or_off_board->currentText().contains("ON")){ - format+="1"; - }else{ - format+="0"; - } - at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BTPWR,format)); -} - -void MainWindow::at_bt_wakeup() -{ - QString format= "012345678901234567890123456789"; - at_check_send_status(at_handler->at_send_cmd_board(MODE_MAX,format)); -} - -void MainWindow::at_bt_sleep() -{ - QString format= "AT^RMVO"; - at_check_send_status(at_handler->at_send_cmd_board(MODE_MAX,format)); -} -/* ----------------------------------------------------------------------------------- */ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); + setWindowTitle("雷鸟产测工具"); + + // 确保控制台输出使用UTF-8编码 + QTextCodec *utf8Codec = QTextCodec::codecForName("UTF-8"); + QTextCodec::setCodecForLocale(utf8Codec); + #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + QTextCodec::setCodecForCStrings(utf8Codec); + QTextCodec::setCodecForTr(utf8Codec); + #endif + + // 初始化串口对象 + serial = new QSerialPort(this); + connect(serial, &QSerialPort::readyRead, this, &MainWindow::readSerialData); + + // 初始刷新串口列表 + updateSerialPorts(); + + // 初始化按钮样式(可选:设置默认样式) + ui->openButton->setStyleSheet("QPushButton { padding: 5px 10px; }"); + + // 设置产测按钮默认蓝色样式 + ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }"); + + // 初始化产测相关变量 + lcdTestTimer = new QTimer(this); + motorTestTimer = new QTimer(this); + test4GTimer = new QTimer(this); + signal4GTimer = new QTimer(this); + cat1SignalTimer = new QTimer(this); + testTimeoutTimer = new QTimer(this); + currentLcdColor = 0; + initRetry4GCount = 0; + signalTest4GCount = 0; + signalReceived4GCount = 0; + signalGood4GCount = 0; + pppCommandCount = 0; + hasReceivedSignalSim = false; + hasReceivedFirstSignal = false; + cat1SignalTestCount = 0; + cat1SignalReceivedCount = 0; + cat1SignalGoodCount = 0; + cat1Signal99Count = 0; + cat1SignalTotalValue = 0; + hasReceivedPppInfo = false; + isProductionTestRunning = false; + currentTestStep = TEST_IDLE; + lcdTestPopupShown = false; + motorTestPopupShown = false; + isWaitingForUserConfirm = false; + keyTestStarted = false; + keyTestDialog = nullptr; + audioTestPopupShown = false; + audioPlaybackPopupShown = false; + audioRecordTimer = new QTimer(this); + audioTestDialog = nullptr; + audioDialogLabel = nullptr; + audioDialogInfo = nullptr; + audioStartButton = nullptr; + audioPassButton = nullptr; + audioFailButton = nullptr; + audioRetestButton = nullptr; + currentAudioStep = AUDIO_PLAYING_1KHZ; + currentModemVersion = ""; + currentSimStatus = -1; + + // 初始化按键测试状态 + for (int i = 0; i < 4; i++) { + keyTestStatus[i] = 0; + keyButtons[i] = nullptr; + } + + // 连接定时器信号 + connect(lcdTestTimer, &QTimer::timeout, this, &MainWindow::onLcdTestTimer); + connect(motorTestTimer, &QTimer::timeout, this, &MainWindow::onMotorTestTimer); + connect(test4GTimer, &QTimer::timeout, this, &MainWindow::on4GTestTimeout); + connect(signal4GTimer, &QTimer::timeout, this, &MainWindow::on4GSignalTimer); + connect(cat1SignalTimer, &QTimer::timeout, this, &MainWindow::onCat1SignalTimer); + connect(testTimeoutTimer, &QTimer::timeout, this, &MainWindow::onTestTimeout); + connect(audioRecordTimer, &QTimer::timeout, this, &MainWindow::onAudioRecordTimer); +} + +MainWindow::~MainWindow() +{ + delete ui; + if (serial->isOpen()) { + serial->close(); + } + delete serial; +} + +// 刷新串口列表 +void MainWindow::on_refreshButton_clicked() +{ + updateSerialPorts(); +} + +// 更新可用串口 +void MainWindow::updateSerialPorts() +{ + ui->portNameBox->clear(); + // 获取所有可用串口 + const auto infos = QSerialPortInfo::availablePorts(); + for (const QSerialPortInfo &info : infos) { + ui->portNameBox->addItem(info.portName() + " (" + info.description() + ")"); + } +} + +// 打开/关闭串口(带按钮变色效果) +void MainWindow::on_openButton_clicked() +{ + if (serial->isOpen()) { + // 关闭串口 + serial->close(); + ui->openButton->setText("打开串口"); + // 恢复按钮默认样式 + ui->openButton->setStyleSheet("QPushButton { padding: 5px 10px; }"); + return; + } + + // 检查是否选择了串口 + if (ui->portNameBox->currentText().isEmpty()) { + QMessageBox::warning(this, "警告", "请先选择串口"); + return; + } + + // 配置串口参数(固定值) + QString portText = ui->portNameBox->currentText(); + QString portName = portText.left(portText.indexOf(" (")); + serial->setPortName(portName); + + // 固定参数配置 + serial->setBaudRate(500000); // 波特率500000 + serial->setDataBits(QSerialPort::Data8); // 8数据位 + serial->setParity(QSerialPort::NoParity); // 无校验位 + serial->setStopBits(QSerialPort::OneStop); // 1停止位 + serial->setFlowControl(QSerialPort::NoFlowControl); + + // 打开串口 + if (serial->open(QIODevice::ReadWrite)) { + ui->openButton->setText("关闭串口"); + // 设置按钮为绿色(打开状态) + ui->openButton->setStyleSheet( + "QPushButton { " + "background-color: #4CAF50; " // 绿色背景 + "color: white; " // 白色文字 + "padding: 5px 10px; " // 内边距 + "border-radius: 3px; " // 圆角 + "}" + "QPushButton:hover { " + "background-color: #45a049; " // hover时加深颜色 + "}" + ); + } else { + QMessageBox::critical(this, "错误", "无法打开串口:" + serial->errorString()); + } +} + +// 发送数据 +void MainWindow::on_sendButton_clicked() +{ + if (!serial->isOpen()) { + QMessageBox::warning(this, "警告", "请先打开串口"); + return; + } + + // 获取发送区文本 + QString sendStr = ui->sendTextEdit->toPlainText(); + if (sendStr.isEmpty()) return; + + // 在发送内容末尾添加\r\n(回车换行) + sendStr += "\r\n"; + + // 发送数据(默认ASCII模式,包含自动添加的换行) + QByteArray sendData = sendStr.toUtf8(); + serial->write(sendData); +} + + +// 清空接收区 +void MainWindow::on_clearRecvButton_clicked() +{ + ui->recvTextEdit->clear(); +} + +// 清空发送区 +void MainWindow::on_clearSendButton_clicked() +{ + ui->sendTextEdit->clear(); +} + + +void MainWindow::ShowSoftVer(const QString& data) +{ + // 查找"BuildVer:"的起始位置(大小写不敏感) + int verStart = data.indexOf("BuildVer:", 0, Qt::CaseInsensitive); + + if (verStart == -1) { + return; // 未找到BuildVer:,直接返回 + } + + // 计算版本信息的起始位置(跳过"BuildVer:") + const QString key = "BuildVer:"; + verStart += key.length(); + + + // 查找结尾的换行符\n(版本信息结束标志) + int verEnd = data.indexOf('\n', verStart); + + if (verEnd == -1) { + return; // 未找到换行符,数据不完整,返回 + } + + // 提取从BuildVer:之后到换行符之前的内容(即版本信息) + QString verInfo = data.mid(verStart, verEnd - verStart); + + // 去除可能的前后空白字符(如空格、制表符) + verInfo = verInfo.trimmed(); + + // 显示到文本框 + ui->VerlineEdit->setText(verInfo); + + // 校验期望VER + QString expectedVer = ui->expectedVerLineEdit ? ui->expectedVerLineEdit->text().trimmed() : QString(); + if (!expectedVer.isEmpty() && verInfo != expectedVer) { + ui->statusbar->showMessage("版本不一致: 实际VER=" + verInfo + " 期望VER=" + expectedVer, 5000); + QMessageBox::critical(this, "版本校验失败", "VER不一致,测试失败!\n实际: " + verInfo + "\n期望: " + expectedVer); + isProductionTestRunning = false; + currentTestStep = TEST_COMPLETED; + showFinalTestResult(); + return; + } +} + + + + +// 检测g_VibratorFunc函数,判断马达开启是否通过 +void MainWindow::CheckVibratorFunc(const QString& data) +{ + // 查找"g_VibratorFunc"的位置,并且只在马达测试阶段且未显示过弹窗时弹出 + if (data.indexOf("g_VibratorFunc") != -1 && currentTestStep == TEST_MOTOR && + !motorTestPopupShown && isProductionTestRunning) { + + qDebug() << "检测到g_VibratorFunc,马达开启通过"; + qDebug() << "准备显示马达测试确认弹窗"; + + // 标记弹窗已显示,避免重复弹出 + motorTestPopupShown = true; + isWaitingForUserConfirm = true; + + // 停止超时检测,因为已经收到响应 + if (testTimeoutTimer->isActive()) { + testTimeoutTimer->stop(); + qDebug() << "马达测试收到响应,停止超时检测"; + } + + // 暂停马达定时器,等待用户确认 + if (motorTestTimer->isActive()) { + motorTestTimer->stop(); + qDebug() << "暂停马达测试定时器,等待用户确认"; + } + + // 弹出确认对话框让测试人员确认马达是否震动 + QMessageBox msgBox(this); + msgBox.setWindowTitle("马达测试确认"); + msgBox.setText("马达测试已开启,请测试人员检查马达是否震动。"); + msgBox.setInformativeText("请选择马达测试结果:"); + msgBox.setIcon(QMessageBox::Question); + + // 设置弹窗尺寸更大 + msgBox.resize(400, 200); + + // 添加自定义按钮 + QPushButton *successButton = msgBox.addButton("✓ 测试通过", QMessageBox::AcceptRole); + QPushButton *failButton = msgBox.addButton("✗ 测试失败", QMessageBox::RejectRole); + QPushButton *retestButton = msgBox.addButton("🔄 重新测试", QMessageBox::ResetRole); + + // 设置按钮样式 + successButton->setStyleSheet( + "QPushButton { " + "background-color: #4CAF50; " // 绿色背景 + "color: white; " // 白色文字 + "padding: 12px 20px; " // 增大内边距 + "border-radius: 4px; " // 圆角 + "font-weight: bold; " // 粗体 + "font-size: 16px; " // 增大字体 + "}" + "QPushButton:hover { " + "background-color: #45a049; " // hover时加深颜色 + "}" + ); + + failButton->setStyleSheet( + "QPushButton { " + "background-color: #f44336; " // 红色背景 + "color: white; " // 白色文字 + "padding: 12px 20px; " // 增大内边距 + "border-radius: 4px; " // 圆角 + "font-weight: bold; " // 粗体 + "font-size: 16px; " // 增大字体 + "}" + "QPushButton:hover { " + "background-color: #da190b; " // hover时加深颜色 + "}" + ); + + retestButton->setStyleSheet( + "QPushButton { " + "background-color: #FF9800; " // 橙色背景 + "color: white; " // 白色文字 + "padding: 12px 20px; " // 增大内边距 + "border-radius: 4px; " // 圆角 + "font-weight: bold; " // 粗体 + "font-size: 16px; " // 增大字体 + "}" + "QPushButton:hover { " + "background-color: #F57C00; " // hover时加深颜色 + "}" + ); + + // 显示对话框并等待用户选择 + msgBox.exec(); + + // 用户已做出选择,取消等待状态 + isWaitingForUserConfirm = false; + + // 无论用户选择什么,都先停止马达 + serial->write("AT^VIBRATORTIMER=0\r\n"); + qDebug() << "发送马达停止指令: AT^VIBRATORTIMER=0"; + + // 根据用户选择处理结果 + if (msgBox.clickedButton() == successButton) { + // 测试人员确认马达震动正常 + qDebug() << "测试人员确认:马达震动正常"; + + ui->statusbar->showMessage("马达测试通过 - 震动正常!", 3000); + updateTestStatus("motor", STATUS_SUCCESS); + + } else if (msgBox.clickedButton() == failButton) { + // 测试人员确认马达震动异常 + qDebug() << "测试人员确认:马达震动异常"; + + ui->statusbar->showMessage("马达测试失败 - 震动异常!", 3000); + updateTestStatus("motor", STATUS_FAILED); + + } else if (msgBox.clickedButton() == retestButton) { + // 重新测试马达 + qDebug() << "用户选择重新测试马达"; + ui->statusbar->showMessage("停止马达震动,准备重新测试...", 2000); + + // 先发送停止马达震动指令 + serial->write("AT^VIBRATORTIMER=0\r\n"); + qDebug() << "发送停止马达指令: AT^VIBRATORTIMER=0"; + + // 重置马达测试状态 + motorTestPopupShown = false; + isWaitingForUserConfirm = false; + + // 延迟1秒后重新开始马达测试 + QTimer::singleShot(1000, this, [this]() { + if (!isProductionTestRunning) return; // 确保产测还在运行 + + qDebug() << "1秒延迟后开始重新测试马达"; + ui->statusbar->showMessage("重新开始马达测试", 2000); + currentTestStep = TEST_MOTOR; + performMotorTest(); + }); + return; // 直接返回,不继续后续流程 + } + + // 用户确认完成,马达测试结束,开始按键测试 + if (isProductionTestRunning && currentTestStep == TEST_MOTOR) { + qDebug() << "马达测试确认完成,开始按键测试"; + currentTestStep = TEST_KEY; + performKeyTest(); + } + } +} + +// 提取IMEI信息(支持多种格式) +void MainWindow::ShowPppInfoIMEI(const QString& data) +{ + QString imeiInfo; + + qDebug() << "开始提取IMEI,原始数据:" << data.trimmed(); + + // 优先处理直接以数字开头的格式(最常见的新格式) + QRegExp imeiPattern("^(\\d{15})"); + if (imeiPattern.indexIn(data.trimmed()) == 0) { + imeiInfo = imeiPattern.cap(1); + qDebug() << "使用数字开头格式提取IMEI:" << imeiInfo; + } + // 方法2:查找"IMEI:"标识的格式(传统格式) + else { + int start = data.indexOf("IMEI:", 0, Qt::CaseInsensitive); + if (start != -1) { + // 计算IMEI号码的起始位置(跳过"IMEI: ") + const QString key = "IMEI:"; + start += key.length(); + + // 跳过可能的空格 + while (start < data.length() && data.at(start) == ' ') { + start++; + } + + // 查找行结束标志(换行符或字符串结束) + int end = data.indexOf('\n', start); + if (end == -1) { + end = data.indexOf('\r', start); + if (end == -1) { + end = data.length(); + } + } + + // 提取IMEI信息 + imeiInfo = data.mid(start, end - start).trimmed(); + qDebug() << "使用IMEI:格式提取IMEI:" << imeiInfo; + } + // 方法3:查找"imei:"标识的格式 + else { + start = data.indexOf("imei:", 0, Qt::CaseInsensitive); + if (start != -1) { + // 计算IMEI号码的起始位置(跳过"imei:") + const QString key = "imei:"; + start += key.length(); + + // 查找@符号作为结束标志 + int end = data.indexOf('@', start); + if (end == -1) { + // 如果没有@符号,查找行结束标志 + end = data.indexOf('\n', start); + if (end == -1) { + end = data.indexOf('\r', start); + if (end == -1) { + end = data.length(); + } + } + } + + // 提取IMEI信息 + imeiInfo = data.mid(start, end - start).trimmed(); + qDebug() << "使用imei:格式提取IMEI:" << imeiInfo; + } else { + qDebug() << "未找到任何IMEI格式,数据:" << data.trimmed(); + return; + } + } + } + + // 验证IMEI格式是否有效 + if (!imeiInfo.isEmpty() && isValidIMEI(imeiInfo)) { + // 显示到IMEI文本框 + ui->IMEIlineEdit->setText(imeiInfo); + qDebug() << "最终提取的IMEI:" << imeiInfo; + } else { + if (imeiInfo.isEmpty()) { + qDebug() << "IMEI信息为空,数据:" << data.trimmed(); + } else { + qDebug() << "IMEI格式不正确,不显示到界面,IMEI:" << imeiInfo; + ui->statusbar->showMessage("IMEI格式不正确: " + imeiInfo, 3000); + } + } +} + +// 提取ICCID信息(支持多种格式) +void MainWindow::ShowPppInfoICCID(const QString& data) +{ + QString iccidInfo; + + // 方法1:使用正则表达式提取@iccid:后面的数字字母组合 + QRegExp iccidRegex("@?iccid:([0-9A-Fa-f]{19,20})(?:@|\\s|$)", Qt::CaseInsensitive); + if (iccidRegex.indexIn(data) != -1) { + iccidInfo = iccidRegex.cap(1); + qDebug() << "使用正则表达式提取ICCID:" << iccidInfo; + } else { + // 方法2:传统方式查找"ICCID:" + int start = data.indexOf("ICCID:", 0, Qt::CaseInsensitive); + if (start == -1) { + qDebug() << "未找到ICCID:标识"; + return; + } + + // 计算ICCID号码的起始位置(跳过"ICCID:") + start += 6; // "ICCID:"的长度 + + // 跳过可能的空格 + while (start < data.length() && data.at(start) == ' ') { + start++; + } + + // 查找ICCID结束标志(@符号、换行符或字符串结束) + int end = data.indexOf('@', start); + if (end == -1) { + end = data.indexOf('\n', start); + if (end == -1) { + end = data.indexOf('\r', start); + if (end == -1) { + end = data.length(); + } + } + } + + // 提取ICCID信息 + iccidInfo = data.mid(start, end - start).trimmed(); + qDebug() << "使用传统方式提取ICCID:" << iccidInfo; + } + + // 验证ICCID格式是否有效 + if (isValidICCID(iccidInfo)) { + // 显示到ICCID文本框 + ui->ICCIDlineEdit->setText(iccidInfo); + qDebug() << "提取的ICCID:" << iccidInfo; + } else { + qDebug() << "ICCID格式不正确,不显示到界面,ICCID:" << iccidInfo; + ui->statusbar->showMessage("ICCID格式不正确: " + iccidInfo, 3000); + } +} + +// 提取Modem Version信息(支持多种格式) +void MainWindow::ShowPppInfoModemVer(const QString& data) +{ + QString modemVerInfo; + int start; + + // 方法1:查找"Modem Version:"标识的格式(传统格式) + start = data.indexOf("Modem Version:", 0, Qt::CaseInsensitive); + if (start != -1) { + // 计算版本信息的起始位置(跳过"Modem Version: ") + const QString key = "Modem Version:"; + start += key.length(); + + // 跳过可能的空格 + while (start < data.length() && data.at(start) == ' ') { + start++; + } + + // 查找行结束标志(换行符或字符串结束) + int end = data.indexOf('\n', start); + if (end == -1) { + end = data.indexOf('\r', start); + if (end == -1) { + end = data.length(); + } + } + + // 提取Modem版本信息 + modemVerInfo = data.mid(start, end - start).trimmed(); + } + // 方法2:查找"@modemVer:"标识的格式(新格式) + else { + start = data.indexOf("@modemVer:", 0, Qt::CaseInsensitive); + if (start != -1) { + // 计算版本信息的起始位置(跳过"@modemVer:") + const QString key = "@modemVer:"; + start += key.length(); + + // 查找行结束标志(换行符或字符串结束) + int end = data.indexOf('\n', start); + if (end == -1) { + end = data.indexOf('\r', start); + if (end == -1) { + end = data.length(); + } + } + + // 提取Modem版本信息 + modemVerInfo = data.mid(start, end - start).trimmed(); + qDebug() << "使用@modemVer:格式提取Modem Version:" << modemVerInfo; + } + // 方法3:查找"modemver(...)"括号格式 + else { + // 使用正则表达式提取括号内的内容 + QRegExp modemPattern("modemver\\(([^)]+)\\)", Qt::CaseInsensitive); + if (modemPattern.indexIn(data) != -1) { + modemVerInfo = modemPattern.cap(1); + qDebug() << "使用括号格式提取Modem Version:" << modemVerInfo; + } else { + qDebug() << "未找到Modem Version信息,数据格式:" << data.trimmed(); + return; + } + } + } + + // 验证Modem Version是否有效(不为空即可) + if (!modemVerInfo.isEmpty()) { + // 保存到成员变量 + currentModemVersion = modemVerInfo; + // 显示到ModemVer文本框 + ui->ModemVerlineEdit->setText(modemVerInfo); + qDebug() << "提取的Modem Version:" << modemVerInfo; + qDebug() << "MODEM类型判断: " << (isEGModem() ? "EG系列" : "非EG系列"); + + modemVerInfo = modemVerInfo.replace("!", ""); + currentModemVersion = modemVerInfo; + ui->ModemVerlineEdit->setText(modemVerInfo); + + // 校验期望MODEM_VER + QString expectedModem = ui->expectedModemVerLineEdit ? ui->expectedModemVerLineEdit->text().trimmed() : QString(); + qDebug() << "提取的Modem Version:" << modemVerInfo; + qDebug() << "期望的Modem Version:" << expectedModem; + if (!expectedModem.isEmpty() && modemVerInfo.compare(expectedModem, Qt::CaseSensitive) != 0) { + ui->statusbar->showMessage("MODEM版本不一致: 实际=" + modemVerInfo + " 期望=" + expectedModem, 5000); + QMessageBox::critical(this, "版本校验失败", "MODEM_VER不一致,测试失败!\n实际: " + modemVerInfo + "\n期望: " + expectedModem); + isProductionTestRunning = false; + currentTestStep = TEST_COMPLETED; + showFinalTestResult(); + return; + } + } else { + qDebug() << "Modem Version信息为空,数据:" << data.trimmed(); + } +} + +// 提取PYVER Version信息(支持多种格式) +void MainWindow::ShowPppInfoPYVer(const QString& data) +{ + QString PYVerInfo; + int start; + + // 方法1:查找"Modem Version:"标识的格式(传统格式) + start = data.indexOf("PYVER Version:", 0, Qt::CaseInsensitive); + if (start != -1) { + // 计算版本信息的起始位置(跳过"Modem Version: ") + const QString key = "PYVER Version:"; + start += key.length(); + + // 跳过可能的空格 + while (start < data.length() && data.at(start) == ' ') { + start++; + } + + // 查找行结束标志(换行符或字符串结束) + int end = data.indexOf('\n', start); + if (end == -1) { + end = data.indexOf('\r', start); + if (end == -1) { + end = data.length(); + } + } + + // 提取Modem版本信息 + PYVerInfo = data.mid(start, end - start).trimmed(); + } + // 方法2:查找"@modemVer:"标识的格式(新格式) + else { + start = data.indexOf("@pyver:", 0, Qt::CaseInsensitive); + if (start != -1) { + // 计算版本信息的起始位置(跳过"@modemVer:") + const QString key = "@pyver:"; + start += key.length(); + + // 查找行结束标志(换行符或字符串结束) + int end = data.indexOf('\n', start); + if (end == -1) { + end = data.indexOf('\r', start); + if (end == -1) { + end = data.length(); + } + } + + // 提取Modem版本信息 + PYVerInfo = data.mid(start, end - start).trimmed(); + qDebug() << "使用@pyver:格式提取pyver:" << PYVerInfo; + } + // 方法3:查找"modemver(...)"括号格式 + else { + // 使用正则表达式提取括号内的内容 + QRegExp PYPattern("pyver\\(([^)]+)\\)", Qt::CaseInsensitive); + if (PYPattern.indexIn(data) != -1) { + PYVerInfo = PYPattern.cap(1); + qDebug() << "使用括号格式提取pvver :" << PYVerInfo; + } else { + qDebug() << "使用括号格式提取pvver :" << data.trimmed(); + return; + } + } + } + + // 验证Modem Version是否有效(不为空即可) + if (!PYVerInfo.isEmpty()) { + // 保存到成员变量 + currentPYVerVersion = PYVerInfo; + // 显示到ModemVer文本框 + ui->PYVerlineEdit->setText(PYVerInfo); + qDebug() << "提取的PYVER Version:" << PYVerInfo; + qDebug() << "MODEM类型判断: " << (isEGModem() ? "EG系列" : "非EG系列"); + + // 校验期望MODEM_VER + QString expectedPYVER = ui->expectedPYVerLineEdit ? ui->expectedPYVerLineEdit->text().trimmed() : QString(); + if (!expectedPYVER.isEmpty() && PYVerInfo.compare(expectedPYVER, Qt::CaseSensitive) != 0) { + ui->statusbar->showMessage("PYVER版本不一致: 实际=" + PYVerInfo + " 期望=" + expectedPYVER, 5000); + QMessageBox::critical(this, "版本校验失败", "PYVER不一致,测试失败!\n实际: " + PYVerInfo + "\n期望: " + expectedPYVER); + isProductionTestRunning = false; + currentTestStep = TEST_COMPLETED; + showFinalTestResult(); + return; + } + } else { + qDebug() << "PYVER Version信息为空,数据:" << data.trimmed(); + } +} + +// IMEI格式验证函数 - IMEI应为15位数字 +bool MainWindow::isValidIMEI(const QString& imei) +{ + // 检查是否为空 + if (imei.isEmpty()) { + return false; + } + + // 检查长度是否为15位 + if (imei.length() != 15) { + qDebug() << "IMEI长度不正确,应为15位,实际为:" << imei.length() << "位,IMEI:" << imei; + return false; + } + + // 检查是否全为数字 + for (int i = 0; i < imei.length(); i++) { + if (!imei.at(i).isDigit()) { + qDebug() << "IMEI包含非数字字符,IMEI:" << imei; + return false; + } + } + + qDebug() << "IMEI格式验证通过:" << imei; + return true; +} + +// ICCID格式验证函数 - ICCID应为19-20位字母数字组合 +bool MainWindow::isValidICCID(const QString& iccid) +{ + // 检查是否为空 + if (iccid.isEmpty()) { + return false; + } + + // 检查长度是否为19-20位 + if (iccid.length() < 19 || iccid.length() > 20) { + qDebug() << "ICCID长度不正确,应为19-20位,实际为:" << iccid.length() << "位,ICCID:" << iccid; + return false; + } + + // 检查是否为字母数字组合(允许数字和字母) + for (int i = 0; i < iccid.length(); i++) { + QChar ch = iccid.at(i); + if (!ch.isDigit() && !ch.isLetter()) { + qDebug() << "ICCID包含非法字符(只允许数字和字母),ICCID:" << iccid; + return false; + } + } + + qDebug() << "ICCID格式验证通过:" << iccid; + return true; +} + +// MODEM类型判断函数 - 判断是否为EG系列MODEM +bool MainWindow::isEGModem() const +{ + bool result = currentModemVersion.startsWith("EG", Qt::CaseInsensitive); + + if(!ui->PYVerlineEdit->text().isEmpty()) + { + qDebug() << "存在PYVER版本,判断为EG版本" << currentPYVerVersion; + return true; + } + // else { + // qDebug() << "不存在PYVER版本,判断为非EG版本" << PYVerInfo; + // return false; + // } + + qDebug() << "isEGModem() 调用 - MODEM版本:" << currentModemVersion << ",结果:" << (result ? "EG系列" : "非EG系列"); + return result; +} + +// 解析MESSAGE_4G_NETWORK_STAT_CHANGED格式数据 +void MainWindow::parseNetworkStatChanged(const QString& data) +{ + qDebug() << "开始解析MESSAGE_4G_NETWORK_STAT_CHANGED数据:" << data.trimmed(); + + // 使用正则表达式解析各个字段 + // 格式:netstat(0),signal(99),sim(1),network(GSM),imei(860132064650112),iccid(898604B7192590313291),operator(-1) + + // 解析netstat + QRegExp netstatRegex("netstat\\((\\d+)\\)"); + if (netstatRegex.indexIn(data) != -1) { + int netstat = netstatRegex.cap(1).toInt(); + qDebug() << "解析到netstat值:" << netstat; + } + + // 解析signal值 + QRegExp signalRegex("signal\\((\\d+)\\)"); + if (signalRegex.indexIn(data) != -1) { + int signalValue = signalRegex.cap(1).toInt(); + qDebug() << "解析到signal值:" << signalValue; + + // 将signal值显示到界面 + ui->recvTextEdit->append(QString("Network Stat Signal值: %1").arg(signalValue)); + ui->statusbar->showMessage(QString("检测到Network Stat Signal值: %1").arg(signalValue), 2000); + + // 如果正在进行4G测试,处理signal值 + if (isProductionTestRunning && (currentTestStep == TEST_PPP_INIT || currentTestStep == TEST_PPP_SIGNAL)) { + // 构造类似@sim:@signal:格式的数据供现有逻辑处理 + QString simulatedData = QString("@sim:%1@signal:%2@").arg(1).arg(signalValue); // 假设sim为1 + + // 解析sim值(从数据中提取实际值) + QRegExp simRegex("sim\\((\\d+)\\)"); + if (simRegex.indexIn(data) != -1) { + int simValue = simRegex.cap(1).toInt(); + simulatedData = QString("@sim:%1@signal:%2@").arg(simValue).arg(signalValue); + qDebug() << "解析到sim值:" << simValue; + + // 保存SIM卡状态 + currentSimStatus = simValue; + qDebug() << "更新SIM卡状态:" << (currentSimStatus == 1 ? "已插入" : "未插入"); + } + + qDebug() << "构造模拟数据供现有逻辑处理:" << simulatedData; + checkSignalAndSimValues(simulatedData); + } + } + + // 解析sim值 + QRegExp simRegex("sim\\((\\d+)\\)"); + if (simRegex.indexIn(data) != -1) { + int simValue = simRegex.cap(1).toInt(); + qDebug() << "解析到sim值:" << simValue; + + // 保存SIM卡状态 + currentSimStatus = simValue; + qDebug() << "更新SIM卡状态:" << (currentSimStatus == 1 ? "已插入" : "未插入"); + } + + // 解析network类型 + QRegExp networkRegex("network\\(([^)]+)\\)"); + if (networkRegex.indexIn(data) != -1) { + QString networkType = networkRegex.cap(1); + qDebug() << "解析到network类型:" << networkType; + } + + // 解析IMEI + QRegExp imeiRegex("imei\\((\\d{15})\\)"); + if (imeiRegex.indexIn(data) != -1) { + QString imei = imeiRegex.cap(1); + qDebug() << "解析到IMEI:" << imei; + + // 验证IMEI格式 + if (isValidIMEI(imei)) { + ui->IMEIlineEdit->setText(imei); + qDebug() << "IMEI格式验证通过,已更新到界面:" << imei; + } else { + qDebug() << "IMEI格式验证失败:" << imei; + } + } + + // 解析ICCID + QRegExp iccidRegex("iccid\\(([0-9A-Fa-f]{19,20})\\)"); + if (iccidRegex.indexIn(data) != -1) { + QString iccid = iccidRegex.cap(1); + qDebug() << "解析到ICCID:" << iccid; + + // 验证ICCID格式 + if (isValidICCID(iccid)) { + ui->ICCIDlineEdit->setText(iccid); + qDebug() << "ICCID格式验证通过,已更新到界面:" << iccid; + } else { + qDebug() << "ICCID格式验证失败:" << iccid; + } + } + + // 解析operator + QRegExp operatorRegex("operator\\(([^)]+)\\)"); + if (operatorRegex.indexIn(data) != -1) { + QString operatorValue = operatorRegex.cap(1); + qDebug() << "解析到operator值:" << operatorValue; + } +} + +// 串口数据接收处理函数 +void MainWindow::readSerialData() +{ + QByteArray recvData = serial->readAll(); + if (recvData.isEmpty()) { + return; + } + + // 将新接收的数据追加到缓存 + recvBuffer += QString::fromUtf8(recvData); + + // 循环处理缓存中所有完整的行(以\n为结束标志) + while (recvBuffer.contains('\n')) { + int newlineIndex = recvBuffer.indexOf('\n'); + QString line = recvBuffer.left(newlineIndex + 1); + recvBuffer = recvBuffer.mid(newlineIndex + 1); + + QString processLine = line; + + // 处理fac:开头的行 + if (line.startsWith("fac:")) { + processLine = line.mid(4); // 移除"fac:"前缀 + } + + // 显示到接收区(如果是fac:开头的行) + if (line.startsWith("fac:")) { + ui->recvTextEdit->insertPlainText(processLine); + ui->recvTextEdit->moveCursor(QTextCursor::End); + } + + // 处理所有数据提取(不管是否以fac:开头)(大小写不敏感) + if (processLine.indexOf("BuildVer:", 0, Qt::CaseInsensitive) != -1) { + ShowSoftVer(processLine); + } + + // 检测g_VibratorFunc,判断马达开启是否通过 + if (processLine.indexOf("g_VibratorFunc") != -1) { + CheckVibratorFunc(processLine); + } + + // 检测wstp_print格式的BTMAC和CyweeChipInfo数据(不需要fac:开头) + if (line.contains("^^^^ BTMAC=") && line.contains("^^^^ CyweeChipInfo=")) { + // 显示到接收区 + ui->recvTextEdit->insertPlainText(line); + ui->recvTextEdit->moveCursor(QTextCursor::End); + + parseWstpPrintData(line); + } + + // 检测设备信息数据(去掉[PPP_INFO]限制,支持多种格式)(大小写不敏感) + // 检测包含@sim:的数据(可能是IMEI数据和4G信号数据) + if (line.contains("@sim:") || processLine.contains("@sim:")) { + qDebug() << "检测到包含@sim:的数据:"; + qDebug() << " 原始line:" << line.trimmed(); + qDebug() << " processLine:" << processLine.trimmed(); + + // 优先处理processLine + QString dataToProcess = processLine.contains("@sim:") ? processLine : line; + + // 提取IMEI(15位数字) + QRegExp imeiRegex("(\\d{15})"); + if (imeiRegex.indexIn(dataToProcess) != -1) { + QString extractedImei = imeiRegex.cap(1); + qDebug() << "从@sim:数据中提取到IMEI:" << extractedImei; + // 验证IMEI格式 + if (isValidIMEI(extractedImei)) { + ui->IMEIlineEdit->setText(extractedImei); + } else { + qDebug() << "从@sim:数据中提取的IMEI格式不正确:" << extractedImei; + ui->statusbar->showMessage("IMEI格式不正确: " + extractedImei, 3000); + } + } else { + qDebug() << "在@sim:数据中未找到15位数字"; + ShowPppInfoIMEI(dataToProcess); + } + + // 检查是否正在进行4G测试,如果是则解析signal和sim值进行判断 + if (isProductionTestRunning && (currentTestStep == TEST_PPP_INIT || currentTestStep == TEST_PPP_SIGNAL)) { + checkSignalAndSimValues(dataToProcess); + } + } + // 检测传统格式的IMEI数据:IMEI:开头的格式 + else if (line.indexOf("IMEI:", 0, Qt::CaseInsensitive) != -1 || processLine.indexOf("IMEI:", 0, Qt::CaseInsensitive) != -1) { + qDebug() << "接收到IMEI数据:" << line.trimmed(); + qDebug() << "原始数据长度:" << line.length() << "内容:" << line.toUtf8().toHex(); + if (processLine.indexOf("IMEI:", 0, Qt::CaseInsensitive) != -1) { + ShowPppInfoIMEI(processLine); + } else { + ShowPppInfoIMEI(line); + } + } + // 检测新格式的IMEI数据:imei:开头的格式 + else if (line.indexOf("imei:", 0, Qt::CaseInsensitive) != -1 || processLine.indexOf("imei:", 0, Qt::CaseInsensitive) != -1) { + qDebug() << "接收到新格式IMEI数据:" << line.trimmed(); + if (processLine.indexOf("imei:", 0, Qt::CaseInsensitive) != -1) { + ShowPppInfoIMEI(processLine); + } else { + ShowPppInfoIMEI(line); + } + } + + if (line.indexOf("ICCID:", 0, Qt::CaseInsensitive) != -1) { + qDebug() << "接收到ICCID数据:" << line.trimmed(); + ShowPppInfoICCID(line); + } + + if (line.indexOf("Modem Version:", 0, Qt::CaseInsensitive) != -1) { + qDebug() << "接收到Modem Version数据:" << line.trimmed(); + ShowPppInfoModemVer(line); + } + // 检测新格式的Modem Version数据:@modemVer:开头的格式 + else if (line.indexOf("@modemVer:", 0, Qt::CaseInsensitive) != -1) { + qDebug() << "接收到新格式Modem Version数据:" << line.trimmed(); + ShowPppInfoModemVer(line); + } + // 检测括号格式的Modem Version数据:modemver(...)格式 + else if (line.indexOf("modemver(", 0, Qt::CaseInsensitive) != -1) { + qDebug() << "接收到括号格式Modem Version数据:" << line.trimmed(); + ShowPppInfoModemVer(line); + } + + if (line.indexOf("pyver:", 0, Qt::CaseInsensitive) != -1) { + qDebug() << "接收到pyver数据:" << line.trimmed(); + ShowPppInfoPYVer(line); + } + // 检测新格式的Modem Version数据:@modemVer:开头的格式 + else if (line.indexOf("@pyVer:", 0, Qt::CaseInsensitive) != -1) { + qDebug() << "接收到新格式接收到括号格式pyver数据数据:" << line.trimmed(); + ShowPppInfoPYVer(line); + } + // 检测括号格式的Modem Version数据:modemver(...)格式 + else if (line.indexOf("pyver(", 0, Qt::CaseInsensitive) != -1) { + qDebug() << "接收到括号格式pyver数据:" << line.trimmed(); + ShowPppInfoPYVer(line); + } + + // 检测MESSAGE_4G_NETWORK_STAT_CHANGED格式数据 + if (line.contains("MESSAGE_4G_NETWORK_STAT_CHANGED")) { + qDebug() << "接收到MESSAGE_4G_NETWORK_STAT_CHANGED数据:" << line.trimmed(); + parseNetworkStatChanged(line); + } + + // 检测工厂模式进入确认(用于产测) + if (line.contains("fac:enter or exit facotry mode")) { + checkFactoryModeResult(line); + } + + // 检测PPP初始化结果(用于产测) + if (line.contains("PPP environment initialized successfully") || + line.contains("PPP init failed")) { + check4GInitResult(line); + } + + // 检测4G信号质量结果(用于产测) + if (line.contains("Overall LTE Quality") || line.contains("LTE Signal Quality") || + line.contains("RSRQ:") || line.contains("RSRP:") || line.contains("总体评级")) { + check4GSignalResult(line); + } + + // 检测LCD测试结果(用于产测) + if (line.contains("LCD test")) { + checkLcdTestResult(line); + } + + // 检测BuildVer启动完成(用于产测)(大小写不敏感) + if (line.contains("BuildVer", Qt::CaseInsensitive)) { + checkBuildVerResult(line); + } + + // 检测按键测试结果(用于产测) + if (line.contains("fac:id")) { + checkKeyTestResult(line); + } + + // 检测录音测试结果(用于产测) + if (line.contains("MEDIAAUDIORECORD") || line.contains("MEDIAMUSICPLAY") || + line.contains("Start Audio Capturer SUCCESS")) { + qDebug() << "录音测试相关数据匹配:" << line.trimmed(); + checkAudioTestResult(line); + } + + // 检测电池测试结果(用于产测) + if (line.contains("GETPOWER") || line.contains("Battery") || line.contains("fac:voltage")) { + checkBatteryTestResult(line); + } + + // 检测G-sensor测试结果(用于产测) + if (line.contains("gsensor") || line.contains("GSENSOR") || line.contains("fac:gsensor")) { + qDebug() << "检测到gsensor相关数据,调用checkGsensorTestResult:" << line.trimmed(); + checkGsensorTestResult(line); + } + + // 检测CAT1信号测试结果 - 只在CAT1测试期间且包含特定格式时处理 + if (hasReceivedFirstSignal && isProductionTestRunning && line.contains("signal:")) { + // 根据MODEM类型过滤特定格式的数据 + bool shouldProcess = false; + if (isEGModem()) { + // EG系列:只处理rx_buffer格式,跳过cmd格式 + shouldProcess = line.contains("rx_buffer:") && !line.contains("cmd ") && !line.contains("bufferlen"); + } else { + // N7系列:处理PPPSIGNALINFO相关格式 + shouldProcess = line.contains("RSRP:") || line.contains("signal:"); + } + + if (shouldProcess) { + qDebug() << "检测到CAT1信号相关数据:" << line.trimmed(); + checkCat1SignalResult(line); + } else { + qDebug() << "跳过CAT1信号数据(格式不匹配):" << line.left(50) + "..."; + } + } + } + + // 限制缓存最大长度 + if (recvBuffer.length() > 2000) { + recvBuffer.clear(); + } +} + + +// 十六进制转换函数(预留,如需可启用) +QByteArray MainWindow::hexStringToByteArray(const QString &hexString) +{ + QByteArray byteArray; + bool ok; + for (int i = 0; i < hexString.size(); i += 2) { + QString hex = hexString.mid(i, 2); + char c = hex.toUInt(&ok, 16) & 0xFF; + if (ok) byteArray.append(c); + } + return byteArray; +} + +QString MainWindow::byteArrayToHexString(const QByteArray &byteArray) +{ + QString hexString; + for (char c : byteArray) { + hexString += QString("%1 ").arg((unsigned char)c, 2, 16, QChar('0')).toUpper(); + } + return hexString; +} + +// 产测主函数 +void MainWindow::on_ProductionTestButton_clicked() +{ + // 检查串口是否已打开 + if (!serial->isOpen()) { + QMessageBox::warning(this, "警告", "请先打开串口连接"); + return; + } + + if (isProductionTestRunning) { + // 如果正在测试,则停止测试 + lcdTestTimer->stop(); + motorTestTimer->stop(); + isProductionTestRunning = false; + currentTestStep = TEST_IDLE; + ui->statusbar->showMessage("产测已停止", 2000); + + // 恢复产测按钮状态 - 变回蓝色并启用 + ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }"); + ui->openButton_2->setEnabled(true); + qDebug() << "产测停止 - 按钮已恢复蓝色并启用"; + + return; + } + + // 开始产测流程 + isProductionTestRunning = true; + currentTestStep = TEST_LCD; + currentLcdColor = 1; // 从红色开始 + initRetry4GCount = 0; + + ui->statusbar->showMessage("开始产测流程...", 2000); + qDebug() << "开始产测流程"; + + // ui->ProductionTestButton->setText("停止产测"); + + // 开始LCD测试 + performLcdTest(); +} + +// LCD测试函数 +void MainWindow::performLcdTest() +{ + if (!isProductionTestRunning || currentTestStep != TEST_LCD) { + qDebug() << "LCD测试跳过 - 产测运行:" << isProductionTestRunning << "当前步骤:" << currentTestStep; + return; + } + + // 第一次进入LCD测试时更新状态并发送进入LCD测试模式指令 + if (currentLcdColor == 1) { + updateTestStatus("lcd", STATUS_TESTING); + + // 发送进入LCD测试模式指令 + serial->write("AT^LCDTEST=1\r\n"); + qDebug() << "发送进入LCD测试模式指令: AT^LCDTEST=1"; + ui->statusbar->showMessage("进入LCD测试模式,1秒后开始颜色测试...", 1000); + + // 延迟1秒后开始颜色测试,确保设备完全进入LCD测试模式 + QTimer::singleShot(1000, this, [this]() { + if (isProductionTestRunning && currentTestStep == TEST_LCD) { + qDebug() << "LCD测试模式初始化完成,开始颜色测试"; + performLcdColorTest(); + } + }); + return; + } + + // 直接执行颜色测试 + performLcdColorTest(); +} + +// LCD颜色测试函数 +void MainWindow::performLcdColorTest() +{ + if (!isProductionTestRunning || currentTestStep != TEST_LCD) { + qDebug() << "LCD颜色测试跳过 - 产测运行:" << isProductionTestRunning << "当前步骤:" << currentTestStep; + return; + } + + qDebug() << "LCD测试 - 测试步骤:" << currentLcdColor << "定时器状态:" << lcdTestTimer->isActive(); + + // 在第一个颜色(红色)开始时就显示确认弹窗 + if (currentLcdColor == 1 && !lcdTestPopupShown) { + qDebug() << "LCD测试开始,显示确认弹窗"; + // 延迟一点显示弹窗,让红色先显示 + QTimer::singleShot(500, this, [this]() { + if (isProductionTestRunning && currentTestStep == TEST_LCD && !lcdTestPopupShown) { + showLcdTestConfirmDialog(); + } + }); + } + + QString colorName; + int colorCommand; + switch (currentLcdColor) { + case 1: + colorName = "红色"; + colorCommand = 6; // AT^LCDTEST=6 红色 + break; + case 2: + colorName = "绿色"; + colorCommand = 3; // AT^LCDTEST=3 绿色 + break; + case 3: + colorName = "蓝色"; + colorCommand = 4; // AT^LCDTEST=4 蓝色 + break; + default: + colorName = "未知"; + colorCommand = 6; + break; + } + + ui->statusbar->showMessage("LCD测试中 - " + colorName + " (1秒)", 1000); + + // 发送LCD测试指令,使用正确的颜色映射 + QString command = QString("AT^LCDTEST=%1\r\n").arg(colorCommand); + serial->write(command.toUtf8()); + qDebug() << "发送LCD指令:" << command.trimmed() << "(" << colorName << ")"; + + // 设置1秒定时器 + lcdTestTimer->start(1000); +} + +// LCD测试定时器槽函数 +void MainWindow::onLcdTestTimer() +{ + lcdTestTimer->stop(); + qDebug() << "LCD定时器触发,当前颜色:" << currentLcdColor; + + if (!isProductionTestRunning) { + qDebug() << "产测未运行,退出定时器"; + return; + } + + currentLcdColor++; + qDebug() << "切换到下一个颜色:" << currentLcdColor; + + if (currentLcdColor <= 3) { + // 继续下一个颜色测试 + qDebug() << "继续下一个颜色测试"; + performLcdColorTest(); + } else { + // LCD测试完成,发送退出LCD测试指令 + qDebug() << "LCD测试完成,退出LCD测试界面"; + ui->statusbar->showMessage("LCD测试完成,退出测试界面", 1000); + + // 发送退出LCD测试指令 + serial->write("AT^LCDTEST=2\r\n"); + qDebug() << "发送LCD退出指令: AT^LCDTEST=2"; + + // LCD颜色测试完成,检查用户是否已确认 + if (!isWaitingForUserConfirm) { + // 用户已确认,可以继续马达测试 + QTimer::singleShot(1000, this, [this]() { + if (isProductionTestRunning) { + qDebug() << "用户已确认LCD结果,开始马达测试"; + currentTestStep = TEST_MOTOR; + performMotorTest(); + } + }); + } else { + // 用户还未确认,等待用户确认后再继续 + qDebug() << "LCD颜色测试完成,等待用户确认结果"; + ui->statusbar->showMessage("LCD测试完成,等待用户确认结果", 3000); + } + } +} + +// 马达测试函数 +void MainWindow::performMotorTest() +{ + qDebug() << "performMotorTest() 被调用"; + qDebug() << "产测运行状态:" << isProductionTestRunning; + qDebug() << "当前测试步骤:" << currentTestStep << "(TEST_MOTOR=" << TEST_MOTOR << ")"; + + if (!isProductionTestRunning || currentTestStep != TEST_MOTOR) { + qDebug() << "马达测试条件不满足,退出函数"; + qDebug() << "isProductionTestRunning:" << isProductionTestRunning; + qDebug() << "currentTestStep:" << currentTestStep << "期望:" << TEST_MOTOR; + return; + } + + qDebug() << "开始马达测试"; + + // 重置马达测试状态 + motorTestPopupShown = false; + + updateTestStatus("motor", STATUS_TESTING); + ui->statusbar->showMessage("马达测试中 - 开启2秒", 2000); + + // 发送马达开启指令 + serial->write("AT^VIBRATORTIMER=1\r\n"); + qDebug() << "发送马达开启指令: AT^VIBRATORTIMER=1"; + + // 先停止可能正在运行的定时器 + if (motorTestTimer->isActive()) { + motorTestTimer->stop(); + qDebug() << "警告:马达定时器已在运行,先停止"; + } + + // 设置2秒定时器 + qDebug() << "启动马达定时器,2秒后关闭马达"; + motorTestTimer->start(2000); + + // 启动10秒超时检测 + testTimeoutTimer->start(10000); +} + +// 马达测试定时器槽函数 +void MainWindow::onMotorTestTimer() +{ + motorTestTimer->stop(); + + if (!isProductionTestRunning) { + return; + } + + qDebug() << "马达测试时间到,关闭马达"; + ui->statusbar->showMessage("马达测试中 - 关闭", 1000); + + // 发送马达关闭指令 + serial->write("AT^VIBRATORTIMER=0\r\n"); + qDebug() << "发送马达关闭指令: AT^VIBRATORTIMER=0"; + + // 马达测试完成,显示确认弹窗 + qDebug() << "马达测试完成,显示确认弹窗"; + + // 如果弹窗还没有显示过,则显示确认弹窗 + if (!motorTestPopupShown) { + showMotorTestConfirmDialog(); + } else { + // 如果弹窗已经显示过,直接开始按键测试 + qDebug() << "马达确认弹窗已显示过,开始按键测试"; + currentTestStep = TEST_KEY; + performKeyTest(); + } +} + +// 4G测试函数 +void MainWindow::perform4GTest() +{ + if (!isProductionTestRunning) { + qDebug() << "4G测试跳过 - 产测未运行"; + return; + } + + initRetry4GCount++; + qDebug() << "4G测试 - 初始化尝试次数:" << initRetry4GCount; + + // 第一次4G测试时更新状态并进行CAT1电源控制 + if (initRetry4GCount == 1) { + updateTestStatus("ppp", STATUS_TESTING); + + // 先发送AT^CAT1POWER=0关闭CAT1电源 + serial->write("AT^CAT1POWER=0\r\n"); + qDebug() << "发送CAT1电源关闭指令: AT^CAT1POWER=0"; + ui->statusbar->showMessage("4G测试中 - 重置CAT1电源...", 2000); + + // 延迟1秒后发送AT^CAT1POWER=1开启CAT1电源 + QTimer::singleShot(1000, this, [this]() { + if (isProductionTestRunning && serial->isOpen()) { + serial->write("AT^CAT1POWER=1\r\n"); + qDebug() << "发送CAT1电源开启指令: AT^CAT1POWER=1"; + ui->statusbar->showMessage("4G测试中 - 启动CAT1电源...", 2000); + + // 延迟1秒后发送AT^CAT1LOGLEVEL=4指令 + QTimer::singleShot(1000, this, [this]() { + if (isProductionTestRunning && serial->isOpen()) { + serial->write("AT^CAT1LOGLEVEL=4\r\n"); + qDebug() << "发送CAT1日志级别设置指令: AT^CAT1LOGLEVEL=4"; + ui->statusbar->showMessage("4G测试中 - 设置CAT1日志级别...", 2000); + + // 延迟1秒后发送AT^PPPSTOPDIAL指令 + QTimer::singleShot(1000, this, [this]() { + if (isProductionTestRunning && serial->isOpen()) { + serial->write("AT^PPPSTOPDIAL\r\n"); + qDebug() << "发送PPP停止拨号指令: AT^PPPSTOPDIAL"; + ui->statusbar->showMessage("4G测试中 - 停止PPP拨号...", 3000); + + // 延迟5秒后重置标志并开始4G信号检测 + QTimer::singleShot(5000, this, [this]() { + if (isProductionTestRunning) { + // 重置标志 + hasReceivedSignalSim = false; + hasReceivedPppInfo = true; // 标记为已收到,跳过PPP等待 + pppCommandCount = 0; + + // 直接开始4G信号质量检测 + qDebug() << "PPPSTOPDIAL延时完成,直接开始4G信号质量检测"; + currentTestStep = TEST_PPP_SIGNAL; + perform4GSignalTest(); + } + }); + } + }); + } + }); + } + }); + return; // 第一次调用时直接返回,等待定时器执行后续步骤 + } + + // 非第一次调用,直接进行4G环境初始化(重试时) + ui->statusbar->showMessage(QString("4G测试中 - 初始化中...(%1/10)").arg(initRetry4GCount), 5000); + + // 不再发送PPPENVINIT指令,直接启动定时器等待后续处理 + + // 启动5秒超时定时器,如果没收到回复就重试 + test4GTimer->start(5000); + qDebug() << "启动4G测试超时定时器(5秒)"; +} + +// 检查4G初始化结果 +// 检查工厂模式进入结果 +void MainWindow::checkFactoryModeResult(const QString& data) +{ + if (!isProductionTestRunning || currentTestStep != TEST_RESET) { + return; + } + + qDebug() << "工厂模式确认收到数据:" << data.trimmed(); + + // 解析新格式:fac:enter or exit facotry mode :1 或 fac:enter or exit facotry mode :0 + if (data.contains("fac:enter or exit facotry mode")) { + // 使用正则表达式提取cmd值 + QRegExp factoryModePattern("fac:enter or exit facotry mode\\s*:\\s*(\\d+)"); + if (factoryModePattern.indexIn(data) != -1) { + QString cmdStr = factoryModePattern.cap(1); + int cmd = cmdStr.toInt(); + + qDebug() << "解析到工厂模式命令:" << cmd << "(1=进入产测, 0=退出产测)"; + + if (cmd == 1) { + // cmd=1 表示成功进入产测模式 + // 停止超时检测,因为已经收到确认 + if (testTimeoutTimer->isActive()) { + testTimeoutTimer->stop(); + qDebug() << "工厂模式进入确认收到,停止超时检测"; + } + + qDebug() << "工厂模式进入成功确认 (cmd=1)"; + ui->statusbar->showMessage("工厂模式进入成功,准备重启设备...", 2000); + + // 产测开始确认 - 按钮变绿色并禁用 + ui->openButton_2->setStyleSheet("QPushButton { background-color: #28A745; color: white; padding: 5px 10px; border: none; border-radius: 3px; }"); + ui->openButton_2->setEnabled(false); + qDebug() << "产测开始确认 - 按钮已变绿色并禁用"; + + // 延迟2秒后发送重启指令 + QTimer::singleShot(2000, this, [this]() { + if (isProductionTestRunning && currentTestStep == TEST_RESET) { + ui->statusbar->showMessage("产测模式已开启 - 重启设备中...", 3000); + qDebug() << "工厂模式确认后发送设备重启指令"; + serial->write("AT^RESET\r\n"); + qDebug() << "发送设备重启指令: AT^RESET"; + + // 切换到等待BuildVer状态 + currentTestStep = TEST_WAIT_BUILDVER; + qDebug() << "等待设备重启完成,寻找BuildVer标志..."; + } + }); + + } else if (cmd == 0) { + // cmd=0 表示退出产测模式 + qDebug() << "工厂模式退出确认 (cmd=0)"; + ui->statusbar->showMessage("工厂模式已退出", 2000); + + } else { + // 未知的cmd值 + qDebug() << "未知的工厂模式命令值:" << cmd; + ui->statusbar->showMessage("收到未知的工厂模式命令", 2000); + } + } else { + // 无法解析cmd值,使用旧的逻辑作为备用 + qDebug() << "无法解析工厂模式命令值,使用旧逻辑"; + + // 停止超时检测,因为已经收到确认 + if (testTimeoutTimer->isActive()) { + testTimeoutTimer->stop(); + qDebug() << "工厂模式确认收到,停止超时检测"; + } + + qDebug() << "工厂模式进入成功确认 (备用逻辑)"; + ui->statusbar->showMessage("工厂模式进入成功,准备重启设备...", 2000); + + // 延迟2秒后发送重启指令 + QTimer::singleShot(2000, this, [this]() { + if (isProductionTestRunning && currentTestStep == TEST_RESET) { + ui->statusbar->showMessage("产测模式已开启 - 重启设备中...", 3000); + qDebug() << "工厂模式确认后发送设备重启指令"; + serial->write("AT^RESET\r\n"); + qDebug() << "发送设备重启指令: AT^RESET"; + + // 切换到等待BuildVer状态 + currentTestStep = TEST_WAIT_BUILDVER; + qDebug() << "等待设备重启完成,寻找BuildVer标志..."; + } + }); + } + } +} + +void MainWindow::check4GInitResult(const QString& data) +{ + if (!isProductionTestRunning || currentTestStep != TEST_PPP_INIT) { + return; + } + + // 收到回复,停止超时定时器 + if (test4GTimer->isActive()) { + test4GTimer->stop(); + qDebug() << "收到4G回复,停止超时定时器"; + } + + if (data.contains("PPP environment initialized successfully")) { + qDebug() << "4G初始化通过"; + ui->statusbar->showMessage("4G初始化通过,发送运行时更新指令", 2000); + + // 标记已收到PPPINFO相关打印 + hasReceivedPppInfo = true; + + // 4G初始化通过,发送运行时更新指令 + currentTestStep = TEST_PPP_UPDATE; + serial->write("AT^PPPRUNTIMEUPDATE\r\n"); + qDebug() << "发送4G运行时更新指令: AT^PPPRUNTIMEUPDATE"; + + // 延迟2秒后开始4G信号质量检测 + QTimer::singleShot(2000, this, [this]() { + if (isProductionTestRunning) { + qDebug() << "开始4G信号质量检测"; + currentTestStep = TEST_PPP_SIGNAL; + perform4GSignalTest(); + } + }); + // ui->ProductionTestButton->setText("开始产测"); + + } else if (data.contains("PPP init failed")) { + qDebug() << "4G初始化失败,重试中..."; + ui->statusbar->showMessage("4G初始化失败,重试中...", 2000); + + // 如果重试次数过多,可以设置上限 + if (initRetry4GCount >= 10) { + qDebug() << "4G初始化重试次数过多,停止测试"; + ui->statusbar->showMessage("4G初始化失败次数过多,测试停止", 5000); + updateTestStatus("ppp", STATUS_FAILED); + isProductionTestRunning = false; + currentTestStep = TEST_IDLE; + + // 保存测试记录到Excel(失败记录) + QString fileName = saveTestRecord(); + + // 显示最终测试结果弹窗 + showFinalTestResult(); + // ui->ProductionTestButton->setText("开始产测"); + return; + } + + // 先发送停止指令,然后延迟重试 + qDebug() << "4G失败重试前发送停止指令"; + serial->write("AT^VIBRATORTIMER=0\r\n"); // 停止马达 + serial->write("AT^LCDTEST=2\r\n"); // 退出LCD测试 + + QTimer::singleShot(1000, this, [this]() { + qDebug() << "停止指令已发送,开始4G失败重试"; + perform4GTest(); + }); + } +} + +// 4G测试超时处理 +void MainWindow::on4GTestTimeout() +{ + test4GTimer->stop(); + + if (!isProductionTestRunning || currentTestStep != TEST_PPP_INIT) { + qDebug() << "4G超时但测试状态已改变,忽略"; + return; + } + + // 检查当前是在等待PPP回复还是等待signal和sim数据 + if (pppCommandCount <= 3) { + // 前3次,等待PPP数据超时 + if (hasReceivedPppInfo) { + qDebug() << "PPP数据等待超时,但已收到PPPINFO,继续正常流程"; + return; + } + + qDebug() << "PPP数据第" << pppCommandCount << "次等待超时,准备重试"; + + // 重新等待PPP数据 + QTimer::singleShot(1000, this, [this]() { + if (isProductionTestRunning) { + sendPppCommand(); + } + }); + return; + } else { + // 超过3次后,等待signal和sim数据超时 + if (hasReceivedSignalSim) { + qDebug() << "4G测试超时,但已收到signal和sim数据,测试已完成"; + return; // 已经在checkSignalAndSimValues中处理了结果 + } + + qDebug() << "4G测试超时,5秒内未收到signal和sim数据,判断为失败"; + ui->statusbar->showMessage("4G测试失败 - 5秒内未收到signal和sim数据", 3000); + } + + // 直接判断为失败,不再重试 + updateTestStatus("ppp", STATUS_FAILED); + isProductionTestRunning = false; + currentTestStep = TEST_COMPLETED; + + // 保存测试记录 + QString fileName = saveTestRecord(); + + // 显示最终测试结果弹窗 + showFinalTestResult(); + return; + + // 检查重试次数(这部分代码现在不会执行到) + if (initRetry4GCount >= 10) { + qDebug() << "4G初始化重试次数过多,停止测试"; + ui->statusbar->showMessage("4G初始化失败次数过多,测试停止", 5000); + updateTestStatus("ppp", STATUS_FAILED); + isProductionTestRunning = false; + currentTestStep = TEST_IDLE; + + // 保存测试记录到Excel(失败记录) + QString fileName = saveTestRecord(); + + // 显示最终测试结果弹窗 + showFinalTestResult(); + return; + } + + // 先发送停止指令,然后延迟重试 + qDebug() << "PPP重试前发送停止指令"; + serial->write("AT^VIBRATORTIMER=0\r\n"); // 停止马达 + // serial->write("AT^LCDTEST=2\r\n"); // 退出LCD测试 - 已屏蔽 + + QTimer::singleShot(1000, this, [this]() { + if (isProductionTestRunning && currentTestStep == TEST_PPP_INIT) { + qDebug() << "停止指令已发送,开始PPP重试"; + perform4GTest(); + } + }); +} + +// 检查LCD测试结果 +void MainWindow::checkLcdTestResult(const QString& data) +{ + // 检测LCD测试回复信息,并且只在LCD测试阶段且未显示过弹窗时弹出 + // 修改:在最后一个颜色(蓝色)显示时才弹窗,让用户观察完整过程 + if (data.contains("LCD test") && currentTestStep == TEST_LCD && + !lcdTestPopupShown && isProductionTestRunning && currentLcdColor >= 3) { + + qDebug() << "检测到LCD测试回复:" << data.trimmed(); + qDebug() << "准备显示LCD测试确认弹窗"; + + // 标记弹窗已显示,避免重复弹出 + lcdTestPopupShown = true; + isWaitingForUserConfirm = true; + + // 注意:不暂停LCD定时器,让颜色切换继续进行 + // LCD颜色切换应该独立于用户确认过程 + qDebug() << "显示LCD确认弹窗,但颜色切换继续进行"; + + // LCD测试回复已检测到,弹窗处理由performLcdTest中的定时器处理 + + // 不需要在这里处理弹窗,由performLcdTest中的定时器处理 + } +} + +// 显示LCD测试确认弹窗 +void MainWindow::showLcdTestConfirmDialog() +{ + if (lcdTestPopupShown) { + qDebug() << "LCD确认弹窗已显示过,跳过"; + return; + } + + qDebug() << "显示LCD测试确认弹窗"; + + // 标记弹窗已显示,避免重复弹出 + lcdTestPopupShown = true; + isWaitingForUserConfirm = true; + + // 弹出确认对话框让测试人员确认LCD显示是否正常 + QMessageBox msgBox(this); + msgBox.setWindowTitle("LCD测试确认"); + msgBox.setText("LCD测试正在进行,请观察LCD是否正常显示红、绿、蓝色切换"); + msgBox.setInformativeText("观察完成后请选择LCD显示结果:"); + msgBox.setIcon(QMessageBox::Question); + + // 设置弹窗尺寸更大 + msgBox.resize(400, 200); + + // 添加自定义按钮 + QPushButton *successButton = msgBox.addButton("✓ 测试通过", QMessageBox::AcceptRole); + QPushButton *failButton = msgBox.addButton("✗ 测试失败", QMessageBox::RejectRole); + QPushButton *retestButton = msgBox.addButton("🔄 重新测试", QMessageBox::ResetRole); + + // 设置按钮样式 + successButton->setStyleSheet( + "QPushButton { " + "background-color: #4CAF50; " // 绿色背景 + "color: white; " // 白色文字 + "padding: 12px 20px; " // 增大内边距 + "border-radius: 4px; " // 圆角 + "font-weight: bold; " // 粗体 + "font-size: 16px; " // 增大字体 + "}" + "QPushButton:hover { " + "background-color: #45a049; " // hover时加深颜色 + "}" + ); + + failButton->setStyleSheet( + "QPushButton { " + "background-color: #f44336; " // 红色背景 + "color: white; " // 白色文字 + "padding: 12px 20px; " // 增大内边距 + "border-radius: 4px; " // 圆角 + "font-weight: bold; " // 粗体 + "font-size: 16px; " // 增大字体 + "}" + "QPushButton:hover { " + "background-color: #da190b; " // hover时加深颜色 + "}" + ); + + retestButton->setStyleSheet( + "QPushButton { " + "background-color: #FF9800; " // 橙色背景 + "color: white; " // 白色文字 + "padding: 12px 20px; " // 增大内边距 + "border-radius: 4px; " // 圆角 + "font-weight: bold; " // 粗体 + "font-size: 16px; " // 增大字体 + "}" + "QPushButton:hover { " + "background-color: #F57C00; " // hover时加深颜色 + "}" + ); + + // 显示对话框并等待用户选择 + msgBox.exec(); + + // 用户已做出选择,取消等待状态 + isWaitingForUserConfirm = false; + + // 根据用户选择处理结果 + if (msgBox.clickedButton() == successButton) { + // 测试人员确认LCD显示正常 + qDebug() << "测试人员确认:LCD显示正常"; + ui->statusbar->showMessage("LCD显示正常", 2000); + updateTestStatus("lcd", STATUS_SUCCESS); + + // 发送停止LCD测试指令 + serial->write("AT^LCDTEST=2\r\n"); + qDebug() << "LCD测试通过,发送停止LCD测试指令: AT^LCDTEST=2"; + + // 停止LCD定时器,防止继续切换颜色和重复调用马达测试 + if (lcdTestTimer->isActive()) { + lcdTestTimer->stop(); + qDebug() << "停止LCD定时器,防止继续切换颜色和重复调用马达测试"; + } + + // 直接启动马达测试 + if (isProductionTestRunning) { + qDebug() << "LCD测试通过确认,直接启动马达测试"; + qDebug() << "当前产测状态:" << isProductionTestRunning << "当前测试步骤:" << currentTestStep; + currentTestStep = TEST_MOTOR; + qDebug() << "设置测试步骤为TEST_MOTOR,准备调用performMotorTest()"; + + // 延迟一点启动马达测试,确保LCD定时器完全停止 + QTimer::singleShot(100, this, [this]() { + if (isProductionTestRunning && currentTestStep == TEST_MOTOR) { + performMotorTest(); + } + }); + } else { + qDebug() << "产测未运行,无法启动马达测试"; + } + + } else if (msgBox.clickedButton() == failButton) { + // 测试人员确认LCD显示异常 + qDebug() << "测试人员确认:LCD显示异常"; + ui->statusbar->showMessage("LCD显示异常!", 2000); + updateTestStatus("lcd", STATUS_FAILED); + + // 发送停止LCD测试指令 + serial->write("AT^LCDTEST=2\r\n"); + qDebug() << "LCD测试失败,发送停止LCD测试指令: AT^LCDTEST=2"; + + // 停止LCD定时器,防止重复调用马达测试 + if (lcdTestTimer->isActive()) { + lcdTestTimer->stop(); + qDebug() << "停止LCD定时器,防止重复调用马达测试"; + } + + // 即使失败也继续马达测试 + if (isProductionTestRunning) { + qDebug() << "LCD测试失败确认,继续马达测试"; + qDebug() << "当前产测状态:" << isProductionTestRunning << "当前测试步骤:" << currentTestStep; + currentTestStep = TEST_MOTOR; + qDebug() << "设置测试步骤为TEST_MOTOR,准备调用performMotorTest()"; + + // 延迟一点启动马达测试,确保LCD定时器完全停止 + QTimer::singleShot(100, this, [this]() { + if (isProductionTestRunning && currentTestStep == TEST_MOTOR) { + performMotorTest(); + } + }); + } else { + qDebug() << "产测未运行,无法启动马达测试"; + } + + } else if (msgBox.clickedButton() == retestButton) { + // 重新测试LCD + qDebug() << "用户选择重新测试LCD"; + ui->statusbar->showMessage("重新开始LCD测试", 2000); + + // 重置LCD测试状态 + lcdTestPopupShown = false; + isWaitingForUserConfirm = false; + currentLcdColor = 1; // 设置为1,从红色开始重新测试 + + // 重新开始LCD测试 + currentTestStep = TEST_LCD; + performLcdTest(); + return; // 直接返回,不继续后续流程 + } + + // 用户确认完成,马达测试已在上面的按钮处理中启动 + qDebug() << "用户确认完成,马达测试已启动"; +} + +// 显示马达测试确认弹窗 +void MainWindow::showMotorTestConfirmDialog() +{ + if (motorTestPopupShown) { + qDebug() << "马达确认弹窗已显示过,跳过"; + return; + } + + qDebug() << "显示马达测试确认弹窗"; + + // 标记弹窗已显示,避免重复弹出 + motorTestPopupShown = true; + isWaitingForUserConfirm = true; + + // 停止超时检测,因为马达测试已完成 + if (testTimeoutTimer->isActive()) { + testTimeoutTimer->stop(); + qDebug() << "马达测试完成,停止超时检测"; + } + + // 弹出确认对话框让测试人员确认马达是否震动 + QMessageBox msgBox(this); + msgBox.setWindowTitle("马达测试确认"); + msgBox.setText("马达测试已完成,请测试人员确认马达是否正常震动。"); + msgBox.setInformativeText("请选择马达测试结果:"); + msgBox.setIcon(QMessageBox::Question); + + // 设置弹窗尺寸更大 + msgBox.resize(400, 200); + + // 添加自定义按钮 + QPushButton *successButton = msgBox.addButton("✓ 测试通过", QMessageBox::AcceptRole); + QPushButton *failButton = msgBox.addButton("✗ 测试失败", QMessageBox::RejectRole); + QPushButton *retestButton = msgBox.addButton("🔄 重新测试", QMessageBox::ResetRole); + + // 设置按钮样式 + successButton->setStyleSheet( + "QPushButton { " + "background-color: #4CAF50; " // 绿色背景 + "color: white; " // 白色文字 + "padding: 12px 20px; " // 增大内边距 + "border-radius: 4px; " // 圆角 + "font-weight: bold; " // 粗体 + "font-size: 16px; " // 增大字体 + "}" + "QPushButton:hover { " + "background-color: #45a049; " // hover时加深颜色 + "}" + ); + + failButton->setStyleSheet( + "QPushButton { " + "background-color: #f44336; " // 红色背景 + "color: white; " // 白色文字 + "padding: 12px 20px; " // 增大内边距 + "border-radius: 4px; " // 圆角 + "font-weight: bold; " // 粗体 + "font-size: 16px; " // 增大字体 + "}" + "QPushButton:hover { " + "background-color: #da190b; " // hover时加深颜色 + "}" + ); + + retestButton->setStyleSheet( + "QPushButton { " + "background-color: #FF9800; " // 橙色背景 + "color: white; " // 白色文字 + "padding: 12px 20px; " // 增大内边距 + "border-radius: 4px; " // 圆角 + "font-weight: bold; " // 粗体 + "font-size: 16px; " // 增大字体 + "}" + "QPushButton:hover { " + "background-color: #F57C00; " // hover时加深颜色 + "}" + ); + + // 显示对话框并等待用户选择 + msgBox.exec(); + + // 用户已做出选择,取消等待状态 + isWaitingForUserConfirm = false; + + // 根据用户选择处理结果 + if (msgBox.clickedButton() == successButton) { + // 测试人员确认马达震动正常 + qDebug() << "测试人员确认:马达震动正常"; + ui->statusbar->showMessage("马达测试通过 - 震动正常!", 3000); + updateTestStatus("motor", STATUS_SUCCESS); + + } else if (msgBox.clickedButton() == failButton) { + // 测试人员确认马达震动异常 + qDebug() << "测试人员确认:马达震动异常"; + ui->statusbar->showMessage("马达测试失败 - 震动异常!", 3000); + updateTestStatus("motor", STATUS_FAILED); + + } else if (msgBox.clickedButton() == retestButton) { + // 重新测试马达 + qDebug() << "用户选择重新测试马达"; + ui->statusbar->showMessage("停止马达震动,准备重新测试...", 2000); + + // 先发送停止马达震动指令 + serial->write("AT^VIBRATORTIMER=0\r\n"); + qDebug() << "发送停止马达指令: AT^VIBRATORTIMER=0"; + + // 重置马达测试状态 + motorTestPopupShown = false; + isWaitingForUserConfirm = false; + + // 延迟1秒后重新开始马达测试 + QTimer::singleShot(1000, this, [this]() { + if (!isProductionTestRunning) return; // 确保产测还在运行 + + qDebug() << "1秒延迟后开始重新测试马达"; + ui->statusbar->showMessage("重新开始马达测试", 2000); + currentTestStep = TEST_MOTOR; + performMotorTest(); + }); + return; // 直接返回,不继续后续流程 + } + + // 用户确认完成,马达测试结束,开始按键测试 + if (isProductionTestRunning && currentTestStep == TEST_MOTOR) { + qDebug() << "马达测试确认完成,开始按键测试"; + currentTestStep = TEST_KEY; + performKeyTest(); + } +} + +// 执行按键测试 +void MainWindow::performKeyTest() +{ + if (!isProductionTestRunning || currentTestStep != TEST_KEY) { + return; + } + + qDebug() << "开始按键测试"; + updateTestStatus("key", STATUS_TESTING); + ui->statusbar->showMessage("按键测试中,请按下设备上的按键", 10000); + + // 重置按键测试状态 + keyTestStarted = true; + for (int i = 0; i < 4; i++) { + keyTestStatus[i] = 0; + } + + // 创建按键测试弹窗 + keyTestDialog = new QDialog(this); + keyTestDialog->setWindowTitle("按键测试"); + keyTestDialog->setFixedSize(450, 280); // 调大尺寸 + keyTestDialog->setModal(true); + + // 设置布局 + QVBoxLayout *layout = new QVBoxLayout(keyTestDialog); + QLabel *instructionLabel = new QLabel("请按下设备上的按键,按钮会变色表示检测到"); + layout->addWidget(instructionLabel); + + // 创建按键按钮网格 + QGridLayout *gridLayout = new QGridLayout(); + + // 创建4个按键按钮 + for (int i = 0; i < 4; i++) { + keyButtons[i] = new QPushButton(QString("按键 %1").arg(i)); + keyButtons[i]->setFixedSize(60, 40); + keyButtons[i]->setStyleSheet( + "QPushButton { " + "background-color: #f0f0f0; " + "border: 2px solid #888888; " + "border-radius: 5px; " + "font-weight: bold; " + "}" + ); + + // 将按钮添加到网格布局(2x2) + gridLayout->addWidget(keyButtons[i], i / 2, i % 2); + } + + layout->addLayout(gridLayout); + + // 添加测试结果按钮 + QHBoxLayout *buttonLayout = new QHBoxLayout(); + + QPushButton *passButton = new QPushButton("✓ 测试通过"); + passButton->setStyleSheet( + "QPushButton { " + "background-color: #4CAF50; " + "color: white; " + "padding: 12px 20px; " + "border-radius: 4px; " + "font-weight: bold; " + "font-size: 16px; " + "}" + ); + + QPushButton *failButton = new QPushButton("✗ 测试失败"); + failButton->setStyleSheet( + "QPushButton { " + "background-color: #f44336; " + "color: white; " + "padding: 12px 20px; " + "border-radius: 4px; " + "font-weight: bold; " + "font-size: 16px; " + "}" + ); + + QPushButton *retestButton = new QPushButton("🔄 重新测试"); + retestButton->setStyleSheet( + "QPushButton { " + "background-color: #FF9800; " + "color: white; " + "padding: 12px 20px; " + "border-radius: 4px; " + "font-weight: bold; " + "font-size: 16px; " + "}" + ); + + buttonLayout->addWidget(passButton); + buttonLayout->addWidget(failButton); + buttonLayout->addWidget(retestButton); + + // 连接按钮事件 + connect(passButton, &QPushButton::clicked, [this]() { + if (keyTestDialog && isProductionTestRunning && currentTestStep == TEST_KEY) { + keyTestDialog->accept(); + qDebug() << "用户选择:按键测试通过"; + ui->statusbar->showMessage("按键测试通过", 2000); + updateTestStatus("key", STATUS_SUCCESS); + + // 继续录音测试 + qDebug() << "=== 按键测试完成,开始录音测试 ==="; + keyTestStarted = false; + currentTestStep = TEST_AUDIO; + qDebug() << "设置currentTestStep为TEST_AUDIO:" << TEST_AUDIO; + performAudioTest(); + } + }); + + connect(failButton, &QPushButton::clicked, [this]() { + if (keyTestDialog && isProductionTestRunning && currentTestStep == TEST_KEY) { + keyTestDialog->accept(); + qDebug() << "用户选择:按键测试失败"; + ui->statusbar->showMessage("按键测试失败", 2000); + updateTestStatus("key", STATUS_FAILED); + + // 继续录音测试 + keyTestStarted = false; + currentTestStep = TEST_AUDIO; + performAudioTest(); + } + }); + + connect(retestButton, &QPushButton::clicked, [this]() { + if (keyTestDialog) { + keyTestDialog->accept(); + qDebug() << "用户选择:重新测试按键"; + ui->statusbar->showMessage("重新开始按键测试", 2000); + + // 重置按键测试状态 + keyTestStarted = false; + + // 重新开始按键测试 + currentTestStep = TEST_KEY; + performKeyTest(); + } + }); + + layout->addLayout(buttonLayout); + + // 显示弹窗 + keyTestDialog->show(); +} + +// 检查按键测试结果 +void MainWindow::checkKeyTestResult(const QString& data) +{ + if (!keyTestStarted || !keyTestDialog) { + return; + } + + // 检测按键ID打印格式: "fac:id : X" + QRegExp keyPattern("fac:id\\s*:\\s*(\\d+)"); + if (keyPattern.indexIn(data) != -1) { + int keyId = keyPattern.cap(1).toInt(); + + if (keyId >= 0 && keyId <= 3) { + qDebug() << "检测到按键按下: ID =" << keyId; + + // 标记该按键已测试 + keyTestStatus[keyId] = 1; + + // 更新按钮颜色 + if (keyButtons[keyId]) { + keyButtons[keyId]->setStyleSheet( + "QPushButton { " + "background-color: #4CAF50; " // 绿色表示已测试 + "color: white; " + "border: 2px solid #45a049; " + "border-radius: 5px; " + "font-weight: bold; " + "}" + ); + keyButtons[keyId]->setText(QString("按键 %1 ✓").arg(keyId)); + } + + ui->statusbar->showMessage(QString("检测到按键 %1").arg(keyId), 1000); + + // 检查是否所有按键都已测试 + bool allKeysTested = true; + for (int i = 0; i < 4; i++) { + if (keyTestStatus[i] == 0) { + allKeysTested = false; + break; + } + } + + if (allKeysTested) { + qDebug() << "所有按键都已检测到,自动通过按键测试"; + ui->statusbar->showMessage("所有按键检测完成,自动通过测试", 2000); + + // 延迟1秒后自动关闭弹窗并标记为通过 + QTimer::singleShot(1000, [this]() { + if (keyTestDialog && isProductionTestRunning && currentTestStep == TEST_KEY) { + keyTestDialog->accept(); + qDebug() << "按键测试自动通过"; + updateTestStatus("key", STATUS_SUCCESS); + + // 继续录音测试 + qDebug() << "=== 按键测试自动完成,开始录音测试 ==="; + keyTestStarted = false; + currentTestStep = TEST_AUDIO; + qDebug() << "设置currentTestStep为TEST_AUDIO(自动):" << TEST_AUDIO; + performAudioTest(); + } + }); + } else { + qDebug() << "按键 " << keyId << " 检测完成,等待其他按键或用户选择"; + } + } + } +} + +// 显示按键测试确认对话框 +void MainWindow::showKeyTestConfirmDialog(bool allKeysTested) +{ + qDebug() << "显示按键测试确认弹窗,所有按键已测试:" << allKeysTested; + + // 弹出确认对话框让测试人员确认按键测试结果 + QMessageBox msgBox(this); + msgBox.setWindowTitle("按键测试确认"); + + if (allKeysTested) { + msgBox.setText("所有按键测试完成,请确认按键功能是否正常"); + msgBox.setInformativeText("所有4个按键都已检测到按下,请选择按键测试结果:"); + } else { + msgBox.setText("按键测试未完全完成"); + msgBox.setInformativeText("部分按键未检测到按下,请选择按键测试结果:"); + } + + msgBox.setIcon(QMessageBox::Question); + + // 添加自定义按钮 + QPushButton *successButton = msgBox.addButton("✓ 测试通过", QMessageBox::AcceptRole); + QPushButton *failButton = msgBox.addButton("✗ 测试失败", QMessageBox::RejectRole); + + // 设置按钮样式 + successButton->setStyleSheet( + "QPushButton { " + "background-color: #4CAF50; " // 绿色背景 + "color: white; " // 白色文字 + "padding: 12px 20px; " // 增大内边距 + "border-radius: 4px; " // 圆角 + "font-weight: bold; " // 粗体 + "font-size: 16px; " // 增大字体 + "}" + "QPushButton:hover { " + "background-color: #45a049; " // hover时加深颜色 + "}" + ); + + failButton->setStyleSheet( + "QPushButton { " + "background-color: #f44336; " // 红色背景 + "color: white; " // 白色文字 + "padding: 12px 20px; " // 增大内边距 + "border-radius: 4px; " // 圆角 + "font-weight: bold; " // 粗体 + "font-size: 16px; " // 增大字体 + "}" + "QPushButton:hover { " + "background-color: #da190b; " // hover时加深颜色 + "}" + ); + + // 显示对话框并等待用户选择 + msgBox.exec(); + + // 根据用户选择处理结果 + if (msgBox.clickedButton() == successButton) { + // 测试人员确认按键正常 + qDebug() << "测试人员确认:按键测试通过"; + ui->statusbar->showMessage("按键测试通过", 2000); + updateTestStatus("key", STATUS_SUCCESS); + + } else if (msgBox.clickedButton() == failButton) { + // 测试人员确认按键异常 + qDebug() << "测试人员确认:按键测试失败"; + ui->statusbar->showMessage("按键测试失败", 2000); + updateTestStatus("key", STATUS_FAILED); + } + + // 按键测试完成,开始录音测试 + if (isProductionTestRunning) { + keyTestStarted = false; + currentTestStep = TEST_AUDIO; + performAudioTest(); + } +} + +// 检查BuildVer启动完成 +void MainWindow::checkBuildVerResult(const QString& data) +{ + // 检测设备启动完成标志,只在等待BuildVer阶段检测(大小写不敏感) + if (data.contains("BuildVer", Qt::CaseInsensitive) && currentTestStep == TEST_WAIT_BUILDVER && + isProductionTestRunning) { + + qDebug() << "检测到BuildVer启动完成标志:" << data.trimmed(); + qDebug() << "设备重启完成,发送AT^PMADDVOTE指令"; + + ui->statusbar->showMessage("设备重启完成,发送初始化指令...", 2000); + + // 发送第一次AT^PMADDVOTE指令 + serial->write("AT^PMADDVOTE\r\n"); + qDebug() << "发送AT^PMADDVOTE指令(第1次): AT^PMADDVOTE"; + + // 延迟0.5秒后发送第二次AT^PMADDVOTE指令 + QTimer::singleShot(500, this, [this]() { + if (isProductionTestRunning && serial->isOpen()) { + serial->write("AT^PMADDVOTE\r\n"); + qDebug() << "发送AT^PMADDVOTE指令(第2次): AT^PMADDVOTE"; + + // 再延迟1秒后切换到LCD测试阶段 + QTimer::singleShot(1000, this, [this]() { + if (isProductionTestRunning) { + qDebug() << "AT^PMADDVOTE指令发送完成,开始LCD测试"; + ui->statusbar->showMessage("初始化完成,开始LCD测试", 2000); + + // 切换到LCD测试阶段 + currentTestStep = TEST_LCD; + + // 延迟1秒后开始LCD测试 + QTimer::singleShot(1000, this, [this]() { + if (isProductionTestRunning && currentTestStep == TEST_LCD) { + qDebug() << "开始LCD测试流程"; + performLcdTest(); + } + }); + } + }); + } + }); + } +} + +// 更新测试状态指示器 +void MainWindow::updateTestStatus(const QString& testName, TestStatus status) +{ + QString iconText, statusText, iconColor, textColor; + + switch (status) { + case STATUS_UNTESTED: + iconText = "○"; + statusText = "未测试"; + iconColor = "#888888"; + textColor = "#888888"; + break; + case STATUS_TESTING: + iconText = "●"; + statusText = "测试中"; + iconColor = "#FFA500"; // 橙色 + textColor = "#FFA500"; + break; + case STATUS_SUCCESS: + iconText = "✓"; + statusText = "通过"; + iconColor = "#4CAF50"; // 绿色 + textColor = "#4CAF50"; + break; + case STATUS_FAILED: + iconText = "✗"; + statusText = "失败"; + iconColor = "#F44336"; // 红色 + textColor = "#F44336"; + break; + } + + QString iconStyle = QString("color: %1; font-size: 18px; font-weight: bold;").arg(iconColor); + QString textStyle = QString("color: %1;").arg(textColor); + + if (testName == "lcd") { + ui->lcdStatusIcon->setText(iconText); + ui->lcdStatusIcon->setStyleSheet(iconStyle); + ui->lcdStatusText->setText(statusText); + ui->lcdStatusText->setStyleSheet(textStyle); + } else if (testName == "motor") { + ui->motorStatusIcon->setText(iconText); + ui->motorStatusIcon->setStyleSheet(iconStyle); + ui->motorStatusText->setText(statusText); + ui->motorStatusText->setStyleSheet(textStyle); + } else if (testName == "key") { + ui->keyStatusIcon->setText(iconText); + ui->keyStatusIcon->setStyleSheet(iconStyle); + ui->keyStatusText->setText(statusText); + ui->keyStatusText->setStyleSheet(textStyle); + } else if (testName == "audio") { + ui->audioStatusIcon->setText(iconText); + ui->audioStatusIcon->setStyleSheet(iconStyle); + ui->audioStatusText->setText(statusText); + ui->audioStatusText->setStyleSheet(textStyle); + } else if (testName == "battery") { + ui->batteryStatusIcon->setText(iconText); + ui->batteryStatusIcon->setStyleSheet(iconStyle); + ui->batteryStatusText->setText(statusText); + ui->batteryStatusText->setStyleSheet(textStyle); + } else if (testName == "gsensor") { + ui->gsensorStatusIcon->setText(iconText); + ui->gsensorStatusIcon->setStyleSheet(iconStyle); + ui->gsensorStatusText->setText(statusText); + ui->gsensorStatusText->setStyleSheet(textStyle); + } else if (testName == "ppp") { + ui->pppStatusIcon->setText(iconText); + ui->pppStatusIcon->setStyleSheet(iconStyle); + ui->pppStatusText->setText(statusText); + ui->pppStatusText->setStyleSheet(textStyle); + } + + // 更新整体状态 + updateOverallStatus(); +} + +// 更新整体状态 +void MainWindow::updateOverallStatus() +{ + // 检查各项测试状态(只检查成功状态,简化逻辑) + bool lcdSuccess = ui->lcdStatusText->text() == "通过"; + bool motorSuccess = ui->motorStatusText->text() == "通过"; + bool keySuccess = ui->keyStatusText->text() == "通过"; + bool audioSuccess = ui->audioStatusText->text() == "通过"; + bool batterySuccess = ui->batteryStatusText->text() == "通过"; + bool gsensorSuccess = ui->gsensorStatusText->text() == "通过"; + bool pppSuccess = ui->pppStatusText->text() == "通过"; + + QString overallIcon, overallText, overallColor; + + if (lcdSuccess && motorSuccess && keySuccess && audioSuccess && batterySuccess && gsensorSuccess && pppSuccess) { + // 所有测试都通过 + overallIcon = "✓"; + overallText = "通过"; + overallColor = "#4CAF50"; + } else { + // 任何其他情况(失败、测试中、等待开始等)都显示为未通过 + overallIcon = "✗"; + overallText = "未通过"; + overallColor = "#F44336"; + } + + QString overallStyle = QString("color: %1; font-size: 18px; font-weight: bold;").arg(overallColor); + QString textStyle = QString("color: %1;").arg(overallColor); + + ui->overallStatusIcon->setText(overallIcon); + ui->overallStatusIcon->setStyleSheet(overallStyle); + ui->overallStatusText->setText(overallText); + ui->overallStatusText->setStyleSheet(textStyle); +} + +// 保存测试记录到CSV文件(可用Excel打开) +QString MainWindow::saveTestRecord() +{ + QDateTime endTime = QDateTime::currentDateTime(); + QString startTimeStr = testStartTime.toString("yyyy-MM-dd hh:mm:ss"); + QString endTimeStr = endTime.toString("yyyy-MM-dd hh:mm:ss"); + + // 计算测试总耗时 + qint64 totalSeconds = testStartTime.secsTo(endTime); + int minutes = totalSeconds / 60; + int seconds = totalSeconds % 60; + QString durationStr = QString("%1分%2秒").arg(minutes).arg(seconds); + + QString date = endTime.toString("yyyy-MM-dd"); + + // 获取当前测试数据 + QString ver = ui->VerlineEdit->text().trimmed(); + QString imei = ui->IMEIlineEdit->text().trimmed(); + QString iccid = ui->ICCIDlineEdit->text().trimmed(); + QString modem = ui->ModemVerlineEdit->text().trimmed(); + QString pyver = ui->PYVerlineEdit->text().trimmed(); + + // 检查ICCID是否有效,如果无效则不写入记录 + if (iccid.isEmpty() || iccid == "未获取") { + qDebug() << "ICCID为空或未获取,跳过保存测试记录"; + ui->statusbar->showMessage("ICCID未获取,测试记录未保存", 3000); + return QString(); // 返回空字符串表示未保存 + } + + // 检查ICCID格式是否正确 + if (!isValidICCID(iccid)) { + qDebug() << "ICCID格式不正确,跳过保存测试记录,ICCID:" << iccid; + ui->statusbar->showMessage("ICCID格式不正确,测试记录未保存: " + iccid, 3000); + return QString(); // 返回空字符串表示未保存 + } + + // 检查IMEI格式是否正确(如果IMEI不为空) + if (!imei.isEmpty() && !isValidIMEI(imei)) { + qDebug() << "IMEI格式不正确,跳过保存测试记录,IMEI:" << imei; + ui->statusbar->showMessage("IMEI格式不正确,测试记录未保存: " + imei, 3000); + return QString(); // 返回空字符串表示未保存 + } + + // 调试信息:输出获取到的值 + qDebug() << "保存时获取的数据:"; + qDebug() << " Ver:" << (ver.isEmpty() ? "空" : ver); + qDebug() << " IMEI:" << (imei.isEmpty() ? "空" : imei); + qDebug() << " ICCID:" << iccid; + qDebug() << " Modem:" << (modem.isEmpty() ? "空" : modem); + qDebug() << " PYVER:" << (pyver.isEmpty() ? "空" : pyver); + + // 获取各项测试结果 + QString lcdResult = ui->lcdStatusText->text(); + QString motorResult = ui->motorStatusText->text(); + QString keyResult = ui->keyStatusText->text(); + QString audioResult = ui->audioStatusText->text(); + QString batteryResult = ui->batteryStatusText->text(); + QString gsensorResult = ui->gsensorStatusText->text(); + QString pppResult = ui->pppStatusText->text(); + QString overallResult = ui->overallStatusText->text(); + + // 创建保存目录(在源码同一路径下) + QString appPath = QCoreApplication::applicationDirPath(); + QString saveDir = appPath + "/产测记录"; + QDir dir; + if (!dir.exists(saveDir)) { + dir.mkpath(saveDir); + } + + // CSV文件路径(统一命名) + QString csvFileName = "产测记录.csv"; + QString csvFilePath = saveDir + "/" + csvFileName; + + // 检查是否是新文件(需要写入表头) + bool isNewFile = !QFile::exists(csvFilePath); + + // 构建新的测试数据行 + QString newDataLine = QString("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15\n") + .arg(startTimeStr) + .arg(endTimeStr) + .arg(durationStr) + .arg(ver.isEmpty() ? "未获取" : ver) + .arg(imei.isEmpty() ? "未获取" : imei) + .arg(iccid.isEmpty() ? "未获取" : iccid) + .arg(modem.isEmpty() ? "未获取" : modem) + .arg(pyver.isEmpty() ? "未获取" : pyver) + .arg(lcdResult) + .arg(motorResult) + .arg(keyResult) + .arg(audioResult) + .arg(batteryResult) + .arg(gsensorResult) + .arg(pppResult) + .arg(overallResult); + + QString finalContent; + + if (isNewFile) { + // 新文件,写入表头和数据 + finalContent += "开始时间,结束时间,测试耗时,软件版本,IMEI,ICCID,Modem版本,PYVER版本,LCD测试,马达测试,按键测试,录音测试,电池测试,G-sensor测试,4G测试,整体结果\n"; + finalContent += newDataLine; + qDebug() << "创建新的CSV文件:" << csvFilePath; + } else { + // 现有文件,需要检查ICCID是否重复 + QFile existingFile(csvFilePath); + if (!existingFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::warning(this, "读取失败", + QString("无法读取现有测试记录文件:\n%1").arg(csvFilePath)); + return QString(); + } + + // 读取所有现有数据 + QStringList existingLines; + QTextStream readStream(&existingFile); + while (!readStream.atEnd()) { + existingLines << readStream.readLine(); + } + existingFile.close(); + + // 构建最终内容 + if (!existingLines.isEmpty()) { + finalContent = existingLines[0] + "\n"; // 表头 + + bool iccidFound = false; + + // 检查每一行数据,查找相同ICCID + for (int i = 1; i < existingLines.size(); i++) { + QString line = existingLines[i]; + if (line.trimmed().isEmpty()) continue; + + // 分割CSV行,获取ICCID字段(第6列,索引为5) + QStringList fields = line.split(","); + if (fields.size() >= 6) { + QString existingIccid = fields[5].trimmed(); + + if (existingIccid == iccid) { + // 找到相同ICCID,替换为新记录 + finalContent += newDataLine; + iccidFound = true; + qDebug() << "找到相同ICCID,替换记录:" << iccid; + } else { + // 保留不同ICCID的记录 + finalContent += line + "\n"; + } + } else { + // 格式不正确的行,保留 + finalContent += line + "\n"; + } + } + + // 如果没有找到相同ICCID,追加新记录 + if (!iccidFound) { + finalContent += newDataLine; + qDebug() << "未找到相同ICCID,追加新记录:" << iccid; + } + } else { + // 文件为空,重建 + finalContent = "开始时间,结束时间,测试耗时,软件版本,IMEI,ICCID,Modem版本,LCD测试,马达测试,按键测试,录音测试,电池测试,G-sensor测试,4G测试,整体结果\n"; + finalContent += newDataLine; + } + } + + // 写入最终内容到文件 + QFile csvFile(csvFilePath); + if (!csvFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::warning(this, "保存失败", + QString("无法创建测试记录文件:\n%1\n错误:%2") + .arg(csvFilePath) + .arg(csvFile.errorString())); + return QString(); // 返回空字符串表示保存失败 + } + + // 使用系统本地编码写入数据(Windows下通常是GBK) + QByteArray localData = finalContent.toLocal8Bit(); + csvFile.write(localData); + qDebug() << "使用本地编码写入数据,大小:" << localData.size() << "字节"; + + csvFile.close(); + + qDebug() << "测试记录已保存到:" << csvFilePath; + qDebug() << "记录内容: 开始时间=" << startTimeStr << ", 结束时间=" << endTimeStr << ", 耗时=" << durationStr + << ", Ver=" << ver << ", IMEI=" << imei << ", ICCID=" << iccid << ", Modem=" << modem + << ", PYVER=" << pyver << ", LCD=" << lcdResult << ", 马达=" << motorResult + << ", 按键=" << keyResult << ", PPP=" << pppResult + << ", 整体=" << overallResult; + + // 显示保存成功消息 + ui->statusbar->showMessage(QString("测试记录已保存: %1").arg(csvFileName), 3000); + + // 返回文件名供外部使用 + return csvFileName; +} + + +// 检查signal和sim值进行4G测试判断 +void MainWindow::checkSignalAndSimValues(const QString& data) +{ + qDebug() << "开始检查signal和sim值,数据:" << data.trimmed(); + + // 标记已收到signal和sim数据 + hasReceivedSignalSim = true; + + // 停止超时检测,因为已经收到数据 + if (test4GTimer->isActive()) { + test4GTimer->stop(); + qDebug() << "收到signal和sim数据,停止4G测试超时检测"; + } + + // 解析sim值:@sim:1@ + QRegExp simRegex("@sim:(\\d+)@"); + int simValue = -1; + if (simRegex.indexIn(data) != -1) { + simValue = simRegex.cap(1).toInt(); + qDebug() << "解析到sim值:" << simValue; + + // 保存SIM卡状态 + currentSimStatus = simValue; + qDebug() << "更新SIM卡状态:" << (currentSimStatus == 1 ? "已插入" : "未插入"); + } else { + qDebug() << "未找到sim值"; + return; + } + + // 解析signal值:@signal:31@ + QRegExp signalRegex("@signal:(\\d+)@"); + int signalValue = -1; + if (signalRegex.indexIn(data) != -1) { + signalValue = signalRegex.cap(1).toInt(); + qDebug() << "解析到signal值:" << signalValue; + + // 将signal值显示到界面 + ui->recvTextEdit->append(QString("Signal值: %1").arg(signalValue)); + ui->statusbar->showMessage(QString("检测到Signal值: %1").arg(signalValue), 2000); + } else { + qDebug() << "未找到signal值"; + return; + } + + // 移除signal=99的立即失败逻辑,改为在CAT1测试中统计处理 + + // 如果是第一次收到signal值,启动CAT1信号测试 + if (!hasReceivedFirstSignal) { + hasReceivedFirstSignal = true; + qDebug() << "收到第一次signal值:" << signalValue << ",启动CAT1信号测试"; + + // 停止signal4GTimer,避免与CAT1测试冲突导致重复弹窗 + if (signal4GTimer->isActive()) { + signal4GTimer->stop(); + qDebug() << "停止signal4GTimer,改用CAT1信号测试"; + } + + // 初始化CAT1信号测试计数器 + cat1SignalTestCount = 0; + cat1SignalReceivedCount = 0; + cat1SignalGoodCount = 0; + cat1Signal99Count = 0; + cat1SignalTotalValue = 0; + // 移除了cat1ProcessedSignals的清理,改用时间戳方式 + + // 启动CAT1信号测试定时器,每2秒发送一次 + cat1SignalTimer->start(2000); + ui->statusbar->showMessage("开始CAT1信号测试,每2秒检测一次...", 3000); + + // 立即发送第一次CAT1信号检测指令 + serial->write("AT^CAT1GETSIGNAL\r\n"); + cat1SignalTestCount++; + qDebug() << "发送第" << cat1SignalTestCount << "次CAT1信号检测指令: AT^CAT1GETSIGNAL"; + return; + } + + // 如果已经启动了CAT1信号测试,不再执行旧的判断逻辑 + if (hasReceivedFirstSignal) { + qDebug() << "已启动CAT1信号测试,跳过旧的signal判断逻辑"; + return; + } + + // 判断4G测试是否通过(这段代码理论上不会执行到) + bool simOk = (simValue == 1); + bool signalOk = (signalValue > 25); + bool testPassed = simOk && signalOk; + + qDebug() << "4G测试判断结果:"; + qDebug() << " sim值:" << simValue << "(期望: 1)" << "检查结果:" << (simOk ? "通过" : "失败"); + qDebug() << " signal值:" << signalValue << "(期望: >25)" << "检查结果:" << (signalOk ? "通过" : "失败"); + qDebug() << " 最终测试结果:" << (testPassed ? "通过" : "失败"); + qDebug() << " 警告:此代码不应该执行到,因为已启动CAT1测试"; + + if (testPassed) { + // 测试通过 + ui->statusbar->showMessage(QString("4G测试通过 - SIM: %1, Signal: %2").arg(simValue).arg(signalValue), 3000); + updateTestStatus("ppp", STATUS_SUCCESS); + + // 完成产测 + if (isProductionTestRunning) { + currentTestStep = TEST_COMPLETED; + isProductionTestRunning = false; + qDebug() << "4G测试通过,产测流程完成"; + + // 保存测试记录 + QString fileName = saveTestRecord(); + + // 显示最终测试结果弹窗 + showFinalTestResult(); + } + } else { + // 测试失败 + QString failReason; + if (simValue != 1) { + failReason += QString("SIM卡状态异常(值:%1,期望:1) ").arg(simValue); + } + if (signalValue == 99) { + failReason += QString("无效信号值(值:%1)").arg(signalValue); + } else if (signalValue <= 25) { + failReason += QString("信号强度不足(值:%1,期望:>25)").arg(signalValue); + } + + ui->statusbar->showMessage(QString("4G测试失败 - %1").arg(failReason), 3000); + updateTestStatus("ppp", STATUS_FAILED); + + // 完成产测(失败) + if (isProductionTestRunning) { + currentTestStep = TEST_COMPLETED; + isProductionTestRunning = false; + qDebug() << "4G测试失败,产测流程完成"; + + // 保存测试记录 + QString fileName = saveTestRecord(); + + // 显示最终测试结果弹窗 + showFinalTestResult(); + } + } +} + +// 解析wstp_print格式的BTMAC和CyweeChipInfo数据 +void MainWindow::parseWstpPrintData(const QString& data) +{ + qDebug() << "检测到wstp_print格式数据:" << data.trimmed(); + + // 解析BTMAC地址 + // 格式:^^^^ BTMAC=XX:XX:XX:XX:XX:XX ^^^^ + QRegExp btmacPattern("\\^\\^\\^\\^ BTMAC=([0-9A-Fa-f:]{17}) \\^\\^\\^\\^"); + if (btmacPattern.indexIn(data) != -1) { + QString btmac = btmacPattern.cap(1); + qDebug() << "解析到BTMAC地址:" << btmac; + + // 这里可以将BTMAC地址填充到相应的文本框 + // 如果有专门的BTMAC文本框,可以这样设置: + // ui->btmacLineEdit->setText(btmac); + + // 暂时显示在状态栏 + ui->statusbar->showMessage(QString("检测到蓝牙MAC地址: %1").arg(btmac), 3000); + } + + // 解析CyweeChipInfo + // 格式:^^^^ CyweeChipInfo=XXXXXX ^^^^ + QRegExp chipinfoPattern("\\^\\^\\^\\^ CyweeChipInfo=([^\\s\\^]+)"); + if (chipinfoPattern.indexIn(data) != -1) { + QString chipinfo = chipinfoPattern.cap(1); + qDebug() << "解析到CyweeChipInfo:" << chipinfo; + + // 这里可以将芯片信息填充到相应的文本框 + // 如果有专门的芯片信息文本框,可以这样设置: + // ui->chipinfoLineEdit->setText(chipinfo); + + // 暂时显示在状态栏 + ui->statusbar->showMessage(QString("检测到芯片信息: %1").arg(chipinfo), 3000); + } + + // 完整的数据格式示例: + // wstp_print("^^^^ BTMAC=%s ^^^^ CyweeChipInfo=%s\n",btaddr_str,chipinfo); + // 实际输出可能是:^^^^ BTMAC=AA:BB:CC:DD:EE:FF ^^^^ CyweeChipInfo=MSA310 + + // 如果需要同时解析两个值的完整格式 + QRegExp fullPattern("\\^\\^\\^\\^ BTMAC=([0-9A-Fa-f:]{17}) \\^\\^\\^\\^ CyweeChipInfo=([^\\s\\^\\n]+)"); + if (fullPattern.indexIn(data) != -1) { + QString btmac = fullPattern.cap(1); + QString chipinfo = fullPattern.cap(2); + + qDebug() << "完整解析 - BTMAC:" << btmac << ", CyweeChipInfo:" << chipinfo; + + // 可以在这里将信息填充到对应的UI控件 + // 例如: + // ui->btmacLineEdit->setText(btmac); + // ui->chipinfoLineEdit->setText(chipinfo); + + ui->statusbar->showMessage(QString("设备信息 - MAC: %1, 芯片: %2").arg(btmac, chipinfo), 5000); + } +} + +// 发送PPP指令 +void MainWindow::sendPppCommand() +{ + if (!isProductionTestRunning || currentTestStep != TEST_PPP_INIT) { + qDebug() << "PPP数据等待跳过 - 测试状态不正确"; + return; + } + + pppCommandCount++; + qDebug() << "等待PPP数据,第" << pppCommandCount << "次"; + + if (pppCommandCount <= 3) { + // 前3次等待PPP相关数据 + ui->statusbar->showMessage(QString("4G测试中 - 等待PPP数据(%1/3)").arg(pppCommandCount), 3000); + + // 不再发送PPPENVINIT指令,直接等待设备自动发送PPPINFO + + // 启动5秒超时定时器,等待PPPINFO回复 + test4GTimer->start(5000); + qDebug() << "启动5秒超时定时器,等待PPPINFO回复"; + } else { + // 超过3次后,改为等待signal和sim数据 + qDebug() << "PPP数据已等待3次,改为等待signal和sim数据"; + ui->statusbar->showMessage("4G测试中 - 等待signal和sim数据...", 5000); + + // 启动5秒超时检测,等待signal和sim数据 + test4GTimer->start(5000); + qDebug() << "启动5秒超时检测,等待signal和sim数据"; + } +} + +// 打开记录文件夹 +void MainWindow::on_openRecordsFolderButton_clicked() +{ + QString appPath = QCoreApplication::applicationDirPath(); + QString saveDir = appPath + "/产测记录"; + + // 如果文件夹不存在,先创建它 + QDir dir; + if (!dir.exists(saveDir)) { + dir.mkpath(saveDir); + qDebug() << "创建产测记录文件夹:" << saveDir; + } + + // 打开文件夹 + bool success = QDesktopServices::openUrl(QUrl::fromLocalFile(saveDir)); + + if (success) { + qDebug() << "成功打开文件夹:" << saveDir; + ui->statusbar->showMessage("已打开产测记录文件夹", 2000); + } else { + qDebug() << "打开文件夹失败:" << saveDir; + QMessageBox::warning(this, "打开失败", + QString("无法打开文件夹:\n%1\n请检查路径是否存在或权限是否足够").arg(saveDir)); + } +} + +void MainWindow::on_openButton_2_clicked() +{ + // 检查串口是否已打开 + if (!serial->isOpen()) { + QMessageBox::warning(this, "警告", "请先打开串口连接"); + return; + } + + if (isProductionTestRunning) { + // 如果正在测试,则停止测试 + lcdTestTimer->stop(); + motorTestTimer->stop(); + test4GTimer->stop(); + signal4GTimer->stop(); + testTimeoutTimer->stop(); + isProductionTestRunning = false; + currentTestStep = TEST_IDLE; + ui->statusbar->showMessage("产测已停止", 2000); + qDebug() << "产测被用户停止"; + + // 恢复产测按钮状态 - 变回蓝色并启用 + ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }"); + ui->openButton_2->setEnabled(true); + qDebug() << "产测停止 - 按钮已恢复蓝色并启用"; + + return; + } + + // 开始产测流程 + isProductionTestRunning = true; + testStartTime = QDateTime::currentDateTime(); // 记录测试开始时间 + currentTestStep = TEST_RESET; + currentLcdColor = 1; // 从红色开始 + initRetry4GCount = 0; + signalTest4GCount = 0; + signalReceived4GCount = 0; + signalGood4GCount = 0; + pppCommandCount = 0; + hasReceivedSignalSim = false; + hasReceivedPppInfo = false; + + // 清空所有UI内容 + ui->recvTextEdit->clear(); // 清空串口接收文本框 + ui->sendTextEdit->clear(); // 清空发送文本框 + ui->statusbar->clearMessage(); // 清空状态栏 + + // 清空设备信息 + ui->VerlineEdit->clear(); // 清空版本信息 + ui->IMEIlineEdit->clear(); // 清空IMEI + ui->ICCIDlineEdit->clear(); // 清空ICCID + ui->ModemVerlineEdit->clear(); // 清空调制解调器版本 + ui->PYVerlineEdit->clear(); // 清空python版本 + + // 重置弹窗状态 + lcdTestPopupShown = false; + motorTestPopupShown = false; + isWaitingForUserConfirm = false; + keyTestStarted = false; + audioTestPopupShown = false; + audioPlaybackPopupShown = false; + + // 重置状态指示器 + updateTestStatus("lcd", STATUS_UNTESTED); + updateTestStatus("motor", STATUS_UNTESTED); + updateTestStatus("key", STATUS_UNTESTED); + updateTestStatus("audio", STATUS_UNTESTED); + updateTestStatus("battery", STATUS_UNTESTED); + updateTestStatus("gsensor", STATUS_UNTESTED); + updateTestStatus("ppp", STATUS_UNTESTED); + + qDebug() << "已清空所有UI内容,准备开始新的产测"; + + ui->statusbar->showMessage("开始产测流程...", 2000); + qDebug() << "=== 开始产测流程 ==="; + qDebug() << "流程: 产测开启(AT^FACTORY=1) → 设备重启 → 等待BuildVer → LCD测试(红绿蓝各1s) → 马达测试(开启2s) → 按键测试 → 录音测试(录音3s+播放) → 电池测试(电压检测) → G-sensor测试 → 4G测试(初始化+信号检测) → 退出产测(AT^FACTORY=0)"; + qDebug() << "LCD指令映射: 进入=AT^LCDTEST=1, 红色=AT^LCDTEST=6, 绿色=AT^LCDTEST=3, 蓝色=AT^LCDTEST=4, 退出=AT^LCDTEST=2"; + + // 发送产测开启指令,等待工厂模式确认 + qDebug() << "Step 1: 发送产测开启指令"; + ui->statusbar->showMessage("发送产测开启指令,等待设备确认...", 3000); + serial->write("AT^FACTORY=1\r\n"); + qDebug() << "发送产测开启指令(第1次): AT^FACTORY=1,等待接收 'fac:enter or exit facotry mode' 确认"; + + // 延迟0.5秒后再发送一次,确保设备接收到指令 + QTimer::singleShot(500, this, [this]() { + if (isProductionTestRunning && serial->isOpen()) { + serial->write("AT^FACTORY=1\r\n"); + qDebug() << "发送产测开启指令(第2次): AT^FACTORY=1"; + } + }); + + // 启动10秒超时检测,如果没有收到工厂模式确认则提示 + testTimeoutTimer->start(10000); +} + +// 执行录音测试 +void MainWindow::performAudioTest() +{ + qDebug() << "*** performAudioTest 被调用 ***"; + qDebug() << "当前状态检查 - isProductionTestRunning:" << isProductionTestRunning; + qDebug() << "当前状态检查 - currentTestStep:" << currentTestStep; + qDebug() << "当前状态检查 - TEST_AUDIO:" << TEST_AUDIO; + + if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) { + qDebug() << "*** performAudioTest 条件不满足,退出 ***"; + return; + } + + qDebug() << "开始录音测试"; + updateTestStatus("audio", STATUS_TESTING); + ui->statusbar->showMessage("录音测试准备就绪", 3000); + + // 重置录音测试相关标志 + audioTestPopupShown = false; + audioPlaybackPopupShown = false; + currentAudioStep = AUDIO_STARTING_RECORD; + + // 显示录音测试弹窗,等待用户点击开始录音 + showAudioTestDialog(); +} + +// 显示录音测试弹窗 +void MainWindow::showAudioTestDialog() +{ + if (audioTestPopupShown || !isProductionTestRunning || currentTestStep != TEST_AUDIO) { + qDebug() << "录音测试弹窗已显示或条件不满足,跳过显示"; + return; + } + + // 如果已经有录音测试弹窗存在,先关闭它 + if (audioTestDialog) { + qDebug() << "检测到已存在的录音测试弹窗,先关闭"; + audioTestDialog->close(); + audioTestDialog->deleteLater(); + audioTestDialog = nullptr; + } + + // 创建录音测试对话框 + audioTestDialog = new QDialog(this); + audioTestDialog->setWindowTitle("录音测试"); + audioTestDialog->setFixedSize(520, 350); + audioTestDialog->setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint | Qt::WindowTitleHint); + + // 设置对话框样式 + audioTestDialog->setStyleSheet( + "QDialog { " + "background-color: #f0f0f0; " + "border-radius: 8px; " + "}" + ); + + // 使用垂直布局管理器 + QVBoxLayout *mainLayout = new QVBoxLayout(audioTestDialog); + mainLayout->setSpacing(15); + mainLayout->setContentsMargins(20, 20, 20, 20); + + // 创建主标签 + audioDialogLabel = new QLabel("🎤 录音测试"); + audioDialogLabel->setAlignment(Qt::AlignCenter); + audioDialogLabel->setStyleSheet( + "QLabel { " + "font-size: 18px; " + "font-weight: bold; " + "background-color: #4CAF50; " + "color: white; " + "border-radius: 4px; " + "padding: 12px; " + "}" + ); + mainLayout->addWidget(audioDialogLabel); + + // 创建信息标签 + audioDialogInfo = new QLabel("🎤 请点击下方按钮开始录音测试\n流程:开始录音→1s后播放1kHz音频→2s后停止播放和录音→1s后播放录音→3s后停止"); + audioDialogInfo->setAlignment(Qt::AlignCenter); + audioDialogInfo->setWordWrap(true); + audioDialogInfo->setMinimumHeight(80); + audioDialogInfo->setStyleSheet( + "QLabel { " + "font-size: 14px; " + "background-color: white; " + "border: 1px solid #ddd; " + "border-radius: 4px; " + "padding: 15px; " + "color: #333; " + "}" + ); + mainLayout->addWidget(audioDialogInfo); + + // 创建开始录音按钮布局 + QHBoxLayout *startLayout = new QHBoxLayout(); + startLayout->setSpacing(10); + + audioStartButton = new QPushButton("🎤 开始录音测试"); + audioStartButton->setMinimumHeight(50); + audioStartButton->setStyleSheet( + "QPushButton { " + "background-color: #2196F3; " + "color: white; " + "padding: 12px 20px; " + "border-radius: 4px; " + "font-weight: bold; " + "font-size: 16px; " + "}" + ); + startLayout->addWidget(audioStartButton); + mainLayout->addLayout(startLayout); + + // 创建测试结果按钮布局 + QHBoxLayout *resultLayout = new QHBoxLayout(); + resultLayout->setSpacing(10); + + // 创建按钮 + audioPassButton = new QPushButton("✓ 录音正常"); + audioPassButton->setMinimumHeight(45); + audioPassButton->setStyleSheet( + "QPushButton { " + "background-color: #4CAF50; " + "color: white; " + "padding: 10px 15px; " + "border-radius: 4px; " + "font-weight: bold; " + "font-size: 14px; " + "} " + "QPushButton:disabled { " + "background-color: #cccccc; " + "color: #666666; " + "}" + ); + audioPassButton->setEnabled(true); // 允许直接点击通过 + + audioFailButton = new QPushButton("✗ 录音异常"); + audioFailButton->setMinimumHeight(45); + audioFailButton->setStyleSheet( + "QPushButton { " + "background-color: #f44336; " + "color: white; " + "padding: 10px 15px; " + "border-radius: 4px; " + "font-weight: bold; " + "font-size: 14px; " + "}" + ); + audioFailButton->setEnabled(false); // 初始禁用 + + audioRetestButton = new QPushButton("🔄 重新测试"); + audioRetestButton->setMinimumHeight(45); + audioRetestButton->setStyleSheet( + "QPushButton { " + "background-color: #FF9800; " + "color: white; " + "padding: 10px 15px; " + "border-radius: 4px; " + "font-weight: bold; " + "font-size: 14px; " + "}" + ); + audioRetestButton->setEnabled(false); // 初始禁用 + + resultLayout->addWidget(audioPassButton); + resultLayout->addWidget(audioFailButton); + resultLayout->addWidget(audioRetestButton); + + // 添加按钮布局到主布局 + mainLayout->addLayout(resultLayout); + + // 连接开始录音按钮事件 + connect(audioStartButton, &QPushButton::clicked, [this]() { + qDebug() << "用户点击开始录音测试"; + + // 禁用开始按钮,更新界面状态 + audioStartButton->setEnabled(false); + audioDialogInfo->setText("🎤 正在开始录音...\n请保持安静"); + + // 发送开始录音指令 + QString recordCommand = "AT^MEDIAAUDIORECORD=xx,mp3,16000,1,16,/user/res/music/1.mp3\r\n"; + serial->write(recordCommand.toUtf8()); + qDebug() << "发送录音开始指令:" << recordCommand.trimmed(); + + // 延迟1秒后发送播放1kHz音频指令 + QTimer::singleShot(1000, this, [this]() { + if (audioTestDialog && isProductionTestRunning) { + audioDialogInfo->setText("📢 正在播放1kHz测试音频(2秒)\n同时进行录音,请注意听声音..."); + + // 发送播放1kHz音频指令 + QString play1khzCommand = "AT^MEDIAMUSICPLAY=xx,/user/res/music/1khz.mp3,1,0\r\n"; + serial->write(play1khzCommand.toUtf8()); + qDebug() << "发送播放1kHz音频指令:" << play1khzCommand.trimmed(); + + // 设置当前步骤为播放1kHz音频,启动2秒定时器 + currentAudioStep = AUDIO_PLAYING_1KHZ; + audioRecordTimer->start(2000); + } + }); + }); + + // 连接测试结果按钮事件 + connect(audioPassButton, &QPushButton::clicked, [this]() { + if (audioTestDialog) { + audioTestDialog->accept(); + qDebug() << "用户确认:录音测试通过"; + ui->statusbar->showMessage("录音测试通过", 2000); + updateTestStatus("audio", STATUS_SUCCESS); + + // 继续电池测试 + currentTestStep = TEST_BATTERY; + performBatteryTest(); + } + }); + + connect(audioFailButton, &QPushButton::clicked, [this]() { + if (audioTestDialog) { + audioTestDialog->accept(); + qDebug() << "用户确认:录音测试失败"; + ui->statusbar->showMessage("录音测试失败", 2000); + updateTestStatus("audio", STATUS_FAILED); + + // 继续电池测试 + currentTestStep = TEST_BATTERY; + performBatteryTest(); + } + }); + + connect(audioRetestButton, &QPushButton::clicked, [this]() { + qDebug() << "用户选择重新测试录音"; + + // 发送停止指令 + serial->write("AT^MEDIAMUSICSTOP\r\n"); + serial->write("AT^MEDIAAUDIORECORDSTOP\r\n"); + + // 重置界面状态 + audioStartButton->setEnabled(true); + audioPassButton->setEnabled(false); + audioFailButton->setEnabled(false); + audioRetestButton->setEnabled(false); + audioDialogInfo->setText("🎤 请点击下方按钮开始录音测试\n流程:开始录音→1s后播放1kHz音频→2s后停止播放和录音→1s后播放录音→3s后停止"); + + // 重置录音测试状态 + currentAudioStep = AUDIO_STARTING_RECORD; + audioRecordTimer->stop(); + + qDebug() << "录音测试已重置,等待用户重新开始"; + }); + + // 显示对话框 + audioTestPopupShown = true; + audioTestDialog->show(); + qDebug() << "录音测试弹窗已显示"; +} + +// 录音测试定时器 - 处理多个步骤的定时 +void MainWindow::onAudioRecordTimer() +{ + audioRecordTimer->stop(); + + if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) { + return; + } + + switch (currentAudioStep) { + case AUDIO_PLAYING_1KHZ: + { + // 2秒播放1kHz音频完成,停止播放 + qDebug() << "1kHz音频播放2秒完成,发送停止播放指令"; + ui->statusbar->showMessage("停止1kHz音频播放...", 2000); + + // 更新弹窗信息 + if (audioDialogInfo) { + audioDialogInfo->setText("⏹️ 停止播放1kHz音频,随后停止录音...\n请稍等片刻..."); + } + + // 先发送停止播放指令 + serial->write("AT^MEDIAMUSICSTOP\r\n"); + qDebug() << "发送停止播放指令: AT^MEDIAMUSICSTOP"; + + // 随后立即发送停止录音指令 + serial->write("AT^MEDIAAUDIORECORDSTOP\r\n"); + qDebug() << "发送停止录音指令: AT^MEDIAAUDIORECORDSTOP"; + + // 设置下一步骤,1秒后播放录制的音频 + currentAudioStep = AUDIO_STOPPING_RECORD; + audioRecordTimer->start(1000); + break; + } + + case AUDIO_STOPPING_RECORD: + { + // 1秒延迟完成,播放录制的音频 + qDebug() << "开始播放录制的音频"; + ui->statusbar->showMessage("正在播放录制的音频...", 3000); + + // 更新弹窗信息 + if (audioDialogInfo) { + audioDialogInfo->setText("🔊 正在播放刚才录制的音频(3秒)\n请仔细聆听音质是否清晰"); + } + + // 发送播放录制音频指令 + QString playRecordedCommand = "AT^MEDIAMUSICPLAY=xx,/user/res/music/1.mp3,1,0\r\n"; + serial->write(playRecordedCommand.toUtf8()); + qDebug() << "发送播放录制音频指令:" << playRecordedCommand.trimmed(); + + // 设置下一步骤,3秒后停止播放录制的音频 + currentAudioStep = AUDIO_PLAYING_RECORDED; + audioRecordTimer->start(3000); + break; + } + + case AUDIO_PLAYING_RECORDED: + { + // 3秒播放录制音频完成,自动停止播放 + qDebug() << "录制音频播放3秒完成,发送停止播放指令"; + ui->statusbar->showMessage("录音测试流程完成", 2000); + + // 更新弹窗信息并启用测试按钮 + if (audioDialogInfo) { + audioDialogInfo->setText("✅ 录音测试流程完成!\n请根据刚才听到的音质选择测试结果"); + } + if (audioPassButton) { + audioPassButton->setEnabled(true); + } + if (audioFailButton) { + audioFailButton->setEnabled(true); + } + if (audioRetestButton) { + audioRetestButton->setEnabled(true); + } + + // 自动发送停止播放指令 + serial->write("AT^MEDIAMUSICSTOP\r\n"); + qDebug() << "发送停止播放指令: AT^MEDIAMUSICSTOP"; + + // 录音测试流程完成 + currentAudioStep = AUDIO_STOPPING_PLAYBACK; + break; + } + + default: + { + qDebug() << "未知的录音测试步骤:" << currentAudioStep; + break; + } + } +} + +// 检查录音测试结果 +void MainWindow::checkAudioTestResult(const QString& data) +{ + if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) { + return; + } + + qDebug() << "录音测试收到数据:" << data.trimmed(); + + // 录音测试现在由用户手动控制,不需要自动检测 + qDebug() << "录音测试收到数据(用户手动控制模式):" << data.trimmed(); +} + +// 执行电池测试 +void MainWindow::performBatteryTest() +{ + if (!isProductionTestRunning || currentTestStep != TEST_BATTERY) { + return; + } + + qDebug() << "开始电池测试"; + updateTestStatus("battery", STATUS_TESTING); + ui->statusbar->showMessage("电池测试中,正在获取电池电压...", 3000); + + // 发送电池电量查询指令 + serial->write("AT^GETPOWER\r\n"); + qDebug() << "发送电池测试指令: AT^GETPOWER"; + + // 启动10秒超时检测 + testTimeoutTimer->start(10000); +} + +// 检查电池测试结果 +void MainWindow::checkBatteryTestResult(const QString& data) +{ + if (!isProductionTestRunning || currentTestStep != TEST_BATTERY) { + return; + } + + qDebug() << "电池测试收到数据:" << data.trimmed(); + + // 解析电池电压数据,支持多种格式: + // 1. fac:voltage : 3.8 , percent 85 , charge : 1 + // 2. Battery: 3.8V + // 3. 3.8V + QRegExp facVoltagePattern("fac:voltage\\s*:\\s*(\\d+\\.\\d+)\\s*,\\s*percent\\s*(\\d+)\\s*,\\s*charge\\s*:\\s*(\\d+)"); + QRegExp batteryPattern("Battery.*?(\\d+\\.\\d+)V?"); + QRegExp voltagePattern("(\\d+\\.\\d+)V"); + + double voltage = 0.0; + int percent = 0; + int charge = -1; // -1表示未检测到充电状态 + bool voltageFound = false; + + if (facVoltagePattern.indexIn(data) != -1) { + // 新格式:fac:voltage : 3.8 , percent 85 , charge : 1 + voltage = facVoltagePattern.cap(1).toDouble(); + percent = facVoltagePattern.cap(2).toInt(); + charge = facVoltagePattern.cap(3).toInt(); + voltageFound = true; + + qDebug() << "使用fac:voltage格式解析到电压:" << voltage << "V, 电量:" << percent << "%, 充电状态:" << charge; + } else if (batteryPattern.indexIn(data) != -1) { + voltage = batteryPattern.cap(1).toDouble(); + voltageFound = true; + qDebug() << "使用Battery格式解析到电压:" << voltage; + } else if (voltagePattern.indexIn(data) != -1) { + voltage = voltagePattern.cap(1).toDouble(); + voltageFound = true; + qDebug() << "使用通用电压格式解析到电压:" << voltage; + } + + if (voltageFound) { + // 停止超时检测,因为已经收到响应 + if (testTimeoutTimer->isActive()) { + testTimeoutTimer->stop(); + qDebug() << "电池测试收到响应,停止超时检测"; + } + + qDebug() << "检测到电池电压:" << voltage << "V"; + + // 首先检查充电状态(如果有充电状态信息) + if (charge == 0) { + qDebug() << "电池未充电,测试失败"; + ui->statusbar->showMessage("电池测试失败 - 设备未充电", 2000); + showBatteryChargeFailDialog(); + return; // 不继续后续测试,等待用户操作 + } else if (charge == -1) { + qDebug() << "未检测到充电状态信息"; + ui->statusbar->showMessage("电池测试 - 未检测到充电状态", 2000); + // 显示提醒框告知用户未检测到充电状态 + QMessageBox msgBox(this); + msgBox.setWindowTitle("充电状态提醒"); + msgBox.setText("未检测到充电状态"); + msgBox.setInformativeText("系统未能检测到设备的充电状态信息,\n但电压检测正常,是否继续测试?"); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + msgBox.setIcon(QMessageBox::Warning); + + int ret = msgBox.exec(); + if (ret == QMessageBox::No) { + updateTestStatus("battery", STATUS_FAILED); + return; + } + } + + // 判断电压是否在正常范围内 (3.3V - 4.4V) + if (voltage >= 3.3 && voltage <= 4.4) { + if (charge == 1) { + qDebug() << "电池电压正常且正在充电,测试通过"; + ui->statusbar->showMessage(QString("电池测试通过 - 电压: %1V, 充电中").arg(voltage), 2000); + } else { + qDebug() << "电池电压正常,测试通过"; + ui->statusbar->showMessage(QString("电池测试通过 - 电压: %1V").arg(voltage), 2000); + } + updateTestStatus("battery", STATUS_SUCCESS); + } else { + qDebug() << "电池电压异常,测试失败"; + ui->statusbar->showMessage(QString("电池测试失败 - 电压异常: %1V").arg(voltage), 2000); + updateTestStatus("battery", STATUS_FAILED); + } + + // 电池测试完成,开始G-sensor测试 + if (isProductionTestRunning && currentTestStep == TEST_BATTERY) { + qDebug() << "电池测试完成,开始G-sensor测试"; + currentTestStep = TEST_GSENSOR; + performGsensorTest(); + } + } +} + +// 执行G-sensor测试 +void MainWindow::performGsensorTest() +{ + if (!isProductionTestRunning || currentTestStep != TEST_GSENSOR) { + return; + } + + qDebug() << "开始G-sensor测试"; + updateTestStatus("gsensor", STATUS_TESTING); + ui->statusbar->showMessage("G-sensor测试中,正在获取sensor ID...", 3000); + + // 发送G-sensor查询指令 + serial->write("AT^GETCYWEEID\r\n"); + qDebug() << "发送G-sensor测试指令: AT^GETCYWEEID"; + + // 启动10秒超时检测 + testTimeoutTimer->start(10000); +} + +// 检查G-sensor测试结果 +void MainWindow::checkGsensorTestResult(const QString& data) +{ + qDebug() << "=== checkGsensorTestResult 被调用 ==="; + qDebug() << "isProductionTestRunning:" << isProductionTestRunning; + qDebug() << "currentTestStep:" << currentTestStep << "(TEST_GSENSOR=" << TEST_GSENSOR << ")"; + + if (!isProductionTestRunning || currentTestStep != TEST_GSENSOR) { + qDebug() << "G-sensor测试条件不满足,跳过处理"; + return; + } + + qDebug() << "G-sensor测试收到数据:" << data.trimmed(); + + // 检测G-sensor ID,格式可能为:fac:gsensor id : 0x13 或类似 + if (data.contains("gsensor") && data.contains("id")) { + QRegExp gsensorPattern("(?:fac:)?gsensor\\s+id\\s*[:]\\s*(0?[xX]?[0-9A-Fa-f]+)"); + qDebug() << "尝试匹配G-sensor模式,输入数据:" << data.trimmed(); + qDebug() << "正则表达式模式:" << gsensorPattern.pattern(); + if (gsensorPattern.indexIn(data) != -1) { + // 停止超时检测,因为已经收到响应 + if (testTimeoutTimer->isActive()) { + testTimeoutTimer->stop(); + qDebug() << "G-sensor测试收到响应,停止超时检测"; + } + + qDebug() << "G-sensor正则表达式匹配通过!"; + QString gsensorId = gsensorPattern.cap(1).toUpper(); // 转换为大写便于比较 + qDebug() << "检测到G-sensor ID:" << gsensorId; + + // 检查G-sensor ID是否为有效值(期望值为0X13) + // 支持多种格式: 0X13, 0x13, 13, 19 (十进制) + bool isValidId = false; + QString expectedId = "0X13"; + + // 统一转换为大写便于比较 + QString upperGsensorId = gsensorId.toUpper(); + + if (upperGsensorId == "0X13" || upperGsensorId == "13") { + isValidId = true; + } else { + // 尝试解析数值进行比较 + bool ok; + int decimalValue = 0; + + // 如果以0X或0x开头,按十六进制解析 + if (upperGsensorId.startsWith("0X")) { + decimalValue = upperGsensorId.mid(2).toInt(&ok, 16); + } else { + // 尝试直接按十六进制解析 + decimalValue = upperGsensorId.toInt(&ok, 16); + // 如果十六进制解析失败,尝试十进制解析 + if (!ok) { + decimalValue = upperGsensorId.toInt(&ok, 10); + } + } + + if (ok && decimalValue == 0x13) { + isValidId = true; + } + } + + if (isValidId) { + qDebug() << "G-sensor ID有效,测试通过"; + ui->statusbar->showMessage(QString("G-sensor测试通过 - ID: %1").arg(gsensorId), 2000); + updateTestStatus("gsensor", STATUS_SUCCESS); + } else { + qDebug() << "G-sensor ID不匹配期望值,测试失败"; + ui->statusbar->showMessage(QString("G-sensor测试失败 - ID: %1 (期望: 0X13)").arg(gsensorId), 2000); + updateTestStatus("gsensor", STATUS_FAILED); + } + + // G-sensor测试完成,开始4G测试 + if (isProductionTestRunning && currentTestStep == TEST_GSENSOR) { + qDebug() << "G-sensor测试完成,开始4G测试"; + + // 开始4G测试 + currentTestStep = TEST_PPP_INIT; + perform4GTest(); + } + } else { + qDebug() << "G-sensor正则表达式匹配失败,数据:" << data.trimmed(); + + // 手动测试特定格式:fac:gsensor id : 0x13 + if (data.contains("gsensor id") && data.contains("0x13")) { + qDebug() << "手动检测到 fac:gsensor id : 0x13 格式,强制通过测试"; + ui->statusbar->showMessage("G-sensor测试通过 - ID: 0x13 (手动检测)", 2000); + updateTestStatus("gsensor", STATUS_SUCCESS); + + // G-sensor测试完成,开始4G测试 + if (isProductionTestRunning && currentTestStep == TEST_GSENSOR) { + qDebug() << "G-sensor测试完成(手动),开始4G测试"; + + // 开始4G测试 + currentTestStep = TEST_PPP_INIT; + perform4GTest(); + } + } + } + } else { + qDebug() << "数据不包含gsensor和id关键字,跳过G-sensor处理"; + } + + // 单独检查错误响应 + if (data.contains("ERROR") || data.contains("FAIL")) { + qDebug() << "G-sensor测试失败 - 设备响应错误"; + ui->statusbar->showMessage("G-sensor测试失败 - 设备无响应", 2000); + updateTestStatus("gsensor", STATUS_FAILED); + + // G-sensor测试失败,仍然继续4G测试 + if (isProductionTestRunning && currentTestStep == TEST_GSENSOR) { + qDebug() << "G-sensor测试失败,继续4G测试"; + + // 开始4G测试 + currentTestStep = TEST_PPP_INIT; + perform4GTest(); + } + } +} + +// 检查CAT1信号测试结果 +void MainWindow::checkCat1SignalResult(const QString& data) +{ + if (!isProductionTestRunning || !hasReceivedFirstSignal) { + return; + } + + qDebug() << "CAT1信号测试收到数据:" << data.trimmed(); + qDebug() << "当前MODEM版本:" << currentModemVersion << ",类型判断:" << (isEGModem() ? "EG系列" : "非EG系列"); + + // 只在CAT1测试期间统计信号值 + if (cat1SignalReceivedCount >= 5) { + qDebug() << "CAT1测试已接收5次响应,跳过统计"; + return; + } + + // 格式过滤已在调用前完成,这里不需要再次过滤 + + // 解析信号值,可能的格式:signal:31 或 CAT1GETSIGNAL OK signal:31 + QRegExp signalRegex("signal:(\\d+)"); + if (signalRegex.indexIn(data) != -1) { + int signalValue = signalRegex.cap(1).toInt(); + + // 改进的重复检查:基于信号值和时间戳的组合,避免相同信号值被误判为重复 + // 只有在短时间内收到完全相同的数据包才认为是重复 + static QString lastProcessedData; + static qint64 lastProcessedTime = 0; + qint64 currentTime = QDateTime::currentMSecsSinceEpoch(); + + // 如果是相同的数据且时间间隔小于100ms,则认为是重复数据 + if (data.trimmed() == lastProcessedData && (currentTime - lastProcessedTime) < 100) { + qDebug() << "跳过重复的CAT1数据(时间间隔:" << (currentTime - lastProcessedTime) << "ms)"; + return; + } + + // 更新最后处理的数据和时间 + lastProcessedData = data.trimmed(); + lastProcessedTime = currentTime; + + // 增加接收计数器 + cat1SignalReceivedCount++; + + qDebug() << "CAT1信号测试解析到signal值:" << signalValue << ",接收次数:" << cat1SignalReceivedCount << "/5"; + + // 将CAT1 signal值显示到界面 + ui->recvTextEdit->append(QString("CAT1 Signal值: %1 (%2/5)").arg(signalValue).arg(cat1SignalReceivedCount)); + + // 统计信号值(用于计算平均值) + if (signalValue == 99) { + cat1Signal99Count++; + // signal=99不计入平均值计算 + qDebug() << "CAT1信号值为99,无效信号次数:" << cat1Signal99Count << "/" << cat1SignalReceivedCount; + ui->statusbar->showMessage(QString("CAT1信号测试 (%1/5) 信号值:99 (无效信号)").arg(cat1SignalReceivedCount), 2000); + } else { + // 累加有效信号值用于计算平均值 + cat1SignalTotalValue += signalValue; + if (signalValue > 25) { + cat1SignalGoodCount++; + } + + // 计算当前平均值(排除signal=99的值) + int validCount = cat1SignalReceivedCount - cat1Signal99Count; + double averageSignal = validCount > 0 ? (double)cat1SignalTotalValue / validCount : 0; + + qDebug() << "CAT1信号值" << signalValue << ",累计总和:" << cat1SignalTotalValue << ",当前平均值:" << averageSignal << ",有效次数:" << validCount << "/" << cat1SignalReceivedCount; + ui->statusbar->showMessage(QString("CAT1信号测试 (%1/5) 信号值:%2 平均值:%3").arg(cat1SignalReceivedCount).arg(signalValue).arg(averageSignal, 0, 'f', 1), 2000); + } + } else { + qDebug() << "CAT1信号测试未能解析signal值,数据:" << data.trimmed(); + } +} + +// 执行4G信号质量测试 +void MainWindow::perform4GSignalTest() +{ + if (!isProductionTestRunning || currentTestStep != TEST_PPP_SIGNAL) { + return; + } + + qDebug() << "开始4G信号质量测试"; + ui->statusbar->showMessage("4G信号质量测试中...", 5000); + + // 根据MODEM类型选择不同的测试方式 + if (isEGModem()) { + qDebug() << "检测到EG系列MODEM,使用CAT1信号测试方式"; + // EG系列MODEM:等待接收到第一次signal值后启动CAT1测试 + // 这里不需要主动发送指令,等待设备自动发送包含signal的数据 + ui->statusbar->showMessage("等待CAT1信号数据...", 5000); + + // 启动超时检测,如果长时间没有收到signal数据则失败 + signal4GTimer->start(10000); // 10秒超时 + qDebug() << "启动CAT1信号等待超时检测(10秒)"; + } else { + qDebug() << "检测到非EG系列MODEM,使用传统PPPSIGNALINFO测试方式"; + // 重置计数器 + signalTest4GCount = 0; + signalReceived4GCount = 0; + signalGood4GCount = 0; + + // 立即发送第一次信号检测指令 + serial->write("AT^PPPSIGNALINFO\r\n"); + qDebug() << "发送4G信号检测指令: AT^PPPSIGNALINFO"; + signalTest4GCount++; + + // 启动5秒定时器,定期检测信号质量 + signal4GTimer->start(5000); + qDebug() << "启动4G信号检测定时器(5秒间隔)"; + } +} + +// 4G信号检测定时器槽函数 +void MainWindow::on4GSignalTimer() +{ + if (!isProductionTestRunning || currentTestStep != TEST_PPP_SIGNAL) { + signal4GTimer->stop(); + return; + } + + if (isEGModem()) { + // EG系列MODEM:超时处理,如果长时间没有收到CAT1信号数据则失败 + signal4GTimer->stop(); + qDebug() << "EG系列MODEM等待CAT1信号数据超时,测试失败"; + ui->statusbar->showMessage("等待CAT1信号数据超时,测试失败", 5000); + + // 显示4G重复测试弹窗 + if (isProductionTestRunning) { + show4GRetryDialog("等待CAT1信号数据超时"); + } else { + updateTestStatus("ppp", STATUS_FAILED); + } + } else { + // 非EG系列MODEM:继续发送PPPSIGNALINFO指令 + serial->write("AT^PPPSIGNALINFO\r\n"); + qDebug() << "定时发送4G信号检测指令: AT^PPPSIGNALINFO (第" << (signalTest4GCount + 1) << "次)"; + signalTest4GCount++; + + // 如果发送次数过多,停止测试并失败 + if (signalTest4GCount >= 10) { // 最多发送10次指令 (约30秒) + signal4GTimer->stop(); + qDebug() << "4G信号检测发送10次指令,未收到足够有效数据,测试失败"; + ui->statusbar->showMessage("4G信号检测超时,测试失败", 5000); + + // 显示4G重复测试弹窗 + if (isProductionTestRunning) { + show4GRetryDialog("4G信号检测超时"); + } else { + updateTestStatus("ppp", STATUS_FAILED); + } + } + } +} + +// CAT1信号测试定时器槽函数 +void MainWindow::onCat1SignalTimer() +{ + if (!isProductionTestRunning || !hasReceivedFirstSignal) { + cat1SignalTimer->stop(); + return; + } + + // 检查是否已经接收到5次响应 + if (cat1SignalReceivedCount >= 5) { + cat1SignalTimer->stop(); + + // 计算平均信号值并判断测试结果 + int validCount = cat1SignalReceivedCount - cat1Signal99Count; + double averageSignal = validCount > 0 ? (double)cat1SignalTotalValue / validCount : 0; + + qDebug() << "CAT1信号测试完成,统计结果:"; + qDebug() << " 发送指令次数:" << cat1SignalTestCount; + qDebug() << " 接收响应次数:" << cat1SignalReceivedCount; + qDebug() << " 有效信号次数:" << validCount; + qDebug() << " 无效信号(99)次数:" << cat1Signal99Count; + qDebug() << " 信号值总和:" << cat1SignalTotalValue; + qDebug() << " 平均信号值:" << averageSignal; + + if (cat1Signal99Count >= 5) { + // 连续5次都是99,判定为失败 + qDebug() << "CAT1信号测试失败,5次测试均为无效信号值99"; + ui->statusbar->showMessage("CAT1信号测试失败 - 连续5次无效信号值(99)", 3000); + + // 停止CAT1定时器 + cat1SignalTimer->stop(); + + // 显示4G重复测试弹窗 + if (isProductionTestRunning) { + show4GRetryDialog("连续5次无效信号值(99)"); + } else { + updateTestStatus("ppp", STATUS_FAILED); + } + } else if (validCount > 0 && averageSignal >= 25.0) { + // 平均信号值大于等于25,判定为通过 + qDebug() << "CAT1信号测试通过,平均信号值" << averageSignal << "大于等于25"; + ui->statusbar->showMessage(QString("CAT1信号测试通过 - 平均信号值:%1").arg(averageSignal, 0, 'f', 1), 3000); + updateTestStatus("ppp", STATUS_SUCCESS); + + // 完成产测 + if (isProductionTestRunning) { + currentTestStep = TEST_COMPLETED; + isProductionTestRunning = false; + qDebug() << "CAT1信号测试通过,产测流程完成"; + + // 保存测试记录 + QString fileName = saveTestRecord(); + + // 显示最终测试结果弹窗 + showFinalTestResult(); + } + } else { + // 平均信号值小于25或没有有效数据,判定为失败 + QString failReason; + if (validCount == 0) { + failReason = "没有有效信号数据"; + } else { + failReason = QString("平均信号值%1小于25").arg(averageSignal, 0, 'f', 1); + } + + qDebug() << "CAT1信号测试失败," << failReason; + ui->statusbar->showMessage(QString("CAT1信号测试失败 - %1").arg(failReason), 3000); + + // 停止CAT1定时器 + cat1SignalTimer->stop(); + + // 显示4G重复测试弹窗 + if (isProductionTestRunning) { + show4GRetryDialog(failReason); + } else { + updateTestStatus("ppp", STATUS_FAILED); + } + } + return; + } + + // 根据MODEM类型发送不同的信号检测指令 + if (isEGModem()) { + // EG系列MODEM使用CAT1GETSIGNAL指令 + serial->write("AT^CAT1GETSIGNAL\r\n"); + cat1SignalTestCount++; + qDebug() << "发送第" << cat1SignalTestCount << "次CAT1信号检测指令: AT^CAT1GETSIGNAL (EG系列MODEM)"; + } else { + // N7系列或其他MODEM使用PPPSIGNALINFO指令 + serial->write("AT^PPPSIGNALINFO\r\n"); + cat1SignalTestCount++; + qDebug() << "发送第" << cat1SignalTestCount << "次信号检测指令: AT^PPPSIGNALINFO (非EG系列MODEM)"; + } +} + +// 检查4G信号质量结果 +void MainWindow::check4GSignalResult(const QString& data) +{ + if (!isProductionTestRunning || currentTestStep != TEST_PPP_SIGNAL) { + return; + } + + // 如果已经启动了CAT1信号测试,则不再使用旧的4G信号测试逻辑 + if (hasReceivedFirstSignal) { + qDebug() << "已启动CAT1信号测试,跳过旧的4G信号测试逻辑"; + return; + } + + qDebug() << "4G信号检测收到数据:" << data.trimmed(); + + // 保存静态变量来跟踪RSRQ和RSRP值 + static double currentRsrq = -6.8; // 默认示例值 + static double currentRsrp = -82; // 默认示例值 + static int rsrqRaw = 26; // 原始RSRQ值 + static int rsrpRaw = 58; // 原始RSRP值 + static bool rsrqReceived = false; + static bool rsrpReceived = false; + + // 解析APP|[PPP] RSRQ格式 + QRegExp appRsrqPattern("APP\\|\\[PPP\\]\\s*RSRQ:\\s*(\\d+)\\s*\\(([\\d\\.-]+)\\s*dB\\)"); + if (appRsrqPattern.indexIn(data) != -1) { + rsrqRaw = appRsrqPattern.cap(1).toInt(); + currentRsrq = appRsrqPattern.cap(2).toDouble(); + rsrqReceived = true; + qDebug() << "解析到APP|[PPP] RSRQ值:" << rsrqRaw << "(" << currentRsrq << "dB)"; + + // 输出RSRQ评级(按要求格式) + QString rsrqGrade = getRsrqGrade(currentRsrq); + QString rsrqOutput = QString("RSRQ: %1 (%2 dB:%3)").arg(rsrqRaw).arg(currentRsrq).arg(rsrqGrade); + qDebug() << rsrqOutput; + ui->recvTextEdit->insertPlainText(rsrqOutput + "\n"); + ui->recvTextEdit->moveCursor(QTextCursor::End); + return; // 每行单独处理 + } + + // 解析APP|[PPP] RSRP格式 + QRegExp appRsrpPattern("APP\\|\\[PPP\\]\\s*RSRP:\\s*(\\d+)\\s*\\(([\\d\\.-]+)\\s*dBm\\)"); + if (appRsrpPattern.indexIn(data) != -1) { + rsrpRaw = appRsrpPattern.cap(1).toInt(); + currentRsrp = appRsrpPattern.cap(2).toDouble(); + rsrpReceived = true; + qDebug() << "解析到APP|[PPP] RSRP值:" << rsrpRaw << "(" << currentRsrp << "dBm)"; + + // 输出RSRP评级(按要求格式) + QString rsrpGrade = getRsrpGrade(currentRsrp); + QString rsrpOutput = QString("RSRP: %1 (%2 dBm:%3)").arg(rsrpRaw).arg(currentRsrp).arg(rsrpGrade); + qDebug() << rsrpOutput; + ui->recvTextEdit->insertPlainText(rsrpOutput + "\n"); + ui->recvTextEdit->moveCursor(QTextCursor::End); + return; // 每行单独处理 + } + + // 解析Overall LTE Quality格式 + if (data.contains("APP|[PPP] Overall LTE Quality:") || data.contains("总体评级:")) { + // 收到一次有效的信号质量数据 + signalReceived4GCount++; + qDebug() << "收到第" << signalReceived4GCount << "次有效4G信号数据"; + + // 如果还没收到RSRQ和RSRP,使用模拟数据进行示例显示 + if (!rsrqReceived) { + QString rsrqGrade = getRsrqGrade(currentRsrq); + QString rsrqOutput = QString("RSRQ: %1 (%2 dB:%3)").arg(rsrqRaw).arg(currentRsrq).arg(rsrqGrade); + qDebug() << "模拟RSRQ输出:" << rsrqOutput; + ui->recvTextEdit->insertPlainText(rsrqOutput + "\n"); + ui->recvTextEdit->moveCursor(QTextCursor::End); + } + + if (!rsrpReceived) { + QString rsrpGrade = getRsrpGrade(currentRsrp); + QString rsrpOutput = QString("RSRP: %1 (%2 dBm:%3)").arg(rsrpRaw).arg(currentRsrp).arg(rsrpGrade); + qDebug() << "模拟RSRP输出:" << rsrpOutput; + ui->recvTextEdit->insertPlainText(rsrpOutput + "\n"); + ui->recvTextEdit->moveCursor(QTextCursor::End); + } + + // 输出完整的信号评估 + QString overallAssessment = getOverallSignalAssessment(currentRsrp, currentRsrq); + QString overallOutput = QString("总体评级:%1").arg(overallAssessment); + qDebug() << overallOutput; + ui->recvTextEdit->insertPlainText(overallOutput + "\n"); + ui->recvTextEdit->moveCursor(QTextCursor::End); + + // 检查信号质量是否良好以上 + bool rsrpGood = data.contains("覆盖极好") || data.contains("覆盖良好") || + overallAssessment.contains("覆盖强度极好") || overallAssessment.contains("覆盖强度良好"); + bool rsrqGood = data.contains("质量极佳") || data.contains("质量良好") || + overallAssessment.contains("信号质量极佳") || overallAssessment.contains("信号质量良好"); + bool isSignalGood = rsrpGood && rsrqGood; + + qDebug() << "信号质量检查: RSRP良好以上=" << rsrpGood << ", RSRQ良好以上=" << rsrqGood << ", 综合判断=" << isSignalGood; + + if (data.contains("LTE信号良好") || isSignalGood) { + signalGood4GCount++; + qDebug() << "检测到LTE信号良好以上,当前良好次数:" << signalGood4GCount << "/5,已接收数据次数:" << signalReceived4GCount << "/5"; + ui->statusbar->showMessage(QString("LTE信号良好 (%1/5) 数据(%2/5)").arg(signalGood4GCount).arg(signalReceived4GCount), 2000); + } else { + qDebug() << "LTE信号质量不达标(需要良好以上),已接收数据次数:" << signalReceived4GCount << "/5"; + ui->statusbar->showMessage(QString("LTE信号质量不达标 数据(%1/5)").arg(signalReceived4GCount), 2000); + } + + // 检查是否已收到5次数据 + if (signalReceived4GCount >= 5) { + signal4GTimer->stop(); + + if (signalGood4GCount >= 5) { + // 5次数据都是良好以上,测试通过 + qDebug() << "5次4G信号数据都达到良好以上标准,测试通过"; + ui->statusbar->showMessage("4G信号测试通过 - 5次信号都达到良好以上!", 5000); + updateTestStatus("ppp", STATUS_SUCCESS); + } else { + // 有信号质量不达标,测试失败 + qDebug() << "4G信号测试失败 - 只有" << signalGood4GCount << "次达到良好以上标准"; + ui->statusbar->showMessage(QString("4G信号测试失败 - 只有%1次达到良好标准").arg(signalGood4GCount), 5000); + updateTestStatus("ppp", STATUS_FAILED); + } + + // 完成产测 + currentTestStep = TEST_COMPLETED; + isProductionTestRunning = false; + qDebug() << "产测流程完成"; + + // 保存测试记录 + QString fileName = saveTestRecord(); + + // 显示最终测试结果弹窗 + showFinalTestResult(); + } + + // 重置状态标志,为下次检测准备 + rsrqReceived = false; + rsrpReceived = false; + } +} + +// 获取RSRQ信号质量评级 +QString MainWindow::getRsrqGrade(double rsrq) +{ + QString grade; + QString description; + + if (rsrq >= -7 && rsrq <= -3) { + grade = "质量极佳"; + description = "(干扰极小)"; + } else if (rsrq >= -12 && rsrq < -7) { + grade = "质量良好"; + description = "(轻微干扰,不影响使用)"; + } else if (rsrq >= -19.5 && rsrq < -12) { + grade = "质量较差"; + description = "(干扰明显,可能掉速)"; + } else if (rsrq < -19.5) { + grade = "质量极差"; + description = "(无法正常通信)"; + } else { + grade = "数值异常"; + description = "(超出正常范围)"; + } + + return QString("%1 %2").arg(grade, description); +} + +// 获取RSRP信号覆盖强度评级 +QString MainWindow::getRsrpGrade(double rsrp) +{ + QString grade; + QString description; + + if (rsrp >= -85 && rsrp <= -44) { + grade = "覆盖极好"; + description = "(满格信号)"; + } else if (rsrp >= -100 && rsrp < -85) { + grade = "覆盖良好"; + description = "(稳定通信)"; + } else if (rsrp >= -110 && rsrp < -100) { + grade = "覆盖较弱"; + description = "(可能掉速)"; + } else if (rsrp >= -140 && rsrp < -110) { + grade = "覆盖极差"; + description = "(频繁断连)"; + } else { + grade = "数值异常"; + description = "(超出正常范围)"; + } + + return QString("%1 %2").arg(grade, description); +} + +// 获取整体信号评估 +QString MainWindow::getOverallSignalAssessment(double rsrp, double rsrq) +{ + QString rsrpGrade, rsrqGrade; + + // 简化的等级判断 + if (rsrp >= -85) { + rsrpGrade = "极好"; + } else if (rsrp >= -100) { + rsrpGrade = "良好"; + } else if (rsrp >= -110) { + rsrpGrade = "较弱"; + } else { + rsrpGrade = "极差"; + } + + if (rsrq >= -7) { + rsrqGrade = "极佳"; + } else if (rsrq >= -12) { + rsrqGrade = "良好"; + } else if (rsrq >= -19.5) { + rsrqGrade = "较差"; + } else { + rsrqGrade = "极差"; + } + + // 综合评估 + QString assessment; + if ((rsrpGrade == "极好" || rsrpGrade == "良好") && (rsrqGrade == "极佳" || rsrqGrade == "良好")) { + assessment = "完全满足4G高清通话、高速上网等业务的稳定接入需求"; + } else if (rsrpGrade == "较弱" || rsrqGrade == "较差") { + assessment = "网络性能可能受影响,建议移动到信号更好的位置"; + } else { + assessment = "信号质量不佳,可能影响正常通信"; + } + + return QString("覆盖强度%1,信号质量%2。%3").arg(rsrpGrade, rsrqGrade, assessment); +} + +// 显示最终测试结果弹窗 +// 显示电池充电失败弹窗 +void MainWindow::showBatteryChargeFailDialog() +{ + QMessageBox chargeFailDialog(this); + chargeFailDialog.setWindowTitle("电池测试失败"); + chargeFailDialog.setText("⚠️ 电池测试失败"); + chargeFailDialog.setInformativeText("检测到设备未充电(charge = 0)\n请连接充电器后重新测试"); + chargeFailDialog.setIcon(QMessageBox::Warning); + + // 添加自定义按钮 + QPushButton *confirmButton = chargeFailDialog.addButton("确认", QMessageBox::AcceptRole); + QPushButton *retryButton = chargeFailDialog.addButton("重新获取", QMessageBox::ActionRole); + + chargeFailDialog.exec(); + + if (chargeFailDialog.clickedButton() == confirmButton) { + qDebug() << "用户确认电池充电失败,标记测试失败"; + updateTestStatus("battery", STATUS_FAILED); + + // ç»§ç»­G-sensor测试 + if (isProductionTestRunning && currentTestStep == TEST_BATTERY) { + qDebug() << "电池测试失败确认,继续G-sensor测试"; + currentTestStep = TEST_GSENSOR; + performGsensorTest(); + } + } else if (chargeFailDialog.clickedButton() == retryButton) { + qDebug() << "用户选择重新获取电池信息"; + ui->statusbar->showMessage("重新获取电池信息...", 2000); + + // 重新发送电池测试指令 + serial->write("AT^GETCYWEEID\r\n"); + qDebug() << "重新发送电池测试指令: AT^GETCYWEEID"; + + // 重新启动超时检测 + testTimeoutTimer->start(10000); + } +} + +// 显示4G重复测试弹窗 +void MainWindow::show4GRetryDialog(const QString& failReason) +{ + QMessageBox retryDialog(this); + retryDialog.setWindowTitle("4G测试失败"); + retryDialog.setText("📶 4G信号测试失败"); + + // 构建详细的失败信息,包括SIM卡状态 + QString detailedInfo = QString("测试失败原因:%1").arg(failReason); + + // 添加SIM卡状态信息 + if (currentSimStatus == 0) { + detailedInfo += "\n\n⚠️ SIM卡状态:未插入"; + detailedInfo += "\n请插入SIM卡后重新测试"; + } else if (currentSimStatus == 1) { + detailedInfo += "\n\n✅ SIM卡状态:已插入"; + } else { + detailedInfo += "\n\n❓ SIM卡状态:未知"; + } + + detailedInfo += "\n\n是否重新进行4G测试?"; + + retryDialog.setInformativeText(detailedInfo); + retryDialog.setIcon(QMessageBox::Warning); + + // 添加自定义按钮 + QPushButton *retryButton = retryDialog.addButton("重新测试", QMessageBox::AcceptRole); + QPushButton *skipButton = retryDialog.addButton("跳过测试", QMessageBox::RejectRole); + + retryDialog.exec(); + + if (retryDialog.clickedButton() == retryButton) { + qDebug() << "用户选择重新进行4G测试"; + ui->statusbar->showMessage("重新开始4G测试...", 2000); + + // 重置4G测试状态 + hasReceivedFirstSignal = false; + cat1SignalTestCount = 0; + cat1SignalReceivedCount = 0; + cat1SignalGoodCount = 0; + cat1Signal99Count = 0; + cat1SignalTotalValue = 0; + // 移除了cat1ProcessedSignals的清理,改用时间戳方式 + + // 重置4G测试计数器,确保重新测试时从头开始 + initRetry4GCount = 0; + signalTest4GCount = 0; + signalReceived4GCount = 0; + signalGood4GCount = 0; + pppCommandCount = 0; + hasReceivedSignalSim = false; + hasReceivedPppInfo = false; + currentSimStatus = -1; // 重置SIM卡状态为未知 + + // 停止所有4G相关定时器 + if (cat1SignalTimer->isActive()) { + cat1SignalTimer->stop(); + } + if (signal4GTimer->isActive()) { + signal4GTimer->stop(); + } + if (test4GTimer->isActive()) { + test4GTimer->stop(); + } + + // 重新开始4G测试 + updateTestStatus("ppp", STATUS_TESTING); + currentTestStep = TEST_PPP_INIT; + perform4GTest(); + + } else if (retryDialog.clickedButton() == skipButton) { + qDebug() << "用户选择跳过4G测试,标记测试失败"; + updateTestStatus("ppp", STATUS_FAILED); + + // 停止所有4G相关定时器,确保测试完全停止 + if (cat1SignalTimer->isActive()) { + cat1SignalTimer->stop(); + qDebug() << "停止CAT1信号测试定时器"; + } + if (signal4GTimer->isActive()) { + signal4GTimer->stop(); + qDebug() << "停止4G信号检测定时器"; + } + if (test4GTimer->isActive()) { + test4GTimer->stop(); + qDebug() << "停止4G测试超时定时器"; + } + + // 重置4G测试相关状态 + hasReceivedFirstSignal = false; + hasReceivedSignalSim = false; + hasReceivedPppInfo = false; + + // 完成产测(失败) + if (isProductionTestRunning) { + currentTestStep = TEST_COMPLETED; + isProductionTestRunning = false; + qDebug() << "用户跳过4G测试,产测流程完成"; + + // 保存测试记录 + QString fileName = saveTestRecord(); + + // 显示最终测试结果弹窗 + showFinalTestResult(); + } + } +} + +void MainWindow::showFinalTestResult() +{ + // 获取各项测试结果 + QString lcdResult = ui->lcdStatusText->text(); + QString motorResult = ui->motorStatusText->text(); + QString keyResult = ui->keyStatusText->text(); + QString audioResult = ui->audioStatusText->text(); + QString batteryResult = ui->batteryStatusText->text(); + QString gsensorResult = ui->gsensorStatusText->text(); + QString pppResult = ui->pppStatusText->text(); + QString overallResult = ui->overallStatusText->text(); + + // 创建结果弹窗 + QMessageBox resultDialog(this); + resultDialog.setWindowTitle("产测结果"); + + // 构建结果内容 + QString resultContent = QString( + "===== 产测完成 =====\n\n" + "📱 LCD测试:%1\n" + "🔧 马达测试:%2\n" + "⌨️ 按键测试:%3\n" + "🎤 录音测试:%4\n" + "🔋 电池测试:%5\n" + "📡 G-sensor测试:%6\n" + "🌐 4G测试:%7\n\n" + "📊 整体结果:%8" + ).arg(lcdResult, motorResult, keyResult, audioResult, + batteryResult, gsensorResult, pppResult, overallResult); + + resultDialog.setText(resultContent); + + // 设置图标和按钮 + if (overallResult == "通过") { + resultDialog.setIcon(QMessageBox::Information); + resultDialog.setInformativeText("🎉 恭喜!所有测试项目均通过!"); + } else { + resultDialog.setIcon(QMessageBox::Critical); + resultDialog.setInformativeText("❌ 测试未通过,请检查相关项目。"); + } + + // 添加确定按钮 + QPushButton *okButton = resultDialog.addButton("确定", QMessageBox::AcceptRole); + okButton->setStyleSheet( + "QPushButton { " + "background-color: #4CAF50; " + "color: white; " + "padding: 10px 20px; " + "border-radius: 5px; " + "font-weight: bold; " + "font-size: 16px; " + "min-width: 80px; " + "}" + "QPushButton:hover { " + "background-color: #45a049; " + "}" + ); + + // 设置弹窗样式 + resultDialog.setStyleSheet( + "QMessageBox { " + "background-color: #f8f9fa; " + "}" + "QMessageBox QLabel { " + "font-size: 14px; " + "line-height: 1.4; " + "}" + ); + + // 显示弹窗 + qDebug() << "显示最终测试结果弹窗"; + resultDialog.exec(); + + // 用户点击确定后的处理 + qDebug() << "用户确认测试结果,发送退出产测指令"; + + // 发送退出产测指令 + if (serial->isOpen()) { + serial->write("AT^RESTORE\r\n"); + qDebug() << "发送退出产测指令: AT^RESTORE"; + ui->statusbar->showMessage("已退出产测模式", 3000); + } + + // 恢复产测按钮状态 - 变回蓝色并启用 + ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }"); + ui->openButton_2->setEnabled(true); + qDebug() << "产测完成 - 按钮已恢复蓝色并启用"; + + // 清空整个产测状态 + clearProductionTestState(); + + qDebug() << "产测流程完全结束,状态已清空"; +} + +// 通用测试超时处理 +void MainWindow::onTestTimeout() +{ + testTimeoutTimer->stop(); + + if (!isProductionTestRunning) { + qDebug() << "测试超时但产测未运行,忽略"; + return; + } + + QString testName; + QString testDescription; + + // 根据当前测试步骤确定测试名称 + switch (currentTestStep) { + case TEST_RESET: + // 工厂模式进入超时 + qDebug() << "工厂模式进入超时,未收到确认消息"; + ui->statusbar->showMessage("工厂模式进入超时,请检查设备", 5000); + + QMessageBox::warning(this, "工厂模式超时", + "未收到工厂模式进入确认消息:\n'fac:enter or exit facotry mode'\n\n请检查设备连接和状态"); + + // 停止产测 + isProductionTestRunning = false; + currentTestStep = TEST_IDLE; + return; + + case TEST_MOTOR: + testName = "motor"; + testDescription = "马达测试"; + break; + case TEST_BATTERY: + testName = "battery"; + testDescription = "电池测试"; + break; + case TEST_GSENSOR: + testName = "gsensor"; + testDescription = "G-sensor测试"; + break; + default: + qDebug() << "未知的测试步骤超时:" << currentTestStep; + return; + } + + qDebug() << testDescription << "超时,10秒内未收到响应"; + + // 弹出超时提示对话框 + QMessageBox timeoutDialog(this); + timeoutDialog.setWindowTitle("测试超时"); + timeoutDialog.setIcon(QMessageBox::Warning); + timeoutDialog.setText(QString("%1开启失败").arg(testDescription)); + timeoutDialog.setInformativeText("10秒内未收到设备响应,请检查机器。"); + + QPushButton *retryButton = timeoutDialog.addButton("重试", QMessageBox::AcceptRole); + QPushButton *skipButton = timeoutDialog.addButton("跳过", QMessageBox::RejectRole); + QPushButton *stopButton = timeoutDialog.addButton("停止测试", QMessageBox::DestructiveRole); + + // 设置按钮样式 + retryButton->setStyleSheet( + "QPushButton { " + "background-color: #4CAF50; " + "color: white; " + "padding: 10px 15px; " + "border-radius: 4px; " + "font-weight: bold; " + "}" + ); + + skipButton->setStyleSheet( + "QPushButton { " + "background-color: #FF9800; " + "color: white; " + "padding: 10px 15px; " + "border-radius: 4px; " + "font-weight: bold; " + "}" + ); + + stopButton->setStyleSheet( + "QPushButton { " + "background-color: #f44336; " + "color: white; " + "padding: 10px 15px; " + "border-radius: 4px; " + "font-weight: bold; " + "}" + ); + + timeoutDialog.exec(); + + if (timeoutDialog.clickedButton() == retryButton) { + // 用户选择重试 + qDebug() << "用户选择重试" << testDescription; + ui->statusbar->showMessage(QString("重试%1").arg(testDescription), 2000); + + // 先发送停止指令,然后重新开始测试 + qDebug() << "重试前发送停止指令"; + serial->write("AT^VIBRATORTIMER=0\r\n"); // 停止马达 + serial->write("AT^LCDTEST=2\r\n"); // 退出LCD测试 + + // 延迟500ms后重新开始测试 + QTimer::singleShot(500, this, [this, testDescription]() { + qDebug() << "停止指令已发送,开始重试" << testDescription; + + // 根据测试类型重新开始测试 + switch (currentTestStep) { + case TEST_MOTOR: + performMotorTest(); + break; + case TEST_BATTERY: + performBatteryTest(); + break; + case TEST_GSENSOR: + performGsensorTest(); + break; + default: + break; + } + }); + + } else if (timeoutDialog.clickedButton() == skipButton) { + // 用户选择跳过,标记为失败并继续下一个测试 + qDebug() << "用户选择跳过" << testDescription; + ui->statusbar->showMessage(QString("%1已跳过").arg(testDescription), 2000); + updateTestStatus(testName, STATUS_FAILED); + + // 继续下一个测试 + switch (currentTestStep) { + case TEST_MOTOR: + currentTestStep = TEST_KEY; + performKeyTest(); + break; + case TEST_BATTERY: + currentTestStep = TEST_GSENSOR; + performGsensorTest(); + break; + case TEST_GSENSOR: + { + // G-sensor测试超时,继续4G测试 + qDebug() << "G-sensor测试超时,继续4G测试"; + updateTestStatus("gsensor", STATUS_FAILED); + currentTestStep = TEST_PPP_INIT; + perform4GTest(); + break; + } + default: + break; + } + + } else { + // 用户选择停止测试 + qDebug() << "用户选择停止测试"; + ui->statusbar->showMessage("测试已停止", 2000); + updateTestStatus(testName, STATUS_FAILED); + + // 停止产测 + isProductionTestRunning = false; + currentTestStep = TEST_IDLE; + + // 保存测试记录并显示结果 + QString fileName = saveTestRecord(); + showFinalTestResult(); + } +} + +// 清空产测状态 +void MainWindow::clearProductionTestState() +{ + qDebug() << "开始清空产测状态"; + + // 停止所有定时器 + if (lcdTestTimer->isActive()) { + lcdTestTimer->stop(); + qDebug() << "停止LCD测试定时器"; + } + + if (motorTestTimer->isActive()) { + motorTestTimer->stop(); + qDebug() << "停止马达测试定时器"; + } + + if (test4GTimer->isActive()) { + test4GTimer->stop(); + qDebug() << "停止4G测试定时器"; + } + + if (signal4GTimer->isActive()) { + signal4GTimer->stop(); + qDebug() << "停止4G信号检测定时器"; + } + + if (cat1SignalTimer->isActive()) { + cat1SignalTimer->stop(); + qDebug() << "停止CAT1信号测试定时器"; + } + + if (testTimeoutTimer->isActive()) { + testTimeoutTimer->stop(); + qDebug() << "停止通用超时定时器"; + } + + // 重置产测状态变量 + isProductionTestRunning = false; + currentTestStep = TEST_IDLE; + currentLcdColor = 0; + initRetry4GCount = 0; + signalTest4GCount = 0; + signalReceived4GCount = 0; + signalGood4GCount = 0; + hasReceivedFirstSignal = false; + cat1SignalTestCount = 0; + cat1SignalReceivedCount = 0; + cat1SignalGoodCount = 0; + cat1Signal99Count = 0; + cat1SignalTotalValue = 0; + // 移除了cat1ProcessedSignals的清理,改用时间戳方式 + currentModemVersion = ""; // 初始化MODEM版本为空 + currentSimStatus = -1; // 重置SIM卡状态为未知 + + // 重置弹窗状态 + lcdTestPopupShown = false; + motorTestPopupShown = false; + isWaitingForUserConfirm = false; + keyTestStarted = false; + audioTestPopupShown = false; + audioPlaybackPopupShown = false; + + // 重置按键测试状态 + for (int i = 0; i < 4; i++) { + keyTestStatus[i] = 0; + } + + // 清空状态指示器 - 重置为未测试状态 + updateTestStatus("lcd", STATUS_UNTESTED); + updateTestStatus("motor", STATUS_UNTESTED); + updateTestStatus("key", STATUS_UNTESTED); + updateTestStatus("audio", STATUS_UNTESTED); + updateTestStatus("battery", STATUS_UNTESTED); + updateTestStatus("gsensor", STATUS_UNTESTED); + updateTestStatus("ppp", STATUS_UNTESTED); + + // 清空串口接收文本框 + ui->recvTextEdit->clear(); + qDebug() << "已清空串口接收文本框"; + + qDebug() << "产测状态清空完成"; +} + +void MainWindow::on_agingTestButton_clicked() +{ + // 清空所有UI内容 + ui->recvTextEdit->clear(); // 清空串口接收文本框 + ui->sendTextEdit->clear(); // 清空发送文本框 + ui->statusbar->clearMessage(); // 清空状态栏 + + // 清空设备信息 + ui->VerlineEdit->clear(); // 清空版本信息 + ui->IMEIlineEdit->clear(); // 清空IMEI + ui->ICCIDlineEdit->clear(); // 清空ICCID + ui->ModemVerlineEdit->clear(); // 清空调制解调器版本 + ui->PYVerlineEdit->clear(); // 清空python版本 + + // 重置弹窗状态 + lcdTestPopupShown = false; + motorTestPopupShown = false; + isWaitingForUserConfirm = false; + keyTestStarted = false; + audioTestPopupShown = false; + audioPlaybackPopupShown = false; + + // 重置状态指示器 + updateTestStatus("lcd", STATUS_UNTESTED); + updateTestStatus("motor", STATUS_UNTESTED); + updateTestStatus("key", STATUS_UNTESTED); + updateTestStatus("audio", STATUS_UNTESTED); + updateTestStatus("battery", STATUS_UNTESTED); + updateTestStatus("gsensor", STATUS_UNTESTED); + updateTestStatus("ppp", STATUS_UNTESTED); + serial->write("AT^FACTORY=2\r\n"); +} + +void MainWindow::on_agingTestButton_2_clicked() +{ + // 清空所有UI内容 + ui->recvTextEdit->clear(); // 清空串口接收文本框 + ui->sendTextEdit->clear(); // 清空发送文本框 + ui->statusbar->clearMessage(); // 清空状态栏 + + // 清空设备信息 + ui->VerlineEdit->clear(); // 清空版本信息 + ui->IMEIlineEdit->clear(); // 清空IMEI + ui->ICCIDlineEdit->clear(); // 清空ICCID + ui->ModemVerlineEdit->clear(); // 清空调制解调器版本 + ui->PYVerlineEdit->clear(); // 清空python版本 + + // 重置弹窗状态 + lcdTestPopupShown = false; + motorTestPopupShown = false; + isWaitingForUserConfirm = false; + keyTestStarted = false; + audioTestPopupShown = false; + audioPlaybackPopupShown = false; + + // 重置状态指示器 + updateTestStatus("lcd", STATUS_UNTESTED); + updateTestStatus("motor", STATUS_UNTESTED); + updateTestStatus("key", STATUS_UNTESTED); + updateTestStatus("audio", STATUS_UNTESTED); + updateTestStatus("battery", STATUS_UNTESTED); + updateTestStatus("gsensor", STATUS_UNTESTED); + updateTestStatus("ppp", STATUS_UNTESTED); + + serial->write("AT^RESTORE\r\n"); +} + +void MainWindow::on_openButton_3_clicked() +{ + // 清空所有UI内容 + ui->recvTextEdit->clear(); // 清空串口接收文本框 + ui->sendTextEdit->clear(); // 清空发送文本框 + ui->statusbar->clearMessage(); // 清空状态栏 + + // 清空设备信息 + ui->VerlineEdit->clear(); // 清空版本信息 + ui->IMEIlineEdit->clear(); // 清空IMEI + ui->ICCIDlineEdit->clear(); // 清空ICCID + ui->ModemVerlineEdit->clear(); // 清空调制解调器版本 + ui->PYVerlineEdit->clear(); // 清空python版本 + + // 重置弹窗状态 + lcdTestPopupShown = false; + motorTestPopupShown = false; + isWaitingForUserConfirm = false; + keyTestStarted = false; + audioTestPopupShown = false; + audioPlaybackPopupShown = false; + + // 重置状态指示器 + updateTestStatus("lcd", STATUS_UNTESTED); + updateTestStatus("motor", STATUS_UNTESTED); + updateTestStatus("key", STATUS_UNTESTED); + updateTestStatus("audio", STATUS_UNTESTED); + updateTestStatus("battery", STATUS_UNTESTED); + updateTestStatus("gsensor", STATUS_UNTESTED); + updateTestStatus("ppp", STATUS_UNTESTED); + + serial->write("AT^FACTORY=3\r\n"); +} diff --git a/mainwindow.h b/mainwindow.h index 8a58b37..2c87f27 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1,145 +1,196 @@ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include -#include -#include -#include -#include -#include -#include -#include "header.h" -#include "result_thread.h" -#include "common.h" -#include "at_data.h" -#include "QFileDialog" -#include "QMessageBox" -#include "QTime" - -#define COM_NUMBER 10 - -// 封装了UI上需要调用的所有函数接口 -QT_BEGIN_NAMESPACE -namespace Ui { -class MainWindow; -} -QT_END_NAMESPACE - -class MainWindow : public QMainWindow { - Q_OBJECT - -public: - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); - -private: - Ui::MainWindow *ui; - /* ------------------------uart------------------------------- */ - Result_Thread *result_thread; - // 是否忽略uart数据,不回显 - bool uart_rx_Ignoring_display {false}; - // 是否有uart通路数据上报 - bool uart_rx_flag {false}; - bool dongle_is_connected {false}; - int dongle_connected_times {0}; - QStringList uart_get_enable_comm_or_port(); - QString uart_get_comm_or_port(int nIndex, bool bValue); - void uart_open(QString com,QString com_band); - void uart_close(); - /* ------------------------spp-------------------------------- */ - QTimer *spp_timer_handle {NULL}; - QTimer *spp_connected_handle {NULL}; - int dongle_try_count {0}; - int spp_try_count {0}; - - /* -----------------------transmit---------------------------- */ - QStringList transmit_fromborad_local_list; - QStringList tansmit_fromborad_borad_list; - QStringList transmit_toboard_local_list; - QStringList transmit_toboard_borad_list; - typedef enum{ - TRANSMIT_IDLE, - TRANSMIT_DOWNLOAD, - TRANSMIT_UPLOAD, - }transmit_mode; - // download is 1,uplaod is 2 - transmit_mode transmit_download_or_upload {TRANSMIT_IDLE}; - QTimer *transmit_timer_handle {NULL}; - void transmit_progress_start(); - /* -------------------------UI------------------------------- */ - enum ui_page{ - PAGE_COMPLETE, - PAGE_BOARD, - }; - void ui_setting_save(); - void ui_setting_read(); - void ui_display(QString str,bool inOrOut); - /* -------------------------AT------------------------------- */ - At_Process *at_handler; - void at_check_send_status(bool flag); - void at_set_bt_format(); - bool bt_test_switch {false}; - /* ------------------------end------------------------------ */ - -private slots: - /* --------------------------UI------------------------------ */ - void ui_tab_mainwindow_complete(); - void ui_tab_mainwindow_board(); - void ui_save_windows(); - /* -------------------------uart----------------------------- */ - void uart_process(); - void uart_send_data(); - void uart_rx_dispaly(int buf_len, u8Piont buf); - void uart_check_dtr_rts(); - void uart_com_select(); - void uart_com_switch(QString com); - void uart_baud_switch(QString baud); - /* -------------------------spp------------------------------- */ - void spp_connect(); - void spp_timer_callback(); - void spp_connected_callback(); - void dongle_suspend(); - void dongle_resume(); - /* -----------------------at/transmit---------------------------- */ - void at_rx_display(int at_buf_len, u8Piont at_buf); - void at_stackinfo_send(); - void at_fsrm_send(); - void at_mediamusicplay_send(); - void at_mediamusicstop_send(); - void at_mediaaudiorecord_send(); - void at_custom_send(); - void transmit_ls_rx_diaplay(int transmit_ls_size, vPiont transmit_ls_buff); - void transmit_rx_display(bool transmit_result_flag); - void transmit_update_progress(); - void transmit_fromboard_name_change(); - void transmit_fromboard_selectfilepath(); - void transmit_fromboard_getfilelist(); - void transmit_fromboard_download(); - void transmit_fromboard_delete(); - void transmit_fromboard_stop(); - void transmit_toboard_choosefile(); - void transmit_toboard_upload(); - void transmit_toboard_stop(); - /* ----------------------- 耦合测试设置 --------------------------- */ - void at_set_dongle_addr_complete(); - void at_bt_delay_ms_complete(); - void at_check_bt_len(int packtype_index); - /* -----------------------耦合测试-整机段-------------------------- */ - void at_get_rx_count_complete(); - void at_bt_tx_complete(); // BT长发(非信令) - void at_bt_rx_complete(); // BT长收(非信令) - void at_ble_tx_complete(); // BLE长发(非信令) - void at_ble_rx_complete(); // BLE长收(非信令) - /* -----------------------传导测试-单板段-------------------------- */ - void at_bt_tx_board(); // BT长发(非信令) - void at_bt_rx_board(); // BT长收(非信令) - void at_ble_tx_board(); // BLE长发(非信令) - void at_ble_rx_board(); // BLE长收(非信令) - void at_bt_dutmode_board(); - void at_bt_btlo_board(); - void at_bt_btpwr_board(); - void at_bt_wakeup(); - void at_bt_sleep(); - /* ------------------------------------------------------------- */ -}; -#endif // MAINWINDOW_H +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +namespace Ui { class MainWindow; } +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + // 状态指示器枚举 + enum TestStatus { + STATUS_UNTESTED, // 未测试 + STATUS_TESTING, // 测试中 + STATUS_SUCCESS, // 通过 + STATUS_FAILED // 失败 + }; + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private slots: + void on_refreshButton_clicked(); // 刷新串口列表 + void on_openButton_clicked(); // 打开/关闭串口 + void on_sendButton_clicked(); // 发送数据 + void on_clearRecvButton_clicked(); // 清空接收区 + void on_clearSendButton_clicked(); // 清空发送区 + void readSerialData(); // 读取串口数据 + + void on_openButton_2_clicked(); + void on_openRecordsFolderButton_clicked(); // 打开记录文件夹 + + // 产测相关槽函数 + void on_ProductionTestButton_clicked(); // 开始产测 + void performLcdTest(); // LCD测试 + void performLcdColorTest(); // LCD颜色测试 + void performMotorTest(); // 马达测试 + void perform4GTest(); // 4G测试 + void perform4GSignalTest(); // 4G信号质量测试 + void onLcdTestTimer(); // LCD测试定时器 + void onMotorTestTimer(); // 马达测试定时器 + void on4GTestTimeout(); // 4G测试超时 + void on4GSignalTimer(); // 4G信号检测定时器 + void onTestTimeout(); // 通用测试超时处理 + void checkFactoryModeResult(const QString& data); // 检查工厂模式进入结果 + void check4GInitResult(const QString& data); // 检查4G初始化结果 + void check4GSignalResult(const QString& data); // 检查4G信号质量结果 + QString getRsrqGrade(double rsrq); // 获取RSRQ信号质量评级 + QString getRsrpGrade(double rsrp); // 获取RSRP信号覆盖强度评级 + QString getOverallSignalAssessment(double rsrp, double rsrq); // 获取整体信号评估 + void showFinalTestResult(); // 显示最终测试结果弹窗 + void showBatteryChargeFailDialog(); // 显示电池充电失败弹窗 + void clearProductionTestState(); // 清空产测状态 + void checkLcdTestResult(const QString& data); // 检查LCD测试结果 + void checkBuildVerResult(const QString& data); // 检查BuildVer启动完成 + void showLcdTestConfirmDialog(); // 显示LCD测试确认弹窗 + void showMotorTestConfirmDialog(); // 显示马达测试确认弹窗 + void performKeyTest(); // 执行按键测试 + void checkKeyTestResult(const QString& data); // 检查按键测试结果 + void showKeyTestConfirmDialog(bool allKeysTested); // 显示按键测试确认弹窗 + void performAudioTest(); // 执行录音测试 + void showAudioTestDialog(); // 显示录音测试弹窗 + void onAudioRecordTimer(); // 录音测试定时器(3秒录音) + void checkAudioTestResult(const QString& data); // 检查录音测试结果 + void performBatteryTest(); // 执行电池测试 + void checkBatteryTestResult(const QString& data); // 检查电池测试结果 + void performGsensorTest(); // 执行G-sensor测试 + void checkGsensorTestResult(const QString& data); // 检查G-sensor测试结果 + void updateTestStatus(const QString& testName, TestStatus status); + void updateOverallStatus(); + QString saveTestRecord(); // 保存测试记录到Excel(静默保存) + void checkSignalAndSimValues(const QString& data); // 检查signal和sim值进行4G测试判断 + void sendPppCommand(); // 发送PPP指令 + void parseWstpPrintData(const QString& data); // 解析wstp_print格式的BTMAC和CyweeChipInfo数据 + + + void onCat1SignalTimer(); + void checkCat1SignalResult(const QString& data); + void show4GRetryDialog(const QString& failReason); + bool isEGModem() const; + bool isValidIMEI(const QString& imei); + bool isValidICCID(const QString& iccid); + + void on_agingTestButton_clicked(); + + void on_agingTestButton_2_clicked(); + + void on_openButton_3_clicked(); + +private: + Ui::MainWindow *ui; + QSerialPort *serial; // 串口对象 + QString recvBuffer; // 用于累积接收的数据,处理分片问题 + void updateSerialPorts(); // 更新可用串口 + + // 产测相关变量 + QTimer *lcdTestTimer; // LCD测试定时器 + QTimer *motorTestTimer; // 马达测试定时器 + QTimer *test4GTimer; // 4G测试超时定时器 + QTimer *signal4GTimer; // 4G信号检测定时器 + QTimer *testTimeoutTimer; // 通用测试超时定时器 + + QTimer *cat1SignalTimer; // CAT1信号测试定时器 + int currentLcdColor; // 当前LCD测试颜色 (1=红, 2=绿, 3=蓝) + int initRetry4GCount; // 4G初始化重试次数 + bool hasReceivedFirstSignal; + int cat1SignalTestCount; + int cat1SignalReceivedCount; + int cat1SignalGoodCount; + int cat1Signal99Count; + int cat1SignalTotalValue; + int signalTest4GCount; // 4G信号检测发送次数 + int signalReceived4GCount; // 4G信号接收到有效数据次数 + int signalGood4GCount; // 4G信号良好以上计数 + int pppCommandCount; // PPP指令发送次数计数器 + bool hasReceivedSignalSim; // 是否已收到signal和sim数据 + bool hasReceivedPppInfo; // 是否已收到PPPINFO相关打印 + QString currentModemVersion; // 当前MODEM版本 + QString currentPYVerVersion; // 当前python版本 + int currentSimStatus; // 当前SIM卡状态:1=插入,0=未插入,-1=未知 + bool isProductionTestRunning; // 产测是否正在运行 + QDateTime testStartTime; // 测试开始时间 + bool lcdTestPopupShown; // LCD测试弹窗是否已显示 + bool motorTestPopupShown; // 马达测试弹窗是否已显示 + bool isWaitingForUserConfirm; // 是否正在等待用户确认 + bool keyTestStarted; // 按键测试是否已开始 + int keyTestStatus[4]; // 按键测试状态 0=未测试 1=已测试 + QDialog *keyTestDialog; // 按键测试弹窗 + QPushButton *keyButtons[4]; // 按键测试按钮 + bool audioTestPopupShown; // 录音测试弹窗是否已显示 + bool audioPlaybackPopupShown; // 录音播放确认弹窗是否已显示 + QTimer *audioRecordTimer; // 录音测试定时器 + QDialog *audioTestDialog; // 录音测试对话框 + QLabel *audioDialogLabel; // 录音对话框标签 + QLabel *audioDialogInfo; // 录音对话框信息 + QPushButton *audioStartButton; // 开始录音按钮 + QPushButton *audioPassButton; // 录音通过按钮 + QPushButton *audioFailButton; // 录音失败按钮 + QPushButton *audioRetestButton; // 重新测试按钮 + + enum AudioTestStep { + AUDIO_STARTING_RECORD, // 开始录音 + AUDIO_PLAYING_1KHZ, // 正在播放1kHz音频 + AUDIO_STOPPING_1KHZ, // 停止播放1kHz音频 + AUDIO_STOPPING_RECORD, // 停止录音 + AUDIO_PLAYING_RECORDED, // 播放录制的音频 + AUDIO_STOPPING_PLAYBACK // 停止播放录制的音频 + } currentAudioStep; + + enum ProductionTestStep { + TEST_IDLE, + TEST_RESET, + TEST_WAIT_BUILDVER, + TEST_LCD, + TEST_MOTOR, + TEST_KEY, + TEST_AUDIO, + TEST_BATTERY, + TEST_GSENSOR, + TEST_PPP_INIT, + TEST_PPP_UPDATE, + TEST_PPP_SIGNAL, + TEST_COMPLETED + } currentTestStep; + // 十六进制与字节数组转换工具函数 + QByteArray hexStringToByteArray(const QString &hexString); + QString byteArrayToHexString(const QByteArray &byteArray); + // 数据提取函数 + void ShowSoftVer(const QString& data); + void CheckVibratorFunc(const QString& data); + // PPP_INFO格式数据提取函数 + void ShowPppInfoIMEI(const QString& data); + void ShowPppInfoICCID(const QString& data); + void ShowPppInfoModemVer(const QString& data); + void ShowPppInfoPYVer(const QString& data); + // CAT1信号测试相关函数 + void parseNetworkStatChanged(const QString& data); +}; +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index 0eaae6b..52a6a1a 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -1,3846 +1,788 @@ - - - MainWindow - - - - 0 - 0 - 890 - 707 - - - - - 黑体 - 50 - false - - - - Factory_Tools - - - - :/icon/windows.ico:/icon/windows.ico - - - 1.000000000000000 - - - Qt::LeftToRight - - - - - - 0 - 0 - 631 - 371 - - - - - Times New Roman - 10 - - - - true - - - QTextBrowser{background-color:rgb(26, 26, 26); - color:rgb(127, 255, 0)} - - - Qt::ScrollBarAlwaysOn - - - Qt::TextBrowserInteraction - - - - - - 0 - 370 - 891 - 311 - - - - - 黑体 - 50 - false - - - - 0 - - - - - false - - - - 0 - 0 - 891 - 291 - - - - - 0 - 0 - - - - - 黑体 - 12 - 50 - false - - - - ArrowCursor - - - 3 - - - - Debug - - - - - 0 - 0 - 771 - 261 - - - - - - - 790 - 30 - 75 - 23 - - - - - Times New Roman - 10 - 50 - false - - - - 发送 - - - - - - 790 - 83 - 75 - 23 - - - - - Times New Roman - 10 - 50 - false - - - - 清除发送 - - - - - - 789 - 157 - 88 - 16 - - - - - Times New Roman - 10 - 50 - false - - - - 加回车换行 - - - false - - - - - - To Board - - - - - 20 - 210 - 831 - 23 - - - - 0 - - - false - - - - - - 20 - 20 - 831 - 161 - - - - - Times New Roman - 10 - 50 - false - - - - Upload File - - - - - 10 - 40 - 121 - 21 - - - - - Times New Roman - 10 - 50 - false - - - - Local File Path: - - - - - - 10 - 100 - 121 - 20 - - - - - Times New Roman - 10 - 50 - false - - - - Board File Path: - - - - - - 730 - 100 - 75 - 23 - - - - - Times New Roman - 10 - 50 - false - - - - stop - - - - - - 140 - 100 - 471 - 20 - - - - - - - 640 - 40 - 161 - 23 - - - - - Times New Roman - 10 - 50 - false - - - - Choose File - - - - - - 640 - 100 - 75 - 23 - - - - - Times New Roman - 10 - 50 - false - - - - Upload - - - false - - - - - - 140 - 40 - 471 - 20 - - - - - - - - From Board - - - - - 20 - 20 - 701 - 71 - - - - - Times New Roman - 10 - 50 - false - - - - File Storage - - - - - 10 - 30 - 121 - 21 - - - - - Times New Roman - 10 - 50 - false - - - - Local File Path: - - - - - - 140 - 30 - 421 - 20 - - - - - - - 580 - 30 - 91 - 23 - - - - - Times New Roman - 10 - 50 - false - - - - .... - - - - - - - 20 - 110 - 701 - 101 - - - - - Times New Roman - 10 - 50 - false - - - - File Selector - - - - - 40 - 20 - 71 - 20 - - - - - Times New Roman - 10 - 50 - false - - - - File Path: - - - - - - 140 - 20 - 531 - 20 - - - - - - - 140 - 60 - 411 - 22 - - - - - - - 570 - 60 - 101 - 23 - - - - - Times New Roman - 9 - 50 - false - - - - Get file List - - - - - - 40 - 60 - 71 - 20 - - - - - Times New Roman - 10 - 50 - false - - - - File Name: - - - - - - 290 - 130 - 75 - 23 - - - - PushButton - - - - - - - 20 - 220 - 711 - 20 - - - - 0 - - - - - - 760 - 20 - 95 - 201 - - - - - - - - Times New Roman - 10 - 50 - false - - - - Download - - - false - - - - - - - - Times New Roman - 10 - 50 - false - - - - Delete - - - - - - - - Times New Roman - 10 - 50 - false - - - - Stop - - - - - - - - - AT命令 - - - - - 0 - 0 - 891 - 271 - - - - - 黑体 - 10 - 50 - false - - - - QTabWidget::West - - - QTabWidget::Triangular - - - 0 - - - Qt::ElideNone - - - - MCU - - - - - 20 - 10 - 831 - 211 - - - - Debug - - - - - 20 - 30 - 791 - 31 - - - - - 10 - - - - - StackInfo - - - - - - - 待开发 - - - - - - - 待开发 - - - - - - - 待开发 - - - - - - - 待开发 - - - - - - - - - 20 - 90 - 371 - 30 - - - - - - - - - - FSRM - - - - - - - - - 20 - 150 - 731 - 25 - - - - - - - 发送 - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 30 - 20 - - - - - - - - - 黑体 - 8 - 50 - false - - - - module id - - - - - - - - 黑体 - 8 - 50 - false - - - - cmd id - - - - - - - payload - - - - - - - - - - MEDIA - - - - - 20 - 10 - 821 - 161 - - - - Media - - - - - 20 - 30 - 591 - 32 - - - - - 3 - - - 3 - - - 3 - - - 3 - - - - - - - - Music Play - - - - - - - Music Stop - - - - - - - - - 20 - 80 - 591 - 32 - - - - - 3 - - - 3 - - - 3 - - - 3 - - - - - - - - Audio Record - - - - - - - - - - BT - - - - - 20 - 10 - 821 - 111 - - - - 耦合测试设置 - - - - - 20 - 40 - 671 - 25 - - - - - - - - 0 - 0 - - - - 延时时间 - - - - - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - ms - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - DongleMAC - - - - - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - 耦合测试 - - - - - 20 - 10 - 831 - 121 - - - - BR EDR - - - - - 20 - 20 - 761 - 81 - - - - - - - - 0 - 0 - - - - Qt::DefaultContextMenu - - - - DH1 - - - - - DH3 - - - - - DH5 - - - - - 2-DH1 - - - - - 2-DH3 - - - - - 2-DH5 - - - - - 3-DH1 - - - - - 3-DH3 - - - - - 3-DH5 - - - - - - - - Length(0-27) - - - - - - - - 0 - 0 - - - - - ON - - - - - - - - - 0 - 0 - - - - - 10101010 - - - - - PRBS9 - - - - - 11110000 - - - - - - - - - 0 - 0 - - - - BR RX - - - - - - - - 0 - 0 - - - - 0 - - - - ON - - - - - - - - - 0 - 0 - - - - BR TX - - - - - - - - 0 - 0 - - - - - - - true - - - QLineEdit::Normal - - - Channel(0-78) - - - Qt::LogicalMoveStyle - - - false - - - - - - - - 0 - 0 - - - - - - - Channel(0-78) - - - - - - - - 0 - 0 - - - - Qt::DefaultContextMenu - - - - DH1 - - - - - DH3 - - - - - DH5 - - - - - 2-DH1 - - - - - 2-DH3 - - - - - 2-DH5 - - - - - 3-DH1 - - - - - 3-DH3 - - - - - 3-DH5 - - - - - - - - - 0 - 0 - - - - - 10101010 - - - - - PRBS9 - - - - - 11110000 - - - - - - - - Length(0-27) - - - - - - - - - - 20 - 140 - 831 - 111 - - - - BLE - - - - - 20 - 70 - 461 - 26 - - - - - 3 - - - - - - 0 - 0 - - - - - ON - - - - - - - - Channel(0-39) - - - - - - - - 0 - 0 - - - - Qt::DefaultContextMenu - - - - BLE 1M - - - - - BLE 2M - - - - - - - - - 0 - 0 - - - - BLE RX - - - - - - - - - 20 - 21 - 761 - 25 - - - - - - - - 0 - 0 - - - - BLE TX - - - - - - - - 0 - 0 - - - - - ON - - - - - - - - Channel(0-39) - - - - - - - - 0 - 0 - - - - - 10101010 - - - - - PRBS9 - - - - - 11110000 - - - - - - - - Length(0-255) - - - - - - - - 0 - 0 - - - - Qt::DefaultContextMenu - - - - BLE 1M - - - - - BLE 2M - - - - - - - - - - 560 - 70 - 221 - 25 - - - - - - - 获取RX Count - - - - - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - - - - false - - - - 0 - 0 - 911 - 291 - - - - - 黑体 - 12 - 50 - false - - - - 2 - - - - Debug - - - - - 0 - 0 - 771 - 261 - - - - - - - 790 - 30 - 75 - 23 - - - - - 黑体 - 10 - 50 - false - - - - 发送 - - - - - - 790 - 83 - 75 - 23 - - - - - 黑体 - 10 - 50 - false - - - - 清除发送 - - - - - - 789 - 157 - 88 - 16 - - - - - 黑体 - 10 - 50 - false - - - - 加回车换行 - - - false - - - - - - MCU - - - - - BT - - - - - 0 - 0 - 911 - 281 - - - - - 黑体 - 10 - 50 - false - - - - QTabWidget::West - - - QTabWidget::Triangular - - - 2 - - - Qt::ElideNone - - - false - - - - 非信令测试 - - - - - 20 - 140 - 831 - 111 - - - - BLE - - - - - 20 - 20 - 761 - 25 - - - - - - - - 0 - 0 - - - - BLE TX - - - - - - - - 0 - 0 - - - - - ON - - - - - OFF - - - - - - - - - - - Channel(0-39) - - - - - - - - 0 - 0 - - - - - 10101010 - - - - - PRBS9 - - - - - 11110000 - - - - - - - - Length(0-255) - - - - - - - - 0 - 0 - - - - Qt::DefaultContextMenu - - - - BLE 1M - - - - - BLE 2M - - - - - - - - - - 20 - 69 - 461 - 26 - - - - - 3 - - - - - - 0 - 0 - - - - - ON - - - - - OFF - - - - - - - - Channel(0-39) - - - - - - - - 0 - 0 - - - - Qt::DefaultContextMenu - - - - BLE 1M - - - - - BLE 2M - - - - - - - - - 0 - 0 - - - - BLE RX - - - - - - - - - - 20 - 10 - 831 - 121 - - - - BR EDR - - - - - 20 - 20 - 761 - 81 - - - - - - - - 0 - 0 - - - - - ON - - - - - OFF - - - - - - - - - 0 - 0 - - - - - 10101010 - - - - - PRBS9 - - - - - 11110000 - - - - - - - - - 0 - 0 - - - - Qt::DefaultContextMenu - - - - DH1 - - - - - DH3 - - - - - DH5 - - - - - 2-DH1 - - - - - 2-DH3 - - - - - 2-DH5 - - - - - 3-DH1 - - - - - 3-DH3 - - - - - 3-DH5 - - - - - - - - - 0 - 0 - - - - - - - Channel(0-78) - - - - - - - - 0 - 0 - - - - - 10101010 - - - - - PRBS9 - - - - - 11110000 - - - - - - - - - 0 - 0 - - - - BR RX - - - - - - - Length(0-27) - - - - - - - - 0 - 0 - - - - 0 - - - - ON - - - - - OFF - - - - - - - - Length(0-27) - - - - - - - - 0 - 0 - - - - BR TX - - - - - - - - 0 - 0 - - - - Qt::DefaultContextMenu - - - - DH1 - - - - - DH3 - - - - - DH5 - - - - - 2-DH1 - - - - - 2-DH3 - - - - - 2-DH5 - - - - - 3-DH1 - - - - - 3-DH3 - - - - - 3-DH5 - - - - - - - - - 0 - 0 - - - - - - - Channel(0-78) - - - - - - - - - - 信令测试 - - - - - 20 - 10 - 831 - 111 - - - - 信令 - - - - - 20 - 30 - 371 - 29 - - - - - 3 - - - 3 - - - 3 - - - 3 - - - - - - 0 - 0 - - - - BTDUTMODE - - - - - - - - 0 - 0 - - - - 信令测试: - - - - - - - - 0 - 0 - - - - - ON - - - - - OFF - - - - - - - - Qt::Horizontal - - - - 30 - 20 - - - - - - - - - - - 其他 - - - - - 20 - 20 - 791 - 121 - - - - 单音测试与功率调整 - - - - - 30 - 40 - 731 - 25 - - - - - 10 - - - - - channel(0-78) - - - - - - - - 0 - 0 - - - - 功率调整 - - - - - - - - 0 - 0 - - - - 单音测试 - - - - - - - - 0 - 0 - - - - - ON - - - - - OFF - - - - - - - - - 0 - 0 - - - - - ON - - - - - OFF - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - power chip(2-14) - - - - - - - - - - 20 - 140 - 791 - 111 - - - - BT_UART - - - - - 30 - 40 - 75 - 23 - - - - 唤醒 - - - - - - 150 - 40 - 75 - 23 - - - - 睡眠 - - - - - - - - - - - - - 650 - 0 - 224 - 389 - - - - - 5 - - - 20 - - - 5 - - - 20 - - - 20 - - - - - - 0 - 0 - - - - - 黑体 - 9 - 50 - false - - - - ArrowCursor - - - false - - - 115200 - - - 6 - - - true - - - - 4800 - - - - - 9600 - - - - - 14400 - - - - - 19200 - - - - - 38400 - - - - - 57600 - - - - - 115200 - - - - - 128000 - - - - - 230400 - - - - - 256000 - - - - - 460800 - - - - - 500000 - - - - - 512000 - - - - - 600000 - - - - - 750000 - - - - - 921600 - - - - - 1000000 - - - - - 1500000 - - - - - 2000000 - - - - - - - - - 0 - 0 - - - - - 黑体 - 9 - 50 - false - - - - - - - MAC地址 - - - - - - - - 0 - 0 - - - - 串口操作 - - - - - - - - 0 - 0 - - - - - 黑体 - 9 - 50 - false - - - - RTS - - - - - - - - 0 - 0 - - - - - 黑体 - 9 - 50 - false - - - - 保存窗口 - - - - - - - - 0 - 0 - - - - - 黑体 - 9 - 50 - false - - - - DTR - - - - - - - - 0 - 0 - - - - - 黑体 - 9 - 50 - false - - - - 16进制显示 - - - - - - - - 0 - 0 - - - - - 黑体 - 9 - 50 - false - - - - 打开串口 - - - true - - - false - - - false - - - false - - - - - - - false - - - - 0 - 0 - - - - - 黑体 - 9 - 50 - false - - - - 连接设备 - - - false - - - - - - - - 0 - 0 - - - - - 黑体 - 9 - 50 - false - - - - 16进制发送 - - - - - - - - 0 - 0 - - - - - 黑体 - 9 - 50 - false - - - - - COM1 - - - - - - - - - 0 - 0 - - - - - 黑体 - 9 - 50 - false - - - - 清除接收 - - - - - - - - 20 - 20 - - - - QPushButton{background-color: rgb(255, 0, 0);} - - - - - - - - - - - - - 0 - 0 - 890 - 22 - - - - - 黑体 - 12 - 50 - false - - - - - - 12 - - - - 菜单 - - - - - - - - - - true - - - true - - - - - true - - - true - - - 整机 - - - - 黑体 - 12 - - - - - - true - - - false - - - 单板 - - - - 12 - - - - - - dongle调试 - - - - 12 - - - - - - - MyComboBox - QComboBox -
custom.h
- - mouse_clicked(bool) - -
- - MyLineEdit - QLineEdit -
custom.h
-
-
- - - - pbtn_open_uart - clicked() - MainWindow - uart_process() - - - 849 - 154 - - - 838 - 261 - - - - - pbtn_clear_display - clicked() - txtb_dispaly - clear() - - - 849 - 293 - - - 614 - 380 - - - - - ckbox_dtr - stateChanged(int) - MainWindow - uart_check_dtr_rts() - - - 815 - 334 - - - 882 - 371 - - - - - ckbox_rts - stateChanged(int) - MainWindow - uart_check_dtr_rts() - - - 711 - 334 - - - 758 - 373 - - - - - cbox_uart_com_select - mouse_clicked(bool) - MainWindow - uart_com_select() - - - 719 - 61 - - - 888 - 100 - - - - - pbtn_spp_connect - clicked() - MainWindow - spp_connect() - - - 811 - 245 - - - 888 - 267 - - - - - pbtn_toboard_stop - clicked() - MainWindow - transmit_toboard_stop() - - - 810 - 559 - - - 739 - 294 - - - - - pbtn_toboard_Upload - clicked() - MainWindow - transmit_toboard_upload() - - - 715 - 559 - - - 665 - 296 - - - - - pbtn_fromboard_getfilelist - clicked() - MainWindow - transmit_fromboard_getfilelist() - - - 670 - 609 - - - 654 - 408 - - - - - pbtn_send_data - clicked() - MainWindow - uart_send_data() - - - 844 - 469 - - - 865 - 411 - - - - - pbtn_fromboard_download - clicked() - MainWindow - transmit_fromboard_download() - - - 830 - 489 - - - 849 - 420 - - - - - pbtn_fromboard_selectfilepath - clicked() - MainWindow - transmit_fromboard_selectfilepath() - - - 665 - 489 - - - 673 - 417 - - - - - pbtn_clear_senddata - clicked() - tedit_input_data - clear() - - - 866 - 522 - - - 700 - 591 - - - - - pbtn_fromboard_stop - clicked() - MainWindow - transmit_fromboard_stop() - - - 855 - 605 - - - 676 - 315 - - - - - pbtn_fromboard_delete - clicked() - MainWindow - transmit_fromboard_delete() - - - 855 - 547 - - - 671 - 351 - - - - - ledit_formboad_bordpath - textEdited(QString) - MainWindow - transmit_fromboard_name_change() - - - 499 - 566 - - - 688 - 273 - - - - - pbtn_toboard_choosefile - clicked() - MainWindow - transmit_toboard_choosefile() - - - 736 - 499 - - - 660 - 343 - - - - - action_complete - triggered(bool) - MainWindow - ui_tab_mainwindow_complete() - - - -1 - -1 - - - 468 - 363 - - - - - action_board - triggered(bool) - MainWindow - ui_tab_mainwindow_board() - - - -1 - -1 - - - 539 - 363 - - - - - pbtn_board - clicked() - tedit_input_data_board - clear() - - - 822 - 522 - - - 767 - 568 - - - - - pbtn_send_data_board - clicked() - MainWindow - uart_send_data() - - - 842 - 469 - - - 888 - 484 - - - - - pbtn_at_mediaaudiorecord - clicked() - MainWindow - at_mediaaudiorecord_send() - - - 646 - 535 - - - 643 - 285 - - - - - pbtn_at_stackinfo - clicked() - MainWindow - at_stackinfo_send() - - - 160 - 485 - - - 654 - 412 - - - - - pbtn_at_fsrm - clicked() - MainWindow - at_fsrm_send() - - - 428 - 544 - - - 655 - 254 - - - - - pbtn_at_mediamusicstop - clicked() - MainWindow - at_mediamusicstop_send() - - - 646 - 485 - - - 656 - 381 - - - - - pbtn_at_mediamusicplay - clicked() - MainWindow - at_mediamusicplay_send() - - - 545 - 485 - - - 654 - 330 - - - - - pbtn_br_tx_complete - clicked() - MainWindow - at_bt_tx_complete() - - - 156 - 481 - - - 636 - 372 - - - - - pbtn_br_rx_complete - clicked() - MainWindow - at_bt_rx_complete() - - - 156 - 519 - - - 637 - 335 - - - - - pbtn_ble_tx_complete - clicked() - MainWindow - at_ble_tx_complete() - - - 149 - 603 - - - 639 - 361 - - - - - pbtn_ble_rx_complete - clicked() - MainWindow - at_ble_rx_complete() - - - 141 - 652 - - - 444 - 354 - - - - - pbtn_br_tx_board - clicked() - MainWindow - at_bt_tx_board() - - - 156 - 481 - - - 639 - 325 - - - - - pbtn_br_rx_board - clicked() - MainWindow - at_bt_rx_board() - - - 156 - 519 - - - 646 - 169 - - - - - pbtn_btdutmode_board - clicked() - MainWindow - at_bt_dutmode_board() - - - 265 - 484 - - - 646 - 210 - - - - - pbtn_ble_tx_board - clicked() - MainWindow - at_ble_tx_board() - - - 139 - 581 - - - 633 - 248 - - - - - pbtn_ble_rx_board - clicked() - MainWindow - at_ble_rx_board() - - - 139 - 630 - - - 643 - 204 - - - - - pbtn_get_rx_count - clicked() - MainWindow - at_get_rx_count_complete() - - - 674 - 652 - - - 647 - 134 - - - - - pbtn_delay_time - clicked() - MainWindow - at_bt_delay_ms_complete() - - - 134 - 492 - - - 637 - 161 - - - - - pbtn_donglemac - clicked() - MainWindow - at_set_dongle_addr_complete() - - - 581 - 492 - - - 653 - 126 - - - - - cbox_uart_com_select - activated(QString) - MainWindow - uart_com_switch(QString) - - - 702 - 55 - - - 764 - 76 - - - - - cbox_uart_baud_select - activated(QString) - MainWindow - uart_baud_switch(QString) - - - 712 - 103 - - - 744 - 133 - - - - - cbox_br_tx_PacketType_complete - activated(int) - MainWindow - at_check_bt_len(int) - - - 514 - 479 - - - 649 - 73 - - - - - cbox_br_rx_PacketType_complete - activated(int) - MainWindow - at_check_bt_len(int) - - - 514 - 517 - - - 647 - 55 - - - - - cbox_br_tx_PacketType_board - activated(int) - MainWindow - at_check_bt_len(int) - - - 514 - 479 - - - 639 - 116 - - - - - cbox_br_rx_PacketType_board - activated(int) - MainWindow - at_check_bt_len(int) - - - 514 - 517 - - - 638 - 85 - - - - - pushButton - clicked() - MainWindow - ui_save_windows() - - - 702 - 285 - - - 647 - 236 - - - - - pbtn_btlo_board - clicked() - MainWindow - at_bt_btlo_board() - - - 144 - 502 - - - 642 - 200 - - - - - pbtn_btpwr_board - clicked() - MainWindow - at_bt_btpwr_board() - - - 589 - 502 - - - 684 - 304 - - - - - pbtn_at_custom_send - clicked() - MainWindow - at_custom_send() - - - 169 - 602 - - - 661 - 190 - - - - - pushButton_3 - clicked() - MainWindow - at_bt_wakeup() - - - 122 - 615 - - - 957 - 601 - - - - - pushButton_4 - clicked() - MainWindow - at_bt_sleep() - - - 244 - 615 - - - 970 - 548 - - - - - - transmit_toboard_choosefile() - uart_send_data() - uart_process() - check_word_wrap() - check_hex_display() - at_stackinfo_send() - uart_check_dtr_rts() - uart_com_select() - transmit_fromboard_selectfilepath() - transmit_fromboard_getfilelist() - transmit_fromboard_download() - transmit_toboard_upload() - transmit_toboard_stop() - transmit_fromboard_delete() - transmit_fromboard_stop() - spp_connect() - transmit_fromboard_name_change() - at_fsrm_send() - at_mediamusicplay_send() - at_mediamusicstop_send() - at_mediaaudiorecord_send() - ui_tab_mainwindow_complete() - ui_tab_mainwindow_board() - at_bt_tx_complete() - at_bt_rx_complete() - at_ble_tx_complete() - at_ble_rx_complete() - at_bt_rx_board() - at_bt_tx_board() - at_ble_tx_board() - at_ble_rx_board() - at_bt_dutmode_board() - at_bt_delay_ms_complete() - at_set_dongle_addr_complete() - at_get_rx_count_complete() - uart_com_switch(QString) - uart_baud_switch(QString) - at_check_bt_len(int) - ui_save_windows() - at_bt_btlo_board() - at_bt_btpwr_board() - at_custom_send() - at_bt_wakeup() - at_bt_sleep() - -
+ + + MainWindow + + + + 0 + 0 + 1309 + 641 + + + + + 10 + + + + MainWindow + + + + + + 10 + 30 + 231 + 31 + + + + + + + 260 + 20 + 741 + 401 + + + + + + + 260 + 460 + 741 + 71 + + + + + + + 10 + 90 + 101 + 51 + + + + 打开串口 + + + + + + 120 + 90 + 101 + 51 + + + + 清空数据 + + + + + + 930 + 540 + 75 + 23 + + + + 发送 + + + + + + 1010 + 30 + 21 + 16 + + + + Ver: + + + + + + 1050 + 30 + 181 + 20 + + + + + + + 1010 + 60 + 31 + 20 + + + + IMEI: + + + + + + 1050 + 60 + 181 + 20 + + + + + + + 1010 + 90 + 41 + 20 + + + + ICCID + + + + + + 1050 + 90 + 181 + 20 + + + + + + + 1050 + 120 + 251 + 20 + + + + + + + 1010 + 120 + 41 + 21 + + + + Modem: + + + + + + 10 + 160 + 101 + 51 + + + + 开始产测 + + + + + + 120 + 160 + 101 + 51 + + + + QPushButton { +background-color: #FF9800; +color: white; +border-radius: 4px; +font-weight: bold; +} +QPushButton:hover { +background-color: #F57C00; +} + + + 打开记录 + + + + + + 10 + 220 + 101 + 51 + + + + QPushButton { +background-color: #9C27B0; +color: white; +border-radius: 4px; +font-weight: bold; +} +QPushButton:hover { +background-color: #7B1FA2; +} + + + 老化测试 + + + + + + 1010 + 180 + 61 + 20 + + + + 最新VER: + + + + + + 1070 + 180 + 231 + 20 + + + + + + + 1010 + 210 + 81 + 20 + + + + 最新MODEM: + + + + + + 1090 + 210 + 231 + 20 + + + + + + + 1020 + 280 + 281 + 271 + + + + 产测状态 + + + + + 10 + 25 + 60 + 20 + + + + LCD测试: + + + + + + 80 + 25 + 20 + 20 + + + + color: #888888; font-size: 18px; font-weight: bold; + + + ○ + + + Qt::AlignCenter + + + + + + 110 + 25 + 60 + 20 + + + + color: #888888; + + + 未测试 + + + + + + 10 + 55 + 60 + 20 + + + + 马达测试: + + + + + + 80 + 55 + 20 + 20 + + + + color: #888888; font-size: 18px; font-weight: bold; + + + ○ + + + Qt::AlignCenter + + + + + + 110 + 55 + 60 + 20 + + + + color: #888888; + + + 未测试 + + + + + + 10 + 85 + 60 + 20 + + + + 按键测试: + + + + + + 80 + 85 + 20 + 20 + + + + color: #888888; font-size: 18px; font-weight: bold; + + + ○ + + + Qt::AlignCenter + + + + + + 110 + 85 + 60 + 20 + + + + color: #888888; + + + 未测试 + + + + + + 10 + 115 + 60 + 20 + + + + 录音测试: + + + + + + 80 + 115 + 20 + 20 + + + + color: #888888; font-size: 18px; font-weight: bold; + + + ○ + + + Qt::AlignCenter + + + + + + 110 + 115 + 60 + 20 + + + + color: #888888; + + + 未测试 + + + + + + 10 + 145 + 60 + 20 + + + + 电池测试: + + + + + + 80 + 145 + 20 + 20 + + + + color: #888888; font-size: 18px; font-weight: bold; + + + ○ + + + Qt::AlignCenter + + + + + + 110 + 145 + 60 + 20 + + + + color: #888888; + + + 未测试 + + + + + + 10 + 175 + 60 + 20 + + + + G-sensor: + + + + + + 80 + 175 + 20 + 20 + + + + color: #888888; font-size: 18px; font-weight: bold; + + + ○ + + + Qt::AlignCenter + + + + + + 110 + 175 + 60 + 20 + + + + color: #888888; + + + 未测试 + + + + + + 10 + 205 + 60 + 20 + + + + 4G测试: + + + + + + 80 + 205 + 20 + 20 + + + + color: #888888; font-size: 18px; font-weight: bold; + + + ○ + + + Qt::AlignCenter + + + + + + 110 + 205 + 60 + 20 + + + + color: #888888; + + + 未测试 + + + + + + 10 + 235 + 60 + 20 + + + + 整体状态: + + + + + + 80 + 235 + 20 + 20 + + + + color: #888888; font-size: 18px; font-weight: bold; + + + ○ + + + Qt::AlignCenter + + + + + + 110 + 235 + 80 + 20 + + + + color: #888888; + + + 等待开始 + + + + + + + 120 + 220 + 101 + 51 + + + + QPushButton { +background-color: #9C27B0; +color: white; +border-radius: 4px; +font-weight: bold; +} +QPushButton:hover { +background-color: #7B1FA2; +} + + + 恢复出厂 + + + + + + 10 + 280 + 101 + 51 + + + + 老化结果 + + + + + + 1050 + 150 + 251 + 20 + + + + + + + + + + 1010 + 150 + 41 + 21 + + + + PYVER + + + + + + 1010 + 240 + 81 + 20 + + + + 最新PY: + + + + + + 1090 + 240 + 231 + 20 + + + + + + + + 0 + 0 + 1309 + 23 + + + + + + + + diff --git a/mythread.cpp b/mythread.cpp deleted file mode 100644 index 6d0a5db..0000000 --- a/mythread.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "mythread.h" - -MyThread::MyThread() -{ - stopped = false; - pauseFlag = false; -} - -MyThread::~MyThread() -{ -} - -void MyThread::process() -{ -} - -void MyThread::run() -{ - while (true) { - QMutexLocker locker(&m_lock_stop); - if (stopped) { - stopped = false; - qDebug() << "线程终止"; - return; - } - if (pauseFlag) { - m_lock_Pause.lock(); - condition.wait(&m_lock_Pause); - m_lock_Pause.unlock(); - } - process(); - } - stopped = false; - pauseFlag = false; -} - -void MyThread::pause() -{ - if (this->isRunning() && !pauseFlag) { - pauseFlag = true; - } -} - -void MyThread::resume() -{ - if (this->isRunning() && pauseFlag) { - pauseFlag = false; - condition.wakeAll(); - } -} - -void MyThread::stop() -{ - if (this->isRunning()) { - if (pauseFlag) { - this->resume(); - } - QMutexLocker locker(&m_lock_stop); - stopped = true; - } -} diff --git a/mythread.h b/mythread.h deleted file mode 100644 index 72164a8..0000000 --- a/mythread.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef MYTHREAD_H -#define MYTHREAD_H -#include -#include -#include -#include -#include -#include -#include - /*-----------------------rx回调函数线程-------------------------------*/ - // 当回调函数执行时,会唤醒此线程。 根据回调函数返回值执行对应函数。 -class MyThread : public QThread -{ - public: - explicit MyThread(); - ~MyThread(); - void stop(); - - protected: - void run() override final; - virtual void process(); - public slots: - void pause(); - void resume(); - - private: - QMutex m_lock_stop; - volatile bool stopped; - QMutex m_lock_Pause; - std::atomic pauseFlag; - QWaitCondition condition; -}; -#endif // MYTHREAD_H diff --git a/readme.txt b/readme.txt deleted file mode 100644 index 096c091..0000000 --- a/readme.txt +++ /dev/null @@ -1,66 +0,0 @@ -main.cpp示例如下 -________________________________________________________________________________________________________________________________________ -#include -#include "interface.h" -#include "info.h" -#include "windows.h" -#include "Library_global.h" -using namespace std; - -class MyInfo : public uapi::Info -{ -public: - MyInfo(){}; - ~MyInfo(){}; - void onReadEvent(int eventType, void *data) override - { - cout<<"eventType = "<InfoEventConnect(&info); - handle->SetCurrentMode(uapi::MODE_BLUETOOTH); - -// 串口配置 - char *com = "COM11"; - handle->SerialPortOpen(com, 921600); - -// 设置为整机段 - handle->SetCurrentMode(uapi::MODE_BLUETOOTH); - -// 发送STACKINFO命令 - handle->AtMessageSend(8,0x0d,NULL,0); - -// 获取文件列表 - char ls_tx[] = "/user/"; - handle->FileGetList(ls_tx, strlen(ls_tx)); - - char board_delete_path[] = "/user/test.mp3"; - handle->FileDelete(board_delete_path, strlen(board_delete_path)); - -// 上传文件 - Sleep(1000); - char local_path[] = "C:/Users/y30032013/Desktop/music.mp3"; - char board_path[] = "/user/music.mp3"; - handle->FileUpload(board_path, local_path); - Sleep(3000); - handle->FileTransmitStop(); - -// 下载文件 - Sleep(1000); - handle->FileGetList(ls_tx, strlen(ls_tx)); - Sleep(3000); - char name[] = "/user/music.mp3"; - char pc_path[] = "C:/Users/y30032013/Desktop/bin/"; - handle->FileDownload(name, pc_path); - - while (1) { - Sleep(100); - } -} -________________________________________________________________________________________________________________________________________ diff --git a/release/LeiNiaoFactoryTool.exe b/release/LeiNiaoFactoryTool.exe new file mode 100644 index 0000000..f08aa2e Binary files /dev/null and b/release/LeiNiaoFactoryTool.exe differ diff --git a/release/at_data.obj b/release/at_data.obj deleted file mode 100644 index 1329fb2..0000000 Binary files a/release/at_data.obj and /dev/null differ diff --git a/release/custom.obj b/release/custom.obj deleted file mode 100644 index 64b0a6b..0000000 Binary files a/release/custom.obj and /dev/null differ diff --git a/release/factory_tool.exe b/release/factory_tool.exe deleted file mode 100644 index efac356..0000000 Binary files a/release/factory_tool.exe and /dev/null differ diff --git a/release/main.obj b/release/main.obj deleted file mode 100644 index 7961d78..0000000 Binary files a/release/main.obj and /dev/null differ diff --git a/release/mainwindow.obj b/release/mainwindow.obj deleted file mode 100644 index b0b1b11..0000000 Binary files a/release/mainwindow.obj and /dev/null differ diff --git a/release/moc_custom.obj b/release/moc_custom.obj deleted file mode 100644 index 39b4657..0000000 Binary files a/release/moc_custom.obj and /dev/null differ diff --git a/release/moc_mainwindow.obj b/release/moc_mainwindow.obj deleted file mode 100644 index 7e546a7..0000000 Binary files a/release/moc_mainwindow.obj and /dev/null differ diff --git a/release/mythread.obj b/release/mythread.obj deleted file mode 100644 index c14deb3..0000000 Binary files a/release/mythread.obj and /dev/null differ diff --git a/release/result_thread.obj b/release/result_thread.obj deleted file mode 100644 index 1c15396..0000000 Binary files a/release/result_thread.obj and /dev/null differ diff --git a/release/wrtm_class.obj b/release/wrtm_class.obj deleted file mode 100644 index c6011e2..0000000 Binary files a/release/wrtm_class.obj and /dev/null differ diff --git "a/release/\344\272\247\346\265\213\350\256\260\345\275\225/\344\272\247\346\265\213\350\256\260\345\275\225.csv" "b/release/\344\272\247\346\265\213\350\256\260\345\275\225/\344\272\247\346\265\213\350\256\260\345\275\225.csv" new file mode 100644 index 0000000..4e782e2 --- /dev/null +++ "b/release/\344\272\247\346\265\213\350\256\260\345\275\225/\344\272\247\346\265\213\350\256\260\345\275\225.csv" @@ -0,0 +1,7 @@ +开始时间,结束时间,测试耗时,软件版本,IMEI,ICCID,Modem版本,LCD测试,马达测试,按键测试,录音测试,电池测试,G-sensor测试,4G测试,整体结果 +2025-10-23 11:27:51,2025-10-23 12:09:27,41分35秒,V1.0.0_20251023_110314,860132064650112,898604B7192590313291,EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0725,通过,通过,通过,通过,失败,通过,失败,未通过 +2025-10-21 17:28:03,2025-10-21 17:28:57,0分54秒,V1.1.0_20251021_142617,866827070011340,89860441192590308567,N706A-H111-STD-BZ_CN2X_HTTPS-000_T1013,通过,通过,通过,通过,通过,通过,通过,通过 +2025-10-24 19:10:59,2025-10-24 19:12:09,1分9秒,V1.0.0_20251024_185411,860132063148589,89860441192590308570,EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0725,通过,通过,通过,通过,通过,通过,通过,通过 +2025-11-03 14:14:22,2025-11-03 14:15:39,1分16秒,V1.0.1_20251103_113708,860132064627870,898604B7192590313369,EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0725,通过,通过,通过,通过,失败,通过,通过,未通过 +2025-11-05 16:43:42,2025-11-05 16:44:22,0分40秒,V1.0.2_20251105_144822,860132064638570,898604B7192590313374,EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0725,PY_SRV_V25,通过,通过,通过,通过,失败,通过,通过 +2025-11-10 12:10:40,2025-11-10 12:11:37,0分56秒,V1.1.2_20251030_135758,866827070012918,898604e4192590355316,N706A-H111-STD-BZ_CN2X_HTTPS-000_T1013,未获取,通过,通过,通过,通过,通过,通过,通过 diff --git "a/release/\344\272\247\346\265\213\350\256\260\345\275\225/\350\200\201\345\214\226\350\256\260\345\275\225/\350\200\201\345\214\226_20251105_094030.csv" "b/release/\344\272\247\346\265\213\350\256\260\345\275\225/\350\200\201\345\214\226\350\256\260\345\275\225/\350\200\201\345\214\226_20251105_094030.csv" new file mode 100644 index 0000000..6614706 --- /dev/null +++ "b/release/\344\272\247\346\265\213\350\256\260\345\275\225/\350\200\201\345\214\226\350\256\260\345\275\225/\350\200\201\345\214\226_20251105_094030.csv" @@ -0,0 +1 @@ +序号,时间,电池测试,G-sensor测试,4G测试 diff --git "a/release/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.zip" "b/release/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.zip" new file mode 100644 index 0000000..b08eb3e Binary files /dev/null and "b/release/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.zip" differ diff --git "a/release/\351\233\267\351\270\237\344\272\247\346\265\213\345\267\245\345\205\267.zip" "b/release/\351\233\267\351\270\237\344\272\247\346\265\213\345\267\245\345\205\267.zip" new file mode 100644 index 0000000..32e7238 Binary files /dev/null and "b/release/\351\233\267\351\270\237\344\272\247\346\265\213\345\267\245\345\205\267.zip" differ diff --git "a/release/\351\233\267\351\270\237\344\272\247\346\265\213\345\267\245\345\205\267/LeiNiaoFactoryTool.exe" "b/release/\351\233\267\351\270\237\344\272\247\346\265\213\345\267\245\345\205\267/LeiNiaoFactoryTool.exe" new file mode 100644 index 0000000..d1adc2c Binary files /dev/null and "b/release/\351\233\267\351\270\237\344\272\247\346\265\213\345\267\245\345\205\267/LeiNiaoFactoryTool.exe" differ diff --git a/result_thread.cpp b/result_thread.cpp deleted file mode 100644 index 57db951..0000000 --- a/result_thread.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "result_thread.h" - -struct result_info g_result_info={0,NULL,0,NULL,false,NONE_DATA,0,NULL}; -QMutex g_result_thread_mlock; -QWaitCondition g_result_thread_condition; - - - -Result_Thread::Result_Thread(QObject *parent) -{ - obj=parent; -} - -Result_Thread::~Result_Thread() -{ -} - -// 给 UI 线程发送消息 -void Result_Thread::process() -{ - g_result_thread_mlock.lock(); - g_result_thread_condition.wait(&g_result_thread_mlock, MLOCK_TIMEOUT); - switch (g_result_info.result_thread_flag) { - case UART_RX_DATA: - QMetaObject::invokeMethod(obj, "uart_rx_dispaly", Q_ARG(int, g_result_info.uart_rx_buf_len),Q_ARG(u8Piont,g_result_info.uart_rx_buf)); // 让UI线程执行 Uart_Rx_Dispaly 槽函数 - g_result_info.result_thread_flag = NONE_DATA; - break; - case LS_RESULT_DATA: - QMetaObject::invokeMethod(obj, "transmit_ls_rx_diaplay",Q_ARG(int , g_result_info.transmit_ls_size),Q_ARG(vPiont,g_result_info.transmit_ls_buff)); - g_result_info.result_thread_flag = NONE_DATA; - break; - case TRANSMIT_FILE_DATA: - QMetaObject::invokeMethod(obj, "transmit_rx_display",Q_ARG(bool, g_result_info.transmit_result_flag)); - g_result_info.transmit_result_flag = false; - g_result_info.result_thread_flag = NONE_DATA; - break; - case AT_RESULT_DATA: - QMetaObject::invokeMethod(obj, "at_rx_display",Q_ARG(int, g_result_info.at_result_len),Q_ARG(u8Piont,g_result_info.at_result_buf)); - g_result_info.result_thread_flag = NONE_DATA; - break; - default: - break; - } - g_result_thread_mlock.unlock(); -} - -uint32_t uart_callback(void *buf, uint32_t buf_len) -{ - g_result_info.uart_rx_buf_len = (int)buf_len; - // rx的数据不包含\0,所以多分配1字节。 - g_result_info.uart_rx_buf=(uint8_t *)malloc(buf_len); - memset(g_result_info.uart_rx_buf,0,buf_len); - memcpy_s(g_result_info.uart_rx_buf, buf_len, (uint8_t *)buf, buf_len); - g_result_info.result_thread_flag = UART_RX_DATA; - g_result_thread_mlock.lock(); - g_result_thread_condition.wakeAll(); - g_result_thread_mlock.unlock(); - return 0; -} - -uint32_t ls_callback(uint32_t size, uapi_ls_info_t *buff) -{ - g_result_info.transmit_ls_buff = (uapi_ls_info_t *)malloc(size * sizeof(uapi_ls_info_t)+1); - memcpy_s(g_result_info.transmit_ls_buff, size * sizeof(uapi_ls_info_t), (uapi_ls_info_t *)buff, size * sizeof(uapi_ls_info_t)); - g_result_info.transmit_ls_size = static_cast(size); - g_result_info.result_thread_flag = LS_RESULT_DATA; - g_result_thread_mlock.lock(); - g_result_thread_condition.wakeAll(); - g_result_thread_mlock.unlock(); - return 0; -} - -uint32_t transmit_callback(bool is_finished, uintptr_t usr_data) -{ - g_result_info.transmit_result_flag = is_finished; - Q_UNUSED(usr_data); - g_result_info.result_thread_flag = TRANSMIT_FILE_DATA; - g_result_thread_mlock.lock(); - g_result_thread_condition.wakeAll(); - g_result_thread_mlock.unlock(); - return 0; -} - -uint32_t at_callback(void *buf, uint32_t len) -{ - uint8_t * at_buff = (uint8_t *)malloc(len); - memcpy_s(at_buff, len , buf, len); - g_result_info.at_result_buf = (uint8_t *)at_buff; - g_result_info.at_result_len = len; - g_result_info.result_thread_flag = AT_RESULT_DATA; - g_result_thread_mlock.lock(); - g_result_thread_condition.wakeAll(); - g_result_thread_mlock.unlock(); - return 0; -} -void transmit_get_data_count(uint32_t *total_size, uint32_t *current_size) -{ - uapi_transmit_progress transmint_data_count; - uapi_transmit_process(&transmint_data_count); - *total_size=transmint_data_count.total_size; - *current_size=transmint_data_count.transmited_size; -} diff --git a/result_thread.h b/result_thread.h deleted file mode 100644 index acb41a5..0000000 --- a/result_thread.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef RESULT_THREAD_H -#define RESULT_THREAD_H -#include "mythread.h" -#include "common.h" -#include -#include -#include -#include -#include - -#define BUF_SIZE 4096 -#define MLOCK_TIMEOUT 2000 -enum get_data_flag -{ - NONE_DATA = -1, - UART_RX_DATA = 0, - LS_RESULT_DATA, - TRANSMIT_FILE_DATA, - AT_RESULT_DATA, -}; - -struct result_info{ - // uart收到的数据 - int uart_rx_buf_len; - uint8_t *uart_rx_buf; - - // ls数据大小和内容 - int transmit_ls_size; - uapi_ls_info_t *transmit_ls_buff; - - // 传输文件是否成功 - bool transmit_result_flag; - - // 当前回调函数标记 - int result_thread_flag; - - // at调用返回 - int at_result_len; - uint8_t *at_result_buf; -}; - -class Result_Thread : public MyThread -{ -public: - Result_Thread(QObject *parent = 0); - ~Result_Thread(); -protected: - void process() override final; -private: - QObject *obj; -}; - -uint32_t uart_callback(void *buf, uint32_t buf_len); -uint32_t ls_callback(uint32_t size, uapi_ls_info_t *buff); -uint32_t transmit_callback(bool is_finished, uintptr_t usr_data); -uint32_t at_callback(void *buf, uint32_t len); -void transmit_get_data_count(uint32_t *total_size, uint32_t *current_size); -#endif // RESULT_THREAD_H diff --git a/untitled_zh_CN.ts b/untitled_zh_CN.ts deleted file mode 100644 index 806770f..0000000 --- a/untitled_zh_CN.ts +++ /dev/null @@ -1,844 +0,0 @@ - - - - - MainWindow - - - 打开串口 - - - - - AT命令 - - - - - - - 发送 - - - - - - - Debug - - - - - - 清除发送 - - - - - From Board - From Boad - - - - - File Storage - - - - - - Local File Path: - - - - - Factory_Tools - - - - - To Board - - - - - Upload File - - - - - Board File Path: - - - - - Choose File - - - - - .... - - - - - File Selector - - - - - File Path: - - - - - Get file List - - - - - File Name: - - - - - Download - - - - - Delete - - - - - Stop - - - - - - MCU - - - - - - - - 待开发 - - - - - FSRM - - - - - module id - - - - - cmd id - - - - - payload - - - - - MEDIA - - - - - Media - - - - - Music Play - - - - - Music Stop - - - - - Audio Record - - - - - - BT - - - - - - - - Channel(0-78) - - - - - - - - Channel(0-39) - - - - - - Length(0-255) - - - - - BTDUTMODE - - - - - 信令测试: - - - - - 其他 - - - - - 单音测试与功率调整 - - - - - channel(0-78) - - - - - 功率调整 - - - - - 单音测试 - - - - - power chip(2-14) - - - - - BT_UART - - - - - 唤醒 - - - - - 睡眠 - - - - - dongle调试 - - - - - - - - - - - OFF - - - - - 耦合测试设置 - - - - - 延时时间 - - - - - ms - - - - - DongleMAC - - - - - 耦合测试 - - - - - - BR EDR - - - - - - - - 2-DH5 - - - - - - - - Length(0-27) - Length - - - - - - - - DH1 - - - - - - - - - - - - - - - ON - - - - - - BR TX - - - - - - - - - - 10101010 - - - - - - - - - - PRBS9 - - - - - - - - - - 11110000 - - - - - - - - DH3 - - - - - - - - DH5 - - - - - - - - 2-DH1 - - - - - - - - 2-DH3 - - - - - - - - 3-DH1 - - - - - - - - 3-DH3 - - - - - - - - 3-DH5 - - - - - - BR RX - - - - - - BLE - - - - - - BLE TX - - - - - - - - BLE 1M - - - - - - - - BLE 2M - - - - - - BLE RX - - - - - 非信令测试 - - - - - 信令测试 - - - - - 菜单 - - - - - 单板 - - - - - 整机 - - - - - 4800 - - - - - 9600 - - - - - 14400 - - - - - 19200 - - - - - 38400 - - - - - 57600 - - - - - - 115200 - - - - - 获取RX Count - - - - - 信令 - - - - - 128000 - - - - - 230400 - - - - - 256000 - - - - - 460800 - - - - - 500000 - - - - - 512000 - - - - - 600000 - - - - - 750000 - - - - - 921600 - - - - - 1000000 - - - - - 1500000 - - - - - 2000000 - - - - - 连接设备 - - - - - MAC地址 - - - - - - 加回车换行 - - - - - - Upload - - - - - stop - - - - - StackInfo - - - - - PushButton - - - - - 串口操作 - - - - - 清除接收 - - - - - 保存窗口 - - - - - 16进制显示 - - - - - 16进制发送 - - - - - RTS - - - - - DTR - - - - - COM1 - - - - - 串口 - - - - - 打开串口失败! - - - - - 注册表 - - - - - 无法打开注册表! - - - - - ls fail! - - - - - - 文件大小为0! - - - - - 文件下载启动失败! - - - - - - - - - AT - - - - - AT send fail! - - - - - - ls - - - - - - - - - - - - File Path - File - - - - - - - - - - 文件路径为空! - - - - - - Board File Name - - - - - Downloade - - - - - delete - - - - - delete file fail! - - - - - - 文件路径为空! - - - - - 文件上传启动失败! - - - - - - MAC地址为空! - - - - - - - - length错误! - - - - - - - - - 操作错误 - - - - - - - - - 应先关闭射频测试项! - - - - - 请选择正确的文件! - - - - - QObject - - - HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM - - - - diff --git a/wrtm_class.cpp b/wrtm_class.cpp deleted file mode 100644 index 2f23908..0000000 --- a/wrtm_class.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "header.h" - -#include "interface.h" -#include "info.h" -#include "windows.h" -#include "Library_global.h" -#include "qdebug.h" -using namespace std; - -static uart_rx_function g_uart_rx_callback=NULL; -static at_result_callback g_at_result_callback=NULL; -static transmit_ls_result g_ls_result_callback=NULL; -static transmit_result_hook g_result_hook_callback=NULL; - - -class MyInfo : public uapi::Info -{ -public: - MyInfo(){}; - ~MyInfo(){}; - void onReadEvent(int eventType, void *data) override - { - uapi::SerialPortReceiveData *precvdata = NULL; - uapi::TransmitResult *ptransResult = NULL; - uapi::FileListResult *flistResult = NULL; - uapi::AtReceiveData *atrecvdata = NULL; - - switch(eventType) - { - case uapi::INFO_SERIALPORT: - precvdata=(uapi::SerialPortReceiveData*)data; - qDebug()<<"INFO_SERIALPORT "<< precvdata->data; - if(g_uart_rx_callback) - g_uart_rx_callback(precvdata->data,precvdata->dataLength); - break; - case uapi::INFO_FILE_TRANSMIT_RESULT: - ptransResult = (uapi::TransmitResult*)data; - qDebug()<<"INFO_FILE_TRANSMIT_RESULT "<< ptransResult->finishResult; - if(g_result_hook_callback) - g_result_hook_callback(ptransResult->finishResult,NULL); - break; - case uapi::INFO_FILE_LIST_RESULT: - flistResult=(uapi::FileListResult*)data; - qDebug()<<"INFO_FILE_LIST_RESULT "<< flistResult->lsInfo->name; - if(g_ls_result_callback) - g_ls_result_callback(flistResult->lsInfoNumber,(uapi_ls_info_t *)flistResult->lsInfo); - break; - case uapi::INFO_AT_RECEIVE: - atrecvdata=(uapi::AtReceiveData*)data; - qDebug()<<"INFO_AT_RECEIVE "<< atrecvdata->data; - if(g_at_result_callback) - g_at_result_callback(atrecvdata->data,atrecvdata->dataLength); - break; - } - - } -}; -static MyInfo info; -static Interface *handle= new Interface(); -uapi_errcode uapi_uart_set_currentMode(int mode) -{ - if (mode == 0) - handle->SetCurrentMode(uapi::MODE_SERIALPORT); - else - handle->SetCurrentMode(uapi::MODE_BLUETOOTH); - return SUCC; -} -uapi_errcode uapi_uart_open(const char *com, uint32_t baud) // 打开uart口, com 格式为 "\\\\.\\COM47", baud 为波特率 -{ - handle->InfoEventConnect(&info); - handle->SetCurrentMode(uapi::MODE_SERIALPORT); - int ret= handle->SerialPortOpen(com,baud); - if (ret == 0) - return SUCC; - else - return FAIL; -} -uapi_errcode uapi_uart_tx_data(void *buf, uint32_t buf_len) // uart TX 发送数据buf -{ - qDebug()<<"tx:"<SerialPortWrite((unsigned char *)buf,buf_len); - return SUCC; -} -uapi_errcode uapi_uart_set_rts_dtr(int rts_flag, int dtr_flag) // uart 设置rts和dtr开关 -{ -// handle->SetCurrentMode(uapi::MODE_SERIALPORT); - handle->SerialPortSetRtsDtr(rts_flag,dtr_flag); - return SUCC; -} -uapi_errcode uapi_uart_callback_register(uart_rx_function callback) // uart 注册回调函数 -{ - g_uart_rx_callback = callback; - return SUCC; -} -uapi_errcode uapi_uart_close(void)// 关闭uart口 -{ - - handle->SerialPortClose(); - return SUCC; -} - -uapi_errcode uapi_at_send(uint8_t module_id, uint8_t cmd_id, uint8_t *pkt, uint32_t pkt_size, at_result_callback callback) // at命令发送接口,module_id及cmd_id请参考《Sparta 产线 测试指南》10.2章 -{ - g_at_result_callback = callback; - - handle->AtMessageSend(module_id,cmd_id,pkt,pkt_size); - - return SUCC; -} - -uapi_errcode uapi_file_download(char* board_file_path, char* local_file_path, transmit_result_hook handler) // 文件下载接口,参数分别为板端文件地址(详细到文件后缀),pc端存储路径(详细到文件夹),传输结果回调函数 -{ - g_result_hook_callback = handler; - handle->FileDownload(board_file_path,local_file_path); - return SUCC; -} - -uapi_errcode uapi_file_upload(char* board_file_path,char* local_file_path, transmit_result_hook handler)// 文件上传接口,参数分别为板端文件地址(详细到文件后缀),pc端存储路径(详细到文件后缀),传输结果回调函数 -{ - g_result_hook_callback = handler; - handle->FileUpload(board_file_path,local_file_path); - return SUCC; -} - -uapi_errcode uapi_ls_send(char *path, uint32_t path_len, transmit_ls_result callback)// 查询文件列表接口,参数为板端文件路径(详细到文件夹),路径长度,get list回调函数 -{ - g_ls_result_callback = callback; - qDebug()<<"uapi_ls_send "<FileGetList(path,path_len); - - return SUCC; -} - -uapi_errcode uapi_file_delete(char *board_file_path, uint32_t board_file_path_len) // 删除指定文件接口,参数为板端文件地址(详细到文件后缀),文件路径长度 -{ - handle->FileDelete(board_file_path,board_file_path_len); - return SUCC; -} - -uapi_errcode uapi_file_transmit_stop(void)// 停止文件下载接口 -{ - handle->FileTransmitStop(); - return SUCC; -} - -uapi_errcode uapi_transmit_process(uapi_transmit_progress *data) // 获取文件传输进度,入参 data 更新为正在传输的文件的总大小和已传输大小 -{ - handle->FileTransmitProgress((uapi::FileTransmitDataCount*)data); - return SUCC; -}