ln产测工具 初始版本
authorpenglei <1624952103@qq.com>
Wed, 26 Nov 2025 12:46:17 +0000 (20:46 +0800)
committerpenglei <1624952103@qq.com>
Wed, 26 Nov 2025 12:48:56 +0000 (20:48 +0800)
63 files changed:
CMakeLists.txt [deleted file]
Demoqrc.qrc [deleted file]
Library_global.h [deleted file]
README.md [deleted file]
Setting.ini [deleted file]
at_data.cpp [deleted file]
at_data.h [deleted file]
common.h [deleted file]
custom.cpp [deleted file]
custom.h [deleted file]
debug/at_data.obj [deleted file]
debug/custom.obj [deleted file]
debug/factory_tool.exe [deleted file]
debug/factory_tool.ilk [deleted file]
debug/factory_tool.pdb [deleted file]
debug/factory_tool.vc.pdb [deleted file]
debug/main.obj [deleted file]
debug/mainwindow.obj [deleted file]
debug/moc_custom.obj [deleted file]
debug/moc_mainwindow.obj [deleted file]
debug/mythread.obj [deleted file]
debug/result_thread.obj [deleted file]
debug/wrtm_class.obj [deleted file]
demopng.rc [deleted file]
factory_tool.pro
header.h [deleted file]
icon/FAIL.ico [deleted file]
icon/succ.ico [deleted file]
icon/windows.ico [deleted file]
icon/windows.png [deleted file]
info.h [deleted file]
interface.h [deleted file]
lib/advapi32.dll [deleted file]
lib/diag.dll [deleted file]
lib/diag.lib [deleted file]
lib/libsecurec.a [deleted file]
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
mythread.cpp [deleted file]
mythread.h [deleted file]
readme.txt [deleted file]
release/LeiNiaoFactoryTool.exe [new file with mode: 0644]
release/at_data.obj [deleted file]
release/custom.obj [deleted file]
release/factory_tool.exe [deleted file]
release/main.obj [deleted file]
release/mainwindow.obj [deleted file]
release/moc_custom.obj [deleted file]
release/moc_mainwindow.obj [deleted file]
release/mythread.obj [deleted file]
release/result_thread.obj [deleted file]
release/wrtm_class.obj [deleted file]
release/产测记录/产测记录.csv [new file with mode: 0644]
release/产测记录/老化记录/老化_20251105_094030.csv [new file with mode: 0644]
release/新建文件夹.zip [new file with mode: 0644]
release/雷鸟产测工具.zip [new file with mode: 0644]
release/雷鸟产测工具/LeiNiaoFactoryTool.exe [new file with mode: 0644]
result_thread.cpp [deleted file]
result_thread.h [deleted file]
untitled_zh_CN.ts [deleted file]
wrtm_class.cpp [deleted file]

