-#include "mainwindow.h"
+#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "config_manager.h"
#include <QMessageBox>
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
- setWindowTitle("雷鸟产测工具 V1.7");
+ setWindowTitle("FD272产测工具 V1.0");
// 确保控制台输出使用UTF-8编码
QTextCodec *utf8Codec = QTextCodec::codecForName("UTF-8");
// 设置产测按钮默认蓝色样式
ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }");
- // 调整二维码/条形码区域的布局比例:上方二维码占 2/3,下方条形码占 1/3
- if (ui->verticalLayout_4) {
- ui->verticalLayout_4->setStretch(0, 0); // checkbox
- ui->verticalLayout_4->setStretch(1, 2); // qr view
- ui->verticalLayout_4->setStretch(2, 1); // barcode view
- }
- if (ui->verticalLayout_2) {
- ui->verticalLayout_2->setStretch(0, 0); // checkbox
- ui->verticalLayout_2->setStretch(1, 2); // qr view
- ui->verticalLayout_2->setStretch(2, 1); // barcode view
- }
// 初始化产测相关变量
lcdTestTimer = new QTimer(this);
motorTestTimer = new QTimer(this);
- test4GTimer = new QTimer(this);
- signal4GTimer = new QTimer(this);
- cat1SignalTimer = new QTimer(this);
testTimeoutTimer = new QTimer(this);
+ gSensorIntervalTimer = 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;
+ touchTestPopupShown = false;
+ brightTestPopupShown = false;
+ deepsleepTestPopupShown = false;
isWaitingForUserConfirm = false;
lcdBacklightOn = false; // 初始化LCD背光状态为关闭
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;
- audioMicMiddleConsecutiveCount = 0;
- audioMicTotalPassCount = 0;
- audioTestFinished = false;
+ keyRotateDetected = false;
+ audioTestRoundIndex = 0;
+ audioTestAnyPass = false;
+ audioTestAwaitingMicLevel = false;
bluetoothTestTimer = new QTimer(this);
+ gpsTestTimer = new QTimer(this);
+ gpsPollTimer = new QTimer(this);
bluetoothAddresses.clear();
bluetoothTestFinished = false;
+ gpsTestFinished = false;
+ gpsInfoSeenIn10Sec = false;
+ gpsMaxNumSats = 0;
+ gpsMaxTrace = 0;
+ gpsMaxCn = 0;
detectedBluetoothAddress = "";
- detectedBluetoothRSSI = 0;
- pingTestTimer = new QTimer(this);
- pingTestFinished = false;
- pingSuccessCount = 0;
- currentAudioStep = AUDIO_PLAYING_1KHZ;
- currentModemVersion = "";
- currentSimStatus = -1;
+ detectedBluetoothRSSI = -128;
+ bluetoothMaxRssi = -128;
+ leaklightGreen = 0;
+ leaklightRed = 0;
+ leaklightIr = 0;
+ leaklightGreenSeen = false;
+ leaklightRedSeen = false;
+ leaklightIrSeen = false;
// 初始化日志文件相关变量
testLogFile = nullptr;
testLogStream = 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);
+ connect(gSensorIntervalTimer, &QTimer::timeout, this, &MainWindow::onGsensorIntervalTimeout);
connect(bluetoothTestTimer, &QTimer::timeout, this, &MainWindow::onBluetoothTestTimer);
- connect(pingTestTimer, &QTimer::timeout, this, &MainWindow::onPingTestTimeout);
-
- // 连接ICCID和IMEI输入框的信号
- connect(ui->ICCIDlineEdit, &QLineEdit::textChanged, this, &MainWindow::onICCIDLineEditTextChanged);
- connect(ui->IMEIlineEdit, &QLineEdit::textChanged, this, &MainWindow::onIMEILineEditTextChanged);
-
- // 连接ICCID和IMEI复选框的信号
- connect(ui->checkBox_iccid, &QCheckBox::stateChanged, this, &MainWindow::onICCIDCheckBoxStateChanged);
- connect(ui->checkBox_imei, &QCheckBox::stateChanged, this, &MainWindow::onIMEICheckBoxStateChanged);
-
- // 初始化GraphicsView的场景
- ui->graphicsView_iccid_qr->setScene(new QGraphicsScene(this));
- ui->graphicsView_iccid_barcode->setScene(new QGraphicsScene(this));
- ui->graphicsView_imei_qr->setScene(new QGraphicsScene(this));
- ui->graphicsView_imei_barcode->setScene(new QGraphicsScene(this));
-
- // 设置GraphicsView的背景和缩放
- ui->graphicsView_iccid_qr->setBackgroundBrush(QBrush(Qt::white));
- ui->graphicsView_iccid_barcode->setBackgroundBrush(QBrush(Qt::white));
- ui->graphicsView_imei_qr->setBackgroundBrush(QBrush(Qt::white));
- ui->graphicsView_imei_barcode->setBackgroundBrush(QBrush(Qt::white));
-
- // 设置GraphicsView的缩放模式,使其能够自适应
- ui->graphicsView_iccid_qr->setRenderHint(QPainter::Antialiasing, false);
- ui->graphicsView_iccid_barcode->setRenderHint(QPainter::Antialiasing, false);
- ui->graphicsView_imei_qr->setRenderHint(QPainter::Antialiasing, false);
- ui->graphicsView_imei_barcode->setRenderHint(QPainter::Antialiasing, false);
+ connect(gpsTestTimer, &QTimer::timeout, this, &MainWindow::onGpsTestTimer);
+ connect(gpsPollTimer, &QTimer::timeout, this, &MainWindow::onGpsPollTimer);
+
+ // 初始化G-sensor采集状态
+ gSensorCollecting = false;
+ gSensorHasStart = false;
+ gSensorHasLast = false;
+ gSensorErrorDetected = false;
+ gSensorAnySample = false;
+ gSensorAllSamplesInRange = true;
+ gSensorStartX = 0.0;
+ gSensorStartY = 0.0;
+ gSensorStartZ = 0.0;
+ gSensorLastX = 0.0;
+ gSensorLastY = 0.0;
+ gSensorLastZ = 0.0;
}
MainWindow::~MainWindow()
}
}
-// 提取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;
- // 尝试重命名日志文件(如果ICCID也已获取)
- renameLogFileWithDeviceInfo();
- } 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;
- // 尝试重命名日志文件(如果IMEI也已获取)
- renameLogFileWithDeviceInfo();
- } 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("!", "").trimmed();
- currentModemVersion = modemVerInfo;
- ui->ModemVerlineEdit->setText(modemVerInfo);
-
- // 校验期望MODEM_VER
- QString expectedModem = ui->expectedModemVerLineEdit ? ui->expectedModemVerLineEdit->text().trimmed() : QString();
- // 对期望值也进行相同的清理处理
- if (!expectedModem.isEmpty()) {
- expectedModem = expectedModem.replace("!", "").trimmed();
- }
-
- qDebug() << "提取的Modem Version:" << modemVerInfo;
- qDebug() << "期望的Modem Version:" << expectedModem;
-
- // 使用大小写不敏感对比,更宽松
- if (!expectedModem.isEmpty() && modemVerInfo.compare(expectedModem, Qt::CaseInsensitive) != 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++;
- }
-
- // 查找结束位置:优先查找@modemVer:(如果PYVer和ModemVer在同一行)
- int end = data.indexOf("@modemVer:", start, Qt::CaseInsensitive);
- if (end == -1) {
- // 如果没有@modemVer:,查找行结束标志(换行符或字符串结束)
- end = data.indexOf('\n', start);
- if (end == -1) {
- end = data.indexOf('\r', start);
- if (end == -1) {
- end = data.length();
- }
- }
- }
-
- // 提取PYVer版本信息(到@modemVer:之前或行尾)
- PYVerInfo = data.mid(start, end - start).trimmed();
- }
- // 方法2:查找"@pyver:"标识的格式(新格式)
- else {
- start = data.indexOf("@pyver:", 0, Qt::CaseInsensitive);
- if (start != -1) {
- // 计算版本信息的起始位置(跳过"@pyver:")
- const QString key = "@pyver:";
- start += key.length();
-
- // 查找结束位置:优先查找@modemVer:(如果PYVer和ModemVer在同一行)
- int end = data.indexOf("@modemVer:", start, Qt::CaseInsensitive);
- if (end == -1) {
- // 如果没有@modemVer:,查找行结束标志(换行符或字符串结束)
- end = data.indexOf('\n', start);
- if (end == -1) {
- end = data.indexOf('\r', start);
- if (end == -1) {
- end = data.length();
- }
- }
- }
-
- // 提取PYVer版本信息(到@modemVer:之前或行尾)
- 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;
- }
- }
- }
-
- // 验证PYVER Version是否有效(不为空即可)
- if (!PYVerInfo.isEmpty()) {
- // 清理版本字符串:移除特殊字符,去除首尾空格
- PYVerInfo = PYVerInfo.replace("!", "").trimmed();
-
- // 保存到成员变量
- currentPYVerVersion = PYVerInfo;
- // 显示到PYVer文本框
- ui->PYVerlineEdit->setText(PYVerInfo);
- qDebug() << "提取的PYVER Version:" << PYVerInfo;
- qDebug() << "MODEM类型判断: " << (isEGModem() ? "EG系列" : "非EG系列");
-
- // 校验期望PYVER
- QString expectedPYVER = ui->expectedPYVerLineEdit ? ui->expectedPYVerLineEdit->text().trimmed() : QString();
- // 对期望值也进行相同的清理处理
- if (!expectedPYVER.isEmpty()) {
- expectedPYVER = expectedPYVER.replace("!", "").trimmed();
- }
-
- qDebug() << "提取的PYVER Version:" << PYVerInfo;
- qDebug() << "期望的PYVER Version:" << expectedPYVER;
-
- // 使用大小写不敏感对比,更宽松
- if (!expectedPYVER.isEmpty() && PYVerInfo.compare(expectedPYVER, Qt::CaseInsensitive) != 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格式数据
+// 解析MESSAGE_4G_NETWORK_STAT_CHANGED格式数据(4G功能已移除,保留空实现以兼容旧日志)
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值显示到界面
- appendToLogFile(QString("Network Stat Signal值: %1\n").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;
- }
+ Q_UNUSED(data);
}
// 串口数据接收处理函数
}
}
- // 检测设备信息数据(去掉[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);
- }
+ // 4G/PPP 相关解析已移除
// 检测工厂模式进入确认(用于产测)
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);
- }
+ // 4G/PPP 相关解析已移除
// 检测LCD测试结果(用于产测)
if (line.contains("LCD test")) {
}
// 检测按键测试结果(用于产测)
- if (line.contains("fac:id")) {
+ if (line.contains("fac:id") || line.contains("testPresenter::OnRotate")) {
checkKeyTestResult(line);
}
// 检测录音测试结果(用于产测)
- if (line.contains("MEDIAAUDIORECORD") || line.contains("MEDIAMUSICPLAY") ||
- line.contains("Start Audio Capturer SUCCESS") ||
- line.contains("fac:mic level:")) {
- qDebug() << "录音测试相关数据匹配:" << line.trimmed();
+ if ((line.contains("AudioTest", Qt::CaseInsensitive) || line.contains("mic level", Qt::CaseInsensitive)) &&
+ isProductionTestRunning && currentTestStep == TEST_AUDIO) {
checkAudioTestResult(line);
}
}
// 检测G-sensor测试结果(用于产测)
- if (line.contains("gsensor") || line.contains("GSENSOR") || line.contains("fac:gsensor")) {
- qDebug() << "检测到gsensor相关数据,调用checkGsensorTestResult:" << line.trimmed();
+ // 设备输出格式可能为:XYZ: X=-1.28,Y=8.22,Z=-4.60
+ if (line.contains("XYZ:") || line.contains("gsensor") || line.contains("GSENSOR") || line.contains("fac:gsensor")) {
+ qDebug() << "检测到gsensor/XYZ相关数据,调用checkGsensorTestResult:" << line.trimmed();
checkGsensorTestResult(line);
}
+
+ // 检测漏光测试结果
+ if (line.contains("leaklight:", Qt::CaseInsensitive) || line.contains("green:", Qt::CaseInsensitive) ||
+ line.contains("red:", Qt::CaseInsensitive) || line.contains("ir:", Qt::CaseInsensitive)) {
+ checkLeaklightTestResult(line);
+ }
// 检测蓝牙测试结果(用于产测)
- if (line.contains("fac:Device:") || line.contains("[BtScan]") || line.contains("BTSCANTEST")) {
+ // 扩大触发条件:fac:Device、[BtScan]、BTSCANTEST、RSSI+Device、RSSI+MAC、或RSSI+MAC地址格式(xx:xx:xx:xx:xx:xx)
+ bool btRelated = line.contains("fac:Device:") || line.contains("[BtScan]") || line.contains("BTSCANTEST") ||
+ (line.contains("RSSI", Qt::CaseInsensitive) && (line.contains("Device", Qt::CaseInsensitive) || line.contains("MAC", Qt::CaseInsensitive) || line.count(':') >= 5));
+ if (btRelated && isProductionTestRunning && currentTestStep == TEST_BLUETOOTH) {
qDebug() << "检测到蓝牙测试相关数据,调用checkBluetoothTestResult:" << line.trimmed();
checkBluetoothTestResult(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) + "...";
- }
+ // 检测SE芯片测试结果(cywee is active / cywee is not active)
+ if (line.contains("cywee", Qt::CaseInsensitive)) {
+ checkSeChipTestResult(line);
}
- // 检测Ping测试结果
- if (isProductionTestRunning && currentTestStep == TEST_PPP_PING &&
- (line.contains("PING", Qt::CaseInsensitive) ||
- line.contains("bytes from", Qt::CaseInsensitive) ||
- line.contains("Reply from", Qt::CaseInsensitive) ||
- line.contains("timeout", Qt::CaseInsensitive) ||
- line.contains("unreachable", Qt::CaseInsensitive))) {
- qDebug() << "检测到Ping测试相关数据:" << line.trimmed();
- checkPingTestResult(line);
+ // 检测GPS测试结果(GPSINFO / trace 等)
+ if ((line.contains("GPSINFO", Qt::CaseInsensitive) || line.contains("num_sats", Qt::CaseInsensitive) ||
+ line.contains("trace", Qt::CaseInsensitive)) &&
+ isProductionTestRunning && currentTestStep == TEST_GPS) {
+ checkGpsTestResult(line);
}
+ // 4G/PPP/Ping/CAT1 相关解析已移除
+
// 检测LCD背光状态
if (line.contains("LCD backlight turned on")) {
lcdBacklightOn = true;
if (isTestItemEnabled("lcd")) {
currentTestStep = TEST_LCD;
currentLcdColor = 1; // 从红色开始
- initRetry4GCount = 0;
ui->statusbar->showMessage("开始产测流程...", 2000);
qDebug() << "开始产测流程";
// LCD未启用,跳过到下一个启用的测试
currentTestStep = TEST_LCD; // 先设置为LCD,然后skipToNextEnabledTest会跳过
currentLcdColor = 1; // 初始化LCD颜色
- initRetry4GCount = 0;
ui->statusbar->showMessage("开始产测流程...", 2000);
qDebug() << "开始产测流程,LCD测试未启用,跳过";
motorTestPopupShown = false;
updateTestStatus("motor", STATUS_TESTING);
- ui->statusbar->showMessage("马达测试中 - 开启2秒", 2000);
+ 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);
}
return;
}
- qDebug() << "马达测试时间到,关闭马达";
- ui->statusbar->showMessage("马达测试中 - 关闭", 1000);
-
- // 发送马达关闭指令
- serial->write("AT^VIBRATORTIMER=0\r\n");
- qDebug() << "发送马达关闭指令: AT^VIBRATORTIMER=0";
+ qDebug() << "马达测试时间到,显示确认弹窗";
+ ui->statusbar->showMessage("马达测试 - 请确认", 1000);
- // 马达测试完成,显示确认弹窗
+ // 马达测试完成,显示确认弹窗(不再发送 VIBRATORTIMER=0)
qDebug() << "马达测试完成,显示确认弹窗";
// 如果弹窗还没有显示过,则显示确认弹窗
}
}
-// 4G测试函数
-void MainWindow::perform4GTest()
-{
- // 检查4G测试是否启用
- if (!isTestItemEnabled("ppp")) {
- qDebug() << "4G测试未启用,跳过";
- updateTestStatus("ppp", STATUS_UNTESTED);
- // 4G测试是最后一个测试,如果未启用,直接完成测试
- if (isProductionTestRunning) {
- currentTestStep = TEST_COMPLETED;
- isProductionTestRunning = false;
- QString fileName = saveTestRecord();
- showFinalTestResult();
- }
- return;
- }
-
- if (!isProductionTestRunning) {
- qDebug() << "4G测试跳过 - 产测未运行";
- return;
- }
-
- initRetry4GCount++;
- qDebug() << "4G测试 - 初始化尝试次数:" << initRetry4GCount;
-
- if (initRetry4GCount == 1) {
- ui->recvTextEdit->append("========== 开始4G测试 ==========");
- } else {
- ui->recvTextEdit->append(QString("========== 4G测试重试 (第%1次) ==========").arg(initRetry4GCount));
- }
- updateTestStatus("ppp", STATUS_TESTING);
-
- // 4G电源已在初始化阶段开关,这里直接使用CAT1GETSIGNAL获取信号
- qDebug() << "4G电源已在初始化阶段开关,直接开始4G信号质量检测";
- ui->statusbar->showMessage("4G测试中 - 开始信号强度检测...", 3000);
-
- // 重置标志
- hasReceivedSignalSim = false;
- hasReceivedPppInfo = true; // 标记为已收到,跳过PPP等待
- hasReceivedFirstSignal = false; // 重置,确保能重新启动CAT1测试
- pppCommandCount = 0;
-
- // 初始化CAT1信号测试计数器
- cat1SignalTestCount = 0;
- cat1SignalReceivedCount = 0;
- cat1SignalGoodCount = 0;
- cat1Signal99Count = 0;
- cat1SignalTotalValue = 0;
-
- // 停止可能正在运行的定时器
- if (cat1SignalTimer->isActive()) {
- cat1SignalTimer->stop();
- qDebug() << "停止CAT1信号测试定时器";
- }
- if (signal4GTimer->isActive()) {
- signal4GTimer->stop();
- qDebug() << "停止4G信号检测定时器";
- }
-
- // 直接开始CAT1信号测试,使用CAT1GETSIGNAL指令
- currentTestStep = TEST_PPP_SIGNAL;
- qDebug() << "开始CAT1信号测试,发送AT^CAT1GETSIGNAL指令";
- ui->recvTextEdit->append("========== 开始4G信号质量测试 ==========");
- ui->statusbar->showMessage("开始CAT1信号测试,每2秒检测一次...", 3000);
-
- // 启动CAT1信号测试定时器,每2秒发送一次
- cat1SignalTimer->start(2000);
-
- // 立即发送第一次CAT1信号检测指令
- serial->write("AT^CAT1GETSIGNAL\r\n");
- cat1SignalTestCount++;
- qDebug() << "发送第" << cat1SignalTestCount << "次CAT1信号检测指令: AT^CAT1GETSIGNAL";
- ui->recvTextEdit->append(">>> 发送指令: AT^CAT1GETSIGNAL");
-}
-
-// 检查4G初始化结果
+// 检查4G初始化结果(4G功能已移除)
// 检查工厂模式进入结果
void MainWindow::checkFactoryModeResult(const QString& data)
{
}
}
-void MainWindow::check4GInitResult(const QString& data)
+// 检查LCD测试结果
+void MainWindow::checkLcdTestResult(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初始化通过(已废弃,不再使用PPP相关指令)";
- // PPP相关指令已失效,不再处理
+ // 检测LCD测试回复信息,并且只在LCD测试阶段且未显示过弹窗时弹出
+ // 修改:在最后一个颜色(蓝色)显示时才弹窗,让用户观察完整过程
+ if (data.contains("LCD test") && currentTestStep == TEST_LCD &&
+ !lcdTestPopupShown && isProductionTestRunning && currentLcdColor >= 3) {
- } else if (data.contains("PPP init failed")) {
- qDebug() << "4G初始化失败,重试中...";
- ui->statusbar->showMessage("4G初始化失败,重试中...", 2000);
+ qDebug() << "检测到LCD测试回复:" << data.trimmed();
+ qDebug() << "准备显示LCD测试确认弹窗";
- // 如果重试次数过多,可以设置上限
- 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;
- }
+ // 标记弹窗已显示,避免重复弹出
+ lcdTestPopupShown = true;
+ isWaitingForUserConfirm = true;
- // 先发送停止指令,然后延迟重试
- qDebug() << "4G失败重试前发送停止指令";
- serial->write("AT^VIBRATORTIMER=0\r\n"); // 停止马达
- serial->write("AT^LCDTEST=2\r\n"); // 退出LCD测试
+ // 注意:不暂停LCD定时器,让颜色切换继续进行
+ // LCD颜色切换应该独立于用户确认过程
+ qDebug() << "显示LCD确认弹窗,但颜色切换继续进行";
- QTimer::singleShot(1000, this, [this]() {
- qDebug() << "停止指令已发送,开始4G失败重试";
- perform4GTest();
- });
+ // LCD测试回复已检测到,弹窗处理由performLcdTest中的定时器处理
+
+ // 不需要在这里处理弹窗,由performLcdTest中的定时器处理
}
}
-// 4G测试超时处理
-void MainWindow::on4GTestTimeout()
+// 显示LCD测试确认弹窗
+void MainWindow::showLcdTestConfirmDialog()
{
- 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确认弹窗已显示过,跳过";
+ if (lcdTestPopupShown) {
+ qDebug() << "LCD确认弹窗已显示过,跳过";
return;
}
// 弹出确认对话框让测试人员确认LCD显示是否正常
QMessageBox msgBox(this);
msgBox.setWindowTitle("LCD测试确认");
- msgBox.setText("LCD测试正在进行,请观察LCD是否正常显示红、绿、蓝色切换");
+ msgBox.setText("LCD测试正在进行,请观察LCD是否正常显示红、绿、蓝、白色切换");
msgBox.setInformativeText("观察完成后请选择LCD显示结果:");
msgBox.setIcon(QMessageBox::Question);
if (msgBox.clickedButton() == successButton) {
// 测试人员确认马达震动正常
qDebug() << "测试人员确认:马达震动正常";
+ if (serial && serial->isOpen()) {
+ serial->write("AT^VIBRATORTIMER=0\r\n");
+ qDebug() << "马达测试通过:发送停止马达指令 AT^VIBRATORTIMER=0";
+ ui->recvTextEdit->append(">>> 发送指令: AT^VIBRATORTIMER=0 (测试通过,关闭马达)");
+ }
ui->statusbar->showMessage("马达测试通过 - 震动正常!", 3000);
updateTestStatus("motor", STATUS_SUCCESS);
} else if (msgBox.clickedButton() == failButton) {
// 测试人员确认马达震动异常
qDebug() << "测试人员确认:马达震动异常";
+ if (serial && serial->isOpen()) {
+ serial->write("AT^VIBRATORTIMER=0\r\n");
+ qDebug() << "马达测试失败:发送停止马达指令 AT^VIBRATORTIMER=0";
+ ui->recvTextEdit->append(">>> 发送指令: AT^VIBRATORTIMER=0 (测试失败,关闭马达)");
+ }
ui->statusbar->showMessage("马达测试失败 - 震动异常!", 3000);
updateTestStatus("motor", STATUS_FAILED);
}
}
+// 执行触控测试(AT^TESTJUMP=TP)
+void MainWindow::performTouchTest()
+{
+ if (!isProductionTestRunning || currentTestStep != TEST_TOUCH) {
+ return;
+ }
+ if (!isTestItemEnabled("tp")) {
+ qDebug() << "触控测试未启用,跳过";
+ updateTestStatus("tp", STATUS_UNTESTED);
+ skipToNextEnabledTest();
+ return;
+ }
+
+ if (testTimeoutTimer->isActive()) {
+ testTimeoutTimer->stop();
+ }
+
+ ui->recvTextEdit->append("========== 开始触控测试(TESTJUMP=TP) ==========");
+ updateTestStatus("tp", STATUS_TESTING);
+ ui->statusbar->showMessage("触控测试中:将进入触控测试界面,请等待判断弹窗", 3000);
+
+ // 1) 每次跳转前先回到产测界面
+ if (serial && serial->isOpen()) {
+ ui->recvTextEdit->append(">>> 发送指令: AT^ENTERTESTVIEW (进入产测界面)");
+ serial->write("AT^ENTERTESTVIEW\r\n");
+ qDebug() << "发送指令: AT^ENTERTESTVIEW (触控测试前)";
+ }
+
+ // 2) 延迟后进入对应测试跳转界面
+ QTimer::singleShot(300, this, [this]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_TOUCH) return;
+ if (!serial || !serial->isOpen()) return;
+
+ ui->recvTextEdit->append(">>> 发送指令: AT^TESTJUMP=TP");
+ serial->write("AT^TESTJUMP=TP\r\n");
+ qDebug() << "发送指令: AT^TESTJUMP=TP";
+
+ // 3) 进入界面后弹窗让用户判断
+ QTimer::singleShot(500, this, [this]() {
+ if (isProductionTestRunning && currentTestStep == TEST_TOUCH) {
+ showTouchTestConfirmDialog();
+ }
+ });
+ });
+}
+
+// 触控测试确认弹窗
+void MainWindow::showTouchTestConfirmDialog()
+{
+ if (touchTestPopupShown) {
+ return;
+ }
+
+ touchTestPopupShown = true;
+ isWaitingForUserConfirm = true;
+
+ QMessageBox msgBox(this);
+ msgBox.setWindowTitle("触控测试确认");
+ msgBox.setIcon(QMessageBox::Question);
+ msgBox.setText("触控测试已进入,请测试人员判断触控是否正常。");
+ msgBox.setInformativeText("请选择触控测试结果:");
+ msgBox.resize(420, 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; }");
+ failButton->setStyleSheet("QPushButton { background-color: #f44336; color: white; padding: 12px 20px; border-radius: 4px; font-weight: bold; font-size: 16px; }");
+ retestButton->setStyleSheet("QPushButton { background-color: #FF9800; color: white; padding: 12px 20px; border-radius: 4px; font-weight: bold; font-size: 16px; }");
+
+ msgBox.exec();
+
+ isWaitingForUserConfirm = false;
+
+ if (msgBox.clickedButton() == successButton) {
+ ui->statusbar->showMessage("触控测试通过", 2000);
+ updateTestStatus("tp", STATUS_SUCCESS);
+ } else if (msgBox.clickedButton() == failButton) {
+ ui->statusbar->showMessage("触控测试失败", 2000);
+ updateTestStatus("tp", STATUS_FAILED);
+ } else if (msgBox.clickedButton() == retestButton) {
+ // 重新测试
+ touchTestPopupShown = false;
+ isWaitingForUserConfirm = false;
+ QTimer::singleShot(300, this, [this]() {
+ if (isProductionTestRunning && currentTestStep == TEST_TOUCH) {
+ performTouchTest();
+ }
+ });
+ return;
+ }
+
+ touchTestPopupShown = false;
+ if (isProductionTestRunning && currentTestStep == TEST_TOUCH) {
+ skipToNextEnabledTest();
+ }
+}
+
+// 执行亮度测试(AT^BRIGHTRAMP)
+void MainWindow::performBrightTest()
+{
+ if (!isProductionTestRunning || currentTestStep != TEST_BRIGHT) {
+ return;
+ }
+ if (!isTestItemEnabled("bright")) {
+ qDebug() << "亮度测试未启用,跳过";
+ updateTestStatus("bright", STATUS_UNTESTED);
+ skipToNextEnabledTest();
+ return;
+ }
+
+ if (testTimeoutTimer->isActive()) {
+ testTimeoutTimer->stop();
+ }
+
+ ui->recvTextEdit->append("========== 开始亮度测试(AT^BRIGHTRAMP) ==========");
+ updateTestStatus("bright", STATUS_TESTING);
+ ui->statusbar->showMessage("亮度测试中:自动调节亮度,请观察后确认", 3000);
+
+ if (!serial || !serial->isOpen()) {
+ return;
+ }
+ ui->recvTextEdit->append(">>> 发送指令: AT^BRIGHTRAMP");
+ serial->write("AT^BRIGHTRAMP\r\n");
+ qDebug() << "发送指令: AT^BRIGHTRAMP";
+
+ QTimer::singleShot(500, this, [this]() {
+ if (isProductionTestRunning && currentTestStep == TEST_BRIGHT) {
+ showBrightTestConfirmDialog();
+ }
+ });
+}
+
+void MainWindow::showBrightTestConfirmDialog()
+{
+ if (brightTestPopupShown) {
+ return;
+ }
+
+ brightTestPopupShown = true;
+ isWaitingForUserConfirm = true;
+
+ QMessageBox msgBox(this);
+ msgBox.setWindowTitle("亮度测试确认");
+ msgBox.setIcon(QMessageBox::Question);
+ msgBox.setText("亮度测试已进入,请测试人员判断亮度是否正常。");
+ msgBox.setInformativeText("请选择亮度测试结果:");
+ msgBox.resize(420, 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; }");
+ failButton->setStyleSheet("QPushButton { background-color: #f44336; color: white; padding: 12px 20px; border-radius: 4px; font-weight: bold; font-size: 16px; }");
+ retestButton->setStyleSheet("QPushButton { background-color: #FF9800; color: white; padding: 12px 20px; border-radius: 4px; font-weight: bold; font-size: 16px; }");
+
+ msgBox.exec();
+
+ isWaitingForUserConfirm = false;
+
+ if (msgBox.clickedButton() == successButton) {
+ ui->statusbar->showMessage("亮度测试通过", 2000);
+ updateTestStatus("bright", STATUS_SUCCESS);
+ } else if (msgBox.clickedButton() == failButton) {
+ ui->statusbar->showMessage("亮度测试失败", 2000);
+ updateTestStatus("bright", STATUS_FAILED);
+ } else if (msgBox.clickedButton() == retestButton) {
+ brightTestPopupShown = false;
+ isWaitingForUserConfirm = false;
+ QTimer::singleShot(300, this, [this]() {
+ if (isProductionTestRunning && currentTestStep == TEST_BRIGHT) {
+ performBrightTest();
+ }
+ });
+ return;
+ }
+
+ brightTestPopupShown = false;
+ if (isProductionTestRunning && currentTestStep == TEST_BRIGHT) {
+ skipToNextEnabledTest();
+ }
+}
+
+// 执行功耗测试(AT^TESTJUMP=DEEPSLEEP,进入后由人工确认)
+void MainWindow::performDeepsleepTest()
+{
+ if (!isProductionTestRunning || currentTestStep != TEST_DEEPSLEEP) {
+ return;
+ }
+ if (!isTestItemEnabled("deepsleep")) {
+ qDebug() << "功耗测试未启用,跳过";
+ updateTestStatus("deepsleep", STATUS_UNTESTED);
+ skipToNextEnabledTest();
+ return;
+ }
+
+ if (testTimeoutTimer->isActive()) {
+ testTimeoutTimer->stop();
+ }
+
+ ui->recvTextEdit->append("========== 开始功耗测试(TESTJUMP=DEEPSLEEP) ==========");
+ updateTestStatus("deepsleep", STATUS_TESTING);
+ ui->statusbar->showMessage("功耗测试:将进入深度睡眠测试界面,请等待确认弹窗", 3000);
+
+ if (serial && serial->isOpen()) {
+ ui->recvTextEdit->append(">>> 发送指令: AT^ENTERTESTVIEW (进入产测界面)");
+ serial->write("AT^ENTERTESTVIEW\r\n");
+ qDebug() << "发送指令: AT^ENTERTESTVIEW (功耗测试前)";
+ }
+
+ QTimer::singleShot(300, this, [this]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_DEEPSLEEP) {
+ return;
+ }
+ if (!serial || !serial->isOpen()) {
+ return;
+ }
+ ui->recvTextEdit->append(">>> 发送指令: AT^TESTJUMP=DEEPSLEEP");
+ serial->write("AT^TESTJUMP=DEEPSLEEP\r\n");
+ qDebug() << "发送指令: AT^TESTJUMP=DEEPSLEEP";
+
+ // 仅进入界面不会真正进深睡,需再发 FACTORYDEEPSLEEPENTER
+ QTimer::singleShot(400, this, [this]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_DEEPSLEEP) {
+ return;
+ }
+ if (!serial || !serial->isOpen()) {
+ return;
+ }
+ ui->recvTextEdit->append(">>> 发送指令: AT^FACTORYDEEPSLEEPENTER");
+ serial->write("AT^FACTORYDEEPSLEEPENTER\r\n");
+ qDebug() << "发送指令: AT^FACTORYDEEPSLEEPENTER";
+ appendToLogFile(">>> 发送指令: AT^FACTORYDEEPSLEEPENTER\n");
+
+ QTimer::singleShot(500, this, [this]() {
+ if (isProductionTestRunning && currentTestStep == TEST_DEEPSLEEP) {
+ showDeepsleepTestConfirmDialog();
+ }
+ });
+ });
+ });
+}
+
+void MainWindow::showDeepsleepTestConfirmDialog()
+{
+ if (deepsleepTestPopupShown) {
+ return;
+ }
+
+ deepsleepTestPopupShown = true;
+ isWaitingForUserConfirm = true;
+
+ QMessageBox msgBox(this);
+ msgBox.setWindowTitle("功耗测试确认");
+ msgBox.setIcon(QMessageBox::Question);
+ msgBox.setText("设备已进入深度睡眠(功耗)测试界面,请测试人员根据功耗/唤醒表现判断是否正常。");
+ msgBox.setInformativeText("请选择功耗测试结果:");
+ msgBox.resize(420, 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; }");
+ failButton->setStyleSheet("QPushButton { background-color: #f44336; color: white; padding: 12px 20px; border-radius: 4px; font-weight: bold; font-size: 16px; }");
+ retestButton->setStyleSheet("QPushButton { background-color: #FF9800; color: white; padding: 12px 20px; border-radius: 4px; font-weight: bold; font-size: 16px; }");
+
+ msgBox.exec();
+
+ isWaitingForUserConfirm = false;
+
+ if (msgBox.clickedButton() == successButton) {
+ ui->statusbar->showMessage("功耗测试通过", 2000);
+ updateTestStatus("deepsleep", STATUS_SUCCESS);
+ } else if (msgBox.clickedButton() == failButton) {
+ ui->statusbar->showMessage("功耗测试失败", 2000);
+ updateTestStatus("deepsleep", STATUS_FAILED);
+ } else if (msgBox.clickedButton() == retestButton) {
+ deepsleepTestPopupShown = false;
+ isWaitingForUserConfirm = false;
+ QTimer::singleShot(300, this, [this]() {
+ if (isProductionTestRunning && currentTestStep == TEST_DEEPSLEEP) {
+ performDeepsleepTest();
+ }
+ });
+ return;
+ }
+
+ deepsleepTestPopupShown = false;
+ if (isProductionTestRunning && currentTestStep == TEST_DEEPSLEEP) {
+ skipToNextEnabledTest();
+ }
+}
+
// 执行按键测试
void MainWindow::performKeyTest()
{
}
qDebug() << "开始按键测试";
- ui->recvTextEdit->append("========== 开始按键测试 ==========");
+ ui->recvTextEdit->append("========== 开始按键测试(TESTJUMP=KEY) ==========");
updateTestStatus("key", STATUS_TESTING);
- ui->statusbar->showMessage("按键测试中,请按下设备上的按键", 10000);
+ ui->statusbar->showMessage("按键测试中,请按键0并执行旋转动作", 10000);
- // 重置按键测试状态
+ // 重置按键测试状态(仅按键0 + 旋转)
keyTestStarted = true;
for (int i = 0; i < 4; i++) {
keyTestStatus[i] = 0;
}
+ keyRotateDetected = false;
+
+ // 先跳转产测主界面,再跳KEY测试界面
+ if (serial && serial->isOpen()) {
+ ui->recvTextEdit->append(">>> 发送指令: AT^ENTERTESTVIEW (进入产测界面)");
+ serial->write("AT^ENTERTESTVIEW\r\n");
+ }
+ QTimer::singleShot(300, this, [this]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_KEY) {
+ return;
+ }
+ if (serial && serial->isOpen()) {
+ ui->recvTextEdit->append(">>> 发送指令: AT^TESTJUMP=KEY");
+ serial->write("AT^TESTJUMP=KEY\r\n");
+ }
+ });
// 创建按键测试弹窗
keyTestDialog = new QDialog(this);
keyTestDialog->setWindowTitle("按键测试");
- keyTestDialog->setFixedSize(450, 280); // 调大尺寸
+ keyTestDialog->setFixedSize(460, 250);
keyTestDialog->setModal(true);
// 设置布局
QVBoxLayout *layout = new QVBoxLayout(keyTestDialog);
- QLabel *instructionLabel = new QLabel("请æ\8c\89ä¸\8b设å¤\87ä¸\8aç\9a\84æ\8c\89é\94®ï¼\8cæ\8c\89é\92®ä¼\9aå\8f\98è\89²è¡¨ç¤ºæ£\80æµ\8bå\88°");
+ QLabel *instructionLabel = new QLabel("请æ£\80æµ\8bæ\8c\89é\94®0ä¸\8eæ\97\8b转äº\8bä»¶ï¼\9bæ£\80æµ\8bå\88°å\90\8eæ\8c\89é\92®ä¼\9aå\8f\98绿");
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);
+
+ // 仅保留按键0和旋转两个检测项
+ QHBoxLayout *indicators = new QHBoxLayout();
+ keyButtons[0] = new QPushButton("按键 0");
+ keyButtons[0]->setFixedSize(120, 44);
+ keyButtons[0]->setStyleSheet("QPushButton { background-color: #f0f0f0; border: 2px solid #888888; border-radius: 5px; font-weight: bold; }");
+
+ keyButtons[1] = new QPushButton("旋转");
+ keyButtons[1]->setFixedSize(120, 44);
+ keyButtons[1]->setStyleSheet("QPushButton { background-color: #f0f0f0; border: 2px solid #888888; border-radius: 5px; font-weight: bold; }");
+ keyButtons[2] = nullptr;
+ keyButtons[3] = nullptr;
+
+ indicators->addWidget(keyButtons[0]);
+ indicators->addWidget(keyButtons[1]);
+ layout->addLayout(indicators);
// 添加测试结果按钮
QHBoxLayout *buttonLayout = new QHBoxLayout();
QRegExp keyPattern("fac:id\\s*:\\s*(\\d+)");
if (keyPattern.indexIn(data) != -1) {
int keyId = keyPattern.cap(1).toInt();
-
- if (keyId >= 0 && keyId <= 3) {
+ if (keyId == 0) {
qDebug() << "检测到按键按下: ID =" << keyId;
-
- // 标记该按键已测试
- keyTestStatus[keyId] = 1;
-
- // 更新按钮颜色
- if (keyButtons[keyId]) {
- keyButtons[keyId]->setStyleSheet(
+ keyTestStatus[0] = 1;
+ if (keyButtons[0]) {
+ keyButtons[0]->setStyleSheet(
"QPushButton { "
- "background-color: #4CAF50; " // 绿色表示已测试
+ "background-color: #4CAF50; "
"color: white; "
"border: 2px solid #45a049; "
"border-radius: 5px; "
"font-weight: bold; "
"}"
);
- keyButtons[keyId]->setText(QString("按键 %1 ✓").arg(keyId));
+ keyButtons[0]->setText("按键 0 ✓");
}
-
- 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;
- skipToNextEnabledTest();
- }
- });
- } else {
- qDebug() << "按键 " << keyId << " 检测完成,等待其他按键或用户选择";
+ ui->statusbar->showMessage("检测到按键 0", 1000);
+ }
+ }
+
+ // 旋转事件:testPresenter::OnRotate
+ if (data.contains("testPresenter::OnRotate")) {
+ keyRotateDetected = true;
+ if (keyButtons[1]) {
+ keyButtons[1]->setStyleSheet(
+ "QPushButton { "
+ "background-color: #4CAF50; "
+ "color: white; "
+ "border: 2px solid #45a049; "
+ "border-radius: 5px; "
+ "font-weight: bold; "
+ "}"
+ );
+ keyButtons[1]->setText("旋转 ✓");
+ }
+ ui->statusbar->showMessage("检测到旋转事件 OnRotate", 1000);
+ }
+
+ // 条件满足自动通过:按键0 + 旋转
+ if (keyTestStatus[0] == 1 && keyRotateDetected) {
+ QTimer::singleShot(500, [this]() {
+ if (keyTestDialog && isProductionTestRunning && currentTestStep == TEST_KEY) {
+ keyTestDialog->accept();
+ updateTestStatus("key", STATUS_SUCCESS);
+ keyTestStarted = false;
+ skipToNextEnabledTest();
}
- }
+ });
}
}
serial->write("AT^PMADDVOTE\r\n");
qDebug() << "发送AT^PMADDVOTE指令(第2次): AT^PMADDVOTE";
- // å¦\82æ\9e\9c4Gæµ\8bè¯\95å·²å\90¯ç\94¨ï¼\8cå\85\88å\85³é\97å\92\8cå¼\80å\90¯4Gç\94µæº\90
- if (isTestItemEnabled("ppp")) {
- qDebug() << "4G测试已启用,在初始化阶段先关闭和开启4G电源";
- // 先发送AT^CAT1POWER=0关闭CAT1电源
- serial->write("AT^CAT1POWER=0\r\n");
- qDebug() << "发送CAT1电源关闭指令: AT^CAT1POWER=0 (初始化阶段)";
-
- // 延迟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 (初始化阶段)";
-
- // 延迟1秒后发送AT^CAT1LOGLEVEL=4指令
+ // å¼\80æ\9cºå\88\9då§\8bå\8c\96å®\8cæ\88\90å\90\8eï¼\8cè¿\9bå\85¥äº§æµ\8bç\95\8cé\9d¢ï¼\88满足AT^ENTERTESTVIEWè¦\81æ±\82ï¼\89
+ if (serial->isOpen()) {
+ ui->recvTextEdit->append(">>> 发送指令: AT^ENTERTESTVIEW (进入产测界面)");
+ serial->write("AT^ENTERTESTVIEW\r\n");
+ qDebug() << "发送AT^ENTERTESTVIEW (进入产测界面)";
+ }
+
+ // 初始化完成后,切换到LCD测试阶段(如果启用)
+ QTimer::singleShot(1000, this, [this]() {
+ if (isProductionTestRunning) {
+ if (isTestItemEnabled("lcd")) {
+ qDebug() << "AT^PMADDVOTE指令发送完成,开始LCD测试";
+ ui->statusbar->showMessage("初始化完成,开始LCD测试", 2000);
+ currentTestStep = TEST_LCD;
QTimer::singleShot(1000, this, [this]() {
- if (isProductionTestRunning && serial->isOpen()) {
- serial->write("AT^CAT1LOGLEVEL=4\r\n");
- qDebug() << "发送CAT1日志级别设置指令: AT^CAT1LOGLEVEL=4 (初始化阶段)";
-
- // 延迟1秒后切换到LCD测试阶段(如果启用)
- QTimer::singleShot(1000, this, [this]() {
- if (isProductionTestRunning) {
- // 检查LCD测试是否启用
- if (isTestItemEnabled("lcd")) {
- qDebug() << "4G电源初始化完成,开始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();
- }
- });
- } else {
- qDebug() << "4G电源初始化完成,LCD测试未启用,跳过";
- ui->statusbar->showMessage("初始化完成,LCD测试未启用,跳过", 2000);
-
- // LCD未启用,跳过到下一个启用的测试
- currentTestStep = TEST_LCD;
- skipToNextEnabledTest();
- }
- }
- });
+ if (isProductionTestRunning && currentTestStep == TEST_LCD) {
+ qDebug() << "开始LCD测试流程";
+ performLcdTest();
}
});
+ } else {
+ qDebug() << "AT^PMADDVOTE指令发送完成,LCD测试未启用,跳过";
+ ui->statusbar->showMessage("初始化完成,LCD测试未启用,跳过", 2000);
+ currentTestStep = TEST_LCD;
+ skipToNextEnabledTest();
}
- });
- } else {
- // 4G测试未启用,直接切换到LCD测试阶段
- QTimer::singleShot(1000, this, [this]() {
- if (isProductionTestRunning) {
- // 检查LCD测试是否启用
- if (isTestItemEnabled("lcd")) {
- 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();
- }
- });
- } else {
- qDebug() << "AT^PMADDVOTE指令发送完成,LCD测试未启用,跳过";
- ui->statusbar->showMessage("初始化完成,LCD测试未启用,跳过", 2000);
-
- // LCD未启用,跳过到下一个启用的测试
- currentTestStep = TEST_LCD;
- skipToNextEnabledTest();
- }
- }
- });
- }
+ }
+ });
}
});
}
{
QString iconText, statusText, iconColor, textColor;
+ // 用于时间记录的统一名称(charge/ntc不计入,由battery代表)
+ QString timeKey = (testName == "audio") ? "mic" : ((testName == "charge" || testName == "ntc") ? QString() : testName);
+
switch (status) {
case STATUS_UNTESTED:
iconText = "○";
statusText = "测试中";
iconColor = "#FFA500"; // 橙色
textColor = "#FFA500";
+ if (!timeKey.isEmpty()) {
+ testStartTimeMap[timeKey] = QDateTime::currentDateTime();
+ testDurationSecMap.remove(timeKey);
+ }
break;
case STATUS_SUCCESS:
iconText = "✓";
statusText = "通过";
iconColor = "#4CAF50"; // 绿色
textColor = "#4CAF50";
+ if (!timeKey.isEmpty() && testStartTimeMap.contains(timeKey)) {
+ qint64 secs = testStartTimeMap[timeKey].secsTo(QDateTime::currentDateTime());
+ testDurationSecMap[timeKey] = secs;
+ testStartTimeMap.remove(timeKey);
+ int m = secs / 60, s = secs % 60;
+ statusText = QString("通过 (%1:%2)").arg(m).arg(s, 2, 10, QChar('0'));
+ }
break;
case STATUS_FAILED:
iconText = "✗";
statusText = "失败";
iconColor = "#F44336"; // 红色
textColor = "#F44336";
+ if (!timeKey.isEmpty() && testStartTimeMap.contains(timeKey)) {
+ qint64 secs = testStartTimeMap[timeKey].secsTo(QDateTime::currentDateTime());
+ testDurationSecMap[timeKey] = secs;
+ testStartTimeMap.remove(timeKey);
+ int m = secs / 60, s = secs % 60;
+ statusText = QString("失败 (%1:%2)").arg(m).arg(s, 2, 10, QChar('0'));
+ }
break;
}
- QString iconStyle = QString("color: %1; font-size: 18px; font-weight: bold;").arg(iconColor);
- QString textStyle = QString("color: %1;").arg(textColor);
-
+ QString rowBg;
+ if (status == STATUS_SUCCESS) {
+ rowBg = "#dff5df";
+ } else if (status == STATUS_FAILED) {
+ rowBg = "#ffe0e0";
+ }
+
+ // 从第一个状态标签获取基准字体,确保状态切换时字体不变
+ QFont baseFont = ui->lcdStatusText->font();
+ int ptSize = baseFont.pointSize() > 0 ? baseFont.pointSize() : 10;
+ QString fontCss = QString("font-family: \"%1\"; font-size: %2pt; font-weight: %3;")
+ .arg(baseFont.family()).arg(ptSize).arg(baseFont.bold() ? 700 : 400);
+ QString iconFontCss = "font-size: 18px; font-weight: bold;";
+
+ const QString iconStyle = rowBg.isEmpty()
+ ? QString("color: %1; %2").arg(iconColor, iconFontCss)
+ : QString("color: %1; %2 background-color: %3;").arg(iconColor, iconFontCss, rowBg);
+ const QString textStyle = rowBg.isEmpty()
+ ? QString("color: %1; %2").arg(textColor, fontCss)
+ : QString("color: %1; %2 background-color: %3;").arg(textColor, fontCss, rowBg);
+ const QString labelStyle = rowBg.isEmpty() ? "" : QString("background-color: %1; %2").arg(rowBg, fontCss);
+
+ auto applyRow = [&](QLabel* nameLabel, QLabel* iconLabel, QLabel* statusLabel) {
+ if (nameLabel) nameLabel->setStyleSheet(labelStyle);
+ iconLabel->setText(iconText);
+ iconLabel->setStyleSheet(iconStyle);
+ statusLabel->setText(statusText);
+ statusLabel->setStyleSheet(textStyle);
+ };
+
if (testName == "lcd") {
- ui->lcdStatusIcon->setText(iconText);
- ui->lcdStatusIcon->setStyleSheet(iconStyle);
- ui->lcdStatusText->setText(statusText);
- ui->lcdStatusText->setStyleSheet(textStyle);
+ applyRow(ui->lcdTestLabel, ui->lcdStatusIcon, ui->lcdStatusText);
+ } else if (testName == "tp") {
+ applyRow(ui->tpTestLabel, ui->tpStatusIcon, ui->tpStatusText);
+ } else if (testName == "bright") {
+ applyRow(ui->brightTestLabel, ui->brightStatusIcon, ui->brightStatusText);
} else if (testName == "motor") {
- ui->motorStatusIcon->setText(iconText);
- ui->motorStatusIcon->setStyleSheet(iconStyle);
- ui->motorStatusText->setText(statusText);
- ui->motorStatusText->setStyleSheet(textStyle);
+ applyRow(ui->motorTestLabel, ui->motorStatusIcon, ui->motorStatusText);
} 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);
+ applyRow(ui->keyTestLabel, ui->keyStatusIcon, ui->keyStatusText);
+ } else if (testName == "deepsleep") {
+ applyRow(ui->deepsleepTestLabel, ui->deepsleepStatusIcon, ui->deepsleepStatusText);
+ } else if (testName == "mic" || testName == "audio") {
+ applyRow(ui->audioTestLabel, ui->audioStatusIcon, ui->audioStatusText);
} else if (testName == "battery") {
- ui->batteryStatusIcon->setText(iconText);
- ui->batteryStatusIcon->setStyleSheet(iconStyle);
- ui->batteryStatusText->setText(statusText);
- ui->batteryStatusText->setStyleSheet(textStyle);
+ applyRow(ui->batteryTestLabel, ui->batteryStatusIcon, ui->batteryStatusText);
} else if (testName == "gsensor") {
- ui->gsensorStatusIcon->setText(iconText);
- ui->gsensorStatusIcon->setStyleSheet(iconStyle);
- ui->gsensorStatusText->setText(statusText);
- ui->gsensorStatusText->setStyleSheet(textStyle);
+ applyRow(ui->gsensorTestLabel, ui->gsensorStatusIcon, ui->gsensorStatusText);
} else if (testName == "bluetooth") {
- ui->bluetoothStatusIcon->setText(iconText);
- ui->bluetoothStatusIcon->setStyleSheet(iconStyle);
- ui->bluetoothStatusText->setText(statusText);
- ui->bluetoothStatusText->setStyleSheet(textStyle);
- } else if (testName == "ppp") {
- ui->pppStatusIcon->setText(iconText);
- ui->pppStatusIcon->setStyleSheet(iconStyle);
- ui->pppStatusText->setText(statusText);
- ui->pppStatusText->setStyleSheet(textStyle);
+ applyRow(ui->bluetoothTestLabel, ui->bluetoothStatusIcon, ui->bluetoothStatusText);
+ } else if (testName == "sechip") {
+ applyRow(ui->sechipTestLabel, ui->sechipStatusIcon, ui->sechipStatusText);
+ } else if (testName == "gps") {
+ applyRow(ui->gpsTestLabel, ui->gpsStatusIcon, ui->gpsStatusText);
+ } else if (testName == "leaklight") {
+ applyRow(ui->leaklightTestLabel, ui->leaklightStatusIcon, ui->leaklightStatusText);
} else if (testName == "charge" || testName == "ntc") {
// charge和ntc是电池测试的子项,它们的状态用于判定,但不单独显示在UI中
// 它们的状态会影响battery的整体状态,但这里不更新UI
// 检查各项测试状态(只检查成功状态,并根据checkbox决定是否参与判定)
bool allEnabledTestsPassed = true;
+ auto isPassed = [](const QString& t) { return t.startsWith("通过"); };
// 检查启用的测试项
if (isTestItemEnabled("lcd")) {
- bool lcdSuccess = ui->lcdStatusText->text() == "通过";
- if (!lcdSuccess) allEnabledTestsPassed = false;
+ if (!isPassed(ui->lcdStatusText->text())) allEnabledTestsPassed = false;
+ }
+ if (isTestItemEnabled("tp")) {
+ if (!isPassed(ui->tpStatusText->text())) allEnabledTestsPassed = false;
+ }
+ if (isTestItemEnabled("bright")) {
+ if (!isPassed(ui->brightStatusText->text())) allEnabledTestsPassed = false;
}
if (isTestItemEnabled("motor")) {
- bool motorSuccess = ui->motorStatusText->text() == "通过";
- if (!motorSuccess) allEnabledTestsPassed = false;
+ if (!isPassed(ui->motorStatusText->text())) allEnabledTestsPassed = false;
}
if (isTestItemEnabled("key")) {
- bool keySuccess = ui->keyStatusText->text() == "通过";
- if (!keySuccess) allEnabledTestsPassed = false;
+ if (!isPassed(ui->keyStatusText->text())) allEnabledTestsPassed = false;
}
- if (isTestItemEnabled("audio")) {
- bool audioSuccess = ui->audioStatusText->text() == "通过";
- if (!audioSuccess) allEnabledTestsPassed = false;
+ if (isTestItemEnabled("deepsleep")) {
+ if (!isPassed(ui->deepsleepStatusText->text())) allEnabledTestsPassed = false;
}
- // 电池测试:检查充电和NTC(如果启用)
- // 注意:charge和ntc的状态通过updateTestStatus("charge", ...)和updateTestStatus("ntc", ...)更新
- // 但由于UI中可能没有独立的charge和ntc状态显示,这里使用battery状态作为综合判定
- // 如果charge或ntc任一启用,都需要检查battery状态
- if (isTestItemEnabled("charge") || isTestItemEnabled("ntc")) {
- bool batterySuccess = ui->batteryStatusText->text() == "通过";
- if (!batterySuccess) allEnabledTestsPassed = false;
+ if (isTestItemEnabled("mic")) {
+ if (!isPassed(ui->audioStatusText->text())) allEnabledTestsPassed = false;
+ }
+ if (isTestItemEnabled("battery")) {
+ if (!isPassed(ui->batteryStatusText->text())) allEnabledTestsPassed = false;
}
if (isTestItemEnabled("gsensor")) {
- bool gsensorSuccess = ui->gsensorStatusText->text() == "通过";
- if (!gsensorSuccess) allEnabledTestsPassed = false;
+ if (!isPassed(ui->gsensorStatusText->text())) allEnabledTestsPassed = false;
}
if (isTestItemEnabled("bluetooth")) {
- bool bluetoothSuccess = ui->bluetoothStatusText->text() == "通过";
- if (!bluetoothSuccess) allEnabledTestsPassed = false;
+ if (!isPassed(ui->bluetoothStatusText->text())) allEnabledTestsPassed = false;
}
- if (isTestItemEnabled("ppp")) {
- bool pppSuccess = ui->pppStatusText->text() == "通过";
- if (!pppSuccess) allEnabledTestsPassed = false;
+ if (isTestItemEnabled("leaklight")) {
+ if (!isPassed(ui->leaklightStatusText->text())) allEnabledTestsPassed = false;
+ }
+ if (isTestItemEnabled("sechip")) {
+ if (!isPassed(ui->sechipStatusText->text())) allEnabledTestsPassed = false;
+ }
+ if (isTestItemEnabled("gps")) {
+ if (!isPassed(ui->gpsStatusText->text())) allEnabledTestsPassed = false;
+ }
+ // 计算各测试项总耗时
+ qint64 totalSecs = 0;
+ for (auto it = testDurationSecMap.constBegin(); it != testDurationSecMap.constEnd(); ++it) {
+ totalSecs += it.value();
+ }
+ QString totalTimeStr;
+ if (totalSecs > 0) {
+ int tm = totalSecs / 60, ts = totalSecs % 60;
+ totalTimeStr = QString("%1分%2秒").arg(tm).arg(ts);
}
-
QString overallIcon, overallText, overallColor;
if (allEnabledTestsPassed) {
- // 所有启用的测试都通过
overallIcon = "✓";
- overallText = "通过";
+ overallText = totalTimeStr.isEmpty() ? "通过" : QString("通过 · 总耗时 %1").arg(totalTimeStr);
overallColor = "#4CAF50";
} else {
- // 任何其他情况(失败、测试中、等待开始等)都显示为未通过
overallIcon = "✗";
- overallText = "未通过";
+ overallText = totalTimeStr.isEmpty() ? "未通过" : QString("未通过 · 总耗时 %1").arg(totalTimeStr);
overallColor = "#F44336";
}
QString overallStyle = QString("color: %1; font-size: 18px; font-weight: bold;").arg(overallColor);
QString textStyle = QString("color: %1;").arg(overallColor);
+ // 整体状态同样保持字体不变
+ int overallPt = ui->overallStatusText->font().pointSize();
+ if (overallPt <= 0) overallPt = 10;
+ QString overallFontCss = QString("font-family: \"%1\"; font-size: %2pt;")
+ .arg(ui->overallStatusText->font().family()).arg(overallPt);
ui->overallStatusIcon->setText(overallIcon);
ui->overallStatusIcon->setStyleSheet(overallStyle);
ui->overallStatusText->setText(overallText);
- ui->overallStatusText->setStyleSheet(textStyle);
+ ui->overallStatusText->setStyleSheet(textStyle + overallFontCss);
}
// 保存测试记录到CSV文件(可用Excel打开)
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 tpResult = ui->tpStatusText->text();
+ QString brightResult = ui->brightStatusText->text();
QString motorResult = ui->motorStatusText->text();
QString keyResult = ui->keyStatusText->text();
+ QString deepsleepResult = ui->deepsleepStatusText->text();
QString audioResult = ui->audioStatusText->text();
QString batteryResult = ui->batteryStatusText->text();
QString gsensorResult = ui->gsensorStatusText->text();
+ QString leaklightResult = ui->leaklightStatusText->text();
QString bluetoothResult = ui->bluetoothStatusText->text();
- QString pppResult = ui->pppStatusText->text();
+ QString sechipResult = ui->sechipStatusText->text();
+ QString gpsResult = ui->gpsStatusText->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,%16\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(bluetoothResult)
- .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版本,PYVER版本,LCD测试,马达测试,按键测试,录音测试,电池测试,G-sensor测试,蓝牙测试,4G测试,整体结果\n";
- finalContent += newDataLine;
- }
- }
-
- // 写入最终内容到文件
+
+ const QString header =
+ "开始时间,结束时间,测试耗时,软件版本,LCD测试,触控测试,亮度测试,马达测试,按键测试,功耗测试,录音测试,电池测试,G-sensor测试,漏光测试,蓝牙测试,SE芯片测试,GPS测试,整体结果\n";
+
+ QString newDataLine = QString("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15,%16,%17,%18\n")
+ .arg(startTimeStr)
+ .arg(endTimeStr)
+ .arg(durationStr)
+ .arg(ver.isEmpty() ? "未获取" : ver)
+ .arg(lcdResult)
+ .arg(tpResult)
+ .arg(brightResult)
+ .arg(motorResult)
+ .arg(keyResult)
+ .arg(deepsleepResult)
+ .arg(audioResult)
+ .arg(batteryResult)
+ .arg(gsensorResult)
+ .arg(leaklightResult)
+ .arg(bluetoothResult)
+ .arg(sechipResult)
+ .arg(gpsResult)
+ .arg(overallResult);
+
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(); // 返回空字符串表示保存失败
+ if (!csvFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
+ 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() << "字节";
-
+
+ if (isNewFile) {
+ csvFile.write(header.toLocal8Bit());
+ }
+ csvFile.write(newDataLine.toLocal8Bit());
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;
-
- // 显示保存成功消息
+
+ qDebug() << "测试记录已追加保存到:" << csvFilePath;
+
ui->statusbar->showMessage(QString("测试记录已保存: %1").arg(csvFileName), 3000);
// 关闭测试日志文件(测试完成)
}
-// 检查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值显示到界面
- appendToLogFile(QString("Signal值: %1\n").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)
{
}
}
-// 发送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()
{
// 如果正在测试,则停止测试
lcdTestTimer->stop();
motorTestTimer->stop();
- test4GTimer->stop();
- signal4GTimer->stop();
testTimeoutTimer->stop();
- cat1SignalTimer->stop();
+ gSensorIntervalTimer->stop();
bluetoothTestTimer->stop();
- pingTestTimer->stop();
isProductionTestRunning = false;
currentTestStep = TEST_IDLE;
// 开始产测流程
isProductionTestRunning = true;
testStartTime = QDateTime::currentDateTime(); // 记录测试开始时间
+ testStartTimeMap.clear();
+ testDurationSecMap.clear();
currentTestStep = TEST_RESET;
currentLcdColor = 1; // 从红色开始
- initRetry4GCount = 0;
- signalTest4GCount = 0;
- signalReceived4GCount = 0;
- signalGood4GCount = 0;
- pppCommandCount = 0;
- hasReceivedSignalSim = false;
- hasReceivedPppInfo = false;
-
- // 在开始新测试前,检查是否需要保存当前UI日志
- QString currentLogContent = ui->recvTextEdit->toPlainText();
- QString currentImei = ui->IMEIlineEdit->text().trimmed();
- QString currentIccid = ui->ICCIDlineEdit->text().trimmed();
-
- // 如果UI有日志内容且IMEI/ICCID已知,则保存日志
- if (!currentLogContent.trimmed().isEmpty() &&
- !currentImei.isEmpty() && currentImei != "未获取" &&
- !currentIccid.isEmpty() && currentIccid != "未获取") {
- qDebug() << "开始新测试前,保存当前UI日志";
- saveRecvTextEditToLog();
- } else {
- qDebug() << "UI日志为空或IMEI/ICCID未知,放弃保存,直接清空UI";
- }
+
+ // 在开始新测试前,尽量保存当前UI日志(如果有内容)
+ saveRecvTextEditToLog();
// 创建测试日志文件
createTestLogFile();
// 清空设备信息
ui->VerlineEdit->clear(); // 清空版本信息
- ui->IMEIlineEdit->clear(); // 清空IMEI
- ui->ICCIDlineEdit->clear(); // 清空ICCID
- ui->ModemVerlineEdit->clear(); // 清空调制解调器版本
- ui->PYVerlineEdit->clear(); // 清空python版本
// 重置弹窗状态
lcdTestPopupShown = false;
motorTestPopupShown = false;
+ touchTestPopupShown = false;
+ brightTestPopupShown = false;
+ deepsleepTestPopupShown = false;
isWaitingForUserConfirm = false;
keyTestStarted = false;
- audioTestPopupShown = false;
- audioPlaybackPopupShown = false;
// 重置状态指示器
updateTestStatus("lcd", STATUS_UNTESTED);
+ updateTestStatus("tp", STATUS_UNTESTED);
+ updateTestStatus("bright", STATUS_UNTESTED);
updateTestStatus("motor", STATUS_UNTESTED);
updateTestStatus("key", STATUS_UNTESTED);
- updateTestStatus("audio", STATUS_UNTESTED);
+ updateTestStatus("deepsleep", STATUS_UNTESTED);
+ updateTestStatus("mic", STATUS_UNTESTED);
updateTestStatus("battery", STATUS_UNTESTED);
updateTestStatus("gsensor", STATUS_UNTESTED);
+ updateTestStatus("leaklight", STATUS_UNTESTED);
updateTestStatus("bluetooth", STATUS_UNTESTED);
- updateTestStatus("ppp", STATUS_UNTESTED);
+ updateTestStatus("sechip", STATUS_UNTESTED);
+ updateTestStatus("gps", 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() << "流程: 产测开启(AT^FACTORY=1) → 设备重启 → … → 全部完成后弹窗确认 → AT^POWEROFF(关机)";
qDebug() << "LCD指令映射: 进入=AT^LCDTEST=1, 红色=AT^LCDTEST=6, 绿色=AT^LCDTEST=3, 蓝色=AT^LCDTEST=4, 退出=AT^LCDTEST=2";
// 发送产测开启指令,等待工厂模式确认
testTimeoutTimer->start(10000);
}
-// 执行录音测试
+// 执行录音测试(配置了等级标准时共测 3 轮,任一轮「实际等级 >= 设置等级」则整体通过)
void MainWindow::performAudioTest()
{
- qDebug() << "*** performAudioTest 被调用 ***";
- qDebug() << "当前状态检查 - isProductionTestRunning:" << isProductionTestRunning;
- qDebug() << "当前状态检查 - currentTestStep:" << currentTestStep;
- qDebug() << "当前状态检查 - TEST_AUDIO:" << TEST_AUDIO;
-
- // 检查录音测试是否启用
- if (!isTestItemEnabled("audio")) {
+ if (!isTestItemEnabled("mic")) {
qDebug() << "录音测试未启用,跳过";
- updateTestStatus("audio", STATUS_UNTESTED);
+ updateTestStatus("mic", STATUS_UNTESTED);
skipToNextEnabledTest();
return;
}
if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) {
- qDebug() << "*** performAudioTest 条件不满足,退出 ***";
+ qDebug() << "录音测试条件不满足,退出";
return;
}
-
- qDebug() << "开始录音测试(自动模式:AT^AUDIOTEST)";
- ui->recvTextEdit->append("========== 开始录音测试 ==========");
- // 录音测试前,无论LCD状态如何,都强制关闭LCD
- // 因为按键测试时按下按键可能会自动开启LCD,但状态可能没有及时更新
- // 为了确保LCD关闭,无论状态如何都发送关闭命令
- qDebug() << "录音测试前强制关闭LCD(无论状态如何)";
- qDebug() << "当前LCD状态 - LCD测试启用:" << isTestItemEnabled("lcd") << "LCD背光状态:" << lcdBacklightOn;
- serial->write("AT^LCDOFF\r\n");
- qDebug() << "发送指令: AT^LCDOFF (关闭LCD)";
- ui->recvTextEdit->append(">>> 发送指令: AT^LCDOFF (关闭LCD,录音测试前强制关闭)");
-
- // 更新LCD状态为关闭(因为发送了关闭命令)
- lcdBacklightOn = false;
+ qDebug() << "开始录音测试";
+ appendToLogFile("\n========== 开始录音测试 ==========\n");
+ updateTestStatus("mic", STATUS_TESTING);
+ audioTestRoundIndex = 0;
+ audioTestAnyPass = false;
+ audioTestAwaitingMicLevel = false;
+
+ QString standard = ui->audioLevelStandardLineEdit->text().trimmed();
+ if (standard.isEmpty()) {
+ appendToLogFile(">>> 未配置等级标准:单轮采样,不做等级校验\n");
+ ui->statusbar->showMessage("录音测试中(未配标准,单轮),请对着麦克风说话...", 5000);
+ } else {
+ appendToLogFile(QString(">>> 已配置等级标准「%1」:共 3 轮,任一轮达标即通过\n").arg(standard));
+ ui->statusbar->showMessage("录音测试 1/3:请对着麦克风说话...", 5000);
+ }
- // LCD关闭后延迟1秒再进行下一步
- QTimer::singleShot(1000, this, [this]() {
- if (isProductionTestRunning && currentTestStep == TEST_AUDIO) {
- performAudioTestContinue();
- }
- });
+ // 录音前关闭LCD(与V1.7一致)
+ if (isTestItemEnabled("lcd") && lcdBacklightOn) {
+ serial->write("AT^LCDOFF\r\n");
+ appendToLogFile(">>> 发送指令: AT^LCDOFF (录音测试前关闭LCD)\n");
+ qDebug() << "录音测试前发送AT^LCDOFF";
+ }
+
+ beginAudioTestAttempt(0);
}
-// 继续录音测试(LCD关闭后或无需关闭LCD时调用)
-void MainWindow::performAudioTestContinue()
+void MainWindow::beginAudioTestAttempt(int roundIndex)
{
- if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) {
+ if (!isProductionTestRunning || currentTestStep != TEST_AUDIO || !serial || !serial->isOpen()) {
+ qDebug() << "录音测试:产测已停止或串口未打开";
return;
}
-
- updateTestStatus("audio", STATUS_TESTING);
- ui->statusbar->showMessage("录音测试中:正在发送AUDIOTEST指令...", 3000);
- // 重置录音测试相关状态
- audioMicMiddleConsecutiveCount = 0;
- audioMicTotalPassCount = 0;
- audioTestFinished = false;
-
- // 获取音频测试通过标准(从UI中读取)
- audioLevelStandard = "中"; // 默认值
- if (ui->recordVolumelineEdit) {
- QString levelText = ui->recordVolumelineEdit->text().trimmed();
- if (!levelText.isEmpty()) {
- audioLevelStandard = levelText;
- }
+ audioTestRoundIndex = roundIndex;
+ audioTestAwaitingMicLevel = true;
+
+ QString standard = ui->audioLevelStandardLineEdit->text().trimmed();
+ if (!standard.isEmpty()) {
+ ui->statusbar->showMessage(QString("录音测试 %1/3:请对着麦克风说话...").arg(roundIndex + 1), 5000);
}
- qDebug() << "音频测试通过标准设置为:" << audioLevelStandard;
- // 发送录音测试指令:先 AT^AUDIOTEST=5 再 AT^AUDIOTEST=7 <音量>
- QTimer::singleShot(0, this, [this]() {
- if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) {
- qDebug() << "录音测试已结束或步骤变化,取消发送AUDIOTEST指令";
+ QString volumeStr = ui->audioVolumeLineEdit->text().trimmed();
+ if (volumeStr.isEmpty()) volumeStr = "2.0";
+
+ QTimer::singleShot(200, this, [this, volumeStr]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_AUDIO || !serial || !serial->isOpen()) {
+ qDebug() << "录音测试:产测已停止或串口未打开";
return;
}
-
- QString audioCmd1 = "AT^AUDIOTEST=5\r\n";
- serial->write(audioCmd1.toUtf8());
- qDebug() << "发送录音测试指令1:" << audioCmd1.trimmed();
- ui->recvTextEdit->append(">>> 发送指令: AT^AUDIOTEST=5");
-
- // 稍微延迟后发送第二条指令(带音量参数)
- QTimer::singleShot(200, this, [this]() {
- if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) {
- qDebug() << "录音测试已结束或步骤变化,取消发送第二条AUDIOTEST指令";
+ serial->write("AT^AUDIOTEST=5\r\n");
+ appendToLogFile(">>> 发送指令: AT^AUDIOTEST=5\n");
+ qDebug() << "发送AT^AUDIOTEST=5";
+ });
+
+ QTimer::singleShot(500, this, [this, volumeStr]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_AUDIO || !serial || !serial->isOpen())
return;
- }
+ QString cmd = QString("AT^AUDIOTEST=7 %1\r\n").arg(volumeStr);
+ serial->write(cmd.toUtf8());
+ appendToLogFile(QString(">>> 发送指令: %1\n").arg(cmd.trimmed()));
+ qDebug() << "发送" << cmd.trimmed();
+ testTimeoutTimer->start(15000); // 15秒超时
+ });
+}
- // 从界面读取音量文本框的值
- QString volumeStr;
- if (ui->audioVolumeLineEdit) {
- volumeStr = ui->audioVolumeLineEdit->text().trimmed();
- }
+void MainWindow::checkAudioTestResult(const QString& data)
+{
+ if (!isProductionTestRunning || currentTestStep != TEST_AUDIO)
+ return;
+ if (!audioTestAwaitingMicLevel)
+ return;
+
+ // 解析 mic level: 静音/极低/低/中/高
+ QRegExp micPattern("mic\\s*level\\s*[::]\\s*(\\S+)", Qt::CaseInsensitive);
+ if (micPattern.indexIn(data) == -1)
+ return;
+
+ QString micLevel = micPattern.cap(1).trimmed();
+ audioTestAwaitingMicLevel = false;
+ testTimeoutTimer->stop();
+
+ qDebug() << "录音测试解析到mic level:" << micLevel;
+ appendToLogFile(QString(">>> 录音测试 第%1轮: mic level=%2\n").arg(audioTestRoundIndex + 1).arg(micLevel));
+ ui->recvTextEdit->append(QString(">>> 录音测试 第%1轮: mic level=%2").arg(audioTestRoundIndex + 1).arg(micLevel));
+
+ // 结束本轮采集
+ if (serial && serial->isOpen()) {
+ serial->write("AT^AUDIOTEST=6\r\n");
+ appendToLogFile(">>> 发送指令: AT^AUDIOTEST=6 (结束本轮音频测试)\n");
+ qDebug() << "发送AT^AUDIOTEST=6";
+ }
+
+ QString standard = ui->audioLevelStandardLineEdit->text().trimmed();
+ if (standard.isEmpty()) {
+ updateTestStatus("mic", STATUS_SUCCESS);
+ ui->statusbar->showMessage(QString("录音测试通过(等级:%1,未配置标准不校验)").arg(micLevel), 3000);
+ skipToNextEnabledTest();
+ return;
+ }
+
+ // 等级排序:静音(0) < 极低(1) < 低(2) < 中(3) < 高(4);达标条件:micRank >= stdRank
+ auto levelRank = [](const QString& s) -> int {
+ if (s == QStringLiteral("静音")) return 0;
+ if (s == QStringLiteral("极低")) return 1;
+ if (s == QStringLiteral("低")) return 2;
+ if (s == QStringLiteral("中")) return 3;
+ if (s == QStringLiteral("高")) return 4;
+ return -1;
+ };
+
+ int micRank = levelRank(micLevel);
+ int stdRank = levelRank(standard);
+
+ if (micRank < 0 || stdRank < 0) {
+ updateTestStatus("mic", STATUS_FAILED);
+ ui->statusbar->showMessage(QString("录音测试失败:无法解析等级(实际:%1, 标准:%2)").arg(micLevel).arg(standard), 3000);
+ skipToNextEnabledTest();
+ return;
+ }
- float volume = 2; // 默认音量为2
- bool ok = false;
- if (!volumeStr.isEmpty()) {
- float v = volumeStr.toFloat(&ok);
- if (ok && v >= 0) {
- volume = v;
- } else {
- qDebug() << "音量文本框内容非法,使用默认音量 2,原始值:" << volumeStr;
- }
- } else {
- qDebug() << "音量文本框为空,使用默认音量 2";
- }
+ const bool roundPass = (micRank >= stdRank);
+ if (roundPass) {
+ audioTestAnyPass = true;
+ appendToLogFile(QString(">>> 第%1轮达标(%2 >= 标准%3)\n").arg(audioTestRoundIndex + 1).arg(micLevel).arg(standard));
+ } else {
+ appendToLogFile(QString(">>> 第%1轮未达标(%2 < 标准%3)\n").arg(audioTestRoundIndex + 1).arg(micLevel).arg(standard));
+ }
+
+ const int completedRound = audioTestRoundIndex;
+ const int nextRound = completedRound + 1;
- QString audioCmd2 = QString("AT^AUDIOTEST=7 %1\r\n").arg(volume);
- serial->write(audioCmd2.toUtf8());
- qDebug() << "发送录音测试指令2:" << audioCmd2.trimmed();
- ui->recvTextEdit->append(QString(">>> 发送指令: AT^AUDIOTEST=7 %1").arg(volume));
+ if (nextRound < 3) {
+ QTimer::singleShot(400, this, [this, nextRound]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) {
+ return;
+ }
+ beginAudioTestAttempt(nextRound);
});
- });
+ return;
+ }
- // 启动 8 秒定时器,在此期间统计"fac:mic level:中"
- if (audioRecordTimer->isActive()) {
- audioRecordTimer->stop();
+ if (audioTestAnyPass) {
+ updateTestStatus("mic", STATUS_SUCCESS);
+ ui->statusbar->showMessage(QString("录音测试通过(3轮中至少一轮达标,标准:%1)").arg(standard), 3000);
+ } else {
+ updateTestStatus("mic", STATUS_FAILED);
+ ui->statusbar->showMessage(QString("录音测试失败:3轮均未达到标准%1").arg(standard), 3000);
}
- audioRecordTimer->start(8000);
+ skipToNextEnabledTest();
}
-// æ\98¾ç¤ºå½\95é\9f³æµ\8bè¯\95å¼¹çª\97
-void MainWindow::showAudioTestDialog()
+// æ\89§è¡\8cç\94µæ± æµ\8bè¯\95
+void MainWindow::performBatteryTest()
{
- if (audioTestPopupShown || !isProductionTestRunning || currentTestStep != TEST_AUDIO) {
- qDebug() << "录音测试弹窗已显示或条件不满足,跳过显示";
+ // 检查电池测试是否启用(充电或NTC任一启用即可)
+ if (!isTestItemEnabled("battery")) {
+ qDebug() << "电池测试未启用(充电和NTC都未启用),跳过";
+ updateTestStatus("battery", STATUS_UNTESTED);
+ updateTestStatus("charge", STATUS_UNTESTED);
+ updateTestStatus("ntc", STATUS_UNTESTED);
+ skipToNextEnabledTest();
return;
}
- // 如果已经有录音测试弹窗存在,先关闭它
- if (audioTestDialog) {
- qDebug() << "检测到已存在的录音测试弹窗,先关闭";
- audioTestDialog->close();
- audioTestDialog->deleteLater();
- audioTestDialog = nullptr;
+ if (!isProductionTestRunning || currentTestStep != TEST_BATTERY) {
+ return;
}
-
- // 创建录音测试对话框
- 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);
-
- // 继续下一个测试
- skipToNextEnabledTest();
- }
- });
-
- connect(audioFailButton, &QPushButton::clicked, [this]() {
- if (audioTestDialog) {
- audioTestDialog->accept();
- qDebug() << "用户确认:录音测试失败";
- ui->statusbar->showMessage("录音测试失败", 2000);
- updateTestStatus("audio", STATUS_FAILED);
-
- // 继续下一个测试
- skipToNextEnabledTest();
- }
- });
-
- 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() << "录音测试弹窗已显示";
-}
-
-// 录音测试定时器 - 8秒超时检查“fac:mic level:中”
-void MainWindow::onAudioRecordTimer()
-{
- audioRecordTimer->stop();
-
- if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) {
- return;
- }
-
- if (audioTestFinished) {
- qDebug() << "录音测试已在8秒内完成,不再处理超时";
- return;
- }
-
- // 8秒内未检测到连续3个或累计6个满足要求的Level,判定录音测试失败
- qDebug() << QString("录音测试8秒超时,连续计数: %1,累计计数: %2,未达到通过标准(连续3次或累计6次),测试失败")
- .arg(audioMicMiddleConsecutiveCount)
- .arg(audioMicTotalPassCount);
- ui->statusbar->showMessage(QString("录音测试失败:8秒内未达到通过标准(连续3次或累计6次满足要求 >= %1)").arg(audioLevelStandard), 3000);
- ui->recvTextEdit->append(QString(">>> 音频测试超时失败: 连续 %1 次,累计 %2 次 (要求: 连续3次或累计6次 >= %3)")
- .arg(audioMicMiddleConsecutiveCount)
- .arg(audioMicTotalPassCount)
- .arg(audioLevelStandard));
- updateTestStatus("audio", STATUS_FAILED);
-
- audioTestFinished = true;
-
- // 发送结束音频测试指令
- QString audioEndCmd = "AT^AUDIOTEST=6\r\n";
- serial->write(audioEndCmd.toUtf8());
- qDebug() << "发送结束音频测试指令:" << audioEndCmd.trimmed();
-
- // 继续后续测试
- skipToNextEnabledTest();
-}
-
-// 解析音频等级(从文字或rms_db数值)
-QString MainWindow::parseAudioLevel(const QString& data)
-{
- // 尝试从 "fac:mic level:" 后面提取值
- QRegExp levelPattern("fac:mic level:(.+)");
- if (levelPattern.indexIn(data) != -1) {
- QString levelStr = levelPattern.cap(1).trimmed();
-
- // 如果是数字(rms_db值),转换为等级文字
- bool ok;
- double rms_db = levelStr.toDouble(&ok);
- if (ok) {
- // 根据rms_db值转换为等级
- if (rms_db < -60.0) {
- return "静音";
- } else if (rms_db < -40.0) {
- return "极低";
- } else if (rms_db < -20.0) {
- return "低";
- } else if (rms_db < -6.0) {
- return "中";
- } else if (rms_db < 0.0) {
- return "高";
- } else {
- return "最大";
- }
- } else {
- // 已经是文字,直接返回(去除可能的空格和换行)
- return levelStr;
- }
- }
-
- return "";
-}
-
-// 获取音频等级数值(用于比较)
-// 返回值:静音=0, 极低=1, 低=2, 中=3, 高=4, 最大=5
-int MainWindow::getAudioLevelValue(const QString& level)
-{
- if (level == "静音") {
- return 0;
- } else if (level == "极低") {
- return 1;
- } else if (level == "低") {
- return 2;
- } else if (level == "中") {
- return 3;
- } else if (level == "高") {
- return 4;
- } else if (level == "最大") {
- return 5;
- }
- return -1; // 未知等级
-}
-
-// 判断检测到的等级是否满足要求
-// 如果设置"低",那么"低"、"中"、"高"、"最大"都可以通过,但"极低"和"静音"不能通过
-bool MainWindow::isAudioLevelPass(const QString& detectedLevel, const QString& requiredLevel)
-{
- int detectedValue = getAudioLevelValue(detectedLevel);
- int requiredValue = getAudioLevelValue(requiredLevel);
-
- if (detectedValue == -1 || requiredValue == -1) {
- return false; // 未知等级,不通过
- }
-
- // 检测到的等级值 >= 要求的等级值,则通过
- return detectedValue >= requiredValue;
-}
-
-// 检查录音测试结果
-void MainWindow::checkAudioTestResult(const QString& data)
-{
- if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) {
- return;
- }
-
- qDebug() << "录音测试收到数据:" << data.trimmed();
-
- // 只在录音测试过程中统计"fac:mic level:"的值
- if (data.contains("fac:mic level:")) {
- // 解析检测到的音频等级
- QString detectedLevel = parseAudioLevel(data);
-
- if (detectedLevel.isEmpty()) {
- qDebug() << "无法解析音频等级,跳过";
- return;
- }
-
- qDebug() << QString("解析到音频等级: %1 (要求: >= %2)").arg(detectedLevel).arg(audioLevelStandard);
-
- // 判断是否满足要求
- bool isPass = isAudioLevelPass(detectedLevel, audioLevelStandard);
-
- if (isPass) {
- // 满足要求,连续计数和累计计数都增加
- audioMicMiddleConsecutiveCount++;
- audioMicTotalPassCount++;
-
- qDebug() << QString("检测到满足要求的等级 \"%1\" (>= %2),连续计数: %3,累计计数: %4")
- .arg(detectedLevel)
- .arg(audioLevelStandard)
- .arg(audioMicMiddleConsecutiveCount)
- .arg(audioMicTotalPassCount);
-
- ui->recvTextEdit->append(QString(">>> 音频测试: 检测到等级 %1 (>= %2),连续 %3 次,累计 %4 次")
- .arg(detectedLevel)
- .arg(audioLevelStandard)
- .arg(audioMicMiddleConsecutiveCount)
- .arg(audioMicTotalPassCount));
- } else {
- // 不满足要求,连续计数清零,但累计计数不变
- qDebug() << QString("检测到不满足要求的等级 \"%1\" (< %2),重置连续计数")
- .arg(detectedLevel)
- .arg(audioLevelStandard);
- audioMicMiddleConsecutiveCount = 0;
-
- ui->recvTextEdit->append(QString(">>> 音频测试: 检测到等级 %1 (< %2,不满足要求),连续计数已重置")
- .arg(detectedLevel)
- .arg(audioLevelStandard));
- }
-
- // 判断是否通过:
- // 1. 连续3次满足要求,或者
- // 2. 累计6次满足要求(即使不是连续的)
- bool testPassed = false;
- QString passReason;
-
- if (audioMicMiddleConsecutiveCount >= 3) {
- testPassed = true;
- passReason = QString("连续 %1 次满足要求").arg(audioMicMiddleConsecutiveCount);
- } else if (audioMicTotalPassCount >= 6) {
- testPassed = true;
- passReason = QString("累计 %1 次满足要求").arg(audioMicTotalPassCount);
- }
-
- if (!audioTestFinished && testPassed) {
- qDebug() << QString("录音测试通过:%1 (要求: >= %2)").arg(passReason).arg(audioLevelStandard);
- ui->statusbar->showMessage(QString("录音测试通过:%1").arg(passReason), 3000);
- ui->recvTextEdit->append(QString(">>> 音频测试通过: %1").arg(passReason));
- updateTestStatus("audio", STATUS_SUCCESS);
-
- audioTestFinished = true;
-
- // 停止8秒定时器,避免再触发超时失败
- if (audioRecordTimer->isActive()) {
- audioRecordTimer->stop();
- }
-
- // 发送结束音频测试指令
- QString audioEndCmd = "AT^AUDIOTEST=6\r\n";
- serial->write(audioEndCmd.toUtf8());
- ui->recvTextEdit->append(">>> 发送指令: AT^AUDIOTEST=6 (结束音频测试)");
- qDebug() << "发送结束音频测试指令:" << audioEndCmd.trimmed();
-
- // 继续后续测试
- skipToNextEnabledTest();
- }
- }
-}
-
-// 执行电池测试
-void MainWindow::performBatteryTest()
-{
- // 检查电池测试是否启用(充电或NTC任一启用即可)
- if (!isTestItemEnabled("charge") && !isTestItemEnabled("ntc")) {
- qDebug() << "电池测试未启用(充电和NTC都未启用),跳过";
- updateTestStatus("battery", STATUS_UNTESTED);
- updateTestStatus("charge", STATUS_UNTESTED);
- updateTestStatus("ntc", STATUS_UNTESTED);
- skipToNextEnabledTest();
- return;
- }
-
- if (!isProductionTestRunning || currentTestStep != TEST_BATTERY) {
- return;
- }
-
- qDebug() << "开始电池测试";
- ui->recvTextEdit->append("========== 开始电池测试 ==========");
- updateTestStatus("battery", STATUS_TESTING);
- ui->statusbar->showMessage("电池测试中,正在获取电池电压...", 3000);
+
+ qDebug() << "开始电池测试";
+ ui->recvTextEdit->append("========== 开始电池测试 ==========");
+ updateTestStatus("battery", STATUS_TESTING);
+ ui->statusbar->showMessage("电池测试中,正在获取电池电压...", 3000);
// 延迟100ms后发送电池电量查询指令,确保串口已准备好
QTimer::singleShot(100, this, [this]() {
// 充电状态检查(根据checkbox决定是否判定)
// 注意:充电状态每次都解析,但只有charge checkbox选中时才用充电状态来判断是否通过
- bool chargeCheckEnabled = isTestItemEnabled("charge");
- bool ntcCheckEnabled = isTestItemEnabled("ntc");
+ bool chargeCheckEnabled = isTestItemEnabled("battery");
+ bool ntcCheckEnabled = isTestItemEnabled("battery");
// 拼接检测结果日志(包含所有已获取的字段)
// 注意:充电状态和温度数据每次都解析并记录,无论checkbox是否选中
ui->statusbar->showMessage("充电检查失败 - 设备未充电", 2000);
ui->recvTextEdit->append(">>> 充电检查失败:设备未充电");
- // 显示充电失败对话框(每次失败都显示,让用户可以选择重试)
+ // 显示充电失败对话框(用户点确认会在此函数内调用skipToNextEnabledTest并返回)
showBatteryChargeFailDialog();
-
- // 注意:不直接返回,继续检查NTC(如果启用),然后根据所有检查结果来决定是否通过
+ return; // 充电失败后不再继续后续NTC等逻辑,已由弹窗处理
} else if (chargeFound && charge != -1 && charge != 0 && charge != 1) {
// 检测到charge字段但值不是0或1,可能是异常值
qDebug() << QString("充电检查:检测到异常charge值 %1,期望0或1").arg(charge);
// NTC温度检查(根据checkbox决定是否判定)
// 注意:温度数据每次都解析,但只有NTC checkbox选中时才用温度>0来判断是否通过
- bool isVoltageNormal = (voltage >= 3.3 && voltage <= 4.4);
+ // 电压范围:3.3V-4.6V(支持充满电时4.5V+的测量值)
+ bool isVoltageNormal = (voltage >= 3.3 && voltage <= 4.6);
bool isTempNormal = true; // 默认温度正常(未检测到温度时不影响结果)
// 温度数据每次都解析(已经在上面解析了),这里只判断是否满足条件
failReasons << "NTC温度检查失败";
}
if (!isVoltageNormal) {
- failReasons << QString("电压异常: %1V(正常范围3.3V-4.4V)").arg(voltage);
+ failReasons << QString("电压异常: %1V(正常范围3.3V-4.6V)").arg(voltage);
}
failMsg += failReasons.join(",");
}
}
-// 执行G-sensor测试
+// 执行G-sensor测试(10秒内计算XYZ变化)
void MainWindow::performGsensorTest()
{
// 检查G-sensor测试是否启用
skipToNextEnabledTest();
return;
}
-
+
if (!isProductionTestRunning || currentTestStep != TEST_GSENSOR) {
return;
}
- qDebug() << "开始G-sensor测试";
+ qDebug() << "开始G-sensor测试(10秒XYZ变化计算)";
ui->recvTextEdit->append("========== 开始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);
+ ui->statusbar->showMessage("G-sensor测试中:AT^GSENSORTEST=1(10秒)", 3000);
+
+ // 重置采集状态
+ gSensorCollecting = false;
+ gSensorHasStart = false;
+ gSensorHasLast = false;
+ gSensorErrorDetected = false;
+ gSensorAnySample = false;
+ gSensorAllSamplesInRange = true;
+ gSensorStartX = 0.0;
+ gSensorStartY = 0.0;
+ gSensorStartZ = 0.0;
+ gSensorLastX = 0.0;
+ gSensorLastY = 0.0;
+ gSensorLastZ = 0.0;
+
+ // 防止通用超时干扰
+ if (testTimeoutTimer->isActive()) {
+ testTimeoutTimer->stop();
+ }
+ if (gSensorIntervalTimer->isActive()) {
+ gSensorIntervalTimer->stop();
+ }
+
+ // 1) 延迟一点后开始打印XYZ
+ QTimer::singleShot(300, this, [this]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_GSENSOR) {
+ return;
+ }
+ if (!serial || !serial->isOpen()) {
+ return;
+ }
+
+ ui->recvTextEdit->append(">>> 发送指令: AT^GSENSORTEST=1 (开始检测与打印)");
+ serial->write("AT^GSENSORTEST=1\r\n");
+ qDebug() << "发送指令: AT^GSENSORTEST=1";
+
+ gSensorCollecting = true;
+ ui->statusbar->showMessage("G-sensor检测与打印中...(10秒)", 2000);
+
+ // 10秒后停止检测并计算
+ gSensorIntervalTimer->start(10000);
+ });
}
-// 检查G-sensor测试结果
+// 检查G-sensor测试结果(解析XYZ)
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;
+
+ const QString trimmed = data.trimmed();
+
+ if (trimmed.contains("ERROR", Qt::CaseInsensitive) || trimmed.contains("FAIL", Qt::CaseInsensitive)) {
+ gSensorErrorDetected = true;
+ return;
+ }
+
+ if (!gSensorCollecting) {
+ return; // 非采集窗口不做解析
+ }
+
+ // 解析格式:XYZ: X=-1.28,Y=8.22,Z=-4.60
+ if (trimmed.contains("XYZ:", Qt::CaseInsensitive)) {
+ QRegExp xyzPattern("XYZ\\s*:\\s*X\\s*=\\s*([-]?[0-9]+\\.?[0-9]*),\\s*Y\\s*=\\s*([-]?[0-9]+\\.?[0-9]*),\\s*Z\\s*=\\s*([-]?[0-9]+\\.?[0-9]*)",
+ Qt::CaseInsensitive);
+ if (xyzPattern.indexIn(trimmed) != -1) {
+ bool okX = false, okY = false, okZ = false;
+ double x = xyzPattern.cap(1).toDouble(&okX);
+ double y = xyzPattern.cap(2).toDouble(&okY);
+ double z = xyzPattern.cap(3).toDouble(&okZ);
+
+ if (okX && okY && okZ) {
+ ui->recvTextEdit->append(QString(">>> G-sensor采样: XYZ: X=%1,Y=%2,Z=%3")
+ .arg(x, 0, 'f', 2).arg(y, 0, 'f', 2).arg(z, 0, 'f', 2));
+ gSensorAnySample = true;
+ // 起始XYZ:第一次解析到的点
+ if (!gSensorHasStart) {
+ gSensorHasStart = true;
+ gSensorStartX = x;
+ gSensorStartY = y;
+ gSensorStartZ = z;
+ ui->statusbar->showMessage(QString("G-sensor起始XYZ已记录:X=%1 Y=%2 Z=%3").arg(x).arg(y).arg(z), 1500);
}
- }
-
- 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测试完成,推进到下一个测试
- if (isProductionTestRunning && currentTestStep == TEST_GSENSOR) {
- qDebug() << "G-sensor测试完成,推进到下一个测试";
- skipToNextEnabledTest();
- }
- } 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测试完成,推进到下一个测试
- if (isProductionTestRunning && currentTestStep == TEST_GSENSOR) {
- qDebug() << "G-sensor测试完成(手动),推进到下一个测试";
- skipToNextEnabledTest();
+
+ // 末尾XYZ:10秒窗口内最后一次解析到的点
+ gSensorHasLast = true;
+ gSensorLastX = x;
+ gSensorLastY = y;
+ gSensorLastZ = z;
+
+ // 每条采样都要满足阈值范围
+ auto parseDoubleOrInvalid = [](const QString& s, bool& ok) -> double {
+ QString t = s.trimmed();
+ if (t.isEmpty()) {
+ ok = false;
+ return 0.0;
+ }
+ return t.toDouble(&ok);
+ };
+ bool okXMin = false, okXMax = false, okYMin = false, okYMax = false, okZMin = false, okZMax = false;
+ double xMin = parseDoubleOrInvalid(ui->gsensorDeltaXMinLineEdit->text(), okXMin);
+ double xMax = parseDoubleOrInvalid(ui->gsensorDeltaXMaxLineEdit->text(), okXMax);
+ double yMin = parseDoubleOrInvalid(ui->gsensorDeltaYMinLineEdit->text(), okYMin);
+ double yMax = parseDoubleOrInvalid(ui->gsensorDeltaYMaxLineEdit->text(), okYMax);
+ double zMin = parseDoubleOrInvalid(ui->gsensorDeltaZMinLineEdit->text(), okZMin);
+ double zMax = parseDoubleOrInvalid(ui->gsensorDeltaZMaxLineEdit->text(), okZMax);
+
+ bool samplePass = true;
+ if (okXMin && x < xMin) samplePass = false;
+ if (okXMax && x > xMax) samplePass = false;
+ if (okYMin && y < yMin) samplePass = false;
+ if (okYMax && y > yMax) samplePass = false;
+ if (okZMin && z < zMin) samplePass = false;
+ if (okZMax && z > zMax) samplePass = false;
+
+ if (!samplePass) {
+ gSensorAllSamplesInRange = false;
+ ui->recvTextEdit->append(">>> G-sensor采样超限");
}
}
}
- } else {
- qDebug() << "数据不包含gsensor和id关键字,跳过G-sensor处理";
}
-
- // 单独检查错误响应
- if (data.contains("ERROR") || data.contains("FAIL")) {
- qDebug() << "G-sensor测试失败 - 设备响应错误";
- ui->statusbar->showMessage("G-sensor测试失败 - 设备无响应", 2000);
+}
+
+// 10秒到时:发送GSENSORTEST=0并计算变化
+void MainWindow::onGsensorIntervalTimeout()
+{
+ if (!isProductionTestRunning || currentTestStep != TEST_GSENSOR) {
+ return;
+ }
+
+ gSensorIntervalTimer->stop();
+
+ if (serial && serial->isOpen()) {
+ ui->recvTextEdit->append(">>> 发送指令: AT^GSENSORTEST=0 (停止检测与打印)");
+ serial->write("AT^GSENSORTEST=0\r\n");
+ qDebug() << "发送指令: AT^GSENSORTEST=0";
+ }
+
+ // 给设备一点时间把最后一行XYZ打印出来
+ QTimer::singleShot(500, this, [this]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_GSENSOR) {
+ return;
+ }
+ gSensorCollecting = false;
+ finalizeGsensorTest();
+ });
+}
+
+// 结束G-sensor判定:要求每条采样都在阈值范围内
+void MainWindow::finalizeGsensorTest()
+{
+ if (!isProductionTestRunning || currentTestStep != TEST_GSENSOR) {
+ return;
+ }
+
+ if (gSensorErrorDetected) {
+ ui->statusbar->showMessage("G-sensor测试失败:设备返回ERROR/FAIL", 3000);
updateTestStatus("gsensor", STATUS_FAILED);
-
- // G-sensor测试失败,仍然继续下一个测试
- if (isProductionTestRunning && currentTestStep == TEST_GSENSOR) {
- qDebug() << "G-sensor测试失败,继续下一个测试";
- skipToNextEnabledTest();
+ skipToNextEnabledTest();
+ return;
+ }
+
+ if (!gSensorAnySample) {
+ ui->statusbar->showMessage("G-sensor测试失败:10秒内未采到XYZ数据", 3000);
+ updateTestStatus("gsensor", STATUS_FAILED);
+ skipToNextEnabledTest();
+ return;
+ }
+
+ // 读取UI阈值(允许空:表示不校验该边界)
+ auto parseDoubleOrInvalid = [](const QString& s, bool& ok) -> double {
+ QString t = s.trimmed();
+ if (t.isEmpty()) {
+ ok = false;
+ return 0.0;
+ }
+ return t.toDouble(&ok);
+ };
+
+ bool okXMin = false, okXMax = false, okYMin = false, okYMax = false, okZMin = false, okZMax = false;
+ parseDoubleOrInvalid(ui->gsensorDeltaXMinLineEdit->text(), okXMin);
+ parseDoubleOrInvalid(ui->gsensorDeltaXMaxLineEdit->text(), okXMax);
+ parseDoubleOrInvalid(ui->gsensorDeltaYMinLineEdit->text(), okYMin);
+ parseDoubleOrInvalid(ui->gsensorDeltaYMaxLineEdit->text(), okYMax);
+ parseDoubleOrInvalid(ui->gsensorDeltaZMinLineEdit->text(), okZMin);
+ parseDoubleOrInvalid(ui->gsensorDeltaZMaxLineEdit->text(), okZMax);
+
+ // okXMin/okXMax 只有在“输入非空且可转 double”时才为 true
+ const bool xMinSet = okXMin;
+ const bool xMaxSet = okXMax;
+ const bool yMinSet = okYMin;
+ const bool yMaxSet = okYMax;
+ const bool zMinSet = okZMin;
+ const bool zMaxSet = okZMax;
+
+ if (!(xMinSet || xMaxSet || yMinSet || yMaxSet || zMinSet || zMaxSet)) {
+ // 未配置任何阈值时:只要采到有效 XYZ 即判定通过(有值就为通过)
+ ui->statusbar->showMessage("G-sensor测试通过:未配置阈值,已采到有效XYZ数据", 3000);
+ updateTestStatus("gsensor", STATUS_SUCCESS);
+ skipToNextEnabledTest();
+ return;
+ }
+
+ if (gSensorAllSamplesInRange) {
+ ui->statusbar->showMessage("G-sensor测试通过:10秒内所有XYZ采样均在阈值范围", 3000);
+ updateTestStatus("gsensor", STATUS_SUCCESS);
+ } else {
+ ui->statusbar->showMessage("G-sensor测试失败:存在超限采样", 3000);
+ updateTestStatus("gsensor", STATUS_FAILED);
+ }
+
+ skipToNextEnabledTest();
+}
+
+// 执行漏光测试
+void MainWindow::performLeaklightTest()
+{
+ if (!isTestItemEnabled("leaklight")) {
+ qDebug() << "漏光测试未启用,跳过";
+ updateTestStatus("leaklight", STATUS_UNTESTED);
+ skipToNextEnabledTest();
+ return;
+ }
+
+ if (!isProductionTestRunning || currentTestStep != TEST_LEAKLIGHT) {
+ return;
+ }
+
+ updateTestStatus("leaklight", STATUS_TESTING);
+ ui->recvTextEdit->append("========== 开始漏光测试 ==========");
+ ui->recvTextEdit->append(">>> 发送指令: AT^LEAKLIGHT");
+ ui->statusbar->showMessage("漏光测试中,等待green/red/ir数据...", 3000);
+
+ leaklightGreen = 0;
+ leaklightRed = 0;
+ leaklightIr = 0;
+ leaklightGreenSeen = false;
+ leaklightRedSeen = false;
+ leaklightIrSeen = false;
+
+ if (serial && serial->isOpen()) {
+ serial->write("AT^LEAKLIGHT\r\n");
+ }
+
+ testTimeoutTimer->start(10000);
+}
+
+void MainWindow::checkLeaklightTestResult(const QString& data)
+{
+ if (!isProductionTestRunning || currentTestStep != TEST_LEAKLIGHT) {
+ return;
+ }
+
+ QRegExp greenPattern("green\\s*:\\s*(\\d+)", Qt::CaseInsensitive);
+ QRegExp redPattern("red\\s*:\\s*(\\d+)", Qt::CaseInsensitive);
+ QRegExp irPattern("ir\\s*:\\s*(\\d+)", Qt::CaseInsensitive);
+
+ if (greenPattern.indexIn(data) != -1) {
+ leaklightGreen = greenPattern.cap(1).toInt();
+ leaklightGreenSeen = true;
+ ui->recvTextEdit->append(QString(">>> 漏光数据 green: %1").arg(leaklightGreen));
+ }
+ if (redPattern.indexIn(data) != -1) {
+ leaklightRed = redPattern.cap(1).toInt();
+ leaklightRedSeen = true;
+ ui->recvTextEdit->append(QString(">>> 漏光数据 red: %1").arg(leaklightRed));
+ }
+ if (irPattern.indexIn(data) != -1) {
+ leaklightIr = irPattern.cap(1).toInt();
+ leaklightIrSeen = true;
+ ui->recvTextEdit->append(QString(">>> 漏光数据 ir: %1").arg(leaklightIr));
+ }
+
+ if (leaklightGreenSeen && leaklightRedSeen && leaklightIrSeen) {
+ if (testTimeoutTimer->isActive()) {
+ testTimeoutTimer->stop();
}
+ const bool pass = (leaklightGreen != 0 && leaklightRed != 0 && leaklightIr != 0);
+ if (pass) {
+ updateTestStatus("leaklight", STATUS_SUCCESS);
+ ui->statusbar->showMessage("漏光测试通过(green/red/ir均非0)", 2500);
+ } else {
+ updateTestStatus("leaklight", STATUS_FAILED);
+ ui->statusbar->showMessage("漏光测试失败(存在0值)", 2500);
+ }
+ skipToNextEnabledTest();
}
}
}
qDebug() << "开始蓝牙测试";
- ui->recvTextEdit->append("========== 开始蓝牙测试 ==========");
+ appendToLogFile("\n========== 开始蓝牙测试 ==========\n");
updateTestStatus("bluetooth", STATUS_TESTING);
// 重置蓝牙测试相关状态
bluetoothAddresses.clear();
+ bluetoothAddressRssiMap.clear();
bluetoothTestFinished = false;
detectedBluetoothAddress = "";
- detectedBluetoothRSSI = 0;
-
- // 检查是否使用指定地址+RSSI模式
- QString targetAddress = ui->bluetoothAddressLineEdit->text().trimmed().toUpper();
- QString rssiThresholdStr = ui->bluetoothRSSILineEdit->text().trimmed();
-
- if (!targetAddress.isEmpty() && !rssiThresholdStr.isEmpty()) {
- // 使用指定地址+RSSI模式
- bool ok;
- int rssiThreshold = rssiThresholdStr.toInt(&ok);
- if (ok) {
- ui->statusbar->showMessage(QString("蓝牙测试中:扫描指定地址 %1,RSSI阈值 %2").arg(targetAddress).arg(rssiThreshold), 3000);
- qDebug() << "蓝牙测试模式:指定地址+RSSI,地址:" << targetAddress << ",RSSI阈值:" << rssiThreshold;
- } else {
- ui->statusbar->showMessage("蓝牙测试中:RSSI阈值格式错误,使用3设备模式", 3000);
- qDebug() << "RSSI阈值格式错误,切换到3设备模式";
- targetAddress = "";
- }
+ detectedBluetoothRSSI = -128; // 初始化为很弱的值
+ bluetoothMaxRssi = -128;
+
+ QString expectAddr = configManager.getTestConfig("bluetoothAddress", "").trimmed().toUpper();
+ QString expectRssiStr = configManager.getTestConfig("bluetoothRSSI", "").trimmed();
+ bool hasTargetAddr = !expectAddr.isEmpty();
+ bool hasRssiThresh = !expectRssiStr.isEmpty();
+ if (hasTargetAddr && hasRssiThresh) {
+ ui->statusbar->showMessage(QString("蓝牙测试中:必须扫到目标%1且该设备RSSI>%2dBm").arg(expectAddr).arg(expectRssiStr), 3000);
+ } else if (hasTargetAddr) {
+ ui->statusbar->showMessage(QString("蓝牙测试中:必须扫到目标设备 %1").arg(expectAddr), 3000);
+ } else if (hasRssiThresh) {
+ ui->statusbar->showMessage(QString("蓝牙测试中:未设目标地址时,最大RSSI需>%1dBm").arg(expectRssiStr), 3000);
} else {
- // 使用3设备模式
- ui->statusbar->showMessage("蓝牙测试中:正在开启蓝牙扫描(3设备模式)...", 3000);
- qDebug() << "蓝牙测试模式:3设备模式";
+ ui->statusbar->showMessage("蓝牙测试中:需扫描到3个设备且至少一个RSSI≥-90dBm通过", 3000);
}
// 先发送蓝牙使能指令
- ui->recvTextEdit->append(">>> 发送指令: AT^BTENABLE (启用蓝牙)");
+ appendToLogFile(">>> 发送指令: AT^BTENABLE (启用蓝牙)\n");
serial->write("AT^BTENABLE\r\n");
qDebug() << "发送蓝牙使能指令: AT^BTENABLE";
}
QString bluetoothCmd = "AT^BTSCANTEST=1\r\n";
- ui->recvTextEdit->append(">>> 发送指令: AT^BTSCANTEST=1 (开始蓝牙扫描)");
+ appendToLogFile(">>> 发送指令: AT^BTSCANTEST=1 (开始蓝牙扫描)\n");
serial->write(bluetoothCmd.toUtf8());
qDebug() << "发送蓝牙测试开启指令:" << bluetoothCmd.trimmed();
- // 启动15秒超时检测
- bluetoothTestTimer->start(15000);
+ // 启动30秒超时检测
+ bluetoothTestTimer->start(30000);
});
}
qDebug() << "蓝牙测试收到数据:" << data.trimmed();
- // 解析蓝牙设备地址和RSSI:支持两种格式
+ // 解析蓝牙设备地址和RSSI:支持多种格式
// 格式1: fac:Device: 1C:1D:2B:68:82:68, RSSI=-89 dBm
// 格式2: [BtScan] Device: 1C:1D:2B:68:82:68, RSSI=-89 dBm
- QRegExp bluetoothPattern1("fac:Device:\\s*([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})\\s*,\\s*RSSI=(-?\\d+)\\s*dBm");
- QRegExp bluetoothPattern2("\\[BtScan\\]\\s*Device:\\s*([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})\\s*,\\s*RSSI=(-?\\d+)\\s*dBm");
+ // 格式3: MAC=20:A5:CB:CF:BD:8B,RSSI=-74dBm 或 MAC=20:A5:CB:CF:BD:8B, RSSI=-74 dBm
+ // 格式4: Device: 20:A5:CB:CF:BD:8B, RSSI=-74
+ // 格式5: 任意包含 MAC地址(xx:xx:xx:xx:xx:xx) 和 RSSI=数字 的行
+ QRegExp bluetoothPattern1("fac:Device:\\s*([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})\\s*,\\s*RSSI=(-?\\d+)\\s*dBm?");
+ QRegExp bluetoothPattern2("\\[BtScan\\]\\s*Device:\\s*([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})\\s*,\\s*RSSI=(-?\\d+)\\s*dBm?");
+ QRegExp bluetoothPattern3("MAC\\s*=\\s*([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})\\s*,\\s*RSSI\\s*=\\s*(-?\\d+)\\s*dBm?", Qt::CaseInsensitive);
+ QRegExp bluetoothPattern4("Device\\s*:\\s*([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})\\s*,\\s*RSSI\\s*=\\s*(-?\\d+)", Qt::CaseInsensitive);
+ QRegExp bluetoothPattern5("([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})\\s*[, ].*RSSI\\s*[=:]?\\s*(-?\\d+)", Qt::CaseInsensitive);
QString address;
int rssi = 0;
address = bluetoothPattern1.cap(1).toUpper();
rssi = bluetoothPattern1.cap(2).toInt(&rssiOk);
matched = true;
- qDebug() << "使用格式1 (fac:Device:) 解析";
+ qDebug() << "蓝牙解析: 格式1 (fac:Device:)";
} else if (bluetoothPattern2.indexIn(data) != -1) {
address = bluetoothPattern2.cap(1).toUpper();
rssi = bluetoothPattern2.cap(2).toInt(&rssiOk);
matched = true;
- qDebug() << "使用格式2 ([BtScan] Device:) 解析";
+ qDebug() << "蓝牙解析: 格式2 ([BtScan] Device:)";
+ } else if (bluetoothPattern3.indexIn(data) != -1) {
+ address = bluetoothPattern3.cap(1).toUpper();
+ rssi = bluetoothPattern3.cap(2).toInt(&rssiOk);
+ matched = true;
+ qDebug() << "蓝牙解析: 格式3 (MAC=...)";
+ } else if (bluetoothPattern4.indexIn(data) != -1) {
+ address = bluetoothPattern4.cap(1).toUpper();
+ rssi = bluetoothPattern4.cap(2).toInt(&rssiOk);
+ matched = true;
+ qDebug() << "蓝牙解析: 格式4 (Device:...)";
+ } else if (bluetoothPattern5.indexIn(data) != -1) {
+ address = bluetoothPattern5.cap(1).toUpper();
+ rssi = bluetoothPattern5.cap(2).toInt(&rssiOk);
+ matched = true;
+ qDebug() << "蓝牙解析: 格式5 (通用MAC+RSSI)";
}
if (matched && rssiOk) {
qDebug() << "解析到蓝牙地址:" << address << ",RSSI:" << rssi;
- // 打印到UI:检测到蓝牙设备
- ui->recvTextEdit->append(QString(">>> 检测到蓝牙设备: MAC=%1, RSSI=%2 dBm").arg(address).arg(rssi));
-
- // 检查是否使用指定地址+RSSI模式
- QString targetAddress = ui->bluetoothAddressLineEdit->text().trimmed().toUpper();
- QString rssiThresholdStr = ui->bluetoothRSSILineEdit->text().trimmed();
+ if (!bluetoothAddresses.contains(address)) {
+ bluetoothAddresses.insert(address);
+ appendToLogFile(QString(">>> 新蓝牙设备:MAC=%1,RSSI=%2dBm(已检测到%3个不同设备)\n")
+ .arg(address).arg(rssi).arg(bluetoothAddresses.size()));
+ }
+ // 更新该地址的最佳RSSI(同一设备可能多次上报,取信号最强的)
+ if (!bluetoothAddressRssiMap.contains(address) || rssi > bluetoothAddressRssiMap[address]) {
+ bluetoothAddressRssiMap[address] = rssi;
+ }
+ if (rssi > bluetoothMaxRssi) {
+ bluetoothMaxRssi = rssi;
+ }
+
+ QString expectAddr = configManager.getTestConfig("bluetoothAddress", "").trimmed().toUpper();
+ QString expectRssiStr = configManager.getTestConfig("bluetoothRSSI", "").trimmed();
+ bool hasTargetAddr = !expectAddr.isEmpty();
+ bool hasRssiThresh = !expectRssiStr.isEmpty();
+ int expectRssi = hasRssiThresh ? expectRssiStr.toInt() : 0;
+
+ bool pass = false;
+ if (hasTargetAddr && hasRssiThresh) {
+ int addrRssi = bluetoothAddressRssiMap.value(expectAddr, -128);
+ pass = bluetoothAddresses.contains(expectAddr) && addrRssi > expectRssi;
+ } else if (hasTargetAddr) {
+ pass = bluetoothAddresses.contains(expectAddr);
+ } else if (hasRssiThresh) {
+ pass = (bluetoothMaxRssi > expectRssi);
+ } else {
+ pass = (bluetoothAddresses.size() >= 3 && bluetoothMaxRssi >= -90);
+ }
- if (!targetAddress.isEmpty() && !rssiThresholdStr.isEmpty()) {
- // 指定地址+RSSI模式
- bool ok;
- int rssiThreshold = rssiThresholdStr.toInt(&ok);
- if (ok && address == targetAddress) {
- qDebug() << "检测到目标地址:" << address << ",RSSI:" << rssi << ",阈值:" << rssiThreshold;
- detectedBluetoothAddress = address;
- detectedBluetoothRSSI = rssi;
-
- if (rssi >= rssiThreshold) {
- // RSSI满足要求,测试通过
- qDebug() << "蓝牙测试通过:检测到指定地址" << address << ",RSSI" << rssi << "大于等于阈值" << rssiThreshold;
- ui->recvTextEdit->append(QString(">>> 蓝牙测试通过: 目标地址 %1, RSSI=%2 dBm (>= 阈值 %3)").arg(address).arg(rssi).arg(rssiThreshold));
- ui->statusbar->showMessage(QString("蓝牙测试通过:地址 %1,RSSI %2").arg(address).arg(rssi), 3000);
- updateTestStatus("bluetooth", STATUS_SUCCESS);
-
- bluetoothTestFinished = true;
-
- // 停止10秒定时器
- if (bluetoothTestTimer->isActive()) {
- bluetoothTestTimer->stop();
- }
-
- // 发送结束蓝牙扫描指令
- QString bluetoothEndCmd = "AT^BTSCANTEST=2\r\n";
- ui->recvTextEdit->append(">>> 发送指令: AT^BTSCANTEST=2 (结束蓝牙扫描)");
- serial->write(bluetoothEndCmd.toUtf8());
- qDebug() << "发送蓝牙测试结束指令:" << bluetoothEndCmd.trimmed();
-
- // 延迟200ms后发送蓝牙禁用指令
- QTimer::singleShot(200, this, [this]() {
- if (isProductionTestRunning && currentTestStep == TEST_BLUETOOTH) {
- ui->recvTextEdit->append(">>> 发送指令: AT^BTDISABLE (禁用蓝牙)");
- serial->write("AT^BTDISABLE\r\n");
- qDebug() << "发送蓝牙禁用指令: AT^BTDISABLE";
-
- // 继续后续测试
- QTimer::singleShot(300, this, [this]() {
- if (isProductionTestRunning && currentTestStep == TEST_BLUETOOTH) {
- skipToNextEnabledTest();
- }
- });
- }
- });
- } else {
- qDebug() << "RSSI不满足要求:" << rssi << "<" << rssiThreshold;
- ui->recvTextEdit->append(QString(">>> 蓝牙测试: 目标地址 %1, RSSI=%2 dBm (< 阈值 %3,不满足要求)").arg(address).arg(rssi).arg(rssiThreshold));
- ui->statusbar->showMessage(QString("蓝牙测试:检测到地址 %1,但RSSI %2 小于阈值 %3").arg(address).arg(rssi).arg(rssiThreshold), 2000);
- }
+ if (pass) {
+ updateTestStatus("bluetooth", STATUS_SUCCESS);
+ if (hasTargetAddr) {
+ int addrRssi = bluetoothAddressRssiMap.value(expectAddr, -128);
+ ui->statusbar->showMessage(QString("蓝牙测试通过:目标%1,RSSI=%2dBm").arg(expectAddr).arg(addrRssi), 3000);
+ } else if (hasRssiThresh) {
+ ui->statusbar->showMessage(QString("蓝牙测试通过:最大RSSI=%1dBm").arg(bluetoothMaxRssi), 3000);
+ } else {
+ ui->statusbar->showMessage(QString("蓝牙测试通过:检测到%1个设备,最大RSSI=%2dBm").arg(bluetoothAddresses.size()).arg(bluetoothMaxRssi), 3000);
}
- } else {
- // 3设备模式
- if (!bluetoothAddresses.contains(address)) {
- bluetoothAddresses.insert(address);
- qDebug() << "检测到新的蓝牙地址:" << address << ",当前已检测到" << bluetoothAddresses.size() << "个不同地址";
- ui->recvTextEdit->append(QString(">>> 新蓝牙设备: MAC=%1, RSSI=%2 dBm (已检测到 %3 个不同设备)").arg(address).arg(rssi).arg(bluetoothAddresses.size()));
- ui->statusbar->showMessage(QString("蓝牙测试:已检测到 %1 个不同地址").arg(bluetoothAddresses.size()), 2000);
-
- // 检查是否达到3个及以上不同的蓝牙地址
- if (bluetoothAddresses.size() >= 3) {
- qDebug() << "蓝牙测试通过:已检测到" << bluetoothAddresses.size() << "个不同的蓝牙地址";
- ui->recvTextEdit->append(QString(">>> 蓝牙测试通过: 已检测到 %1 个不同设备 (要求>=3)").arg(bluetoothAddresses.size()));
- ui->statusbar->showMessage(QString("蓝牙测试通过:检测到 %1 个不同地址").arg(bluetoothAddresses.size()), 3000);
- updateTestStatus("bluetooth", STATUS_SUCCESS);
-
- bluetoothTestFinished = true;
-
- // 停止10秒定时器
- if (bluetoothTestTimer->isActive()) {
- bluetoothTestTimer->stop();
- }
-
- // 发送结束蓝牙扫描指令
- QString bluetoothEndCmd = "AT^BTSCANTEST=2\r\n";
- ui->recvTextEdit->append(">>> 发送指令: AT^BTSCANTEST=2 (结束蓝牙扫描)");
- serial->write(bluetoothEndCmd.toUtf8());
- qDebug() << "发送蓝牙测试结束指令:" << bluetoothEndCmd.trimmed();
-
- // 延迟200ms后发送蓝牙禁用指令
- QTimer::singleShot(200, this, [this]() {
+ bluetoothTestFinished = true;
+ if (bluetoothTestTimer->isActive()) {
+ bluetoothTestTimer->stop();
+ }
+
+ QString bluetoothEndCmd = "AT^BTSCANTEST=2\r\n";
+ ui->recvTextEdit->append(">>> 发送指令: AT^BTSCANTEST=2 (结束蓝牙扫描)");
+ serial->write(bluetoothEndCmd.toUtf8());
+
+ QTimer::singleShot(200, this, [this]() {
+ if (isProductionTestRunning && currentTestStep == TEST_BLUETOOTH) {
+ ui->recvTextEdit->append(">>> 发送指令: AT^BTDISABLE (禁用蓝牙)");
+ serial->write("AT^BTDISABLE\r\n");
+ QTimer::singleShot(300, this, [this]() {
if (isProductionTestRunning && currentTestStep == TEST_BLUETOOTH) {
- ui->recvTextEdit->append(">>> 发送指令: AT^BTDISABLE (禁用蓝牙)");
- serial->write("AT^BTDISABLE\r\n");
- qDebug() << "发送蓝牙禁用指令: AT^BTDISABLE";
-
- // 继续后续测试
- QTimer::singleShot(300, this, [this]() {
- if (isProductionTestRunning && currentTestStep == TEST_BLUETOOTH) {
- skipToNextEnabledTest();
- }
- });
+ skipToNextEnabledTest();
}
});
}
- } else {
- qDebug() << "检测到重复的蓝牙地址:" << address << ",已存在,跳过";
- // 即使是重复地址,也打印到UI(但标记为重复)
- ui->recvTextEdit->append(QString(">>> 重复蓝牙设备: MAC=%1, RSSI=%2 dBm (已存在)").arg(address).arg(rssi));
- }
+ });
}
}
}
}
if (bluetoothTestFinished) {
- qDebug() << "蓝牙测试已在10秒内完成,不再处理超时";
- return;
- }
+ qDebug() << "蓝牙测试已在30秒窗口内完成,不再处理超时";
+ return;
+ }
- // 检查是否使用指定地址+RSSI模式
- QString targetAddress = ui->bluetoothAddressLineEdit->text().trimmed().toUpper();
- QString rssiThresholdStr = ui->bluetoothRSSILineEdit->text().trimmed();
-
- if (!targetAddress.isEmpty() && !rssiThresholdStr.isEmpty()) {
- // 指定地址+RSSI模式超时
- bool ok;
- int rssiThreshold = rssiThresholdStr.toInt(&ok);
- if (ok) {
- if (detectedBluetoothAddress.isEmpty()) {
- qDebug() << "蓝牙测试10秒超时,未检测到指定地址" << targetAddress;
- ui->statusbar->showMessage(QString("蓝牙测试失败:10秒内未检测到指定地址 %1").arg(targetAddress), 3000);
- } else {
- qDebug() << "蓝牙测试10秒超时,检测到指定地址" << detectedBluetoothAddress << "但RSSI" << detectedBluetoothRSSI << "小于阈值" << rssiThreshold;
- ui->statusbar->showMessage(QString("蓝牙测试失败:检测到地址 %1,但RSSI %2 小于阈值 %3").arg(detectedBluetoothAddress).arg(detectedBluetoothRSSI).arg(rssiThreshold), 3000);
- }
+ QString expectAddr = configManager.getTestConfig("bluetoothAddress", "").trimmed().toUpper();
+ QString expectRssiStr = configManager.getTestConfig("bluetoothRSSI", "").trimmed();
+ bool hasTargetAddr = !expectAddr.isEmpty();
+ bool hasRssiThresh = !expectRssiStr.isEmpty();
+ int expectRssi = hasRssiThresh ? expectRssiStr.toInt() : 0;
+ if (hasTargetAddr && hasRssiThresh) {
+ if (!bluetoothAddresses.contains(expectAddr)) {
+ ui->statusbar->showMessage(QString("蓝牙测试失败:未扫到目标 %1").arg(expectAddr), 3000);
} else {
- qDebug() << "蓝牙测试10秒超时,RSSI阈值格式错误";
- ui->statusbar->showMessage("蓝牙测试失败:RSSI阈值格式错误", 3000);
+ int addrRssi = bluetoothAddressRssiMap.value(expectAddr, -128);
+ ui->statusbar->showMessage(QString("蓝牙测试失败:目标%1 RSSI=%2dBm,需>%3dBm").arg(expectAddr).arg(addrRssi).arg(expectRssi), 3000);
}
+ } else if (hasTargetAddr) {
+ ui->statusbar->showMessage(QString("蓝牙测试失败:未扫到目标设备 %1").arg(expectAddr), 3000);
+ } else if (hasRssiThresh) {
+ ui->statusbar->showMessage(QString("蓝牙测试失败:最大RSSI=%1dBm,需>%2dBm").arg(bluetoothMaxRssi).arg(expectRssi), 3000);
} else {
- // 3设备模式超时
- qDebug() << "蓝牙测试10秒超时,仅检测到" << bluetoothAddresses.size() << "个不同地址(需要3个及以上),测试失败";
- ui->statusbar->showMessage(QString("蓝牙测试失败:10秒内仅检测到 %1 个不同地址(需要3个及以上)").arg(bluetoothAddresses.size()), 3000);
+ qDebug() << "蓝牙测试30秒超时,检测到" << bluetoothAddresses.size() << "个设备,最大RSSI=" << bluetoothMaxRssi << "(需要>=3且至少一个RSSI>=-90)";
+ ui->statusbar->showMessage(QString("蓝牙测试失败:检测到%1个设备,最大RSSI=%2dBm(需要>=3且至少一个≥-90dBm)").arg(bluetoothAddresses.size()).arg(bluetoothMaxRssi), 3000);
}
updateTestStatus("bluetooth", STATUS_FAILED);
});
}
-// æ£\80æ\9f¥CAT1ä¿¡å\8f·æµ\8bè¯\95ç»\93æ\9e\9c
-void MainWindow::checkCat1SignalResult(const QString& data)
+// æ\89§è¡\8cSEè\8a¯ç\89\87æµ\8bè¯\95
+void MainWindow::performSeChipTest()
{
- if (!isProductionTestRunning || !hasReceivedFirstSignal) {
+ if (!isTestItemEnabled("sechip")) {
+ qDebug() << "SE芯片测试未启用,跳过";
+ updateTestStatus("sechip", STATUS_UNTESTED);
+ skipToNextEnabledTest();
return;
}
-
- qDebug() << "CAT1信号测试收到数据:" << data.trimmed();
- qDebug() << "当前MODEM版本:" << currentModemVersion << ",类型判断:" << (isEGModem() ? "EG系列" : "非EG系列");
-
- // 只在CAT1测试期间统计信号值
- if (cat1SignalReceivedCount >= 5) {
- qDebug() << "CAT1测试已接收5次响应,跳过统计";
+
+ if (!isProductionTestRunning || currentTestStep != TEST_SECHIP) {
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值显示到界面
- appendToLogFile(QString("CAT1 Signal值: %1 (%2/5)\n").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;
+ updateTestStatus("sechip", STATUS_TESTING);
+ appendToLogFile("\n========== 开始SE芯片测试 ==========\n");
+ appendToLogFile(">>> 发送指令: AT^GETCYWEEACTIVE\n");
+ ui->statusbar->showMessage("SE芯片测试中,等待cywee active响应...", 3000);
+
+ if (serial && serial->isOpen()) {
+ serial->write("AT^GETCYWEEACTIVE\r\n");
}
- qDebug() << "开始4G信号质量测试(统一使用CAT1GETSIGNAL)";
- ui->recvTextEdit->append("========== 开始4G信号质量测试 ==========");
- ui->statusbar->showMessage("4G信号质量测试中...", 5000);
-
- // 统一使用CAT1GETSIGNAL测试方式,不再区分MODEM类型,不再使用PPP相关指令
- // 初始化CAT1信号测试计数器
- cat1SignalTestCount = 0;
- cat1SignalReceivedCount = 0;
- cat1SignalGoodCount = 0;
- cat1Signal99Count = 0;
- cat1SignalTotalValue = 0;
- hasReceivedFirstSignal = true; // 标记为已启动,直接开始CAT1测试
-
- // 启动CAT1信号测试定时器,每2秒发送一次
- cat1SignalTimer->start(2000);
- ui->statusbar->showMessage("开始CAT1信号测试,每2秒检测一次...", 3000);
-
- // 立即发送第一次CAT1信号检测指令
- serial->write("AT^CAT1GETSIGNAL\r\n");
- cat1SignalTestCount++;
- qDebug() << "发送第" << cat1SignalTestCount << "次CAT1信号检测指令: AT^CAT1GETSIGNAL";
- ui->recvTextEdit->append(">>> 发送指令: AT^CAT1GETSIGNAL");
+ testTimeoutTimer->start(10000);
}
-// 4G信号检测定时器槽函数
-void MainWindow::on4GSignalTimer()
+// 检查SE芯片测试结果
+void MainWindow::checkSeChipTestResult(const QString& data)
{
- if (!isProductionTestRunning || currentTestStep != TEST_PPP_SIGNAL) {
- signal4GTimer->stop();
+ if (!isProductionTestRunning || currentTestStep != TEST_SECHIP) {
return;
}
+
+ // 打印SE芯片原始响应到产测日志(appendToLogFile会同时写入recvTextEdit、logtextEdit和testLogFile)
+ appendToLogFile(QString(">>> SE芯片原始响应: %1\n").arg(data.trimmed()));
- 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);
+ if (data.contains("cywee is active !!!", Qt::CaseInsensitive)) {
+ if (testTimeoutTimer->isActive()) {
+ testTimeoutTimer->stop();
}
- } else {
- // 非EG系列MODEM:统一使用CAT1GETSIGNAL,不再使用PPPSIGNALINFO
- // 这个分支理论上不会执行到,因为perform4GSignalTest已经统一使用CAT1GETSIGNAL
- signal4GTimer->stop();
- qDebug() << "4G信号检测超时,测试失败";
- ui->statusbar->showMessage("4G信号检测超时,测试失败", 5000);
-
- // 显示4G重复测试弹窗
- if (isProductionTestRunning) {
- show4GRetryDialog("4G信号检测超时");
- } else {
- updateTestStatus("ppp", STATUS_FAILED);
+ updateTestStatus("sechip", STATUS_SUCCESS);
+ ui->statusbar->showMessage("SE芯片测试通过(cywee is active)", 2500);
+ appendToLogFile(">>> SE芯片: cywee is active !!! (通过)\n");
+ skipToNextEnabledTest();
+ } else if (data.contains("cywee is not active !!!", Qt::CaseInsensitive)) {
+ if (testTimeoutTimer->isActive()) {
+ testTimeoutTimer->stop();
}
+ updateTestStatus("sechip", STATUS_FAILED);
+ ui->statusbar->showMessage("SE芯片测试失败(cywee is not active)", 2500);
+ appendToLogFile(">>> SE芯片: cywee is not active !!! (失败)\n");
+ skipToNextEnabledTest();
}
}
-// CAT1信号测试定时器槽函数
-void MainWindow::onCat1SignalTimer()
+// 执行GPS测试
+void MainWindow::performGpsTest()
{
- 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);
-
- // CAT1信号测试通过后,进行Ping测试
- if (isProductionTestRunning) {
- qDebug() << "CAT1信号测试通过,开始Ping测试";
- currentTestStep = TEST_PPP_PING;
- performPingTest();
- } else {
- updateTestStatus("ppp", STATUS_SUCCESS);
- }
- } 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);
- }
- }
+ if (!isTestItemEnabled("gps")) {
+ qDebug() << "GPS测试未启用,跳过";
+ updateTestStatus("gps", STATUS_UNTESTED);
+ skipToNextEnabledTest();
return;
}
-
- // 统一使用CAT1GETSIGNAL指令
- serial->write("AT^CAT1GETSIGNAL\r\n");
- cat1SignalTestCount++;
- qDebug() << "发送第" << cat1SignalTestCount << "次CAT1信号检测指令: AT^CAT1GETSIGNAL";
-}
-// Ping测试函数
-void MainWindow::performPingTest()
-{
- if (!isProductionTestRunning || currentTestStep != TEST_PPP_PING) {
- qDebug() << "Ping测试跳过 - 测试状态不正确";
+ if (!isProductionTestRunning || currentTestStep != TEST_GPS) {
return;
}
-
- qDebug() << "========== 开始Ping测试 ==========";
- ui->recvTextEdit->append("========== 开始Ping测试 ==========");
- ui->statusbar->showMessage("Ping测试中 - 检查网络连通性...", 3000);
-
- // 重置Ping测试状态
- pingTestFinished = false;
- pingSuccessCount = 0;
-
- // 从配置管理器获取Ping指令
- QString pingCmd = configManager.getPingCommand();
-
- if (pingCmd.isEmpty()) {
- qDebug() << "Ping指令未配置,使用默认指令";
- pingCmd = "AT^PING=www.163.com";
- }
-
- // 确保指令以\r\n结尾
- if (!pingCmd.endsWith("\r\n")) {
- pingCmd += "\r\n";
- }
-
- // 发送Ping指令
- serial->write(pingCmd.toUtf8());
- qDebug() << "发送Ping指令:" << pingCmd.trimmed();
- appendToLogFile(QString("发送Ping指令: %1\n").arg(pingCmd.trimmed()));
-
- // 启动超时定时器(30秒超时)
- pingTestTimer->start(30000);
+
+ updateTestStatus("gps", STATUS_TESTING);
+ appendToLogFile("\n========== 开始GPS测试 ==========\n");
+ ui->statusbar->showMessage("GPS测试中:10秒内应收到信息,30秒内 trace 卫星数≥3 通过", 5000);
+
+ gpsTestFinished = false;
+ gpsInfoSeenIn10Sec = false;
+ gpsMaxNumSats = 0;
+ gpsMaxTrace = 0;
+ gpsMaxCn = 0;
+
+ // 1. 先切换到GPS测试界面
+ ui->recvTextEdit->append(">>> 发送指令: AT^ENTERTESTVIEW (进入产测界面)");
+ serial->write("AT^ENTERTESTVIEW\r\n");
+ QTimer::singleShot(300, this, [this]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_GPS) return;
+ ui->recvTextEdit->append(">>> 发送指令: AT^TESTJUMP=GPS (切换到GPS测试界面)");
+ serial->write("AT^TESTJUMP=GPS\r\n");
+ QTimer::singleShot(500, this, [this]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_GPS) return;
+ // 2. 开启GPS
+ ui->recvTextEdit->append(">>> 发送指令: AT^GPS=1 (开启GPS)");
+ serial->write("AT^GPS=1\r\n");
+ QTimer::singleShot(500, this, [this]() {
+ if (!isProductionTestRunning || currentTestStep != TEST_GPS) return;
+ // 3. 开始轮询AT^GPSINFO,每2秒发一次
+ ui->recvTextEdit->append(">>> 发送指令: AT^GPSINFO (获取GPS信息)");
+ serial->write("AT^GPSINFO\r\n");
+ gpsPollTimer->start(2000);
+ gpsTestTimer->start(30000);
+ });
+ });
+ });
}
-// 检查Ping测试结果
-void MainWindow::checkPingTestResult(const QString& data)
+// 检查GPS测试结果
+void MainWindow::checkGpsTestResult(const QString& data)
{
- if (!isProductionTestRunning || currentTestStep != TEST_PPP_PING || pingTestFinished) {
+ if (!isProductionTestRunning || currentTestStep != TEST_GPS || gpsTestFinished) {
return;
- }
-
- qDebug() << "Ping测试收到数据:" << data.trimmed();
-
- // 检测Ping成功的关键字
- // 可能的成功响应格式:
- // "PING OK" 或 "ping success" 或包含 "bytes from" 等
- if (data.contains("PING OK", Qt::CaseInsensitive) ||
- data.contains("ping success", Qt::CaseInsensitive) ||
- data.contains("bytes from", Qt::CaseInsensitive) ||
- data.contains("Reply from", Qt::CaseInsensitive)) {
-
- pingSuccessCount++;
- qDebug() << "检测到Ping成功响应,成功次数:" << pingSuccessCount;
- appendToLogFile(QString("Ping成功响应: %1\n").arg(data.trimmed()));
-
- // 只要检测到一次成功就认为网络连通
- if (pingSuccessCount >= 1) {
- pingTestFinished = true;
- pingTestTimer->stop();
-
- qDebug() << "Ping测试通过 - 网络连通";
- ui->statusbar->showMessage("Ping测试通过 - 网络连通", 3000);
- ui->recvTextEdit->append("========== Ping测试通过 ==========");
- appendToLogFile("========== Ping测试通过 ==========\n");
-
- // 4G测试完全通过
- updateTestStatus("ppp", STATUS_SUCCESS);
-
- // 完成产测
- if (isProductionTestRunning) {
- currentTestStep = TEST_COMPLETED;
- isProductionTestRunning = false;
- qDebug() << "Ping测试通过,产测流程完成";
-
- // 保存测试记录
- QString fileName = saveTestRecord();
-
- // 显示最终测试结果弹窗
- showFinalTestResult();
- }
+ }
+
+ if (!gpsInfoSeenIn10Sec) {
+ gpsInfoSeenIn10Sec = true; // 收到第一条信息即满足10秒内看信息
+ }
+
+ // 打印AT^GPSINFO原始响应到产测日志
+ appendToLogFile(QString(">>> GPS原始响应: %1\n").arg(data.trimmed()));
+
+ // 解析 GPSINFO: stat=1, num_sats=0, valid_star=0, vga=2, quality=300000.00, last_ms=...
+ QRegExp numSatsPattern("num_sats\\s*=\\s*(\\d+)", Qt::CaseInsensitive);
+ if (numSatsPattern.indexIn(data) != -1) {
+ int numSats = numSatsPattern.cap(1).toInt();
+ if (numSats > gpsMaxNumSats) {
+ gpsMaxNumSats = numSats;
}
+ appendToLogFile(QString(">>> GPS信息: num_sats=%1\n").arg(numSats));
}
- // 检测Ping失败的关键字
- else if (data.contains("PING FAIL", Qt::CaseInsensitive) ||
- data.contains("ping failed", Qt::CaseInsensitive) ||
- data.contains("timeout", Qt::CaseInsensitive) ||
- data.contains("unreachable", Qt::CaseInsensitive)) {
-
- pingTestFinished = true;
- pingTestTimer->stop();
-
- qDebug() << "Ping测试失败 - 网络不通";
- ui->statusbar->showMessage("Ping测试失败 - 网络不通", 3000);
- ui->recvTextEdit->append("========== Ping测试失败 ==========");
- appendToLogFile(QString("Ping失败响应: %1\n").arg(data.trimmed()));
- appendToLogFile("========== Ping测试失败 ==========\n");
-
- // 显示4G重试对话框
- if (isProductionTestRunning) {
- show4GRetryDialog("Ping测试失败 - 网络不通");
- } else {
- updateTestStatus("ppp", STATUS_FAILED);
+
+ // 卫星数判定以 trace 为准(如 trace=3、trace:3、trace 3)
+ QRegExp tracePattern("trace\\s*[=:]?\\s*(\\d+)", Qt::CaseInsensitive);
+ if (tracePattern.indexIn(data) != -1) {
+ int tr = tracePattern.cap(1).toInt();
+ if (tr > gpsMaxTrace) {
+ gpsMaxTrace = tr;
+ }
+ appendToLogFile(QString(">>> GPS信息: trace=%1\n").arg(tr));
+ }
+
+ // 解析CN值(可能格式:cn=30 或 CN:30 或类似)
+ QRegExp cnPattern("cn\\s*[=:]\\s*(\\d+)", Qt::CaseInsensitive);
+ if (cnPattern.indexIn(data) != -1) {
+ int cn = cnPattern.cap(1).toInt();
+ if (cn > gpsMaxCn) {
+ gpsMaxCn = cn;
}
}
+
+ // 实时判断:trace 卫星数≥3 即通过
+ if (gpsInfoSeenIn10Sec && gpsMaxTrace >= 3) {
+ gpsTestTimer->stop();
+ gpsPollTimer->stop();
+ gpsTestFinished = true;
+ updateTestStatus("gps", STATUS_SUCCESS);
+ ui->statusbar->showMessage(QString("GPS测试通过:trace卫星数=%1").arg(gpsMaxTrace), 3000);
+ ui->recvTextEdit->append(QString(">>> GPS测试通过:trace=%1 (num_sats记录=%2, CNmax=%3)")
+ .arg(gpsMaxTrace).arg(gpsMaxNumSats).arg(gpsMaxCn));
+ serial->write("AT^GPS=0\r\n");
+ ui->recvTextEdit->append(">>> 发送指令: AT^GPS=0 (关闭GPS)");
+ skipToNextEnabledTest();
+ }
}
-// Ping测试超时处理
-void MainWindow::onPingTestTimeout()
+// GPS轮询:每2秒发送AT^GPSINFO
+void MainWindow::onGpsPollTimer()
{
- pingTestTimer->stop();
-
- if (!isProductionTestRunning || currentTestStep != TEST_PPP_PING || pingTestFinished) {
- qDebug() << "Ping超时但测试状态已改变,忽略";
+ if (!isProductionTestRunning || currentTestStep != TEST_GPS || gpsTestFinished) {
+ gpsPollTimer->stop();
return;
}
-
- pingTestFinished = true;
-
- qDebug() << "Ping测试超时 - 30秒内未收到响应";
- ui->statusbar->showMessage("Ping测试超时 - 网络连通性检查失败", 3000);
- ui->recvTextEdit->append("========== Ping测试超时 ==========");
- appendToLogFile("========== Ping测试超时 - 30秒内未收到响应 ==========\n");
-
- // 显示4G重试对话框
- if (isProductionTestRunning) {
- show4GRetryDialog("Ping测试超时");
- } else {
- updateTestStatus("ppp", STATUS_FAILED);
+ if (serial && serial->isOpen()) {
+ serial->write("AT^GPSINFO\r\n");
}
}
-// 检查4G信号质量结果
-void MainWindow::check4GSignalResult(const QString& data)
+// GPS测试30秒超时处理
+void MainWindow::onGpsTestTimer()
{
- if (!isProductionTestRunning || currentTestStep != TEST_PPP_SIGNAL) {
+ gpsTestTimer->stop();
+ gpsPollTimer->stop();
+
+ if (!isProductionTestRunning || currentTestStep != TEST_GPS) {
return;
}
-
- // 如果已经启动了CAT1信号测试,则不再使用旧的4G信号测试逻辑
- if (hasReceivedFirstSignal) {
- qDebug() << "已启动CAT1信号测试,跳过旧的4G信号测试逻辑";
+
+ if (gpsTestFinished) {
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;
- appendToLogFile(rsrqOutput + "\n");
- 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;
- appendToLogFile(rsrpOutput + "\n");
- 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;
- appendToLogFile(overallOutput + "\n");
-
- // 检查信号质量是否良好以上
- 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);
+
+ gpsTestFinished = true;
+
+ bool pass = gpsInfoSeenIn10Sec && gpsMaxTrace >= 3;
+ if (pass) {
+ updateTestStatus("gps", STATUS_SUCCESS);
+ ui->statusbar->showMessage(QString("GPS测试通过:trace卫星数=%1").arg(gpsMaxTrace), 3000);
+ } else {
+ updateTestStatus("gps", STATUS_FAILED);
+ QString reason;
+ if (!gpsInfoSeenIn10Sec) {
+ reason = "10秒内未收到GPS信息";
} 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();
+ reason = QString("trace卫星数=%1(需要≥3)").arg(gpsMaxTrace);
}
-
- // 重置状态标志,为下次检测准备
- rsrqReceived = false;
- rsrpReceived = false;
+ ui->statusbar->showMessage(QString("GPS测试失败:%1").arg(reason), 3000);
+ ui->recvTextEdit->append(QString(">>> GPS测试失败:%1").arg(reason));
}
+
+ serial->write("AT^GPS=0\r\n");
+ ui->recvTextEdit->append(">>> 发送指令: AT^GPS=0 (关闭GPS)");
+ skipToNextEnabledTest();
}
// 获取RSRQ信号质量评级
chargeFailDialog.exec();
if (chargeFailDialog.clickedButton() == confirmButton) {
- qDebug() << "用户确认电池充电失败,标记测试失败";
+ qDebug() << "用户确认电池充电失败,标记测试失败,推进到下一项测试";
updateTestStatus("battery", STATUS_FAILED);
-
- // 继续下一个测试
if (isProductionTestRunning && currentTestStep == TEST_BATTERY) {
- qDebug() << "电池测试失败确认,继续下一个测试";
skipToNextEnabledTest();
}
} else if (chargeFailDialog.clickedButton() == retryButton) {
}
}
-// 显示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 tpResult = ui->tpStatusText->text();
+ QString brightResult = ui->brightStatusText->text();
QString motorResult = ui->motorStatusText->text();
QString keyResult = ui->keyStatusText->text();
+ QString deepsleepResult = ui->deepsleepStatusText->text();
QString audioResult = ui->audioStatusText->text();
QString batteryResult = ui->batteryStatusText->text();
QString gsensorResult = ui->gsensorStatusText->text();
+ QString leaklightResult = ui->leaklightStatusText->text();
QString bluetoothResult = ui->bluetoothStatusText->text();
- QString pppResult = ui->pppStatusText->text();
+ QString sechipResult = ui->sechipStatusText->text();
+ QString gpsResult = ui->gpsStatusText->text();
QString overallResult = ui->overallStatusText->text();
// 创建结果弹窗
QString resultContent = QString(
"===== 产测完成 =====\n\n"
"📱 LCD测试:%1\n"
- "🔧 马达测试:%2\n"
- "⌨️ 按键测试:%3\n"
- "🎤 录音测试:%4\n"
- "🔋 电池测试:%5\n"
- "📡 G-sensor测试:%6\n"
- "📶 蓝牙测试:%7\n"
- "🌐 4G测试:%8\n\n"
- "📊 整体结果:%9"
- ).arg(lcdResult, motorResult, keyResult, audioResult,
- batteryResult, gsensorResult, bluetoothResult, pppResult, overallResult);
+ "🖐️ 触控测试:%2\n"
+ "🌞 亮度测试:%3\n"
+ "🔧 马达测试:%4\n"
+ "⌨️ 按键测试:%5\n"
+ "⚡ 功耗测试:%6\n"
+ "🎤 录音测试:%7\n"
+ "🔋 电池测试:%8\n"
+ "📡 G-sensor测试:%9\n"
+ "❤️ 漏光测试:%10\n"
+ "📶 蓝牙测试:%11\n"
+ "🔒 SE芯片测试:%12\n"
+ "📍 GPS测试:%13\n"
+ "📊 整体结果:%14"
+ ).arg(lcdResult)
+ .arg(tpResult)
+ .arg(brightResult)
+ .arg(motorResult)
+ .arg(keyResult)
+ .arg(deepsleepResult)
+ .arg(audioResult)
+ .arg(batteryResult)
+ .arg(gsensorResult)
+ .arg(leaklightResult)
+ .arg(bluetoothResult)
+ .arg(sechipResult)
+ .arg(gpsResult)
+ .arg(overallResult);
resultDialog.setText(resultContent);
qDebug() << "显示最终测试结果弹窗";
resultDialog.exec();
- // 用户点击确定后的处理
- qDebug() << "用户确认测试结果,发送退出产测指令";
+ // 用户点击确定后的处理:关机,不执行重启/RESTORE
+ qDebug() << "用户确认测试结果,发送关机指令";
- // 发送退出产测指令
if (serial->isOpen()) {
- ui->recvTextEdit->append(">>> 发送指令: AT^RESTORE (退出产测)");
- serial->write("AT^RESTORE\r\n");
- qDebug() << "发送退出产测指令: AT^RESTORE";
- ui->statusbar->showMessage("已退出产测模式", 3000);
+ ui->recvTextEdit->append(">>> 发送指令: AT^POWEROFF (产测结束关机)");
+ serial->write("AT^POWEROFF\r\n");
+ qDebug() << "发送关机指令: AT^POWEROFF";
+ ui->statusbar->showMessage("已发送关机指令", 3000);
}
// 恢复产测按钮状态 - 变回蓝色并启用
testName = "motor";
testDescription = "马达测试";
break;
+ case TEST_AUDIO:
+ testName = "mic";
+ testDescription = "录音测试";
+ break;
case TEST_BATTERY:
testName = "battery";
testDescription = "电池测试";
testName = "gsensor";
testDescription = "G-sensor测试";
break;
+ case TEST_LEAKLIGHT:
+ testName = "leaklight";
+ testDescription = "漏光测试";
+ break;
case TEST_BLUETOOTH:
testName = "bluetooth";
testDescription = "蓝牙测试";
break;
+ case TEST_SECHIP:
+ testName = "sechip";
+ testDescription = "SE芯片测试";
+ break;
+ case TEST_GPS:
+ testName = "gps";
+ testDescription = "GPS测试";
+ break;
default:
qDebug() << "未知的测试步骤超时:" << currentTestStep;
return;
case TEST_MOTOR:
performMotorTest();
break;
+ case TEST_AUDIO:
+ performAudioTest();
+ break;
case TEST_BATTERY:
performBatteryTest();
break;
case TEST_GSENSOR:
performGsensorTest();
break;
+ case TEST_LEAKLIGHT:
+ performLeaklightTest();
+ break;
case TEST_BLUETOOTH:
performBluetoothTest();
break;
+ case TEST_SECHIP:
+ performSeChipTest();
+ break;
+ case TEST_GPS:
+ performGpsTest();
+ break;
default:
break;
}
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() << "停止通用超时定时器";
}
+
+ if (gSensorIntervalTimer->isActive()) {
+ gSensorIntervalTimer->stop();
+ qDebug() << "停止G-sensor采集定时器";
+ }
+ if (gpsTestTimer->isActive()) {
+ gpsTestTimer->stop();
+ qDebug() << "停止GPS测试定时器";
+ }
+ if (gpsPollTimer->isActive()) {
+ gpsPollTimer->stop();
+ qDebug() << "停止GPS轮询定时器";
+ }
+
+ // 清空测试时间记录
+ testStartTimeMap.clear();
+ testDurationSecMap.clear();
// 重置产测状态变量
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;
+ touchTestPopupShown = false;
+ brightTestPopupShown = false;
+ deepsleepTestPopupShown = false;
isWaitingForUserConfirm = false;
keyTestStarted = false;
- audioTestPopupShown = false;
- audioPlaybackPopupShown = false;
// 重置按键测试状态
for (int i = 0; i < 4; i++) {
// 清空设备信息
ui->VerlineEdit->clear(); // 清空版本信息
- ui->IMEIlineEdit->clear(); // 清空IMEI
- ui->ICCIDlineEdit->clear(); // 清空ICCID
- ui->ModemVerlineEdit->clear(); // 清空调制解调器版本
- ui->PYVerlineEdit->clear(); // 清空python版本
// 重置弹窗状态
lcdTestPopupShown = false;
motorTestPopupShown = false;
+ touchTestPopupShown = false;
+ brightTestPopupShown = false;
+ deepsleepTestPopupShown = false;
isWaitingForUserConfirm = false;
keyTestStarted = false;
- audioTestPopupShown = false;
- audioPlaybackPopupShown = false;
// 不清除状态指示器,保留上次测试结果供查看
// 用户可以一边查看测试结果,一边执行老化测试
// 清空设备信息
ui->VerlineEdit->clear(); // 清空版本信息
- ui->IMEIlineEdit->clear(); // 清空IMEI
- ui->ICCIDlineEdit->clear(); // 清空ICCID
- ui->ModemVerlineEdit->clear(); // 清空调制解调器版本
- ui->PYVerlineEdit->clear(); // 清空python版本
// 重置弹窗状态
lcdTestPopupShown = false;
motorTestPopupShown = false;
+ touchTestPopupShown = false;
+ brightTestPopupShown = false;
+ deepsleepTestPopupShown = false;
isWaitingForUserConfirm = false;
keyTestStarted = false;
- audioTestPopupShown = false;
- audioPlaybackPopupShown = false;
// 不清除状态指示器,保留上次测试结果供查看
// 用户可以一边查看测试结果,一边执行恢复出厂操作
// 清空设备信息
ui->VerlineEdit->clear(); // 清空版本信息
- ui->IMEIlineEdit->clear(); // 清空IMEI
- ui->ICCIDlineEdit->clear(); // 清空ICCID
- ui->ModemVerlineEdit->clear(); // 清空调制解调器版本
- ui->PYVerlineEdit->clear(); // 清空python版本
// 重置弹窗状态
lcdTestPopupShown = false;
motorTestPopupShown = false;
+ touchTestPopupShown = false;
+ brightTestPopupShown = false;
+ deepsleepTestPopupShown = false;
isWaitingForUserConfirm = false;
keyTestStarted = false;
- audioTestPopupShown = false;
- audioPlaybackPopupShown = false;
// 不清除状态指示器,保留上次测试结果供查看
// 首先清除所有版本信息相关的LineEdit
ui->VerlineEdit->clear();
- ui->IMEIlineEdit->clear();
- ui->ModemVerlineEdit->clear();
- ui->PYVerlineEdit->clear();
- ui->ICCIDlineEdit->clear();
ui->factoryModeLineEdit->clear();
ui->factoryModeLineEdit->setStyleSheet(""); // 清除样式
QString portText = ui->portNameBox->currentText();
configManager.setTestConfig("portName", portText);
- // 保存音频测试参数
- configManager.setTestConfig("audioVolume", ui->audioVolumeLineEdit->text());
- if (ui->recordVolumelineEdit) {
- configManager.setTestConfig("audioLevelStandard", ui->recordVolumelineEdit->text().trimmed());
- }
-
// 保存期望版本信息
- configManager.setTestConfig("expectedModemVer", ui->expectedModemVerLineEdit->text());
- configManager.setTestConfig("expectedPYVer", ui->expectedPYVerLineEdit->text());
configManager.setTestConfig("expectedVer", ui->expectedVerLineEdit->text());
// 保存蓝牙测试参数
configManager.setTestConfig("bluetoothAddress", ui->bluetoothAddressLineEdit->text());
configManager.setTestConfig("bluetoothRSSI", ui->bluetoothRSSILineEdit->text());
+ // 保存录音测试参数
+ configManager.setTestConfig("audioVolume", ui->audioVolumeLineEdit->text());
+ configManager.setTestConfig("audioLevelStandard", ui->audioLevelStandardLineEdit->text());
+
// 保存测试项checkbox状态
configManager.setTestCheckbox("lcd", ui->checkBox_lcd->isChecked());
configManager.setTestCheckbox("vib", ui->checkBox_vib->isChecked());
configManager.setTestCheckbox("btn", ui->checkBox_btn->isChecked());
- configManager.setTestCheckbox("mic", ui->checkBox_mic->isChecked());
- configManager.setTestCheckbox("charge", ui->checkBox_charge->isChecked());
- configManager.setTestCheckbox("ntc", ui->checkBox_ntc->isChecked());
+ configManager.setTestCheckbox("tp", ui->checkBox_tp->isChecked());
+ configManager.setTestCheckbox("bright", ui->checkBox_bright->isChecked());
+ configManager.setTestCheckbox("deepsleep", ui->checkBox_deepsleep->isChecked());
+ configManager.setTestCheckbox("battery", ui->checkBox_battery->isChecked());
+ configManager.setTestCheckbox("leaklight", ui->checkBox_leaklight->isChecked());
// gsensor checkbox可能不存在,跳过
configManager.setTestCheckbox("bt", ui->checkBox_bt->isChecked());
- configManager.setTestCheckbox("4g", ui->checkBox_4g->isChecked());
+ configManager.setTestCheckbox("mic", ui->checkBox_mic->isChecked());
+ configManager.setTestCheckbox("sechip", ui->checkBox_sechip->isChecked());
+ configManager.setTestCheckbox("gps", ui->checkBox_gps->isChecked());
+
+ // 保存G-sensor XYZ变化标准(10秒)
+ configManager.setTestConfig("gsensorDeltaXMin", ui->gsensorDeltaXMinLineEdit->text());
+ configManager.setTestConfig("gsensorDeltaXMax", ui->gsensorDeltaXMaxLineEdit->text());
+ configManager.setTestConfig("gsensorDeltaYMin", ui->gsensorDeltaYMinLineEdit->text());
+ configManager.setTestConfig("gsensorDeltaYMax", ui->gsensorDeltaYMaxLineEdit->text());
+ configManager.setTestConfig("gsensorDeltaZMin", ui->gsensorDeltaZMinLineEdit->text());
+ configManager.setTestConfig("gsensorDeltaZMax", ui->gsensorDeltaZMaxLineEdit->text());
// 保存到文件
configManager.saveConfig();
}
}
- // 恢复音频测试参数
- QString audioVolume = configManager.getTestConfig("audioVolume", "2.0");
- ui->audioVolumeLineEdit->setText(audioVolume);
-
- QString audioLevelStandard = configManager.getTestConfig("audioLevelStandard", "中");
- if (ui->recordVolumelineEdit) {
- ui->recordVolumelineEdit->setText(audioLevelStandard);
- }
-
// 恢复期望版本信息
- ui->expectedModemVerLineEdit->setText(configManager.getTestConfig("expectedModemVer", ""));
- ui->expectedPYVerLineEdit->setText(configManager.getTestConfig("expectedPYVer", ""));
ui->expectedVerLineEdit->setText(configManager.getTestConfig("expectedVer", ""));
// 恢复蓝牙测试参数
ui->bluetoothAddressLineEdit->setText(configManager.getTestConfig("bluetoothAddress", ""));
ui->bluetoothRSSILineEdit->setText(configManager.getTestConfig("bluetoothRSSI", ""));
+ // 恢复录音测试参数
+ ui->audioVolumeLineEdit->setText(configManager.getTestConfig("audioVolume", "2.0"));
+ ui->audioLevelStandardLineEdit->setText(configManager.getTestConfig("audioLevelStandard", "中"));
+
// 恢复测试项checkbox状态
ui->checkBox_lcd->setChecked(configManager.getTestCheckbox("lcd", true));
ui->checkBox_vib->setChecked(configManager.getTestCheckbox("vib", true));
ui->checkBox_btn->setChecked(configManager.getTestCheckbox("btn", true));
- ui->checkBox_mic->setChecked(configManager.getTestCheckbox("mic", true));
- ui->checkBox_charge->setChecked(configManager.getTestCheckbox("charge", true));
- ui->checkBox_ntc->setChecked(configManager.getTestCheckbox("ntc", true));
+ ui->checkBox_tp->setChecked(configManager.getTestCheckbox("tp", true));
+ ui->checkBox_bright->setChecked(configManager.getTestCheckbox("bright", true));
+ ui->checkBox_deepsleep->setChecked(configManager.getTestCheckbox("deepsleep", true));
+ ui->checkBox_battery->setChecked(configManager.getTestCheckbox("battery", configManager.getTestCheckbox("charge", true)));
+ ui->checkBox_leaklight->setChecked(configManager.getTestCheckbox("leaklight", true));
// gsensor checkbox可能不存在,跳过
ui->checkBox_bt->setChecked(configManager.getTestCheckbox("bt", true));
- ui->checkBox_4g->setChecked(configManager.getTestCheckbox("4g", true));
- ui->checkBox_bt->setChecked(configManager.getTestCheckbox("bt", true));
- ui->checkBox_4g->setChecked(configManager.getTestCheckbox("4g", true));
+ ui->checkBox_mic->setChecked(configManager.getTestCheckbox("mic", true));
+ ui->checkBox_sechip->setChecked(configManager.getTestCheckbox("sechip", true));
+ ui->checkBox_gps->setChecked(configManager.getTestCheckbox("gps", true));
+
+ // 恢复G-sensor XYZ变化标准(10秒)
+ ui->gsensorDeltaXMinLineEdit->setText(configManager.getTestConfig("gsensorDeltaXMin", ""));
+ ui->gsensorDeltaXMaxLineEdit->setText(configManager.getTestConfig("gsensorDeltaXMax", ""));
+ ui->gsensorDeltaYMinLineEdit->setText(configManager.getTestConfig("gsensorDeltaYMin", ""));
+ ui->gsensorDeltaYMaxLineEdit->setText(configManager.getTestConfig("gsensorDeltaYMax", ""));
+ ui->gsensorDeltaZMinLineEdit->setText(configManager.getTestConfig("gsensorDeltaZMin", ""));
+ ui->gsensorDeltaZMaxLineEdit->setText(configManager.getTestConfig("gsensorDeltaZMax", ""));
qDebug() << "测试项checkbox状态已恢复";
return ui->checkBox_vib->isChecked();
} else if (testName == "btn" || testName == "key") {
return ui->checkBox_btn->isChecked();
+ } else if (testName == "tp" || testName == "touch") {
+ return ui->checkBox_tp->isChecked();
+ } else if (testName == "bright") {
+ return ui->checkBox_bright->isChecked();
+ } else if (testName == "deepsleep") {
+ return ui->checkBox_deepsleep->isChecked();
} else if (testName == "mic" || testName == "audio") {
return ui->checkBox_mic->isChecked();
- } else if (testName == "charge") {
- return ui->checkBox_charge->isChecked();
- } else if (testName == "ntc") {
- return ui->checkBox_ntc->isChecked();
+ } else if (testName == "charge" || testName == "ntc" || testName == "battery") {
+ return ui->checkBox_battery->isChecked();
} else if (testName == "gsensor") {
// gsensor checkbox可能不存在,默认启用
return true;
+ } else if (testName == "leaklight") {
+ return ui->checkBox_leaklight->isChecked();
} else if (testName == "bt" || testName == "bluetooth") {
return ui->checkBox_bt->isChecked();
- } else if (testName == "4g" || testName == "ppp") {
- return ui->checkBox_4g->isChecked();
+ } else if (testName == "sechip") {
+ return ui->checkBox_sechip->isChecked();
+ } else if (testName == "gps") {
+ return ui->checkBox_gps->isChecked();
}
return true; // 默认启用
}
// 根据当前测试步骤,推进到下一个启用的测试项
if (currentTestStep == TEST_LCD) {
- // LCD测试完成,检查马达测试
+ // LCD测试完成:按需求依次进入 触控 -> 亮度 -> 马达
+ if (isTestItemEnabled("tp")) {
+ currentTestStep = TEST_TOUCH;
+ qDebug() << "skipToNextEnabledTest: 推进到触控测试";
+ performTouchTest();
+ } else if (isTestItemEnabled("bright")) {
+ currentTestStep = TEST_BRIGHT;
+ qDebug() << "skipToNextEnabledTest: 推进到亮度测试";
+ performBrightTest();
+ } else {
+ // 触控/亮度都未启用,直接检查马达
+ if (isTestItemEnabled("motor")) {
+ currentTestStep = TEST_MOTOR;
+ qDebug() << "skipToNextEnabledTest: 推进到马达测试";
+ performMotorTest();
+ } else {
+ qDebug() << "马达测试未启用,跳过";
+ updateTestStatus("motor", STATUS_UNTESTED);
+ currentTestStep = TEST_MOTOR; // 推进到下一个测试步骤
+ skipToNextEnabledTest(); // 递归继续下一个
+ }
+ }
+ } else if (currentTestStep == TEST_TOUCH) {
+ // 触控测试完成:检查亮度 -> 马达
+ if (isTestItemEnabled("bright")) {
+ currentTestStep = TEST_BRIGHT;
+ qDebug() << "skipToNextEnabledTest: 推进到亮度测试";
+ performBrightTest();
+ } else {
+ // 直接检查马达
+ if (isTestItemEnabled("motor")) {
+ currentTestStep = TEST_MOTOR;
+ qDebug() << "skipToNextEnabledTest: 推进到马达测试";
+ performMotorTest();
+ } else {
+ qDebug() << "马达测试未启用,跳过";
+ updateTestStatus("motor", STATUS_UNTESTED);
+ currentTestStep = TEST_MOTOR;
+ skipToNextEnabledTest();
+ }
+ }
+ } else if (currentTestStep == TEST_BRIGHT) {
+ // 亮度测试完成:检查马达
if (isTestItemEnabled("motor")) {
currentTestStep = TEST_MOTOR;
qDebug() << "skipToNextEnabledTest: 推进到马达测试";
} else {
qDebug() << "马达测试未启用,跳过";
updateTestStatus("motor", STATUS_UNTESTED);
- currentTestStep = TEST_MOTOR; // 推进到下一个测试步骤
- skipToNextEnabledTest(); // 递归继续下一个
+ currentTestStep = TEST_MOTOR;
+ skipToNextEnabledTest();
}
} else if (currentTestStep == TEST_MOTOR) {
// 马达测试完成,检查按键测试
qDebug() << " isWaitingForUserConfirm:" << isWaitingForUserConfirm;
qDebug() << " motorTestPopupShown:" << motorTestPopupShown;
- if (isWaitingForUserConfirm && motorTestPopupShown) {
+ if (isWaitingForUserConfirm && (motorTestPopupShown || touchTestPopupShown || brightTestPopupShown)) {
qDebug() << "skipToNextEnabledTest: 马达测试正在等待用户确认,暂不推进到按键测试";
return; // 等待用户确认完成后再推进
}
skipToNextEnabledTest(); // 递归继续下一个
}
} else if (currentTestStep == TEST_KEY) {
- // 按键测试完成,检查录音测试
- if (isTestItemEnabled("audio")) {
+ // 按键测试完成:功耗测试 -> 录音 -> 电池
+ if (isTestItemEnabled("deepsleep")) {
+ currentTestStep = TEST_DEEPSLEEP;
+ qDebug() << "skipToNextEnabledTest: 推进到功耗测试";
+ performDeepsleepTest();
+ } else if (isTestItemEnabled("mic")) {
currentTestStep = TEST_AUDIO;
+ qDebug() << "skipToNextEnabledTest: 推进到录音测试";
performAudioTest();
+ } else if (isTestItemEnabled("battery")) {
+ currentTestStep = TEST_BATTERY;
+ performBatteryTest();
} else {
- qDebug() << "录音测试未启用,跳过";
- updateTestStatus("audio", STATUS_UNTESTED);
- currentTestStep = TEST_AUDIO; // 推进到下一个测试步骤
- skipToNextEnabledTest(); // 递归继续下一个
+ qDebug() << "功耗/录音/电池测试均未启用,跳过";
+ updateTestStatus("deepsleep", STATUS_UNTESTED);
+ updateTestStatus("mic", STATUS_UNTESTED);
+ updateTestStatus("battery", STATUS_UNTESTED);
+ currentTestStep = TEST_BATTERY;
+ skipToNextEnabledTest();
+ }
+ } else if (currentTestStep == TEST_DEEPSLEEP) {
+ if (isTestItemEnabled("mic")) {
+ currentTestStep = TEST_AUDIO;
+ qDebug() << "skipToNextEnabledTest: 推进到录音测试";
+ performAudioTest();
+ } else if (isTestItemEnabled("battery")) {
+ currentTestStep = TEST_BATTERY;
+ performBatteryTest();
+ } else {
+ qDebug() << "录音和电池测试均未启用,跳过";
+ updateTestStatus("mic", STATUS_UNTESTED);
+ updateTestStatus("battery", STATUS_UNTESTED);
+ currentTestStep = TEST_BATTERY;
+ skipToNextEnabledTest();
}
} else if (currentTestStep == TEST_AUDIO) {
- // 录音测试完成,检查电池测试(如果充电或ntc任一启用,都需要执行电池测试)
- if (isTestItemEnabled("charge") || isTestItemEnabled("ntc")) {
+ // 录音测试完成,检查电池测试
+ if (isTestItemEnabled("battery")) {
currentTestStep = TEST_BATTERY;
performBatteryTest();
} else {
qDebug() << "电池测试未启用,跳过";
updateTestStatus("battery", STATUS_UNTESTED);
- currentTestStep = TEST_BATTERY; // 推进到下一个测试步骤
- skipToNextEnabledTest(); // 递归继续下一个
+ currentTestStep = TEST_BATTERY;
+ skipToNextEnabledTest();
}
} else if (currentTestStep == TEST_BATTERY) {
// 电池测试完成,检查G-sensor测试
skipToNextEnabledTest(); // 递归继续下一个
}
} else if (currentTestStep == TEST_GSENSOR) {
- // G-sensor测试完成,检查蓝牙测试
+ // G-sensor测试完成,检查漏光测试
+ if (isTestItemEnabled("leaklight")) {
+ currentTestStep = TEST_LEAKLIGHT;
+ performLeaklightTest();
+ } else {
+ qDebug() << "漏光测试未启用,跳过";
+ updateTestStatus("leaklight", STATUS_UNTESTED);
+ currentTestStep = TEST_LEAKLIGHT;
+ skipToNextEnabledTest();
+ }
+ } else if (currentTestStep == TEST_LEAKLIGHT) {
+ // 漏光测试完成,检查蓝牙测试
if (isTestItemEnabled("bluetooth")) {
currentTestStep = TEST_BLUETOOTH;
performBluetoothTest();
skipToNextEnabledTest(); // 递归继续下一个
}
} else if (currentTestStep == TEST_BLUETOOTH) {
- // 蓝牙测试完成,检查4G测试
- if (isTestItemEnabled("ppp")) {
- currentTestStep = TEST_PPP_INIT;
- perform4GTest();
+ // 蓝牙测试完成,检查SE芯片测试
+ if (isTestItemEnabled("sechip")) {
+ currentTestStep = TEST_SECHIP;
+ performSeChipTest();
} else {
- qDebug() << "4G测试未启用,跳过";
- updateTestStatus("ppp", STATUS_UNTESTED);
- // 所有测试完成
- currentTestStep = TEST_COMPLETED;
- isProductionTestRunning = false;
- QString fileName = saveTestRecord();
- showFinalTestResult();
+ qDebug() << "SE芯片测试未启用,跳过";
+ updateTestStatus("sechip", STATUS_UNTESTED);
+ currentTestStep = TEST_SECHIP;
+ skipToNextEnabledTest();
}
+ } else if (currentTestStep == TEST_SECHIP) {
+ // SE芯片测试完成,检查GPS测试
+ if (isTestItemEnabled("gps")) {
+ currentTestStep = TEST_GPS;
+ performGpsTest();
+ } else {
+ qDebug() << "GPS测试未启用,跳过";
+ updateTestStatus("gps", STATUS_UNTESTED);
+ currentTestStep = TEST_GPS;
+ skipToNextEnabledTest();
+ }
+ } else if (currentTestStep == TEST_GPS) {
+ // GPS测试完成,所有测试完成
+ currentTestStep = TEST_COMPLETED;
+ isProductionTestRunning = false;
+ saveTestRecord();
+ showFinalTestResult();
} else {
qDebug() << "未知的测试步骤,无法推进";
}
return;
}
- // 检查IMEI和ICCID
- QString imei = ui->IMEIlineEdit->text().trimmed();
- QString iccid = ui->ICCIDlineEdit->text().trimmed();
-
- if (imei.isEmpty() || imei == "未获取" || iccid.isEmpty() || iccid == "未获取") {
- qDebug() << "IMEI或ICCID未获取,跳过保存日志。IMEI:" << imei << "ICCID:" << iccid;
- return;
- }
-
// 创建日志目录
QString appPath = QCoreApplication::applicationDirPath();
QString logsDir = appPath + "/产测记录/logs";
// 生成日志文件名
QDateTime now = QDateTime::currentDateTime();
- QString fileName = QString("%1_%2_%3_%4_UI日志.log")
+ QString fileName = QString("%1_%2_UI日志.log")
.arg(now.toString("yyyyMMdd"))
- .arg(now.toString("hhmmss"))
- .arg(imei)
- .arg(iccid);
+ .arg(now.toString("hhmmss"));
QString filePath = logsDir + "/" + fileName;
QTextStream stream(&logFile);
stream.setCodec("UTF-8");
stream << QString("=== UI日志保存时间: %1 ===\n").arg(now.toString("yyyy-MM-dd hh:mm:ss"));
- stream << QString("IMEI: %1\n").arg(imei);
- stream << QString("ICCID: %1\n").arg(iccid);
stream << "========================================\n";
stream << logContent;
logFile.close();
QString fullLogContent = ui->logtextEdit->toPlainText();
if (!fullLogContent.trimmed().isEmpty()) {
// 生成完整日志文件名(加full后缀)
- QString fullFileName = QString("%1_%2_%3_%4_UI日志full.log")
+ QString fullFileName = QString("%1_%2_UI日志full.log")
.arg(now.toString("yyyyMMdd"))
- .arg(now.toString("hhmmss"))
- .arg(imei)
- .arg(iccid);
+ .arg(now.toString("hhmmss"));
QString fullFilePath = logsDir + "/" + fullFileName;
QTextStream fullStream(&fullLogFile);
fullStream.setCodec("UTF-8");
fullStream << QString("=== 完整日志保存时间: %1 ===\n").arg(now.toString("yyyy-MM-dd hh:mm:ss"));
- fullStream << QString("IMEI: %1\n").arg(imei);
- fullStream << QString("ICCID: %1\n").arg(iccid);
fullStream << "========================================\n";
fullStream << fullLogContent;
fullLogFile.close();
// 获取当前时间
QDateTime now = QDateTime::currentDateTime();
- // 获取IMEI和ICCID(可能还没有,使用"未知"作为占位符)
- QString imei = ui->IMEIlineEdit->text().trimmed();
- QString iccid = ui->ICCIDlineEdit->text().trimmed();
-
- if (imei.isEmpty()) {
- imei = "未知";
- }
- if (iccid.isEmpty()) {
- iccid = "未知";
- }
-
// 创建日志目录(在CSV记录目录下的logs子目录)
QString appPath = QCoreApplication::applicationDirPath();
QString logsDir = appPath + "/产测记录/logs";
dir.mkpath(logsDir);
}
- // 生成文件名:yyyymmdd_hhmmss_imei_iccid.log
- QString fileName = QString("%1_%2_%3_%4.log")
+ // 生成文件名:yyyymmdd_hhmmss.log
+ QString fileName = QString("%1_%2.log")
.arg(now.toString("yyyyMMdd"))
- .arg(now.toString("hhmmss"))
- .arg(imei)
- .arg(iccid);
+ .arg(now.toString("hhmmss"));
testLogFilePath = logsDir + "/" + fileName;
// 写入日志文件头
*testLogStream << QString("=== 测试开始时间: %1 ===\n").arg(now.toString("yyyy-MM-dd hh:mm:ss"));
- *testLogStream << QString("IMEI: %1\n").arg(imei);
- *testLogStream << QString("ICCID: %1\n").arg(iccid);
*testLogStream << "========================================\n";
testLogStream->flush();
// 使用设备信息重命名日志文件
void MainWindow::renameLogFileWithDeviceInfo()
{
- // 如果日志文件未打开或路径为空,不处理
- if (!testLogFile || testLogFilePath.isEmpty()) {
- return;
- }
-
- // 获取IMEI和ICCID
- QString imei = ui->IMEIlineEdit->text().trimmed();
- QString iccid = ui->ICCIDlineEdit->text().trimmed();
-
- // 如果IMEI和ICCID都还是"未知"或为空,不重命名
- if (imei.isEmpty() || imei == "未知" || iccid.isEmpty() || iccid == "未知") {
- return;
- }
-
- // 从当前文件名中提取时间部分
- QFileInfo fileInfo(testLogFilePath);
- QString baseName = fileInfo.baseName();
- QStringList parts = baseName.split("_");
-
- if (parts.size() >= 2) {
- QString datePart = parts[0]; // yyyymmdd
- QString timePart = parts[1]; // hhmmss
-
- // 生成新文件名
- QString newFileName = QString("%1_%2_%3_%4.log")
- .arg(datePart)
- .arg(timePart)
- .arg(imei)
- .arg(iccid);
-
- QString newFilePath = fileInfo.absolutePath() + "/" + newFileName;
-
- // 如果新文件名与当前文件名不同,重命名
- if (newFilePath != testLogFilePath) {
- // 先关闭文件
- if (testLogFile->isOpen()) {
- testLogFile->close();
- }
-
- // 重命名文件
- QFile oldFile(testLogFilePath);
- if (oldFile.rename(newFilePath)) {
- testLogFilePath = newFilePath;
- qDebug() << "日志文件已重命名:" << newFilePath;
-
- // 重新打开文件(追加模式)
- if (testLogFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
- testLogStream = new QTextStream(testLogFile);
- testLogStream->setCodec("UTF-8");
- } else {
- qDebug() << "重命名后无法重新打开日志文件:" << newFilePath;
- delete testLogFile;
- testLogFile = nullptr;
- testLogStream = nullptr;
- }
- } else {
- qDebug() << "无法重命名日志文件:" << oldFile.errorString();
- // 重新打开原文件
- if (testLogFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
- testLogStream = new QTextStream(testLogFile);
- testLogStream->setCodec("UTF-8");
- }
- }
- }
- }
-}
-
-// ICCID输入框文本改变时触发
-void MainWindow::onICCIDLineEditTextChanged(const QString& text)
-{
- refreshICCIDCodes();
-}
-
-// IMEI输入框文本改变时触发
-void MainWindow::onIMEILineEditTextChanged(const QString& text)
-{
- refreshIMEICodes();
-}
-
-// ICCID复选框状态改变时触发
-void MainWindow::onICCIDCheckBoxStateChanged(int state)
-{
- Q_UNUSED(state);
- refreshICCIDCodes();
-}
-
-// IMEI复选框状态改变时触发
-void MainWindow::onIMEICheckBoxStateChanged(int state)
-{
- Q_UNUSED(state);
- refreshIMEICodes();
-}
-
-// 刷新ICCID的二维码和条形码
-void MainWindow::refreshICCIDCodes()
-{
- QString text = ui->ICCIDlineEdit->text().trimmed();
- if (ui->checkBox_iccid->isChecked() && !text.isEmpty()) {
- qDebug() << "刷新ICCID二维码和条形码:" << text;
- generateQRCode(text, ui->graphicsView_iccid_qr);
- generateBarcode(text, ui->graphicsView_iccid_barcode);
- } else {
- // 如果未选中或文本为空,清空显示
- if (ui->graphicsView_iccid_qr->scene()) {
- ui->graphicsView_iccid_qr->scene()->clear();
- }
- if (ui->graphicsView_iccid_barcode->scene()) {
- ui->graphicsView_iccid_barcode->scene()->clear();
- }
- }
-}
-
-// 刷新IMEI的二维码和条形码
-void MainWindow::refreshIMEICodes()
-{
- QString text = ui->IMEIlineEdit->text().trimmed();
- if (ui->checkBox_imei->isChecked() && !text.isEmpty()) {
- qDebug() << "刷新IMEI二维码和条形码:" << text;
- generateQRCode(text, ui->graphicsView_imei_qr);
- generateBarcode(text, ui->graphicsView_imei_barcode);
- } else {
- // 如果未选中或文本为空,清空显示
- if (ui->graphicsView_imei_qr->scene()) {
- ui->graphicsView_imei_qr->scene()->clear();
- }
- if (ui->graphicsView_imei_barcode->scene()) {
- ui->graphicsView_imei_barcode->scene()->clear();
- }
- }
-}
-
-// 生成二维码
-void MainWindow::generateQRCode(const QString& text, QGraphicsView* view)
-{
- if (!view || text.isEmpty()) {
- return;
- }
-
- // 获取视图的实际可用尺寸(减去边距)
- QSize viewSize = view->size();
- int margin = 10;
- int availableSize = qMin(viewSize.width(), viewSize.height()) - 2 * margin;
- if (availableSize < 100) {
- availableSize = 200; // 最小尺寸
- }
-
- // 创建二维码图片,使用视图的实际尺寸
- QPixmap qrPixmap = QRCodeBarcodeGenerator::createQRCodePixmap(text, availableSize);
-
- // 清空场景并添加二维码图片
- if (!view->scene()) {
- view->setScene(new QGraphicsScene(this));
- }
- view->scene()->clear();
- QGraphicsPixmapItem* item = view->scene()->addPixmap(qrPixmap);
-
- // 设置场景大小
- view->scene()->setSceneRect(0, 0, qrPixmap.width(), qrPixmap.height());
-
- // 铺满窗口,保持宽高比
- view->fitInView(item, Qt::KeepAspectRatio);
-
- // 确保视图更新
- view->update();
-}
-
-// 窗口大小改变时刷新二维码和条形码
-void MainWindow::resizeEvent(QResizeEvent* event)
-{
- QMainWindow::resizeEvent(event);
-
- // 延迟刷新,确保窗口大小已经更新
- QTimer::singleShot(100, this, [this]() {
- refreshICCIDCodes();
- refreshIMEICodes();
- });
-}
-
-// 生成条形码
-void MainWindow::generateBarcode(const QString& text, QGraphicsView* view)
-{
- if (!view || text.isEmpty()) {
- return;
- }
-
- // 获取视图的实际可用尺寸(减去边距)
- QSize viewSize = view->size();
- int margin = 10;
- int availableWidth = viewSize.width() - 2 * margin;
- int availableHeight = viewSize.height() - 2 * margin;
-
- if (availableWidth < 200) {
- availableWidth = 300; // 最小宽度
- }
- if (availableHeight < 50) {
- availableHeight = 100; // 最小高度
- }
-
- // 创建条形码图片,使用视图的实际尺寸
- QPixmap barcodePixmap = QRCodeBarcodeGenerator::createBarcodePixmap(text, availableWidth, availableHeight);
-
- // 清空场景并添加条形码图片
- if (!view->scene()) {
- view->setScene(new QGraphicsScene(this));
- }
- view->scene()->clear();
- QGraphicsPixmapItem* item = view->scene()->addPixmap(barcodePixmap);
-
- // 设置场景大小
- view->scene()->setSceneRect(0, 0, barcodePixmap.width(), barcodePixmap.height());
-
- // 铺满窗口,保持宽高比
- view->fitInView(item, Qt::KeepAspectRatio);
-
- // 确保视图更新
- view->update();
+ // 已移除 IMEI/ICCID 相关功能,不再按设备信息重命名日志
+ return;
}