From: xue <2144439972@qq.com> Date: Mon, 13 Apr 2026 01:57:34 +0000 (+0800) Subject: FD272_factory_V1.6 X-Git-Url: http://git.snicker.com.cn/sitemap.xml?a=commitdiff_plain;h=48ef9c6eb49b5d7614d09b786f2d4e8e5fff7f46;p=mirrors%2Ffactory_tool.git FD272_factory_V1.6 --- diff --git a/mainwindow.cpp b/mainwindow.cpp index 27f475c..a6c35d3 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -80,7 +80,6 @@ MainWindow::MainWindow(QWidget *parent) lcdBacklightOn = false; // 初始化LCD背光状态为关闭 keyTestStarted = false; keyTestDialog = nullptr; - keyRotateDetected = false; audioTestRoundIndex = 0; audioTestAnyPass = false; audioTestAwaitingMicLevel = false; @@ -144,6 +143,7 @@ MainWindow::MainWindow(QWidget *parent) gSensorErrorDetected = false; gSensorAnySample = false; gSensorAllSamplesInRange = true; + gSensorValidSampleCount = 0; gSensorStartX = 0.0; gSensorStartY = 0.0; gSensorStartZ = 0.0; @@ -613,7 +613,7 @@ void MainWindow::readSerialData() } // 检测按键测试结果(用于产测) - if (line.contains("fac:id") || line.contains("testPresenter::OnRotate")) { + if (line.contains("fac:id")) { checkKeyTestResult(line); } @@ -730,7 +730,6 @@ void MainWindow::on_ProductionTestButton_clicked() // 开始产测流程 isProductionTestRunning = true; - // 根据checkbox决定从哪个测试开始 if (isTestItemEnabled("lcd")) { currentTestStep = TEST_LCD; currentLcdColor = 1; // 从红色开始 @@ -738,19 +737,14 @@ void MainWindow::on_ProductionTestButton_clicked() ui->statusbar->showMessage("开始产测流程...", 2000); qDebug() << "开始产测流程"; - // ui->ProductionTestButton->setText("停止产测"); - - // 开始LCD测试 performLcdTest(); } else { - // LCD未启用,跳过到下一个启用的测试 - currentTestStep = TEST_LCD; // 先设置为LCD,然后skipToNextEnabledTest会跳过 - currentLcdColor = 1; // 初始化LCD颜色 + currentTestStep = TEST_LCD; + currentLcdColor = 1; ui->statusbar->showMessage("开始产测流程...", 2000); qDebug() << "开始产测流程,LCD测试未启用,跳过"; - // 跳过LCD测试,进入下一个启用的测试 skipToNextEnabledTest(); } } @@ -1708,7 +1702,7 @@ void MainWindow::showBrightTestConfirmDialog() } } -// 执行功耗测试(AT^TESTJUMP=DEEPSLEEP,进入后由人工确认) +// 执行功耗测试(功耗前先 AT^PMRMVOTE 取消投票,再 AT^TESTJUMP=DEEPSLEEP,进入后由人工确认) void MainWindow::performDeepsleepTest() { if (!isProductionTestRunning || currentTestStep != TEST_DEEPSLEEP) { @@ -1730,9 +1724,9 @@ void MainWindow::performDeepsleepTest() ui->statusbar->showMessage("功耗测试:将进入深度睡眠测试界面,请等待确认弹窗", 3000); if (serial && serial->isOpen()) { - ui->recvTextEdit->append(">>> 发送指令: AT^ENTERTESTVIEW (进入产测界面)"); - serial->write("AT^ENTERTESTVIEW\r\n"); - qDebug() << "发送指令: AT^ENTERTESTVIEW (功耗测试前)"; + ui->recvTextEdit->append(">>> 发送指令: AT^PMRMVOTE (取消投票,功耗测试前)"); + serial->write("AT^PMRMVOTE\r\n"); + qDebug() << "发送指令: AT^PMRMVOTE (功耗测试前)"; } QTimer::singleShot(300, this, [this]() { @@ -1742,27 +1736,39 @@ void MainWindow::performDeepsleepTest() if (!serial || !serial->isOpen()) { return; } - ui->recvTextEdit->append(">>> 发送指令: AT^TESTJUMP=DEEPSLEEP"); - serial->write("AT^TESTJUMP=DEEPSLEEP\r\n"); - qDebug() << "发送指令: AT^TESTJUMP=DEEPSLEEP"; + ui->recvTextEdit->append(">>> 发送指令: AT^ENTERTESTVIEW (进入产测界面)"); + serial->write("AT^ENTERTESTVIEW\r\n"); + qDebug() << "发送指令: AT^ENTERTESTVIEW (功耗测试前)"; - // 仅进入界面不会真正进深睡,需再发 FACTORYDEEPSLEEPENTER - QTimer::singleShot(400, this, [this]() { + QTimer::singleShot(300, 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"); + ui->recvTextEdit->append(">>> 发送指令: AT^TESTJUMP=DEEPSLEEP"); + serial->write("AT^TESTJUMP=DEEPSLEEP\r\n"); + qDebug() << "发送指令: AT^TESTJUMP=DEEPSLEEP"; - QTimer::singleShot(500, this, [this]() { - if (isProductionTestRunning && currentTestStep == TEST_DEEPSLEEP) { - showDeepsleepTestConfirmDialog(); + // 仅进入界面不会真正进深睡,需再发 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(); + } + }); }); }); }); @@ -1854,14 +1860,13 @@ void MainWindow::performKeyTest() qDebug() << "开始按键测试"; ui->recvTextEdit->append("========== 开始按键测试(TESTJUMP=KEY) =========="); updateTestStatus("key", STATUS_TESTING); - ui->statusbar->showMessage("按键测试中,请按键0并执行旋转动作", 10000); + ui->statusbar->showMessage("按键测试中,请按下按键 0", 10000); - // 重置按键测试状态(仅按键0 + 旋转) + // 重置按键测试状态(仅按键 0) keyTestStarted = true; for (int i = 0; i < 4; i++) { keyTestStatus[i] = 0; } - keyRotateDetected = false; // 先跳转产测主界面,再跳KEY测试界面 if (serial && serial->isOpen()) { @@ -1881,28 +1886,25 @@ void MainWindow::performKeyTest() // 创建按键测试弹窗 keyTestDialog = new QDialog(this); keyTestDialog->setWindowTitle("按键测试"); - keyTestDialog->setFixedSize(460, 250); + keyTestDialog->setFixedSize(400, 220); keyTestDialog->setModal(true); // 设置布局 QVBoxLayout *layout = new QVBoxLayout(keyTestDialog); - QLabel *instructionLabel = new QLabel("请检测按键0与旋转事件;检测到后按钮会变绿"); + QLabel *instructionLabel = new QLabel("请按下按键 0;检测到后下方按钮会变绿"); layout->addWidget(instructionLabel); - // 仅保留按键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[1] = nullptr; keyButtons[2] = nullptr; keyButtons[3] = nullptr; indicators->addWidget(keyButtons[0]); - indicators->addWidget(keyButtons[1]); + indicators->addStretch(); layout->addLayout(indicators); // 添加测试结果按钮 @@ -2024,38 +2026,17 @@ void MainWindow::checkKeyTestResult(const QString& data) keyButtons[0]->setText("按键 0 ✓"); } ui->statusbar->showMessage("检测到按键 0", 1000); + // 仅按键 0:检测到后自动结束本项 + QTimer::singleShot(500, [this]() { + if (keyTestDialog && isProductionTestRunning && currentTestStep == TEST_KEY) { + keyTestDialog->accept(); + updateTestStatus("key", STATUS_SUCCESS); + keyTestStarted = false; + skipToNextEnabledTest(); + } + }); } } - - // 旋转事件: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(); - } - }); - } } // 显示按键测试确认对话框 @@ -2163,25 +2144,26 @@ void MainWindow::checkBuildVerResult(const QString& data) qDebug() << "发送AT^ENTERTESTVIEW (进入产测界面)"; } - // 初始化完成后,切换到LCD测试阶段(如果启用) + // 初始化完成后,切换到 LCD(若启用);功耗测试在 GPS 之后 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 && currentTestStep == TEST_LCD) { - qDebug() << "开始LCD测试流程"; - performLcdTest(); - } - }); - } else { - qDebug() << "AT^PMADDVOTE指令发送完成,LCD测试未启用,跳过"; - ui->statusbar->showMessage("初始化完成,LCD测试未启用,跳过", 2000); - currentTestStep = TEST_LCD; - skipToNextEnabledTest(); - } + if (!isProductionTestRunning) { + return; + } + if (isTestItemEnabled("lcd")) { + qDebug() << "AT^PMADDVOTE指令发送完成,开始LCD测试"; + ui->statusbar->showMessage("初始化完成,开始LCD测试", 2000); + currentTestStep = TEST_LCD; + QTimer::singleShot(1000, this, [this]() { + if (isProductionTestRunning && currentTestStep == TEST_LCD) { + qDebug() << "开始LCD测试流程"; + performLcdTest(); + } + }); + } else { + qDebug() << "AT^PMADDVOTE指令发送完成,LCD测试未启用,跳过"; + ui->statusbar->showMessage("初始化完成,LCD测试未启用,跳过", 2000); + currentTestStep = TEST_LCD; + skipToNextEnabledTest(); } }); } @@ -2937,9 +2919,6 @@ void MainWindow::checkBatteryTestResult(const QString& data) int charge = -1; // -1表示未检测到充电状态 bool voltageFound = false; bool chargeFound = false; - // 温度正常范围(可根据实际电池规格调整,此处为常见NTC有效范围) - const double MIN_NORMAL_TEMP = 0.0; // 最低正常温度:0℃ - const double MAX_NORMAL_TEMP = 60.0; // 最高正常温度:60℃ // 尝试多种fac:voltage格式 if (facVoltagePattern1.indexIn(data) != -1) { @@ -3001,6 +2980,24 @@ void MainWindow::checkBatteryTestResult(const QString& data) qDebug() << "使用备用charge格式3解析成功(charge 格式)"; } } + + // 仅有 charge 字段、无电压行时:charge==1 也直接通过 + if (isTestItemEnabled("battery") && chargeFound && charge == 1 && !voltageFound) { + if (testTimeoutTimer->isActive()) { + testTimeoutTimer->stop(); + qDebug() << "电池测试收到响应,停止超时检测"; + } + ui->recvTextEdit->append(">>> 电池测试通过:设备正在充电 (charge=1)"); + qDebug() << "电池测试通过:仅依据充电状态(无电压字段)"; + updateTestStatus("charge", STATUS_SUCCESS); + updateTestStatus("ntc", STATUS_SUCCESS); + updateTestStatus("battery", STATUS_SUCCESS); + ui->statusbar->showMessage("电池测试通过(正在充电)", 2000); + if (isProductionTestRunning && currentTestStep == TEST_BATTERY) { + skipToNextEnabledTest(); + } + return; + } // 详细日志输出 if (voltageFound) { @@ -3028,228 +3025,70 @@ void MainWindow::checkBatteryTestResult(const QString& data) } if (voltageFound) { - // 停止超时检测 if (testTimeoutTimer->isActive()) { testTimeoutTimer->stop(); qDebug() << "电池测试收到响应,停止超时检测"; } - // 充电状态检查(根据checkbox决定是否判定) - // 注意:充电状态每次都解析,但只有charge checkbox选中时才用充电状态来判断是否通过 - bool chargeCheckEnabled = isTestItemEnabled("battery"); - bool ntcCheckEnabled = isTestItemEnabled("battery"); - - // 拼接检测结果日志(包含所有已获取的字段) - // 注意:充电状态和温度数据每次都解析并记录,无论checkbox是否选中 QString resultLog = QString("检测到电池电压:%1V").arg(voltage); - if (percent > 0) resultLog += QString(", 电量:%1%").arg(percent); + if (percent > 0) { + resultLog += QString(", 电量:%1%").arg(percent); + } if (temp != -1.0) { resultLog += QString(", 温度:%1℃").arg(temp); - // 如果NTC未启用,在日志中说明温度数据已解析但不用于判定 - if (!ntcCheckEnabled) { - resultLog += "(NTC未启用,不用于判定)"; - } } if (chargeFound && charge != -1) { - QString chargeStatusText; - if (charge == 1) { - chargeStatusText = "充电中"; - } else if (charge == 0) { - chargeStatusText = "未充电"; - } else { - chargeStatusText = QString("未知值(%1)").arg(charge); - } + const QString chargeStatusText = (charge == 1) ? "充电中" + : (charge == 0) ? "未充电" : QString("未知值(%1)").arg(charge); resultLog += QString(", 充电状态:%1").arg(chargeStatusText); - // 如果充电检查未启用,在日志中说明充电状态已解析但不用于判定 - if (!chargeCheckEnabled) { - resultLog += "(充电检查未启用,不用于判定)"; - } - } else if (chargeFound && charge == -1) { - resultLog += ", 充电状态:解析失败"; - qDebug() << "警告: charge字段存在但值为-1,可能解析有问题"; } else { resultLog += ", 充电状态:未检测到"; } qDebug() << resultLog; ui->recvTextEdit->append(QString(">>> 电池测试: %1").arg(resultLog)); - - bool chargePassed = true; // 默认通过(如果未启用检查) - bool ntcPassed = true; // 默认通过(如果未启用检查) - - // 充电状态每次都解析(已经在上面解析了),这里只判断是否满足条件 - if (chargeCheckEnabled) { - // charge checkbox选中,需要判断充电状态 - if (chargeFound && charge == 1) { - // 充电中,通过 - chargePassed = true; - updateTestStatus("charge", STATUS_SUCCESS); - qDebug() << "充电检查通过:设备正在充电 (charge=1)"; - ui->recvTextEdit->append(">>> 充电检查通过:设备正在充电"); - } else if (chargeFound && charge == 0) { - // 未充电,不通过 - chargePassed = false; - updateTestStatus("charge", STATUS_FAILED); - qDebug() << "充电检查失败:设备未充电 (charge=0)"; - ui->statusbar->showMessage("充电检查失败 - 设备未充电", 2000); - ui->recvTextEdit->append(">>> 充电检查失败:设备未充电"); - - // 显示充电失败对话框(用户点确认会在此函数内调用skipToNextEnabledTest并返回) - showBatteryChargeFailDialog(); - return; // 充电失败后不再继续后续NTC等逻辑,已由弹窗处理 - } else if (chargeFound && charge != -1 && charge != 0 && charge != 1) { - // 检测到charge字段但值不是0或1,可能是异常值 - qDebug() << QString("充电检查:检测到异常charge值 %1,期望0或1").arg(charge); - ui->recvTextEdit->append(QString(">>> 警告: 充电状态值异常: %1 (期望0或1)").arg(charge)); - QMessageBox msgBox(this); - msgBox.setWindowTitle("充电状态异常"); - msgBox.setText(QString("检测到异常的充电状态值: %1").arg(charge)); - msgBox.setInformativeText("期望值为0(未充电)或1(充电中),\n但检测到的值不符合预期,是否继续测试?"); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::Yes); - msgBox.setIcon(QMessageBox::Warning); - - int ret = msgBox.exec(); - if (ret == QMessageBox::No) { - updateTestStatus("charge", STATUS_FAILED); - chargePassed = false; - } else { - // 用户选择继续,认为充电检查通过 - chargePassed = true; - updateTestStatus("charge", STATUS_SUCCESS); - } - } else { - // 未检测到充电状态(chargeFound=false 或 charge=-1),如果启用了充电检查,需要提示 - qDebug() << "充电检查:未检测到充电状态信息"; - ui->recvTextEdit->append(">>> 警告: 未检测到充电状态信息"); - QMessageBox msgBox(this); - msgBox.setWindowTitle("充电状态检查提醒"); - msgBox.setText("未检测到设备的充电状态信息"); - msgBox.setInformativeText("系统未能检测到设备的充电状态信息,\n但电压检测正常,是否继续测试?"); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::Yes); - msgBox.setIcon(QMessageBox::Warning); - - int ret = msgBox.exec(); - if (ret == QMessageBox::No) { - updateTestStatus("charge", STATUS_FAILED); - chargePassed = false; - } else { - // 用户选择继续,认为充电检查通过 - chargePassed = true; - updateTestStatus("charge", STATUS_SUCCESS); - } - } - } else { - // 充电检查未启用,不判定(但充电状态仍然已解析) - chargePassed = true; - QString chargeStatusDesc = "未检测到"; - if (chargeFound) { - if (charge == 1) { - chargeStatusDesc = "充电中"; - } else if (charge == 0) { - chargeStatusDesc = "未充电"; - } else { - chargeStatusDesc = QString("值%1").arg(charge); - } - } - qDebug() << QString("充电检查未启用,充电状态已解析: %1(但不用于判定)").arg(chargeStatusDesc); - } - // NTC温度检查(根据checkbox决定是否判定) - // 注意:温度数据每次都解析,但只有NTC checkbox选中时才用温度>0来判断是否通过 - // 电压范围:3.3V-4.6V(支持充满电时4.5V+的测量值) - bool isVoltageNormal = (voltage >= 3.3 && voltage <= 4.6); - bool isTempNormal = true; // 默认温度正常(未检测到温度时不影响结果) - - // 温度数据每次都解析(已经在上面解析了),这里只判断是否满足条件 - if (ntcCheckEnabled) { - // NTC checkbox选中,需要判断温度是否>0 - if (temp != -1.0) { - // 判断条件:temp > 0.0 - isTempNormal = (temp > 0.0); - if (!isTempNormal) { - ntcPassed = false; - qDebug() << QString("NTC检查失败:温度 %1℃ 不满足要求(需要 > 0℃)").arg(temp); - updateTestStatus("ntc", STATUS_FAILED); - } else { - ntcPassed = true; - updateTestStatus("ntc", STATUS_SUCCESS); - qDebug() << QString("NTC检查通过:温度 %1℃ 满足要求(> 0℃)").arg(temp); - } - } else { - // 未检测到温度,如果启用了NTC检查,需要提示 - qDebug() << "NTC检查:未检测到温度信息"; - QMessageBox msgBox(this); - msgBox.setWindowTitle("NTC温度检查提醒"); - msgBox.setText("未检测到设备的温度信息"); - msgBox.setInformativeText("系统未能检测到设备的温度信息,\n但电压检测正常,是否继续测试?"); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::Yes); - msgBox.setIcon(QMessageBox::Warning); - - int ret = msgBox.exec(); - if (ret == QMessageBox::No) { - updateTestStatus("ntc", STATUS_FAILED); - return; - } - // 用户选择继续,认为NTC检查通过 - ntcPassed = true; - updateTestStatus("ntc", STATUS_SUCCESS); - } - } else { - // NTC检查未启用,不判定(但温度数据仍然已解析) - ntcPassed = true; - qDebug() << QString("NTC检查未启用,温度数据已解析: %1℃(但不用于判定)").arg(temp != -1.0 ? QString::number(temp) : "未检测到"); + if (chargeFound && charge == 0) { + updateTestStatus("charge", STATUS_FAILED); + qDebug() << "充电检查失败:设备未充电 (charge=0)"; + ui->statusbar->showMessage("充电检查失败 - 设备未充电", 2000); + ui->recvTextEdit->append(">>> 充电检查失败:设备未充电"); + showBatteryChargeFailDialog(); + return; } - // 更新充电状态(用于判定,不显示在UI) - // charge和ntc的状态用于最终判定,但不单独显示 - // 如果充电检查失败,已经在上面return了,这里只记录状态用于判定 - - // 最终判断:只有启用的检查项都通过,才认为电池测试通过 - bool allChecksPassed = chargePassed && ntcPassed && isVoltageNormal; - - if (allChecksPassed) { - QString successMsg = QString("电池测试通过 - 电压: %1V").arg(voltage); - if (charge == 1 && chargeCheckEnabled) { - successMsg += ", 充电中"; - } - if (temp != -1.0 && ntcCheckEnabled) { - successMsg += QString(", 温度: %1℃").arg(temp); - } - if (percent > 0) successMsg += QString(", 电量: %1%").arg(percent); - - qDebug() << successMsg; - ui->statusbar->showMessage(successMsg, 2000); - updateTestStatus("battery", STATUS_SUCCESS); - } else { - QString failMsg = "电池测试失败 - "; - QStringList failReasons; - if (!chargePassed && chargeCheckEnabled) { - failReasons << "充电检查失败"; - } - if (!ntcPassed && ntcCheckEnabled) { - failReasons << "NTC温度检查失败"; - } - if (!isVoltageNormal) { - failReasons << QString("电压异常: %1V(正常范围3.3V-4.6V)").arg(voltage); - } - failMsg += failReasons.join(","); + if (chargeFound && charge != 0 && charge != 1) { + updateTestStatus("charge", STATUS_FAILED); + updateTestStatus("battery", STATUS_FAILED); + const QString msg = QString("电池测试失败:充电状态值异常 (%1),期望0或1").arg(charge); + qDebug() << msg; + ui->recvTextEdit->append(">>> " + msg); + ui->statusbar->showMessage(msg, 3000); + return; + } - qDebug() << failMsg; - ui->statusbar->showMessage(failMsg, 2000); + if (!chargeFound) { + updateTestStatus("charge", STATUS_UNTESTED); updateTestStatus("battery", STATUS_FAILED); + const QString msg = "电池测试失败:未检测到充电状态信息"; + qDebug() << msg; + ui->recvTextEdit->append(">>> " + msg); + ui->statusbar->showMessage(msg, 3000); + return; } - // 电池测试完成,进入下一个测试(仅所有检查通过时继续) - if (isProductionTestRunning && currentTestStep == TEST_BATTERY && allChecksPassed) { - qDebug() << "电池测试完成(所有检查通过),推进到下一个测试"; + // charge==1:仅据此判定通过(不校验电压、电量、温度) + updateTestStatus("charge", STATUS_SUCCESS); + updateTestStatus("ntc", STATUS_SUCCESS); + updateTestStatus("battery", STATUS_SUCCESS); + ui->recvTextEdit->append(">>> 电池测试通过:设备正在充电 (charge=1)"); + ui->statusbar->showMessage("电池测试通过(正在充电)", 2000); + if (isProductionTestRunning && currentTestStep == TEST_BATTERY) { skipToNextEnabledTest(); } } } -// 执行G-sensor测试(10秒内计算XYZ变化) +// 执行G-sensor测试(采满5帧有效XYZ即结束,否则最长5秒超时) void MainWindow::performGsensorTest() { // 检查G-sensor测试是否启用 @@ -3264,10 +3103,10 @@ void MainWindow::performGsensorTest() return; } - qDebug() << "开始G-sensor测试(10秒XYZ变化计算)"; + qDebug() << "开始G-sensor测试(采满5次或最长5秒)"; ui->recvTextEdit->append("========== 开始G-sensor测试 =========="); updateTestStatus("gsensor", STATUS_TESTING); - ui->statusbar->showMessage("G-sensor测试中:AT^GSENSORTEST=1(10秒)", 3000); + ui->statusbar->showMessage("G-sensor测试中:AT^GSENSORTEST=1(采满5帧或5秒超时)", 3000); // 重置采集状态 gSensorCollecting = false; @@ -3276,6 +3115,7 @@ void MainWindow::performGsensorTest() gSensorErrorDetected = false; gSensorAnySample = false; gSensorAllSamplesInRange = true; + gSensorValidSampleCount = 0; gSensorStartX = 0.0; gSensorStartY = 0.0; gSensorStartZ = 0.0; @@ -3308,16 +3148,16 @@ void MainWindow::performGsensorTest() const double yx = parseG(ui->gsensorDeltaYMaxLineEdit->text(), oyx); const double zm = parseG(ui->gsensorDeltaZMinLineEdit->text(), ozm); const double zx = parseG(ui->gsensorDeltaZMaxLineEdit->text(), ozx); - if (oxm && oxx && xm >= xx) { - ui->recvTextEdit->append(QString(">>> G-sensor参数警告: X 的 min(%1) ≥ max(%2),不存在满足 min xx) { + ui->recvTextEdit->append(QString(">>> G-sensor参数警告: X 的 min(%1) > max(%2),闭区间内无解") .arg(xm, 0, 'g', 8).arg(xx, 0, 'g', 8)); } - if (oym && oyx && ym >= yx) { - ui->recvTextEdit->append(QString(">>> G-sensor参数警告: Y 的 min(%1) ≥ max(%2),不存在满足 min yx) { + ui->recvTextEdit->append(QString(">>> G-sensor参数警告: Y 的 min(%1) > max(%2),闭区间内无解") .arg(ym, 0, 'g', 8).arg(yx, 0, 'g', 8)); } - if (ozm && ozx && zm >= zx) { - ui->recvTextEdit->append(QString(">>> G-sensor参数警告: Z 的 min(%1) ≥ max(%2),不存在满足 min zx) { + ui->recvTextEdit->append(QString(">>> G-sensor参数警告: Z 的 min(%1) > max(%2),闭区间内无解") .arg(zm, 0, 'g', 8).arg(zx, 0, 'g', 8)); } } @@ -3336,10 +3176,10 @@ void MainWindow::performGsensorTest() qDebug() << "发送指令: AT^GSENSORTEST=1"; gSensorCollecting = true; - ui->statusbar->showMessage("G-sensor检测与打印中...(10秒)", 2000); + ui->statusbar->showMessage("G-sensor检测与打印中...(5帧或5秒)", 2000); - // 10秒后停止检测并计算 - gSensorIntervalTimer->start(10000); + // 最长5秒;通常采满5帧后提前结束 + gSensorIntervalTimer->start(5000); }); } @@ -3384,13 +3224,13 @@ void MainWindow::checkGsensorTestResult(const QString& data) ui->statusbar->showMessage(QString("G-sensor起始XYZ已记录:X=%1 Y=%2 Z=%3").arg(x).arg(y).arg(z), 1500); } - // 末尾XYZ:10秒窗口内最后一次解析到的点 + // 末尾XYZ:采集窗口内最后一次解析到的点 gSensorHasLast = true; gSensorLastX = x; gSensorLastY = y; gSensorLastZ = z; - // 瞬时 XYZ(如 XYZ:X=0.00,Y=0.19,Z=-9.92):开区间 min < 值 < max;min 可为负、max 可为正,与其它组合同为 double 比较 + // 瞬时 XYZ:闭区间 min ≤ 值 ≤ max(边界也算通过) auto parseDoubleOrInvalid = [](const QString& s, bool& ok) -> double { QString t = s.trimmed(); if (t.isEmpty()) { @@ -3409,29 +3249,29 @@ void MainWindow::checkGsensorTestResult(const QString& data) bool samplePass = true; QStringList overMsgs; - if (okXMin && !(x > xMin)) { + if (okXMin && x < xMin) { samplePass = false; - overMsgs << QString("X=%1 未满足 X>%2").arg(x, 0, 'f', 3).arg(xMin, 0, 'f', 3); + overMsgs << QString("X=%1 未满足 X≥min(%2)").arg(x, 0, 'f', 3).arg(xMin, 0, 'f', 3); } - if (okXMax && !(x < xMax)) { + if (okXMax && x > xMax) { samplePass = false; - overMsgs << QString("X=%1 未满足 X<%2").arg(x, 0, 'f', 3).arg(xMax, 0, 'f', 3); + overMsgs << QString("X=%1 未满足 X≤max(%2)").arg(x, 0, 'f', 3).arg(xMax, 0, 'f', 3); } - if (okYMin && !(y > yMin)) { + if (okYMin && y < yMin) { samplePass = false; - overMsgs << QString("Y=%1 未满足 Y>%2").arg(y, 0, 'f', 3).arg(yMin, 0, 'f', 3); + overMsgs << QString("Y=%1 未满足 Y≥min(%2)").arg(y, 0, 'f', 3).arg(yMin, 0, 'f', 3); } - if (okYMax && !(y < yMax)) { + if (okYMax && y > yMax) { samplePass = false; - overMsgs << QString("Y=%1 未满足 Y<%2").arg(y, 0, 'f', 3).arg(yMax, 0, 'f', 3); + overMsgs << QString("Y=%1 未满足 Y≤max(%2)").arg(y, 0, 'f', 3).arg(yMax, 0, 'f', 3); } - if (okZMin && !(z > zMin)) { + if (okZMin && z < zMin) { samplePass = false; - overMsgs << QString("Z=%1 未满足 Z>%2").arg(z, 0, 'f', 3).arg(zMin, 0, 'f', 3); + overMsgs << QString("Z=%1 未满足 Z≥min(%2)").arg(z, 0, 'f', 3).arg(zMin, 0, 'f', 3); } - if (okZMax && !(z < zMax)) { + if (okZMax && z > zMax) { samplePass = false; - overMsgs << QString("Z=%1 未满足 Z<%2").arg(z, 0, 'f', 3).arg(zMax, 0, 'f', 3); + overMsgs << QString("Z=%1 未满足 Z≤max(%2)").arg(z, 0, 'f', 3).arg(zMax, 0, 'f', 3); } if (!samplePass) { @@ -3440,37 +3280,52 @@ void MainWindow::checkGsensorTestResult(const QString& data) .arg(overMsgs.join("; ")) .arg(x, 0, 'f', 3).arg(y, 0, 'f', 3).arg(z, 0, 'f', 3)); } + + gSensorValidSampleCount++; + ui->statusbar->showMessage(QString("G-sensor 已采 %1/5 帧").arg(gSensorValidSampleCount), 1500); + if (gSensorValidSampleCount >= 5) { + stopGsensorCollectionAndFinalizeSoon(QStringLiteral(",已采满5帧")); + } } } } } -// 10秒到时:发送GSENSORTEST=0并计算变化 -void MainWindow::onGsensorIntervalTimeout() +void MainWindow::stopGsensorCollectionAndFinalizeSoon(const QString& reasonSuffix) { if (!isProductionTestRunning || currentTestStep != TEST_GSENSOR) { return; } - + if (!gSensorCollecting) { + return; + } + gSensorCollecting = false; gSensorIntervalTimer->stop(); if (serial && serial->isOpen()) { - ui->recvTextEdit->append(">>> 发送指令: AT^GSENSORTEST=0 (停止检测与打印)"); + appendToLogFile(QString(">>> 发送指令: AT^GSENSORTEST=0 (停止检测与打印%1)\n").arg(reasonSuffix)); serial->write("AT^GSENSORTEST=0\r\n"); - qDebug() << "发送指令: AT^GSENSORTEST=0"; + qDebug() << "发送指令: AT^GSENSORTEST=0" << reasonSuffix; } - // 给设备一点时间把最后一行XYZ打印出来 QTimer::singleShot(500, this, [this]() { if (!isProductionTestRunning || currentTestStep != TEST_GSENSOR) { return; } - gSensorCollecting = false; finalizeGsensorTest(); }); } -// 结束G-sensor判定:每条采样的瞬时 X/Y/Z 对已配置边界满足严格开区间 min < 值 < max +// 采集超时:发送GSENSORTEST=0并结束判定 +void MainWindow::onGsensorIntervalTimeout() +{ + if (!isProductionTestRunning || currentTestStep != TEST_GSENSOR) { + return; + } + stopGsensorCollectionAndFinalizeSoon(QStringLiteral(",采集超时")); +} + +// 结束G-sensor判定:每条采样的瞬时 X/Y/Z 对已配置边界满足闭区间 min ≤ 值 ≤ max void MainWindow::finalizeGsensorTest() { if (!isProductionTestRunning || currentTestStep != TEST_GSENSOR) { @@ -3485,7 +3340,7 @@ void MainWindow::finalizeGsensorTest() } if (!gSensorAnySample) { - ui->statusbar->showMessage("G-sensor测试失败:10秒内未采到XYZ数据", 3000); + ui->statusbar->showMessage("G-sensor测试失败:未采到有效XYZ(5帧/5秒内)", 3000); updateTestStatus("gsensor", STATUS_FAILED); skipToNextEnabledTest(); return; @@ -3526,10 +3381,10 @@ void MainWindow::finalizeGsensorTest() } if (gSensorAllSamplesInRange) { - ui->statusbar->showMessage("G-sensor测试通过:10秒内各采样瞬时XYZ均满足已配置开区间", 3000); + ui->statusbar->showMessage("G-sensor测试通过:各采样瞬时XYZ均满足闭区间[min,max]", 3000); updateTestStatus("gsensor", STATUS_SUCCESS); } else { - ui->statusbar->showMessage("G-sensor测试失败:存在瞬时XYZ超出开区间(min,max)的采样(见日志)", 3000); + ui->statusbar->showMessage("G-sensor测试失败:存在瞬时XYZ超出闭区间的采样(见日志)", 3000); updateTestStatus("gsensor", STATUS_FAILED); } @@ -5007,7 +4862,7 @@ void MainWindow::saveTestConfigToSettings() configManager.setTestCheckbox("sechip", ui->checkBox_sechip->isChecked()); configManager.setTestCheckbox("gps", ui->checkBox_gps->isChecked()); - // 保存G-sensor XYZ变化标准(10秒) + // 保存G-sensor XYZ范围参数 configManager.setTestConfig("gsensorDeltaXMin", ui->gsensorDeltaXMinLineEdit->text()); configManager.setTestConfig("gsensorDeltaXMax", ui->gsensorDeltaXMaxLineEdit->text()); configManager.setTestConfig("gsensorDeltaYMin", ui->gsensorDeltaYMinLineEdit->text()); @@ -5063,7 +4918,7 @@ void MainWindow::loadTestConfigFromSettings() ui->checkBox_sechip->setChecked(configManager.getTestCheckbox("sechip", true)); ui->checkBox_gps->setChecked(configManager.getTestCheckbox("gps", true)); - // 恢复G-sensor XYZ变化标准(10秒) + // 恢复G-sensor XYZ范围参数 ui->gsensorDeltaXMinLineEdit->setText(configManager.getTestConfig("gsensorDeltaXMin", "")); ui->gsensorDeltaXMaxLineEdit->setText(configManager.getTestConfig("gsensorDeltaXMax", "")); ui->gsensorDeltaYMinLineEdit->setText(configManager.getTestConfig("gsensorDeltaYMin", "")); @@ -5199,27 +5054,7 @@ void MainWindow::skipToNextEnabledTest() skipToNextEnabledTest(); // 递归继续下一个 } } else if (currentTestStep == TEST_KEY) { - // 按键测试完成:功耗测试 -> 录音 -> 电池 - 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("deepsleep", STATUS_UNTESTED); - updateTestStatus("mic", STATUS_UNTESTED); - updateTestStatus("battery", STATUS_UNTESTED); - currentTestStep = TEST_BATTERY; - skipToNextEnabledTest(); - } - } else if (currentTestStep == TEST_DEEPSLEEP) { + // 按键测试完成:录音 -> 电池(功耗在 GPS 之后) if (isTestItemEnabled("mic")) { currentTestStep = TEST_AUDIO; qDebug() << "skipToNextEnabledTest: 推进到录音测试"; @@ -5228,12 +5063,19 @@ void MainWindow::skipToNextEnabledTest() currentTestStep = TEST_BATTERY; performBatteryTest(); } else { - qDebug() << "录音和电池测试均未启用,跳过"; + qDebug() << "录音/电池测试均未启用,跳过"; updateTestStatus("mic", STATUS_UNTESTED); updateTestStatus("battery", STATUS_UNTESTED); currentTestStep = TEST_BATTERY; skipToNextEnabledTest(); } + } else if (currentTestStep == TEST_DEEPSLEEP) { + // 功耗测试在所有其它项(含 GPS)之后执行,完成后结束产测 + qDebug() << "skipToNextEnabledTest: 功耗测试完成,结束产测"; + currentTestStep = TEST_COMPLETED; + isProductionTestRunning = false; + saveTestRecord(); + showFinalTestResult(); } else if (currentTestStep == TEST_AUDIO) { // 录音测试完成,检查电池测试 if (isTestItemEnabled("battery")) { @@ -5301,11 +5143,17 @@ void MainWindow::skipToNextEnabledTest() skipToNextEnabledTest(); } } else if (currentTestStep == TEST_GPS) { - // GPS测试完成,所有测试完成 - currentTestStep = TEST_COMPLETED; - isProductionTestRunning = false; - saveTestRecord(); - showFinalTestResult(); + // GPS 之后:若启用功耗测试则最后执行,否则结束 + if (isTestItemEnabled("deepsleep")) { + currentTestStep = TEST_DEEPSLEEP; + qDebug() << "skipToNextEnabledTest: GPS 完成,推进到功耗测试(最后一项)"; + performDeepsleepTest(); + } else { + currentTestStep = TEST_COMPLETED; + isProductionTestRunning = false; + saveTestRecord(); + showFinalTestResult(); + } } else { qDebug() << "未知的测试步骤,无法推进"; } diff --git a/mainwindow.h b/mainwindow.h index 20185bb..91e1042 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -89,7 +89,7 @@ private slots: void checkBatteryTestResult(const QString& data); // 检查电池测试结果 void performGsensorTest(); // 执行G-sensor测试 void checkGsensorTestResult(const QString& data); // 检查G-sensor测试结果 - void onGsensorIntervalTimeout(); // 10秒后关闭GSENSORTEST并计算变化 + void onGsensorIntervalTimeout(); // 最长5秒后关闭GSENSORTEST并结束判定 void performLeaklightTest(); // 心率漏光测试 void checkLeaklightTestResult(const QString& data); // 检查漏光测试结果 void performBluetoothTest(); // 执行蓝牙测试 @@ -136,7 +136,7 @@ private: QTimer *lcdTestTimer; // LCD测试定时器 QTimer *motorTestTimer; // 马达测试定时器 QTimer *testTimeoutTimer; // 通用测试超时定时器 - QTimer *gSensorIntervalTimer; // G-sensor打印10秒后停止 + QTimer *gSensorIntervalTimer; // G-sensor采集最长5秒后停止(或满5帧提前停) QTimer *bluetoothTestTimer; // 蓝牙测试定时器 QTimer *gpsTestTimer; // GPS测试30秒总超时定时器 @@ -168,7 +168,6 @@ private: int gpsMaxCn; // GPS测试期间最大CN值(仅日志) QMap testStartTimeMap; // 各项测试开始时间 QMap testDurationSecMap; // 各项测试耗时(秒) - bool keyRotateDetected; // 按键测试中是否检测到旋转事件 int audioTestRoundIndex; // 录音测试当前轮次 0..2(有等级标准时共3轮) bool audioTestAnyPass; // 三轮中是否至少一轮满足等级标准 bool audioTestAwaitingMicLevel; // 本轮是否仍在等待首条 mic level(防重复解析) @@ -241,16 +240,18 @@ private: /// 蓝牙目标 MAC / RSSI:优先界面输入,空则读 settings(与产测是否已保存无关) void getBluetoothExpectFromUiOrConfig(QString& expectAddr, QString& expectRssiStr) const; - // G-sensor:解析瞬时 XYZ 与 UI 开区间阈值并更新测试结果 + // G-sensor:解析瞬时 XYZ 与 UI 闭区间阈值并更新测试结果 void finalizeGsensorTest(); + void stopGsensorCollectionAndFinalizeSoon(const QString& reasonSuffix); // G-sensor XYZ窗口采集状态 bool gSensorCollecting; // 是否正在收集XYZ数据 bool gSensorHasStart; // 是否已记录起始XYZ bool gSensorHasLast; // 是否已记录末尾XYZ bool gSensorErrorDetected; // 是否检测到错误/异常响应 - bool gSensorAnySample; // 10秒窗口内是否采到至少一组XYZ - bool gSensorAllSamplesInRange; // 各采样瞬时X/Y/Z是否均满足已配置边界:min<值 - G-sensor 瞬时XYZ范围: + G-sensor 瞬时XYZ(闭区间 min≤值≤max;采满5帧或最长5秒): @@ -1083,19 +1083,19 @@ background-color: #F57C00; - + 4 - + - 功耗测试: + 录音测试: - + color: #888888; font-size: 18px; font-weight: bold; @@ -1108,7 +1108,7 @@ background-color: #F57C00; - + color: #888888; @@ -1118,7 +1118,7 @@ background-color: #F57C00; - + Qt::Horizontal @@ -1133,19 +1133,19 @@ background-color: #F57C00; - + 4 - + - 录音测试: + 电池测试: - + color: #888888; font-size: 18px; font-weight: bold; @@ -1158,7 +1158,7 @@ background-color: #F57C00; - + color: #888888; @@ -1168,7 +1168,7 @@ background-color: #F57C00; - + Qt::Horizontal @@ -1183,19 +1183,19 @@ background-color: #F57C00; - + 4 - + - 电池测试: + G-sensor: - + color: #888888; font-size: 18px; font-weight: bold; @@ -1208,7 +1208,7 @@ background-color: #F57C00; - + color: #888888; @@ -1218,7 +1218,7 @@ background-color: #F57C00; - + Qt::Horizontal @@ -1233,19 +1233,19 @@ background-color: #F57C00; - + 4 - + - G-sensor: + 漏光测试: - + color: #888888; font-size: 18px; font-weight: bold; @@ -1258,7 +1258,7 @@ background-color: #F57C00; - + color: #888888; @@ -1268,7 +1268,7 @@ background-color: #F57C00; - + Qt::Horizontal @@ -1283,19 +1283,19 @@ background-color: #F57C00; - + 4 - + - 漏光测试: + 蓝牙测试: - + color: #888888; font-size: 18px; font-weight: bold; @@ -1308,7 +1308,7 @@ background-color: #F57C00; - + color: #888888; @@ -1318,7 +1318,7 @@ background-color: #F57C00; - + Qt::Horizontal @@ -1333,19 +1333,19 @@ background-color: #F57C00; - + 4 - + - 蓝牙测试: + SE芯片测试: - + color: #888888; font-size: 18px; font-weight: bold; @@ -1358,7 +1358,7 @@ background-color: #F57C00; - + color: #888888; @@ -1368,7 +1368,7 @@ background-color: #F57C00; - + Qt::Horizontal @@ -1383,19 +1383,19 @@ background-color: #F57C00; - + 4 - + - SE芯片测试: + GPS测试: - + color: #888888; font-size: 18px; font-weight: bold; @@ -1408,7 +1408,7 @@ background-color: #F57C00; - + color: #888888; @@ -1418,7 +1418,7 @@ background-color: #F57C00; - + Qt::Horizontal @@ -1433,19 +1433,19 @@ background-color: #F57C00; - + 4 - + - GPS测试: + 功耗测试: - + color: #888888; font-size: 18px; font-weight: bold; @@ -1458,7 +1458,7 @@ background-color: #F57C00; - + color: #888888; @@ -1468,7 +1468,7 @@ background-color: #F57C00; - + Qt::Horizontal @@ -1619,20 +1619,20 @@ background-color: #F57C00; - + - 功耗测试 + GPS测试 - - + + - GPS测试 + 功耗测试 - +