diff --git a/CMakeLists.txt b/CMakeLists.txt
deleted file mode 100644 (file)
index b893ae5..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-cmake_minimum_required(VERSION 3.5)\r
-\r
-project(LANGUAGES CXX)\r
-\r
-set(CMAKE_INCLUDE_CURRENT_DIR ON)\r
-\r
-set(CMAKE_AUTOUIC ON)\r
-set(CMAKE_AUTOMOC ON)\r
-set(CMAKE_AUTORCC ON)\r
-\r
-set(CMAKE_CXX_STANDARD 11)\r
-set(CMAKE_CXX_STANDARD_REQUIRED ON)\r
-set(RC_ICONS windows.ico)\r
-# QtCreator supports the following variables for Android, which are identical to qmake Android variables.\r
-# Check http://doc.qt.io/qt-5/deployment-android.html for more information.\r
-# They need to be set before the find_package(Qt5 ...) call.\r
-\r
-#if(ANDROID)\r
-#    set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")\r
-#    if (ANDROID_ABI STREQUAL "armeabi-v7a")\r
-#        set(ANDROID_EXTRA_LIBS\r
-#            ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so\r
-#            ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)\r
-#    endif()\r
-#endif()\r
-\r
-find_package(Qt5 COMPONENTS Widgets LinguistTools REQUIRED)\r
-\r
-set(TS_FILES untitled_zh_CN.ts)\r
-include_directories(${CMAKE_SOURCE_DIR})\r
-if(ANDROID)\r
-  add_library(SHARED\r
-    main.cpp\r
-    mainwindow.cpp\r
-    mainwindow.h\r
-    mainwindow.ui\r
-    ${TS_FILES}\r
-  )\r
-else()\r
-  add_executable(\r
-    WIN32\r
-    main.cpp\r
-    mainwindow.cpp\r
-    mainwindow.h\r
-    mainwindow.ui\r
-    mythread.h\r
-    mythread.cpp\r
-    custom.h\r
-    custom.cpp\r
-    Demoqrc.qrc\r
-    demopng.rc\r
-    at_data.cpp\r
-    at_data.h\r
-    result_thread.cpp\r
-    result_thread.h\r
-    common.h\r
-    ${TS_FILES}\r
-  )\r
-endif()\r
-\r
-target_link_libraries( PRIVATE\r
-                      Qt5::Widgets\r
-                      ${CMAKE_SOURCE_DIR}/lib/libwireless_tools.dll)\r
-target_link_libraries( PRIVATE\r
-                      Qt5::Widgets\r
-                      ${CMAKE_SOURCE_DIR}/lib/libsecurec.a)\r
-\r
-qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})\r
diff --git a/Demoqrc.qrc b/Demoqrc.qrc
deleted file mode 100644 (file)
index 7f18d42..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<RCC>\r
-    <qresource prefix="/">\r
-        <file>icon/windows.png</file>\r
-        <file>icon/windows.ico</file>\r
-        <file>icon/FAIL.ico</file>\r
-        <file>icon/succ.ico</file>\r
-    </qresource>\r
-</RCC>\r
diff --git a/Library_global.h b/Library_global.h
deleted file mode 100644 (file)
index b110ebe..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*\r
- * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.\r
- */\r
-#ifndef LIBRARY_GLOBAL_H\r
-#define LIBRARY_GLOBAL_H\r
-\r
-#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || \\r
-    defined(_WIN32) || defined(__WIN32__) || defined(__NT__)\r
-\r
-#define Q_DECL_EXPORT __declspec(dllexport)\r
-#define Q_DECL_IMPORT __declspec(dllimport)\r
-#else\r
-#define Q_DECL_EXPORT __attribute__((visibility("default")))\r
-#define Q_DECL_IMPORT __attribute__((visibility("default")))\r
-#endif\r
-\r
-#if defined(LIBRARY_LIBRARY)\r
-#define LIBRARY_EXPORT Q_DECL_EXPORT\r
-#else\r
-#define LIBRARY_EXPORT Q_DECL_IMPORT\r
-#endif\r
-\r
-namespace uapi {\r
-struct FileInfo {\r
-    unsigned short sn;\r
-    unsigned char name_len;\r
-    unsigned char is_dir;\r
-    unsigned int file_size;\r
-    char name[0xFF];\r
-};\r
-\r
-struct FileListResult {\r
-    unsigned int lsInfoNumber;\r
-    FileInfo lsInfo[0];\r
-};\r
-\r
-struct FileTransmitDataCount {\r
-    unsigned int total_size;\r
-    unsigned int transmited_size;\r
-};\r
-\r
-struct TransmitResult {\r
-    bool finishResult;\r
-};\r
-\r
-struct AtReceiveData {\r
-    unsigned int dataLength;\r
-    unsigned char *data;\r
-};\r
-\r
-struct SerialPortReceiveData {\r
-    unsigned int dataLength;\r
-    unsigned char *data;\r
-};\r
-enum InfoType {\r
-    INFO_SERIALPORT, // 单板段数据\r
-    INFO_FILE_TRANSMIT_RESULT,\r
-    INFO_FILE_LIST_RESULT,\r
-    INFO_AT_RECEIVE,\r
-};\r
-enum ConnectMode {\r
-    MODE_SERIALPORT,\r
-    MODE_BLUETOOTH\r
-};\r
-enum  ErrorCode{\r
-    ERROR_FAIL = -1,\r
-    ERROR_SUCC = 0x0,\r
-};\r
-}\r
-\r
-#endif // LIBRARY_GLOBAL_H\r
diff --git a/README.md b/README.md
deleted file mode 100644 (file)
index 4bd4606..0000000
--- a/README.md
+++ /dev/null
@@ -1,32 +0,0 @@
-## 项目名称
-> 请介绍一下你的项目吧  
-
-
-
-## 运行条件
-> 列出运行该项目所必须的条件和相关依赖  
-* 条件一
-* 条件二
-* 条件三
-
-
-
-## 运行说明
-> 说明如何运行和使用你的项目,建议给出具体的步骤说明
-* 操作一
-* 操作二
-* 操作三  
-
-
-
-## 测试说明
-> 如果有测试相关内容需要说明,请填写在这里  
-
-
-
-## 技术架构
-> 使用的技术框架或系统架构图等相关说明,请填写在这里  
-
-
-## 协作者
-> 高效的协作会激发无尽的创造力,将他们的名字记录在这里吧
diff --git a/Setting.ini b/Setting.ini
deleted file mode 100644 (file)
index e3f6e21..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-[Uart_setting]\r
-uart_com=COM41\r
-uart_baud=18\r
-spp_addr=\r
-\r
-[Download_Setting]\r
-download_board_path=/user/\r
-download_local_path=\r
-\r
-[Upload_Setting]\r
-upload_board_path=\r
-upload_local_path=\r
-\r
-[At_Setting]\r
-at_mediamusicplay=\r
-at_mediaaudiorecord=\r
-at_fsrm=\r
-at_delay_ms=\r
-at_spp_addr=\r
-custom_module_id=\r
-custom_cmd_id=\r
-custom_payload=\r
diff --git a/at_data.cpp b/at_data.cpp
deleted file mode 100644 (file)
index 1d76e0d..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-#include <at_data.h>\r
-\r
-At_Process::At_Process(QObject *parent)\r
-{\r
-    Q_UNUSED(parent);\r
-    phy_type_list<<"01"<<"02";\r
-    ble_pattern_type_list<<"02 "<<"00 "<<"01 ";\r
-    br_pattern_type_list<<"03 "<<"04 "<<"09 ";\r
-    packet_type_list<<"04 01 "<<"0B 01 "<<"0F 01 "<<"04 00 "<<"0A 00 "<<"0E 00 "<<"08 00 "<<"0B 00 "<<"0F 00 ";\r
-    br_len_array<<27<<183<<339<<54<<367<<679<<83<<552<<1021;\r
-    board_cmd_map.insert(BT_MODE_BR_TX,"AT^BTTX=");\r
-    board_cmd_map.insert(BT_MODE_BR_RX,"AT^BTRX=");\r
-    board_cmd_map.insert(BT_MODE_BLE_TX,"AT^BLETX=");\r
-    board_cmd_map.insert(BT_MODE_BLE_RX,"AT^BLERX=");\r
-    board_cmd_map.insert(BT_MODE_BTDUTMODE, "AT^BTDUTMODE=");\r
-    board_cmd_map.insert(DONGLE_MODE_SPPCONN,"AT+SPPCONN=");\r
-    board_cmd_map.insert(DONGLE_MODE_AT,"AT");\r
-    board_cmd_map.insert(DONGLE_MODE_ADDR,"AT+ADDR");\r
-    board_cmd_map.insert(BT_MODE_BTLO,"AT^BTLO=");\r
-    board_cmd_map.insert(BT_MODE_BTPWR,"AT^BTPWR=");\r
-\r
-}\r
-At_Process::~At_Process(){}\r
-QString At_Process::at_get_packet_type(int packet_type_index)\r
-{\r
-    return packet_type_list.at(packet_type_index);\r
-}\r
-int At_Process::at_get_packet_len(int packet_type_index)\r
-{\r
-    return br_len_array.at(packet_type_index);\r
-}\r
-QString At_Process::at_get_br_pattern_type(int pattern_type_index)\r
-{\r
-    return br_pattern_type_list.at(pattern_type_index);\r
-}\r
-QString At_Process::at_get_ble_pattern_type(int pattern_type_index)\r
-{\r
-    return ble_pattern_type_list.at(pattern_type_index);\r
-}\r
-\r
-QString At_Process::at_get_ble_phy_type(int phy_type_index)\r
-{\r
-    return phy_type_list.at(phy_type_index);\r
-}\r
-QString At_Process::at_get_cmd_board(at_mode_board mode)\r
-{\r
-    return board_cmd_map[mode];\r
-}\r
-QString At_Process::at_get_switch_format(QString br_switch)\r
-{\r
-    QString str;\r
-    if(br_switch.contains("OFF")){\r
-        str="00";\r
-    }else if(br_switch.contains("ON")){\r
-        str="01 ";\r
-    }\r
-    return str;\r
-}\r
-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)\r
-{\r
-    QString str;\r
-    str += at_get_switch_format(br_switch);\r
-    if(br_switch.contains("ON")){\r
-        str += QString("%1 ").arg(channel.toUInt(), 2, 16, QLatin1Char('0'));\r
-        str += at_get_packet_type(packet_type_index);\r
-        QString str_temp = QString("%1").arg(payload_len.toUInt(), 4, 16, QLatin1Char('0'));\r
-        str.insert(9, str_temp.mid(0, 2)+" ");\r
-        str.insert(9, str_temp.mid(2, 2)+" ");\r
-        str += at_get_br_pattern_type(pattern_type);\r
-        if(mode==BT_MODE_BR_TX){\r
-            str.insert(3, "02 ");\r
-        }\r
-    }\r
-    return str;\r
-}\r
-\r
-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)\r
-{\r
-    QString str=NULL;\r
-    str += at_get_switch_format(br_switch);\r
-    if(br_switch.contains("ON")){\r
-        str += QString("%1 ").arg(channel.toUInt(), 2, 16, QLatin1Char('0'));\r
-        if(mode==BT_MODE_BLE_TX){\r
-            str+= at_get_ble_pattern_type(pattern_type_index);\r
-            str+= QString("%1 ").arg(payload_len.toUInt(), 2, 16, QLatin1Char('0'));\r
-        }\r
-        str+=at_get_ble_phy_type(phy_index);\r
-    }\r
-    return str;\r
-}\r
-\r
-\r
-bool At_Process::at_send_cmd_board(at_mode_board mode,QString format)\r
-{\r
-//    char *buf=nullptr;\r
-    uint32_t buf_len=0;\r
-    bool ret=false;\r
-    QString str=at_get_cmd_board(mode);\r
-    str+=format;\r
-    str+="\r\n";\r
-    std::string bufstr = str.toStdString();\r
-    const char* buf = bufstr.c_str();\r
-    buf_len = strlen(buf);\r
-    if(uapi_uart_tx_data((void*)buf, buf_len)){\r
-        ret=true;\r
-    }\r
-    return ret;\r
-}\r
-\r
-bool At_Process::at_send_cmd_string(at_module_id module_id, at_cmd_id cmd_id,QString format)\r
-{\r
-    char *buf = nullptr;\r
-    uint32_t buf_len=0;\r
-    bool ret=false;\r
-    QByteArray arr = format.toLatin1();\r
-    buf = arr.data();\r
-    buf_len = arr.size();\r
-    if (uapi_at_send(module_id, cmd_id, (uint8_t *)buf, buf_len, at_callback) == SUCC) {\r
-        at_set_id(module_id, cmd_id);\r
-        ret=true;\r
-    }\r
-    return ret;\r
-}\r
-\r
-void At_Process::at_set_id(at_module_id at_module_id_temp, at_cmd_id at_cmd_id_temp)\r
-{\r
-    at_module_id_save = at_module_id_temp;\r
-    at_cmd_id_save = at_cmd_id_temp;\r
-}\r
-\r
-void At_Process::at_get_id(at_module_id *at_module_id, at_cmd_id *at_cmd_id)\r
-{\r
-    *at_module_id = at_module_id_save;\r
-    *at_cmd_id = at_cmd_id_save;\r
-}\r
diff --git a/at_data.h b/at_data.h
deleted file mode 100644 (file)
index 8323390..0000000
--- a/at_data.h
+++ /dev/null
@@ -1,112 +0,0 @@
-#ifndef AT_DATA_H\r
-#define AT_DATA_H\r
-\r
-#include<stdio.h>\r
-#include<stdint.h>\r
-#include<qstring.h>\r
-#include<qdebug.h>\r
-#include<result_thread.h>\r
-\r
-struct at_media_command {\r
-    uint8_t cmd[2];\r
-    uint8_t payload[0];\r
-};\r
-\r
-enum at_br_packet_type\r
-{\r
-    PACKET_DH1,\r
-    PACKET_DH3,\r
-    PACKET_DH5,\r
-    PACKET_2DH1,\r
-    PACKET_2DH3,\r
-    PACKET_2DH5,\r
-    PACKET_3DH1,\r
-    PACKET_3DH3,\r
-    PACKET_3DH5,\r
-};\r
-\r
-enum at_ble_phy\r
-{\r
-    PHY_1M,\r
-    PHY_2M,\r
-};\r
-\r
-enum  at_pattern_type\r
-{\r
-    PATTERN_TYPE_1,\r
-    PATTERN_TYPE_2,\r
-    PATTERN_TYPE_3,\r
-};\r
-\r
-enum at_mode_board\r
-{\r
-    BT_MODE_BR_TX,\r
-    BT_MODE_BR_RX,\r
-    BT_MODE_BLE_TX,\r
-    BT_MODE_BLE_RX,\r
-    BT_MODE_BTDUTMODE,\r
-    BT_MODE_BTLO,\r
-    BT_MODE_BTPWR,\r
-    DONGLE_MODE_SPPCONN,\r
-    DONGLE_MODE_AT,\r
-    DONGLE_MODE_ADDR,\r
-    MODE_MAX,\r
-};\r
-\r
-enum at_module_id\r
-{\r
-    MODULE_MCU =0x08,\r
-    MODULE_BT =0x09,\r
-    MODULE_AUDIO =0x0A,\r
-};\r
-\r
-enum at_cmd_id\r
-{\r
-    AUDIO_CMD = 0x00,\r
-    MCU_CMD_FSRM = 0x09,\r
-    MCU_CMD_STACKINFO = 0x0D,\r
-    MCU_CMD_CHECK_CONNECTED=0x40,\r
-    MCU_CMD_RETURN_VALUE=0x41,\r
-    BT_CMD_SETTXPOWER = 0x7A,\r
-    BT_CMD_DUTMODE = 0x7D,\r
-    BT_CMD_GET_RX = 0x83,\r
-    BT_CMD_BR_TX,\r
-    BT_CMD_BR_RX,\r
-    BT_CMD_BLE_TX,\r
-    BT_CMD_BLE_RX,\r
-    BT_CMD_DELAY_MS,\r
-    BT_CMD_DONGLE_MAC,\r
-    BT_CMD_RX_RESULT = 0xFF,\r
-};\r
-\r
-\r
-class At_Process\r
-{\r
-public:\r
-    At_Process(QObject *parent = 0);\r
-    ~At_Process();\r
-    QString at_get_br_format(at_mode_board bt_mode,QString br_switch,QString channel, int packet_type, QString payload_len, int pattern_type);\r
-    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);\r
-    bool at_send_cmd_string(at_module_id module_id, at_cmd_id cmd_id,QString format);\r
-    bool at_send_cmd_board(at_mode_board bt_mode,QString format);\r
-    void at_get_id(at_module_id *at_module_id, at_cmd_id *at_cmd_id);\r
-    int at_get_packet_len(int packet_type);\r
-    QString at_get_switch_format(QString br_switch);\r
-private:\r
-    at_module_id at_module_id_save;\r
-    at_cmd_id at_cmd_id_save;\r
-    QStringList phy_type_list;\r
-    QStringList ble_pattern_type_list;\r
-    QStringList br_pattern_type_list;\r
-    QStringList packet_type_list;\r
-    QVector<int> br_len_array;\r
-    QMap<at_mode_board, QString> board_cmd_map;\r
-private:\r
-    QString at_get_cmd_board(at_mode_board bt_mode);\r
-    QString at_get_ble_phy_type(int phy_type_index);\r
-    QString at_get_ble_pattern_type(int pattern_type);\r
-    QString at_get_br_pattern_type(int pattern_type);\r
-    QString at_get_packet_type(int packet_type);\r
-    void at_set_id(at_module_id at_module_id, at_cmd_id at_cmd_id);\r
-};\r
-#endif // AT_DATA_H\r
diff --git a/common.h b/common.h
deleted file mode 100644 (file)
index c9ed230..0000000
--- a/common.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef COMMON_H\r
-#define COMMON_H\r
-\r
-#include <QMetaType>\r
-#include <QDebug>\r
-\r
-typedef uint8_t* u8Piont;\r
-typedef void* vPiont;\r
-\r
-Q_DECLARE_METATYPE(u8Piont);\r
-Q_DECLARE_METATYPE(vPiont);\r
-\r
-#define MESSAGE_INFO_COLOR(STRING) "<font color=red>" STRING "</font>" "<font color=\"#7FFF00\"> </font>"\r
-#define CHECK_DONGLE_CONNECTED\r
-\r
-#endif // COMMON_H\r
diff --git a/custom.cpp b/custom.cpp
deleted file mode 100644 (file)
index 542ed25..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <custom.h>\r
-\r
-MyComboBox::MyComboBox(QWidget *paraent) : QComboBox(paraent) {}\r
-MyComboBox::~MyComboBox() {}\r
-\r
-void MyComboBox::mousePressEvent(QMouseEvent *e)\r
-{\r
-    if (e->button() == Qt::LeftButton) {\r
-        emit mouse_clicked(true);\r
-    }\r
-    QComboBox::mousePressEvent(e);\r
-}\r
-\r
-void MyComboBox::ChangeItem(QString str)\r
-{\r
-    for(int i=0;i<this->count();i++ ){\r
-        if(this->itemText(i).contains(str)){\r
-            this->setCurrentIndex(i);\r
-            break;\r
-        }\r
-    }\r
-}\r
-\r
-MyLineEdit::MyLineEdit(QWidget *parent):QLineEdit(parent)\r
-{\r
-\r
-}\r
-\r
-void MyLineEdit::keyPressEvent(QKeyEvent *event)\r
-{\r
-    qDebug()<<event->key();\r
-    if(event->key()==Qt::Key_Up){\r
-        int current_data=this->text().toInt()+1;\r
-        const QIntValidator *validator=(QIntValidator *)this->validator();\r
-        if(current_data <= validator->top()){\r
-            this->setText(QString::number(current_data,10));\r
-        }\r
-    }else if(event->key()==Qt::Key_Down){\r
-        int current_data=this->text().toInt()-1;\r
-        const QIntValidator *validator=(QIntValidator *)this->validator();\r
-        if(current_data >= validator->bottom()){\r
-            this->setText(QString::number(current_data,10));\r
-        }\r
-    }else{\r
-        QLineEdit::keyPressEvent(event);//执行\r
-    }\r
-    event->ignore();//输出后,才将继续执行主窗口的keypressEvent事件\r
-}\r
diff --git a/custom.h b/custom.h
deleted file mode 100644 (file)
index dca637f..0000000
--- a/custom.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef MYCOMBOBOX_H\r
-#define MYCOMBOBOX_H\r
-#include <QComboBox>\r
-#include <QMouseEvent>\r
-#include <qlineedit.h>\r
-#include <qDebug.h>\r
-#include <QKeyEvent>\r
-#include <QIntValidator>\r
-\r
-// 自定义 QComboBox 类,实现 clicked 信号\r
-class MyComboBox : public QComboBox\r
-{\r
-    Q_OBJECT\r
-   public:\r
-    explicit MyComboBox(QWidget *paraent = 0);\r
-    ~MyComboBox();\r
-    void ChangeItem(QString str);\r
-   protected:\r
-    virtual void mousePressEvent(QMouseEvent *e) override;\r
-   signals:\r
-    void mouse_clicked(bool);\r
-};\r
-\r
-// 自定义MyLineEdit类,实现 up down按键自动加减值\r
-class MyLineEdit : public QLineEdit\r
-{\r
-    Q_OBJECT\r
-public:\r
-    explicit MyLineEdit(QWidget *parent=0);\r
-protected:\r
-    void keyPressEvent(QKeyEvent *event);\r
-};\r
-\r
-class MyValidator : public QIntValidator\r
-{\r
-    Q_OBJECT\r
-public:\r
-    explicit MyValidator(QObject * parent = 0):QIntValidator(parent)\r
-    {\r
-    }\r
-    MyValidator(int bottom, int top, QObject * parent):QIntValidator(bottom, top, parent)\r
-    {\r
-    }\r
-    virtual void setRange(int bottom, int top)\r
-    {\r
-        QIntValidator::setRange(bottom, top);\r
-    }\r
-    ~MyValidator()\r
-    {\r
-    }\r
-    virtual State validate(QString &str, int &n) const\r
-    {\r
-        if(str.contains("+")){\r
-            return Invalid;\r
-        }\r
-        if(n > 1 && str.startsWith("0")){\r
-            return Invalid;\r
-        }\r
-        if(str.toInt()<bottom()||str.toInt()>top()){\r
-            return Invalid;\r
-        }\r
-        return QIntValidator::validate(str, n);\r
-    }\r
-//    virtual void fixup(QString &s) const\r
-//    {\r
-//        s = QString("%1").arg(bottom());\r
-//    }\r
-};\r
-\r
-#endif // MYCOMBOBOX_H\r
diff --git a/debug/at_data.obj b/debug/at_data.obj
deleted file mode 100644 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
index 4b0ae81..0000000
+++ /dev/null
@@ -1 +0,0 @@
-IDI_ICON1 ICON DISCARDABLE "icon/windows.ico"\r
index 4b23984..b9290e6 100644 (file)
@@ -1,52 +1,29 @@
-#-------------------------------------------------\r
-#\r
-# Project created by QtCreator 2024-03-04T16:59:50\r
-#\r
-#-------------------------------------------------\r
-\r
-QT       += core gui\r
-\r
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets\r
-\r
-TARGET = factory_tool\r
-TEMPLATE = app\r
-\r
-\r
-SOURCES += main.cpp\\r
-        mainwindow.cpp \\r
-    at_data.cpp \\r
-    custom.cpp \\r
-    mythread.cpp \\r
-    result_thread.cpp \\r
-    wrtm_class.cpp\r
-\r
-HEADERS  += mainwindow.h \\r
-    Library_global.h \\r
-    at_data.h \\r
-    common.h \\r
-    custom.h \\r
-    info.h \\r
-    interface.h \\r
-    mythread.h \\r
-    result_thread.h \\r
-    header.h\r
-\r
-FORMS    += mainwindow.ui\r
-\r
-DISTFILES += \\r
-    CMakeLists.txt \\r
-    readme.txt \\r
-    untitled_zh_CN.ts\r
-\r
-INCLUDEPATH += $$PWD/.\r
-DEPENDPATH += $$PWD/.\r
-\r
-\r
-LIBS += -L$$PWD/lib/\r
-LIBS += libsecurec.a\r
-LIBS += -ldiag\r
-LIBS += -lAdvapi32\r
-\r
-\r
-INCLUDEPATH += $$PWD/lib\r
-DEPENDPATH += $$PWD/lib\r
+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 (file)
index e70123a..0000000
--- a/header.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef HEADER_H\r
-#define HEADER_H\r
-#include <stdint.h>\r
-\r
-//#ifdef __cplusplus\r
-//extern "C" {\r
-//#endif\r
-/*-----------------------业务处理-------------------------------*/\r
-typedef enum {\r
-    FAIL = 0x0,\r
-    SUCC = 0x1,\r
-} uapi_errcode;\r
-\r
-typedef struct {\r
-    uint32_t total_size; // 当前传输文件总大小\r
-    uint32_t transmited_size; // 当前文件已传输大小\r
-} uapi_transmit_progress;\r
-\r
-typedef struct {\r
-    uint16_t sn; // 序号\r
-    uint8_t name_len; // 文件(夹)名长度\r
-    uint8_t is_dir; // 是否是文件夹\r
-    uint32_t file_size; // 文件大小\r
-    uint8_t name[0xFF]; // 文件(夹)名\r
-} uapi_ls_info_t;\r
-\r
-typedef uint32_t (*uart_rx_function)(void *buf, uint32_t len); //  uart RX 回调函数\r
-typedef uint32_t (*at_result_callback)(void *buf, uint32_t len); // AT 命令返回值回调函数,入参buf包括 mould_id + cmd_id + payload\r
-typedef uint32_t (*transmit_ls_result)(uint32_t size, uapi_ls_info_t *buff); // transmit get list回调函数,入参 size 为文件(夹)的数量,buff 为文件(夹)的信息\r
-typedef uint32_t (*transmit_result_hook)(bool is_finished, uintptr_t usr_data); // 传输结果回调函数,is_finished 为传输结束标志,usr_data 预留接口,目前为NULL\r
-\r
-uapi_errcode uapi_uart_open(const char *com,  uint32_t baud); // 打开uart口, com 格式为 "\\\\.\\COM47", baud 为波特率\r
-uapi_errcode uapi_uart_tx_data(void *buf, uint32_t buf_len); // uart TX 发送数据buf\r
-uapi_errcode uapi_uart_set_rts_dtr(int rts_flag, int dtr_flag); // uart 设置rts和dtr开关\r
-uapi_errcode uapi_uart_callback_register(uart_rx_function callback); // uart 注册回调函数\r
-uapi_errcode uapi_uart_close(void); // 关闭uart口\r
-uapi_errcode uapi_uart_set_currentMode(int mode); //0 SERIALPORT(单板) 1 BLUETOOTH(整机)\r
-\r
-\r
-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章\r
-uapi_errcode uapi_file_download(char* board_file_path, char* local_file_path, transmit_result_hook handler); // 文件下载接口,参数分别为板端文件地址(详细到文件后缀),pc端存储路径(详细到文件夹),传输结果回调函数\r
-uapi_errcode uapi_file_upload(char* board_file_path,char* local_file_path, transmit_result_hook handler); // 文件上传接口,参数分别为板端文件地址(详细到文件后缀),pc端存储路径(详细到文件后缀),传输结果回调函数\r
-uapi_errcode uapi_ls_send(char *path, uint32_t path_len, transmit_ls_result callback); // 查询文件列表接口,参数为板端文件路径(详细到文件夹),路径长度,get list回调函数\r
-uapi_errcode uapi_file_delete(char *board_file_path, uint32_t board_file_path_len); // 删除指定文件接口,参数为板端文件地址(详细到文件后缀),文件路径长度\r
-uapi_errcode uapi_file_transmit_stop(void); // 停止文件下载接口\r
-uapi_errcode uapi_transmit_process(uapi_transmit_progress *data); // 获取文件传输进度,入参 data 更新为正在传输的文件的总大小和已传输大小\r
-\r
-//#ifdef __cplusplus\r
-//}\r
-//#endif\r
-#endif\r
diff --git a/icon/FAIL.ico b/icon/FAIL.ico
deleted file mode 100644 (file)
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 (file)
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 (file)
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 (file)
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 (file)
index d1152e3..0000000
--- a/info.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*\r
- * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.\r
- */\r
-#ifndef INFO_H\r
-#define INFO_H\r
-\r
-namespace uapi {\r
-class Info {\r
-public:\r
-    virtual ~Info() {};\r
-    virtual void onReadEvent(int eventType, void *data) = 0;\r
-};\r
-}\r
-#endif // INFO_H\r
diff --git a/interface.h b/interface.h
deleted file mode 100644 (file)
index 404bc43..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef INTERFACE_H\r
-#define INTERFACE_H\r
-#include "info.h"\r
-#include "Library_global.h"\r
-\r
-class Application;\r
-\r
-class LIBRARY_EXPORT Interface\r
-{\r
-public:\r
-    Interface();\r
-    ~Interface();\r
-    int SerialPortInit(int byteSize, int parity, int stopBits);\r
-    int SerialPortSetRtsDtr(bool rtsFlag, bool DtrFlag);\r
-    int SerialPortOpen(const char *portName,int baud);\r
-    int SerialPortClose(void);\r
-    int SerialPortWrite(const unsigned char *data,unsigned int len);\r
-    int FileDownload(const char *boardFilePath, const char *localFilePath);\r
-    int FileGetList(const char *boardPath, unsigned int boardPathLen);\r
-    int FileUpload(const char *boardFilePath, char *localFilePath); // boardFilePath包含文件名+后缀\r
-    int FileDelete(const char *boardFilePath, unsigned int boardFilePathLen);\r
-    int FileTransmitStop(void);\r
-    int FileTransmitProgress(uapi::FileTransmitDataCount *data); // 获取文件总大小和已传输大小到data中\r
-    int AtMessageSend(unsigned char moduleId, unsigned char cmdId, const unsigned char *data, unsigned int dataLen);\r
-    int InfoEventConnect(uapi::Info *event); // 连接读取事件,返回event type和data\r
-    int SetCurrentMode(uapi::ConnectMode mode); // 设置当前连接类型(单板段or整机段)\r
-private:\r
-    Application *applicationHandle;\r
-};\r
-\r
-#endif // INTERFACE_H\r
diff --git a/lib/advapi32.dll b/lib/advapi32.dll
deleted file mode 100644 (file)
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 (file)
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 (file)
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 (file)
index 94ff990..0000000
Binary files a/lib/libsecurec.a and /dev/null differ
index 177bfa0..c264415 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -1,10 +1,35 @@
-#include "mainwindow.h"\r
-#include <QApplication>\r
-\r
-int main(int argc, char *argv[])\r
-{\r
-    QApplication a(argc, argv);\r
-    MainWindow w;\r
-    w.show();\r
-    return a.exec();\r
-}\r
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QTextCodec>
+#ifdef _WIN32
+#include <windows.h>
+#include <io.h>
+#include <fcntl.h>
+#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();
+}
index 0ccf2cf..15c091b 100644 (file)
-#include "mainwindow.h"\r
-#include "./ui_mainwindow.h"\r
-// 初始化线程、状态寄存器、配置信息\r
-MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)\r
-{\r
-    ui->setupUi(this);\r
-    result_thread = new Result_Thread(this);\r
-    result_thread->start();\r
-    result_thread->pause();\r
-    at_handler = new At_Process(this);\r
-    ui_setting_read();\r
-    at_set_bt_format();\r
-}\r
-\r
-//  结束线程\r
-MainWindow::~MainWindow()\r
-{\r
-    if (spp_timer_handle != NULL) {\r
-        spp_timer_handle->stop();\r
-        spp_timer_handle = NULL;\r
-    }\r
-    if (spp_connected_handle != NULL) {\r
-        spp_connected_handle->stop();\r
-        spp_connected_handle = NULL;\r
-    }\r
-    ui_setting_save();\r
-    result_thread->stop();\r
-    result_thread->wait();\r
-    if (transmit_timer_handle != NULL) {\r
-        transmit_timer_handle->stop();\r
-        transmit_timer_handle = NULL;\r
-    }\r
-    if (ui->pbtn_open_uart->isChecked()) {\r
-        if (uapi_uart_close() == TRUE) {\r
-        }\r
-    }\r
-    delete result_thread;\r
-    delete at_handler;\r
-    delete ui;\r
-}\r
-\r
-void MainWindow::ui_display(QString str,bool inOrOut)\r
-{\r
-//    QTime Time= QTime::currentTime();//获取系统当前的时间\r
-//    QString str_time = Time.toString("[hh:mm:ss ");//格式化时间\r
-    ui->txtb_dispaly->moveCursor(QTextCursor::End);\r
-    if(inOrOut){\r
-        ui->txtb_dispaly->setTextColor(QColor(127, 255, 0));\r
-    }else{\r
-        ui->txtb_dispaly->setTextColor(Qt::red);\r
-    }\r
-//    if(inOrOut){\r
-//        str_time.append("IN] : ");\r
-//    }else{\r
-//        str_time.append("OUT] : ");\r
-//    }\r
-//    str.prepend(str_time);\r
-//    str+="\r\n";\r
-    ui->txtb_dispaly->insertPlainText(str);\r
-    ui->txtb_dispaly->moveCursor(QTextCursor::End);\r
-}\r
-\r
-void MainWindow::ui_tab_mainwindow_complete()\r
-{\r
-    if (ui->stkw_stage->currentIndex() == PAGE_COMPLETE) {\r
-        ui->action_complete->setChecked(true);\r
-        return;\r
-    }\r
-    ui->stkw_stage->setCurrentIndex(PAGE_COMPLETE);\r
-    ui->ledit_spp_addr->setEnabled(true);\r
-    ui->connected_flag->setStyleSheet("QPushButton{background-color: rgb(255, 0, 0);}");\r
-    if (spp_connected_handle != NULL) {\r
-        spp_connected_handle->start(1500);\r
-    }\r
-    if (ui->action_board->isChecked()) {\r
-        ui->action_board->setChecked(false);\r
-    }\r
-    if(ui->pbtn_open_uart->isChecked()){\r
-        uart_close();\r
-    }\r
-}\r
-void MainWindow::ui_tab_mainwindow_board()\r
-{\r
-    if (ui->stkw_stage->currentIndex() == PAGE_BOARD) {\r
-        ui->action_board->setChecked(true);\r
-        return;\r
-    }\r
-    ui->stkw_stage->setCurrentIndex(PAGE_BOARD);\r
-    ui->ledit_spp_addr->setEnabled(false);\r
-    ui->connected_flag->setStyleSheet("QPushButton{background-color: rgb(240, 240, 240);}");\r
-    if (spp_connected_handle != NULL) {\r
-        spp_connected_handle->stop();\r
-    }\r
-    dongle_is_connected = false;\r
-    if (ui->action_complete->isChecked()) {\r
-        ui->action_complete->setChecked(false);\r
-    }\r
-    if(ui->pbtn_open_uart->isChecked()){\r
-        uart_close();\r
-    }\r
-\r
-}\r
-void MainWindow::ui_save_windows()\r
-{\r
-    QString fname = QFileDialog::getExistingDirectory(this, "请选择文件");\r
-    QFile file(fname+"/save.txt");\r
-    if (!file.open(QFile::WriteOnly | QFile::Text)) //检测文件是否打开\r
-    {\r
-        QMessageBox::information(this, "Error Message", "Please Select a Text File!");\r
-        return;\r
-    }\r
-\r
-    QTextStream out(&file); //分行写入文件\r
-    out << ui->txtb_dispaly->toPlainText();  //这里的File_edit就是之前声明的Textedit控件的名字\r
-}\r
-// 存储config配置文件\r
-void MainWindow::ui_setting_save()\r
-{\r
-    QSettings *settings = new QSettings("Setting.ini", QSettings::IniFormat);\r
-\r
-    // 写入第一组数据\r
-    settings->beginGroup("Uart_setting");\r
-    settings->setValue("uart_com", ui->cbox_uart_com_select->currentText());\r
-    settings->setValue("uart_baud", ui->cbox_uart_baud_select->currentIndex());\r
-    settings->setValue("spp_addr", ui->ledit_spp_addr->text());\r
-    settings->sync();\r
-    settings->endGroup();\r
-    // 写入第二组数据\r
-    settings->beginGroup("Download_Setting");\r
-    settings->setValue("download_board_path", ui->ledit_formboad_bordpath->text());\r
-    settings->setValue("download_local_path", ui->ledit_frombord_savefilepath->text());\r
-    settings->sync();\r
-    settings->endGroup();\r
-\r
-    settings->beginGroup("Upload_Setting");\r
-    settings->setValue("upload_board_path", ui->ledit_toboard_boardpath->text());\r
-    settings->setValue("upload_local_path", ui->ledit_toboard_filepath->text());\r
-    settings->sync();\r
-    settings->endGroup();\r
-\r
-    settings->beginGroup("At_Setting");\r
-    settings->setValue("at_mediamusicplay", ui->ledit_at_mediamusicplay->text());\r
-    settings->setValue("at_mediaaudiorecord", ui->ledit_at_mediaaudiorecord->text());\r
-    settings->setValue("at_fsrm", ui->ledit_at_fsrm->text());\r
-    settings->setValue("at_delay_ms", ui->ledit_delay_ms->text());\r
-    settings->setValue("at_spp_addr", ui->ledit_dongle_mac->text());\r
-    settings->setValue("custom_module_id", ui->ledit_at_custom_moduleId->text());\r
-    settings->setValue("custom_cmd_id", ui->ledit_at_custom_CmdId->text());\r
-    settings->setValue("custom_payload", ui->ledit_at_custom_Payload->text());\r
-    settings->sync();\r
-    settings->endGroup();\r
-\r
-    delete settings;\r
-    settings = nullptr;\r
-}\r
-// 读取config配置\r
-void MainWindow::ui_setting_read()\r
-{\r
-    uart_com_select();\r
-    QSettings *settings = new QSettings("Setting.ini", QSettings::IniFormat);\r
-    ui->cbox_uart_com_select->ChangeItem(settings->value("Uart_setting/uart_com").toString());\r
-    ui->cbox_uart_baud_select->setCurrentIndex(settings->value("Uart_setting/uart_baud").toInt());\r
-    ui->ledit_spp_addr->setText(settings->value("Uart_setting/spp_addr").toString());\r
-    ui->tbw_stage_complete->setEnabled(true);\r
-    ui->ledit_formboad_bordpath->setText(settings->value("Download_Setting/download_board_path").toString());\r
-    ui->ledit_frombord_savefilepath->setText(settings->value("Download_Setting/download_local_path").toString());\r
-    ui->ledit_toboard_boardpath->setText(settings->value("Upload_Setting/upload_board_path").toString());\r
-    ui->ledit_toboard_filepath->setText(settings->value("Upload_Setting/upload_local_path").toString());\r
-    ui->ledit_at_mediamusicplay->setText(settings->value("At_Setting/at_mediamusicplay").toString());\r
-    ui->ledit_at_mediaaudiorecord->setText(settings->value("At_Setting/at_mediaaudiorecord").toString());\r
-    ui->ledit_at_fsrm->setText(settings->value("At_Setting/at_fsrm").toString());\r
-    ui->ledit_delay_ms->setText(settings->value("At_Setting/at_delay_ms").toString());\r
-    ui->ledit_dongle_mac->setText(settings->value("At_Setting/at_spp_addr").toString());\r
-    ui->ledit_at_custom_moduleId->setText(settings->value("At_Setting/custom_module_id").toString());\r
-    ui->ledit_at_custom_CmdId->setText(settings->value("At_Setting/custom_cmd_id").toString());\r
-    ui->ledit_at_custom_Payload->setText(settings->value("At_Setting/custom_payload").toString());\r
-    ui->tbw_stage_complete->setEnabled(false);\r
-    ui->ledit_btlo_channel->setText("0");\r
-    ui->ledit_btpwr_powerchip->setText("2");\r
-}\r
-\r
-\r
-/* --------------------------------uart操作--------------------------- */\r
-void MainWindow::uart_process()\r
-{\r
-    if (ui->pbtn_open_uart->isChecked()) {\r
-        QString str_com = ui->cbox_uart_com_select->currentText();\r
-        QString str_uart_baud = ui->cbox_uart_baud_select->currentText();\r
-        uart_open(str_com,str_uart_baud);\r
-    } else {\r
-        uart_close();\r
-    }\r
-}\r
-void MainWindow::uart_open(QString com,QString com_baud)\r
-{\r
-    char buf[15] = {0};\r
-    uint32_t band = com_baud.toUInt();\r
-    com.replace("COM", "");\r
-    int comNumber = com.toInt();\r
-    if (comNumber < COM_NUMBER) {\r
-         (void)sprintf_s(buf, "COM%d", comNumber);\r
-    } else {\r
-      (void)sprintf_s(buf, "\\\\.\\COM%d", comNumber);\r
-    }\r
-    if (uapi_uart_open(buf, band)) {\r
-       uapi_uart_callback_register(uart_callback);\r
-       result_thread->resume();\r
-\r
-       if(ui->stkw_stage->currentIndex() == PAGE_COMPLETE){\r
-            ui->tbw_stage_complete->setEnabled(true);\r
-            ui->pbtn_spp_connect->setEnabled(true);\r
-//            uapi_uart_set_currentMode(1);\r
-       }else if(ui->stkw_stage->currentIndex() == PAGE_BOARD){\r
-           ui->tbw_stage_board->setEnabled(true);\r
-//           uapi_uart_set_currentMode(0);\r
-       }\r
-\r
-       ui->pbtn_open_uart->setText("关闭串口");\r
-       ui_display("open uart success.\r\n",false);\r
-       if(!ui->pbtn_open_uart->isChecked()){\r
-           ui->pbtn_open_uart->setChecked(true);\r
-       }\r
-    } else {\r
-            ui_display("open uart fail.\r\n",false);\r
-            QMessageBox::warning(this, tr("SerialPort"), tr("Open SerialPort failed"), QMessageBox::Ok);\r
-            ui->pbtn_open_uart->setChecked(false);\r
-    }\r
-}\r
-void MainWindow::uart_close()\r
-{\r
-        if (uapi_uart_close() == TRUE) {\r
-            result_thread->pause();\r
-//            ui_display("close uart success.\r\n",false);\r
-            ui->tbw_stage_complete->setEnabled(false);\r
-            ui->tbw_stage_board->setEnabled(false);\r
-            ui->pbtn_spp_connect->setEnabled(false);\r
-            ui->pbtn_open_uart->setText("打开串口");\r
-            if(ui->pbtn_open_uart->isChecked()){\r
-                ui->pbtn_open_uart->setChecked(false);\r
-            }\r
-            if (spp_connected_handle != NULL) {\r
-                spp_connected_handle->stop();\r
-                spp_connected_handle = NULL;\r
-            }\r
-            if (spp_timer_handle != NULL) {\r
-                spp_timer_handle->stop();\r
-                spp_timer_handle = NULL;\r
-            }\r
-        } else {\r
-//            ui_display("close uart fail.\r\n",false);\r
-        }\r
-}\r
-void MainWindow::uart_send_data()\r
-{\r
-    QString str;\r
-    int buf_len = 0;\r
-    char* buf = nullptr;\r
-    if(ui->stkw_stage->currentIndex() == PAGE_COMPLETE){\r
-        str = ui->tedit_input_data->toPlainText();\r
-    }else{\r
-        str = ui->tedit_input_data_board->toPlainText();\r
-    }\r
-    uapi_uart_callback_register(uart_callback);\r
-    if (ui->ckbox_hex_send->isChecked()) {\r
-        QByteArray array = str.toLatin1();\r
-        QByteArray hex_bytes = QByteArray::fromHex(array.data());\r
-        buf_len = hex_bytes.size();\r
-        buf = hex_bytes.data();\r
-        str=str.toUpper();\r
-        uapi_uart_tx_data(buf, buf_len);\r
-    } else {\r
-        if ((ui->stkw_stage->currentIndex() == PAGE_COMPLETE &&ui->ckbox_word_wrap->isChecked())||\r
-                (ui->stkw_stage->currentIndex() ==PAGE_BOARD && ui->ckbox_word_wrap_board->isChecked())) {\r
-            str+="\r\n";\r
-        }\r
-        std::string bufstr = str.toStdString();\r
-        buf =(char*) bufstr.c_str();\r
-        buf_len = strlen(buf);\r
-        uapi_uart_tx_data(buf, buf_len);\r
-    }\r
-\r
-\r
-\r
-    ui_display(str,false);\r
-}\r
-\r
-// uart收到的数据进行回显到显示栏\r
-void MainWindow::uart_rx_dispaly(int buf_len, u8Piont buf)\r
-{\r
-    uart_rx_flag = true;\r
-    if (uart_rx_Ignoring_display) {\r
-        QString str((char *)buf);\r
-        if(str.contains("ADDR")){\r
-            ui->ledit_dongle_mac->setText(str.mid(str.indexOf("=",0)+1,12));\r
-        }\r
-        return;\r
-    }\r
-    QString str;\r
-    QByteArray data((const char*)buf, buf_len);\r
-    if (ui->ckbox_Hex_Display->isChecked()) {\r
-        for (int i = 0; i < data.size(); i++) {\r
-           str += QString("%1 ").arg((quint8)data.at(i), 2, 16, QChar('0'));\r
-        }\r
-        str=str.toUpper();\r
-    } else {\r
-        for (int i = 0; i < data.size(); i++) {\r
-           str += QString(data.at(i));\r
-        }\r
-    }\r
-    ui_display(str,true);\r
-    free(buf);\r
-}\r
-\r
-void MainWindow::uart_check_dtr_rts()\r
-{\r
-    bool rts = false, dtr = false;\r
-    if (ui->ckbox_rts->isChecked()) {\r
-        rts = true;\r
-    }\r
-    if (ui->ckbox_dtr->isChecked()) {\r
-        dtr = true;\r
-    }\r
-    if (uapi_uart_set_rts_dtr(rts, dtr) == TRUE) {\r
-//        ui_display("set rts dtr success.\r\n",false);\r
-    }\r
-}\r
-\r
-void MainWindow::uart_com_select()\r
-{\r
-    ui->cbox_uart_com_select->clear();\r
-    QStringList strlist = uart_get_enable_comm_or_port();\r
-    qSort(strlist.begin(), strlist.end(),[](const QString& s1, const QString& s2){\r
-        QString a1=s1;QString a2=s2;\r
-        return a1.replace("COM","").toInt() < a2.replace("COM","").toInt(); });\r
-        ui->cbox_uart_com_select->addItems(strlist);\r
-}\r
-void MainWindow::uart_com_switch(QString com)\r
-{\r
-    QString str_uart_baud = ui->cbox_uart_baud_select->currentText();\r
-    if(ui->pbtn_open_uart->isChecked()){\r
-        uart_close();\r
-        uart_open(com,str_uart_baud);\r
-    }\r
-}\r
-void MainWindow::uart_baud_switch(QString baud)\r
-{\r
-   QString str_com = ui->cbox_uart_com_select->currentText();\r
-    if(ui->pbtn_open_uart->isChecked()){\r
-        uart_close();\r
-        uart_open(str_com,baud);\r
-    }\r
-}\r
-// nIndex为索引号 bValue选择返回值为key还是value,默认为value\r
-QString MainWindow::uart_get_comm_or_port(int nIndex, bool bValue)\r
-{\r
-    QString strCommRet = QObject::tr("");\r
-    HKEY hKey;\r
-    if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_READ, &hKey) != 0) {\r
-        QMessageBox::warning(this, tr("Register"), tr("can't open register"),QMessageBox::Ok);\r
-        return QObject::tr(""); // 无法打开注册表\r
-    }\r
-    QString strKeyMsg;   // 键名\r
-    QString strValueMsg; // 键值\r
-    TCHAR portName[256]; // 键名数组\r
-    TCHAR commName[256]; // 键值数组\r
-    ulong nKeySize = sizeof(portName);\r
-    ulong nValueSize = sizeof(commName);\r
-    ulong nType;\r
-    memset(commName,0,sizeof(commName));\r
-    memset(portName,0,sizeof(portName));\r
-    if (::RegEnumValue(hKey, nIndex, portName, &nKeySize, 0, &nType, (BYTE *)commName, &nValueSize) == 0) { // 列举键名\r
-        // 读取键名\r
-        for (uint i = 0; i < nKeySize; i++) {\r
-            if (portName[i] != 0x00)\r
-                strKeyMsg.append(portName[i]);\r
-        }\r
-        // 读取键值\r
-        for (uint j = 0; j < nValueSize; j++) {\r
-            if (commName[j] != 0x00)\r
-                strValueMsg.append(commName[j]);\r
-        }\r
-        if (bValue)\r
-            strCommRet = strValueMsg;\r
-        else\r
-            strCommRet = strKeyMsg;\r
-    } else {\r
-        ::RegCloseKey(hKey);    // 关闭注册表\r
-        return QObject::tr(""); // 无可用串口\r
-    }\r
-    return strCommRet;\r
-}\r
-\r
-QStringList MainWindow::uart_get_enable_comm_or_port()\r
-{\r
-    QStringList CommPortList;\r
-    QString strCommPath = QObject::tr("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM");\r
-    QSettings *settings = new QSettings(strCommPath, QSettings::NativeFormat);\r
-    QStringList keyList = settings->allKeys();\r
-    if (!keyList.isEmpty()) {\r
-        for (int i = 0; i < keyList.count(); i++)\r
-            CommPortList.append(uart_get_comm_or_port(i, true));\r
-    }\r
-    return CommPortList;\r
-}\r
-\r
-/* ------------------------------------------------------------------- */\r
-void MainWindow::spp_connected_callback()\r
-{\r
-    at_handler->at_send_cmd_string(MODULE_MCU,MCU_CMD_CHECK_CONNECTED,NULL);\r
-    dongle_connected_times++;\r
-    if (dongle_connected_times > 5) {\r
-        ui_display("Dongle has been disconnected.\r\n",false);\r
-        dongle_is_connected = false;\r
-    }\r
-    if (dongle_is_connected == true) {\r
-        ui->connected_flag->setStyleSheet("QPushButton{background-color: rgb(0, 255, 64);}");\r
-        uapi_uart_set_currentMode(1);//设置整机模式,通过蓝牙透传指令\r
-    } else {\r
-        ui->connected_flag->setStyleSheet("QPushButton{background-color: rgb(255, 0, 0);}");\r
-    }\r
-}\r
-\r
-void MainWindow::spp_timer_callback()\r
-{\r
-    bool final_ret = false;\r
-    if (dongle_try_count > 5) {\r
-        ui_display("\r\nNo device, check the dongle is connected.\r\n",false);\r
-        final_ret = true;\r
-    }\r
-    if (uart_rx_flag == false) {\r
-        at_handler->at_send_cmd_string(MODULE_MCU,MCU_CMD_CHECK_CONNECTED,NULL);\r
-        dongle_try_count++;\r
-    } else if (spp_try_count % 3 == 0) { // 每3次重新发送一次连接AT命令\r
-        QString str = ui->ledit_spp_addr->text();\r
-        at_handler->at_send_cmd_board(DONGLE_MODE_SPPCONN,str);\r
-    } else if (spp_try_count > 10) { // 循环10次还有数据上报则表示连接失败\r
-        ui_display("\r\nconnect fail.\r\n",false);\r
-        final_ret = true;\r
-    }\r
-    if (dongle_is_connected == true) {\r
-        final_ret = true;\r
-        ui_display("\r\nDongle has been connected.\r\n",false);\r
-        if (spp_connected_handle == NULL) {\r
-            spp_connected_handle = new QTimer(this);\r
-            connect(spp_connected_handle, SIGNAL(timeout()), this, SLOT(spp_connected_callback()));\r
-            spp_connected_handle->start(1500);\r
-        }\r
-    }\r
-    if (final_ret == false) {\r
-        at_handler->at_send_cmd_board(DONGLE_MODE_AT,NULL);\r
-        spp_try_count++;\r
-        uart_rx_flag = false;\r
-        ui_display(".",false);\r
-    } else {\r
-        spp_timer_handle->stop();\r
-        spp_timer_handle = NULL;\r
-        uart_rx_Ignoring_display = false;\r
-        ui->pbtn_spp_connect->setEnabled(true);\r
-    }\r
-}\r
-\r
-void MainWindow::spp_connect()\r
-{\r
-    uart_rx_Ignoring_display = true;\r
-    dongle_is_connected = false;\r
-    dongle_try_count = 0;\r
-    spp_try_count = 0;\r
-    uapi_uart_callback_register(uart_callback);\r
-    at_handler->at_send_cmd_board(DONGLE_MODE_ADDR,NULL);\r
-    ui_display("spp connectting...",false);\r
-    spp_timer_handle = new QTimer(this);\r
-    connect(spp_timer_handle, SIGNAL(timeout()), this, SLOT(spp_timer_callback()));\r
-    // spp查询定时器周期为1500ms\r
-    spp_timer_handle->start(1500);\r
-    ui->pbtn_spp_connect->setEnabled(false);\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/* -------------------------业务处理部分------------------------------------- */\r
-\r
-void MainWindow::transmit_ls_rx_diaplay(int transmit_ls_size, vPiont transmit_ls_buff)\r
-{\r
-    if(transmit_ls_size>0){\r
-        ui_display("文件名            大小\r\n",true);\r
-    }\r
-    uapi_ls_info_t *transmit_ls_buff_temp = (uapi_ls_info_t *)transmit_ls_buff;\r
-    for (int i = 0; i < transmit_ls_size; i++) {\r
-        QString strName = QString::fromUtf8((char *)(transmit_ls_buff_temp[i].name));\r
-        QString strFileLen = QString::number(transmit_ls_buff_temp[i].file_size,10);\r
-        if (transmit_ls_buff_temp[i].is_dir) {\r
-            strName.append("/");\r
-        }\r
-        ui_display(strName+"            "+strFileLen+"\r\n",true);\r
-        ui->cbox_fromborad_filelist->addItem(strName,strFileLen);\r
-    }\r
-    free(transmit_ls_buff);\r
-}\r
-\r
-void MainWindow::transmit_rx_display(bool transmit_result_flag)\r
-{\r
-    uint32_t total_size=0;\r
-    uint32_t current_size=0;\r
-    transmit_get_data_count(&total_size,&current_size);\r
-    uint32_t value = transmit_result_flag ? total_size : 0;\r
-    if (transmit_timer_handle) {\r
-        transmit_timer_handle->stop();\r
-        transmit_timer_handle = NULL;\r
-    }\r
-    if (transmit_download_or_upload == TRANSMIT_UPLOAD) {\r
-        ui->pbar_toboard->setValue(value);\r
-        ui->pbtn_toboard_Upload->setEnabled(true);\r
-    }\r
-    if (transmit_download_or_upload == TRANSMIT_DOWNLOAD) {\r
-        ui->pbar_fromboard->setValue(value);\r
-        ui->pbtn_fromboard_download->setEnabled(true);\r
-    }\r
-    if (transmit_result_flag) {\r
-        ui_display("download or upload file success.\r\n",false);\r
-    } else {\r
-        ui_display("download or upload file fail.\r\n",false);\r
-    }\r
-    transmit_download_or_upload = TRANSMIT_IDLE;\r
-    ui->pbtn_fromboard_delete->setEnabled(true);\r
-    ui->pbtn_fromboard_getfilelist->setEnabled(true);\r
-}\r
-\r
-void MainWindow::transmit_fromboard_name_change()\r
-{\r
-    ui->cbox_fromborad_filelist->clear();\r
-}\r
-\r
-void MainWindow::transmit_fromboard_selectfilepath()\r
-{\r
-    QString fname = QFileDialog::getExistingDirectory(this, "请选择文件");\r
-    ui->ledit_frombord_savefilepath->setText(fname);\r
-}\r
-\r
-void MainWindow::transmit_fromboard_getfilelist()\r
-{\r
-    QString str = ui->ledit_formboad_bordpath->text();\r
-    if (str.isEmpty()) {\r
-        QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-    ui->cbox_fromborad_filelist->clear();\r
-\r
-    std::string bufstr = str.toStdString();\r
-    char* buf =(char*) bufstr.c_str();\r
-\r
-    int ret = uapi_ls_send(buf, strlen(buf), ls_callback);\r
-    if (ret == FAIL) {\r
-        QMessageBox::warning(this, tr("ls"), tr("ls fail!\r\n"), QMessageBox::Ok);\r
-    }\r
-    tansmit_fromborad_borad_list.push_back(str);\r
-    QCompleter *com = new QCompleter(tansmit_fromborad_borad_list, this);\r
-    com->setCaseSensitivity(Qt::CaseInsensitive);\r
-    delete ui->ledit_formboad_bordpath->completer();\r
-    ui->ledit_formboad_bordpath->setCompleter(com);\r
-}\r
-\r
-void MainWindow::transmit_fromboard_download()\r
-{\r
-    QString str_savepath = ui->ledit_frombord_savefilepath->text();\r
-    QString str_file_path = ui->ledit_formboad_bordpath->text();\r
-    QString str_file_name = ui->cbox_fromborad_filelist->currentText();\r
-    if (str_savepath.isEmpty() || str_file_path.isEmpty() || str_file_name.isEmpty()) {\r
-        QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-    if (str_file_name.contains("/")) {\r
-        QMessageBox::warning(this, tr("Board File Name"), tr("请选择正确的文件!"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-    qDebug()<<ui->cbox_fromborad_filelist->currentData().toInt();\r
-    if(ui->cbox_fromborad_filelist->currentData().toInt()==0){\r
-        QMessageBox::warning(this, tr("Board File Name"), tr("filesize 0"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-    if(!str_file_path.endsWith("/")){\r
-        str_file_path.append("/");\r
-    }\r
-    str_file_path.append(str_file_name);\r
-    std::string buf_temp = str_file_path.toStdString();\r
-//    QByteArray buf_temp  = str_file_path.toUtf8() ;\r
-    char *str_file_buff = (char *)buf_temp.c_str();\r
-    std::string buf_temp2 = str_savepath.toStdString();\r
-//    QByteArray buf_temp2  = str_file_path.toUtf8();\r
-    char *str_save_buff = (char *)buf_temp2.c_str();\r
-    int ret = uapi_file_download(str_file_buff, str_save_buff, transmit_callback);\r
-    if (ret == FAIL) {\r
-        QMessageBox::warning(this, tr("Downloade"), tr("文件下载启动失败!"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-    transmit_progress_start();\r
-    transmit_download_or_upload = TRANSMIT_DOWNLOAD;\r
-    transmit_fromborad_local_list.push_back(str_savepath);\r
-    QCompleter *com = new QCompleter(transmit_fromborad_local_list, this);\r
-    com->setCaseSensitivity(Qt::CaseInsensitive);\r
-    delete ui->ledit_frombord_savefilepath->completer();\r
-    ui->ledit_frombord_savefilepath->setCompleter(com);\r
-    ui->pbtn_fromboard_download->setEnabled(false);\r
-    ui->pbtn_fromboard_delete->setEnabled(false);\r
-    ui->pbtn_fromboard_getfilelist->setEnabled(false);\r
-}\r
-\r
-void MainWindow::transmit_fromboard_delete()\r
-{\r
-    QString str_file_path = ui->ledit_formboad_bordpath->text();\r
-    QString str_file_name = ui->cbox_fromborad_filelist->currentText();\r
-    if (str_file_path.isEmpty() || str_file_name.isEmpty()) {\r
-        QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-    if (str_file_name.contains("/")) {\r
-        str_file_name.chop(1);\r
-    } else {\r
-        str_file_path.append("/");\r
-    }\r
-    str_file_path.append(str_file_name);\r
-\r
-    std::string bufstr = str_file_path.toStdString();\r
-    char* str_file_buff =(char*) bufstr.c_str();\r
-\r
-//    char *str_file_buff = (char *)str_file_path.toUtf8().data();//.toStdString().c_str();\r
-    int buflen = strlen(str_file_buff);\r
-    int ret = uapi_file_delete(str_file_buff, buflen); // ls\r
-    if (ret == FAIL) {\r
-        QMessageBox::warning(this, tr("delete"), tr("delete file fail!\r\n"), QMessageBox::Ok);\r
-    }\r
-    ui->cbox_fromborad_filelist->removeItem(ui->cbox_fromborad_filelist->currentIndex());\r
-}\r
-\r
-void MainWindow::transmit_fromboard_stop()\r
-{\r
-    if (transmit_timer_handle) {\r
-        transmit_timer_handle->stop();\r
-        transmit_timer_handle = NULL;\r
-    }\r
-    transmit_download_or_upload = TRANSMIT_IDLE;\r
-    ui->pbar_fromboard->setValue(0);\r
-    ui->pbtn_fromboard_download->setEnabled(true);\r
-    ui->pbtn_fromboard_delete->setEnabled(true);\r
-    ui->pbtn_fromboard_getfilelist->setEnabled(true);\r
-    uapi_file_transmit_stop();\r
-}\r
-\r
-void MainWindow::transmit_toboard_choosefile()\r
-{\r
-    QString fname = QFileDialog::getOpenFileName(this, "请选择文件");\r
-    ui->ledit_toboard_filepath->setText(fname);\r
-}\r
-\r
-void MainWindow::transmit_toboard_upload()\r
-{\r
-    QString board_file_path = ui->ledit_toboard_boardpath->text();\r
-    QString local_file_path = ui->ledit_toboard_filepath->text();\r
-    if (board_file_path.isEmpty() || local_file_path.isEmpty()) {\r
-        QMessageBox::warning(this, tr("File Path"), tr("File Path Empty!"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-\r
-    std::string bufboard_file_path = board_file_path.toStdString();\r
-    char* buf_board_file_path =(char*) bufboard_file_path.c_str();\r
-\r
-    std::string buflocal_file_path = local_file_path.toStdString();\r
-    char* buf_local_file_path =(char*) buflocal_file_path.c_str();\r
-\r
-//    char *buf_board_file_path = (char *)board_file_path.toUtf8().data();//.toStdString().c_str();\r
-//    char *buf_local_file_path = (char *)local_file_path.toUtf8().data();//.toStdString().c_str();\r
-    int ret = uapi_file_upload(buf_board_file_path, buf_local_file_path, transmit_callback);\r
-    if (ret == FAIL) {\r
-        QMessageBox::warning(this, tr("Upload"), tr("文件上传启动失败!\r\n"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-    transmit_progress_start();\r
-    transmit_download_or_upload = TRANSMIT_UPLOAD;\r
-    transmit_toboard_local_list.push_back(local_file_path);\r
-    transmit_toboard_borad_list.push_back(board_file_path);\r
-    QCompleter *com1 = new QCompleter(transmit_toboard_local_list, this);\r
-    com1->setCaseSensitivity(Qt::CaseInsensitive);\r
-    delete ui->ledit_toboard_filepath->completer();\r
-    ui->ledit_toboard_filepath->setCompleter(com1);\r
-    QCompleter *com2 = new QCompleter(transmit_toboard_borad_list, this);\r
-    com2->setCaseSensitivity(Qt::CaseInsensitive);\r
-    delete ui->ledit_toboard_boardpath->completer();\r
-    ui->ledit_toboard_boardpath->setCompleter(com2);\r
-    ui->pbtn_toboard_Upload->setEnabled(false);\r
-}\r
-\r
-void MainWindow::transmit_toboard_stop()\r
-{\r
-    if (transmit_timer_handle) {\r
-        transmit_timer_handle->stop();\r
-        transmit_timer_handle = NULL;\r
-    }\r
-    transmit_download_or_upload = TRANSMIT_IDLE;\r
-    ui->pbar_toboard->setValue(0);\r
-    ui->pbtn_toboard_Upload->setEnabled(true);\r
-    uapi_file_transmit_stop();\r
-}\r
-\r
-void MainWindow::transmit_update_progress()\r
-{\r
-    uint32_t total_size=0;\r
-    uint32_t current_size=0;\r
-    transmit_get_data_count(&total_size,&current_size);\r
-    if (transmit_download_or_upload == TRANSMIT_UPLOAD) {\r
-        ui->pbar_toboard->setMaximum(total_size);\r
-        ui->pbar_toboard->setValue(current_size);\r
-    }\r
-    if (transmit_download_or_upload == TRANSMIT_DOWNLOAD) {\r
-        ui->pbar_fromboard->setMaximum(total_size);\r
-        ui->pbar_fromboard->setValue(current_size);\r
-    }\r
-}\r
-void MainWindow::transmit_progress_start()\r
-{\r
-    transmit_timer_handle = new QTimer(this);\r
-    connect(transmit_timer_handle, SIGNAL(timeout()), this, SLOT(transmit_update_progress()));\r
-    // 进度条更新时间为60ms\r
-    transmit_timer_handle->start(60);\r
-}\r
-void MainWindow::at_check_send_status(bool flag)\r
-{\r
-    if(flag){\r
-        ui_display("at cmd send success.\r\n",false);\r
-    }else{\r
-        QMessageBox::warning(this, tr("AT"), tr("AT send fail!\r\n"), QMessageBox::Ok);\r
-        ui_display("at cmd send fail.\r\n",false);\r
-    }\r
-}\r
-\r
-void MainWindow::dongle_suspend()\r
-{\r
-    if(ui->stkw_stage->currentIndex() == PAGE_COMPLETE){\r
-         ui->tbw_stage_complete->setEnabled(false);\r
-         ui->pbtn_spp_connect->setEnabled(true);\r
-    }else if(ui->stkw_stage->currentIndex() == PAGE_BOARD){\r
-        ui->tbw_stage_board->setEnabled(false);\r
-    }\r
-}\r
-\r
-void MainWindow::dongle_resume()\r
-{\r
-    if(ui->stkw_stage->currentIndex() == PAGE_COMPLETE){\r
-         ui->tbw_stage_complete->setEnabled(true);\r
-         ui->pbtn_spp_connect->setEnabled(true);\r
-    }else if(ui->stkw_stage->currentIndex() == PAGE_BOARD){\r
-        ui->tbw_stage_board->setEnabled(true);\r
-    }\r
-}\r
-\r
-void MainWindow::at_rx_display(int at_buf_len, u8Piont at_buf)\r
-{\r
-    Q_UNUSED(at_buf_len);\r
-    at_module_id at_module_id_temp;\r
-    at_cmd_id at_cmd_id_temp;\r
-    at_handler->at_get_id(&at_module_id_temp, &at_cmd_id_temp);\r
-    if (at_buf[0] == MODULE_BT && at_buf[1] == BT_CMD_RX_RESULT) { // 耦合测试RxCount\r
-        uint32_t rx_count = at_buf[2] + (at_buf[3] << 8);\r
-        ui->ledit_display_rx_count->setText(QString::number(rx_count));\r
-    } else if (at_buf[0] == MODULE_MCU && at_buf[1] == MCU_CMD_CHECK_CONNECTED) { // Dongle是否已连接\r
-        dongle_is_connected = true;\r
-        dongle_connected_times = 0;\r
-        dongle_resume();\r
-    } else if (at_buf[0] == MODULE_MCU && at_buf[1] == MCU_CMD_RETURN_VALUE) {\r
-        for (int i = 0; i < 40; i++) {\r
-            qDebug("buf[%d] is %d.\r\n", i, at_buf[i]);\r
-        }\r
-        ui_display("cmd executed " + (QString)(at_buf[2] == 0 ? "Succ!" : "Fail!") + "\r\n",false);\r
-        if (at_buf[3] != 0) {\r
-            QByteArray data((const char*)&at_buf[4], at_buf[3]);\r
-            ui_display(QString(data),false);\r
-        }\r
-    } else if (at_buf[0] == at_module_id_temp && at_buf[1] == at_cmd_id_temp) {\r
-        ui_display("at receive success.\r\n",false);\r
-    } else {\r
-        ui_display("at receive fail.\r\n",false);\r
-    }\r
-    free(at_buf);\r
-}\r
-\r
-void MainWindow::at_stackinfo_send()\r
-{\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_MCU,MCU_CMD_STACKINFO,NULL));\r
-}\r
-\r
-void MainWindow::at_fsrm_send()\r
-{\r
-    QString str = ui->ledit_at_fsrm->text();\r
-    if (str.isEmpty()) {\r
-        QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_MCU,MCU_CMD_FSRM,str));\r
-}\r
-\r
-void MainWindow::at_mediamusicplay_send()\r
-{\r
-    uint8_t media_buf_cmd[2] = {0x00, 0x00};\r
-    QString str = ui->ledit_at_mediamusicplay->text();\r
-    if (str.isEmpty()) {\r
-        QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-    QString media_sub_str;\r
-    QByteArray data((const char*)media_buf_cmd, 2);\r
-    for (int i = 0; i < data.size(); i++) {\r
-        media_sub_str += QString(data.at(i));\r
-    }\r
-    str.prepend(media_sub_str);\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_AUDIO,AUDIO_CMD,str));\r
-}\r
-\r
-void MainWindow::at_mediamusicstop_send()\r
-{\r
-    uint8_t media_buf_cmd[2] = {0x00, 0x03};\r
-    QString media_sub_str;\r
-    QByteArray data((const char*)media_buf_cmd, 2);\r
-    for (int i = 0; i < data.size(); i++) {\r
-        media_sub_str += QString(data.at(i));\r
-    }\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_AUDIO,AUDIO_CMD,media_sub_str));\r
-}\r
-\r
-void MainWindow::at_mediaaudiorecord_send()\r
-{\r
-    uint8_t media_buf_cmd[2] = {0x01, 0x00};\r
-    QString str = ui->ledit_at_mediaaudiorecord->text();\r
-    if (str.isEmpty()) {\r
-        QMessageBox::warning(this, tr("File Path"), tr("文件路径为空!"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-    QString media_sub_str;\r
-    QByteArray data((const char*)media_buf_cmd, 2);\r
-    for (int i = 0; i < data.size(); i++) {\r
-        media_sub_str += QString(data.at(i));\r
-    }\r
-    str.prepend(media_sub_str);\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_AUDIO,AUDIO_CMD,str));\r
-}\r
-\r
-/* ----------------------- 耦合测试设置 ------------------------------------------------- */\r
-void MainWindow::at_bt_delay_ms_complete()\r
-{\r
-    QString str = ui->ledit_delay_ms->text();\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_DELAY_MS,str));\r
-}\r
-\r
-void MainWindow::at_set_dongle_addr_complete()\r
-{\r
-    QString str = ui->ledit_dongle_mac->text();\r
-    if (str.isEmpty() || str.size() != 12) {\r
-        QMessageBox::warning(this, tr("File Path"), tr("MAC地址为空!"), QMessageBox::Ok);\r
-        return;\r
-    }\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_DONGLE_MAC,str));\r
-}\r
-void MainWindow::at_set_bt_format()\r
-{\r
-    ui->ledit_br_rx_channel_complete->setValidator(new MyValidator(0,78,this));\r
-    ui->ledit_br_tx_channel_complete->setValidator(new MyValidator(0,78,this));\r
-    ui->ledit_ble_rx_channel_complete->setValidator(new MyValidator(0,39,this));\r
-    ui->ledit_ble_tx_channel_complete->setValidator(new MyValidator(0,39,this));\r
-    ui->ledit_br_rx_PayloadLen_complete->setValidator(new MyValidator(0,27,this));\r
-    ui->ledit_br_tx_PayloadLen_complete->setValidator(new MyValidator(0,27,this));\r
-    ui->ledit_ble_tx_PayloadLen_complete->setValidator(new MyValidator(0,255,this));\r
-\r
-    ui->ledit_br_rx_channel_board->setValidator(new MyValidator(0,78,this));\r
-    ui->ledit_br_tx_channel_board->setValidator(new MyValidator(0,78,this));\r
-    ui->ledit_ble_rx_channel_board->setValidator(new MyValidator(0,39,this));\r
-    ui->ledit_ble_tx_channel_board->setValidator(new MyValidator(0,39,this));\r
-    ui->ledit_br_rx_PayloadLen_board->setValidator(new MyValidator(0,27,this));\r
-    ui->ledit_br_tx_PayloadLen_board->setValidator(new MyValidator(0,27,this));\r
-    ui->ledit_ble_tx_PayloadLen_board->setValidator(new MyValidator(0,255,this));\r
-    ui->ledit_btlo_channel->setValidator(new MyValidator(0,78,this));\r
-}\r
-\r
-void MainWindow::at_check_bt_len(int packtype_index)\r
-{\r
-    QComboBox *cbox = qobject_cast<QComboBox *>(sender());\r
-    int len=at_handler->at_get_packet_len(packtype_index);\r
-    QString name = cbox->objectName();\r
-    if(name == "cbox_br_tx_PacketType_complete"){\r
-        const MyValidator *validator=(MyValidator *)ui->ledit_br_tx_PayloadLen_complete->validator();\r
-        delete validator;\r
-        ui->ledit_br_tx_PayloadLen_complete->setPlaceholderText("Length(0-"+QString::number(len)+")");\r
-        ui->ledit_br_tx_PayloadLen_complete->setValidator(new MyValidator(0,len,this));\r
-    }else if(name == "cbox_br_rx_PacketType_complete"){\r
-        const MyValidator *validator=(MyValidator *)ui->ledit_br_rx_PayloadLen_complete->validator();\r
-        delete validator;\r
-        ui->ledit_br_rx_PayloadLen_complete->setPlaceholderText("Length(0-"+QString::number(len)+")");\r
-        ui->ledit_br_rx_PayloadLen_complete->setValidator(new MyValidator(0,len,this));\r
-    }else if(name == "cbox_br_tx_PacketType_board"){\r
-        const MyValidator *validator=(MyValidator *)ui->ledit_br_tx_PayloadLen_board->validator();\r
-        delete validator;\r
-        ui->ledit_br_tx_PayloadLen_board->setPlaceholderText("Length(0-"+QString::number(len)+")");\r
-        ui->ledit_br_tx_PayloadLen_board->setValidator(new MyValidator(0,len,this));\r
-    }else if(name == "cbox_br_rx_PacketType_board"){\r
-        const MyValidator *validator=(MyValidator *)ui->ledit_br_rx_PayloadLen_board->validator();\r
-        delete validator;\r
-        ui->ledit_br_rx_PayloadLen_board->setPlaceholderText("Length(0-"+QString::number(len)+")");\r
-        ui->ledit_br_rx_PayloadLen_board->setValidator(new MyValidator(0,len,this));\r
-    }\r
-}\r
-\r
-/* -----------------------耦合测试-整机段------------------------------------------------ */\r
-void MainWindow::at_get_rx_count_complete()\r
-{\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_GET_RX, NULL));\r
-}\r
-\r
-void MainWindow::at_bt_tx_complete()\r
-{\r
-    QString br_tx_switch = ui->cbox_br_tx_on_or_off_complete->currentText();\r
-    QString channel = ui->ledit_br_tx_channel_complete->text();\r
-    int packet_type_index = ui->cbox_br_tx_PacketType_complete->currentIndex();\r
-    QString payload_len = ui->ledit_br_tx_PayloadLen_complete->text();\r
-    int pattern_type_index = ui->cbox_br_tx_pattern_type_complete->currentIndex();\r
-    QString format=at_handler->at_get_br_format(BT_MODE_BR_TX,br_tx_switch,channel,packet_type_index,payload_len,pattern_type_index);\r
-    if(format==NULL){\r
-        QMessageBox::warning(this, tr("AT"), tr("length错误!"), QMessageBox::Ok);\r
-    }\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_BR_TX,format));\r
-    dongle_is_connected = false;\r
-    dongle_suspend();\r
-}\r
-\r
-void MainWindow::at_bt_rx_complete()\r
-{\r
-    QString br_tx_switch = ui->cbox_br_tx_on_or_off_complete->currentText();\r
-    QString channel = ui->ledit_br_rx_channel_complete->text();\r
-    int packet_type_index = ui->cbox_br_rx_PacketType_complete->currentIndex();\r
-    QString payload_len = ui->ledit_br_rx_PayloadLen_complete->text();\r
-    int pattern_type_index = ui->cbox_br_rx_pattern_type_complete->currentIndex();\r
-    QString format=at_handler->at_get_br_format(BT_MODE_BR_RX,br_tx_switch,channel,packet_type_index,payload_len,pattern_type_index);\r
-    if(format==NULL){\r
-        QMessageBox::warning(this, tr("AT"), tr("length错误!"), QMessageBox::Ok);\r
-    }\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_BR_RX,format));\r
-    dongle_is_connected = false;\r
-    dongle_suspend();\r
-}\r
-\r
-void MainWindow::at_ble_tx_complete()\r
-{\r
-    QString br_tx_switch = ui->cbox_ble_tx_on_or_off_complete->currentText();\r
-    QString channel = ui->ledit_ble_tx_channel_complete->text();\r
-    int pattern_type_index = ui->cbox_ble_tx_pattern_type_complete->currentIndex();\r
-    QString payload_len = ui->ledit_ble_tx_PayloadLen_complete->text();\r
-    int phy_type_index = ui->cbox_ble_tx_PacketType_complete->currentIndex();\r
-    QString format=at_handler->at_get_ble_format(BT_MODE_BLE_TX,br_tx_switch,channel,pattern_type_index,payload_len,phy_type_index);\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_BLE_TX,format));\r
-    dongle_is_connected = false;\r
-    dongle_suspend();\r
-}\r
-\r
-void MainWindow::at_ble_rx_complete()\r
-{\r
-    QString br_tx_switch = ui->cbox_ble_rx_on_or_off_complete->currentText();\r
-    QString channel = ui->ledit_ble_rx_channel_complete->text();\r
-    int phy_type_index = ui->cbox_ble_rx_PacketType_complete->currentIndex();\r
-    QString format=at_handler->at_get_ble_format(BT_MODE_BLE_RX,br_tx_switch,channel,0,0,phy_type_index);\r
-    at_check_send_status(at_handler->at_send_cmd_string(MODULE_BT,BT_CMD_BLE_RX,format));\r
-    dongle_is_connected = false;\r
-    dongle_suspend();\r
-}\r
-\r
-void MainWindow::at_custom_send()\r
-{\r
-    QString moduleId = ui->ledit_at_custom_moduleId->text();\r
-    QString cmdId = ui->ledit_at_custom_CmdId->text();\r
-    QString payload = ui->ledit_at_custom_Payload->text();\r
-    bool ok;\r
-    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));\r
-}\r
-/* -----------------------传导测试-单板段------------------------------------------------ */\r
-void MainWindow::at_bt_tx_board()\r
-{\r
-    QString br_tx_switch = ui->cbox_br_tx_on_or_off_board->currentText();\r
-    if (br_tx_switch.contains("ON") && bt_test_switch == true) {\r
-        QMessageBox::warning(this, tr("操作错误"), tr("应先关闭射频测试项!"), QMessageBox::Ok);\r
-    }\r
-    bt_test_switch = br_tx_switch.contains("ON") ? true : false;\r
-    QString channel = ui->ledit_br_tx_channel_board->text();\r
-    int packet_type_index = ui->cbox_br_tx_PacketType_board->currentIndex();\r
-    QString payload_len = ui->ledit_br_tx_PayloadLen_board->text();\r
-    int pattern_type_index = ui->cbox_br_tx_pattern_type_board->currentIndex();\r
-    QString format=at_handler->at_get_br_format(BT_MODE_BR_TX,br_tx_switch,channel,packet_type_index,payload_len,pattern_type_index);\r
-    if(format==NULL){\r
-        QMessageBox::warning(this, tr("AT"), tr("length错误!"), QMessageBox::Ok);\r
-    }\r
-    at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BR_TX,format));\r
-}\r
-void MainWindow::at_bt_rx_board()\r
-{\r
-    QString br_rx_switch = ui->cbox_br_rx_on_or_off_board->currentText();\r
-    if (br_rx_switch.contains("ON") && bt_test_switch == true) {\r
-        QMessageBox::warning(this, tr("操作错误"), tr("应先关闭射频测试项!"), QMessageBox::Ok);\r
-    }\r
-    bt_test_switch = br_rx_switch.contains("ON") ? true : false;\r
-    QString channel = ui->ledit_br_rx_channel_board->text();\r
-    int packet_type_index = ui->cbox_br_rx_PacketType_board->currentIndex();\r
-    QString payload_len = ui->ledit_br_rx_PayloadLen_board->text();\r
-    int pattern_type_index = ui->cbox_br_rx_pattern_type_board->currentIndex();\r
-    QString format=at_handler->at_get_br_format(BT_MODE_BR_RX,br_rx_switch,channel,packet_type_index,payload_len,pattern_type_index);\r
-    if(format==NULL){\r
-        QMessageBox::warning(this, tr("AT"), tr("length错误!"), QMessageBox::Ok);\r
-    }\r
-    at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BR_RX,format));\r
-}\r
-void MainWindow::at_ble_tx_board()\r
-{\r
-    QString ble_tx_switch = ui->cbox_ble_tx_on_or_off_board->currentText();\r
-    if (ble_tx_switch.contains("ON") && bt_test_switch == true) {\r
-        QMessageBox::warning(this, tr("操作错误"), tr("应先关闭射频测试项!"), QMessageBox::Ok);\r
-    }\r
-    bt_test_switch = ble_tx_switch.contains("ON") ? true : false;\r
-    QString channel = ui->ledit_ble_tx_channel_board->text();\r
-    int pattern_type_index = ui->cbox_ble_tx_pattern_type_board->currentIndex();\r
-    QString payload_len = ui->ledit_ble_tx_PayloadLen_board->text();\r
-    int phy_type_index = ui->cbox_ble_tx_PacketType_board->currentIndex();\r
-    QString format=at_handler->at_get_ble_format(BT_MODE_BLE_TX,ble_tx_switch,channel,pattern_type_index,payload_len,phy_type_index);\r
-    at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BLE_TX,format));\r
-}\r
-void MainWindow::at_ble_rx_board()\r
-{\r
-    QString ble_rx_switch = ui->cbox_ble_rx_on_or_off_board->currentText();\r
-    if (ble_rx_switch.contains("ON") && bt_test_switch == true) {\r
-        QMessageBox::warning(this, tr("操作错误"), tr("应先关闭射频测试项!"), QMessageBox::Ok);\r
-    }\r
-    bt_test_switch = ble_rx_switch.contains("ON") ? true : false;\r
-    QString channel = ui->ledit_ble_rx_channel_board->text();\r
-    int phy_type_index = ui->cbox_ble_rx_PacketType_board->currentIndex();\r
-    QString format=at_handler->at_get_ble_format(BT_MODE_BLE_RX,ble_rx_switch,channel,0,0,phy_type_index);\r
-    at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BLE_RX,format));\r
-}\r
-\r
-void MainWindow::at_bt_dutmode_board()\r
-{\r
-    QString bt_dutmode_switch = ui->cbox_btdutmode_on_or_off_board->currentText();\r
-    if (bt_dutmode_switch.contains("ON") && bt_test_switch == true) {\r
-        QMessageBox::warning(this, tr("操作错误"), tr("应先关闭射频测试项!"), QMessageBox::Ok);\r
-    }\r
-    bt_test_switch = bt_dutmode_switch.contains("ON") ? true : false;\r
-    QString format=at_handler->at_get_switch_format(bt_dutmode_switch);\r
-    at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BTDUTMODE,format));\r
-}\r
-void MainWindow::at_bt_btlo_board()\r
-{\r
-    QString format;\r
-    format += ui->ledit_btlo_channel->text()+",";\r
-    format += "7,";\r
-    if(ui->cbox_btlo_on_or_off_board->currentText().contains("ON")){\r
-        format+="1";\r
-    }else{\r
-        format+="2";\r
-    }\r
-    at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BTLO,format));\r
-}\r
-\r
-void MainWindow::at_bt_btpwr_board()\r
-{\r
-    QString format;\r
-    format += ui->ledit_btpwr_powerchip->text()+",";\r
-    if(ui->cbox_btpwr_on_or_off_board->currentText().contains("ON")){\r
-        format+="1";\r
-    }else{\r
-        format+="0";\r
-    }\r
-    at_check_send_status(at_handler->at_send_cmd_board(BT_MODE_BTPWR,format));\r
-}\r
-\r
-void MainWindow::at_bt_wakeup()\r
-{\r
-    QString format= "012345678901234567890123456789";\r
-    at_check_send_status(at_handler->at_send_cmd_board(MODE_MAX,format));\r
-}\r
-\r
-void MainWindow::at_bt_sleep()\r
-{\r
-    QString format= "AT^RMVO";\r
-    at_check_send_status(at_handler->at_send_cmd_board(MODE_MAX,format));\r
-}\r
-/* ----------------------------------------------------------------------------------- */\r
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include <QMessageBox>
+#include <QDateTime>
+#include <QDebug>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QGridLayout>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QRegExp>
+#include <QTextStream>
+#include <QStandardPaths>
+#include <QDir>
+#include <QFile>
+#include <QDesktopServices>
+#include <QUrl>
+#include <QCoreApplication>
+#include <QTextCodec>
+
+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");
+}
index 8a58b37..2c87f27 100644 (file)
-#ifndef MAINWINDOW_H\r
-#define MAINWINDOW_H\r
-\r
-#include <Windows.h>\r
-#include <custom.h>\r
-#include <stdio.h>\r
-#include <QCompleter>\r
-#include <QMainWindow>\r
-#include <QSettings>\r
-#include <QTimer>\r
-#include "header.h"\r
-#include "result_thread.h"\r
-#include "common.h"\r
-#include "at_data.h"\r
-#include "QFileDialog"\r
-#include "QMessageBox"\r
-#include "QTime"\r
-\r
-#define COM_NUMBER 10\r
-\r
-// 封装了UI上需要调用的所有函数接口\r
-QT_BEGIN_NAMESPACE\r
-namespace Ui {\r
-class MainWindow;\r
-}\r
-QT_END_NAMESPACE\r
-\r
-class MainWindow : public QMainWindow {\r
-    Q_OBJECT\r
-\r
-public:\r
-    MainWindow(QWidget *parent = nullptr);\r
-    ~MainWindow();\r
-\r
-private:\r
-    Ui::MainWindow *ui;\r
-    /* ------------------------uart------------------------------- */\r
-    Result_Thread *result_thread;\r
-    // 是否忽略uart数据,不回显\r
-    bool uart_rx_Ignoring_display {false};\r
-    // 是否有uart通路数据上报\r
-    bool uart_rx_flag {false};\r
-    bool dongle_is_connected {false};\r
-    int dongle_connected_times {0};\r
-    QStringList uart_get_enable_comm_or_port();\r
-    QString uart_get_comm_or_port(int nIndex, bool bValue);\r
-    void uart_open(QString com,QString com_band);\r
-    void uart_close();\r
-    /* ------------------------spp-------------------------------- */\r
-    QTimer *spp_timer_handle {NULL};\r
-    QTimer *spp_connected_handle {NULL};\r
-    int dongle_try_count {0};\r
-    int spp_try_count {0};\r
-\r
-    /* -----------------------transmit---------------------------- */\r
-    QStringList transmit_fromborad_local_list;\r
-    QStringList tansmit_fromborad_borad_list;\r
-    QStringList transmit_toboard_local_list;\r
-    QStringList transmit_toboard_borad_list;\r
-    typedef enum{\r
-        TRANSMIT_IDLE,\r
-        TRANSMIT_DOWNLOAD,\r
-        TRANSMIT_UPLOAD,\r
-    }transmit_mode;\r
-    // download is 1,uplaod is 2\r
-    transmit_mode transmit_download_or_upload {TRANSMIT_IDLE};\r
-    QTimer *transmit_timer_handle {NULL};\r
-    void transmit_progress_start();\r
-    /* -------------------------UI------------------------------- */\r
-    enum ui_page{\r
-        PAGE_COMPLETE,\r
-        PAGE_BOARD,\r
-    };\r
-    void ui_setting_save();\r
-    void ui_setting_read();\r
-    void ui_display(QString str,bool inOrOut);\r
-    /* -------------------------AT------------------------------- */\r
-    At_Process *at_handler;\r
-    void at_check_send_status(bool flag);\r
-    void at_set_bt_format();\r
-    bool bt_test_switch {false};\r
-    /* ------------------------end------------------------------ */\r
-\r
-private slots:\r
-    /* --------------------------UI------------------------------ */\r
-    void ui_tab_mainwindow_complete();\r
-    void ui_tab_mainwindow_board();\r
-    void ui_save_windows();\r
-    /* -------------------------uart----------------------------- */\r
-    void uart_process();\r
-    void uart_send_data();\r
-    void uart_rx_dispaly(int buf_len, u8Piont buf);\r
-    void uart_check_dtr_rts();\r
-    void uart_com_select();\r
-    void uart_com_switch(QString com);\r
-    void uart_baud_switch(QString baud);\r
-    /* -------------------------spp------------------------------- */\r
-    void spp_connect();\r
-    void spp_timer_callback();\r
-    void spp_connected_callback();\r
-    void dongle_suspend();\r
-    void dongle_resume();\r
-    /* -----------------------at/transmit---------------------------- */\r
-    void at_rx_display(int at_buf_len, u8Piont at_buf);\r
-    void at_stackinfo_send();\r
-    void at_fsrm_send();\r
-    void at_mediamusicplay_send();\r
-    void at_mediamusicstop_send();\r
-    void at_mediaaudiorecord_send();\r
-    void at_custom_send();\r
-    void transmit_ls_rx_diaplay(int transmit_ls_size, vPiont transmit_ls_buff);\r
-    void transmit_rx_display(bool transmit_result_flag);\r
-    void transmit_update_progress();\r
-    void transmit_fromboard_name_change();\r
-    void transmit_fromboard_selectfilepath();\r
-    void transmit_fromboard_getfilelist();\r
-    void transmit_fromboard_download();\r
-    void transmit_fromboard_delete();\r
-    void transmit_fromboard_stop();\r
-    void transmit_toboard_choosefile();\r
-    void transmit_toboard_upload();\r
-    void transmit_toboard_stop();\r
-    /* ----------------------- 耦合测试设置 --------------------------- */\r
-    void at_set_dongle_addr_complete();\r
-    void at_bt_delay_ms_complete();\r
-    void at_check_bt_len(int packtype_index);\r
-    /* -----------------------耦合测试-整机段-------------------------- */\r
-    void at_get_rx_count_complete();\r
-    void at_bt_tx_complete();  // BT长发(非信令)\r
-    void at_bt_rx_complete();  // BT长收(非信令)\r
-    void at_ble_tx_complete(); // BLE长发(非信令)\r
-    void at_ble_rx_complete(); // BLE长收(非信令)\r
-    /* -----------------------传导测试-单板段-------------------------- */\r
-    void at_bt_tx_board();  // BT长发(非信令)\r
-    void at_bt_rx_board();  // BT长收(非信令)\r
-    void at_ble_tx_board(); // BLE长发(非信令)\r
-    void at_ble_rx_board(); // BLE长收(非信令)\r
-    void at_bt_dutmode_board();\r
-    void at_bt_btlo_board();\r
-    void at_bt_btpwr_board();\r
-    void at_bt_wakeup();\r
-    void at_bt_sleep();\r
-    /* ------------------------------------------------------------- */\r
-};\r
-#endif // MAINWINDOW_H\r
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QSerialPort>
+#include <QSerialPortInfo>
+#include <QTimer>
+#include <QDialog>
+#include <QPushButton>
+#include <QDateTime>
+#include <QStandardPaths>
+#include <QDir>
+#include <QTextStream>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QLabel>
+
+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
index 0eaae6b..52a6a1a 100644 (file)
-<?xml version="1.0" encoding="UTF-8"?>\r
-<ui version="4.0">\r
- <class>MainWindow</class>\r
- <widget class="QMainWindow" name="MainWindow">\r
-  <property name="geometry">\r
-   <rect>\r
-    <x>0</x>\r
-    <y>0</y>\r
-    <width>890</width>\r
-    <height>707</height>\r
-   </rect>\r
-  </property>\r
-  <property name="font">\r
-   <font>\r
-    <family>黑体</family>\r
-    <weight>50</weight>\r
-    <bold>false</bold>\r
-   </font>\r
-  </property>\r
-  <property name="windowTitle">\r
-   <string>Factory_Tools</string>\r
-  </property>\r
-  <property name="windowIcon">\r
-   <iconset>\r
-    <normaloff>:/icon/windows.ico</normaloff>:/icon/windows.ico</iconset>\r
-  </property>\r
-  <property name="windowOpacity">\r
-   <double>1.000000000000000</double>\r
-  </property>\r
-  <property name="layoutDirection">\r
-   <enum>Qt::LeftToRight</enum>\r
-  </property>\r
-  <widget class="QWidget" name="centralwidget">\r
-   <widget class="QTextBrowser" name="txtb_dispaly">\r
-    <property name="geometry">\r
-     <rect>\r
-      <x>0</x>\r
-      <y>0</y>\r
-      <width>631</width>\r
-      <height>371</height>\r
-     </rect>\r
-    </property>\r
-    <property name="font">\r
-     <font>\r
-      <family>Times New Roman</family>\r
-      <pointsize>10</pointsize>\r
-     </font>\r
-    </property>\r
-    <property name="mouseTracking">\r
-     <bool>true</bool>\r
-    </property>\r
-    <property name="styleSheet">\r
-     <string notr="true">QTextBrowser{background-color:rgb(26, 26, 26);\r
-                       color:rgb(127, 255, 0)}</string>\r
-    </property>\r
-    <property name="verticalScrollBarPolicy">\r
-     <enum>Qt::ScrollBarAlwaysOn</enum>\r
-    </property>\r
-    <property name="textInteractionFlags">\r
-     <set>Qt::TextBrowserInteraction</set>\r
-    </property>\r
-   </widget>\r
-   <widget class="QStackedWidget" name="stkw_stage">\r
-    <property name="geometry">\r
-     <rect>\r
-      <x>0</x>\r
-      <y>370</y>\r
-      <width>891</width>\r
-      <height>311</height>\r
-     </rect>\r
-    </property>\r
-    <property name="font">\r
-     <font>\r
-      <family>黑体</family>\r
-      <weight>50</weight>\r
-      <bold>false</bold>\r
-     </font>\r
-    </property>\r
-    <property name="currentIndex">\r
-     <number>0</number>\r
-    </property>\r
-    <widget class="QWidget" name="page_compelte">\r
-     <widget class="QTabWidget" name="tbw_stage_complete">\r
-      <property name="enabled">\r
-       <bool>false</bool>\r
-      </property>\r
-      <property name="geometry">\r
-       <rect>\r
-        <x>0</x>\r
-        <y>0</y>\r
-        <width>891</width>\r
-        <height>291</height>\r
-       </rect>\r
-      </property>\r
-      <property name="sizePolicy">\r
-       <sizepolicy hsizetype="Fixed" vsizetype="Fixed">\r
-        <horstretch>0</horstretch>\r
-        <verstretch>0</verstretch>\r
-       </sizepolicy>\r
-      </property>\r
-      <property name="font">\r
-       <font>\r
-        <family>黑体</family>\r
-        <pointsize>12</pointsize>\r
-        <weight>50</weight>\r
-        <bold>false</bold>\r
-       </font>\r
-      </property>\r
-      <property name="cursor">\r
-       <cursorShape>ArrowCursor</cursorShape>\r
-      </property>\r
-      <property name="currentIndex">\r
-       <number>3</number>\r
-      </property>\r
-      <widget class="QWidget" name="tab_complete_debug">\r
-       <attribute name="title">\r
-        <string>Debug</string>\r
-       </attribute>\r
-       <widget class="QTextEdit" name="tedit_input_data">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>0</x>\r
-          <y>0</y>\r
-          <width>771</width>\r
-          <height>261</height>\r
-         </rect>\r
-        </property>\r
-       </widget>\r
-       <widget class="QPushButton" name="pbtn_send_data">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>790</x>\r
-          <y>30</y>\r
-          <width>75</width>\r
-          <height>23</height>\r
-         </rect>\r
-        </property>\r
-        <property name="font">\r
-         <font>\r
-          <family>Times New Roman</family>\r
-          <pointsize>10</pointsize>\r
-          <weight>50</weight>\r
-          <bold>false</bold>\r
-         </font>\r
-        </property>\r
-        <property name="text">\r
-         <string>发送</string>\r
-        </property>\r
-       </widget>\r
-       <widget class="QPushButton" name="pbtn_clear_senddata">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>790</x>\r
-          <y>83</y>\r
-          <width>75</width>\r
-          <height>23</height>\r
-         </rect>\r
-        </property>\r
-        <property name="font">\r
-         <font>\r
-          <family>Times New Roman</family>\r
-          <pointsize>10</pointsize>\r
-          <weight>50</weight>\r
-          <bold>false</bold>\r
-         </font>\r
-        </property>\r
-        <property name="text">\r
-         <string>清除发送</string>\r
-        </property>\r
-       </widget>\r
-       <widget class="QCheckBox" name="ckbox_word_wrap">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>789</x>\r
-          <y>157</y>\r
-          <width>88</width>\r
-          <height>16</height>\r
-         </rect>\r
-        </property>\r
-        <property name="font">\r
-         <font>\r
-          <family>Times New Roman</family>\r
-          <pointsize>10</pointsize>\r
-          <weight>50</weight>\r
-          <bold>false</bold>\r
-         </font>\r
-        </property>\r
-        <property name="text">\r
-         <string>加回车换行</string>\r
-        </property>\r
-        <property name="tristate">\r
-         <bool>false</bool>\r
-        </property>\r
-       </widget>\r
-      </widget>\r
-      <widget class="QWidget" name="tab_complete_toboard">\r
-       <attribute name="title">\r
-        <string>To Board</string>\r
-       </attribute>\r
-       <widget class="QProgressBar" name="pbar_toboard">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>20</x>\r
-          <y>210</y>\r
-          <width>831</width>\r
-          <height>23</height>\r
-         </rect>\r
-        </property>\r
-        <property name="value">\r
-         <number>0</number>\r
-        </property>\r
-        <property name="invertedAppearance">\r
-         <bool>false</bool>\r
-        </property>\r
-       </widget>\r
-       <widget class="QGroupBox" name="groupBox_4">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>20</x>\r
-          <y>20</y>\r
-          <width>831</width>\r
-          <height>161</height>\r
-         </rect>\r
-        </property>\r
-        <property name="font">\r
-         <font>\r
-          <family>Times New Roman</family>\r
-          <pointsize>10</pointsize>\r
-          <weight>50</weight>\r
-          <bold>false</bold>\r
-         </font>\r
-        </property>\r
-        <property name="title">\r
-         <string>Upload File</string>\r
-        </property>\r
-        <widget class="QLabel" name="label">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>10</x>\r
-           <y>40</y>\r
-           <width>121</width>\r
-           <height>21</height>\r
-          </rect>\r
-         </property>\r
-         <property name="font">\r
-          <font>\r
-           <family>Times New Roman</family>\r
-           <pointsize>10</pointsize>\r
-           <weight>50</weight>\r
-           <bold>false</bold>\r
-          </font>\r
-         </property>\r
-         <property name="text">\r
-          <string>Local File Path:</string>\r
-         </property>\r
-        </widget>\r
-        <widget class="QLabel" name="label_2">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>10</x>\r
-           <y>100</y>\r
-           <width>121</width>\r
-           <height>20</height>\r
-          </rect>\r
-         </property>\r
-         <property name="font">\r
-          <font>\r
-           <family>Times New Roman</family>\r
-           <pointsize>10</pointsize>\r
-           <weight>50</weight>\r
-           <bold>false</bold>\r
-          </font>\r
-         </property>\r
-         <property name="text">\r
-          <string>Board File Path:</string>\r
-         </property>\r
-        </widget>\r
-        <widget class="QPushButton" name="pbtn_toboard_stop">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>730</x>\r
-           <y>100</y>\r
-           <width>75</width>\r
-           <height>23</height>\r
-          </rect>\r
-         </property>\r
-         <property name="font">\r
-          <font>\r
-           <family>Times New Roman</family>\r
-           <pointsize>10</pointsize>\r
-           <weight>50</weight>\r
-           <bold>false</bold>\r
-          </font>\r
-         </property>\r
-         <property name="text">\r
-          <string>stop</string>\r
-         </property>\r
-        </widget>\r
-        <widget class="QLineEdit" name="ledit_toboard_boardpath">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>140</x>\r
-           <y>100</y>\r
-           <width>471</width>\r
-           <height>20</height>\r
-          </rect>\r
-         </property>\r
-        </widget>\r
-        <widget class="QPushButton" name="pbtn_toboard_choosefile">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>640</x>\r
-           <y>40</y>\r
-           <width>161</width>\r
-           <height>23</height>\r
-          </rect>\r
-         </property>\r
-         <property name="font">\r
-          <font>\r
-           <family>Times New Roman</family>\r
-           <pointsize>10</pointsize>\r
-           <weight>50</weight>\r
-           <bold>false</bold>\r
-          </font>\r
-         </property>\r
-         <property name="text">\r
-          <string>Choose File</string>\r
-         </property>\r
-        </widget>\r
-        <widget class="QPushButton" name="pbtn_toboard_Upload">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>640</x>\r
-           <y>100</y>\r
-           <width>75</width>\r
-           <height>23</height>\r
-          </rect>\r
-         </property>\r
-         <property name="font">\r
-          <font>\r
-           <family>Times New Roman</family>\r
-           <pointsize>10</pointsize>\r
-           <weight>50</weight>\r
-           <bold>false</bold>\r
-          </font>\r
-         </property>\r
-         <property name="text">\r
-          <string>Upload</string>\r
-         </property>\r
-         <property name="checkable">\r
-          <bool>false</bool>\r
-         </property>\r
-        </widget>\r
-        <widget class="QLineEdit" name="ledit_toboard_filepath">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>140</x>\r
-           <y>40</y>\r
-           <width>471</width>\r
-           <height>20</height>\r
-          </rect>\r
-         </property>\r
-        </widget>\r
-       </widget>\r
-      </widget>\r
-      <widget class="QWidget" name="tab_complete_fromboard">\r
-       <attribute name="title">\r
-        <string>From Board</string>\r
-       </attribute>\r
-       <widget class="QGroupBox" name="groupBox_2">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>20</x>\r
-          <y>20</y>\r
-          <width>701</width>\r
-          <height>71</height>\r
-         </rect>\r
-        </property>\r
-        <property name="font">\r
-         <font>\r
-          <family>Times New Roman</family>\r
-          <pointsize>10</pointsize>\r
-          <weight>50</weight>\r
-          <bold>false</bold>\r
-         </font>\r
-        </property>\r
-        <property name="title">\r
-         <string>File Storage</string>\r
-        </property>\r
-        <widget class="QLabel" name="label_4">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>10</x>\r
-           <y>30</y>\r
-           <width>121</width>\r
-           <height>21</height>\r
-          </rect>\r
-         </property>\r
-         <property name="font">\r
-          <font>\r
-           <family>Times New Roman</family>\r
-           <pointsize>10</pointsize>\r
-           <weight>50</weight>\r
-           <bold>false</bold>\r
-          </font>\r
-         </property>\r
-         <property name="text">\r
-          <string>Local File Path:</string>\r
-         </property>\r
-        </widget>\r
-        <widget class="QLineEdit" name="ledit_frombord_savefilepath">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>140</x>\r
-           <y>30</y>\r
-           <width>421</width>\r
-           <height>20</height>\r
-          </rect>\r
-         </property>\r
-        </widget>\r
-        <widget class="QPushButton" name="pbtn_fromboard_selectfilepath">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>580</x>\r
-           <y>30</y>\r
-           <width>91</width>\r
-           <height>23</height>\r
-          </rect>\r
-         </property>\r
-         <property name="font">\r
-          <font>\r
-           <family>Times New Roman</family>\r
-           <pointsize>10</pointsize>\r
-           <weight>50</weight>\r
-           <bold>false</bold>\r
-          </font>\r
-         </property>\r
-         <property name="text">\r
-          <string>....</string>\r
-         </property>\r
-        </widget>\r
-       </widget>\r
-       <widget class="QGroupBox" name="groupBox_3">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>20</x>\r
-          <y>110</y>\r
-          <width>701</width>\r
-          <height>101</height>\r
-         </rect>\r
-        </property>\r
-        <property name="font">\r
-         <font>\r
-          <family>Times New Roman</family>\r
-          <pointsize>10</pointsize>\r
-          <weight>50</weight>\r
-          <bold>false</bold>\r
-         </font>\r
-        </property>\r
-        <property name="title">\r
-         <string>File Selector</string>\r
-        </property>\r
-        <widget class="QLabel" name="label_11">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>40</x>\r
-           <y>20</y>\r
-           <width>71</width>\r
-           <height>20</height>\r
-          </rect>\r
-         </property>\r
-         <property name="font">\r
-          <font>\r
-           <family>Times New Roman</family>\r
-           <pointsize>10</pointsize>\r
-           <weight>50</weight>\r
-           <bold>false</bold>\r
-          </font>\r
-         </property>\r
-         <property name="text">\r
-          <string>File Path:</string>\r
-         </property>\r
-        </widget>\r
-        <widget class="QLineEdit" name="ledit_formboad_bordpath">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>140</x>\r
-           <y>20</y>\r
-           <width>531</width>\r
-           <height>20</height>\r
-          </rect>\r
-         </property>\r
-        </widget>\r
-        <widget class="QComboBox" name="cbox_fromborad_filelist">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>140</x>\r
-           <y>60</y>\r
-           <width>411</width>\r
-           <height>22</height>\r
-          </rect>\r
-         </property>\r
-        </widget>\r
-        <widget class="QPushButton" name="pbtn_fromboard_getfilelist">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>570</x>\r
-           <y>60</y>\r
-           <width>101</width>\r
-           <height>23</height>\r
-          </rect>\r
-         </property>\r
-         <property name="font">\r
-          <font>\r
-           <family>Times New Roman</family>\r
-           <pointsize>9</pointsize>\r
-           <weight>50</weight>\r
-           <bold>false</bold>\r
-          </font>\r
-         </property>\r
-         <property name="text">\r
-          <string>Get file List</string>\r
-         </property>\r
-        </widget>\r
-        <widget class="QLabel" name="label_12">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>40</x>\r
-           <y>60</y>\r
-           <width>71</width>\r
-           <height>20</height>\r
-          </rect>\r
-         </property>\r
-         <property name="font">\r
-          <font>\r
-           <family>Times New Roman</family>\r
-           <pointsize>10</pointsize>\r
-           <weight>50</weight>\r
-           <bold>false</bold>\r
-          </font>\r
-         </property>\r
-         <property name="text">\r
-          <string>File Name:</string>\r
-         </property>\r
-        </widget>\r
-        <widget class="QPushButton" name="pushButton_29">\r
-         <property name="geometry">\r
-          <rect>\r
-           <x>290</x>\r
-           <y>130</y>\r
-           <width>75</width>\r
-           <height>23</height>\r
-          </rect>\r
-         </property>\r
-         <property name="text">\r
-          <string>PushButton</string>\r
-         </property>\r
-        </widget>\r
-       </widget>\r
-       <widget class="QProgressBar" name="pbar_fromboard">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>20</x>\r
-          <y>220</y>\r
-          <width>711</width>\r
-          <height>20</height>\r
-         </rect>\r
-        </property>\r
-        <property name="value">\r
-         <number>0</number>\r
-        </property>\r
-       </widget>\r
-       <widget class="QWidget" name="layoutWidget">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>760</x>\r
-          <y>20</y>\r
-          <width>95</width>\r
-          <height>201</height>\r
-         </rect>\r
-        </property>\r
-        <layout class="QVBoxLayout" name="verticalLayout">\r
-         <item>\r
-          <widget class="QPushButton" name="pbtn_fromboard_download">\r
-           <property name="font">\r
-            <font>\r
-             <family>Times New Roman</family>\r
-             <pointsize>10</pointsize>\r
-             <weight>50</weight>\r
-             <bold>false</bold>\r
-            </font>\r
-           </property>\r
-           <property name="text">\r
-            <string>Download</string>\r
-           </property>\r
-           <property name="checkable">\r
-            <bool>false</bool>\r
-           </property>\r
-          </widget>\r
-         </item>\r
-         <item>\r
-          <widget class="QPushButton" name="pbtn_fromboard_delete">\r
-           <property name="font">\r
-            <font>\r
-             <family>Times New Roman</family>\r
-             <pointsize>10</pointsize>\r
-             <weight>50</weight>\r
-             <bold>false</bold>\r
-            </font>\r
-           </property>\r
-           <property name="text">\r
-            <string>Delete</string>\r
-           </property>\r
-          </widget>\r
-         </item>\r
-         <item>\r
-          <widget class="QPushButton" name="pbtn_fromboard_stop">\r
-           <property name="font">\r
-            <font>\r
-             <family>Times New Roman</family>\r
-             <pointsize>10</pointsize>\r
-             <weight>50</weight>\r
-             <bold>false</bold>\r
-            </font>\r
-           </property>\r
-           <property name="text">\r
-            <string>Stop</string>\r
-           </property>\r
-          </widget>\r
-         </item>\r
-        </layout>\r
-       </widget>\r
-      </widget>\r
-      <widget class="QWidget" name="tab_complete_at_cmd">\r
-       <attribute name="title">\r
-        <string>AT命令</string>\r
-       </attribute>\r
-       <widget class="QTabWidget" name="tbw_at_cmd">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>0</x>\r
-          <y>0</y>\r
-          <width>891</width>\r
-          <height>271</height>\r
-         </rect>\r
-        </property>\r
-        <property name="font">\r
-         <font>\r
-          <family>黑体</family>\r
-          <pointsize>10</pointsize>\r
-          <weight>50</weight>\r
-          <bold>false</bold>\r
-         </font>\r
-        </property>\r
-        <property name="tabPosition">\r
-         <enum>QTabWidget::West</enum>\r
-        </property>\r
-        <property name="tabShape">\r
-         <enum>QTabWidget::Triangular</enum>\r
-        </property>\r
-        <property name="currentIndex">\r
-         <number>0</number>\r
-        </property>\r
-        <property name="elideMode">\r
-         <enum>Qt::ElideNone</enum>\r
-        </property>\r
-        <widget class="QWidget" name="tab_at_cmd_mcu">\r
-         <attribute name="title">\r
-          <string>MCU</string>\r
-         </attribute>\r
-         <widget class="QGroupBox" name="groupBox">\r
-          <property name="geometry">\r
-           <rect>\r
-            <x>20</x>\r
-            <y>10</y>\r
-            <width>831</width>\r
-            <height>211</height>\r
-           </rect>\r
-          </property>\r
-          <property name="title">\r
-           <string>Debug</string>\r
-          </property>\r
-          <widget class="QWidget" name="horizontalLayoutWidget">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>30</y>\r
-             <width>791</width>\r
-             <height>31</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,1,1,1">\r
-            <property name="spacing">\r
-             <number>10</number>\r
-            </property>\r
-            <item>\r
-             <widget class="QPushButton" name="pbtn_at_stackinfo">\r
-              <property name="text">\r
-               <string>StackInfo</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item>\r
-             <widget class="QPushButton" name="pushButton_2">\r
-              <property name="text">\r
-               <string>待开发</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item>\r
-             <widget class="QPushButton" name="pushButton_7">\r
-              <property name="text">\r
-               <string>待开发</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item>\r
-             <widget class="QPushButton" name="pushButton_6">\r
-              <property name="text">\r
-               <string>待开发</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item>\r
-             <widget class="QPushButton" name="pushButton_9">\r
-              <property name="text">\r
-               <string>待开发</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-          <widget class="QWidget" name="layoutWidget">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>90</y>\r
-             <width>371</width>\r
-             <height>30</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QGridLayout" name="gridLayout_3">\r
-            <item row="0" column="0">\r
-             <widget class="QLineEdit" name="ledit_at_fsrm"/>\r
-            </item>\r
-            <item row="0" column="1">\r
-             <widget class="QPushButton" name="pbtn_at_fsrm">\r
-              <property name="text">\r
-               <string>FSRM</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-          <widget class="QWidget" name="layoutWidget">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>150</y>\r
-             <width>731</width>\r
-             <height>25</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="2,0,1,1,6">\r
-            <item>\r
-             <widget class="QPushButton" name="pbtn_at_custom_send">\r
-              <property name="text">\r
-               <string>发送</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item>\r
-             <spacer name="horizontalSpacer_4">\r
-              <property name="orientation">\r
-               <enum>Qt::Horizontal</enum>\r
-              </property>\r
-              <property name="sizeType">\r
-               <enum>QSizePolicy::Minimum</enum>\r
-              </property>\r
-              <property name="sizeHint" stdset="0">\r
-               <size>\r
-                <width>30</width>\r
-                <height>20</height>\r
-               </size>\r
-              </property>\r
-             </spacer>\r
-            </item>\r
-            <item>\r
-             <widget class="QLineEdit" name="ledit_at_custom_moduleId">\r
-              <property name="font">\r
-               <font>\r
-                <family>黑体</family>\r
-                <pointsize>8</pointsize>\r
-                <weight>50</weight>\r
-                <bold>false</bold>\r
-               </font>\r
-              </property>\r
-              <property name="placeholderText">\r
-               <string>module id</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item>\r
-             <widget class="QLineEdit" name="ledit_at_custom_CmdId">\r
-              <property name="font">\r
-               <font>\r
-                <family>黑体</family>\r
-                <pointsize>8</pointsize>\r
-                <weight>50</weight>\r
-                <bold>false</bold>\r
-               </font>\r
-              </property>\r
-              <property name="placeholderText">\r
-               <string>cmd id</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item>\r
-             <widget class="QLineEdit" name="ledit_at_custom_Payload">\r
-              <property name="placeholderText">\r
-               <string>payload</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-         </widget>\r
-        </widget>\r
-        <widget class="QWidget" name="tab_at_cmd_media">\r
-         <attribute name="title">\r
-          <string>MEDIA</string>\r
-         </attribute>\r
-         <widget class="QGroupBox" name="groupBox_5">\r
-          <property name="geometry">\r
-           <rect>\r
-            <x>20</x>\r
-            <y>10</y>\r
-            <width>821</width>\r
-            <height>161</height>\r
-           </rect>\r
-          </property>\r
-          <property name="title">\r
-           <string>Media</string>\r
-          </property>\r
-          <widget class="QWidget" name="layoutWidget">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>30</y>\r
-             <width>591</width>\r
-             <height>32</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QGridLayout" name="gridLayout_2" columnstretch="4,1,1">\r
-            <property name="leftMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <property name="topMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <property name="rightMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <property name="bottomMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <item row="0" column="0">\r
-             <widget class="QLineEdit" name="ledit_at_mediamusicplay"/>\r
-            </item>\r
-            <item row="0" column="1">\r
-             <widget class="QPushButton" name="pbtn_at_mediamusicplay">\r
-              <property name="text">\r
-               <string>Music Play</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="2">\r
-             <widget class="QPushButton" name="pbtn_at_mediamusicstop">\r
-              <property name="text">\r
-               <string>Music Stop</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-          <widget class="QWidget" name="layoutWidget">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>80</y>\r
-             <width>591</width>\r
-             <height>32</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QGridLayout" name="gridLayout_4" columnstretch="5,1">\r
-            <property name="leftMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <property name="topMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <property name="rightMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <property name="bottomMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <item row="0" column="0">\r
-             <widget class="QLineEdit" name="ledit_at_mediaaudiorecord"/>\r
-            </item>\r
-            <item row="0" column="1">\r
-             <widget class="QPushButton" name="pbtn_at_mediaaudiorecord">\r
-              <property name="text">\r
-               <string>Audio Record</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-         </widget>\r
-        </widget>\r
-        <widget class="QWidget" name="tab_at_cmd_bt">\r
-         <attribute name="title">\r
-          <string>BT</string>\r
-         </attribute>\r
-         <widget class="QGroupBox" name="groupBox_7">\r
-          <property name="geometry">\r
-           <rect>\r
-            <x>20</x>\r
-            <y>10</y>\r
-            <width>821</width>\r
-            <height>111</height>\r
-           </rect>\r
-          </property>\r
-          <property name="title">\r
-           <string>耦合测试设置</string>\r
-          </property>\r
-          <widget class="QWidget" name="layoutWidget">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>40</y>\r
-             <width>671</width>\r
-             <height>25</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,2,3,1,2">\r
-            <item>\r
-             <widget class="QPushButton" name="pbtn_delay_time">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>延时时间</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item>\r
-             <widget class="QLineEdit" name="ledit_delay_ms">\r
-              <property name="text">\r
-               <string/>\r
-              </property>\r
-              <property name="alignment">\r
-               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\r
-              </property>\r
-              <property name="placeholderText">\r
-               <string>ms</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item>\r
-             <spacer name="horizontalSpacer">\r
-              <property name="orientation">\r
-               <enum>Qt::Horizontal</enum>\r
-              </property>\r
-              <property name="sizeHint" stdset="0">\r
-               <size>\r
-                <width>40</width>\r
-                <height>20</height>\r
-               </size>\r
-              </property>\r
-             </spacer>\r
-            </item>\r
-            <item>\r
-             <widget class="QPushButton" name="pbtn_donglemac">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>DongleMAC</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item>\r
-             <widget class="QLineEdit" name="ledit_dongle_mac">\r
-              <property name="text">\r
-               <string/>\r
-              </property>\r
-              <property name="alignment">\r
-               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-         </widget>\r
-        </widget>\r
-        <widget class="QWidget" name="tab_at_cmd_rftest">\r
-         <attribute name="title">\r
-          <string>耦合测试</string>\r
-         </attribute>\r
-         <widget class="QGroupBox" name="groupBox_13">\r
-          <property name="geometry">\r
-           <rect>\r
-            <x>20</x>\r
-            <y>10</y>\r
-            <width>831</width>\r
-            <height>121</height>\r
-           </rect>\r
-          </property>\r
-          <property name="title">\r
-           <string>BR EDR</string>\r
-          </property>\r
-          <widget class="QWidget" name="layoutWidget">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>20</y>\r
-             <width>761</width>\r
-             <height>81</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QGridLayout" name="gridLayout_5" columnstretch="2,1,4,2,4,2">\r
-            <item row="0" column="3">\r
-             <widget class="QComboBox" name="cbox_br_tx_PacketType_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="contextMenuPolicy">\r
-               <enum>Qt::DefaultContextMenu</enum>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH5</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH5</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH5</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="1" column="4">\r
-             <widget class="MyLineEdit" name="ledit_br_rx_PayloadLen_complete">\r
-              <property name="placeholderText">\r
-               <string>Length(0-27)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="1" column="1">\r
-             <widget class="QComboBox" name="cbox_br_rx_on_or_off_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>ON</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="1" column="5">\r
-             <widget class="QComboBox" name="cbox_br_rx_pattern_type_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>10101010</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>PRBS9</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>11110000</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="1" column="0">\r
-             <widget class="QPushButton" name="pbtn_br_rx_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>BR RX</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="1">\r
-             <widget class="QComboBox" name="cbox_br_tx_on_or_off_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="minimumContentsLength">\r
-               <number>0</number>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>ON</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="0">\r
-             <widget class="QPushButton" name="pbtn_br_tx_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>BR TX</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="2">\r
-             <widget class="MyLineEdit" name="ledit_br_tx_channel_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string/>\r
-              </property>\r
-              <property name="frame">\r
-               <bool>true</bool>\r
-              </property>\r
-              <property name="echoMode">\r
-               <enum>QLineEdit::Normal</enum>\r
-              </property>\r
-              <property name="placeholderText">\r
-               <string>Channel(0-78)</string>\r
-              </property>\r
-              <property name="cursorMoveStyle">\r
-               <enum>Qt::LogicalMoveStyle</enum>\r
-              </property>\r
-              <property name="clearButtonEnabled">\r
-               <bool>false</bool>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="1" column="2">\r
-             <widget class="MyLineEdit" name="ledit_br_rx_channel_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string/>\r
-              </property>\r
-              <property name="placeholderText">\r
-               <string>Channel(0-78)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="1" column="3">\r
-             <widget class="QComboBox" name="cbox_br_rx_PacketType_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="contextMenuPolicy">\r
-               <enum>Qt::DefaultContextMenu</enum>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH5</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH5</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH5</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="5">\r
-             <widget class="QComboBox" name="cbox_br_tx_pattern_type_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>10101010</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>PRBS9</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>11110000</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="4">\r
-             <widget class="MyLineEdit" name="ledit_br_tx_PayloadLen_complete">\r
-              <property name="placeholderText">\r
-               <string>Length(0-27)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-         </widget>\r
-         <widget class="QGroupBox" name="groupBox_14">\r
-          <property name="geometry">\r
-           <rect>\r
-            <x>20</x>\r
-            <y>140</y>\r
-            <width>831</width>\r
-            <height>111</height>\r
-           </rect>\r
-          </property>\r
-          <property name="title">\r
-           <string>BLE</string>\r
-          </property>\r
-          <widget class="QWidget" name="layoutWidget_8">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>70</y>\r
-             <width>461</width>\r
-             <height>26</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QGridLayout" name="gridLayout_13" columnstretch="2,1,4,2">\r
-            <property name="rightMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <item row="0" column="1">\r
-             <widget class="QComboBox" name="cbox_ble_rx_on_or_off_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>ON</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="2">\r
-             <widget class="MyLineEdit" name="ledit_ble_rx_channel_complete">\r
-              <property name="placeholderText">\r
-               <string>Channel(0-39)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="3">\r
-             <widget class="QComboBox" name="cbox_ble_rx_PacketType_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="contextMenuPolicy">\r
-               <enum>Qt::DefaultContextMenu</enum>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>BLE 1M</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>BLE 2M</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="0">\r
-             <widget class="QPushButton" name="pbtn_ble_rx_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>BLE RX</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-          <widget class="QWidget" name="layoutWidget">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>21</y>\r
-             <width>761</width>\r
-             <height>25</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QGridLayout" name="gridLayout_6" columnstretch="2,1,4,2,4,2">\r
-            <item row="0" column="0">\r
-             <widget class="QPushButton" name="pbtn_ble_tx_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>BLE TX</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="1">\r
-             <widget class="QComboBox" name="cbox_ble_tx_on_or_off_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>ON</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="2">\r
-             <widget class="MyLineEdit" name="ledit_ble_tx_channel_complete">\r
-              <property name="placeholderText">\r
-               <string>Channel(0-39)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="3">\r
-             <widget class="QComboBox" name="cbox_ble_tx_pattern_type_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>10101010</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>PRBS9</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>11110000</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="4">\r
-             <widget class="MyLineEdit" name="ledit_ble_tx_PayloadLen_complete">\r
-              <property name="placeholderText">\r
-               <string>Length(0-255)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="5">\r
-             <widget class="QComboBox" name="cbox_ble_tx_PacketType_complete">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="contextMenuPolicy">\r
-               <enum>Qt::DefaultContextMenu</enum>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>BLE 1M</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>BLE 2M</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-          <widget class="QWidget" name="layoutWidget">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>560</x>\r
-             <y>70</y>\r
-             <width>221</width>\r
-             <height>25</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,2">\r
-            <item>\r
-             <widget class="QPushButton" name="pbtn_get_rx_count">\r
-              <property name="text">\r
-               <string>获取RX Count</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item>\r
-             <widget class="QLineEdit" name="ledit_display_rx_count">\r
-              <property name="text">\r
-               <string/>\r
-              </property>\r
-              <property name="alignment">\r
-               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\r
-              </property>\r
-              <property name="placeholderText">\r
-               <string/>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-         </widget>\r
-        </widget>\r
-       </widget>\r
-      </widget>\r
-     </widget>\r
-    </widget>\r
-    <widget class="QWidget" name="page_board">\r
-     <widget class="QTabWidget" name="tbw_stage_board">\r
-      <property name="enabled">\r
-       <bool>false</bool>\r
-      </property>\r
-      <property name="geometry">\r
-       <rect>\r
-        <x>0</x>\r
-        <y>0</y>\r
-        <width>911</width>\r
-        <height>291</height>\r
-       </rect>\r
-      </property>\r
-      <property name="font">\r
-       <font>\r
-        <family>黑体</family>\r
-        <pointsize>12</pointsize>\r
-        <weight>50</weight>\r
-        <bold>false</bold>\r
-       </font>\r
-      </property>\r
-      <property name="currentIndex">\r
-       <number>2</number>\r
-      </property>\r
-      <widget class="QWidget" name="tab_board_debug">\r
-       <attribute name="title">\r
-        <string>Debug</string>\r
-       </attribute>\r
-       <widget class="QTextEdit" name="tedit_input_data_board">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>0</x>\r
-          <y>0</y>\r
-          <width>771</width>\r
-          <height>261</height>\r
-         </rect>\r
-        </property>\r
-       </widget>\r
-       <widget class="QPushButton" name="pbtn_send_data_board">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>790</x>\r
-          <y>30</y>\r
-          <width>75</width>\r
-          <height>23</height>\r
-         </rect>\r
-        </property>\r
-        <property name="font">\r
-         <font>\r
-          <family>黑体</family>\r
-          <pointsize>10</pointsize>\r
-          <weight>50</weight>\r
-          <bold>false</bold>\r
-         </font>\r
-        </property>\r
-        <property name="text">\r
-         <string>发送</string>\r
-        </property>\r
-       </widget>\r
-       <widget class="QPushButton" name="pbtn_board">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>790</x>\r
-          <y>83</y>\r
-          <width>75</width>\r
-          <height>23</height>\r
-         </rect>\r
-        </property>\r
-        <property name="font">\r
-         <font>\r
-          <family>黑体</family>\r
-          <pointsize>10</pointsize>\r
-          <weight>50</weight>\r
-          <bold>false</bold>\r
-         </font>\r
-        </property>\r
-        <property name="text">\r
-         <string>清除发送</string>\r
-        </property>\r
-       </widget>\r
-       <widget class="QCheckBox" name="ckbox_word_wrap_board">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>789</x>\r
-          <y>157</y>\r
-          <width>88</width>\r
-          <height>16</height>\r
-         </rect>\r
-        </property>\r
-        <property name="font">\r
-         <font>\r
-          <family>黑体</family>\r
-          <pointsize>10</pointsize>\r
-          <weight>50</weight>\r
-          <bold>false</bold>\r
-         </font>\r
-        </property>\r
-        <property name="text">\r
-         <string>加回车换行</string>\r
-        </property>\r
-        <property name="tristate">\r
-         <bool>false</bool>\r
-        </property>\r
-       </widget>\r
-      </widget>\r
-      <widget class="QWidget" name="tab_board_mcu">\r
-       <attribute name="title">\r
-        <string>MCU</string>\r
-       </attribute>\r
-      </widget>\r
-      <widget class="QWidget" name="tab_board_bt">\r
-       <attribute name="title">\r
-        <string>BT</string>\r
-       </attribute>\r
-       <widget class="QTabWidget" name="tabWidget_BT">\r
-        <property name="geometry">\r
-         <rect>\r
-          <x>0</x>\r
-          <y>0</y>\r
-          <width>911</width>\r
-          <height>281</height>\r
-         </rect>\r
-        </property>\r
-        <property name="font">\r
-         <font>\r
-          <family>黑体</family>\r
-          <pointsize>10</pointsize>\r
-          <weight>50</weight>\r
-          <bold>false</bold>\r
-         </font>\r
-        </property>\r
-        <property name="tabPosition">\r
-         <enum>QTabWidget::West</enum>\r
-        </property>\r
-        <property name="tabShape">\r
-         <enum>QTabWidget::Triangular</enum>\r
-        </property>\r
-        <property name="currentIndex">\r
-         <number>2</number>\r
-        </property>\r
-        <property name="elideMode">\r
-         <enum>Qt::ElideNone</enum>\r
-        </property>\r
-        <property name="tabBarAutoHide">\r
-         <bool>false</bool>\r
-        </property>\r
-        <widget class="QWidget" name="tab_bt_rftest">\r
-         <attribute name="title">\r
-          <string>非信令测试</string>\r
-         </attribute>\r
-         <widget class="QGroupBox" name="groupBox_11">\r
-          <property name="geometry">\r
-           <rect>\r
-            <x>20</x>\r
-            <y>140</y>\r
-            <width>831</width>\r
-            <height>111</height>\r
-           </rect>\r
-          </property>\r
-          <property name="title">\r
-           <string>BLE</string>\r
-          </property>\r
-          <widget class="QWidget" name="layoutWidget_2">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>20</y>\r
-             <width>761</width>\r
-             <height>25</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QGridLayout" name="gridLayout_7" columnstretch="2,1,4,2,4,2">\r
-            <item row="0" column="0">\r
-             <widget class="QPushButton" name="pbtn_ble_tx_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>BLE TX</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="1">\r
-             <widget class="QComboBox" name="cbox_ble_tx_on_or_off_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>ON</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>OFF</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="2">\r
-             <widget class="MyLineEdit" name="ledit_ble_tx_channel_board">\r
-              <property name="whatsThis">\r
-               <string/>\r
-              </property>\r
-              <property name="placeholderText">\r
-               <string>Channel(0-39)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="3">\r
-             <widget class="QComboBox" name="cbox_ble_tx_pattern_type_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>10101010</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>PRBS9</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>11110000</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="4">\r
-             <widget class="MyLineEdit" name="ledit_ble_tx_PayloadLen_board">\r
-              <property name="placeholderText">\r
-               <string>Length(0-255)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="5">\r
-             <widget class="QComboBox" name="cbox_ble_tx_PacketType_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="contextMenuPolicy">\r
-               <enum>Qt::DefaultContextMenu</enum>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>BLE 1M</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>BLE 2M</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-          <widget class="QWidget" name="layoutWidget_9">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>69</y>\r
-             <width>461</width>\r
-             <height>26</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QGridLayout" name="gridLayout_14" columnstretch="2,1,4,2">\r
-            <property name="rightMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <item row="0" column="1">\r
-             <widget class="QComboBox" name="cbox_ble_rx_on_or_off_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>ON</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>OFF</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="2">\r
-             <widget class="MyLineEdit" name="ledit_ble_rx_channel_board">\r
-              <property name="placeholderText">\r
-               <string>Channel(0-39)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="3">\r
-             <widget class="QComboBox" name="cbox_ble_rx_PacketType_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="contextMenuPolicy">\r
-               <enum>Qt::DefaultContextMenu</enum>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>BLE 1M</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>BLE 2M</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="0">\r
-             <widget class="QPushButton" name="pbtn_ble_rx_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>BLE RX</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-         </widget>\r
-         <widget class="QGroupBox" name="groupBox_15">\r
-          <property name="geometry">\r
-           <rect>\r
-            <x>20</x>\r
-            <y>10</y>\r
-            <width>831</width>\r
-            <height>121</height>\r
-           </rect>\r
-          </property>\r
-          <property name="title">\r
-           <string>BR EDR</string>\r
-          </property>\r
-          <widget class="QWidget" name="layoutWidget_3">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>20</y>\r
-             <width>761</width>\r
-             <height>81</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QGridLayout" name="gridLayout_8" columnstretch="2,1,4,2,4,2">\r
-            <item row="1" column="1">\r
-             <widget class="QComboBox" name="cbox_br_rx_on_or_off_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>ON</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>OFF</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="1" column="5">\r
-             <widget class="QComboBox" name="cbox_br_rx_pattern_type_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>10101010</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>PRBS9</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>11110000</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="3">\r
-             <widget class="QComboBox" name="cbox_br_tx_PacketType_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="contextMenuPolicy">\r
-               <enum>Qt::DefaultContextMenu</enum>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH5</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH5</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH5</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="2">\r
-             <widget class="MyLineEdit" name="ledit_br_tx_channel_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string/>\r
-              </property>\r
-              <property name="placeholderText">\r
-               <string>Channel(0-78)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="5">\r
-             <widget class="QComboBox" name="cbox_br_tx_pattern_type_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>10101010</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>PRBS9</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>11110000</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="1" column="0">\r
-             <widget class="QPushButton" name="pbtn_br_rx_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>BR RX</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="4">\r
-             <widget class="MyLineEdit" name="ledit_br_tx_PayloadLen_board">\r
-              <property name="placeholderText">\r
-               <string>Length(0-27)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="1">\r
-             <widget class="QComboBox" name="cbox_br_tx_on_or_off_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="minimumContentsLength">\r
-               <number>0</number>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>ON</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>OFF</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="1" column="4">\r
-             <widget class="MyLineEdit" name="ledit_br_rx_PayloadLen_board">\r
-              <property name="placeholderText">\r
-               <string>Length(0-27)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="0">\r
-             <widget class="QPushButton" name="pbtn_br_tx_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>BR TX</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="1" column="3">\r
-             <widget class="QComboBox" name="cbox_br_rx_PacketType_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="contextMenuPolicy">\r
-               <enum>Qt::DefaultContextMenu</enum>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>DH5</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>2-DH5</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH1</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH3</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>3-DH5</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="1" column="2">\r
-             <widget class="MyLineEdit" name="ledit_br_rx_channel_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string/>\r
-              </property>\r
-              <property name="placeholderText">\r
-               <string>Channel(0-78)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-         </widget>\r
-        </widget>\r
-        <widget class="QWidget" name="tab_bt_duttest">\r
-         <attribute name="title">\r
-          <string>信令测试</string>\r
-         </attribute>\r
-         <widget class="QGroupBox" name="groupBox_12">\r
-          <property name="geometry">\r
-           <rect>\r
-            <x>20</x>\r
-            <y>10</y>\r
-            <width>831</width>\r
-            <height>111</height>\r
-           </rect>\r
-          </property>\r
-          <property name="title">\r
-           <string>信令</string>\r
-          </property>\r
-          <widget class="QWidget" name="layoutWidget_5">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>20</x>\r
-             <y>30</y>\r
-             <width>371</width>\r
-             <height>29</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QGridLayout" name="gridLayout_11" columnstretch="2,2,1,2">\r
-            <property name="leftMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <property name="topMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <property name="rightMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <property name="bottomMargin">\r
-             <number>3</number>\r
-            </property>\r
-            <item row="0" column="1">\r
-             <widget class="QPushButton" name="pbtn_btdutmode_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>BTDUTMODE</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="0">\r
-             <widget class="QLabel" name="label_7">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Preferred">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>信令测试:</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="3">\r
-             <widget class="QComboBox" name="cbox_btdutmode_on_or_off_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>ON</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>OFF</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="2">\r
-             <spacer name="horizontalSpacer_3">\r
-              <property name="orientation">\r
-               <enum>Qt::Horizontal</enum>\r
-              </property>\r
-              <property name="sizeHint" stdset="0">\r
-               <size>\r
-                <width>30</width>\r
-                <height>20</height>\r
-               </size>\r
-              </property>\r
-             </spacer>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-         </widget>\r
-        </widget>\r
-        <widget class="QWidget" name="tab">\r
-         <attribute name="title">\r
-          <string>其他</string>\r
-         </attribute>\r
-         <widget class="QGroupBox" name="groupBox_6">\r
-          <property name="geometry">\r
-           <rect>\r
-            <x>20</x>\r
-            <y>20</y>\r
-            <width>791</width>\r
-            <height>121</height>\r
-           </rect>\r
-          </property>\r
-          <property name="title">\r
-           <string>单音测试与功率调整</string>\r
-          </property>\r
-          <widget class="QWidget" name="layoutWidget">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>30</x>\r
-             <y>40</y>\r
-             <width>731</width>\r
-             <height>25</height>\r
-            </rect>\r
-           </property>\r
-           <layout class="QGridLayout" name="gridLayout_9" columnstretch="4,1,8,8,4,1,8">\r
-            <property name="horizontalSpacing">\r
-             <number>10</number>\r
-            </property>\r
-            <item row="0" column="2">\r
-             <widget class="QLineEdit" name="ledit_btlo_channel">\r
-              <property name="placeholderText">\r
-               <string>channel(0-78)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="4">\r
-             <widget class="QPushButton" name="pbtn_btpwr_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>功率调整</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="0">\r
-             <widget class="QPushButton" name="pbtn_btlo_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <property name="text">\r
-               <string>单音测试</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="5">\r
-             <widget class="QComboBox" name="cbox_btpwr_on_or_off_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>ON</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>OFF</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="1">\r
-             <widget class="QComboBox" name="cbox_btlo_on_or_off_board">\r
-              <property name="sizePolicy">\r
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-                <horstretch>0</horstretch>\r
-                <verstretch>0</verstretch>\r
-               </sizepolicy>\r
-              </property>\r
-              <item>\r
-               <property name="text">\r
-                <string>ON</string>\r
-               </property>\r
-              </item>\r
-              <item>\r
-               <property name="text">\r
-                <string>OFF</string>\r
-               </property>\r
-              </item>\r
-             </widget>\r
-            </item>\r
-            <item row="0" column="3">\r
-             <spacer name="horizontalSpacer_2">\r
-              <property name="orientation">\r
-               <enum>Qt::Horizontal</enum>\r
-              </property>\r
-              <property name="sizeHint" stdset="0">\r
-               <size>\r
-                <width>40</width>\r
-                <height>20</height>\r
-               </size>\r
-              </property>\r
-             </spacer>\r
-            </item>\r
-            <item row="0" column="6">\r
-             <widget class="QLineEdit" name="ledit_btpwr_powerchip">\r
-              <property name="placeholderText">\r
-               <string>power chip(2-14)</string>\r
-              </property>\r
-             </widget>\r
-            </item>\r
-           </layout>\r
-          </widget>\r
-         </widget>\r
-         <widget class="QGroupBox" name="groupBox_8">\r
-          <property name="geometry">\r
-           <rect>\r
-            <x>20</x>\r
-            <y>140</y>\r
-            <width>791</width>\r
-            <height>111</height>\r
-           </rect>\r
-          </property>\r
-          <property name="title">\r
-           <string>BT_UART</string>\r
-          </property>\r
-          <widget class="QPushButton" name="pushButton_3">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>30</x>\r
-             <y>40</y>\r
-             <width>75</width>\r
-             <height>23</height>\r
-            </rect>\r
-           </property>\r
-           <property name="text">\r
-            <string>唤醒</string>\r
-           </property>\r
-          </widget>\r
-          <widget class="QPushButton" name="pushButton_4">\r
-           <property name="geometry">\r
-            <rect>\r
-             <x>150</x>\r
-             <y>40</y>\r
-             <width>75</width>\r
-             <height>23</height>\r
-            </rect>\r
-           </property>\r
-           <property name="text">\r
-            <string>睡眠</string>\r
-           </property>\r
-          </widget>\r
-         </widget>\r
-        </widget>\r
-       </widget>\r
-      </widget>\r
-     </widget>\r
-    </widget>\r
-   </widget>\r
-   <widget class="QWidget" name="layoutWidget">\r
-    <property name="geometry">\r
-     <rect>\r
-      <x>650</x>\r
-      <y>0</y>\r
-      <width>224</width>\r
-      <height>389</height>\r
-     </rect>\r
-    </property>\r
-    <layout class="QGridLayout" name="gridLayout">\r
-     <property name="leftMargin">\r
-      <number>5</number>\r
-     </property>\r
-     <property name="topMargin">\r
-      <number>20</number>\r
-     </property>\r
-     <property name="rightMargin">\r
-      <number>5</number>\r
-     </property>\r
-     <property name="bottomMargin">\r
-      <number>20</number>\r
-     </property>\r
-     <property name="spacing">\r
-      <number>20</number>\r
-     </property>\r
-     <item row="1" column="0" colspan="3">\r
-      <widget class="QComboBox" name="cbox_uart_baud_select">\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>黑体</family>\r
-         <pointsize>9</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <property name="cursor">\r
-        <cursorShape>ArrowCursor</cursorShape>\r
-       </property>\r
-       <property name="editable">\r
-        <bool>false</bool>\r
-       </property>\r
-       <property name="currentText">\r
-        <string>115200</string>\r
-       </property>\r
-       <property name="currentIndex">\r
-        <number>6</number>\r
-       </property>\r
-       <property name="duplicatesEnabled">\r
-        <bool>true</bool>\r
-       </property>\r
-       <item>\r
-        <property name="text">\r
-         <string>4800</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>9600</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>14400</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>19200</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>38400</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>57600</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>115200</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>128000</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>230400</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>256000</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>460800</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>500000</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>512000</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>600000</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>750000</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>921600</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>1000000</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>1500000</string>\r
-        </property>\r
-       </item>\r
-       <item>\r
-        <property name="text">\r
-         <string>2000000</string>\r
-        </property>\r
-       </item>\r
-      </widget>\r
-     </item>\r
-     <item row="3" column="0" colspan="3">\r
-      <widget class="QLineEdit" name="ledit_spp_addr">\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>黑体</family>\r
-         <pointsize>9</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <property name="whatsThis">\r
-        <string/>\r
-       </property>\r
-       <property name="placeholderText">\r
-        <string>         MAC地址</string>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-     <item row="2" column="0">\r
-      <widget class="QLabel" name="label_3">\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="text">\r
-        <string>串口操作</string>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-     <item row="6" column="0">\r
-      <widget class="QCheckBox" name="ckbox_rts">\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>黑体</family>\r
-         <pointsize>9</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <property name="text">\r
-        <string>RTS</string>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-     <item row="5" column="0">\r
-      <widget class="QPushButton" name="pushButton">\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>黑体</family>\r
-         <pointsize>9</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <property name="text">\r
-        <string>保存窗口</string>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-     <item row="6" column="1">\r
-      <widget class="QCheckBox" name="ckbox_dtr">\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>黑体</family>\r
-         <pointsize>9</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <property name="text">\r
-        <string>DTR</string>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-     <item row="7" column="0">\r
-      <widget class="QCheckBox" name="ckbox_Hex_Display">\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>黑体</family>\r
-         <pointsize>9</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <property name="text">\r
-        <string>16进制显示</string>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-     <item row="2" column="1" colspan="2">\r
-      <widget class="QPushButton" name="pbtn_open_uart">\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>黑体</family>\r
-         <pointsize>9</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <property name="text">\r
-        <string>打开串口</string>\r
-       </property>\r
-       <property name="checkable">\r
-        <bool>true</bool>\r
-       </property>\r
-       <property name="autoDefault">\r
-        <bool>false</bool>\r
-       </property>\r
-       <property name="default">\r
-        <bool>false</bool>\r
-       </property>\r
-       <property name="flat">\r
-        <bool>false</bool>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-     <item row="4" column="0" colspan="2">\r
-      <widget class="QPushButton" name="pbtn_spp_connect">\r
-       <property name="enabled">\r
-        <bool>false</bool>\r
-       </property>\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>黑体</family>\r
-         <pointsize>9</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <property name="text">\r
-        <string>连接设备</string>\r
-       </property>\r
-       <property name="checkable">\r
-        <bool>false</bool>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-     <item row="7" column="1" colspan="2">\r
-      <widget class="QCheckBox" name="ckbox_hex_send">\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>黑体</family>\r
-         <pointsize>9</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <property name="text">\r
-        <string>16进制发送</string>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-     <item row="0" column="0" colspan="3">\r
-      <widget class="MyComboBox" name="cbox_uart_com_select">\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>黑体</family>\r
-         <pointsize>9</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <item>\r
-        <property name="text">\r
-         <string>COM1</string>\r
-        </property>\r
-       </item>\r
-      </widget>\r
-     </item>\r
-     <item row="5" column="1" colspan="2">\r
-      <widget class="QPushButton" name="pbtn_clear_display">\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>黑体</family>\r
-         <pointsize>9</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <property name="text">\r
-        <string>清除接收</string>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-     <item row="4" column="2">\r
-      <widget class="QPushButton" name="connected_flag">\r
-       <property name="maximumSize">\r
-        <size>\r
-         <width>20</width>\r
-         <height>20</height>\r
-        </size>\r
-       </property>\r
-       <property name="styleSheet">\r
-        <string notr="true">QPushButton{background-color: rgb(255, 0, 0);}</string>\r
-       </property>\r
-       <property name="text">\r
-        <string/>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-    </layout>\r
-   </widget>\r
-  </widget>\r
-  <widget class="QMenuBar" name="menubar">\r
-   <property name="geometry">\r
-    <rect>\r
-     <x>0</x>\r
-     <y>0</y>\r
-     <width>890</width>\r
-     <height>22</height>\r
-    </rect>\r
-   </property>\r
-   <property name="font">\r
-    <font>\r
-     <family>黑体</family>\r
-     <pointsize>12</pointsize>\r
-     <weight>50</weight>\r
-     <bold>false</bold>\r
-    </font>\r
-   </property>\r
-   <widget class="QMenu" name="menu">\r
-    <property name="font">\r
-     <font>\r
-      <pointsize>12</pointsize>\r
-     </font>\r
-    </property>\r
-    <property name="title">\r
-     <string>菜单</string>\r
-    </property>\r
-    <addaction name="action_complete"/>\r
-    <addaction name="separator"/>\r
-    <addaction name="action_board"/>\r
-   </widget>\r
-   <addaction name="menu"/>\r
-  </widget>\r
-  <widget class="QStatusBar" name="statusbar">\r
-   <property name="enabled">\r
-    <bool>true</bool>\r
-   </property>\r
-   <property name="sizeGripEnabled">\r
-    <bool>true</bool>\r
-   </property>\r
-  </widget>\r
-  <action name="action_complete">\r
-   <property name="checkable">\r
-    <bool>true</bool>\r
-   </property>\r
-   <property name="checked">\r
-    <bool>true</bool>\r
-   </property>\r
-   <property name="text">\r
-    <string>整机</string>\r
-   </property>\r
-   <property name="font">\r
-    <font>\r
-     <family>黑体</family>\r
-     <pointsize>12</pointsize>\r
-    </font>\r
-   </property>\r
-  </action>\r
-  <action name="action_board">\r
-   <property name="checkable">\r
-    <bool>true</bool>\r
-   </property>\r
-   <property name="checked">\r
-    <bool>false</bool>\r
-   </property>\r
-   <property name="text">\r
-    <string>单板</string>\r
-   </property>\r
-   <property name="font">\r
-    <font>\r
-     <pointsize>12</pointsize>\r
-    </font>\r
-   </property>\r
-  </action>\r
-  <action name="actiondongle">\r
-   <property name="text">\r
-    <string>dongle调试</string>\r
-   </property>\r
-   <property name="font">\r
-    <font>\r
-     <pointsize>12</pointsize>\r
-    </font>\r
-   </property>\r
-  </action>\r
- </widget>\r
- <customwidgets>\r
-  <customwidget>\r
-   <class>MyComboBox</class>\r
-   <extends>QComboBox</extends>\r
-   <header location="global">custom.h</header>\r
-   <slots>\r
-    <signal>mouse_clicked(bool)</signal>\r
-   </slots>\r
-  </customwidget>\r
-  <customwidget>\r
-   <class>MyLineEdit</class>\r
-   <extends>QLineEdit</extends>\r
-   <header location="global">custom.h</header>\r
-  </customwidget>\r
- </customwidgets>\r
- <resources/>\r
- <connections>\r
-  <connection>\r
-   <sender>pbtn_open_uart</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>uart_process()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>849</x>\r
-     <y>154</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>838</x>\r
-     <y>261</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_clear_display</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>txtb_dispaly</receiver>\r
-   <slot>clear()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>849</x>\r
-     <y>293</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>614</x>\r
-     <y>380</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>ckbox_dtr</sender>\r
-   <signal>stateChanged(int)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>uart_check_dtr_rts()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>815</x>\r
-     <y>334</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>882</x>\r
-     <y>371</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>ckbox_rts</sender>\r
-   <signal>stateChanged(int)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>uart_check_dtr_rts()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>711</x>\r
-     <y>334</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>758</x>\r
-     <y>373</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>cbox_uart_com_select</sender>\r
-   <signal>mouse_clicked(bool)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>uart_com_select()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>719</x>\r
-     <y>61</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>888</x>\r
-     <y>100</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_spp_connect</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>spp_connect()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>811</x>\r
-     <y>245</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>888</x>\r
-     <y>267</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_toboard_stop</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>transmit_toboard_stop()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>810</x>\r
-     <y>559</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>739</x>\r
-     <y>294</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_toboard_Upload</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>transmit_toboard_upload()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>715</x>\r
-     <y>559</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>665</x>\r
-     <y>296</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_fromboard_getfilelist</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>transmit_fromboard_getfilelist()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>670</x>\r
-     <y>609</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>654</x>\r
-     <y>408</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_send_data</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>uart_send_data()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>844</x>\r
-     <y>469</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>865</x>\r
-     <y>411</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_fromboard_download</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>transmit_fromboard_download()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>830</x>\r
-     <y>489</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>849</x>\r
-     <y>420</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_fromboard_selectfilepath</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>transmit_fromboard_selectfilepath()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>665</x>\r
-     <y>489</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>673</x>\r
-     <y>417</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_clear_senddata</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>tedit_input_data</receiver>\r
-   <slot>clear()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>866</x>\r
-     <y>522</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>700</x>\r
-     <y>591</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_fromboard_stop</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>transmit_fromboard_stop()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>855</x>\r
-     <y>605</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>676</x>\r
-     <y>315</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_fromboard_delete</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>transmit_fromboard_delete()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>855</x>\r
-     <y>547</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>671</x>\r
-     <y>351</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>ledit_formboad_bordpath</sender>\r
-   <signal>textEdited(QString)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>transmit_fromboard_name_change()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>499</x>\r
-     <y>566</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>688</x>\r
-     <y>273</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_toboard_choosefile</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>transmit_toboard_choosefile()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>736</x>\r
-     <y>499</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>660</x>\r
-     <y>343</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>action_complete</sender>\r
-   <signal>triggered(bool)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>ui_tab_mainwindow_complete()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>-1</x>\r
-     <y>-1</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>468</x>\r
-     <y>363</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>action_board</sender>\r
-   <signal>triggered(bool)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>ui_tab_mainwindow_board()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>-1</x>\r
-     <y>-1</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>539</x>\r
-     <y>363</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_board</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>tedit_input_data_board</receiver>\r
-   <slot>clear()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>822</x>\r
-     <y>522</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>767</x>\r
-     <y>568</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_send_data_board</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>uart_send_data()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>842</x>\r
-     <y>469</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>888</x>\r
-     <y>484</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_at_mediaaudiorecord</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_mediaaudiorecord_send()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>646</x>\r
-     <y>535</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>643</x>\r
-     <y>285</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_at_stackinfo</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_stackinfo_send()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>160</x>\r
-     <y>485</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>654</x>\r
-     <y>412</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_at_fsrm</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_fsrm_send()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>428</x>\r
-     <y>544</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>655</x>\r
-     <y>254</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_at_mediamusicstop</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_mediamusicstop_send()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>646</x>\r
-     <y>485</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>656</x>\r
-     <y>381</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_at_mediamusicplay</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_mediamusicplay_send()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>545</x>\r
-     <y>485</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>654</x>\r
-     <y>330</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_br_tx_complete</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_bt_tx_complete()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>156</x>\r
-     <y>481</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>636</x>\r
-     <y>372</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_br_rx_complete</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_bt_rx_complete()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>156</x>\r
-     <y>519</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>637</x>\r
-     <y>335</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_ble_tx_complete</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_ble_tx_complete()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>149</x>\r
-     <y>603</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>639</x>\r
-     <y>361</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_ble_rx_complete</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_ble_rx_complete()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>141</x>\r
-     <y>652</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>444</x>\r
-     <y>354</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_br_tx_board</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_bt_tx_board()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>156</x>\r
-     <y>481</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>639</x>\r
-     <y>325</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_br_rx_board</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_bt_rx_board()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>156</x>\r
-     <y>519</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>646</x>\r
-     <y>169</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_btdutmode_board</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_bt_dutmode_board()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>265</x>\r
-     <y>484</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>646</x>\r
-     <y>210</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_ble_tx_board</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_ble_tx_board()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>139</x>\r
-     <y>581</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>633</x>\r
-     <y>248</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_ble_rx_board</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_ble_rx_board()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>139</x>\r
-     <y>630</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>643</x>\r
-     <y>204</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_get_rx_count</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_get_rx_count_complete()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>674</x>\r
-     <y>652</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>647</x>\r
-     <y>134</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_delay_time</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_bt_delay_ms_complete()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>134</x>\r
-     <y>492</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>637</x>\r
-     <y>161</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_donglemac</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_set_dongle_addr_complete()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>581</x>\r
-     <y>492</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>653</x>\r
-     <y>126</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>cbox_uart_com_select</sender>\r
-   <signal>activated(QString)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>uart_com_switch(QString)</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>702</x>\r
-     <y>55</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>764</x>\r
-     <y>76</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>cbox_uart_baud_select</sender>\r
-   <signal>activated(QString)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>uart_baud_switch(QString)</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>712</x>\r
-     <y>103</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>744</x>\r
-     <y>133</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>cbox_br_tx_PacketType_complete</sender>\r
-   <signal>activated(int)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_check_bt_len(int)</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>514</x>\r
-     <y>479</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>649</x>\r
-     <y>73</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>cbox_br_rx_PacketType_complete</sender>\r
-   <signal>activated(int)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_check_bt_len(int)</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>514</x>\r
-     <y>517</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>647</x>\r
-     <y>55</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>cbox_br_tx_PacketType_board</sender>\r
-   <signal>activated(int)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_check_bt_len(int)</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>514</x>\r
-     <y>479</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>639</x>\r
-     <y>116</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>cbox_br_rx_PacketType_board</sender>\r
-   <signal>activated(int)</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_check_bt_len(int)</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>514</x>\r
-     <y>517</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>638</x>\r
-     <y>85</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pushButton</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>ui_save_windows()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>702</x>\r
-     <y>285</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>647</x>\r
-     <y>236</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_btlo_board</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_bt_btlo_board()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>144</x>\r
-     <y>502</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>642</x>\r
-     <y>200</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_btpwr_board</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_bt_btpwr_board()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>589</x>\r
-     <y>502</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>684</x>\r
-     <y>304</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pbtn_at_custom_send</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_custom_send()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>169</x>\r
-     <y>602</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>661</x>\r
-     <y>190</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pushButton_3</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_bt_wakeup()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>122</x>\r
-     <y>615</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>957</x>\r
-     <y>601</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
-  <connection>\r
-   <sender>pushButton_4</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>at_bt_sleep()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>244</x>\r
-     <y>615</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>970</x>\r
-     <y>548</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
- </connections>\r
- <slots>\r
-  <slot>transmit_toboard_choosefile()</slot>\r
-  <slot>uart_send_data()</slot>\r
-  <slot>uart_process()</slot>\r
-  <slot>check_word_wrap()</slot>\r
-  <slot>check_hex_display()</slot>\r
-  <slot>at_stackinfo_send()</slot>\r
-  <slot>uart_check_dtr_rts()</slot>\r
-  <slot>uart_com_select()</slot>\r
-  <slot>transmit_fromboard_selectfilepath()</slot>\r
-  <slot>transmit_fromboard_getfilelist()</slot>\r
-  <slot>transmit_fromboard_download()</slot>\r
-  <slot>transmit_toboard_upload()</slot>\r
-  <slot>transmit_toboard_stop()</slot>\r
-  <slot>transmit_fromboard_delete()</slot>\r
-  <slot>transmit_fromboard_stop()</slot>\r
-  <slot>spp_connect()</slot>\r
-  <slot>transmit_fromboard_name_change()</slot>\r
-  <slot>at_fsrm_send()</slot>\r
-  <slot>at_mediamusicplay_send()</slot>\r
-  <slot>at_mediamusicstop_send()</slot>\r
-  <slot>at_mediaaudiorecord_send()</slot>\r
-  <slot>ui_tab_mainwindow_complete()</slot>\r
-  <slot>ui_tab_mainwindow_board()</slot>\r
-  <slot>at_bt_tx_complete()</slot>\r
-  <slot>at_bt_rx_complete()</slot>\r
-  <slot>at_ble_tx_complete()</slot>\r
-  <slot>at_ble_rx_complete()</slot>\r
-  <slot>at_bt_rx_board()</slot>\r
-  <slot>at_bt_tx_board()</slot>\r
-  <slot>at_ble_tx_board()</slot>\r
-  <slot>at_ble_rx_board()</slot>\r
-  <slot>at_bt_dutmode_board()</slot>\r
-  <slot>at_bt_delay_ms_complete()</slot>\r
-  <slot>at_set_dongle_addr_complete()</slot>\r
-  <slot>at_get_rx_count_complete()</slot>\r
-  <slot>uart_com_switch(QString)</slot>\r
-  <slot>uart_baud_switch(QString)</slot>\r
-  <slot>at_check_bt_len(int)</slot>\r
-  <slot>ui_save_windows()</slot>\r
-  <slot>at_bt_btlo_board()</slot>\r
-  <slot>at_bt_btpwr_board()</slot>\r
-  <slot>at_custom_send()</slot>\r
-  <slot>at_bt_wakeup()</slot>\r
-  <slot>at_bt_sleep()</slot>\r
- </slots>\r
-</ui>\r
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1309</width>
+    <height>641</height>
+   </rect>
+  </property>
+  <property name="font">
+   <font>
+    <pointsize>10</pointsize>
+   </font>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <widget class="QComboBox" name="portNameBox">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>30</y>
+      <width>231</width>
+      <height>31</height>
+     </rect>
+    </property>
+   </widget>
+   <widget class="QTextEdit" name="recvTextEdit">
+    <property name="geometry">
+     <rect>
+      <x>260</x>
+      <y>20</y>
+      <width>741</width>
+      <height>401</height>
+     </rect>
+    </property>
+   </widget>
+   <widget class="QTextEdit" name="sendTextEdit">
+    <property name="geometry">
+     <rect>
+      <x>260</x>
+      <y>460</y>
+      <width>741</width>
+      <height>71</height>
+     </rect>
+    </property>
+   </widget>
+   <widget class="QPushButton" name="openButton">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>90</y>
+      <width>101</width>
+      <height>51</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>打开串口</string>
+    </property>
+   </widget>
+   <widget class="QPushButton" name="clearRecvButton">
+    <property name="geometry">
+     <rect>
+      <x>120</x>
+      <y>90</y>
+      <width>101</width>
+      <height>51</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>清空数据</string>
+    </property>
+   </widget>
+   <widget class="QPushButton" name="sendButton">
+    <property name="geometry">
+     <rect>
+      <x>930</x>
+      <y>540</y>
+      <width>75</width>
+      <height>23</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>发送</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="Verlabel">
+    <property name="geometry">
+     <rect>
+      <x>1010</x>
+      <y>30</y>
+      <width>21</width>
+      <height>16</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>Ver:</string>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="VerlineEdit">
+    <property name="geometry">
+     <rect>
+      <x>1050</x>
+      <y>30</y>
+      <width>181</width>
+      <height>20</height>
+     </rect>
+    </property>
+   </widget>
+   <widget class="QLabel" name="Verlabel_2">
+    <property name="geometry">
+     <rect>
+      <x>1010</x>
+      <y>60</y>
+      <width>31</width>
+      <height>20</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>IMEI:</string>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="IMEIlineEdit">
+    <property name="geometry">
+     <rect>
+      <x>1050</x>
+      <y>60</y>
+      <width>181</width>
+      <height>20</height>
+     </rect>
+    </property>
+   </widget>
+   <widget class="QLabel" name="Verlabel_3">
+    <property name="geometry">
+     <rect>
+      <x>1010</x>
+      <y>90</y>
+      <width>41</width>
+      <height>20</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>ICCID</string>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="ICCIDlineEdit">
+    <property name="geometry">
+     <rect>
+      <x>1050</x>
+      <y>90</y>
+      <width>181</width>
+      <height>20</height>
+     </rect>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="ModemVerlineEdit">
+    <property name="geometry">
+     <rect>
+      <x>1050</x>
+      <y>120</y>
+      <width>251</width>
+      <height>20</height>
+     </rect>
+    </property>
+   </widget>
+   <widget class="QLabel" name="Verlabel_4">
+    <property name="geometry">
+     <rect>
+      <x>1010</x>
+      <y>120</y>
+      <width>41</width>
+      <height>21</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>Modem:</string>
+    </property>
+   </widget>
+   <widget class="QPushButton" name="openButton_2">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>160</y>
+      <width>101</width>
+      <height>51</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>开始产测</string>
+    </property>
+   </widget>
+   <widget class="QPushButton" name="openRecordsFolderButton">
+    <property name="geometry">
+     <rect>
+      <x>120</x>
+      <y>160</y>
+      <width>101</width>
+      <height>51</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string>QPushButton { 
+background-color: #FF9800; 
+color: white; 
+border-radius: 4px; 
+font-weight: bold; 
+}
+QPushButton:hover { 
+background-color: #F57C00; 
+}</string>
+    </property>
+    <property name="text">
+     <string>打开记录</string>
+    </property>
+   </widget>
+   <widget class="QPushButton" name="agingTestButton">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>220</y>
+      <width>101</width>
+      <height>51</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string>QPushButton { 
+background-color: #9C27B0; 
+color: white; 
+border-radius: 4px; 
+font-weight: bold; 
+}
+QPushButton:hover { 
+background-color: #7B1FA2; 
+}</string>
+    </property>
+    <property name="text">
+     <string>老化测试</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="ExpectedVerLabel">
+    <property name="geometry">
+     <rect>
+      <x>1010</x>
+      <y>180</y>
+      <width>61</width>
+      <height>20</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>最新VER:</string>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="expectedVerLineEdit">
+    <property name="geometry">
+     <rect>
+      <x>1070</x>
+      <y>180</y>
+      <width>231</width>
+      <height>20</height>
+     </rect>
+    </property>
+   </widget>
+   <widget class="QLabel" name="ExpectedModemLabel">
+    <property name="geometry">
+     <rect>
+      <x>1010</x>
+      <y>210</y>
+      <width>81</width>
+      <height>20</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>最新MODEM:</string>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="expectedModemVerLineEdit">
+    <property name="geometry">
+     <rect>
+      <x>1090</x>
+      <y>210</y>
+      <width>231</width>
+      <height>20</height>
+     </rect>
+    </property>
+   </widget>
+   <widget class="QGroupBox" name="testStatusGroupBox">
+    <property name="geometry">
+     <rect>
+      <x>1020</x>
+      <y>280</y>
+      <width>281</width>
+      <height>271</height>
+     </rect>
+    </property>
+    <property name="title">
+     <string>产测状态</string>
+    </property>
+    <widget class="QLabel" name="lcdTestLabel">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>25</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>LCD测试:</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="lcdStatusIcon">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>25</y>
+       <width>20</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888; font-size: 18px; font-weight: bold;</string>
+     </property>
+     <property name="text">
+      <string>○</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+    <widget class="QLabel" name="lcdStatusText">
+     <property name="geometry">
+      <rect>
+       <x>110</x>
+       <y>25</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888;</string>
+     </property>
+     <property name="text">
+      <string>未测试</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="motorTestLabel">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>55</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>马达测试:</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="motorStatusIcon">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>55</y>
+       <width>20</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888; font-size: 18px; font-weight: bold;</string>
+     </property>
+     <property name="text">
+      <string>○</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+    <widget class="QLabel" name="motorStatusText">
+     <property name="geometry">
+      <rect>
+       <x>110</x>
+       <y>55</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888;</string>
+     </property>
+     <property name="text">
+      <string>未测试</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="keyTestLabel">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>85</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>按键测试:</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="keyStatusIcon">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>85</y>
+       <width>20</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888; font-size: 18px; font-weight: bold;</string>
+     </property>
+     <property name="text">
+      <string>○</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+    <widget class="QLabel" name="keyStatusText">
+     <property name="geometry">
+      <rect>
+       <x>110</x>
+       <y>85</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888;</string>
+     </property>
+     <property name="text">
+      <string>未测试</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="audioTestLabel">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>115</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>录音测试:</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="audioStatusIcon">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>115</y>
+       <width>20</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888; font-size: 18px; font-weight: bold;</string>
+     </property>
+     <property name="text">
+      <string>○</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+    <widget class="QLabel" name="audioStatusText">
+     <property name="geometry">
+      <rect>
+       <x>110</x>
+       <y>115</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888;</string>
+     </property>
+     <property name="text">
+      <string>未测试</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="batteryTestLabel">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>145</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>电池测试:</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="batteryStatusIcon">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>145</y>
+       <width>20</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888; font-size: 18px; font-weight: bold;</string>
+     </property>
+     <property name="text">
+      <string>○</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+    <widget class="QLabel" name="batteryStatusText">
+     <property name="geometry">
+      <rect>
+       <x>110</x>
+       <y>145</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888;</string>
+     </property>
+     <property name="text">
+      <string>未测试</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="gsensorTestLabel">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>175</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>G-sensor:</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="gsensorStatusIcon">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>175</y>
+       <width>20</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888; font-size: 18px; font-weight: bold;</string>
+     </property>
+     <property name="text">
+      <string>○</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+    <widget class="QLabel" name="gsensorStatusText">
+     <property name="geometry">
+      <rect>
+       <x>110</x>
+       <y>175</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888;</string>
+     </property>
+     <property name="text">
+      <string>未测试</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="pppTestLabel">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>205</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>4G测试:</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="pppStatusIcon">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>205</y>
+       <width>20</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888; font-size: 18px; font-weight: bold;</string>
+     </property>
+     <property name="text">
+      <string>○</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+    <widget class="QLabel" name="pppStatusText">
+     <property name="geometry">
+      <rect>
+       <x>110</x>
+       <y>205</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888;</string>
+     </property>
+     <property name="text">
+      <string>未测试</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="overallTestLabel">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>235</y>
+       <width>60</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>整体状态:</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="overallStatusIcon">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>235</y>
+       <width>20</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888; font-size: 18px; font-weight: bold;</string>
+     </property>
+     <property name="text">
+      <string>○</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+    <widget class="QLabel" name="overallStatusText">
+     <property name="geometry">
+      <rect>
+       <x>110</x>
+       <y>235</y>
+       <width>80</width>
+       <height>20</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string>color: #888888;</string>
+     </property>
+     <property name="text">
+      <string>等待开始</string>
+     </property>
+    </widget>
+   </widget>
+   <widget class="QPushButton" name="agingTestButton_2">
+    <property name="geometry">
+     <rect>
+      <x>120</x>
+      <y>220</y>
+      <width>101</width>
+      <height>51</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string>QPushButton { 
+background-color: #9C27B0; 
+color: white; 
+border-radius: 4px; 
+font-weight: bold; 
+}
+QPushButton:hover { 
+background-color: #7B1FA2; 
+}</string>
+    </property>
+    <property name="text">
+     <string>恢复出厂</string>
+    </property>
+   </widget>
+   <widget class="QPushButton" name="openButton_3">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>280</y>
+      <width>101</width>
+      <height>51</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>老化结果</string>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="PYVerlineEdit">
+    <property name="geometry">
+     <rect>
+      <x>1050</x>
+      <y>150</y>
+      <width>251</width>
+      <height>20</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string/>
+    </property>
+   </widget>
+   <widget class="QLabel" name="Verlabel_5">
+    <property name="geometry">
+     <rect>
+      <x>1010</x>
+      <y>150</y>
+      <width>41</width>
+      <height>21</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>PYVER</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="ExpectedModemLabel_2">
+    <property name="geometry">
+     <rect>
+      <x>1010</x>
+      <y>240</y>
+      <width>81</width>
+      <height>20</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>最新PY:</string>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="expectedPYVerLineEdit">
+    <property name="geometry">
+     <rect>
+      <x>1090</x>
+      <y>240</y>
+      <width>231</width>
+      <height>20</height>
+     </rect>
+    </property>
+   </widget>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>1309</width>
+     <height>23</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/mythread.cpp b/mythread.cpp
deleted file mode 100644 (file)
index 6d0a5db..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#include "mythread.h"\r
-\r
-MyThread::MyThread()\r
-{\r
-    stopped = false;\r
-    pauseFlag = false;\r
-}\r
-\r
-MyThread::~MyThread()\r
-{\r
-}\r
-\r
-void MyThread::process()\r
-{\r
-}\r
-\r
-void MyThread::run()\r
-{\r
-    while (true) {\r
-        QMutexLocker locker(&m_lock_stop);\r
-        if (stopped) {\r
-            stopped = false;\r
-            qDebug() << "线程终止";\r
-            return;\r
-        }\r
-        if (pauseFlag) {\r
-            m_lock_Pause.lock();\r
-            condition.wait(&m_lock_Pause);\r
-            m_lock_Pause.unlock();\r
-        }\r
-        process();\r
-    }\r
-    stopped = false;\r
-    pauseFlag = false;\r
-}\r
-\r
-void MyThread::pause()\r
-{\r
-    if (this->isRunning() && !pauseFlag) {\r
-        pauseFlag = true;\r
-    }\r
-}\r
-\r
-void MyThread::resume()\r
-{\r
-    if (this->isRunning() && pauseFlag) {\r
-        pauseFlag = false;\r
-        condition.wakeAll();\r
-    }\r
-}\r
-\r
-void MyThread::stop()\r
-{\r
-    if (this->isRunning()) {\r
-        if (pauseFlag) {\r
-            this->resume();\r
-        }\r
-        QMutexLocker locker(&m_lock_stop);\r
-        stopped = true;\r
-    }\r
-}\r
diff --git a/mythread.h b/mythread.h
deleted file mode 100644 (file)
index 72164a8..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef MYTHREAD_H\r
-#define MYTHREAD_H\r
-#include <atomic>\r
-#include <QWaitCondition.h>\r
-#include <QMutex>\r
-#include <QThread>\r
-#include <header.h>\r
-#include <qdebug.h>\r
-#include <QString>\r
- /*-----------------------rx回调函数线程-------------------------------*/\r
- // 当回调函数执行时,会唤醒此线程。 根据回调函数返回值执行对应函数。\r
-class MyThread : public QThread\r
-{\r
-   public:\r
-    explicit MyThread();\r
-    ~MyThread();\r
-    void stop();\r
-\r
-   protected:\r
-    void run() override final;\r
-    virtual void process();\r
-   public slots:\r
-    void pause();\r
-    void resume();\r
-\r
-   private:\r
-    QMutex m_lock_stop;\r
-    volatile bool stopped;\r
-    QMutex m_lock_Pause;\r
-    std::atomic<bool> pauseFlag;\r
-    QWaitCondition condition;\r
-};\r
-#endif // MYTHREAD_H\r
diff --git a/readme.txt b/readme.txt
deleted file mode 100644 (file)
index 096c091..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-main.cpp示例如下\r
-________________________________________________________________________________________________________________________________________\r
-#include <iostream>\r
-#include "interface.h"\r
-#include "info.h"\r
-#include "windows.h"\r
-#include "Library_global.h"\r
-using namespace std;\r
-\r
-class MyInfo : public uapi::Info\r
-{\r
-public:\r
-    MyInfo(){};\r
-    ~MyInfo(){};\r
-    void onReadEvent(int eventType, void *data) override\r
-    {\r
-        cout<<"eventType = "<<eventType<<endl;\r
-    }\r
-};\r
-\r
-\r
-int main()\r
-{\r
-    MyInfo info;\r
-    Interface *handle = new Interface();\r
-    handle->InfoEventConnect(&info);\r
-    handle->SetCurrentMode(uapi::MODE_BLUETOOTH);\r
-\r
-// 串口配置\r
-    char *com = "COM11";\r
-    handle->SerialPortOpen(com, 921600);\r
-\r
-// 设置为整机段\r
-    handle->SetCurrentMode(uapi::MODE_BLUETOOTH);\r
-\r
-// 发送STACKINFO命令\r
-        handle->AtMessageSend(8,0x0d,NULL,0);\r
-\r
-// 获取文件列表\r
-    char ls_tx[] = "/user/";\r
-    handle->FileGetList(ls_tx, strlen(ls_tx));\r
-\r
-    char board_delete_path[] = "/user/test.mp3";\r
-    handle->FileDelete(board_delete_path, strlen(board_delete_path));\r
-\r
-// 上传文件\r
-    Sleep(1000);\r
-        char local_path[] = "C:/Users/y30032013/Desktop/music.mp3";\r
-    char board_path[] = "/user/music.mp3";\r
-    handle->FileUpload(board_path, local_path);\r
-    Sleep(3000);\r
-    handle->FileTransmitStop();\r
-\r
-// 下载文件\r
-        Sleep(1000);\r
-    handle->FileGetList(ls_tx, strlen(ls_tx));\r
-    Sleep(3000);\r
-    char name[] = "/user/music.mp3";\r
-    char pc_path[] = "C:/Users/y30032013/Desktop/bin/";\r
-    handle->FileDownload(name, pc_path);\r
-\r
-    while (1) {\r
-       Sleep(100);\r
-    }\r
-}\r
-________________________________________________________________________________________________________________________________________\r
diff --git a/release/LeiNiaoFactoryTool.exe b/release/LeiNiaoFactoryTool.exe
new file mode 100644 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
index c6011e2..0000000
Binary files a/release/wrtm_class.obj and /dev/null differ
diff --git a/release/产测记录/产测记录.csv b/release/产测记录/产测记录.csv
new file mode 100644 (file)
index 0000000..4e782e2
--- /dev/null
@@ -0,0 +1,7 @@
+开始时间,结束时间,测试耗时,软件版本,IMEI,ICCID,Modem版本,LCD测试,马达测试,按键测试,录音测试,电池测试,G-sensor测试,4G测试,整体结果\r
+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,通过,通过,通过,通过,失败,通过,失败,未通过\r
+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,通过,通过,通过,通过,通过,通过,通过,通过\r
+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,通过,通过,通过,通过,通过,通过,通过,通过\r
+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,通过,通过,通过,通过,失败,通过,通过,未通过\r
+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,通过,通过,通过,通过,失败,通过,通过\r
+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,未获取,通过,通过,通过,通过,通过,通过,通过\r
diff --git a/release/产测记录/老化记录/老化_20251105_094030.csv b/release/产测记录/老化记录/老化_20251105_094030.csv
new file mode 100644 (file)
index 0000000..6614706
--- /dev/null
@@ -0,0 +1 @@
+åº\8få\8f·,æ\97¶é\97´,ç\94µæ± æµ\8bè¯\95,G-sensoræµ\8bè¯\95,4Gæµ\8bè¯\95\r
diff --git a/release/新建文件夹.zip b/release/新建文件夹.zip
new file mode 100644 (file)
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/雷鸟产测工具.zip b/release/雷鸟产测工具.zip
new file mode 100644 (file)
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/雷鸟产测工具/LeiNiaoFactoryTool.exe b/release/雷鸟产测工具/LeiNiaoFactoryTool.exe
new file mode 100644 (file)
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 (file)
index 57db951..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-#include "result_thread.h"\r
-\r
-struct result_info g_result_info={0,NULL,0,NULL,false,NONE_DATA,0,NULL};\r
-QMutex g_result_thread_mlock;\r
-QWaitCondition g_result_thread_condition;\r
-\r
-\r
-\r
-Result_Thread::Result_Thread(QObject *parent)\r
-{\r
-    obj=parent;\r
-}\r
-\r
-Result_Thread::~Result_Thread()\r
-{\r
-}\r
-\r
-// 给 UI 线程发送消息\r
-void Result_Thread::process()\r
-{\r
-    g_result_thread_mlock.lock();\r
-    g_result_thread_condition.wait(&g_result_thread_mlock, MLOCK_TIMEOUT);\r
-    switch (g_result_info.result_thread_flag) {\r
-        case UART_RX_DATA:\r
-            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 槽函数\r
-            g_result_info.result_thread_flag = NONE_DATA;\r
-            break;\r
-        case LS_RESULT_DATA:\r
-            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));\r
-            g_result_info.result_thread_flag = NONE_DATA;\r
-            break;\r
-        case TRANSMIT_FILE_DATA:\r
-            QMetaObject::invokeMethod(obj, "transmit_rx_display",Q_ARG(bool, g_result_info.transmit_result_flag));\r
-            g_result_info.transmit_result_flag = false;\r
-            g_result_info.result_thread_flag = NONE_DATA;\r
-            break;\r
-        case AT_RESULT_DATA:\r
-            QMetaObject::invokeMethod(obj, "at_rx_display",Q_ARG(int, g_result_info.at_result_len),Q_ARG(u8Piont,g_result_info.at_result_buf));\r
-            g_result_info.result_thread_flag = NONE_DATA;\r
-            break;\r
-        default:\r
-            break;\r
-    }\r
-    g_result_thread_mlock.unlock();\r
-}\r
-\r
-uint32_t uart_callback(void *buf, uint32_t buf_len)\r
-{\r
-    g_result_info.uart_rx_buf_len = (int)buf_len;\r
-    // rx的数据不包含\0,所以多分配1字节。\r
-    g_result_info.uart_rx_buf=(uint8_t *)malloc(buf_len);\r
-    memset(g_result_info.uart_rx_buf,0,buf_len);\r
-    memcpy_s(g_result_info.uart_rx_buf, buf_len, (uint8_t *)buf, buf_len);\r
-    g_result_info.result_thread_flag = UART_RX_DATA;\r
-    g_result_thread_mlock.lock();\r
-    g_result_thread_condition.wakeAll();\r
-    g_result_thread_mlock.unlock();\r
-    return 0;\r
-}\r
-\r
-uint32_t ls_callback(uint32_t size, uapi_ls_info_t *buff)\r
-{\r
-    g_result_info.transmit_ls_buff = (uapi_ls_info_t *)malloc(size * sizeof(uapi_ls_info_t)+1);\r
-    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));\r
-    g_result_info.transmit_ls_size = static_cast<int>(size);\r
-    g_result_info.result_thread_flag = LS_RESULT_DATA;\r
-    g_result_thread_mlock.lock();\r
-    g_result_thread_condition.wakeAll();\r
-    g_result_thread_mlock.unlock();\r
-    return 0;\r
-}\r
-\r
-uint32_t transmit_callback(bool is_finished, uintptr_t usr_data)\r
-{\r
-    g_result_info.transmit_result_flag = is_finished;\r
-    Q_UNUSED(usr_data);\r
-    g_result_info.result_thread_flag = TRANSMIT_FILE_DATA;\r
-    g_result_thread_mlock.lock();\r
-    g_result_thread_condition.wakeAll();\r
-    g_result_thread_mlock.unlock();\r
-    return 0;\r
-}\r
-\r
-uint32_t at_callback(void *buf, uint32_t len)\r
-{\r
-    uint8_t * at_buff = (uint8_t *)malloc(len);\r
-    memcpy_s(at_buff, len , buf, len);\r
-    g_result_info.at_result_buf = (uint8_t *)at_buff;\r
-    g_result_info.at_result_len = len;\r
-    g_result_info.result_thread_flag = AT_RESULT_DATA;\r
-    g_result_thread_mlock.lock();\r
-    g_result_thread_condition.wakeAll();\r
-    g_result_thread_mlock.unlock();\r
-    return 0;\r
-}\r
-void transmit_get_data_count(uint32_t *total_size, uint32_t *current_size)\r
-{\r
-    uapi_transmit_progress transmint_data_count;\r
-    uapi_transmit_process(&transmint_data_count);\r
-    *total_size=transmint_data_count.total_size;\r
-    *current_size=transmint_data_count.transmited_size;\r
-}\r
diff --git a/result_thread.h b/result_thread.h
deleted file mode 100644 (file)
index acb41a5..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef RESULT_THREAD_H\r
-#define RESULT_THREAD_H\r
-#include "mythread.h"\r
-#include "common.h"\r
-#include <header.h>\r
-#include <stdint.h>\r
-#include <QMutex>\r
-#include <QWaitCondition>\r
-#include <qdebug.h>\r
-\r
-#define BUF_SIZE 4096\r
-#define MLOCK_TIMEOUT 2000\r
-enum get_data_flag\r
-{\r
-    NONE_DATA = -1,\r
-    UART_RX_DATA = 0,\r
-    LS_RESULT_DATA,\r
-    TRANSMIT_FILE_DATA,\r
-    AT_RESULT_DATA,\r
-};\r
-\r
-struct result_info{\r
-    // uart收到的数据\r
-    int uart_rx_buf_len;\r
-    uint8_t *uart_rx_buf;\r
-\r
-    // ls数据大小和内容\r
-    int transmit_ls_size;\r
-    uapi_ls_info_t *transmit_ls_buff;\r
-\r
-    // 传输文件是否成功\r
-    bool transmit_result_flag;\r
-\r
-    // 当前回调函数标记\r
-    int result_thread_flag;\r
-\r
-    // at调用返回\r
-    int at_result_len;\r
-    uint8_t *at_result_buf;\r
-};\r
-\r
-class Result_Thread : public MyThread\r
-{\r
-public:\r
-    Result_Thread(QObject *parent = 0);\r
-    ~Result_Thread();\r
-protected:\r
-     void process() override final;\r
-private:\r
-     QObject *obj;\r
-};\r
-\r
-uint32_t uart_callback(void *buf, uint32_t buf_len);\r
-uint32_t ls_callback(uint32_t size, uapi_ls_info_t *buff);\r
-uint32_t transmit_callback(bool is_finished, uintptr_t usr_data);\r
-uint32_t at_callback(void *buf, uint32_t len);\r
-void transmit_get_data_count(uint32_t *total_size, uint32_t *current_size);\r
-#endif // RESULT_THREAD_H\r
diff --git a/untitled_zh_CN.ts b/untitled_zh_CN.ts
deleted file mode 100644 (file)
index 806770f..0000000
+++ /dev/null
@@ -1,844 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="zh_CN">
-<context>
-    <name>MainWindow</name>
-    <message>
-        <location filename="mainwindow.ui" line="2771"/>
-        <source>打开串口</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="636"/>
-        <source>AT命令</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="147"/>
-        <location filename="mainwindow.ui" line="768"/>
-        <location filename="mainwindow.ui" line="1607"/>
-        <source>发送</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="117"/>
-        <location filename="mainwindow.ui" line="681"/>
-        <location filename="mainwindow.ui" line="1577"/>
-        <source>Debug</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="168"/>
-        <location filename="mainwindow.ui" line="1628"/>
-        <source>清除发送</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="368"/>
-        <source>From Board</source>
-        <oldsource>From Boad</oldsource>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="388"/>
-        <source>File Storage</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="254"/>
-        <location filename="mainwindow.ui" line="408"/>
-        <source>Local File Path:</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="21"/>
-        <source>Factory_Tools</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="198"/>
-        <source>To Board</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="234"/>
-        <source>Upload File</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="275"/>
-        <source>Board File Path:</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="327"/>
-        <source>Choose File</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="439"/>
-        <source>....</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="461"/>
-        <source>File Selector</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="481"/>
-        <source>File Path:</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="522"/>
-        <source>Get file List</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="543"/>
-        <source>File Name:</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="594"/>
-        <source>Download</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="612"/>
-        <source>Delete</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="627"/>
-        <source>Stop</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="669"/>
-        <location filename="mainwindow.ui" line="1658"/>
-        <source>MCU</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="706"/>
-        <location filename="mainwindow.ui" line="713"/>
-        <location filename="mainwindow.ui" line="720"/>
-        <location filename="mainwindow.ui" line="727"/>
-        <source>待开发</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="749"/>
-        <source>FSRM</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="799"/>
-        <source>module id</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="814"/>
-        <source>cmd id</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="821"/>
-        <source>payload</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="831"/>
-        <source>MEDIA</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="843"/>
-        <source>Media</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="873"/>
-        <source>Music Play</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="880"/>
-        <source>Music Stop</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="914"/>
-        <source>Audio Record</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="924"/>
-        <location filename="mainwindow.ui" line="1663"/>
-        <source>BT</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1207"/>
-        <location filename="mainwindow.ui" line="1229"/>
-        <location filename="mainwindow.ui" line="2039"/>
-        <location filename="mainwindow.ui" line="2201"/>
-        <source>Channel(0-78)</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1369"/>
-        <location filename="mainwindow.ui" line="1452"/>
-        <location filename="mainwindow.ui" line="1762"/>
-        <location filename="mainwindow.ui" line="1859"/>
-        <source>Channel(0-39)</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1484"/>
-        <location filename="mainwindow.ui" line="1794"/>
-        <source>Length(0-255)</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2256"/>
-        <source>BTDUTMODE</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2269"/>
-        <source>信令测试:</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2312"/>
-        <source>其他</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2324"/>
-        <source>单音测试与功率调整</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2342"/>
-        <source>channel(0-78)</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2355"/>
-        <source>功率调整</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2368"/>
-        <source>单音测试</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2428"/>
-        <source>power chip(2-14)</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2445"/>
-        <source>BT_UART</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2457"/>
-        <source>唤醒</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2470"/>
-        <source>睡眠</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2973"/>
-        <source>dongle调试</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1751"/>
-        <location filename="mainwindow.ui" line="1851"/>
-        <location filename="mainwindow.ui" line="1939"/>
-        <location filename="mainwindow.ui" line="2106"/>
-        <location filename="mainwindow.ui" line="2288"/>
-        <location filename="mainwindow.ui" line="2387"/>
-        <location filename="mainwindow.ui" line="2407"/>
-        <source>OFF</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="936"/>
-        <source>耦合测试设置</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="957"/>
-        <source>延时时间</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="970"/>
-        <source>ms</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="996"/>
-        <source>DongleMAC</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1016"/>
-        <source>耦合测试</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1028"/>
-        <location filename="mainwindow.ui" line="1912"/>
-        <source>BR EDR</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1078"/>
-        <location filename="mainwindow.ui" line="1271"/>
-        <location filename="mainwindow.ui" line="2007"/>
-        <location filename="mainwindow.ui" line="2169"/>
-        <source>2-DH5</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1101"/>
-        <location filename="mainwindow.ui" line="1319"/>
-        <location filename="mainwindow.ui" line="2084"/>
-        <location filename="mainwindow.ui" line="2114"/>
-        <source>Length(0-27)</source>
-        <oldsource>Length</oldsource>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1053"/>
-        <location filename="mainwindow.ui" line="1246"/>
-        <location filename="mainwindow.ui" line="1982"/>
-        <location filename="mainwindow.ui" line="2144"/>
-        <source>DH1</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1115"/>
-        <location filename="mainwindow.ui" line="1171"/>
-        <location filename="mainwindow.ui" line="1361"/>
-        <location filename="mainwindow.ui" line="1444"/>
-        <location filename="mainwindow.ui" line="1746"/>
-        <location filename="mainwindow.ui" line="1846"/>
-        <location filename="mainwindow.ui" line="1934"/>
-        <location filename="mainwindow.ui" line="2101"/>
-        <location filename="mainwindow.ui" line="2283"/>
-        <location filename="mainwindow.ui" line="2382"/>
-        <location filename="mainwindow.ui" line="2402"/>
-        <source>ON</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1185"/>
-        <location filename="mainwindow.ui" line="2127"/>
-        <source>BR TX</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1130"/>
-        <location filename="mainwindow.ui" line="1301"/>
-        <location filename="mainwindow.ui" line="1466"/>
-        <location filename="mainwindow.ui" line="1776"/>
-        <location filename="mainwindow.ui" line="1954"/>
-        <location filename="mainwindow.ui" line="2053"/>
-        <source>10101010</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1135"/>
-        <location filename="mainwindow.ui" line="1306"/>
-        <location filename="mainwindow.ui" line="1471"/>
-        <location filename="mainwindow.ui" line="1781"/>
-        <location filename="mainwindow.ui" line="1959"/>
-        <location filename="mainwindow.ui" line="2058"/>
-        <source>PRBS9</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1140"/>
-        <location filename="mainwindow.ui" line="1311"/>
-        <location filename="mainwindow.ui" line="1476"/>
-        <location filename="mainwindow.ui" line="1786"/>
-        <location filename="mainwindow.ui" line="1964"/>
-        <location filename="mainwindow.ui" line="2063"/>
-        <source>11110000</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1058"/>
-        <location filename="mainwindow.ui" line="1251"/>
-        <location filename="mainwindow.ui" line="1987"/>
-        <location filename="mainwindow.ui" line="2149"/>
-        <source>DH3</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1063"/>
-        <location filename="mainwindow.ui" line="1256"/>
-        <location filename="mainwindow.ui" line="1992"/>
-        <location filename="mainwindow.ui" line="2154"/>
-        <source>DH5</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1068"/>
-        <location filename="mainwindow.ui" line="1261"/>
-        <location filename="mainwindow.ui" line="1997"/>
-        <location filename="mainwindow.ui" line="2159"/>
-        <source>2-DH1</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1073"/>
-        <location filename="mainwindow.ui" line="1266"/>
-        <location filename="mainwindow.ui" line="2002"/>
-        <location filename="mainwindow.ui" line="2164"/>
-        <source>2-DH3</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1083"/>
-        <location filename="mainwindow.ui" line="1276"/>
-        <location filename="mainwindow.ui" line="2012"/>
-        <location filename="mainwindow.ui" line="2174"/>
-        <source>3-DH1</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1088"/>
-        <location filename="mainwindow.ui" line="1281"/>
-        <location filename="mainwindow.ui" line="2017"/>
-        <location filename="mainwindow.ui" line="2179"/>
-        <source>3-DH3</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1093"/>
-        <location filename="mainwindow.ui" line="1286"/>
-        <location filename="mainwindow.ui" line="2022"/>
-        <location filename="mainwindow.ui" line="2184"/>
-        <source>3-DH5</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1154"/>
-        <location filename="mainwindow.ui" line="2077"/>
-        <source>BR RX</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1336"/>
-        <location filename="mainwindow.ui" line="1711"/>
-        <source>BLE</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1430"/>
-        <location filename="mainwindow.ui" line="1732"/>
-        <source>BLE TX</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1386"/>
-        <location filename="mainwindow.ui" line="1501"/>
-        <location filename="mainwindow.ui" line="1811"/>
-        <location filename="mainwindow.ui" line="1876"/>
-        <source>BLE 1M</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1391"/>
-        <location filename="mainwindow.ui" line="1506"/>
-        <location filename="mainwindow.ui" line="1816"/>
-        <location filename="mainwindow.ui" line="1881"/>
-        <source>BLE 2M</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1405"/>
-        <location filename="mainwindow.ui" line="1895"/>
-        <source>BLE RX</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1699"/>
-        <source>非信令测试</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2211"/>
-        <source>信令测试</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2922"/>
-        <source>菜单</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2963"/>
-        <source>单板</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2946"/>
-        <source>整机</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2538"/>
-        <source>4800</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2543"/>
-        <source>9600</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2548"/>
-        <source>14400</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2553"/>
-        <source>19200</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2558"/>
-        <source>38400</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2563"/>
-        <source>57600</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2528"/>
-        <location filename="mainwindow.ui" line="2568"/>
-        <source>115200</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="1526"/>
-        <source>获取RX Count</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2223"/>
-        <source>信令</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2573"/>
-        <source>128000</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2578"/>
-        <source>230400</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2583"/>
-        <source>256000</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2588"/>
-        <source>460800</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2593"/>
-        <source>500000</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2598"/>
-        <source>512000</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2603"/>
-        <source>600000</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2608"/>
-        <source>750000</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2613"/>
-        <source>921600</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2618"/>
-        <source>1000000</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2623"/>
-        <source>1500000</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2628"/>
-        <source>2000000</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2807"/>
-        <source>连接设备</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2653"/>
-        <source>         MAC地址</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="189"/>
-        <location filename="mainwindow.ui" line="1649"/>
-        <source>加回车换行</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="348"/>
-        <location filename="mainwindow.cpp" line="645"/>
-        <source>Upload</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="296"/>
-        <source>stop</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="699"/>
-        <source>StackInfo</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="556"/>
-        <source>PushButton</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2666"/>
-        <source>串口操作</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2875"/>
-        <source>清除接收</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2708"/>
-        <source>保存窗口</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2750"/>
-        <source>16进制显示</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2831"/>
-        <source>16进制发送</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2687"/>
-        <source>RTS</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2729"/>
-        <source>DTR</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.ui" line="2853"/>
-        <source>COM1</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="223"/>
-        <source>串口</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="223"/>
-        <source>打开串口失败!</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="352"/>
-        <source>注册表</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="352"/>
-        <source>无法打开注册表!</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="539"/>
-        <source>ls fail!<byte value="xd"/>
-</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="563"/>
-        <source>文件大小为0!</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="576"/>
-        <source>文件下载启动失败!</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="701"/>
-        <location filename="mainwindow.cpp" line="895"/>
-        <location filename="mainwindow.cpp" line="911"/>
-        <location filename="mainwindow.cpp" line="964"/>
-        <location filename="mainwindow.cpp" line="981"/>
-        <source>AT</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="701"/>
-        <source>AT send fail!<byte value="xd"/>
-</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="539"/>
-        <source>ls</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="532"/>
-        <location filename="mainwindow.cpp" line="554"/>
-        <location filename="mainwindow.cpp" line="596"/>
-        <location filename="mainwindow.cpp" line="638"/>
-        <location filename="mainwindow.cpp" line="765"/>
-        <location filename="mainwindow.cpp" line="776"/>
-        <location filename="mainwindow.cpp" line="804"/>
-        <location filename="mainwindow.cpp" line="827"/>
-        <source>File Path</source>
-        <oldsource>File</oldsource>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="532"/>
-        <location filename="mainwindow.cpp" line="554"/>
-        <location filename="mainwindow.cpp" line="596"/>
-        <location filename="mainwindow.cpp" line="765"/>
-        <location filename="mainwindow.cpp" line="776"/>
-        <location filename="mainwindow.cpp" line="804"/>
-        <source>文件路径为空!</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="558"/>
-        <location filename="mainwindow.cpp" line="563"/>
-        <source>Board File Name</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="576"/>
-        <source>Downloade</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="608"/>
-        <source>delete</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="608"/>
-        <source>delete file fail!<byte value="xd"/>
-</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="638"/>
-        <source>文件路径为空!</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="645"/>
-        <source>文件上传启动失败!<byte value="xd"/>
-</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="827"/>
-        <source>MAC地址为空!</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="895"/>
-        <location filename="mainwindow.cpp" line="911"/>
-        <location filename="mainwindow.cpp" line="964"/>
-        <location filename="mainwindow.cpp" line="981"/>
-        <source>length错误!</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="955"/>
-        <location filename="mainwindow.cpp" line="972"/>
-        <location filename="mainwindow.cpp" line="989"/>
-        <location filename="mainwindow.cpp" line="1003"/>
-        <location filename="mainwindow.cpp" line="1016"/>
-        <source>操作错误</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="955"/>
-        <location filename="mainwindow.cpp" line="972"/>
-        <location filename="mainwindow.cpp" line="989"/>
-        <location filename="mainwindow.cpp" line="1003"/>
-        <location filename="mainwindow.cpp" line="1016"/>
-        <source>应先关闭射频测试项!</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="mainwindow.cpp" line="558"/>
-        <source>请选择正确的文件!</source>
-        <translation type="unfinished"></translation>
-    </message>
-</context>
-<context>
-    <name>QObject</name>
-    <message>
-        <location filename="mainwindow.cpp" line="387"/>
-        <source>HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM</source>
-        <translation type="unfinished"></translation>
-    </message>
-</context>
-</TS>
diff --git a/wrtm_class.cpp b/wrtm_class.cpp
deleted file mode 100644 (file)
index 2f23908..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-#include "header.h"\r
-\r
-#include "interface.h"\r
-#include "info.h"\r
-#include "windows.h"\r
-#include "Library_global.h"\r
-#include "qdebug.h"\r
-using namespace std;\r
-\r
-static uart_rx_function g_uart_rx_callback=NULL;\r
-static at_result_callback g_at_result_callback=NULL;\r
-static transmit_ls_result g_ls_result_callback=NULL;\r
-static transmit_result_hook g_result_hook_callback=NULL;\r
-\r
-\r
-class MyInfo : public uapi::Info\r
-{\r
-public:\r
-    MyInfo(){};\r
-    ~MyInfo(){};\r
-    void onReadEvent(int eventType, void *data) override\r
-    {\r
-        uapi::SerialPortReceiveData *precvdata = NULL;\r
-        uapi::TransmitResult *ptransResult = NULL;\r
-        uapi::FileListResult *flistResult = NULL;\r
-        uapi::AtReceiveData *atrecvdata = NULL;\r
-\r
-        switch(eventType)\r
-        {\r
-            case uapi::INFO_SERIALPORT:\r
-                precvdata=(uapi::SerialPortReceiveData*)data;\r
-                qDebug()<<"INFO_SERIALPORT "<< precvdata->data;\r
-                if(g_uart_rx_callback)\r
-                    g_uart_rx_callback(precvdata->data,precvdata->dataLength);\r
-                break;\r
-            case uapi::INFO_FILE_TRANSMIT_RESULT:\r
-                ptransResult = (uapi::TransmitResult*)data;\r
-                qDebug()<<"INFO_FILE_TRANSMIT_RESULT "<< ptransResult->finishResult;\r
-                if(g_result_hook_callback)\r
-                    g_result_hook_callback(ptransResult->finishResult,NULL);\r
-                break;\r
-            case uapi::INFO_FILE_LIST_RESULT:\r
-                flistResult=(uapi::FileListResult*)data;\r
-                qDebug()<<"INFO_FILE_LIST_RESULT "<< flistResult->lsInfo->name;\r
-                if(g_ls_result_callback)\r
-                    g_ls_result_callback(flistResult->lsInfoNumber,(uapi_ls_info_t *)flistResult->lsInfo);\r
-                break;\r
-            case uapi::INFO_AT_RECEIVE:\r
-                atrecvdata=(uapi::AtReceiveData*)data;\r
-                qDebug()<<"INFO_AT_RECEIVE "<< atrecvdata->data;\r
-                if(g_at_result_callback)\r
-                    g_at_result_callback(atrecvdata->data,atrecvdata->dataLength);\r
-                break;\r
-        }\r
-\r
-    }\r
-};\r
-static  MyInfo info;\r
-static Interface *handle= new Interface();\r
-uapi_errcode uapi_uart_set_currentMode(int mode)\r
-{\r
-    if (mode == 0)\r
-        handle->SetCurrentMode(uapi::MODE_SERIALPORT);\r
-    else\r
-        handle->SetCurrentMode(uapi::MODE_BLUETOOTH);\r
-    return SUCC;\r
-}\r
-uapi_errcode uapi_uart_open(const char *com,  uint32_t baud) // 打开uart口, com 格式为 "\\\\.\\COM47", baud 为波特率\r
-{\r
-    handle->InfoEventConnect(&info);\r
-    handle->SetCurrentMode(uapi::MODE_SERIALPORT);\r
-    int ret= handle->SerialPortOpen(com,baud);\r
-    if (ret == 0)\r
-        return SUCC;\r
-    else\r
-        return FAIL;\r
-}\r
-uapi_errcode uapi_uart_tx_data(void *buf, uint32_t buf_len) // uart TX 发送数据buf\r
-{\r
-    qDebug()<<"tx:"<<QString((char *)buf);\r
-    handle->SerialPortWrite((unsigned char *)buf,buf_len);\r
-    return SUCC;\r
-}\r
-uapi_errcode uapi_uart_set_rts_dtr(int rts_flag, int dtr_flag) // uart 设置rts和dtr开关\r
-{\r
-//    handle->SetCurrentMode(uapi::MODE_SERIALPORT);\r
-    handle->SerialPortSetRtsDtr(rts_flag,dtr_flag);\r
-    return SUCC;\r
-}\r
-uapi_errcode uapi_uart_callback_register(uart_rx_function callback) // uart 注册回调函数\r
-{\r
-    g_uart_rx_callback = callback;\r
-    return SUCC;\r
-}\r
-uapi_errcode uapi_uart_close(void)// 关闭uart口\r
-{\r
-\r
-    handle->SerialPortClose();\r
-    return SUCC;\r
-}\r
-\r
-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章\r
-{\r
-     g_at_result_callback = callback;\r
-\r
-    handle->AtMessageSend(module_id,cmd_id,pkt,pkt_size);\r
-\r
-    return SUCC;\r
-}\r
-\r
-uapi_errcode uapi_file_download(char* board_file_path, char* local_file_path, transmit_result_hook handler) // 文件下载接口,参数分别为板端文件地址(详细到文件后缀),pc端存储路径(详细到文件夹),传输结果回调函数\r
-{\r
-    g_result_hook_callback = handler;\r
-    handle->FileDownload(board_file_path,local_file_path);\r
-    return SUCC;\r
-}\r
-\r
-uapi_errcode uapi_file_upload(char* board_file_path,char* local_file_path, transmit_result_hook handler)// 文件上传接口,参数分别为板端文件地址(详细到文件后缀),pc端存储路径(详细到文件后缀),传输结果回调函数\r
-{\r
-    g_result_hook_callback = handler;\r
-    handle->FileUpload(board_file_path,local_file_path);\r
-    return SUCC;\r
-}\r
-\r
-uapi_errcode uapi_ls_send(char *path, uint32_t path_len, transmit_ls_result callback)// 查询文件列表接口,参数为板端文件路径(详细到文件夹),路径长度,get list回调函数\r
-{\r
-    g_ls_result_callback = callback;\r
-    qDebug()<<"uapi_ls_send  "<<path;\r
-    handle->FileGetList(path,path_len);\r
-\r
-    return SUCC;\r
-}\r
-\r
-uapi_errcode uapi_file_delete(char *board_file_path, uint32_t board_file_path_len) // 删除指定文件接口,参数为板端文件地址(详细到文件后缀),文件路径长度\r
-{\r
-    handle->FileDelete(board_file_path,board_file_path_len);\r
-    return SUCC;\r
-}\r
-\r
-uapi_errcode uapi_file_transmit_stop(void)// 停止文件下载接口\r
-{\r
-    handle->FileTransmitStop();\r
-    return SUCC;\r
-}\r
-\r
-uapi_errcode uapi_transmit_process(uapi_transmit_progress *data) // 获取文件传输进度,入参 data 更新为正在传输的文件的总大小和已传输大小\r
-{\r
-    handle->FileTransmitProgress((uapi::FileTransmitDataCount*)data);\r
-    return SUCC;\r
-}\r