From: xue <2144439972@qq.com> Date: Fri, 24 Apr 2026 06:47:37 +0000 (+0800) Subject: 1.录音测试回退为一次 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=d6ccbb14e20c8ada8072edee935437cc21240f6b;p=mirrors%2Ffactory_tool.git 1.录音测试回退为一次 2.漏光测试失败则直接复测 3.取消关机指令 --- diff --git a/mainwindow.cpp b/mainwindow.cpp index 48329d6..f436833 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,4 +1,4 @@ -#include "mainwindow.h" +#include "mainwindow.h" #include "ui_mainwindow.h" #include "config_manager.h" #include @@ -60,7 +60,7 @@ MainWindow::MainWindow(QWidget *parent) , ui(new Ui::MainWindow) { ui->setupUi(this); - setWindowTitle("FD272产测工具 V1.0"); + setWindowTitle("FD272产测工具 V1.9"); // 确保控制台输出使用UTF-8编码 QTextCodec *utf8Codec = QTextCodec::codecForName("UTF-8"); @@ -106,8 +106,6 @@ MainWindow::MainWindow(QWidget *parent) lcdBacklightOn = false; // 初始化LCD背光状态为关闭 keyTestStarted = false; keyTestDialog = nullptr; - audioTestRoundIndex = 0; - audioTestAnyPass = false; audioTestAwaitingMicLevel = false; bluetoothTestTimer = new QTimer(this); gpsTestTimer = new QTimer(this); @@ -128,6 +126,7 @@ MainWindow::MainWindow(QWidget *parent) leaklightGreenSeen = false; leaklightRedSeen = false; leaklightIrSeen = false; + leaklightAttemptIndex = 0; // 初始化日志文件相关变量 testLogFile = nullptr; testLogStream = nullptr; @@ -162,7 +161,6 @@ MainWindow::MainWindow(QWidget *parent) connect(bluetoothTestTimer, &QTimer::timeout, this, &MainWindow::onBluetoothTestTimer); connect(gpsTestTimer, &QTimer::timeout, this, &MainWindow::onGpsTestTimer); connect(gpsPollTimer, &QTimer::timeout, this, &MainWindow::onGpsPollTimer); - // 初始化G-sensor采集状态 gSensorCollecting = false; gSensorHasStart = false; @@ -598,11 +596,11 @@ void MainWindow::readSerialData() qDebug() << "产测模式: 已开启"; appendToLogFile(QString("=== 产测模式状态: 已开启 ===\n")); - // 如果还未标记为已检测,标记并开始获取版本信息 - if (!factoryModeChecked) { + // 仅在非产测流程中自动拉版本;产测时串口可能出现该行,避免与当前测试 AT 并发(如 G-sensor) + if (!isProductionTestRunning && !factoryModeChecked) { factoryModeChecked = true; QTimer::singleShot(1000, this, [this]() { - if (!versionInfoFetched) { + if (!isProductionTestRunning && !versionInfoFetched) { startVersionInfoFetch(); } }); @@ -614,11 +612,10 @@ void MainWindow::readSerialData() qDebug() << "产测模式: 已关闭"; appendToLogFile(QString("=== 产测模式状态: 已关闭 ===\n")); - // 如果还未标记为已检测,标记并开始获取版本信息 - if (!factoryModeChecked) { + if (!isProductionTestRunning && !factoryModeChecked) { factoryModeChecked = true; QTimer::singleShot(1000, this, [this]() { - if (!versionInfoFetched) { + if (!isProductionTestRunning && !versionInfoFetched) { startVersionInfoFetch(); } }); @@ -2501,7 +2498,7 @@ void MainWindow::on_openButton_2_clicked() } } -// 执行录音测试(配置了等级标准时共测 3 轮,任一轮「实际等级 >= 设置等级」则整体通过) +// 执行录音测试(单轮;有等级标准则 mic level 与标准比较一次,无标准则只采样不判等级) void MainWindow::performAudioTest() { if (!isTestItemEnabled("mic")) { @@ -2519,8 +2516,6 @@ void MainWindow::performAudioTest() qDebug() << "开始录音测试"; appendToLogFile("\n========== 开始录音测试 ==========\n"); updateTestStatus("mic", STATUS_TESTING); - audioTestRoundIndex = 0; - audioTestAnyPass = false; audioTestAwaitingMicLevel = false; QString standard = ui->audioLevelStandardLineEdit->text().trimmed(); @@ -2528,8 +2523,8 @@ void MainWindow::performAudioTest() appendToLogFile(">>> 未配置等级标准:单轮采样,不做等级校验\n"); ui->statusbar->showMessage("录音测试中(未配标准,单轮),请对着麦克风说话...", 5000); } else { - appendToLogFile(QString(">>> 已配置等级标准「%1」:共 3 轮,任一轮达标即通过\n").arg(standard)); - ui->statusbar->showMessage("录音测试 1/3:请对着麦克风说话...", 5000); + appendToLogFile(QString(">>> 已配置等级标准「%1」:单轮判定\n").arg(standard)); + ui->statusbar->showMessage("录音测试中,请对着麦克风说话...", 5000); } // 录音前关闭LCD(与V1.7一致) @@ -2539,24 +2534,18 @@ void MainWindow::performAudioTest() qDebug() << "录音测试前发送AT^LCDOFF"; } - beginAudioTestAttempt(0); + beginAudioTestAttempt(); } -void MainWindow::beginAudioTestAttempt(int roundIndex) +void MainWindow::beginAudioTestAttempt() { if (!isProductionTestRunning || currentTestStep != TEST_AUDIO || !serial || !serial->isOpen()) { qDebug() << "录音测试:产测已停止或串口未打开"; return; } - audioTestRoundIndex = roundIndex; audioTestAwaitingMicLevel = true; - QString standard = ui->audioLevelStandardLineEdit->text().trimmed(); - if (!standard.isEmpty()) { - ui->statusbar->showMessage(QString("录音测试 %1/3:请对着麦克风说话...").arg(roundIndex + 1), 5000); - } - QString volumeStr = ui->audioVolumeLineEdit->text().trimmed(); if (volumeStr.isEmpty()) volumeStr = "2.0"; @@ -2598,8 +2587,8 @@ void MainWindow::checkAudioTestResult(const QString& data) 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)); + appendToLogFile(QString(">>> 录音测试 mic level=%1\n").arg(micLevel)); + ui->recvTextEdit->append(QString(">>> 录音测试 mic level=%1").arg(micLevel)); // 结束本轮采集 if (serial && serial->isOpen()) { @@ -2607,64 +2596,58 @@ void MainWindow::checkAudioTestResult(const QString& data) 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; - } - 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)); - } + // 固件在 =6 后异步停止 AI 语音/解码线程;稍候再判定/切下一项,减轻与后续 AT 的竞态。 + static const int kMsAfterAudiotestStop = 2000; + ui->statusbar->showMessage(QStringLiteral("录音本轮已结束,等待设备完成音频收尾…"), 2000); + appendToLogFile(QString(">>> 等待 %1 ms 后再继续(避开 AUDIOTEST 异步停止)\n").arg(kMsAfterAudiotestStop)); + qDebug() << "录音测试:已发 AUDIOTEST=6," << kMsAfterAudiotestStop << "ms 后再判定/切下一项"; - const int completedRound = audioTestRoundIndex; - const int nextRound = completedRound + 1; + QTimer::singleShot(kMsAfterAudiotestStop, this, [this, micLevel]() { + if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) { + return; + } - if (nextRound < 3) { - QTimer::singleShot(400, this, [this, nextRound]() { - if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) { - return; - } - beginAudioTestAttempt(nextRound); - }); - return; - } + QString standard = ui->audioLevelStandardLineEdit->text().trimmed(); + if (standard.isEmpty()) { + updateTestStatus("mic", STATUS_SUCCESS); + ui->statusbar->showMessage(QString("录音测试通过(等级:%1,未配置标准不校验)").arg(micLevel), 3000); + skipToNextEnabledTest(); + return; + } - 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); - } - skipToNextEnabledTest(); + // 等级排序:静音(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; + } + + const bool roundPass = (micRank >= stdRank); + if (roundPass) { + appendToLogFile(QString(">>> 单轮达标(%1 >= 标准%2)\n").arg(micLevel).arg(standard)); + updateTestStatus("mic", STATUS_SUCCESS); + ui->statusbar->showMessage(QString("录音测试通过(%1 ≥ 标准%2)").arg(micLevel).arg(standard), 3000); + } else { + appendToLogFile(QString(">>> 单轮未达标(%1 < 标准%2)\n").arg(micLevel).arg(standard)); + updateTestStatus("mic", STATUS_FAILED); + ui->statusbar->showMessage(QString("录音测试失败(%1 低于标准%2)").arg(micLevel).arg(standard), 3000); + } + skipToNextEnabledTest(); + }); } // 执行电池测试 @@ -2689,8 +2672,8 @@ void MainWindow::performBatteryTest() updateTestStatus("battery", STATUS_TESTING); ui->statusbar->showMessage("电池测试中,正在获取电池电压...", 3000); - // 延迟100ms后发送电池电量查询指令,确保串口已准备好 - QTimer::singleShot(100, this, [this]() { + // 短暂延迟后再发 GETPOWER + QTimer::singleShot(200, this, [this]() { if (isProductionTestRunning && currentTestStep == TEST_BATTERY && serial && serial->isOpen()) { // 发送电池电量查询指令 serial->write("AT^GETPOWER\r\n"); @@ -3226,6 +3209,7 @@ void MainWindow::performLeaklightTest() ui->recvTextEdit->append(">>> 发送指令: AT^LEAKLIGHT"); ui->statusbar->showMessage("漏光测试中,等待green/red/ir数据...", 3000); + leaklightAttemptIndex = 0; leaklightGreen = 0; leaklightRed = 0; leaklightIr = 0; @@ -3274,10 +3258,32 @@ void MainWindow::checkLeaklightTestResult(const QString& data) 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(); + return; } + + // 首次不通过:自动再测一次;重测仍不通过则判失败 + if (leaklightAttemptIndex == 0) { + leaklightAttemptIndex = 1; + leaklightGreen = 0; + leaklightRed = 0; + leaklightIr = 0; + leaklightGreenSeen = false; + leaklightRedSeen = false; + leaklightIrSeen = false; + ui->recvTextEdit->append(">>> 漏光首次未通过(存在0值),自动重测一次"); + appendToLogFile(">>> 漏光首次未通过,自动重测一次\n"); + ui->statusbar->showMessage("漏光首次未通过,正在自动重测…", 3000); + if (serial && serial->isOpen()) { + ui->recvTextEdit->append(">>> 发送指令: AT^LEAKLIGHT (重测)"); + serial->write("AT^LEAKLIGHT\r\n"); + } + testTimeoutTimer->start(10000); + return; + } + + updateTestStatus("leaklight", STATUS_FAILED); + ui->statusbar->showMessage("漏光测试失败(重测后仍存在0值)", 2500); skipToNextEnabledTest(); } } @@ -4008,24 +4014,21 @@ void MainWindow::showFinalTestResult() qDebug() << "显示最终测试结果弹窗"; resultDialog.exec(); - // 用户点击确定后的处理:关机,不执行重启/RESTORE - qDebug() << "用户确认测试结果,发送关机指令"; - - if (serial->isOpen()) { - ui->recvTextEdit->append(">>> 发送指令: AT^POWEROFF (产测结束关机)"); - serial->write("AT^POWEROFF\r\n"); - qDebug() << "发送关机指令: AT^POWEROFF"; - ui->statusbar->showMessage("已发送关机指令", 3000); - } - - // 恢复产测按钮状态 - 变回蓝色并启用 + // 用户点击确定后:不自动发送关机(避免影响后续操作;需关机请用界面关机按钮) + qDebug() << "用户确认测试结果,产测收尾(不发送 AT^POWEROFF)"; + ui->recvTextEdit->append(">>> 产测结束:未自动发送关机指令"); + ui->statusbar->showMessage("产测已结束,未自动关机", 3000); + finalizeAfterProductionResultDialog(); +} + +void MainWindow::finalizeAfterProductionResultDialog() +{ ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }"); ui->openButton_2->setEnabled(true); qDebug() << "产测完成 - 按钮已恢复蓝色并启用"; - - // 清空整个产测状态 + clearProductionTestState(); - + qDebug() << "产测流程完全结束,状态已清空"; } @@ -4228,7 +4231,7 @@ void MainWindow::onTestTimeout() void MainWindow::clearProductionTestState() { qDebug() << "开始清空产测状态"; - + // 停止所有定时器 if (lcdTestTimer->isActive()) { lcdTestTimer->stop(); diff --git a/mainwindow.h b/mainwindow.h index 6f049fd..c3275a0 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -84,8 +84,8 @@ private slots: void showKeyTestConfirmDialog(bool allKeysTested); // 显示按键测试确认弹窗 void performDeepsleepTest(); // 功耗:ENTERTESTVIEW -> TESTJUMP=DEEPSLEEP -> FACTORYDEEPSLEEPENTER void showDeepsleepTestConfirmDialog(); // 功耗测试确认弹窗 - void performAudioTest(); // 执行录音测试(有标准时共3轮,任一轮达标即通过) - void beginAudioTestAttempt(int roundIndex); // 发送单轮 AT^AUDIOTEST + void performAudioTest(); // 执行录音测试(单轮;有标准则按等级判定一次) + void beginAudioTestAttempt(); // 发送 AT^AUDIOTEST=5/7 单轮采集 void checkAudioTestResult(const QString& data); // 检查录音测试结果 void performBatteryTest(); // 执行电池测试 void checkBatteryTestResult(const QString& data); // 检查电池测试结果 @@ -172,15 +172,14 @@ private: int gpsMaxCn; // GPS测试期间最大CN值(仅日志) QMap testStartTimeMap; // 各项测试开始时间 QMap testDurationSecMap; // 各项测试耗时(秒) - int audioTestRoundIndex; // 录音测试当前轮次 0..2(有等级标准时共3轮) - bool audioTestAnyPass; // 三轮中是否至少一轮满足等级标准 - bool audioTestAwaitingMicLevel; // 本轮是否仍在等待首条 mic level(防重复解析) + bool audioTestAwaitingMicLevel; // 是否仍在等待首条 mic level(防重复解析) int leaklightGreen; int leaklightRed; int leaklightIr; bool leaklightGreenSeen; bool leaklightRedSeen; bool leaklightIrSeen; + int leaklightAttemptIndex; // 0=首次;1=首次失败后自动重测(仅一轮重试) // 日志文件相关变量 QFile *testLogFile; // 测试日志文件对象 QTextStream *testLogStream; // 测试日志文件流 @@ -251,6 +250,8 @@ private: void finalizeGsensorTest(); void stopGsensorCollectionAndFinalizeSoon(const QString& reasonSuffix); + void finalizeAfterProductionResultDialog(); // 恢复产测按钮并 clearProductionTestState + // G-sensor XYZ窗口采集状态 bool gSensorCollecting; // 是否正在收集XYZ数据 bool gSensorHasStart; // 是否已记录起始XYZ