gSensorIntervalTimer = new QTimer(this);
currentLcdColor = 0;
isProductionTestRunning = false;
+ postFactoryVoteSequenceStarted = false;
+ waitingPmaddvoteOkForGreenButton = false;
currentTestStep = TEST_IDLE;
lcdTestPopupShown = false;
motorTestPopupShown = false;
if (bootDetected && !factoryModeChecked && !isProductionTestRunning) {
checkFactoryMode(line);
}
+
+ // 产测已开始:等待开机完成关键字后再进入 PMADDVOTE(与空闲时的 checkBootDetection 使用同一关键字列表)
+ if (isProductionTestRunning && currentTestStep == TEST_WAIT_BOOT) {
+ tryAdvanceProductionAfterBootKeywords(line);
+ if (currentTestStep == TEST_WAIT_BOOT && processLine != line) {
+ tryAdvanceProductionAfterBootKeywords(processLine);
+ }
+ }
// 版本信息获取:当正在获取版本信息时,接收到数据后继续发送下一条指令
if (versionInfoFetched && currentVersionCommandIndex >= 0 &&
// 4G/PPP 相关解析已移除
- // 检测工厂模式进入确认(用于产测)
- if (line.contains("fac:enter or exit facotry mode")) {
+ // 检测工厂模式进入确认(用于产测;兼容 facotry/factory 拼写,大小写不敏感)
+ if (line.contains("enter or exit facotry mode", Qt::CaseInsensitive) ||
+ line.contains("enter or exit factory mode", Qt::CaseInsensitive)) {
checkFactoryModeResult(line);
}
+
+ tryApplyProductionStartGreenAfterPmaddvoteOk(line);
// 4G/PPP 相关解析已移除
lcdTestTimer->stop();
motorTestTimer->stop();
isProductionTestRunning = false;
+ postFactoryVoteSequenceStarted = false;
+ waitingPmaddvoteOkForGreenButton = false;
currentTestStep = TEST_IDLE;
ui->statusbar->showMessage("产测已停止", 2000);
// 开始产测流程
isProductionTestRunning = true;
+ postFactoryVoteSequenceStarted = false;
+ waitingPmaddvoteOkForGreenButton = false;
if (isTestItemEnabled("lcd")) {
currentTestStep = TEST_LCD;
currentLcdColor = 1; // 从红色开始
if (!isProductionTestRunning || currentTestStep != TEST_RESET) {
return;
}
-
+
+ const bool hasFacConfirm = data.contains("enter or exit facotry mode", Qt::CaseInsensitive)
+ || data.contains("enter or exit factory mode", Qt::CaseInsensitive);
+ if (!hasFacConfirm) {
+ return;
+ }
+
qDebug() << "工厂模式确认收到数据:" << data.trimmed();
-
- // 解析新格式:fac:enter or exit facotry mode :1 或 fac:enter or exit facotry mode :0
- if (data.contains("fac:enter or exit facotry mode")) {
- // 使用正则表达式提取cmd值
- QRegExp factoryModePattern("fac:enter or exit facotry mode\\s*:\\s*(\\d+)");
- if (factoryModePattern.indexIn(data) != -1) {
- QString cmdStr = factoryModePattern.cap(1);
- int cmd = cmdStr.toInt();
-
- qDebug() << "解析到工厂模式命令:" << cmd << "(1=进入产测, 0=退出产测)";
-
- if (cmd == 1) {
- // cmd=1 表示成功进入产测模式
- // 停止超时检测,因为已经收到确认
- if (testTimeoutTimer->isActive()) {
- testTimeoutTimer->stop();
- qDebug() << "工厂模式进入确认收到,停止超时检测";
- }
-
- qDebug() << "工厂模式进入成功确认 (cmd=1)";
- ui->statusbar->showMessage("工厂模式进入成功,准备重启设备...", 2000);
-
- // 产测开始确认 - 按钮变绿色并禁用
- ui->openButton_2->setStyleSheet("QPushButton { background-color: #28A745; color: white; padding: 5px 10px; border: none; border-radius: 3px; }");
- ui->openButton_2->setEnabled(false);
- qDebug() << "产测开始确认 - 按钮已变绿色并禁用";
-
- // 延迟2秒后发送重启指令
- QTimer::singleShot(2000, this, [this]() {
- if (isProductionTestRunning && currentTestStep == TEST_RESET) {
- ui->statusbar->showMessage("产测模式已开启 - 重启设备中...", 3000);
- qDebug() << "工厂模式确认后发送设备重启指令";
- ui->recvTextEdit->append(">>> 发送指令: AT^RESET (恢复出厂设置/重启设备)");
- serial->write("AT^RESET\r\n");
- qDebug() << "发送设备重启指令: AT^RESET";
-
- // 切换到等待BuildVer状态
- currentTestStep = TEST_WAIT_BUILDVER;
- qDebug() << "等待设备重启完成,寻找BuildVer标志...";
- }
- });
-
- } else if (cmd == 0) {
- // cmd=0 表示退出产测模式
- qDebug() << "工厂模式退出确认 (cmd=0)";
- ui->statusbar->showMessage("工厂模式已退出", 2000);
-
- } else {
- // 未知的cmd值
- qDebug() << "未知的工厂模式命令值:" << cmd;
- ui->statusbar->showMessage("收到未知的工厂模式命令", 2000);
- }
- } else {
- // 无法解析cmd值,使用旧的逻辑作为备用
- qDebug() << "无法解析工厂模式命令值,使用旧逻辑";
-
- // 停止超时检测,因为已经收到确认
+
+ int cmd = -1;
+ QRegExp reFacotry("(?:fac:)?enter or exit facotry mode\\s*:\\s*(\\d+)", Qt::CaseInsensitive);
+ QRegExp reFactory("(?:fac:)?enter or exit factory mode\\s*:\\s*(\\d+)", Qt::CaseInsensitive);
+ if (reFacotry.indexIn(data) != -1) {
+ cmd = reFacotry.cap(1).toInt();
+ } else if (reFactory.indexIn(data) != -1) {
+ cmd = reFactory.cap(1).toInt();
+ }
+
+ if (cmd >= 0) {
+ qDebug() << "解析到工厂模式命令:" << cmd << "(1=进入产测, 0=退出产测)";
+
+ if (cmd == 1) {
if (testTimeoutTimer->isActive()) {
testTimeoutTimer->stop();
- qDebug() << "工厂模式确认收到,停止超时检测";
+ qDebug() << "工厂模式进入确认收到,停止超时检测";
}
-
- qDebug() << "工厂模式进入成功确认 (备用逻辑)";
- ui->statusbar->showMessage("工厂模式进入成功,准备重启设备...", 2000);
-
- // 延迟2秒后发送重启指令
- QTimer::singleShot(2000, this, [this]() {
- if (isProductionTestRunning && currentTestStep == TEST_RESET) {
- ui->statusbar->showMessage("产测模式已开启 - 重启设备中...", 3000);
- qDebug() << "工厂模式确认后发送设备重启指令";
- ui->recvTextEdit->append(">>> 发送指令: AT^RESET (恢复出厂设置/重启设备)");
- serial->write("AT^RESET\r\n");
- qDebug() << "发送设备重启指令: AT^RESET";
-
- // 切换到等待BuildVer状态
- currentTestStep = TEST_WAIT_BUILDVER;
- qDebug() << "等待设备重启完成,寻找BuildVer标志...";
- }
- });
+
+ qDebug() << "工厂模式进入成功确认 (cmd=1)";
+ ui->statusbar->showMessage("工厂模式进入成功,等待 PMADDVOTE OK...", 2000);
+
+ ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }");
+ qDebug() << "工厂模式进入成功,已发 PMADDVOTE 链后将根据 OK 把产测按钮变绿";
+
+ currentTestStep = TEST_PMADDVOTE_INIT;
+ qDebug() << "不执行 AT^RESET,直接进入 PMADDVOTE / ENTERTESTVIEW";
+ runPostFactoryProductionInit();
+
+ } else if (cmd == 0) {
+ qDebug() << "工厂模式退出确认 (cmd=0)";
+ ui->statusbar->showMessage("工厂模式已退出", 2000);
+
+ } else {
+ qDebug() << "未知的工厂模式命令值:" << cmd;
+ ui->statusbar->showMessage("收到未知的工厂模式命令", 2000);
+ }
+ } else {
+ qDebug() << "无法解析工厂模式命令值,使用备用逻辑";
+
+ if (testTimeoutTimer->isActive()) {
+ testTimeoutTimer->stop();
+ qDebug() << "工厂模式确认收到,停止超时检测";
}
+
+ qDebug() << "工厂模式进入成功确认 (备用逻辑)";
+ ui->statusbar->showMessage("工厂模式进入成功,等待 PMADDVOTE OK...", 2000);
+
+ ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }");
+
+ currentTestStep = TEST_PMADDVOTE_INIT;
+ qDebug() << "不执行 AT^RESET,直接进入 PMADDVOTE / ENTERTESTVIEW (备用解析路径)";
+ runPostFactoryProductionInit();
}
}
}
}
-// 检查BuildVer启动完成
+// 工厂确认或重启后:PMADDVOTE → ENTERTESTVIEW → LCD
+void MainWindow::runPostFactoryProductionInit()
+{
+ if (!isProductionTestRunning || !serial || !serial->isOpen()) {
+ qDebug() << "runPostFactoryProductionInit: 产测未运行或串口未打开,跳过";
+ return;
+ }
+ if (postFactoryVoteSequenceStarted) {
+ qDebug() << "runPostFactoryProductionInit: 初始化链已在执行,忽略重复调用";
+ return;
+ }
+ postFactoryVoteSequenceStarted = true;
+ waitingPmaddvoteOkForGreenButton = true;
+
+ serial->write("AT^PMADDVOTE\r\n");
+ qDebug() << "发送AT^PMADDVOTE指令(第1次): AT^PMADDVOTE";
+
+ QTimer::singleShot(500, this, [this]() {
+ if (isProductionTestRunning && serial->isOpen()) {
+ serial->write("AT^PMADDVOTE\r\n");
+ qDebug() << "发送AT^PMADDVOTE指令(第2次): AT^PMADDVOTE";
+
+ if (serial->isOpen()) {
+ ui->recvTextEdit->append(">>> 发送指令: AT^ENTERTESTVIEW (进入产测界面)");
+ serial->write("AT^ENTERTESTVIEW\r\n");
+ qDebug() << "发送AT^ENTERTESTVIEW (进入产测界面)";
+ }
+
+ QTimer::singleShot(1000, this, [this]() {
+ 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();
+ }
+ });
+ }
+ });
+}
+
+void MainWindow::tryAdvanceProductionAfterBootKeywords(const QString& data)
+{
+ if (!isProductionTestRunning || currentTestStep != TEST_WAIT_BOOT) {
+ return;
+ }
+
+ const QStringList keywords = configManager.getBootDetectionKeywords();
+ if (keywords.isEmpty()) {
+ return;
+ }
+
+ for (const QString& keyword : keywords) {
+ if (data.contains(keyword, Qt::CaseInsensitive)) {
+ qDebug() << "产测:检测到开机完成关键字:" << keyword << ",数据片段:" << data.left(120);
+ appendToLogFile(QString("=== 产测流程-检测到开机完成: %1 ===\n").arg(keyword));
+
+ bootDetected = true;
+ currentTestStep = TEST_PMADDVOTE_INIT;
+
+ if (testTimeoutTimer->isActive()) {
+ testTimeoutTimer->stop();
+ }
+
+ ui->statusbar->showMessage("设备已开机,正在发送 PMADDVOTE / ENTERTESTVIEW…", 3000);
+ ui->recvTextEdit->append(">>> 已检测到开机完成,进入 PMADDVOTE / ENTERTESTVIEW 初始化链(未发 AT^FACTORY=1)");
+
+ runPostFactoryProductionInit();
+ return;
+ }
+ }
+}
+
+void MainWindow::tryApplyProductionStartGreenAfterPmaddvoteOk(const QString& line)
+{
+ if (!waitingPmaddvoteOkForGreenButton || !isProductionTestRunning ||
+ currentTestStep != TEST_PMADDVOTE_INIT) {
+ return;
+ }
+ const QString t = line.trimmed();
+ if (t.compare(QStringLiteral("OK"), Qt::CaseInsensitive) != 0) {
+ return;
+ }
+ waitingPmaddvoteOkForGreenButton = false;
+ ui->openButton_2->setStyleSheet("QPushButton { background-color: #28A745; color: white; padding: 5px 10px; border: none; border-radius: 3px; }");
+ ui->openButton_2->setEnabled(false);
+ qDebug() << "收到 AT^PMADDVOTE 的 OK 响应,产测按钮已变绿并禁用";
+ ui->statusbar->showMessage("PMADDVOTE 成功,产测进行中", 2000);
+}
+
+// 检查BuildVer启动完成(仅当仍使用「先重启再等 BuildVer」时使用)
void MainWindow::checkBuildVerResult(const QString& data)
{
- // 检测设备启动完成标志,只在等待BuildVer阶段检测(大小写不敏感)
- if (data.contains("BuildVer", Qt::CaseInsensitive) && currentTestStep == TEST_WAIT_BUILDVER &&
+ if (data.contains("BuildVer", Qt::CaseInsensitive) && currentTestStep == TEST_WAIT_BUILDVER &&
isProductionTestRunning) {
-
+
qDebug() << "检测到BuildVer启动完成标志:" << data.trimmed();
- qDebug() << "设备重启完成,发送AT^PMADDVOTE指令";
-
- ui->statusbar->showMessage("设备重启完成,发送初始化指令...", 2000);
-
- // 发送第一次AT^PMADDVOTE指令
- serial->write("AT^PMADDVOTE\r\n");
- qDebug() << "发送AT^PMADDVOTE指令(第1次): AT^PMADDVOTE";
-
- // 延迟0.5秒后发送第二次AT^PMADDVOTE指令
- QTimer::singleShot(500, this, [this]() {
- if (isProductionTestRunning && serial->isOpen()) {
- serial->write("AT^PMADDVOTE\r\n");
- qDebug() << "发送AT^PMADDVOTE指令(第2次): AT^PMADDVOTE";
-
- // 开机初始化完成后,进入产测界面(满足AT^ENTERTESTVIEW要求)
- if (serial->isOpen()) {
- ui->recvTextEdit->append(">>> 发送指令: AT^ENTERTESTVIEW (进入产测界面)");
- serial->write("AT^ENTERTESTVIEW\r\n");
- qDebug() << "发送AT^ENTERTESTVIEW (进入产测界面)";
- }
-
- // 初始化完成后,切换到 LCD(若启用);功耗测试在 GPS 之后
- QTimer::singleShot(1000, this, [this]() {
- 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();
- }
- });
- }
- });
+ ui->statusbar->showMessage("设备启动完成,发送初始化指令...", 2000);
+
+ currentTestStep = TEST_PMADDVOTE_INIT;
+ runPostFactoryProductionInit();
}
}
gSensorIntervalTimer->stop();
bluetoothTestTimer->stop();
isProductionTestRunning = false;
+ postFactoryVoteSequenceStarted = false;
+ waitingPmaddvoteOkForGreenButton = false;
currentTestStep = TEST_IDLE;
// 关闭测试日志文件
// 开始产测流程
isProductionTestRunning = true;
+ postFactoryVoteSequenceStarted = false;
+ waitingPmaddvoteOkForGreenButton = false;
+ recvBuffer.clear();
testStartTime = QDateTime::currentDateTime(); // 记录测试开始时间
testStartTimeMap.clear();
testDurationSecMap.clear();
- currentTestStep = TEST_RESET;
+ currentTestStep = TEST_WAIT_BOOT;
currentLcdColor = 1; // 从红色开始
// 在开始新测试前,尽量保存当前UI日志(如果有内容)
ui->statusbar->showMessage("开始产测流程...", 2000);
qDebug() << "=== 开始产测流程 ===";
- qDebug() << "流程: 产测开启(AT^FACTORY=1) → 设备重启 → … → 全部完成后弹窗确认 → AT^RESTORE(恢复出厂) → AT^POWEROFF(关机)";
+ qDebug() << "流程: 等待开机完成 → 跳过 AT^FACTORY=1 → PMADDVOTE/ENTERTESTVIEW → 各测试项 → 完成后弹窗确认等";
qDebug() << "LCD测试: 仅发送 AT^LCDTEST=1";
- // 发送产测开启指令,等待工厂模式确认
- qDebug() << "Step 1: 发送产测开启指令";
- ui->statusbar->showMessage("发送产测开启指令,等待设备确认...", 3000);
- ui->recvTextEdit->append(">>> 发送指令: AT^FACTORY=1 (开始产测)");
- serial->write("AT^FACTORY=1\r\n");
- qDebug() << "发送产测开启指令(第1次): AT^FACTORY=1,等待接收 'fac:enter or exit facotry mode' 确认";
-
- // 延迟0.5秒后再发送一次,确保设备接收到指令
- QTimer::singleShot(500, this, [this]() {
- if (isProductionTestRunning && serial->isOpen()) {
- ui->recvTextEdit->append(">>> 发送指令: AT^FACTORY=1 (开始产测 - 第2次)");
- serial->write("AT^FACTORY=1\r\n");
- qDebug() << "发送产测开启指令(第2次): AT^FACTORY=1";
- }
- });
-
- // 启动10秒超时检测,如果没有收到工厂模式确认则提示
- testTimeoutTimer->start(10000);
+ // 不再发送 AT^FACTORY=1:固件侧常会触发整机重启;在开机完成后再发 PMADDVOTE / ENTERTESTVIEW
+ qDebug() << "Step 1: 等待串口开机关键字(bootDetectionKeywords),然后 PMADDVOTE / ENTERTESTVIEW";
+
+ ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }");
+ ui->openButton_2->setEnabled(true);
+ qDebug() << "产测开始 - 先等开机完成;之后等待 AT^PMADDVOTE 回复 OK 后按钮变绿(期间可再点此按钮停止)";
+
+ const QStringList bootKws = configManager.getBootDetectionKeywords();
+ if (bootKws.isEmpty()) {
+ qDebug() << "bootDetectionKeywords 为空,跳过等待开机";
+ ui->recvTextEdit->append(">>> 未配置开机关键字,跳过等待,直接发送 PMADDVOTE / ENTERTESTVIEW(未发 AT^FACTORY=1)");
+ ui->statusbar->showMessage("未配置开机关键字,直接初始化…", 3000);
+ currentTestStep = TEST_PMADDVOTE_INIT;
+ runPostFactoryProductionInit();
+ } else {
+ ui->recvTextEdit->append(">>> 等待设备开机完成(与 settings 中 bootDetectionKeywords 匹配后,再发 PMADDVOTE / ENTERTESTVIEW)");
+ ui->statusbar->showMessage("等待设备开机完成… 请上电或重启设备", 0);
+ testTimeoutTimer->stop();
+ testTimeoutTimer->start(120000);
+ }
}
// 执行录音测试(配置了等级标准时共测 3 轮,任一轮「实际等级 >= 设置等级」则整体通过)
// 根据当前测试步骤确定测试名称
switch (currentTestStep) {
+ case TEST_WAIT_BOOT:
+ qDebug() << "等待设备开机超时,未匹配到 bootDetectionKeywords";
+ ui->statusbar->showMessage("等待开机超时,请检查设备或关键字配置", 5000);
+ QMessageBox::warning(this, "等待开机超时",
+ QStringLiteral("在 120 秒内未在串口日志中检测到开机关键字(bootDetectionKeywords)。\n"
+ "请确认设备已上电/重启,或在 settings.json 中配置与固件日志一致的关键字。"));
+ isProductionTestRunning = false;
+ waitingPmaddvoteOkForGreenButton = false;
+ postFactoryVoteSequenceStarted = false;
+ currentTestStep = TEST_IDLE;
+ ui->openButton_2->setStyleSheet("QPushButton { background-color: #4A90E2; color: white; padding: 5px 10px; border: none; border-radius: 3px; }");
+ ui->openButton_2->setEnabled(true);
+ return;
+
case TEST_RESET:
// 工厂模式进入超时
qDebug() << "工厂模式进入超时,未收到确认消息";
// 重置产测状态变量
isProductionTestRunning = false;
+ postFactoryVoteSequenceStarted = false;
+ waitingPmaddvoteOkForGreenButton = false;
currentTestStep = TEST_IDLE;
currentLcdColor = 0;