if (line.startsWith("fac:")) {
appendToLogFile(processLine);
}
+
+ // 设备打印 InitBroadcastService start:未在产测则自动等同点击「开始产测」;已在等待开机则直接视为就绪并进入 PMADDVOTE
+ {
+ const QString kInitBc = QStringLiteral("InitBroadcastService start");
+ const bool hasInitBc = line.contains(kInitBc, Qt::CaseInsensitive) ||
+ processLine.contains(kInitBc, Qt::CaseInsensitive);
+ if (hasInitBc && serial && serial->isOpen()) {
+ if (!isProductionTestRunning) {
+ qDebug() << "检测到 InitBroadcastService start,将自动开始产测流程";
+ QTimer::singleShot(0, this, [this, kInitBc]() {
+ if (!serial || !serial->isOpen() || isProductionTestRunning) {
+ return;
+ }
+ ui->recvTextEdit->append(">>> 检测到 InitBroadcastService start,自动开始产测");
+ appendToLogFile("=== 检测到 InitBroadcastService start,自动开始产测 ===\n");
+ beginProductionTestSession();
+ tryAdvanceProductionAfterBootKeywords(kInitBc);
+ });
+ } else if (currentTestStep == TEST_WAIT_BOOT) {
+ tryAdvanceProductionAfterBootKeywords(line);
+ if (currentTestStep == TEST_WAIT_BOOT && processLine != line) {
+ tryAdvanceProductionAfterBootKeywords(processLine);
+ }
+ }
+ }
+ }
// 开机检测(仅在未检测到开机时执行)
// 同时检查原始行和去掉fac:前缀的行,确保能匹配到关键字
return;
}
+ const QString kInitBroadcast = QStringLiteral("InitBroadcastService start");
const QStringList keywords = configManager.getBootDetectionKeywords();
- if (keywords.isEmpty()) {
+
+ QString matchedReason;
+ if (data.contains(kInitBroadcast, Qt::CaseInsensitive)) {
+ matchedReason = kInitBroadcast;
+ } else {
+ if (keywords.isEmpty()) {
+ return;
+ }
+ for (const QString& keyword : keywords) {
+ if (data.contains(keyword, Qt::CaseInsensitive)) {
+ matchedReason = keyword;
+ break;
+ }
+ }
+ }
+
+ if (matchedReason.isEmpty()) {
return;
}
- for (const QString& keyword : keywords) {
- if (data.contains(keyword, Qt::CaseInsensitive)) {
- qDebug() << "产测:检测到开机完成关键字:" << keyword << ",数据片段:" << data.left(120);
- appendToLogFile(QString("=== 产测流程-检测到开机完成: %1 ===\n").arg(keyword));
+ qDebug() << "产测:检测到开机完成:" << matchedReason << ",数据片段:" << data.left(120);
+ appendToLogFile(QString("=== 产测流程-检测到开机完成: %1 ===\n").arg(matchedReason));
- bootDetected = true;
- currentTestStep = TEST_PMADDVOTE_INIT;
+ bootDetected = true;
+ currentTestStep = TEST_PMADDVOTE_INIT;
- if (testTimeoutTimer->isActive()) {
- testTimeoutTimer->stop();
- }
+ if (testTimeoutTimer->isActive()) {
+ testTimeoutTimer->stop();
+ }
- ui->statusbar->showMessage("设备已开机,正在发送 PMADDVOTE / ENTERTESTVIEW…", 3000);
- ui->recvTextEdit->append(">>> 已检测到开机完成,进入 PMADDVOTE / ENTERTESTVIEW 初始化链(未发 AT^FACTORY=1)");
+ ui->statusbar->showMessage("设备已开机,正在发送 PMADDVOTE / ENTERTESTVIEW…", 3000);
+ ui->recvTextEdit->append(">>> 已检测到开机完成,进入 PMADDVOTE / ENTERTESTVIEW 初始化链(未发 AT^FACTORY=1)");
- runPostFactoryProductionInit();
- return;
- }
- }
+ runPostFactoryProductionInit();
}
void MainWindow::tryApplyProductionStartGreenAfterPmaddvoteOk(const QString& line)
}
}
-void MainWindow::on_openButton_2_clicked()
+void MainWindow::beginProductionTestSession()
{
- // 检查串口是否已打开
- if (!serial->isOpen()) {
- QMessageBox::warning(this, "警告", "请先打开串口连接");
+ if (isProductionTestRunning) {
+ qDebug() << "beginProductionTestSession: 已在产测中,忽略";
return;
}
-
- if (isProductionTestRunning) {
- // 如果正在测试,则停止测试
- lcdTestTimer->stop();
- motorTestTimer->stop();
- testTimeoutTimer->stop();
- gSensorIntervalTimer->stop();
- bluetoothTestTimer->stop();
- isProductionTestRunning = false;
- postFactoryVoteSequenceStarted = false;
- waitingPmaddvoteOkForGreenButton = false;
- currentTestStep = TEST_IDLE;
-
- // 关闭测试日志文件
- if (testLogFile && testLogStream) {
- *testLogStream << QString("=== 测试被用户停止: %1 ===\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
- testLogStream->flush();
- }
- closeTestLogFile();
-
- ui->statusbar->showMessage("产测已停止", 2000);
- qDebug() << "产测被用户停止";
-
- // 恢复产测按钮状态 - 变回蓝色并启用
- ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }");
- ui->openButton_2->setEnabled(true);
- qDebug() << "产测停止 - 按钮已恢复蓝色并启用";
-
+ if (!serial || !serial->isOpen()) {
+ qDebug() << "beginProductionTestSession: 串口未打开,忽略";
return;
}
- // 开始产测流程
isProductionTestRunning = true;
postFactoryVoteSequenceStarted = false;
waitingPmaddvoteOkForGreenButton = false;
testDurationSecMap.clear();
currentTestStep = TEST_WAIT_BOOT;
currentLcdColor = 1; // 从红色开始
-
+
// 在开始新测试前,尽量保存当前UI日志(如果有内容)
saveRecvTextEditToLog();
productionDeviceMac.clear();
// 创建测试日志文件
createTestLogFile();
-
+
// 清空所有UI内容
ui->recvTextEdit->clear(); // 清空串口接收文本框
ui->sendTextEdit->clear(); // 清空发送文本框
ui->statusbar->clearMessage(); // 清空状态栏
-
+
// 重置开机检测状态
bootDetected = false;
factoryModeChecked = false;
versionInfoFetched = false;
-
+
// 清空设备信息
ui->VerlineEdit->clear(); // 清空版本信息
-
+
// 重置弹窗状态
lcdTestPopupShown = false;
motorTestPopupShown = false;
deepsleepTestPopupShown = false;
isWaitingForUserConfirm = false;
keyTestStarted = false;
-
+
// 重置状态指示器
updateTestStatus("lcd", STATUS_UNTESTED);
updateTestStatus("tp", STATUS_UNTESTED);
updateTestStatus("bluetooth", STATUS_UNTESTED);
updateTestStatus("sechip", STATUS_UNTESTED);
updateTestStatus("gps", STATUS_UNTESTED);
-
+
qDebug() << "已清空所有UI内容,准备开始新的产测";
-
+
ui->statusbar->showMessage("开始产测流程...", 2000);
qDebug() << "=== 开始产测流程 ===";
qDebug() << "流程: 等待开机完成 → 跳过 AT^FACTORY=1 → PMADDVOTE/ENTERTESTVIEW → 各测试项 → 完成后弹窗确认等";
qDebug() << "LCD测试: 仅发送 AT^LCDTEST=1";
-
+
// 不再发送 AT^FACTORY=1:固件侧常会触发整机重启;在开机完成后再发 PMADDVOTE / ENTERTESTVIEW
qDebug() << "Step 1: 等待串口开机关键字(bootDetectionKeywords),然后 PMADDVOTE / ENTERTESTVIEW";
}
}
+void MainWindow::on_openButton_2_clicked()
+{
+ // 检查串口是否已打开
+ if (!serial->isOpen()) {
+ QMessageBox::warning(this, "警告", "请先打开串口连接");
+ return;
+ }
+
+ if (isProductionTestRunning) {
+ // 如果正在测试,则停止测试
+ lcdTestTimer->stop();
+ motorTestTimer->stop();
+ testTimeoutTimer->stop();
+ gSensorIntervalTimer->stop();
+ bluetoothTestTimer->stop();
+ isProductionTestRunning = false;
+ postFactoryVoteSequenceStarted = false;
+ waitingPmaddvoteOkForGreenButton = false;
+ currentTestStep = TEST_IDLE;
+
+ // 关闭测试日志文件
+ if (testLogFile && testLogStream) {
+ *testLogStream << QString("=== 测试被用户停止: %1 ===\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
+ testLogStream->flush();
+ }
+ closeTestLogFile();
+
+ ui->statusbar->showMessage("产测已停止", 2000);
+ qDebug() << "产测被用户停止";
+
+ // 恢复产测按钮状态 - 变回蓝色并启用
+ ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }");
+ ui->openButton_2->setEnabled(true);
+ qDebug() << "产测停止 - 按钮已恢复蓝色并启用";
+
+ return;
+ }
+
+ beginProductionTestSession();
+}
+
// 执行录音测试(单轮;有等级标准则 mic level 与标准比较一次,无标准则只采样不判等级)
void MainWindow::performAudioTest()
{
qDebug() << "发送AT^AUDIOTEST=6";
}
- // 固件在 =6 后异步停止 AI 语音/解码线程;稍候再判定/切下一项,减轻与后续 AT 的竞态。
+ // 顺序说明:上面已立刻发送 AT^AUDIOTEST=6,这一步才是「通知固件停止录音」。
+ // 固件收到 =6 后会异步停线程/拆音频(需数百 ms~1s+);此处延迟后再 skipToNext/发电池 AT,
+ // 避免与收尾并发导致异常。日志里在延迟期间仍可能出现 [AudioTest]/mic level,那是设备仍在打印,并非未先关再进下一项。
static const int kMsAfterAudiotestStop = 2000;
- ui->statusbar->showMessage(QStringLiteral("å½\95é\9f³æ\9c¬è½®å·²ç»\93æ\9d\9fï¼\8cç\89å¾\85设å¤\87å®\8cæ\88\90é\9f³é¢\91收尾…"), 2000);
- appendToLogFile(QString(">>> 等待 %1 ms 后再继续(避开 AUDIOTEST 异步停止)\n").arg(kMsAfterAudiotestStop));
- qDebug() << "录音测试:已发 AUDIOTEST=6," << kMsAfterAudiotestStop << "ms 后再判定/切下一项";
+ ui->statusbar->showMessage(QStringLiteral("å·²å\8f\91é\80\81å\81\9cæ¢å½\95é\9f³(AT^AUDIOTEST=6)ï¼\8cç\89å¾\85设å¤\87收尾…"), 2000);
+ appendToLogFile(QString(">>> 已发送 AT^AUDIOTEST=6;延迟 %1 ms 待设备异步停止完毕,再进入下一项测试\n").arg(kMsAfterAudiotestStop));
+ qDebug() << "录音测试:已发 AUDIOTEST=6," << kMsAfterAudiotestStop << "ms 后再进入下一项";
QTimer::singleShot(kMsAfterAudiotestStop, this, [this, micLevel]() {
if (!isProductionTestRunning || currentTestStep != TEST_AUDIO) {