From: SnickerSun Date: Fri, 5 Dec 2025 05:03:23 +0000 (+0800) Subject: release LN factorytool V1.1 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=1336b5681c0f68ae1752e975aba49721c1b82b33;p=mirrors%2Ffactory_tool.git release LN factorytool V1.1 --- diff --git a/config_manager.cpp b/config_manager.cpp new file mode 100644 index 0000000..36f73a7 --- /dev/null +++ b/config_manager.cpp @@ -0,0 +1,279 @@ +#include "config_manager.h" +#include +#include +#include +#include +#include +#include +#include + +ConfigManager::ConfigManager() + : configLoaded(false) +{ + setDefaultConfig(); +} + +ConfigManager::~ConfigManager() +{ +} + +void ConfigManager::setDefaultConfig() +{ + // 设置默认配置 + QJsonObject defaultConfig; + + // 默认开机检测关键字 + QJsonArray bootKeywords; + bootKeywords.append("BuildVer"); + bootKeywords.append("NAND flash ID"); + bootKeywords.append("NAND ID:"); + defaultConfig["bootDetectionKeywords"] = bootKeywords; + + // 默认版本信息获取指令 + QJsonArray versionCommands; + versionCommands.append("AT^CAT1GETVER"); + versionCommands.append("AT^CAT1GETSIGNAL"); + versionCommands.append("AT^FACTORY"); + defaultConfig["versionInfoCommands"] = versionCommands; + + // 默认产测模式检测指令 + defaultConfig["factoryModeCheckCommand"] = "AT^FACTORY"; + + // 默认产测模式关键字 + QJsonArray factoryKeywords; + factoryKeywords.append("FACTORY TEST MODE:"); + defaultConfig["factoryModeKeywords"] = factoryKeywords; + + // 默认测试参数配置 + QJsonObject testConfig; + testConfig["portName"] = ""; + testConfig["audioVolume"] = "2.0"; + testConfig["audioLevelStandard"] = "中"; + testConfig["expectedModemVer"] = ""; + testConfig["expectedPYVer"] = ""; + testConfig["expectedVer"] = ""; + testConfig["bluetoothAddress"] = ""; + testConfig["bluetoothRSSI"] = ""; + defaultConfig["testConfig"] = testConfig; + + configObject = defaultConfig; + configLoaded = true; +} + +bool ConfigManager::loadConfig(const QString& configPath) +{ + QString filePath = configPath; + if (filePath.isEmpty()) { + // 默认路径:应用程序目录下的settings.json + QString appPath = QCoreApplication::applicationDirPath(); + filePath = appPath + "/settings.json"; + } + + QFile file(filePath); + if (!file.exists()) { + qDebug() << "配置文件不存在,使用默认配置并创建文件:" << filePath; + setDefaultConfig(); + + // 创建配置文件目录(如果不存在) + QFileInfo fileInfo(filePath); + QDir dir = fileInfo.absoluteDir(); + if (!dir.exists()) { + dir.mkpath("."); + } + + // 将默认配置保存到文件 + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QJsonDocument doc(configObject); + file.write(doc.toJson()); + file.close(); + qDebug() << "已创建默认配置文件:" << filePath; + configLoaded = true; + return true; + } else { + qDebug() << "无法创建配置文件:" << filePath << "错误:" << file.errorString(); + configLoaded = true; // 即使文件创建失败,也使用默认配置 + return false; + } + } + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << "无法打开配置文件:" << filePath << "错误:" << file.errorString(); + setDefaultConfig(); + return false; + } + + QByteArray data = file.readAll(); + file.close(); + + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(data, &error); + + if (error.error != QJsonParseError::NoError) { + qDebug() << "配置文件JSON解析错误:" << error.errorString(); + setDefaultConfig(); + return false; + } + + if (!doc.isObject()) { + qDebug() << "配置文件格式错误:不是JSON对象"; + setDefaultConfig(); + return false; + } + + configObject = doc.object(); + configLoaded = true; + + // 合并默认配置(如果配置文件中缺少某些项,使用默认值) + QJsonObject defaultConfig; + setDefaultConfig(); + defaultConfig = configObject; + + // 重新加载文件配置 + doc = QJsonDocument::fromJson(data, &error); + configObject = doc.object(); + + // 合并缺失的配置项 + if (!configObject.contains("bootDetectionKeywords")) { + configObject["bootDetectionKeywords"] = defaultConfig["bootDetectionKeywords"]; + } + if (!configObject.contains("versionInfoCommands")) { + configObject["versionInfoCommands"] = defaultConfig["versionInfoCommands"]; + } + if (!configObject.contains("factoryModeCheckCommand")) { + configObject["factoryModeCheckCommand"] = defaultConfig["factoryModeCheckCommand"]; + } + if (!configObject.contains("factoryModeKeywords")) { + configObject["factoryModeKeywords"] = defaultConfig["factoryModeKeywords"]; + } + if (!configObject.contains("testConfig")) { + configObject["testConfig"] = defaultConfig["testConfig"]; + } else { + // 合并testConfig中的缺失项 + QJsonObject savedTestConfig = configObject["testConfig"].toObject(); + QJsonObject defaultTestConfig = defaultConfig["testConfig"].toObject(); + for (auto it = defaultTestConfig.begin(); it != defaultTestConfig.end(); ++it) { + if (!savedTestConfig.contains(it.key())) { + savedTestConfig[it.key()] = it.value(); + } + } + configObject["testConfig"] = savedTestConfig; + } + + qDebug() << "配置文件加载成功:" << filePath; + return true; +} + +QStringList ConfigManager::getBootDetectionKeywords() const +{ + QStringList keywords; + if (configObject.contains("bootDetectionKeywords") && + configObject["bootDetectionKeywords"].isArray()) { + QJsonArray array = configObject["bootDetectionKeywords"].toArray(); + for (int i = 0; i < array.size(); ++i) { + if (array[i].isString()) { + keywords.append(array[i].toString()); + } + } + } + return keywords; +} + +QStringList ConfigManager::getVersionInfoCommands() const +{ + QStringList commands; + if (configObject.contains("versionInfoCommands") && + configObject["versionInfoCommands"].isArray()) { + QJsonArray array = configObject["versionInfoCommands"].toArray(); + for (int i = 0; i < array.size(); ++i) { + if (array[i].isString()) { + commands.append(array[i].toString()); + } + } + } + return commands; +} + +QString ConfigManager::getFactoryModeCheckCommand() const +{ + if (configObject.contains("factoryModeCheckCommand") && + configObject["factoryModeCheckCommand"].isString()) { + return configObject["factoryModeCheckCommand"].toString(); + } + return "AT^FACTORY"; +} + +QStringList ConfigManager::getFactoryModeKeywords() const +{ + QStringList keywords; + if (configObject.contains("factoryModeKeywords") && + configObject["factoryModeKeywords"].isArray()) { + QJsonArray array = configObject["factoryModeKeywords"].toArray(); + for (int i = 0; i < array.size(); ++i) { + if (array[i].isString()) { + keywords.append(array[i].toString()); + } + } + } + return keywords; +} + +bool ConfigManager::isValid() const +{ + return configLoaded; +} + +// 获取测试参数配置值 +QString ConfigManager::getTestConfig(const QString& key, const QString& defaultValue) const +{ + if (configObject.contains("testConfig") && configObject["testConfig"].isObject()) { + QJsonObject testConfig = configObject["testConfig"].toObject(); + if (testConfig.contains(key) && testConfig[key].isString()) { + return testConfig[key].toString(); + } + } + return defaultValue; +} + +// 设置测试参数配置值 +void ConfigManager::setTestConfig(const QString& key, const QString& value) +{ + if (!configObject.contains("testConfig") || !configObject["testConfig"].isObject()) { + configObject["testConfig"] = QJsonObject(); + } + QJsonObject testConfig = configObject["testConfig"].toObject(); + testConfig[key] = value; + configObject["testConfig"] = testConfig; +} + +// 保存配置到文件 +bool ConfigManager::saveConfig(const QString& configPath) +{ + QString filePath = configPath; + if (filePath.isEmpty()) { + // 默认路径:应用程序目录下的settings.json + QString appPath = QCoreApplication::applicationDirPath(); + filePath = appPath + "/settings.json"; + } + + // 创建配置文件目录(如果不存在) + QFileInfo fileInfo(filePath); + QDir dir = fileInfo.absoluteDir(); + if (!dir.exists()) { + dir.mkpath("."); + } + + // 保存到文件 + QFile file(filePath); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + qDebug() << "无法保存配置文件:" << filePath << "错误:" << file.errorString(); + return false; + } + + QJsonDocument doc(configObject); + file.write(doc.toJson()); + file.close(); + + qDebug() << "配置文件已保存:" << filePath; + return true; +} + diff --git a/config_manager.h b/config_manager.h new file mode 100644 index 0000000..cd4a45c --- /dev/null +++ b/config_manager.h @@ -0,0 +1,40 @@ +#ifndef CONFIG_MANAGER_H +#define CONFIG_MANAGER_H + +#include +#include +#include + +class ConfigManager +{ +public: + ConfigManager(); + ~ConfigManager(); + + // 加载配置文件 + bool loadConfig(const QString& configPath = QString()); + + // 获取配置项 + QStringList getBootDetectionKeywords() const; + QStringList getVersionInfoCommands() const; + QString getFactoryModeCheckCommand() const; + QStringList getFactoryModeKeywords() const; + + // 测试参数配置相关方法 + QString getTestConfig(const QString& key, const QString& defaultValue = "") const; + void setTestConfig(const QString& key, const QString& value); + bool saveConfig(const QString& configPath = QString()); // 保存配置到文件 + + // 检查配置是否有效 + bool isValid() const; + +private: + QJsonObject configObject; + bool configLoaded; + + // 默认配置 + void setDefaultConfig(); +}; + +#endif // CONFIG_MANAGER_H + diff --git a/factory_tool.pro b/factory_tool.pro index b9290e6..5b5038e 100644 --- a/factory_tool.pro +++ b/factory_tool.pro @@ -14,11 +14,13 @@ CODECFORSRC = UTF-8 # 源文件列表 SOURCES += \ main.cpp \ - mainwindow.cpp + mainwindow.cpp \ + config_manager.cpp # 头文件列表 HEADERS += \ - mainwindow.h + mainwindow.h \ + config_manager.h # UI 文件列表(关键:必须包含 mainwindow.ui) FORMS += \ diff --git a/mainwindow.cpp b/mainwindow.cpp index d7e7963..33a9162 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,5 +1,6 @@ #include "mainwindow.h" #include "ui_mainwindow.h" +#include "config_manager.h" #include #include #include @@ -35,13 +36,16 @@ MainWindow::MainWindow(QWidget *parent) QTextCodec::setCodecForCStrings(utf8Codec); QTextCodec::setCodecForTr(utf8Codec); #endif - + // 初始化串口对象 serial = new QSerialPort(this); connect(serial, &QSerialPort::readyRead, this, &MainWindow::readSerialData); // 初始刷新串口列表 updateSerialPorts(); + + // 从settings.json加载测试参数 + loadTestConfigFromSettings(); // 初始化按钮样式(可选:设置默认样式) ui->openButton->setStyleSheet("QPushButton { padding: 5px 10px; }"); @@ -101,6 +105,20 @@ MainWindow::MainWindow(QWidget *parent) testLogFile = nullptr; testLogStream = nullptr; testLogFilePath = ""; + // 初始化配置管理器 + configManager.loadConfig(); + // 初始化开机检测相关变量 + bootDetected = false; + factoryModeChecked = false; + versionInfoFetched = false; + // 初始化版本信息获取相关变量 + versionCommandQueue.clear(); + currentVersionCommandIndex = -1; + versionCommandTimer = new QTimer(this); + connect(versionCommandTimer, &QTimer::timeout, this, &MainWindow::onVersionCommandTimeout); + + // 从settings.json加载测试参数 + loadTestConfigFromSettings(); // 初始化按键测试状态 for (int i = 0; i < 4; i++) { @@ -121,6 +139,9 @@ MainWindow::MainWindow(QWidget *parent) MainWindow::~MainWindow() { + // 保存测试参数到settings.json + saveTestConfigToSettings(); + // 关闭日志文件 closeTestLogFile(); @@ -175,13 +196,13 @@ void MainWindow::on_openButton_clicked() ui->openButton->setStyleSheet("QPushButton { padding: 5px 10px; }"); return; } - + // 检查是否选择了串口 if (ui->portNameBox->currentText().isEmpty()) { QMessageBox::warning(this, "警告", "请先选择串口"); return; } - + // 配置串口参数(固定值) QString portText = ui->portNameBox->currentText(); QString portName = portText.left(portText.indexOf(" (")); @@ -221,7 +242,7 @@ void MainWindow::on_sendButton_clicked() QMessageBox::warning(this, "警告", "请先打开串口"); return; } - + // 获取发送区文本 QString sendStr = ui->sendTextEdit->toPlainText(); if (sendStr.isEmpty()) return; @@ -499,7 +520,7 @@ void MainWindow::ShowPppInfoIMEI(const QString& data) // 提取IMEI信息 imeiInfo = data.mid(start, end - start).trimmed(); qDebug() << "使用imei:格式提取IMEI:" << imeiInfo; - } else { + } else { qDebug() << "未找到任何IMEI格式,数据:" << data.trimmed(); return; } @@ -637,11 +658,11 @@ void MainWindow::ShowPppInfoModemVer(const QString& data) if (modemPattern.indexIn(data) != -1) { modemVerInfo = modemPattern.cap(1); qDebug() << "使用括号格式提取Modem Version:" << modemVerInfo; - } else { + } else { qDebug() << "未找到Modem Version信息,数据格式:" << data.trimmed(); - return; + return; + } } - } } // 验证Modem Version是否有效(不为空即可) @@ -945,7 +966,7 @@ void MainWindow::readSerialData() if (recvData.isEmpty()) { return; } - + // 将新接收的数据追加到缓存 recvBuffer += QString::fromUtf8(recvData); @@ -966,6 +987,30 @@ void MainWindow::readSerialData() if (line.startsWith("fac:")) { appendToLogFile(processLine); } + + // 开机检测(仅在未检测到开机时执行) + // 同时检查原始行和去掉fac:前缀的行,确保能匹配到关键字 + if (!bootDetected && !isProductionTestRunning) { + checkBootDetection(line); + // 如果原始行没匹配到,也检查去掉fac:前缀的行 + if (!bootDetected && processLine != line) { + checkBootDetection(processLine); + } + } + + // 产测模式检测(在检测到开机后执行) + if (bootDetected && !factoryModeChecked && !isProductionTestRunning) { + checkFactoryMode(line); + } + + // 版本信息获取:当正在获取版本信息时,接收到数据后继续发送下一条指令 + if (versionInfoFetched && currentVersionCommandIndex >= 0 && + currentVersionCommandIndex < versionCommandQueue.size() && + !isProductionTestRunning) { + // 如果当前指令的响应已收到(通过超时或检测到响应),继续下一条 + // 这里主要通过超时机制来推进,但也可以检测到特定响应后立即推进 + // 暂时依赖超时机制,如果需要可以添加响应检测逻辑 + } // 处理所有数据提取(不管是否以fac:开头)(大小写不敏感) if (processLine.indexOf("BuildVer:", 0, Qt::CaseInsensitive) != -1) { @@ -985,6 +1030,46 @@ void MainWindow::readSerialData() parseWstpPrintData(line); } + // 检测FACTORY TEST MODE状态(wstp_print格式) + if (line.contains("FACTORY TEST MODE:", Qt::CaseInsensitive)) { + qDebug() << "检测到FACTORY TEST MODE信息:" << line.trimmed(); + appendToLogFile(QString("检测到FACTORY TEST MODE信息: %1\n").arg(line.trimmed())); + + if (line.contains("FACTORY TEST MODE: ENABLED", Qt::CaseInsensitive)) { + // 产测模式已开启 + ui->factoryModeLineEdit->setText("是"); + ui->factoryModeLineEdit->setStyleSheet("background-color: #ffcccc;"); // 红底 + qDebug() << "产测模式: 已开启"; + appendToLogFile(QString("=== 产测模式状态: 已开启 ===\n")); + + // 如果还未标记为已检测,标记并开始获取版本信息 + if (!factoryModeChecked) { + factoryModeChecked = true; + QTimer::singleShot(1000, this, [this]() { + if (!versionInfoFetched) { + startVersionInfoFetch(); + } + }); + } + } else if (line.contains("FACTORY TEST MODE: DISABLED", Qt::CaseInsensitive)) { + // 产测模式已关闭 + ui->factoryModeLineEdit->setText("否"); + ui->factoryModeLineEdit->setStyleSheet("background-color: #ccffcc;"); // 绿底 + qDebug() << "产测模式: 已关闭"; + appendToLogFile(QString("=== 产测模式状态: 已关闭 ===\n")); + + // 如果还未标记为已检测,标记并开始获取版本信息 + if (!factoryModeChecked) { + factoryModeChecked = true; + QTimer::singleShot(1000, this, [this]() { + if (!versionInfoFetched) { + startVersionInfoFetch(); + } + }); + } + } + } + // 检测设备信息数据(去掉[PPP_INFO]限制,支持多种格式)(大小写不敏感) // 检测包含@sim:的数据(可能是IMEI数据和4G信号数据) if (line.contains("@sim:") || processLine.contains("@sim:")) { @@ -1280,22 +1365,22 @@ void MainWindow::performLcdColorTest() QString colorName; int colorCommand; switch (currentLcdColor) { - case 1: + case 1: colorName = "红色"; colorCommand = 6; // AT^LCDTEST=6 红色 - break; - case 2: + break; + case 2: colorName = "绿色"; colorCommand = 3; // AT^LCDTEST=3 绿色 - break; - case 3: + break; + case 3: colorName = "蓝色"; colorCommand = 4; // AT^LCDTEST=4 蓝色 - break; - default: + break; + default: colorName = "未知"; colorCommand = 6; - break; + break; } ui->statusbar->showMessage("LCD测试中 - " + colorName + " (1秒)", 1000); @@ -1367,7 +1452,7 @@ void MainWindow::performMotorTest() qDebug() << "currentTestStep:" << currentTestStep << "期望:" << TEST_MOTOR; return; } - + qDebug() << "开始马达测试"; // 重置马达测试状态 @@ -1431,7 +1516,7 @@ void MainWindow::perform4GTest() qDebug() << "4G测试跳过 - 产测未运行"; return; } - + initRetry4GCount++; qDebug() << "4G测试 - 初始化尝试次数:" << initRetry4GCount; @@ -1766,7 +1851,7 @@ void MainWindow::showLcdTestConfirmDialog() qDebug() << "LCD确认弹窗已显示过,跳过"; return; } - + qDebug() << "显示LCD测试确认弹窗"; // 标记弹窗已显示,避免重复弹出 @@ -2238,7 +2323,7 @@ void MainWindow::checkKeyTestResult(const QString& data) for (int i = 0; i < 4; i++) { if (keyTestStatus[i] == 0) { allKeysTested = false; - break; + break; } } @@ -2401,7 +2486,7 @@ void MainWindow::updateTestStatus(const QString& testName, TestStatus status) statusText = "未测试"; iconColor = "#888888"; textColor = "#888888"; - break; + break; case STATUS_TESTING: iconText = "●"; statusText = "测试中"; @@ -2491,7 +2576,7 @@ void MainWindow::updateOverallStatus() overallIcon = "✓"; overallText = "通过"; overallColor = "#4CAF50"; - } else { + } else { // 任何其他情况(失败、测试中、等待开始等)都显示为未通过 overallIcon = "✗"; overallText = "未通过"; @@ -2611,7 +2696,7 @@ QString MainWindow::saveTestRecord() finalContent += "开始时间,结束时间,测试耗时,软件版本,IMEI,ICCID,Modem版本,PYVER版本,LCD测试,马达测试,按键测试,录音测试,电池测试,G-sensor测试,蓝牙测试,4G测试,整体结果\n"; finalContent += newDataLine; qDebug() << "创建新的CSV文件:" << csvFilePath; - } else { + } else { // 现有文件,需要检查ICCID是否重复 QFile existingFile(csvFilePath); if (!existingFile.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -2649,7 +2734,7 @@ QString MainWindow::saveTestRecord() finalContent += newDataLine; iccidFound = true; qDebug() << "找到相同ICCID,替换记录:" << iccid; - } else { + } else { // 保留不同ICCID的记录 finalContent += line + "\n"; } @@ -2703,10 +2788,25 @@ QString MainWindow::saveTestRecord() QDateTime endTime = QDateTime::currentDateTime(); *testLogStream << QString("=== 测试结束时间: %1 ===\n").arg(endTime.toString("yyyy-MM-dd hh:mm:ss")); *testLogStream << QString("测试记录已保存: %1\n").arg(csvFileName); + + // 将recvTextEdit的内容追加到测试日志文件 + QString recvContent = ui->recvTextEdit->toPlainText(); + if (!recvContent.isEmpty()) { + *testLogStream << "\n=== UI日志内容 ===\n"; + *testLogStream << recvContent; + *testLogStream << "\n=== UI日志结束 ===\n"; + } + testLogStream->flush(); } closeTestLogFile(); + // 保存UI日志到独立文件(如果有效) + saveRecvTextEditToLog(); + + // 清除UI中的日志内容,防止重复保存 + ui->recvTextEdit->clear(); + // 返回文件名供外部使用 return csvFileName; } @@ -2751,7 +2851,7 @@ void MainWindow::checkSignalAndSimValues(const QString& data) // 将signal值显示到界面 appendToLogFile(QString("Signal值: %1\n").arg(signalValue)); ui->statusbar->showMessage(QString("检测到Signal值: %1").arg(signalValue), 2000); - } else { + } else { qDebug() << "未找到signal值"; return; } @@ -2821,8 +2921,8 @@ void MainWindow::checkSignalAndSimValues(const QString& data) // 显示最终测试结果弹窗 showFinalTestResult(); - } - } else { + } + } else { // 测试失败 QString failReason; if (simValue != 1) { @@ -2928,7 +3028,7 @@ void MainWindow::sendPppCommand() // 启动5秒超时定时器,等待PPPINFO回复 test4GTimer->start(5000); qDebug() << "启动5秒超时定时器,等待PPPINFO回复"; - } else { + } else { // 超过3次后,改为等待signal和sim数据 qDebug() << "PPP数据已等待3次,改为等待signal和sim数据"; ui->statusbar->showMessage("4G测试中 - 等待signal和sim数据...", 5000); @@ -2958,7 +3058,7 @@ void MainWindow::on_openRecordsFolderButton_clicked() if (success) { qDebug() << "成功打开文件夹:" << saveDir; ui->statusbar->showMessage("已打开产测记录文件夹", 2000); - } else { + } else { qDebug() << "打开文件夹失败:" << saveDir; QMessageBox::warning(this, "打开失败", QString("无法打开文件夹:\n%1\n请检查路径是否存在或权限是否足够").arg(saveDir)); @@ -3014,6 +3114,21 @@ void MainWindow::on_openButton_2_clicked() 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"; + } + // 创建测试日志文件 createTestLogFile(); @@ -3022,6 +3137,11 @@ void MainWindow::on_openButton_2_clicked() ui->sendTextEdit->clear(); // 清空发送文本框 ui->statusbar->clearMessage(); // 清空状态栏 + // 重置开机检测状态 + bootDetected = false; + factoryModeChecked = false; + versionInfoFetched = false; + // 清空设备信息 ui->VerlineEdit->clear(); // 清空版本信息 ui->IMEIlineEdit->clear(); // 清空IMEI @@ -3092,6 +3212,16 @@ void MainWindow::performAudioTest() // 重置录音测试相关状态 audioMicMiddleConsecutiveCount = 0; audioTestFinished = false; + + // 获取音频测试通过标准(从UI中读取) + audioLevelStandard = "中"; // 默认值 + if (ui->recordVolumelineEdit) { + QString levelText = ui->recordVolumelineEdit->text().trimmed(); + if (!levelText.isEmpty()) { + audioLevelStandard = levelText; + } + } + qDebug() << "音频测试通过标准设置为:" << audioLevelStandard; // 发送录音测试指令:先 AT^AUDIOTEST=5 再 AT^AUDIOTEST=7 <音量> QString audioCmd1 = "AT^AUDIOTEST=5\r\n"; @@ -3117,7 +3247,7 @@ void MainWindow::performAudioTest() float v = volumeStr.toFloat(&ok); if (ok && v >= 0) { volume = v; - } else { + } else { qDebug() << "音量文本框内容非法,使用默认音量 2,原始值:" << volumeStr; } } else { @@ -3378,9 +3508,9 @@ void MainWindow::onAudioRecordTimer() return; } - // 8秒内未检测到连续5个"fac:mic level:中",判定录音测试失败 - qDebug() << "录音测试8秒超时,未检测到连续5个\"fac:mic level:中\",测试失败"; - ui->statusbar->showMessage("录音测试失败:8秒内未检测到连续5个\"fac:mic level:中\"", 3000); + // 8秒内未检测到连续3个设置的标准Level,判定录音测试失败 + qDebug() << QString("录音测试8秒超时,未检测到连续3个\"fac:mic level:%1\",测试失败").arg(audioLevelStandard); + ui->statusbar->showMessage(QString("录音测试失败:8秒内未检测到连续3个\"fac:mic level:%1\"").arg(audioLevelStandard), 3000); updateTestStatus("audio", STATUS_FAILED); audioTestFinished = true; @@ -3402,26 +3532,28 @@ void MainWindow::checkAudioTestResult(const QString& data) return; } - qDebug() << "录音测试收到数据:" << data.trimmed(); - qDebug() << "录音测试收到数据:" << data.trimmed(); - // 只在录音测试过程中统计“fac:mic level:中” + // 只在录音测试过程中统计"fac:mic level:"的值 if (data.contains("fac:mic level:")) { - if (data.contains("fac:mic level:中")) { + // 构建要检测的字符串 + QString targetLevel = QString("fac:mic level:%1").arg(audioLevelStandard); + + if (data.contains(targetLevel)) { audioMicMiddleConsecutiveCount++; - qDebug() << "检测到 \"fac:mic level:中\" ,当前连续计数:" - << audioMicMiddleConsecutiveCount; + qDebug() << QString("检测到 \"fac:mic level:%1\" ,当前连续计数: %2") + .arg(audioLevelStandard) + .arg(audioMicMiddleConsecutiveCount); } else { // 遇到其他 mic level 打印,连续计数清零 qDebug() << "检测到其他 mic level 打印,重置连续计数"; audioMicMiddleConsecutiveCount = 0; } - // 达到连续5次"fac:mic level:中"视为录音测试通过 + // 达到连续3次设置的标准Level视为录音测试通过 if (!audioTestFinished && audioMicMiddleConsecutiveCount >= 3) { - qDebug() << "录音测试通过:已检测到连续5个 \"fac:mic level:中\""; - ui->statusbar->showMessage("录音测试通过:检测到连续3个\"fac:mic level:中\"", 3000); + qDebug() << QString("录音测试通过:已检测到连续3个 \"fac:mic level:%1\"").arg(audioLevelStandard); + ui->statusbar->showMessage(QString("录音测试通过:检测到连续3个\"fac:mic level:%1\"").arg(audioLevelStandard), 3000); updateTestStatus("audio", STATUS_SUCCESS); audioTestFinished = true; @@ -3474,7 +3606,7 @@ void MainWindow::checkBatteryTestResult(const QString& data) if (!isProductionTestRunning || currentTestStep != TEST_BATTERY) { return; } - + qDebug() << "电池测试收到数据:" << data.trimmed(); // 解析电池数据,支持多种格式: @@ -3559,7 +3691,7 @@ void MainWindow::checkBatteryTestResult(const QString& data) int ret = msgBox.exec(); if (ret == QMessageBox::No) { updateTestStatus("battery", STATUS_FAILED); - return; + return; } } @@ -3597,7 +3729,7 @@ void MainWindow::checkBatteryTestResult(const QString& data) qDebug() << successMsg; ui->statusbar->showMessage(successMsg, 2000); updateTestStatus("battery", STATUS_SUCCESS); - } else { + } else { // 电压或温度异常 QString failMsg = QString("电池测试失败 - %1").arg(failReason); if (temp == -1.0 && !isVoltageNormal) { @@ -3886,7 +4018,7 @@ void MainWindow::checkBluetoothTestResult(const QString& data) perform4GTest(); } }); - } else { + } else { qDebug() << "RSSI不满足要求:" << rssi << "<" << rssiThreshold; ui->statusbar->showMessage(QString("蓝牙测试:检测到地址 %1,但RSSI %2 小于阈值 %3").arg(address).arg(rssi).arg(rssiThreshold), 2000); } @@ -3942,8 +4074,8 @@ void MainWindow::onBluetoothTestTimer() if (bluetoothTestFinished) { qDebug() << "蓝牙测试已在10秒内完成,不再处理超时"; - return; - } + return; + } // 检查是否使用指定地址+RSSI模式 QString targetAddress = ui->bluetoothAddressLineEdit->text().trimmed().toUpper(); @@ -4042,7 +4174,7 @@ void MainWindow::checkCat1SignalResult(const QString& data) // signal=99不计入平均值计算 qDebug() << "CAT1信号值为99,无效信号次数:" << cat1Signal99Count << "/" << cat1SignalReceivedCount; ui->statusbar->showMessage(QString("CAT1信号测试 (%1/5) 信号值:99 (无效信号)").arg(cat1SignalReceivedCount), 2000); - } else { + } else { // 累加有效信号值用于计算平均值 cat1SignalTotalValue += signalValue; if (signalValue > 25) { @@ -4055,8 +4187,8 @@ void MainWindow::checkCat1SignalResult(const QString& data) 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 { + } + } else { qDebug() << "CAT1信号测试未能解析signal值,数据:" << data.trimmed(); } } @@ -4197,7 +4329,7 @@ void MainWindow::onCat1SignalTimer() // 显示最终测试结果弹窗 showFinalTestResult(); } - } else { + } else { // 平均信号值小于25或没有有效数据,判定为失败 QString failReason; if (validCount == 0) { @@ -4670,13 +4802,18 @@ void MainWindow::showFinalTestResult() "}" ); - // 设置弹窗样式 + // 设置弹窗样式和字体(14号字,与UI一致) + QFont dialogFont = resultDialog.font(); + dialogFont.setPointSize(14); + resultDialog.setFont(dialogFont); + resultDialog.setStyleSheet( "QMessageBox { " "background-color: #f8f9fa; " + "font-size: 14pt; " "}" "QMessageBox QLabel { " - "font-size: 14px; " + "font-size: 14pt; " "line-height: 1.4; " "}" ); @@ -4753,8 +4890,8 @@ void MainWindow::onTestTimeout() default: qDebug() << "未知的测试步骤超时:" << currentTestStep; return; - } - + } + qDebug() << testDescription << "超时,10秒内未收到响应"; // 弹出超时提示对话框 @@ -4872,7 +5009,7 @@ void MainWindow::onTestTimeout() break; } - } else { + } else { // 用户选择停止测试 qDebug() << "用户选择停止测试"; ui->statusbar->showMessage("测试已停止", 2000); @@ -5082,6 +5219,376 @@ void MainWindow::on_openButton_4_clicked() serial->write("AT^FACTORY=3\r\n"); } +// 检测设备开机 +void MainWindow::checkBootDetection(const QString& data) +{ + if (bootDetected) { + return; // 已经检测到开机,不再重复检测 + } + + QStringList keywords = configManager.getBootDetectionKeywords(); + if (keywords.isEmpty()) { + qDebug() << "警告:bootDetectionKeywords 为空,无法进行开机检测"; + return; + } + + for (const QString& keyword : keywords) { + if (data.contains(keyword, Qt::CaseInsensitive)) { + qDebug() << "检测到设备开机关键字:" << keyword << ",数据片段:" << data.left(100); + appendToLogFile(QString("=== 检测到设备开机: %1 ===\n").arg(keyword)); + + bootDetected = true; + + // 延迟1秒后自动发送产测模式检测指令(无论是否有日志,都要检测) + QTimer::singleShot(1000, this, [this]() { + if (!factoryModeChecked && serial->isOpen()) { + QString cmd = configManager.getFactoryModeCheckCommand(); + if (!cmd.isEmpty()) { + // 如果是查询指令,确保使用 ? 参数 + if (!cmd.contains("?") && !cmd.contains("=")) { + cmd = cmd + "?"; + } + serial->write((cmd + "\r\n").toUtf8()); + qDebug() << "检测到开机,自动发送产测模式检测指令:" << cmd; + appendToLogFile(QString("=== 检测到开机,自动发送产测模式检测指令: %1 ===\n").arg(cmd)); + } else { + qDebug() << "产测模式检测指令为空,跳过检测"; + appendToLogFile(QString("=== 产测模式检测指令为空,跳过检测 ===\n")); + // 如果指令为空,直接标记为已检测,并开始获取版本信息 + factoryModeChecked = true; + QTimer::singleShot(1000, this, [this]() { + if (!versionInfoFetched) { + startVersionInfoFetch(); + } + }); + } + } else { + if (!serial->isOpen()) { + qDebug() << "串口未打开,无法发送产测模式检测指令"; + } else { + qDebug() << "产测模式已检测过,跳过发送检测指令"; + } + } + }); + + break; + } + } +} + +// 检测产测模式 +void MainWindow::checkFactoryMode(const QString& data) +{ + if (factoryModeChecked) { + return; // 已经检测过,不再重复检测 + } + + QStringList keywords = configManager.getFactoryModeKeywords(); + bool found = false; + for (const QString& keyword : keywords) { + if (data.contains(keyword, Qt::CaseInsensitive)) { + qDebug() << "检测到产测模式关键字:" << keyword; + appendToLogFile(QString("=== 检测到产测模式: %1 ===\n").arg(keyword)); + + factoryModeChecked = true; + found = true; + + // 解析产测模式状态并更新UI + if (data.contains("FACTORY TEST MODE: ENABLED", Qt::CaseInsensitive)) { + ui->factoryModeLineEdit->setText("是"); + ui->factoryModeLineEdit->setStyleSheet("background-color: #ffcccc;"); // 红底 + qDebug() << "产测模式: 已开启"; + } else if (data.contains("FACTORY TEST MODE: DISABLED", Qt::CaseInsensitive)) { + ui->factoryModeLineEdit->setText("否"); + ui->factoryModeLineEdit->setStyleSheet("background-color: #ccffcc;"); // 绿底 + qDebug() << "产测模式: 已关闭"; + } + + // 延迟1秒后开始获取版本信息 + QTimer::singleShot(1000, this, [this]() { + if (!versionInfoFetched) { + startVersionInfoFetch(); + } + }); + + break; + } + } + + // 如果没有检测到产测模式关键字,但收到了产测模式检测指令的响应(可能是OK或ERROR) + // 解析 AT^FACTORY 或 AT^FACTORY? 的响应 + if (!found) { + // 检查是否是 AT^FACTORY 相关指令的响应 + // AT^FACTORY? 的响应可能是:+FACTORY: 1 或 +FACTORY: 0 + QRegExp factoryResponsePattern("\\+FACTORY:\\s*(\\d+)", Qt::CaseInsensitive); + if (factoryResponsePattern.indexIn(data) != -1) { + int factoryValue = factoryResponsePattern.cap(1).toInt(); + qDebug() << "解析到产测模式响应值:" << factoryValue; + appendToLogFile(QString("=== 产测模式检测响应: %1 ===\n").arg(factoryValue)); + + factoryModeChecked = true; + + // 更新UI + if (factoryValue == 1) { + ui->factoryModeLineEdit->setText("是"); + ui->factoryModeLineEdit->setStyleSheet("background-color: #ffcccc;"); // 红底 + qDebug() << "产测模式: 已开启 (响应值=1)"; + } else { + ui->factoryModeLineEdit->setText("否"); + ui->factoryModeLineEdit->setStyleSheet("background-color: #ccffcc;"); // 绿底 + qDebug() << "产测模式: 已关闭 (响应值=0)"; + } + + // 延迟1秒后开始获取版本信息 + QTimer::singleShot(1000, this, [this]() { + if (!versionInfoFetched) { + startVersionInfoFetch(); + } + }); + } + // 如果响应是OK,可能是 AT^FACTORY 的确认响应(进入产测模式) + else if (data.contains("OK", Qt::CaseInsensitive) && + (data.contains("FACTORY", Qt::CaseInsensitive) || + data.contains("AT^FACTORY", Qt::CaseInsensitive))) { + qDebug() << "产测模式检测指令返回OK,认为已进入产测模式"; + appendToLogFile(QString("=== 产测模式检测指令返回OK,认为已进入产测模式 ===\n")); + + factoryModeChecked = true; + + // 更新UI(假设OK表示已开启) + ui->factoryModeLineEdit->setText("是"); + ui->factoryModeLineEdit->setStyleSheet("background-color: #ffcccc;"); // 红底 + + // 延迟1秒后开始获取版本信息 + QTimer::singleShot(1000, this, [this]() { + if (!versionInfoFetched) { + startVersionInfoFetch(); + } + }); + } + // 记录其他响应用于调试 + else if (data.contains("ERROR", Qt::CaseInsensitive) || + data.contains("+CME ERROR", Qt::CaseInsensitive) || + data.contains("OK", Qt::CaseInsensitive)) { + qDebug() << "产测模式检测指令响应:" << data.trimmed(); + appendToLogFile(QString("产测模式检测指令响应: %1\n").arg(data.trimmed())); + } + } +} + +// 开始获取版本信息 +void MainWindow::startVersionInfoFetch() +{ + if (versionInfoFetched && currentVersionCommandIndex >= 0) { + qDebug() << "版本信息获取正在进行中,跳过重复请求"; + return; // 正在获取中,不再重复获取 + } + + versionCommandQueue = configManager.getVersionInfoCommands(); + if (versionCommandQueue.isEmpty()) { + qDebug() << "版本信息指令列表为空"; + appendToLogFile(QString("=== 版本信息指令列表为空 ===\n")); + return; + } + + qDebug() << "开始获取版本信息,共" << versionCommandQueue.size() << "条指令"; + appendToLogFile(QString("=== 开始获取版本信息,共%1条指令 ===\n").arg(versionCommandQueue.size())); + + currentVersionCommandIndex = 0; + versionInfoFetched = true; + + // 延迟500ms后发送第一条指令,确保串口就绪 + QTimer::singleShot(500, this, [this]() { + if (serial->isOpen()) { + sendNextVersionCommand(); + } else { + qDebug() << "串口未打开,无法发送版本信息指令"; + appendToLogFile(QString("=== 串口未打开,无法获取版本信息 ===\n")); + versionInfoFetched = false; + currentVersionCommandIndex = -1; + } + }); +} + +// 发送下一个版本信息指令 +void MainWindow::sendNextVersionCommand() +{ + if (currentVersionCommandIndex < 0 || currentVersionCommandIndex >= versionCommandQueue.size()) { + qDebug() << "版本信息获取完成"; + appendToLogFile(QString("=== 版本信息获取完成 ===\n")); + versionCommandTimer->stop(); + return; + } + + QString cmd = versionCommandQueue[currentVersionCommandIndex]; + if (serial->isOpen()) { + serial->write((cmd + "\r\n").toUtf8()); + qDebug() << "发送版本信息指令[" << (currentVersionCommandIndex + 1) << "/" << versionCommandQueue.size() << "]:" << cmd; + appendToLogFile(QString("发送版本信息指令: %1\n").arg(cmd)); + + // 启动超时定时器(每个指令等待2秒) + versionCommandTimer->start(2000); + currentVersionCommandIndex++; + } +} + +// 版本信息指令超时处理 +void MainWindow::onVersionCommandTimeout() +{ + versionCommandTimer->stop(); + + // 继续发送下一条指令 + if (currentVersionCommandIndex < versionCommandQueue.size()) { + sendNextVersionCommand(); + } else { + qDebug() << "所有版本信息指令已发送完成"; + appendToLogFile(QString("=== 所有版本信息指令已发送完成 ===\n")); + // 重置状态,允许再次获取 + versionInfoFetched = false; + currentVersionCommandIndex = -1; + } +} + +// 获取版本信息按钮点击事件 +void MainWindow::on_getVersionInfoButton_clicked() +{ + // 检查串口是否已打开 + if (!serial->isOpen()) { + QMessageBox::warning(this, "警告", "请先打开串口连接"); + return; + } + + // 重置版本信息获取状态 + versionInfoFetched = false; + currentVersionCommandIndex = -1; + versionCommandQueue.clear(); + + // 开始获取版本信息 + startVersionInfoFetch(); +} + +// 保存测试参数到settings.json +void MainWindow::saveTestConfigToSettings() +{ + // 保存串口选择 + 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.saveConfig(); + + qDebug() << "测试参数已保存到settings.json"; +} + +// 从settings.json加载测试参数 +void MainWindow::loadTestConfigFromSettings() +{ + // 恢复串口选择(在updateSerialPorts之后调用,确保串口列表已更新) + QString savedPortName = configManager.getTestConfig("portName", ""); + if (!savedPortName.isEmpty()) { + // 查找匹配的串口项 + int index = ui->portNameBox->findText(savedPortName); + if (index >= 0) { + ui->portNameBox->setCurrentIndex(index); + qDebug() << "恢复串口选择:" << savedPortName; + } else { + qDebug() << "保存的串口不存在,使用默认选择"; + } + } + + // 恢复音频测试参数 + 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", "")); + + qDebug() << "测试参数已从settings.json加载"; +} + +// 保存recvTextEdit内容到日志文件 +void MainWindow::saveRecvTextEditToLog() +{ + QString logContent = ui->recvTextEdit->toPlainText(); + + // 检查是否有内容 + if (logContent.trimmed().isEmpty()) { + qDebug() << "recvTextEdit内容为空,跳过保存"; + 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"; + QDir dir; + if (!dir.exists(logsDir)) { + dir.mkpath(logsDir); + } + + // 生成日志文件名 + QDateTime now = QDateTime::currentDateTime(); + QString fileName = QString("%1_%2_%3_%4_UI日志.log") + .arg(now.toString("yyyyMMdd")) + .arg(now.toString("hhmmss")) + .arg(imei) + .arg(iccid); + + QString filePath = logsDir + "/" + fileName; + + // 保存到文件 + QFile logFile(filePath); + if (logFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + 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(); + + qDebug() << "UI日志已保存到:" << filePath; + ui->statusbar->showMessage(QString("UI日志已保存: %1").arg(fileName), 3000); + } else { + qDebug() << "无法保存UI日志文件:" << filePath << "错误:" << logFile.errorString(); + } +} + // 创建测试日志文件 void MainWindow::createTestLogFile() { diff --git a/mainwindow.h b/mainwindow.h index df94d91..1c705ae 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -19,6 +19,7 @@ #include #include #include +#include "config_manager.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } @@ -116,6 +117,9 @@ private slots: void on_agingTestButton_2_clicked(); void on_openButton_3_clicked(); + + // 版本信息获取按钮 + void on_getVersionInfoButton_clicked(); private: Ui::MainWindow *ui; @@ -168,7 +172,8 @@ private: QPushButton *audioPassButton; // 录音通过按钮 QPushButton *audioFailButton; // 录音失败按钮 QPushButton *audioRetestButton; // 重新测试按钮 - int audioMicMiddleConsecutiveCount; // 连续检测到"fac:mic level:中"的次数 + int audioMicMiddleConsecutiveCount; // 连续检测到设置的标准Level的次数 + QString audioLevelStandard; // 音频测试通过标准("中"或"低"等) bool audioTestFinished; // 录音测试是否已完成(成功或失败) QSet bluetoothAddresses; // 蓝牙测试检测到的不同蓝牙地址集合 bool bluetoothTestFinished; // 蓝牙测试是否已完成(成功或失败) @@ -179,6 +184,19 @@ private: QTextStream *testLogStream; // 测试日志文件流 QString testLogFilePath; // 测试日志文件路径 + // 配置管理 + ConfigManager configManager; // 配置管理器(不使用指针,直接作为成员) + + // 开机检测相关变量 + bool bootDetected; // 是否已检测到开机 + bool factoryModeChecked; // 是否已检测产测模式 + bool versionInfoFetched; // 是否已获取版本信息 + + // 版本信息获取相关变量 + QStringList versionCommandQueue; // 版本信息AT指令队列 + int currentVersionCommandIndex; // 当前执行的版本信息指令索引 + QTimer *versionCommandTimer; // 版本信息指令发送定时器 + enum AudioTestStep { AUDIO_STARTING_RECORD, // 开始录音 AUDIO_PLAYING_1KHZ, // 正在播放1kHz音频 @@ -217,5 +235,17 @@ private: void ShowPppInfoPYVer(const QString& data); // CAT1信号测试相关函数 void parseNetworkStatChanged(const QString& data); + + // 开机检测和版本信息获取相关函数 + void checkBootDetection(const QString& data); // 检测设备开机 + void checkFactoryMode(const QString& data); // 检测产测模式 + void startVersionInfoFetch(); // 开始获取版本信息 + void sendNextVersionCommand(); // 发送下一个版本信息指令 + void onVersionCommandTimeout(); // 版本信息指令超时处理 + void saveRecvTextEditToLog(); // 保存recvTextEdit内容到日志文件 + + // 测试参数配置保存和恢复(使用settings.json) + void saveTestConfigToSettings(); // 保存测试参数到settings.json + void loadTestConfigFromSettings(); // 从settings.json加载测试参数 }; #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index b0ecb5e..53e5a2d 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 1309 - 641 + 823 @@ -36,43 +36,81 @@ 6 - - - - 280 - 16777215 - - - - - 0 - 0 - + + + 6 - - - 6 - - - - - - Arial - 14 - - - - QComboBox::AdjustToContentsOnFirstShow - - - 6 - - + + + + Qt::Horizontal + + + + + + + + + + Arial Black + 75 + true + + + + 老化测试: + + + + + + + + Agra + 14 + + + + 老化结果 + + + + + + + + Agra + 14 + 75 + true + + + + QPushButton { +background-color: #9C27B0; +color: white; +border-radius: 4px; +font-weight: bold; +} +QPushButton:hover { +background-color: #7B1FA2; +} + + + 老化测试 + + + + + + + Agra @@ -80,12 +118,12 @@ - 开始产测 + 清空数据 - - + + Agra @@ -93,38 +131,25 @@ - 打开串口 + 获取设备信息 - - + + Agra 14 - 75 - true - - QPushButton { -background-color: #9C27B0; -color: white; -border-radius: 4px; -font-weight: bold; -} -QPushButton:hover { -background-color: #7B1FA2; -} - - 恢复出厂 + 开始产测 - + Agra @@ -145,12 +170,12 @@ background-color: #7B1FA2; } - 老化测试 + 恢复出厂 - - + + Agra @@ -158,24 +183,31 @@ background-color: #7B1FA2; - 清空数据 + 打开串口 - - + + - Agra + Arial 14 - - 老化结果 + + QComboBox::AdjustToContentsOnFirstShow - + + + + Qt::Horizontal + + + + @@ -204,45 +236,211 @@ background-color: #F57C00; - - - 6 - + - + + + Qt::Horizontal + + + + + - Agra - 14 + Arial Black + 75 + true - - - 0 - 0 - + + 测试参数及通过标准: + + + + + + + 6 + + + + + 0 + 0 + + + + + Agra + 14 + + + + 测试音频播放音量 + + + + + + + + Arial + 14 + + + + + + + 0.0~2.0, 取值标准,麦克风能收音的最低喇叭音量。 + + + 2.0 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 例如: 2 + + + + + + + + + + + 录音音量标准: + + + + + + + 可选:高,中,低,极低,静音。连续出现三个指定的音量标准,视为测试通过。 + + + 中 + + + 可选:高,中,低,极低,静音 + + + + + + + + + + + Qt::Horizontal + + + + + + + - 音频测试音量 + 目标MODEM版本: - - - - Agra - 14 - + + + 为空不校验Modem版本是否正确 - Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + - 2 + 目标PY版本: + + + + + + + 为空不校验Py版本是否正确 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 目标固件版本: + + + + + + + + + + 为空不校验固件版本是否正确。 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 广播设备-蓝牙地址: + + + + + + + + + + 供测试用常广播的经典蓝牙设备地址。可为空,为空时,扫描到3个以上设备为通过。 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 例如: 1C:1D:2B:68:82:68 + + + + + + + 广播设备- Min_RSSI: + + + + + + + + + + 如Min_RSSI = -80,则扫到广播设备且RSSI > -80为成功。 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - 例如: 2 + 例如: -80 @@ -262,17 +460,9 @@ background-color: #F57C00; - - - - - 5 - 0 - - - + 6 @@ -316,24 +506,10 @@ background-color: #F57C00; - - - + + - - - - 380 - 0 - - - - - 2 - 0 - - - + 6 @@ -345,157 +521,143 @@ background-color: #F57C00; 4 - + Ver: - + - Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - + IMEI: - + - Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - + ICCID - + - Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - + Modem: - + - Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - + PYVER - + - - Qt::AlignLeft|Qt::AlignVCenter - - - - - - - 最新VER: - - - - - - Qt::AlignLeft|Qt::AlignVCenter - - - - - - - 最新MODEM: + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - Qt::AlignLeft|Qt::AlignVCenter + + + + + Arial Black + 75 + true + - - - - - 最新PY: + 设备状态: - - - Qt::AlignLeft|Qt::AlignVCenter + + + + Arial + 14 + - - - - - 蓝牙地址: + - - - - - Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true - 例如: 1C:1D:2B:68:82:68 + 例如: 是/否 - - - - RSSI阈值: + + + + + 0 + 0 + - - - - - - Qt::AlignLeft|Qt::AlignVCenter + + + Agra + 14 + - - 例如: -80 + + 设备在产测模式 + + + + Qt::Horizontal + + + @@ -513,7 +675,7 @@ background-color: #F57C00; 0 0 424 - 318 + 523 @@ -1003,7 +1165,6 @@ background-color: #F57C00; - diff --git a/settings.json b/settings.json new file mode 100644 index 0000000..fa7504d --- /dev/null +++ b/settings.json @@ -0,0 +1,27 @@ +{ + "bootDetectionKeywords": [ + "BuildVer", + "NAND flash ID", + "NAND ID:" + ], + "versionInfoCommands": [ + "AT^CAT1GETVER", + "AT^CAT1GETSIGNAL", + "AT^FACTORY" + ], + "factoryModeCheckCommand": "AT^FACTORY", + "factoryModeKeywords": [ + "FACTORY TEST MODE:" + ], + "testConfig": { + "portName": "", + "audioVolume": "2.0", + "audioLevelStandard": "中", + "expectedModemVer": "", + "expectedPYVer": "", + "expectedVer": "", + "bluetoothAddress": "", + "bluetoothRSSI": "" + } +} +