From: SnickerSun Date: Thu, 27 Nov 2025 05:57:51 +0000 (+0800) Subject: 已经和cursor集成,可以在cursor编程了。 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=282ab8e643822686e542a888ee5e3f8f12035575;p=mirrors%2Ffactory_tool.git 已经和cursor集成,可以在cursor编程了。 --- diff --git a/.vscode/launch.json b/.vscode/launch.json index 8b331a9..9caf0a4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,14 +5,14 @@ "name": "Debug (GDB)", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/debug/HiBTMacWriteTool.exe", + "program": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/debug/HiBTMacWriteTool.exe", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [ { "name": "PATH", - "value": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin" + "value": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}" } ], "externalConsole": false, @@ -36,14 +36,14 @@ "name": "Release (GDB)", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/release/HiBTMacWriteTool.exe", + "program": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/release/HiBTMacWriteTool.exe", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [ { "name": "PATH", - "value": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin" + "value": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}" } ], "externalConsole": false, @@ -62,14 +62,14 @@ "name": "Debug (No Build)", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/debug/HiBTMacWriteTool.exe", + "program": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/debug/HiBTMacWriteTool.exe", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [ { "name": "PATH", - "value": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin" + "value": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}" } ], "externalConsole": false, diff --git a/.vscode/settings.json b/.vscode/settings.json index 67b3e2f..b3bc38d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -26,7 +26,7 @@ "C_Cpp.default.compilerPath": "d:/Qt/Qt5.14.2/Tools/mingw730_32/bin/g++.exe", "C_Cpp.default.cStandard": "c11", "C_Cpp.default.cppStandard": "c++11", - "C_Cpp.default.intelliSenseMode": "gcc-x64", + "C_Cpp.default.intelliSenseMode": "gcc-x86", "files.exclude": { "**/.git": true, "**/.svn": true, diff --git a/.vscode/tasks.json b/.vscode/tasks.json index f01276a..1888183 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -4,15 +4,19 @@ { "label": "qmake: Configure Project", "type": "shell", - "command": "qmake", + "command": "D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin\\qmake.exe", "args": [ - "HiBTMacWriteTool.pro" + "HiBTMacWriteTool.pro", + "-spec", + "win32-g++", + "CONFIG+=debug", + "CONFIG+=qml_debug" ], "options": { - "cwd": "${workspaceFolder}", + "cwd": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug", "env": { "QTDIR": "d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32", - "PATH": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin" + "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}" } }, "group": { @@ -62,17 +66,16 @@ { "label": "build: Debug", "dependsOn": [ - "fix: Link Order", "clean: Build Files" ], "type": "shell", - "command": "mingw32-make", + "command": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin\\mingw32-make.exe", "args": [], "options": { "cwd": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug", "env": { "QTDIR": "d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32", - "PATH": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin" + "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}" } }, "group": { @@ -93,7 +96,7 @@ "fix: Link Order" ], "type": "shell", - "command": "mingw32-make", + "command": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin\\mingw32-make.exe", "args": [ "release" ], @@ -101,7 +104,7 @@ "cwd": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug", "env": { "QTDIR": "d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32", - "PATH": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin" + "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}" } }, "group": "build", @@ -116,7 +119,7 @@ { "label": "clean: Build Files", "type": "shell", - "command": "mingw32-make", + "command": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin\\mingw32-make.exe", "args": [ "clean" ], @@ -124,24 +127,68 @@ "cwd": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug", "env": { "QTDIR": "d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32", - "PATH": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin" + "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}" } }, "group": "build", "problemMatcher": [] }, + { + "label": "run: Debug", + "type": "shell", + "command": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/debug/HiBTMacWriteTool.exe", + "args": [], + "options": { + "cwd": "${workspaceFolder}", + "env": { + "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}" + } + }, + "group": "test", + "dependsOn": "build: Debug", + "presentation": { + "reveal": "always", + "panel": "dedicated", + "focus": false + }, + "problemMatcher": [] + }, + { + "label": "run: Release", + "type": "shell", + "command": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/release/HiBTMacWriteTool.exe", + "args": [], + "options": { + "cwd": "${workspaceFolder}", + "env": { + "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}" + } + }, + "group": "test", + "dependsOn": "build: Release", + "presentation": { + "reveal": "always", + "panel": "dedicated", + "focus": false + }, + "problemMatcher": [] + }, { "label": "qmake: Reconfigure", "type": "shell", - "command": "qmake", + "command": "D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin\\qmake.exe", "args": [ - "HiBTMacWriteTool.pro" + "${workspaceFolder}/HiBTMacWriteTool.pro", + "-spec", + "win32-g++", + "CONFIG+=debug", + "CONFIG+=qml_debug" ], "options": { - "cwd": "${workspaceFolder}", + "cwd": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug", "env": { "QTDIR": "d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32", - "PATH": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin" + "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}" } }, "group": "build", diff --git "a/AT\346\214\207\344\273\244\346\211\247\350\241\214\350\267\257\345\276\204\345\210\206\346\236\220.md" "b/AT\346\214\207\344\273\244\346\211\247\350\241\214\350\267\257\345\276\204\345\210\206\346\236\220.md" new file mode 100644 index 0000000..aeec766 --- /dev/null +++ "b/AT\346\214\207\344\273\244\346\211\247\350\241\214\350\267\257\345\276\204\345\210\206\346\236\220.md" @@ -0,0 +1,105 @@ +# AT指令执行路径分析 + +## 执行流程图 + +``` +spp_connect_1() + ↓ +打开串口,设置working_state_1=true + ↓ +readData1() 持续监听 + ↓ +检测到 BOOT_UP_MSG ("yaffs filesystem init start") + ↓ +waiting_cmd1=true, cmd_index_1=0, 获取可用MAC地址 + ↓ +检测到 TIME_FOR_CMD ("bt enable_bt_stack ret") + ↓ +uart_send_data1(ATCMD_ADD_VOTE) [cmd_index=0] + ↓ +等待响应结束标志 (OK~) + ↓ +uart_process1() case 0: 处理投票指令 + ↓ +cmd_index_1++ → 1 + ↓ +uart_send_data1(ATCMD_GET_MAC) [cmd_index=1] + ↓ +等待响应结束标志 + ↓ +uart_process1() case 1: 解析MAC地址,检查是否已占用 + ↓ +cmd_index_1++ → 2 + ↓ +uart_send_data1(ATCMD_SET_MAC) [cmd_index=2] + ↓ +等待响应结束标志 + ↓ +uart_process1() case 2: 设置MAC完成 + ↓ +cmd_index_1++ → 3 + ↓ +uart_send_data1(ATCMD_GET_MAC) [cmd_index=3] + ↓ +等待响应结束标志 + ↓ +uart_process1() case 3: 验证MAC地址设置 + ↓ +cmd_index_1++ → 4 + ↓ +等待 STARTUP_POST_INIT 和 STARTUP_POST_INIT_TASK + ↓ +uart_send_data1(ATCMD_GET_CPUID) [cmd_index=4] + ↓ +等待响应结束标志 + ↓ +uart_process1() case 4: 解析CPU ID,保存到数据库 + ↓ +cmd_index_1++ → 5 + ↓ +uart_send_data1(ATCMD_POWEROFF) [cmd_index=5] + ↓ +等待响应结束标志 + ↓ +uart_process1() case 5: 关机完成,显示成功 + ↓ +cmd_index_1=-1, 工作完成 +``` + +## AT指令列表 + +| 指令 | 定义 | 用途 | 超时时间 | +|------|------|------|----------| +| ATCMD_ADD_VOTE | `AT^PMADDVOTE\r\n` | 阻止设备休眠 | 1.5秒 | +| ATCMD_GET_MAC | `AT^GETBTMAC\r\n` | 查询MAC地址 | 3秒 | +| ATCMD_SET_MAC | `AT^BTADDR=%1 6\r\n` | 设置MAC地址 | 1.5秒 | +| ATCMD_GET_CPUID | `AT^GETIDS\r\n` | 获取CPU ID | 5秒 | +| ATCMD_POWEROFF | `AT^POWEROFF\r\n` | 关机 | 1.5秒 | + +## 检测信号 + +| 信号 | 定义 | 用途 | +|------|------|------| +| BOOT_UP_MSG | `"yaffs filesystem init start"` | 检测设备开机 | +| TIME_FOR_CMD | `"bt enable_bt_stack ret"` | 检测可以发送AT指令的时机 | +| STARTUP_POST_INIT | `"APP\|startup_post_init !"` | 系统启动完成信号1 | +| STARTUP_POST_INIT_TASK | `"APP\|startup_post_init_task !"` | 系统启动完成信号2 | + +## 当前问题 + +1. **代码重复**: 只有串口1有完整实现,串口2/3/4只有空函数 +2. **变量分散**: 每个串口的状态变量都是独立的(cmd_index_1, uart_rx_flag1等) +3. **难以扩展**: 添加新功能需要修改4个地方 +4. **配置不统一**: 每个串口使用相同的配置但代码重复 + +## 改进方案 + +### 1. 统一配置结构 +创建 `SerialPortContext` 结构体,封装每个串口的所有状态 + +### 2. 统一处理函数 +将 readData1/uart_process1/uart_send_data1 等函数改为模板函数,接受端口索引 + +### 3. 4线程独立工作 +每个串口使用独立的上下文,互不干扰 + diff --git a/README_CURSOR.md b/README_CURSOR.md new file mode 100644 index 0000000..6ac746e --- /dev/null +++ b/README_CURSOR.md @@ -0,0 +1,74 @@ +# Cursor/VSCode 编译和运行配置说明 + +## 已配置的功能 + +### 1. 编译任务 (Tasks) + +在 Cursor/VSCode 中按 `Ctrl+Shift+P`,输入 "Tasks: Run Task",可以选择以下任务: + +- **build: Debug** (默认构建任务) + - 使用32位MinGW编译Debug版本 + - 路径:`D:\Qt\Qt5.14.2\Tools\mingw730_32\bin\mingw32-make.exe` + - 构建目录:`../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug` + +- **build: Release** + - 使用32位MinGW编译Release版本 + +- **clean: Build Files** + - 清理构建文件 + +- **qmake: Configure Project** + - 重新配置Qt项目 + +- **qmake: Reconfigure** + - 重新生成Makefile + +- **run: Debug** + - 编译并运行Debug版本(不调试) + +- **run: Release** + - 编译并运行Release版本(不调试) + +### 2. 调试配置 (Launch) + +按 `F5` 或使用调试面板,可以选择以下配置: + +- **Debug (GDB)** + - 使用GDB调试器 + - 自动编译后启动调试 + - 可执行文件:`../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/debug/HiBTMacWriteTool.exe` + +- **Release (GDB)** + - 调试Release版本 + +- **Debug (No Build)** + - 直接运行已编译的程序,不重新编译 + +### 3. 路径配置 + +所有配置都使用32位MinGW工具链: + +- **MinGW工具链**:`D:\Qt\Qt5.14.2\Tools\mingw730_32\bin` +- **Qt库路径**:`D:\Qt\Qt5.14.2\5.14.2\mingw73_32` +- **构建目录**:`D:\workspace\fd230_source_win\build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug` + +### 4. 快速使用 + +1. **编译项目**: + - 按 `Ctrl+Shift+B` (默认构建任务) + - 或 `Ctrl+Shift+P` → "Tasks: Run Task" → "build: Debug" + +2. **运行项目(不调试)**: + - `Ctrl+Shift+P` → "Tasks: Run Task" → "run: Debug" + +3. **调试项目**: + - 按 `F5` 启动调试 + - 或使用调试面板选择配置 + +### 5. 注意事项 + +- 确保构建目录存在,如果不存在,先运行 "qmake: Configure Project" +- 首次使用前,建议先运行 "qmake: Reconfigure" 生成Makefile +- 所有路径都使用绝对路径,确保在不同环境下都能正常工作 +- 使用32位MinGW工具链,与QtCreator保持一致 + diff --git a/Setting.ini b/Setting.ini index e3f6e21..02406f5 100644 --- a/Setting.ini +++ b/Setting.ini @@ -1,5 +1,5 @@ [Uart_setting] -uart_com=COM41 +uart_com=COM8 uart_baud=18 spp_addr= diff --git a/fix_link_order.ps1 b/fix_link_order.ps1 new file mode 100644 index 0000000..f796176 --- /dev/null +++ b/fix_link_order.ps1 @@ -0,0 +1,36 @@ +# 修复 Makefile 中的链接顺序,确保 advapi32 在最后 +# 这个脚本会在编译前自动修复链接顺序 + +$makefilePath = "D:\workspace\fd230_source_win\build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug\Makefile.Debug" + +if (Test-Path $makefilePath) { + $content = Get-Content $makefilePath -Raw -Encoding UTF8 + + # 检查是否已经有 advapi32 + if ($content -match "LIBS\s*=\s*(.*)") { + $libsLine = $matches[1] + + # 如果 advapi32 不在最后,移除它并添加到末尾 + if ($libsLine -match "-ladvapi32" -and $libsLine -notmatch "-ladvapi32\s*$") { + Write-Host "Fixing link order..." -ForegroundColor Yellow + $libsLine = $libsLine -replace "\s+-ladvapi32", "" + $libsLine = $libsLine.TrimEnd() + " -ladvapi32" + $content = $content -replace "LIBS\s*=\s*.*", "LIBS = $libsLine" + Set-Content $makefilePath $content -NoNewline -Encoding UTF8 + Write-Host "Link order fixed!" -ForegroundColor Green + } elseif ($libsLine -notmatch "-ladvapi32") { + # 如果没有 advapi32,添加到末尾 + Write-Host "Adding advapi32 to link command..." -ForegroundColor Yellow + $libsLine = $libsLine.TrimEnd() + " -ladvapi32" + $content = $content -replace "LIBS\s*=\s*.*", "LIBS = $libsLine" + Set-Content $makefilePath $content -NoNewline -Encoding UTF8 + Write-Host "advapi32 added!" -ForegroundColor Green + } else { + Write-Host "Link order is correct!" -ForegroundColor Green + } + } +} else { + Write-Host "Makefile.Debug not found, skipping link order fix" -ForegroundColor Yellow + exit 0 +} + diff --git a/mac_address.db b/mac_address.db new file mode 100644 index 0000000..e69de29 diff --git a/mainwindow.cpp b/mainwindow.cpp index 0a47afd..89dd459 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -7,57 +7,72 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); + + // 初始化串口对象 serialport1 = new QSerialPort(this); serialport2 = new QSerialPort(this); serialport3 = new QSerialPort(this); serialport4 = new QSerialPort(this); - - spp_timer_handle1 = new QTimer(this); - connect(spp_timer_handle1, SIGNAL(timeout()), this, SLOT(spp_timer_callback1())); - - result_thread1 = new Result_Thread(this,1); - result_thread2 = new Result_Thread(this,2); - result_thread3 = new Result_Thread(this,3); - result_thread4 = new Result_Thread(this,4); - result_thread1->start(); - result_thread1->pause(); - result_thread2->start(); - result_thread2->pause(); - result_thread3->start(); - result_thread3->pause(); - result_thread4->start(); - result_thread4->pause(); + + QSerialPort *ports[MAX_SERIAL_PORTS] = {serialport1, serialport2, serialport3, serialport4}; + + // 初始化统一配置结构 + for (int i = 0; i < MAX_SERIAL_PORTS; i++) { + // 创建串口上下文 + port_contexts[i] = new SerialPortContext(i + 1); + + // 创建定时器 + spp_timer_handles[i] = new QTimer(this); + + // 连接定时器信号(使用lambda捕获端口索引) + connect(spp_timer_handles[i], &QTimer::timeout, [this, i]() { + this->spp_timer_callback(i); + }); + + // 初始化上下文 + port_contexts[i]->init(ports[i], spp_timer_handles[i]); + + // 创建结果线程 + result_threads[i] = new Result_Thread(this, i + 1); + result_threads[i]->start(); + result_threads[i]->pause(); + } + + // 向后兼容:映射到数组 + result_thread1 = result_threads[0]; + result_thread2 = result_threads[1]; + result_thread3 = result_threads[2]; + result_thread4 = result_threads[3]; + + // 向后兼容:保留原有的定时器引用(映射到数组) + // 注意:spp_timer_handle1 将在后续代码中通过 port_contexts[0]->spp_timer_handle 访问 + ui_setting_read(); - } -void MainWindow::ui_show_result1(QString msg,bool success) -{ - ui->label_runtime_status1->setText(msg); - if (success) - { - this->write_success_count1++; - ui->label_result_success1->setText(tr("成功%1").arg(write_success_count1)); - }else{ - this->write_fail_count1++; - ui->label_result_fail1->setText(tr("失败%1").arg(write_fail_count1)); - poweroff_watch1(); - } - if (spp_timer_handle1->isActive()) - spp_timer_handle1->stop(); - -} +// ui_show_result1已在后面实现为向后兼容函数 -void MainWindow::readData1() +// 统一的readData函数 +void MainWindow::readData(int port_index) { - const QByteArray data = serialport1->readAll(); -// qDebug()<= MAX_SERIAL_PORTS) { + qDebug() << tr("无效的端口索引:") << port_index; + return; + } + + SerialPortContext *ctx = port_contexts[port_index]; + if (ctx == nullptr || ctx->serialport == nullptr) { + qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; + return; + } + + const QByteArray data = ctx->serialport->readAll(); + // 调试输出 + if(ctx->uart_rx_flag) + qDebug() << tr("端口%1接收数据:").arg(port_index) << data; -if (working_state_1 == false) -{ - qDebug() << tr("写号结束,跳过读取串口"); + if (ctx->working_state == false) { + qDebug() << tr("端口%1写号结束,跳过读取串口").arg(port_index); return; } @@ -67,370 +82,435 @@ if (working_state_1 == false) } // 将新数据添加到开机检测缓存中 - boot_detect_buffer.append(data); + ctx->boot_detect_buffer.append(data); // 保持缓存大小合理,避免内存过度使用(保留最近8192字节) - if (boot_detect_buffer.length() > 8192) { - boot_detect_buffer = boot_detect_buffer.right(8192); + if (ctx->boot_detect_buffer.length() > 8192) { + ctx->boot_detect_buffer = ctx->boot_detect_buffer.right(8192); // 只在第一次超过限制时打印,避免重复打印 - static bool buffer_limit_warned = false; - if (!buffer_limit_warned) { - qDebug() << tr("开机检测缓存过大,保留最近8192字节"); - buffer_limit_warned = true; + static bool buffer_limit_warned[MAX_SERIAL_PORTS] = {false, false, false, false}; + if (!buffer_limit_warned[port_index]) { + qDebug() << tr("端口%1开机检测缓存过大,保留最近8192字节").arg(port_index); + buffer_limit_warned[port_index] = true; } } + // 在缓存区中检测开机信号,处理分包情况 - if (boot_detect_buffer.indexOf(BOOT_UP_MSG)>=0) - { - this->ui->label_runtime_status1->setText(tr("发现新设备")); - waiting_cmd1 = true; - cmd_index_1 = 0; + if (ctx->boot_detect_buffer.indexOf(BOOT_UP_MSG) >= 0) { + UIPortWidgets widgets = getUIPortWidgets(port_index); + widgets.label_runtime_status->setText(tr("发现新设备")); + ctx->waiting_cmd = true; + ctx->cmd_index = 0; QString avalible_mac = settings::getInstance().getAvalibleMac(); - ui->ledit_spp_addr_1->setText(avalible_mac); - ui->txtb_dispaly->clear(); + widgets.ledit_spp_addr->setText(avalible_mac); + widgets.txtb_dispaly->clear(); // 检测到开机信号后清理缓存,避免无限增长 - boot_detect_buffer.clear(); - qDebug() << tr("检测到开机信号(yaffs filesystem init start),清理缓存"); - + ctx->boot_detect_buffer.clear(); + qDebug() << tr("端口%1检测到开机信号(yaffs filesystem init start),清理缓存").arg(port_index); } // 在缓存区中检测MAC地址信息,处理分包情况 - if (working_state_1 && !waiting_cmd1) { + if (ctx->working_state && !ctx->waiting_cmd) { // 使用正则表达式在缓存区中查找完整的MAC地址 QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); - int macPos = macRegex.indexIn(boot_detect_buffer); + int macPos = macRegex.indexIn(ctx->boot_detect_buffer); if (macPos >= 0) { QString foundMac = macRegex.cap(1); // 提取MAC地址部分 (28:11:06:XX:XX:XX) - qDebug() << tr("🔍 在开机缓冲区中发现完整MAC地址:") << foundMac; + qDebug() << tr("端口%1在开机缓冲区中发现完整MAC地址:").arg(port_index) << foundMac; // 转换为无冒号格式 QString macWithoutColon = foundMac.replace(":", "").toUpper(); - qDebug() << tr("转换后的MAC地址:") << macWithoutColon; + qDebug() << tr("端口%1转换后的MAC地址:").arg(port_index) << macWithoutColon; // 检查MAC地址是否已被使用 bool mac_used = settings::getInstance().getMacUsed(macWithoutColon); - qDebug() << tr("MAC地址是否已被使用:") << mac_used; + qDebug() << tr("端口%1 MAC地址是否已被使用:").arg(port_index) << mac_used; if (mac_used) { - ui_display1(tr("手表地址") + macWithoutColon + tr("已占用\r\n"), LOG_DIRECT_OUT); - ui_show_result1(tr("Mac地址已占用"), false); + ui_display(port_index, tr("手表地址") + macWithoutColon + tr("已占用\r\n"), LOG_DIRECT_OUT); + ui_show_result(port_index, tr("Mac地址已占用"), false); } else { - ui_display1(tr("手表当前地址") + macWithoutColon + tr(" 可用!\r\n"), LOG_DIRECT_IN); - qDebug() << tr("✅ 手表当前MAC地址可用:") << macWithoutColon; + ui_display(port_index, tr("手表当前地址") + macWithoutColon + tr(" 可用!\r\n"), LOG_DIRECT_IN); + qDebug() << tr("端口%1手表当前MAC地址可用:").arg(port_index) << macWithoutColon; } } } + // 在缓存区中检测命令时机信号,处理分包情况 - if (waiting_cmd1 && boot_detect_buffer.indexOf(TIME_FOR_CMD)>=0) - { - uart_send_data1(ATCMD_ADD_VOTE); + if (ctx->waiting_cmd && ctx->boot_detect_buffer.indexOf(TIME_FOR_CMD) >= 0) { + uart_send_data(port_index, ATCMD_ADD_VOTE); // 检测到命令时机后也清理缓存 - boot_detect_buffer.clear(); - qDebug() << tr("检测到命令时机信号,清理缓存"); + ctx->boot_detect_buffer.clear(); + qDebug() << tr("端口%1检测到命令时机信号,清理缓存").arg(port_index); } // 检测启动完成信号,需要同时检测到两个信号 - if (waiting_cmd1 && !startup_complete_detected && - boot_detect_buffer.indexOf(STARTUP_POST_INIT) >= 0 && - boot_detect_buffer.indexOf(STARTUP_POST_INIT_TASK) >= 0) - { - startup_complete_detected = true; // 设置标志,防止重复触发 - qDebug() << tr("✅ 检测到启动完成信号,系统已完全启动"); - ui_display1(tr("系统启动完成,可以执行GETIDS\r\n"), LOG_DIRECT_IN); + if (ctx->waiting_cmd && !ctx->startup_complete_detected && + ctx->boot_detect_buffer.indexOf(STARTUP_POST_INIT) >= 0 && + ctx->boot_detect_buffer.indexOf(STARTUP_POST_INIT_TASK) >= 0) { + ctx->startup_complete_detected = true; // 设置标志,防止重复触发 + qDebug() << tr("端口%1检测到启动完成信号,系统已完全启动").arg(port_index); + ui_display(port_index, tr("系统启动完成,可以执行GETIDS\r\n"), LOG_DIRECT_IN); // 清理缓存 - boot_detect_buffer.clear(); - qDebug() << tr("检测到启动完成信号,清理缓存"); + ctx->boot_detect_buffer.clear(); + qDebug() << tr("端口%1检测到启动完成信号,清理缓存").arg(port_index); // 如果当前正在等待GETIDS执行,且没有AT命令在执行,则触发GETIDS - if ((cmd_index_1 == 3 || cmd_index_1 == 4) && !uart_rx_flag1) { - qDebug() << tr("🚀 启动完成且正在等待GETIDS,立即触发GETIDS执行"); - qDebug() << tr("当前cmd_index_1:") << cmd_index_1; + if ((ctx->cmd_index == 3 || ctx->cmd_index == 4) && !ctx->uart_rx_flag) { + qDebug() << tr("端口%1启动完成且正在等待GETIDS,立即触发GETIDS执行").arg(port_index); + qDebug() << tr("端口%1当前cmd_index:").arg(port_index) << ctx->cmd_index; - if (cmd_index_1 == 3) { - cmd_index_1++; // 从3递增到4 - qDebug() << tr("cmd_index_1从3递增到4"); + if (ctx->cmd_index == 3) { + ctx->cmd_index++; // 从3递增到4 + qDebug() << tr("端口%1 cmd_index从3递增到4").arg(port_index); } - // 如果cmd_index_1已经是4,保持不变,重新执行case 4 + // 如果cmd_index已经是4,保持不变,重新执行case 4 // 清空之前的响应缓冲区,准备接收GETIDS响应 - uart_rx_buff_array1.clear(); - qDebug() << tr("清空响应缓冲区,准备执行GETIDS"); + ctx->uart_rx_buff_array.clear(); + qDebug() << tr("端口%1清空响应缓冲区,准备执行GETIDS").arg(port_index); // 重新执行switch逻辑,现在startup_complete_detected = true - switch(cmd_index_1) { + switch(ctx->cmd_index) { case 4: - qDebug() << tr("✅ 系统已完全启动,发送GETIDS指令"); - this->uart_send_data1(ATCMD_GET_CPUID); + qDebug() << tr("端口%1系统已完全启动,发送GETIDS指令").arg(port_index); + uart_send_data(port_index, ATCMD_GET_CPUID); break; default: - qDebug() << tr("启动完成回调中的cmd_index_1异常:") << cmd_index_1; + qDebug() << tr("端口%1启动完成回调中的cmd_index异常:").arg(port_index) << ctx->cmd_index; break; } } } - if (uart_rx_flag1) - {//指令下达完毕,开始接收数据 - uart_rx_buff_array1.append(data); - qDebug() << tr("📥 AT命令响应数据累积中,当前长度:") << uart_rx_buff_array1.length(); - qDebug() << tr("📥 当前累积内容:") << uart_rx_buff_array1; + if (ctx->uart_rx_flag) { + // 指令下达完毕,开始接收数据 + ctx->uart_rx_buff_array.append(data); + qDebug() << tr("端口%1 AT命令响应数据累积中,当前长度:").arg(port_index) << ctx->uart_rx_buff_array.length(); + qDebug() << tr("端口%1当前累积内容:").arg(port_index) << ctx->uart_rx_buff_array; // 检查各种可能的结束标志 - bool hasOK = uart_rx_buff_array1.indexOf("OK~") >= 0; - bool hasPowerOff = uart_rx_buff_array1.indexOf("power off device!") >= 0; - bool hasDSPPowerDown = uart_rx_buff_array1.indexOf("DSP0 power down") >= 0; + bool hasOK = ctx->uart_rx_buff_array.indexOf("OK~") >= 0; + bool hasPowerOff = ctx->uart_rx_buff_array.indexOf("power off device!") >= 0; + bool hasDSPPowerDown = ctx->uart_rx_buff_array.indexOf("DSP0 power down") >= 0; // 特殊处理:对于GETBTMAC命令,如果检测到完整的MAC地址响应,认为命令完成 bool isGetMacComplete = false; - qDebug() << tr("🔧 当前命令G_cmd:") << G_cmd; - qDebug() << tr("🔧 是否包含GETBTMAC:") << G_cmd.contains("GETBTMAC"); + qDebug() << tr("端口%1当前命令G_cmd:").arg(port_index) << ctx->G_cmd; + qDebug() << tr("端口%1是否包含GETBTMAC:").arg(port_index) << ctx->G_cmd.contains("GETBTMAC"); - if (G_cmd.contains("GETBTMAC")) { - qDebug() << tr("🔧 开始GETBTMAC特殊检测"); + if (ctx->G_cmd.contains("GETBTMAC")) { + qDebug() << tr("端口%1开始GETBTMAC特殊检测").arg(port_index); // 检查是否包含完整的MAC地址格式和CyweeChipInfo - bool hasLocalAddr = uart_rx_buff_array1.indexOf("get nv local_addr") >= 0; - bool hasBTMAC = uart_rx_buff_array1.indexOf("BTMAC=") >= 0; - bool hasCyweeChipInfo = uart_rx_buff_array1.indexOf("CyweeChipInfo=") >= 0; + bool hasLocalAddr = ctx->uart_rx_buff_array.indexOf("get nv local_addr") >= 0; + bool hasBTMAC = ctx->uart_rx_buff_array.indexOf("BTMAC=") >= 0; + bool hasCyweeChipInfo = ctx->uart_rx_buff_array.indexOf("CyweeChipInfo=") >= 0; - qDebug() << tr("🔧 检测结果 - hasLocalAddr:") << hasLocalAddr << tr("hasBTMAC:") << hasBTMAC << tr("hasCyweeChipInfo:") << hasCyweeChipInfo; + qDebug() << tr("端口%1检测结果 - hasLocalAddr:").arg(port_index) << hasLocalAddr + << tr("hasBTMAC:") << hasBTMAC << tr("hasCyweeChipInfo:") << hasCyweeChipInfo; if (hasLocalAddr && hasBTMAC && hasCyweeChipInfo) { - qDebug() << tr("🔧 基本条件满足,检查MAC地址格式"); + qDebug() << tr("端口%1基本条件满足,检查MAC地址格式").arg(port_index); // 进一步检查是否包含完整的MAC地址格式 QRegExp completeMacRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); - int macPos = completeMacRegex.indexIn(uart_rx_buff_array1); - qDebug() << tr("🔧 MAC地址正则匹配结果:") << macPos; + int macPos = completeMacRegex.indexIn(ctx->uart_rx_buff_array); + qDebug() << tr("端口%1 MAC地址正则匹配结果:").arg(port_index) << macPos; if (macPos >= 0) { QString foundMac = completeMacRegex.cap(1); - qDebug() << tr("🔧 找到完整MAC地址:") << foundMac; + qDebug() << tr("端口%1找到完整MAC地址:").arg(port_index) << foundMac; isGetMacComplete = true; - qDebug() << tr("✅ GETBTMAC命令响应完整,包含完整MAC地址和CyweeChipInfo"); + qDebug() << tr("端口%1 GETBTMAC命令响应完整,包含完整MAC地址和CyweeChipInfo").arg(port_index); } } } else { - qDebug() << tr("🔧 当前命令不是GETBTMAC,跳过GETBTMAC特殊检测"); + qDebug() << tr("端口%1当前命令不是GETBTMAC,跳过GETBTMAC特殊检测").arg(port_index); } + qDebug() << tr("端口%1结束标志检查 - OK~:").arg(port_index) << hasOK + << tr("power off:") << hasPowerOff << tr("DSP0 power down:") << hasDSPPowerDown + << tr("GETMAC完整:") << isGetMacComplete; - qDebug() << tr("🔍 结束标志检查 - OK~:") << hasOK << tr("power off:") << hasPowerOff << tr("DSP0 power down:") << hasDSPPowerDown << tr("GETMAC完整:") << isGetMacComplete; - - if (hasOK || hasPowerOff || hasDSPPowerDown || isGetMacComplete) - { - qDebug() << tr("✅ 检测到结束标志,开始处理AT命令结果"); + if (hasOK || hasPowerOff || hasDSPPowerDown || isGetMacComplete) { + qDebug() << tr("端口%1检测到结束标志,开始处理AT命令结果").arg(port_index); // 停止超时定时器 - if (spp_timer_handle1->isActive()) { - spp_timer_handle1->stop(); - qDebug() << tr("🛑 停止AT命令超时定时器"); + if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { + ctx->spp_timer_handle->stop(); + qDebug() << tr("端口%1停止AT命令超时定时器").arg(port_index); } - uart_rx_flag1 = false; - uart_process1();//开始处理当前指令结果 -if (cmd_index_1 <0) - { - if (spp_timer_handle1->isActive()) - spp_timer_handle1->stop(); - - if (uart_rx_buff_array1.indexOf("power off device") >= 0 ) - { - ui_display1(tr("关机成功\r\n"),LOG_DIRECT_IN); -} + ctx->uart_rx_flag = false; + uart_process(port_index); // 开始处理当前指令结果 + + if (ctx->cmd_index < 0) { + if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { + ctx->spp_timer_handle->stop(); + } + + if (ctx->uart_rx_buff_array.indexOf("power off device") >= 0) { + ui_display(port_index, tr("关机成功\r\n"), LOG_DIRECT_IN); + } return; } - cmd_index_1 ++; //开始执行下一指令 - qDebug()<<"next cmdindex "<cmd_index++; // 开始执行下一指令 + qDebug() << tr("端口%1 next cmdindex").arg(port_index) << ctx->cmd_index; + + UIPortWidgets widgets = getUIPortWidgets(port_index); + switch(ctx->cmd_index) { case 0: { - + // 空操作 } + break; case 1: { - qDebug() << tr("=== 执行case 1: 查询手表MAC地址 ==="); - this->uart_send_data1(ATCMD_GET_MAC); + qDebug() << tr("端口%1执行case 1: 查询手表MAC地址").arg(port_index); + uart_send_data(port_index, ATCMD_GET_MAC); } break; case 2: { - QString set_mac_cmd=QString(ATCMD_SET_MAC).arg(ui->ledit_spp_addr_1->text()); - this->uart_send_data1(set_mac_cmd); + QString set_mac_cmd = QString(ATCMD_SET_MAC).arg(widgets.ledit_spp_addr->text()); + uart_send_data(port_index, set_mac_cmd); } break; case 3: { - this->uart_send_data1(ATCMD_GET_MAC); + uart_send_data(port_index, ATCMD_GET_MAC); } break; case 4: { // 只有在检测到启动完成信号后才发送GETIDS - if (startup_complete_detected) { - qDebug() << tr("✅ 系统已完全启动,发送GETIDS指令"); - this->uart_send_data1(ATCMD_GET_CPUID); + if (ctx->startup_complete_detected) { + qDebug() << tr("端口%1系统已完全启动,发送GETIDS指令").arg(port_index); + uart_send_data(port_index, ATCMD_GET_CPUID); } else { - qDebug() << tr("⏳ 等待系统完全启动信号,暂不发送GETIDS"); - ui_display1(tr("等待系统完全启动信号...\r\n"), LOG_DIRECT_OUT); + qDebug() << tr("端口%1等待系统完全启动信号,暂不发送GETIDS").arg(port_index); + ui_display(port_index, tr("等待系统完全启动信号...\r\n"), LOG_DIRECT_OUT); // 保持在case 4,等待启动完成信号 - cmd_index_1 = 4; + ctx->cmd_index = 4; return; } } break; case 5: { - this->uart_send_data1(ATCMD_POWEROFF); + uart_send_data(port_index, ATCMD_POWEROFF); } break; default: { - cmd_index_1=-1; - if (spp_timer_handle1->isActive()) - spp_timer_handle1->stop(); + ctx->cmd_index = -1; + if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { + ctx->spp_timer_handle->stop(); + } } break; } } - else{ - - } } +} - - -// m_timer->stop(); - - - -// { -// ui_display1(data,false); -// } -// m_console->putData(data); +// 向后兼容:readData1 +void MainWindow::readData1() +{ + readData(0); } + +// 向后兼容:readData2/3/4 void MainWindow::readData2() { - const QByteArray data = serialport2->readAll(); - qDebug()<putData(data); + readData(1); } void MainWindow::readData3() { - const QByteArray data = serialport3->readAll(); - qDebug()<putData(data); + readData(2); } void MainWindow::readData4() { - const QByteArray data = serialport4->readAll(); - qDebug()<putData(data); + readData(3); } // 结束线程 MainWindow::~MainWindow() { - if (spp_timer_handle1 != nullptr) { - spp_timer_handle1->stop(); - spp_timer_handle1 = nullptr; - } -// if (spp_connected_handle != nullptr) { -// spp_connected_handle->stop(); -// spp_connected_handle = nullptr; -// } ui_setting_save(); - result_thread1->stop(); - result_thread1->wait(); - result_thread2->stop(); - result_thread2->wait(); - result_thread3->stop(); - result_thread3->wait(); - result_thread4->stop(); - result_thread4->wait(); - - - delete result_thread1; - delete result_thread2; - delete result_thread3; - delete result_thread4; + + // 停止所有线程和定时器 + for (int i = 0; i < MAX_SERIAL_PORTS; i++) { + if (spp_timer_handles[i] != nullptr) { + spp_timer_handles[i]->stop(); + } + if (result_threads[i] != nullptr) { + result_threads[i]->stop(); + result_threads[i]->wait(); + delete result_threads[i]; + } + if (port_contexts[i] != nullptr) { + delete port_contexts[i]; + } + } + delete ui; } -void MainWindow::poweroff_watch1() +// 统一的poweroff_watch函数 +void MainWindow::poweroff_watch(int port_index) { -// cmd_index_1 = 4; //直接执行关机 - this->uart_send_data1(ATCMD_POWEROFF); + if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { + qDebug() << tr("无效的端口索引:") << port_index; + return; + } + + uart_send_data(port_index, ATCMD_POWEROFF); } -void MainWindow::ui_display1(QString str,bool inOrOut) +// 向后兼容:poweroff_watch1 +void MainWindow::poweroff_watch1() { + poweroff_watch(0); +} - ui->txtb_dispaly->moveCursor(QTextCursor::End); - if(inOrOut){ - ui->txtb_dispaly->setTextColor(QColor(127, 255, 0)); - }else{ - ui->txtb_dispaly->setTextColor(Qt::red); - } - ui->txtb_dispaly->insertPlainText(str); - ui->txtb_dispaly->moveCursor(QTextCursor::End); +// 旧的ui_display1/2/3实现已删除,使用统一的ui_display函数 +void MainWindow::ui_display4(QString str,bool inOrOut) +{ + ui_display(3, str, inOrOut); } -void MainWindow::ui_display2(QString str,bool inOrOut) + +// ==================== 统一处理函数实现 ==================== + +// 获取指定端口的UI控件 +MainWindow::UIPortWidgets MainWindow::getUIPortWidgets(int port_index) { -// QTime Time= QTime::currentTime();//获取系统当前的时间 -// QString str_time = Time.toString("[hh:mm:ss ");//格式化时间 - ui->txtb_dispaly_2->moveCursor(QTextCursor::End); - if(inOrOut){ - ui->txtb_dispaly_2->setTextColor(QColor(127, 255, 0)); - }else{ - ui->txtb_dispaly_2->setTextColor(Qt::red); + UIPortWidgets widgets; + switch(port_index) { + case 0: + widgets.txtb_dispaly = ui->txtb_dispaly; + widgets.label_runtime_status = ui->label_runtime_status1; + widgets.ledit_spp_addr = ui->ledit_spp_addr_1; + widgets.label_result_success = ui->label_result_success1; + widgets.label_result_fail = ui->label_result_fail1; + widgets.cbox_uart_com_select = ui->cbox_uart_com_select_1; + widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_1; + break; + case 1: + widgets.txtb_dispaly = ui->txtb_dispaly_2; + widgets.label_runtime_status = ui->label_runtime_status2; + widgets.ledit_spp_addr = ui->ledit_spp_addr_2; + widgets.label_result_success = ui->label_result_success2; + widgets.label_result_fail = ui->label_result_fail2; + widgets.cbox_uart_com_select = ui->cbox_uart_com_select_2; + widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_2; + break; + case 2: + widgets.txtb_dispaly = ui->txtb_dispaly_3; + widgets.label_runtime_status = ui->label_runtime_status3; + widgets.ledit_spp_addr = ui->ledit_spp_addr_3; + widgets.label_result_success = ui->label_result_success3; + widgets.label_result_fail = ui->label_result_fail3; + widgets.cbox_uart_com_select = ui->cbox_uart_com_select_3; + widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_3; + break; + case 3: + widgets.txtb_dispaly = ui->txtb_dispaly_4; + widgets.label_runtime_status = ui->label_runtime_status4; + widgets.ledit_spp_addr = ui->ledit_spp_addr_4; + widgets.label_result_success = ui->label_result_success4; + widgets.label_result_fail = ui->label_result_fail4; + widgets.cbox_uart_com_select = ui->cbox_uart_com_select_4; + widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_4; + break; + default: + widgets.txtb_dispaly = ui->txtb_dispaly; + widgets.label_runtime_status = ui->label_runtime_status1; + widgets.ledit_spp_addr = ui->ledit_spp_addr_1; + widgets.label_result_success = ui->label_result_success1; + widgets.label_result_fail = ui->label_result_fail1; + widgets.cbox_uart_com_select = ui->cbox_uart_com_select_1; + widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_1; + break; } -// if(inOrOut){ -// str_time.append("IN] : "); -// }else{ -// str_time.append("OUT] : "); -// } -// str.prepend(str_time); -// str+="\r\n"; - ui->txtb_dispaly_2->insertPlainText(str); - ui->txtb_dispaly_2->moveCursor(QTextCursor::End); + return widgets; } -void MainWindow::ui_display3(QString str,bool inOrOut) + +// 统一的UI显示函数 +void MainWindow::ui_display(int port_index, QString str, bool inOrOut) { -// QTime Time= QTime::currentTime();//获取系统当前的时间 -// QString str_time = Time.toString("[hh:mm:ss ");//格式化时间 - ui->txtb_dispaly_3->moveCursor(QTextCursor::End); + if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { + qDebug() << tr("无效的端口索引:") << port_index; + return; + } + + UIPortWidgets widgets = getUIPortWidgets(port_index); + if (widgets.txtb_dispaly == nullptr) { + qDebug() << tr("UI控件未找到,端口索引:") << port_index; + return; + } + + widgets.txtb_dispaly->moveCursor(QTextCursor::End); if(inOrOut){ - ui->txtb_dispaly_3->setTextColor(QColor(127, 255, 0)); + widgets.txtb_dispaly->setTextColor(QColor(127, 255, 0)); }else{ - ui->txtb_dispaly_3->setTextColor(Qt::red); + widgets.txtb_dispaly->setTextColor(Qt::red); } -// if(inOrOut){ -// str_time.append("IN] : "); -// }else{ -// str_time.append("OUT] : "); -// } -// str.prepend(str_time); -// str+="\r\n"; - ui->txtb_dispaly_3->insertPlainText(str); - ui->txtb_dispaly_3->moveCursor(QTextCursor::End); + widgets.txtb_dispaly->insertPlainText(str); + widgets.txtb_dispaly->moveCursor(QTextCursor::End); } -void MainWindow::ui_display4(QString str,bool inOrOut) + +// 统一的结果显示函数 +void MainWindow::ui_show_result(int port_index, QString msg, bool success) { -// QTime Time= QTime::currentTime();//获取系统当前的时间 -// QString str_time = Time.toString("[hh:mm:ss ");//格式化时间 - ui->txtb_dispaly_4->moveCursor(QTextCursor::End); - if(inOrOut){ - ui->txtb_dispaly_4->setTextColor(QColor(127, 255, 0)); - }else{ - ui->txtb_dispaly_4->setTextColor(Qt::red); + if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { + qDebug() << tr("无效的端口索引:") << port_index; + return; } -// if(inOrOut){ -// str_time.append("IN] : "); -// }else{ -// str_time.append("OUT] : "); -// } -// str.prepend(str_time); -// str+="\r\n"; - ui->txtb_dispaly_4->insertPlainText(str); - ui->txtb_dispaly_4->moveCursor(QTextCursor::End); + + SerialPortContext *ctx = port_contexts[port_index]; + UIPortWidgets widgets = getUIPortWidgets(port_index); + + if (widgets.label_runtime_status == nullptr) { + qDebug() << tr("UI控件未找到,端口索引:") << port_index; + return; + } + + widgets.label_runtime_status->setText(msg); + if (success) { + ctx->write_success_count++; + widgets.label_result_success->setText(tr("成功%1").arg(ctx->write_success_count)); + } else { + ctx->write_fail_count++; + widgets.label_result_fail->setText(tr("失败%1").arg(ctx->write_fail_count)); + poweroff_watch(port_index); + } + if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { + ctx->spp_timer_handle->stop(); + } +} + +// 向后兼容:ui_display1 +void MainWindow::ui_display1(QString str,bool inOrOut) +{ + ui_display(0, str, inOrOut); +} + +// 向后兼容:ui_show_result1 +void MainWindow::ui_show_result1(QString msg,bool success) +{ + ui_show_result(0, msg, success); +} + +// 向后兼容:ui_display2 +void MainWindow::ui_display2(QString str,bool inOrOut) +{ + ui_display(1, str, inOrOut); +} + +// 向后兼容:ui_display3 +void MainWindow::ui_display3(QString str,bool inOrOut) +{ + ui_display(2, str, inOrOut); } void MainWindow::ui_save_windows() @@ -476,197 +556,188 @@ void MainWindow::ui_setting_read() /* --------------------------------uart操作--------------------------- */ -void MainWindow::uart_process1() +// 统一的uart_process函数 +void MainWindow::uart_process(int port_index) { - qDebug()<<"uart_process1 "<< cmd_index_1; - //处理指令结果 - switch(cmd_index_1){ + if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { + qDebug() << tr("无效的端口索引:") << port_index; + return; + } + + SerialPortContext *ctx = port_contexts[port_index]; + if (ctx == nullptr) { + qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; + return; + } + + UIPortWidgets widgets = getUIPortWidgets(port_index); + + qDebug() << tr("端口%1 uart_process").arg(port_index) << ctx->cmd_index; + // 处理指令结果 + switch(ctx->cmd_index) { case 0: - ui_display1(tr("阻止休眠\r\n"),LOG_DIRECT_IN); - qDebug()<uart_send_data1(ATCMD_SETUART); - return; // 等待SETUART指令完成,不继续执行下一个指令 - } - */ + ui_display(port_index, tr("阻止休眠\r\n"), LOG_DIRECT_IN); + qDebug() << tr("端口%1阻止休眠").arg(port_index); break; case 1: { - //检查当前的号是否已经是写过的号,放置重复写号造成的浪费。 - qDebug() << tr("=== 执行case 1: 查询手表MAC地址 ==="); - qDebug() << tr("uart_rx_buff_array1长度:") << uart_rx_buff_array1.length(); - qDebug() << tr("uart_rx_buff_array1内容:") << uart_rx_buff_array1; - + // 检查当前的号是否已经是写过的号,防止重复写号造成的浪费 + qDebug() << tr("端口%1执行case 1: 查询手表MAC地址").arg(port_index); + qDebug() << tr("端口%1 uart_rx_buff_array长度:").arg(port_index) << ctx->uart_rx_buff_array.length(); + qDebug() << tr("端口%1 uart_rx_buff_array内容:").arg(port_index) << ctx->uart_rx_buff_array; // 使用正则表达式查找MAC地址格式: BTMAC=28:11:06:XX:XX:XX,支持多包检测 - qDebug() << tr("🔍 开始在AT响应中查找MAC地址"); - qDebug() << tr("当前缓存内容:") << uart_rx_buff_array1; - qDebug() << tr("缓存长度:") << uart_rx_buff_array1.length(); + qDebug() << tr("端口%1开始在AT响应中查找MAC地址").arg(port_index); + qDebug() << tr("端口%1当前缓存内容:").arg(port_index) << ctx->uart_rx_buff_array; + qDebug() << tr("端口%1缓存长度:").arg(port_index) << ctx->uart_rx_buff_array.length(); QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); - int ret = macRegex.indexIn(uart_rx_buff_array1); - qDebug() << tr("正则表达式查找结果:") << ret; + int ret = macRegex.indexIn(ctx->uart_rx_buff_array); + qDebug() << tr("端口%1正则表达式查找结果:").arg(port_index) << ret; // 如果正则表达式没找到,尝试简单的BTMAC=查找来调试 - int simple_ret = uart_rx_buff_array1.indexOf("BTMAC="); - qDebug() << tr("简单BTMAC=查找结果:") << simple_ret; + int simple_ret = ctx->uart_rx_buff_array.indexOf("BTMAC="); + qDebug() << tr("端口%1简单BTMAC=查找结果:").arg(port_index) << simple_ret; if (simple_ret >= 0) { // 显示BTMAC=后面的内容,看看是否完整 - QString after_btmac = uart_rx_buff_array1.mid(simple_ret); - qDebug() << tr("BTMAC=后面的内容:") << after_btmac; + QString after_btmac = ctx->uart_rx_buff_array.mid(simple_ret); + qDebug() << tr("端口%1 BTMAC=后面的内容:").arg(port_index) << after_btmac; // 备用方法:如果正则表达式失败,尝试手动提取MAC地址 if (ret < 0) { - qDebug() << tr("🔧 正则表达式失败,尝试备用提取方法"); + qDebug() << tr("端口%1正则表达式失败,尝试备用提取方法").arg(port_index); // 查找BTMAC=后面是否有足够的字符来组成MAC地址 - QString remaining = uart_rx_buff_array1.mid(simple_ret + 6); // 跳过"BTMAC=" - qDebug() << tr("BTMAC=后的剩余内容:") << remaining; + QString remaining = ctx->uart_rx_buff_array.mid(simple_ret + 6); // 跳过"BTMAC=" + qDebug() << tr("端口%1 BTMAC=后的剩余内容:").arg(port_index) << remaining; // 尝试提取MAC地址,即使不完整也显示当前状态 QRegExp partialMacRegex("([0-9A-Fa-f:]+)"); if (partialMacRegex.indexIn(remaining) >= 0) { QString partialMac = partialMacRegex.cap(1); - qDebug() << tr("部分MAC地址:") << partialMac; + qDebug() << tr("端口%1部分MAC地址:").arg(port_index) << partialMac; // 检查是否是完整的MAC地址(应该有5个冒号) int colonCount = partialMac.count(':'); - qDebug() << tr("冒号数量:") << colonCount << tr("(完整MAC地址应该有5个冒号)"); + qDebug() << tr("端口%1冒号数量:").arg(port_index) << colonCount << tr("(完整MAC地址应该有5个冒号)"); if (colonCount == 5) { - qDebug() << tr("✅ 检测到完整MAC地址,使用备用方法处理"); + qDebug() << tr("端口%1检测到完整MAC地址,使用备用方法处理").arg(port_index); QString unit = partialMac.replace(":", "").toUpper(); - qDebug() << tr("备用方法提取的MAC地址:") << unit; + qDebug() << tr("端口%1备用方法提取的MAC地址:").arg(port_index) << unit; bool mac_used = settings::getInstance().getMacUsed(unit.toUpper()); - qDebug() << tr("MAC地址是否已被使用:") << mac_used; + qDebug() << tr("端口%1 MAC地址是否已被使用:").arg(port_index) << mac_used; if (mac_used) { - ui_display1(tr("手表地址")+unit+tr("已占用\r\n"),LOG_DIRECT_OUT); - ui_show_result1(tr("Mac地址已占用"),false); - cmd_index_1 = -1; + ui_display(port_index, tr("手表地址") + unit + tr("已占用\r\n"), LOG_DIRECT_OUT); + ui_show_result(port_index, tr("Mac地址已占用"), false); + ctx->cmd_index = -1; } else { - ui_display1(tr("手表当前地址")+unit+tr(" 可用!\r\n"),LOG_DIRECT_IN); + ui_display(port_index, tr("手表当前地址") + unit + tr(" 可用!\r\n"), LOG_DIRECT_IN); } // 跳过后面的正常处理 break; } else { - qDebug() << tr("⚠️ MAC地址不完整,等待更多数据"); + qDebug() << tr("端口%1 MAC地址不完整,等待更多数据").arg(port_index); } } } } - if (ret >= 0) - { + if (ret >= 0) { QString mac_with_colon = macRegex.cap(1); // 提取MAC地址部分 (28:11:06:4D:29:EF) - qDebug() << tr("找到BTMAC=,位置:") << ret; - qDebug() << tr("提取的MAC地址(带冒号):") << mac_with_colon; + qDebug() << tr("端口%1找到BTMAC=,位置:").arg(port_index) << ret; + qDebug() << tr("端口%1提取的MAC地址(带冒号):").arg(port_index) << mac_with_colon; - QString unit = mac_with_colon.replace(":", "").toUpper(); // "28110604D29EF" - qDebug() << tr("处理后的MAC地址(无冒号):") << unit; + QString unit = mac_with_colon.replace(":", "").toUpper(); // "28110604D29EF" + qDebug() << tr("端口%1处理后的MAC地址(无冒号):").arg(port_index) << unit; bool mac_used = settings::getInstance().getMacUsed(unit.toUpper()); - qDebug() << tr("MAC地址是否已被使用:") << mac_used; + qDebug() << tr("端口%1 MAC地址是否已被使用:").arg(port_index) << mac_used; - if (mac_used) - { - ui_display1(tr("手表地址")+unit+tr("已占用\r\n"),LOG_DIRECT_OUT); - ui_show_result1(tr("Mac地址已占用"),false); - cmd_index_1 = -1; - }else{ - ui_display1(tr("手表当前地址")+unit+tr(" 可用!\r\n"),LOG_DIRECT_IN); - } - - }else{ - qDebug() << tr("在uart_rx_buff_array1中未找到BTMAC="); - qDebug() << tr("完整缓存内容(十六进制):") << uart_rx_buff_array1.toHex(); - ui_display1(tr("查询手表Mac失败!\r\n"),LOG_DIRECT_OUT); - cmd_index_1 = -1; - ui_show_result1(tr("查询手表Mac失败"),false); + if (mac_used) { + ui_display(port_index, tr("手表地址") + unit + tr("已占用\r\n"), LOG_DIRECT_OUT); + ui_show_result(port_index, tr("Mac地址已占用"), false); + ctx->cmd_index = -1; + } else { + ui_display(port_index, tr("手表当前地址") + unit + tr(" 可用!\r\n"), LOG_DIRECT_IN); + } + } else { + qDebug() << tr("端口%1在uart_rx_buff_array中未找到BTMAC=").arg(port_index); + qDebug() << tr("端口%1完整缓存内容(十六进制):").arg(port_index) << ctx->uart_rx_buff_array.toHex(); + ui_display(port_index, tr("查询手表Mac失败!\r\n"), LOG_DIRECT_OUT); + ctx->cmd_index = -1; + ui_show_result(port_index, tr("查询手表Mac失败"), false); } - } break; case 2: { - QString new_mac = ui->ledit_spp_addr_1->text(); - ui_display1(tr("执行设置地址\r\n"),LOG_DIRECT_OUT); - qDebug() << tr("=== 执行case 2: 设置MAC地址完成 ==="); - qDebug() << tr("设置的MAC地址:") << new_mac; - ui_display1(tr("MAC地址设置完成,等待设备处理...\r\n"), LOG_DIRECT_IN); + QString new_mac = widgets.ledit_spp_addr->text(); + ui_display(port_index, tr("执行设置地址\r\n"), LOG_DIRECT_OUT); + qDebug() << tr("端口%1执行case 2: 设置MAC地址完成").arg(port_index); + qDebug() << tr("端口%1设置的MAC地址:").arg(port_index) << new_mac; + ui_display(port_index, tr("MAC地址设置完成,等待设备处理...\r\n"), LOG_DIRECT_IN); } break; case 3: { // 验证设置的MAC地址是否成功 - QString unit = ui->ledit_spp_addr_1->text(); - qDebug() << tr("=== 执行case 3: 验证设置的MAC地址 ==="); - qDebug() << tr("期望的MAC地址:") << unit; - qDebug() << tr("响应数据长度:") << uart_rx_buff_array1.length(); + QString unit = widgets.ledit_spp_addr->text(); + qDebug() << tr("端口%1执行case 3: 验证设置的MAC地址").arg(port_index); + qDebug() << tr("端口%1期望的MAC地址:").arg(port_index) << unit; + qDebug() << tr("端口%1响应数据长度:").arg(port_index) << ctx->uart_rx_buff_array.length(); - if (uart_rx_buff_array1.length() < 50) { - qDebug() << tr("⚠️ 响应数据较短,可能是超时或设备重启中"); + if (ctx->uart_rx_buff_array.length() < 50) { + qDebug() << tr("端口%1响应数据较短,可能是超时或设备重启中").arg(port_index); } - // 使用正则表达式查找MAC地址格式: BTMAC=28:11:06:XX:XX:XX,支持多包检测 QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); - int ret = macRegex.indexIn(uart_rx_buff_array1); - if (ret >= 0) - { + int ret = macRegex.indexIn(ctx->uart_rx_buff_array); + if (ret >= 0) { // 提取MAC地址部分 QString mac_with_colon = macRegex.cap(1); // "28:11:06:4D:29:EF" - QString unit_watch = mac_with_colon.replace(":", "").toUpper(); // "28110604D29EF" + QString unit_watch = mac_with_colon.replace(":", "").toUpper(); // "28110604D29EF" - qDebug() << tr("手表返回的MAC地址:") << unit_watch; - qDebug() << tr("期望的MAC地址:") << unit; + qDebug() << tr("端口%1手表返回的MAC地址:").arg(port_index) << unit_watch; + qDebug() << tr("端口%1期望的MAC地址:").arg(port_index) << unit; - if(unit_watch.toUpper() == unit.toUpper()) - { - ui_display1(tr("设置Mac")+unit_watch+tr("成功\r\n"),LOG_DIRECT_IN); - }else{ - ui_display1(tr("设置Mac")+unit_watch+tr("失败\r\n"),LOG_DIRECT_OUT); - cmd_index_1 = -2; - ui_show_result1(tr("Mac地址设置失败"),false); - } - - }else{ - ui_display1(tr("设置Mac")+unit+tr("失败\r\n"),LOG_DIRECT_OUT); - cmd_index_1 = -3; - ui_show_result1(tr("查询手表Mac失败"),false); + if (unit_watch.toUpper() == unit.toUpper()) { + ui_display(port_index, tr("设置Mac") + unit_watch + tr("成功\r\n"), LOG_DIRECT_IN); + } else { + ui_display(port_index, tr("设置Mac") + unit_watch + tr("失败\r\n"), LOG_DIRECT_OUT); + ctx->cmd_index = -2; + ui_show_result(port_index, tr("Mac地址设置失败"), false); + } + } else { + ui_display(port_index, tr("设置Mac") + unit + tr("失败\r\n"), LOG_DIRECT_OUT); + ctx->cmd_index = -3; + ui_show_result(port_index, tr("查询手表Mac失败"), false); } - } break; case 4: { - qDebug() << tr("=== 执行case 4: 获取CPU ID ==="); - qDebug() << tr("响应内容:") << uart_rx_buff_array1; - qDebug() << tr("响应长度:") << uart_rx_buff_array1.length(); + qDebug() << tr("端口%1执行case 4: 获取CPU ID").arg(port_index); + qDebug() << tr("端口%1响应内容:").arg(port_index) << ctx->uart_rx_buff_array; + qDebug() << tr("端口%1响应长度:").arg(port_index) << ctx->uart_rx_buff_array.length(); // 使用分包检测方式查找CPU ID信息 - int ret = uart_rx_buff_array1.indexOf("[soc id:]"); - qDebug() << tr("[soc id:]查找结果:") << ret; + int ret = ctx->uart_rx_buff_array.indexOf("[soc id:]"); + qDebug() << tr("端口%1 [soc id:]查找结果:").arg(port_index) << ret; - if (ret >= 0) - { + if (ret >= 0) { // 查找[soc id:]后面的内容,直到遇到OK~或其他结束标志 - QString soc_section = uart_rx_buff_array1.mid(ret); - qDebug() << tr("SOC部分内容:") << soc_section; + QString soc_section = ctx->uart_rx_buff_array.mid(ret); + qDebug() << tr("端口%1 SOC部分内容:").arg(port_index) << soc_section; // 检查是否包含完整的数据结束标志 bool hasCompleteData = soc_section.contains("OK~") || soc_section.contains("\r\n\r\n"); - qDebug() << tr("是否包含完整数据标志:") << hasCompleteData; + qDebug() << tr("端口%1是否包含完整数据标志:").arg(port_index) << hasCompleteData; // 提取所有的十六进制数据(0x开头的),支持分包和多行格式 QRegExp hexRegex("0x[0-9A-Fa-f]{4}"); @@ -676,11 +747,11 @@ void MainWindow::uart_process1() while ((pos = hexRegex.indexIn(soc_section, pos)) != -1) { hexValues << hexRegex.cap(0); pos += hexRegex.matchedLength(); - qDebug() << tr("找到十六进制值:") << hexRegex.cap(0) << tr("位置:") << pos; + qDebug() << tr("端口%1找到十六进制值:").arg(port_index) << hexRegex.cap(0) << tr("位置:") << pos; } - qDebug() << tr("提取的十六进制值:") << hexValues; - qDebug() << tr("十六进制值数量:") << hexValues.size(); + qDebug() << tr("端口%1提取的十六进制值:").arg(port_index) << hexValues; + qDebug() << tr("端口%1十六进制值数量:").arg(port_index) << hexValues.size(); // 检查数据完整性:需要至少10个十六进制值且有结束标志 if (hexValues.size() >= 10 && hasCompleteData) { @@ -690,92 +761,78 @@ void MainWindow::uart_process1() cpu_id += hex.mid(2); // 去掉"0x"前缀 } - qDebug() << tr("组合的CPU ID:") << cpu_id; - ui_display1("cpuid: " + cpu_id + "\r\n", LOG_DIRECT_IN); + qDebug() << tr("端口%1组合的CPU ID:").arg(port_index) << cpu_id; + ui_display(port_index, "cpuid: " + cpu_id + "\r\n", LOG_DIRECT_IN); - int db_ret = settings::getInstance().set_mac_used(ui->ledit_spp_addr_1->text(), cpu_id, true); - qDebug() << "set mac used " << ui->ledit_spp_addr_1->text() << " " << cpu_id << " ret " << db_ret; + int db_ret = settings::getInstance().set_mac_used(widgets.ledit_spp_addr->text(), cpu_id, true); + qDebug() << tr("端口%1 set mac used").arg(port_index) << widgets.ledit_spp_addr->text() << cpu_id << tr("ret") << db_ret; - if (db_ret == 1) - { - ui->textBrowser_result->setText(settings::getInstance().getmacStatusFull()); - ui_display1(tr("设置mac成功\r\n"), LOG_DIRECT_IN); + if (db_ret == 1) { + ui->textBrowser_result->setText(settings::getInstance().getmacStatusFull()); + ui_display(port_index, tr("设置mac成功\r\n"), LOG_DIRECT_IN); } else { - ui_show_result1(tr("获取cpuid失败\r\n"), false); + ui_show_result(port_index, tr("获取cpuid失败\r\n"), false); } } else { - qDebug() << tr("CPU ID数据不完整 - 十六进制值:") << hexValues.size() << tr("完整标志:") << hasCompleteData; + qDebug() << tr("端口%1 CPU ID数据不完整 - 十六进制值:").arg(port_index) << hexValues.size() << tr("完整标志:") << hasCompleteData; if (!hasCompleteData) { - qDebug() << tr("等待完整的AT^GETIDS响应数据"); - ui_display1(tr("等待CPU ID完整数据...\r\n"), LOG_DIRECT_OUT); + qDebug() << tr("端口%1等待完整的AT^GETIDS响应数据").arg(port_index); + ui_display(port_index, tr("等待CPU ID完整数据...\r\n"), LOG_DIRECT_OUT); return; // 等待更多数据 } else if (hexValues.size() < 10) { - qDebug() << tr("十六进制值数量不足,期望>=10,实际:") << hexValues.size(); - ui_display1(tr("CPU ID格式不正确\r\n"), LOG_DIRECT_OUT); - cmd_index_1 = -4; - ui_show_result1(tr("获取CPU ID失败"), false); + qDebug() << tr("端口%1十六进制值数量不足,期望>=10,实际:").arg(port_index) << hexValues.size(); + ui_display(port_index, tr("CPU ID格式不正确\r\n"), LOG_DIRECT_OUT); + ctx->cmd_index = -4; + ui_show_result(port_index, tr("获取CPU ID失败"), false); } } } else { - qDebug() << tr("未找到[soc id:]标志,可能数据分包传输中"); - ui_display1(tr("等待CPU ID数据...\r\n"), LOG_DIRECT_OUT); + qDebug() << tr("端口%1未找到[soc id:]标志,可能数据分包传输中").arg(port_index); + ui_display(port_index, tr("等待CPU ID数据...\r\n"), LOG_DIRECT_OUT); // 不使用备用CPU ID,直接失败 - cmd_index_1 = -4; - ui_show_result1(tr("获取CPU ID失败"), false); + ctx->cmd_index = -4; + ui_show_result(port_index, tr("获取CPU ID失败"), false); } } break; case 5: { - int ret = uart_rx_buff_array1.indexOf("power off device"); - if (ret >= 0 ) - { - ui_display1(tr("关机成功\r\n"),LOG_DIRECT_IN); - }else{ - ui_display1(tr("关机失败\r\n"),LOG_DIRECT_OUT); + int ret = ctx->uart_rx_buff_array.indexOf("power off device"); + if (ret >= 0) { + ui_display(port_index, tr("关机成功\r\n"), LOG_DIRECT_IN); + } else { + ui_display(port_index, tr("关机失败\r\n"), LOG_DIRECT_OUT); } - ui_show_result1(tr("设置mac成功\r\n"),true); - + ui_show_result(port_index, tr("设置mac成功\r\n"), true); } break; default: { - cmd_index_1=-1; + ctx->cmd_index = -1; } break; } } + +// 向后兼容:uart_process1 +void MainWindow::uart_process1() +{ + uart_process(0); +} +// 向后兼容:uart_process2/3/4 void MainWindow::uart_process2() { -// if (ui->pbtn_open_uart->isChecked()) { - QString str_com = ui->cbox_uart_com_select_1->currentText(); - QString str_uart_baud = ui->cbox_uart_baud_select->currentText(); -// uart_open(str_com,str_uart_baud); -// } else { -// uart_close(); -// } + uart_process(1); } void MainWindow::uart_process3() { -// if (ui->pbtn_open_uart->isChecked()) { - QString str_com = ui->cbox_uart_com_select_1->currentText(); - QString str_uart_baud = ui->cbox_uart_baud_select->currentText(); -// uart_open(str_com,str_uart_baud); -// } else { -// uart_close(); -// } + uart_process(2); } void MainWindow::uart_process4() { -// if (ui->pbtn_open_uart->isChecked()) { - QString str_com = ui->cbox_uart_com_select_1->currentText(); - QString str_uart_baud = ui->cbox_uart_baud_select->currentText(); -// uart_open(str_com,str_uart_baud); -// } else { -// uart_close(); -// } + uart_process(3); } //void MainWindow::uart_open(QString com,QString com_baud) //{ @@ -785,59 +842,123 @@ void MainWindow::uart_process4() //{ //} -void MainWindow::uart_send_data1(QString cmd) +// 统一的uart_send_data函数 +void MainWindow::uart_send_data(int port_index, QString cmd) { - qint64 ret =0; + if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { + qDebug() << tr("无效的端口索引:") << port_index; + return; + } + + SerialPortContext *ctx = port_contexts[port_index]; + if (ctx == nullptr || ctx->serialport == nullptr) { + qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; + return; + } + + qint64 ret = 0; // 发送AT指令之前清空缓存区,确保响应数据的准确性 - uart_rx_buff_array1.clear(); - qDebug() << tr("🧹 发送AT指令前清空缓存区"); + ctx->uart_rx_buff_array.clear(); + qDebug() << tr("端口%1发送AT指令前清空缓存区").arg(port_index); - qDebug()<<"uart_send_data1 "<write(cmd.toUtf8()); - m_bytesToWrite1 = ret; - qDebug()<<"uart_send_data1 "<serialport->write(cmd.toUtf8()); + ctx->m_bytesToWrite = ret; + qDebug() << tr("端口%1 uart_send_data").arg(port_index) << cmd << tr(" ret") << ctx->m_bytesToWrite; - G_cmd=cmd; - if (spp_timer_handle1->isActive()) - spp_timer_handle1->stop(); + ctx->G_cmd = cmd; + if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { + ctx->spp_timer_handle->stop(); + } // 对于特定命令使用更长的超时时间 if (cmd.contains("GETIDS")) { - spp_timer_handle1->start(5000); // 5秒超时 - qDebug() << tr("GETIDS命令使用5秒超时"); + ctx->spp_timer_handle->start(5000); // 5秒超时 + qDebug() << tr("端口%1 GETIDS命令使用5秒超时").arg(port_index); } else if (cmd.contains("GETBTMAC")) { - spp_timer_handle1->start(3000); // GETBTMAC命令3秒超时 - qDebug() << tr("GETBTMAC命令使用3秒超时"); + ctx->spp_timer_handle->start(3000); // GETBTMAC命令3秒超时 + qDebug() << tr("端口%1 GETBTMAC命令使用3秒超时").arg(port_index); } else { - spp_timer_handle1->start(1500); // 其他命令1.5秒超时 + ctx->spp_timer_handle->start(1500); // 其他命令1.5秒超时 } -// ui_display1(cmd,true); -// 发送指令,在发送结束的handleBytesWritten1中,设置接收状态, -// 接收函数 readData1 中确认指令是否执行完毕,然后执行下一个指令。 + // 发送指令,在发送结束的handleBytesWritten中,设置接收状态, + // 接收函数 readData 中确认指令是否执行完毕,然后执行下一个指令。 +} + +// 向后兼容:uart_send_data1 +void MainWindow::uart_send_data1(QString cmd) +{ + uart_send_data(0, cmd); } +// 向后兼容:uart_send_data2/3/4 void MainWindow::uart_send_data2(QString cmd) { - + uart_send_data(1, cmd); } void MainWindow::uart_send_data3(QString cmd) { - + uart_send_data(2, cmd); } void MainWindow::uart_send_data4(QString cmd) { + uart_send_data(3, cmd); +} + +// 统一的spp_timer_callback函数 +void MainWindow::spp_timer_callback(int port_index) +{ + if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { + qDebug() << tr("无效的端口索引:") << port_index; + return; + } + + SerialPortContext *ctx = port_contexts[port_index]; + if (ctx == nullptr) { + qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; + return; + } + + ctx->uart_rx_flag = false; + qDebug() << tr("端口%1 AT命令超时:").arg(port_index) << ctx->G_cmd; + + if (ctx->G_cmd == ATCMD_ADD_VOTE) { + uart_send_data(port_index, ATCMD_ADD_VOTE); + } else if (ctx->G_cmd.contains("GETIDS")) { + // GETIDS命令超时,跳过CPU ID获取,继续执行关机 + ui_display(port_index, tr("获取CPU ID超时,跳过此步骤\r\n"), LOG_DIRECT_OUT); + + // 直接跳到关机步骤 + ctx->cmd_index = 4; // 设置为4,这样下次会执行case 5(关机) + ctx->uart_rx_flag = false; + uart_process(port_index); // 直接处理,跳过CPU ID + } else { + ui_display(port_index, tr("AT命令超时: %1\r\n").arg(ctx->G_cmd), LOG_DIRECT_OUT); + if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { + ctx->spp_timer_handle->stop(); + } + } +} +// 向后兼容:spp_timer_callback1 +void MainWindow::spp_timer_callback1() +{ + spp_timer_callback(0); } // uart收到的数据进行回显到显示栏 void MainWindow::uart_rx_dispaly1(int buf_len, u8Piont buf) { - uart_rx_flag1 = true; - if (uart_rx_Ignoring_display) { - QString str((char *)buf); - if(str.contains("ADDR")){ + // 使用端口0的上下文 + SerialPortContext *ctx = port_contexts[0]; + if (ctx) { + ctx->uart_rx_flag = true; + if (ctx->uart_rx_Ignoring_display) { + QString str((char *)buf); + if(str.contains("ADDR")){ // ui->ledit_dongle_mac->setText(str.mid(str.indexOf("=",0)+1,12)); + } + return; } - return; } QString str; QByteArray data((const char*)buf, buf_len); @@ -937,205 +1058,187 @@ void MainWindow::spp_connected_callback() { ui_display1("com send cmd failed! ",false); } +// 向后兼容:spp_timer_callback2/3/4 void MainWindow::spp_timer_callback2() { - + spp_timer_callback(1); } void MainWindow::spp_timer_callback3() { - + spp_timer_callback(2); } void MainWindow::spp_timer_callback4() { - + spp_timer_callback(3); } -void MainWindow::spp_timer_callback1() -{ - uart_rx_flag1 = false; - qDebug() << tr("AT命令超时:") << G_cmd; - - if(G_cmd==ATCMD_ADD_VOTE) - { - this->uart_send_data1(ATCMD_ADD_VOTE); - } - else if(G_cmd.contains("GETIDS")) - { - // GETIDS命令超时,跳过CPU ID获取,继续执行关机 - ui_display1(tr("获取CPU ID超时,跳过此步骤\r\n"), LOG_DIRECT_OUT); - - // 直接跳到关机步骤 - cmd_index_1 = 4; // 设置为4,这样下次会执行case 5(关机) - uart_rx_flag1 = false; - uart_process1(); // 直接处理,跳过CPU ID - } - else - { - ui_display1(tr("AT命令超时: %1\r\n").arg(G_cmd), LOG_DIRECT_OUT); - if (spp_timer_handle1->isActive()) - spp_timer_handle1->stop(); - } -} +// spp_timer_callback1已在后面实现为向后兼容函数 -void MainWindow::spp_connect_1() +// 统一的spp_connect函数 +void MainWindow::spp_connect(int port_index) { - if (working_state_1 == false) - { + if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { + qDebug() << tr("无效的端口索引:") << port_index; + return; + } + + SerialPortContext *ctx = port_contexts[port_index]; + if (ctx == nullptr || ctx->serialport == nullptr) { + qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; + return; + } + + UIPortWidgets widgets = getUIPortWidgets(port_index); + + if (ctx->working_state == false) { + // 开始工作 QString baud_rate = ui->cbox_uart_baud_select->currentText(); - QString com_name = ui->cbox_uart_com_select_1->currentText(); + QString com_name = widgets.cbox_uart_com_select->currentText(); - qDebug() << tr("=== 开始连接串口1 ==="); + qDebug() << tr("=== 开始连接串口%1 ===").arg(port_index + 1); qDebug() << tr("串口名称:") << com_name; qDebug() << tr("波特率:") << baud_rate; - serialport1->setPortName(com_name); - serialport1->setBaudRate(baud_rate.toInt()); + ctx->serialport->setPortName(com_name); + ctx->serialport->setBaudRate(baud_rate.toInt()); // 设置串口参数以提高兼容性 - serialport1->setDataBits(QSerialPort::Data8); - serialport1->setParity(QSerialPort::NoParity); - serialport1->setStopBits(QSerialPort::OneStop); - serialport1->setFlowControl(QSerialPort::NoFlowControl); + ctx->serialport->setDataBits(QSerialPort::Data8); + ctx->serialport->setParity(QSerialPort::NoParity); + ctx->serialport->setStopBits(QSerialPort::OneStop); + ctx->serialport->setFlowControl(QSerialPort::NoFlowControl); // 设置更大的读缓冲区,提高数据处理能力 - serialport1->setReadBufferSize(32768); // 32KB缓冲区 + ctx->serialport->setReadBufferSize(32768); // 32KB缓冲区 - qDebug() << tr("串口配置 - 波特率:") << serialport1->baudRate(); - qDebug() << tr("串口配置 - 数据位:") << serialport1->dataBits(); - qDebug() << tr("串口配置 - 停止位:") << serialport1->stopBits(); - qDebug() << tr("串口配置 - 校验位:") << serialport1->parity(); - qDebug() << tr("串口配置 - 流控制:") << serialport1->flowControl(); - qDebug() << tr("串口读缓冲区大小:") << serialport1->readBufferSize(); - - ui->txtb_dispaly->clear(); - if (serialport1->isOpen()) - { - qDebug() << tr("串口已经打开,重置命令索引"); - this->cmd_index_1 = 0; -// this->uart_send_data1(ATCMD_GET_MAC); - - // - }else{ - if (serialport1->open(QIODevice::ReadWrite)) { - // serialport1->setEnabled(true); - // serialport1->setLocalEchoEnabled(false); - - qDebug() << tr("串口打开成功,连接信号槽"); - connect(serialport1, &QSerialPort::readyRead, this, &MainWindow::readData1); - connect(serialport1, &QSerialPort::bytesWritten, this, &MainWindow::handleBytesWritten1); -this->cmd_index_1 = 0; -// this->uart_send_data1(ATCMD_GET_MAC); - // serialport1->close(); - // disconnect(serialport1, &QSerialPort::readyRead, this, &MainWindow::readData1); - + qDebug() << tr("端口%1串口配置 - 波特率:").arg(port_index) << ctx->serialport->baudRate(); + qDebug() << tr("端口%1串口配置 - 数据位:").arg(port_index) << ctx->serialport->dataBits(); + qDebug() << tr("端口%1串口配置 - 停止位:").arg(port_index) << ctx->serialport->stopBits(); + qDebug() << tr("端口%1串口配置 - 校验位:").arg(port_index) << ctx->serialport->parity(); + qDebug() << tr("端口%1串口配置 - 流控制:").arg(port_index) << ctx->serialport->flowControl(); + qDebug() << tr("端口%1串口读缓冲区大小:").arg(port_index) << ctx->serialport->readBufferSize(); + + widgets.txtb_dispaly->clear(); + if (ctx->serialport->isOpen()) { + qDebug() << tr("端口%1串口已经打开,重置命令索引").arg(port_index); + ctx->cmd_index = 0; + } else { + if (ctx->serialport->open(QIODevice::ReadWrite)) { + qDebug() << tr("端口%1串口打开成功,连接信号槽").arg(port_index); + + // 使用lambda捕获port_index来连接信号槽 + connect(ctx->serialport, &QSerialPort::readyRead, [this, port_index]() { + this->readData(port_index); + }); + connect(ctx->serialport, &QSerialPort::bytesWritten, [this, port_index](qint64 bytes) { + this->handleBytesWritten(port_index, bytes); + }); + + ctx->cmd_index = 0; } else { - qDebug() << tr("串口打开失败:") << serialport1->errorString(); - QMessageBox::critical(this, tr("Error"), serialport1->errorString()); - - ui_display1(tr("Open error\r\n"),false); + qDebug() << tr("端口%1串口打开失败:").arg(port_index) << ctx->serialport->errorString(); + QMessageBox::critical(this, tr("Error"), ctx->serialport->errorString()); + ui_display(port_index, tr("Open error\r\n"), false); return; } } - // 开始工作 - qDebug() << tr("=== 开始写地址工作模式 ==="); - qDebug() << tr("系统信息 - Qt版本:") << QT_VERSION_STR; - qDebug() << tr("系统信息 - 编译器:") << - #ifdef _MSC_VER - "MSVC " + QString::number(_MSC_VER); - #elif defined(__GNUC__) - "GCC " + QString::number(__GNUC__) + "." + QString::number(__GNUC_MINOR__); - #else - "Unknown"; - #endif - working_state_1 = true; - write_fail_count1= 0; - write_success_count1 =0; - + // 开始工作 + qDebug() << tr("端口%1开始写地址工作模式").arg(port_index); + ctx->working_state = true; + ctx->write_fail_count = 0; + ctx->write_success_count = 0; // 初始化开机检测缓存 - boot_detect_buffer.clear(); - waiting_cmd1 = false; // 重置等待命令状态 - startup_complete_detected = false; // 重置启动完成检测标志 - // setuart_sent = false; // 重置SETUART指令发送标志 (已注释:不再使用SETUART) - qDebug() << tr("初始化开机检测缓存"); - + ctx->boot_detect_buffer.clear(); + ctx->waiting_cmd = false; // 重置等待命令状态 + ctx->startup_complete_detected = false; // 重置启动完成检测标志 + qDebug() << tr("端口%1初始化开机检测缓存").arg(port_index); - ui->label_result_fail1->setText(tr("失败%1").arg(write_fail_count1)); - ui->label_result_success1->setText(tr("成功%1").arg(write_success_count1)); - ui->pbtn_spp_reconnect_1->setText(tr("停止写地址")); -ui->label_runtime_status1->setText(tr("等待手表开机")); + widgets.label_result_fail->setText(tr("失败%1").arg(ctx->write_fail_count)); + widgets.label_result_success->setText(tr("成功%1").arg(ctx->write_success_count)); + widgets.pbtn_spp_reconnect->setText(tr("停止写地址")); + widgets.label_runtime_status->setText(tr("等待手表开机")); - qDebug() << tr("工作状态设置: working_state_1 = true"); - qDebug() << tr("等待检测手表开机信号:") << BOOT_UP_MSG; - qDebug() << tr("等待检测命令时机信号:") << TIME_FOR_CMD; - -// QString avalible_mac = settings::getInstance().getAvalibleMac(); -// ui->ledit_spp_addr_1->setText(avalible_mac); -// int ret =0; - // ret = settings::getInstance().set_mac_used(avalible_mac,"",true); - - // qDebug()<< "set mac "<< avalible_mac<<" used , ret "<< ret; - + qDebug() << tr("端口%1工作状态设置: working_state = true").arg(port_index); + qDebug() << tr("端口%1等待检测手表开机信号:").arg(port_index) << BOOT_UP_MSG; + qDebug() << tr("端口%1等待检测命令时机信号:").arg(port_index) << TIME_FOR_CMD; - qDebug()<pbtn_spp_reconnect_1->setText(tr("开始写地址")); - ui->label_runtime_status1->setText(tr("已停止写地址...")); - working_state_1 = false; + qDebug() << settings::getInstance().getmacStatusFull(); + } else { + // 停止工作 + qDebug() << tr("端口%1停止写地址工作模式").arg(port_index); + widgets.pbtn_spp_reconnect->setText(tr("开始写地址")); + widgets.label_runtime_status->setText(tr("已停止写地址...")); + ctx->working_state = false; // 清空开机检测缓存 - boot_detect_buffer.clear(); - qDebug() << tr("清空开机检测缓存"); + ctx->boot_detect_buffer.clear(); + qDebug() << tr("端口%1清空开机检测缓存").arg(port_index); - ui->txtb_dispaly->clear(); - if(serialport1->isOpen()) - serialport1->close(); - disconnect(serialport1, &QSerialPort::readyRead, this, &MainWindow::readData1); - disconnect(serialport1, &QSerialPort::bytesWritten, this, &MainWindow::handleBytesWritten1); - - + widgets.txtb_dispaly->clear(); + if (ctx->serialport->isOpen()) { + ctx->serialport->close(); + } + disconnect(ctx->serialport, &QSerialPort::readyRead, this, nullptr); + disconnect(ctx->serialport, &QSerialPort::bytesWritten, this, nullptr); } - +} -// this->serialport1->setBaudRate() -// ui_display1("connect com1 ",false); +// 向后兼容:spp_connect_1 +void MainWindow::spp_connect_1() +{ + spp_connect(0); } -void MainWindow::handleBytesWritten1(qint64 bytes) +// 统一的handleBytesWritten函数 +void MainWindow::handleBytesWritten(int port_index, qint64 bytes) { - qDebug()<<" handleBytesWritten1 m_bytesToWrite1 "<= MAX_SERIAL_PORTS) { + qDebug() << tr("无效的端口索引:") << port_index; + return; + } + + SerialPortContext *ctx = port_contexts[port_index]; + if (ctx == nullptr) { + qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; + return; + } + + qDebug() << tr("端口%1 handleBytesWritten m_bytesToWrite").arg(port_index) << ctx->m_bytesToWrite << tr("written") << bytes; + ctx->m_bytesToWrite -= bytes; + if (ctx->m_bytesToWrite == 0) { + ctx->uart_rx_flag = true; + ctx->uart_rx_buff_array.clear(); } } + +// 向后兼容:handleBytesWritten1 +void MainWindow::handleBytesWritten1(qint64 bytes) +{ + handleBytesWritten(0, bytes); +} +// 向后兼容:spp_connect_2/3/4 void MainWindow::spp_connect_2() { - ui_display2("connect com1 ",false); - + spp_connect(1); } void MainWindow::spp_connect_3() { - ui_display3("connect com1 ",false); - + spp_connect(2); } void MainWindow::spp_connect_4() { - ui_display4("connect com1 ",false); - + spp_connect(3); } void MainWindow::spp_connect_all() { - uart_rx_Ignoring_display = true; + // 使用端口0的上下文 + SerialPortContext *ctx = port_contexts[0]; + if (ctx) { + ctx->uart_rx_Ignoring_display = true; + } // dongle_is_connected = false; // dongle_try_count = 0; // spp_try_count = 0; @@ -1144,7 +1247,9 @@ void MainWindow::spp_connect_all() ui_display1("spp connectting...",false); // spp查询定时器周期为1500ms - spp_timer_handle1->start(1500); + if (spp_timer_handles[0]) { + spp_timer_handles[0]->start(1500); + } // ui->pbtn_spp_connect->setEnabled(false); } diff --git a/mainwindow.h b/mainwindow.h index 609d94d..eedfe6c 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -19,8 +19,15 @@ #include "sqldbmanager.h" #include "settings.h" +#include "serial_port_context.h" +#include +#include +#include +#include +#include #define COM_NUMBER 10 +#define MAX_SERIAL_PORTS 4 // 封装了UI上需要调用的所有函数接口 QT_BEGIN_NAMESPACE @@ -42,32 +49,52 @@ private: bool LOG_DIRECT_OUT=false; bool LOG_DIRECT_IN=true; /* ------------------------uart------------------------------- */ - Result_Thread *result_thread1; - - - /*----------写地址任务相关变量---------------*/ + // 统一配置:4个串口的上下文数组 + SerialPortContext *port_contexts[MAX_SERIAL_PORTS]; + QTimer *spp_timer_handles[MAX_SERIAL_PORTS]; + Result_Thread *result_threads[MAX_SERIAL_PORTS]; + + // 向后兼容:保留原有变量名(映射到port_contexts[0]) + // 这些变量将在实现中通过宏或内联函数映射到port_contexts[0] QSerialPort *serialport1; - //指令长度 - qint64 m_bytesToWrite1=0; - //指令顺序, AT =0 , SET_MAC = 1 , GET_MAC = 2 , GET_CPUINFO = 3; - int cmd_index_1=0; - int write_success_count1=0; - int write_fail_count1=0; - - // 是否忽略uart数据,不回显 - bool uart_rx_Ignoring_display {false}; - // 是否有uart通路数据上报 - bool uart_rx_flag1 {false}; - QByteArray uart_rx_buff_array1; - QTimer *spp_timer_handle1 {nullptr}; - bool working_state_1=false; //true 说明写号执行过程中,false说明写号结束 - bool waiting_cmd1 = false; //等待命令时机 - bool startup_complete_detected = false; //启动完成信号已检测标志 - // bool setuart_sent = false; //SETUART指令是否已发送标志 (已注释:不再使用SETUART) - QByteArray boot_detect_buffer; //用于缓存开机检测数据,处理分包情况 + QSerialPort *serialport2; + QSerialPort *serialport3; + QSerialPort *serialport4; + Result_Thread *result_thread1; + Result_Thread *result_thread2; + Result_Thread *result_thread3; + Result_Thread *result_thread4; + + // UI控件映射辅助结构 + struct UIPortWidgets { + QTextBrowser *txtb_dispaly; + QLabel *label_runtime_status; + QLineEdit *ledit_spp_addr; + QLabel *label_result_success; + QLabel *label_result_fail; + QComboBox *cbox_uart_com_select; // 串口选择框 + QPushButton *pbtn_spp_reconnect; // 连接按钮 + }; + + // 获取指定端口的UI控件 + UIPortWidgets getUIPortWidgets(int port_index); + + // 统一处理函数(支持多端口) + void readData(int port_index); + void uart_process(int port_index); + void uart_send_data(int port_index, QString cmd); + void handleBytesWritten(int port_index, qint64 bytes); + void spp_timer_callback(int port_index); + void spp_connect(int port_index); + void ui_display(int port_index, QString str, bool inOrOut); + void ui_show_result(int port_index, QString msg, bool success); + void poweroff_watch(int port_index); + + // 向后兼容:保留原有函数名(调用统一函数,port_index=0) void ui_display1(QString str,bool inOrOut); void ui_show_result1(QString msg,bool success); void poweroff_watch1(); + void uart_send_data1(QString cmd); /*----------写地址任务相关变量---end------------*/ @@ -83,16 +110,6 @@ private: // int dongle_try_count {0}; // int spp_try_count {0}; - void uart_send_data1(QString cmd); - - - QSerialPort *serialport2; - QSerialPort *serialport3; - QSerialPort *serialport4; - Result_Thread *result_thread2; - Result_Thread *result_thread3; - Result_Thread *result_thread4; - /* -------------------------UI------------------------------- */ enum ui_page{ @@ -103,6 +120,7 @@ private: void ui_setting_read(); + // 向后兼容:保留原有函数名(调用统一函数) void ui_display2(QString str,bool inOrOut); void ui_display3(QString str,bool inOrOut); void ui_display4(QString str,bool inOrOut); diff --git a/mainwindow.ui b/mainwindow.ui index bbd187a..3d8081f 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -177,33 +177,6 @@ - - false - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - 全部开始写地址 - - - false - - - - - true @@ -222,7 +195,7 @@ - 设置Mac地址 + 全部开始测试 false @@ -241,13 +214,9 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Arial'; font-size:14pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'黑体'; font-size:9pt;">28110601012D 至</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'黑体'; font-size:9pt;">2811060287CD</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'黑体'; font-size:9pt;">共 100000 地址</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'黑体'; font-size:9pt;">截止:2024-11-1</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'黑体'; font-size:9pt;">已成功写入 0 地址</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'黑体'; font-size:9pt;">还剩余 1000 地址</span></p></body></html> +</style></head><body style=" font-family:'Arial','Arial','黑体'; font-size:14pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">已测试xxx设备</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">xxx成功,xxx失败。</p></body></html> @@ -359,7 +328,7 @@ p, li { white-space: pre-wrap; } - 开始写地址 + 开始测试 false @@ -433,7 +402,7 @@ font: 75 18pt "Agra"; - 已停止写地址... + 已停止测试... @@ -497,7 +466,7 @@ font: 75 18pt "Agra"; - false + true @@ -514,7 +483,7 @@ font: 75 18pt "Agra"; - 开始写地址 + 开始测试 false @@ -585,7 +554,7 @@ font: 75 18pt "Agra"; - 已停止写地址... + 已停止测试... @@ -649,7 +618,7 @@ font: 75 18pt "Agra"; - false + true @@ -666,7 +635,7 @@ font: 75 18pt "Agra"; - 开始写地址 + 开始测试 false @@ -737,7 +706,7 @@ font: 75 18pt "Agra"; - 已停止写地址... + 已停止测试... @@ -801,7 +770,7 @@ font: 75 18pt "Agra"; - false + true @@ -818,7 +787,7 @@ font: 75 18pt "Agra"; - 开始写地址 + 开始测试 false @@ -889,7 +858,7 @@ font: 75 18pt "Agra"; - 已停止写地址... + 已停止测试... @@ -984,22 +953,6 @@ font: 75 18pt "Agra"; - - pushButton_open_mac_config - clicked() - MainWindow - ui_open_mac_config() - - - 1192 - 126 - - - 676 - 346 - - - pushButton_openlogfolder clicked() diff --git a/rebuild_fixed.ps1 b/rebuild_fixed.ps1 new file mode 100644 index 0000000..85fef03 --- /dev/null +++ b/rebuild_fixed.ps1 @@ -0,0 +1,46 @@ +# 清理并重新编译项目(已修复链接顺序) + +$BuildDir = "D:\workspace\fd230_source_win\build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug" +$QtDir = "d:\Qt\Qt5.14.2\5.14.2\mingw73_32" +$MingwDir = "D:\Qt\Qt5.14.2\Tools\mingw730_32" +$env:QTDIR = $QtDir +$env:PATH = "$MingwDir\bin;$QtDir\bin;$env:PATH" + +Write-Host "========================================" -ForegroundColor Green +Write-Host "Clean and rebuild project" -ForegroundColor Green +Write-Host "========================================" -ForegroundColor Green +Write-Host "" + +Set-Location $BuildDir + +Write-Host "Step 1: Cleaning old build files..." -ForegroundColor Yellow +& "$MingwDir\bin\mingw32-make.exe" clean *>&1 | Out-Null +if ($LASTEXITCODE -ne 0) { + Write-Host "Warning: Clean failed, continuing..." -ForegroundColor Yellow +} + +Write-Host "" +Write-Host "Step 2: Fixing link order..." -ForegroundColor Yellow +Set-Location "D:\workspace\fd230_source_win\HiBTMacWriteTool" +& powershell -ExecutionPolicy Bypass -File "fix_link_order.ps1" + +Write-Host "" +Write-Host "Step 3: Rebuilding..." -ForegroundColor Yellow +Set-Location $BuildDir +& "$MingwDir\bin\mingw32-make.exe" + +if ($LASTEXITCODE -ne 0) { + Write-Host "" + Write-Host "========================================" -ForegroundColor Red + Write-Host "Build failed!" -ForegroundColor Red + Write-Host "========================================" -ForegroundColor Red + Read-Host "Press Enter to exit" + exit 1 +} + +Write-Host "" +Write-Host "========================================" -ForegroundColor Green +Write-Host "Build successful!" -ForegroundColor Green +Write-Host "========================================" -ForegroundColor Green +Read-Host "Press Enter to exit" + diff --git a/serial_port_context.h b/serial_port_context.h new file mode 100644 index 0000000..0f081a3 --- /dev/null +++ b/serial_port_context.h @@ -0,0 +1,92 @@ +#ifndef SERIAL_PORT_CONTEXT_H +#define SERIAL_PORT_CONTEXT_H + +#include +#include +#include +#include + +// 前向声明 +class QSerialPort; +class QTimer; + +// 串口上下文结构体 - 统一管理每个串口的状态 +struct SerialPortContext { + // 串口对象 + QSerialPort *serialport; + + // 指令相关 + qint64 m_bytesToWrite; // 指令长度 + int cmd_index; // 指令顺序: 0=AT投票, 1=GET_MAC, 2=SET_MAC, 3=GET_MAC验证, 4=GET_CPUID, 5=POWEROFF + QString G_cmd; // 当前执行的AT命令 + + // 状态标志 + bool working_state; // true=写号执行中, false=写号结束 + bool waiting_cmd; // 等待命令时机 + bool startup_complete_detected; // 启动完成信号已检测标志 + bool uart_rx_flag; // 是否有uart通路数据上报 + bool uart_rx_Ignoring_display; // 是否忽略uart数据,不回显 + + // 数据缓冲区 + QByteArray uart_rx_buff_array; // AT命令响应缓冲区 + QByteArray boot_detect_buffer; // 开机检测数据缓存,处理分包情况 + + // 定时器 + QTimer *spp_timer_handle; // AT命令超时定时器 + + // 统计 + int write_success_count; // 成功计数 + int write_fail_count; // 失败计数 + + // UI控件索引(用于区分不同串口的UI显示) + int port_index; // 端口索引: 1, 2, 3, 4 + + // 构造函数 + SerialPortContext(int index) + : serialport(nullptr) + , m_bytesToWrite(0) + , cmd_index(0) + , working_state(false) + , waiting_cmd(false) + , startup_complete_detected(false) + , uart_rx_flag(false) + , uart_rx_Ignoring_display(false) + , spp_timer_handle(nullptr) + , write_success_count(0) + , write_fail_count(0) + , port_index(index) + { + } + + // 初始化函数 + void init(QSerialPort *port, QTimer *timer) { + serialport = port; + spp_timer_handle = timer; + reset(); + } + + // 重置状态 + void reset() { + m_bytesToWrite = 0; + cmd_index = 0; + G_cmd.clear(); + working_state = false; + waiting_cmd = false; + startup_complete_detected = false; + uart_rx_flag = false; + uart_rx_Ignoring_display = false; + uart_rx_buff_array.clear(); + boot_detect_buffer.clear(); + write_success_count = 0; + write_fail_count = 0; + } + + // 清理缓冲区 + void clearBuffers() { + uart_rx_buff_array.clear(); + boot_detect_buffer.clear(); + } +}; + +#endif // SERIAL_PORT_CONTEXT_H + diff --git "a/\345\256\236\347\216\260\346\200\273\347\273\223.md" "b/\345\256\236\347\216\260\346\200\273\347\273\223.md" new file mode 100644 index 0000000..447a94c --- /dev/null +++ "b/\345\256\236\347\216\260\346\200\273\347\273\223.md" @@ -0,0 +1,173 @@ +# AT指令执行路径分析与4线程实现总结 + +## 一、AT指令执行路径分析 + +### 完整执行流程 + +``` +1. spp_connect(port_index) + └─> 打开串口,设置 working_state = true + └─> 初始化状态变量 + +2. readData(port_index) - 持续监听 + ├─> 检测 BOOT_UP_MSG ("yaffs filesystem init start") + │ └─> waiting_cmd = true, cmd_index = 0 + │ └─> 获取可用MAC地址 + │ + ├─> 检测 TIME_FOR_CMD ("bt enable_bt_stack ret") + │ └─> uart_send_data(ATCMD_ADD_VOTE) [cmd_index=0] + │ + ├─> 检测 STARTUP_POST_INIT 和 STARTUP_POST_INIT_TASK + │ └─> startup_complete_detected = true + │ + └─> 接收AT命令响应 + └─> 检测结束标志 (OK~, power off device!, DSP0 power down) + └─> uart_process(port_index) + +3. uart_process(port_index) - 处理AT命令响应 + ├─> case 0: 处理投票指令 + │ └─> cmd_index++ → 1 + │ + ├─> case 1: 解析GET_MAC响应 + │ ├─> 提取MAC地址 + │ ├─> 检查是否已占用 + │ └─> cmd_index++ → 2 + │ + ├─> case 2: 处理SET_MAC完成 + │ └─> cmd_index++ → 3 + │ + ├─> case 3: 验证SET_MAC结果 + │ └─> cmd_index++ → 4 + │ + ├─> case 4: 解析GET_CPUID响应 + │ ├─> 提取CPU ID + │ ├─> 保存到数据库 + │ └─> cmd_index++ → 5 + │ + └─> case 5: 处理关机完成 + └─> cmd_index = -1, 工作完成 + +4. 发送下一个AT命令 (在readData中) + └─> switch(cmd_index) + ├─> case 1: uart_send_data(ATCMD_GET_MAC) + ├─> case 2: uart_send_data(ATCMD_SET_MAC) + ├─> case 3: uart_send_data(ATCMD_GET_MAC) + ├─> case 4: uart_send_data(ATCMD_GET_CPUID) [需等待启动完成] + └─> case 5: uart_send_data(ATCMD_POWEROFF) +``` + +### AT指令列表 + +| 指令 | 定义 | 用途 | 超时 | cmd_index | +|------|------|------|------|-----------| +| ATCMD_ADD_VOTE | `AT^PMADDVOTE\r\n` | 阻止休眠 | 1.5s | 0 | +| ATCMD_GET_MAC | `AT^GETBTMAC\r\n` | 查询MAC | 3s | 1, 3 | +| ATCMD_SET_MAC | `AT^BTADDR=%1 6\r\n` | 设置MAC | 1.5s | 2 | +| ATCMD_GET_CPUID | `AT^GETIDS\r\n` | 获取CPU ID | 5s | 4 | +| ATCMD_POWEROFF | `AT^POWEROFF\r\n` | 关机 | 1.5s | 5 | + +## 二、统一配置设计 + +### 结构体设计 + +已创建 `SerialPortContext` 结构体,统一管理每个串口的状态: + +```cpp +struct SerialPortContext { + QSerialPort *serialport; // 串口对象 + QTimer *spp_timer_handle; // 超时定时器 + int cmd_index; // 当前命令索引 + bool working_state; // 工作状态 + bool waiting_cmd; // 等待命令时机 + bool startup_complete_detected; // 启动完成标志 + bool uart_rx_flag; // 接收标志 + QByteArray uart_rx_buff_array; // 响应缓冲区 + QByteArray boot_detect_buffer; // 开机检测缓存 + QString G_cmd; // 当前命令 + qint64 m_bytesToWrite; // 待发送字节数 + int write_success_count; // 成功计数 + int write_fail_count; // 失败计数 + int port_index; // 端口索引 (1-4) +}; +``` + +### 统一函数设计 + +所有处理函数都接受 `port_index` 参数,使用 `port_contexts[port_index]` 访问对应上下文: + +- `readData(int port_index)` - 统一数据读取 +- `uart_process(int port_index)` - 统一命令处理 +- `uart_send_data(int port_index, QString cmd)` - 统一命令发送 +- `handleBytesWritten(int port_index, qint64 bytes)` - 统一发送完成处理 +- `spp_timer_callback(int port_index)` - 统一超时处理 +- `spp_connect(int port_index)` - 统一连接处理 +- `ui_display(int port_index, QString str, bool inOrOut)` - 统一UI显示 +- `ui_show_result(int port_index, QString msg, bool success)` - 统一结果显示 + +## 三、4线程独立工作实现 + +### 初始化 + +在构造函数中: +```cpp +// 为4个串口创建独立的上下文 +for (int i = 0; i < MAX_SERIAL_PORTS; i++) { + port_contexts[i] = new SerialPortContext(i + 1); + spp_timer_handles[i] = new QTimer(this); + port_contexts[i]->init(ports[i], spp_timer_handles[i]); +} +``` + +### 独立工作 + +每个串口: +- 有独立的上下文 (`port_contexts[i]`) +- 有独立的定时器 (`spp_timer_handles[i]`) +- 有独立的信号槽连接 +- 互不干扰,可以同时工作 + +### 向后兼容 + +保留原有函数名,内部调用统一函数: +```cpp +void MainWindow::readData1() { + readData(0); // 调用统一函数,port_index=0 +} +``` + +## 四、实现状态 + +### ✅ 已完成 +1. 创建 `SerialPortContext` 结构体 +2. 修改 `mainwindow.h`,添加统一配置数组 +3. 修改构造函数,初始化统一配置 +4. 修改析构函数,清理统一配置 +5. 创建分析文档 + +### 🔄 待实现 +1. 实现统一的 `readData(int port_index)` 函数 +2. 实现统一的 `uart_process(int port_index)` 函数 +3. 实现统一的 `uart_send_data(int port_index, QString cmd)` 函数 +4. 实现其他统一处理函数 +5. 实现向后兼容的包装函数 +6. 实现UI控件映射(根据port_index映射到不同UI控件) +7. 测试4个串口的独立工作 + +## 五、下一步工作 + +由于代码量很大(readData1函数有300+行),建议: + +1. **逐步重构**:先实现统一的 `readData` 函数,将 `readData1` 的逻辑提取出来 +2. **测试验证**:每完成一个统一函数,测试确保功能正常 +3. **UI映射**:创建辅助函数,根据 `port_index` 返回对应的UI控件 +4. **完整测试**:实现所有统一函数后,测试4个串口同时工作 + +## 六、优势 + +统一配置后的优势: +1. **代码复用**:4个串口共享同一套处理逻辑 +2. **易于维护**:修改一处,所有串口生效 +3. **易于扩展**:添加新功能只需修改统一函数 +4. **独立工作**:每个串口有独立上下文,互不干扰 +5. **向后兼容**:保留原有函数名,不影响现有代码 + diff --git "a/\347\273\237\344\270\200\351\205\215\347\275\256\345\256\236\347\216\260\346\226\271\346\241\210.md" "b/\347\273\237\344\270\200\351\205\215\347\275\256\345\256\236\347\216\260\346\226\271\346\241\210.md" new file mode 100644 index 0000000..bbe3343 --- /dev/null +++ "b/\347\273\237\344\270\200\351\205\215\347\275\256\345\256\236\347\216\260\346\226\271\346\241\210.md" @@ -0,0 +1,78 @@ +# 统一配置实现方案 + +## 实现步骤 + +### 1. 已完成 +- ✅ 创建 `SerialPortContext` 结构体 +- ✅ 修改 `mainwindow.h`,添加统一配置数组 +- ✅ 修改构造函数,初始化统一配置 +- ✅ 修改析构函数,清理统一配置 + +### 2. 待实现 + +#### 2.1 统一处理函数 +需要创建以下统一函数(接受 `port_index` 参数): +- `void readData(int port_index)` - 统一的数据读取函数 +- `void uart_process(int port_index)` - 统一的AT命令处理函数 +- `void uart_send_data(int port_index, QString cmd)` - 统一的AT命令发送函数 +- `void handleBytesWritten(int port_index, qint64 bytes)` - 统一的发送完成处理 +- `void spp_timer_callback(int port_index)` - 统一的超时处理 +- `void spp_connect(int port_index)` - 统一的串口连接函数 +- `void ui_display(int port_index, QString str, bool inOrOut)` - 统一的UI显示函数 +- `void ui_show_result(int port_index, QString msg, bool success)` - 统一的结果显示函数 +- `void poweroff_watch(int port_index)` - 统一的关机函数 + +#### 2.2 向后兼容函数 +保留原有函数名,内部调用统一函数(port_index=0): +- `readData1()` → `readData(0)` +- `readData2()` → `readData(1)` +- `readData3()` → `readData(2)` +- `readData4()` → `readData(3)` +- 其他函数类似 + +#### 2.3 UI控件映射 +需要根据 `port_index` 映射到不同的UI控件: +- port_index=0: `ui->txtb_dispaly`, `ui->label_runtime_status1`, `ui->ledit_spp_addr_1` 等 +- port_index=1: `ui->txtb_dispaly_2`, `ui->label_runtime_status2`, `ui->ledit_spp_addr_2` 等 +- port_index=2: `ui->txtb_dispaly_3`, `ui->label_runtime_status3`, `ui->ledit_spp_addr_3` 等 +- port_index=3: `ui->txtb_dispaly_4`, `ui->label_runtime_status4`, `ui->ledit_spp_addr_4` 等 + +## 代码重构要点 + +### 变量替换规则 +原代码中的变量需要替换为 `port_contexts[port_index]->xxx`: + +| 原变量 | 新变量 | +|--------|--------| +| `cmd_index_1` | `port_contexts[port_index]->cmd_index` | +| `uart_rx_flag1` | `port_contexts[port_index]->uart_rx_flag` | +| `uart_rx_buff_array1` | `port_contexts[port_index]->uart_rx_buff_array` | +| `boot_detect_buffer` | `port_contexts[port_index]->boot_detect_buffer` | +| `working_state_1` | `port_contexts[port_index]->working_state` | +| `waiting_cmd1` | `port_contexts[port_index]->waiting_cmd` | +| `startup_complete_detected` | `port_contexts[port_index]->startup_complete_detected` | +| `m_bytesToWrite1` | `port_contexts[port_index]->m_bytesToWrite` | +| `G_cmd` | `port_contexts[port_index]->G_cmd` | +| `spp_timer_handle1` | `port_contexts[port_index]->spp_timer_handle` | +| `serialport1` | `port_contexts[port_index]->serialport` | +| `write_success_count1` | `port_contexts[port_index]->write_success_count` | +| `write_fail_count1` | `port_contexts[port_index]->write_fail_count` | + +## 实现建议 + +由于代码量很大,建议分阶段实现: + +1. **第一阶段**:实现统一的 `readData(int port_index)` 函数 +2. **第二阶段**:实现统一的 `uart_process(int port_index)` 函数 +3. **第三阶段**:实现统一的 `uart_send_data(int port_index, QString cmd)` 函数 +4. **第四阶段**:实现其他统一函数 +5. **第五阶段**:修改所有向后兼容函数,调用统一函数 +6. **第六阶段**:测试4个串口的独立工作 + +## 注意事项 + +1. **线程安全**:确保多线程访问串口上下文时使用适当的锁 +2. **UI更新**:UI更新需要在主线程中进行,使用信号槽机制 +3. **错误处理**:每个端口应该有独立的错误处理 +4. **资源管理**:确保每个端口的资源正确释放 +