diff --git a/App/WheelMeasure/WheelMeasureApp/Presenter/Inc/WheelMeasurePresenter.h b/App/WheelMeasure/WheelMeasureApp/Presenter/Inc/WheelMeasurePresenter.h index 24dca867..c94a7d94 100644 --- a/App/WheelMeasure/WheelMeasureApp/Presenter/Inc/WheelMeasurePresenter.h +++ b/App/WheelMeasure/WheelMeasureApp/Presenter/Inc/WheelMeasurePresenter.h @@ -180,6 +180,9 @@ private: // TCP检测触发回调 bool onTCPDetectionTriggered(int param); + // 启动下一个待扫描相机(TCP顺序循环) + void startNextTCPCamera(); + // 发送TCP测量结果 void sendTCPMeasureResults(); @@ -187,12 +190,13 @@ private: IVrWheelMeasureConfig* m_config = nullptr; WheelMeasureConfigResult m_configResult; IWheelMeasureStatus* m_statusUpdate = nullptr; - int m_currentCameraIndex = 1; // 默认相机索引(1-based) // TCP协议 WheelMeasureTCPProtocol m_tcpProtocol; // TCP服务器协议 bool m_tcpDetectionMode = false; // 是否为TCP触发的检测 QMap m_tcpResults; // TCP检测结果缓存 + std::vector m_tcpScanList; // TCP模式下待扫描的相机列表(1-based) + size_t m_tcpScanIndex = 0; // TCP模式下当前扫描索引 }; #endif // WHEELMEASUREPRESENTER_H diff --git a/App/WheelMeasure/WheelMeasureApp/Presenter/Src/WheelMeasurePresenter.cpp b/App/WheelMeasure/WheelMeasureApp/Presenter/Src/WheelMeasurePresenter.cpp index be674297..34d2f709 100644 --- a/App/WheelMeasure/WheelMeasureApp/Presenter/Src/WheelMeasurePresenter.cpp +++ b/App/WheelMeasure/WheelMeasureApp/Presenter/Src/WheelMeasurePresenter.cpp @@ -54,6 +54,9 @@ int WheelMeasurePresenter::InitApp() SetWorkStatus(WorkStatus::InitIng); + // 默认相机索引初始化为1(1-based) + m_currentCameraIndex = 1; + // 加载配置 QString configPath = PathManager::GetInstance().GetConfigFilePath(); if (!initializeConfig(configPath)) { @@ -171,9 +174,22 @@ void WheelMeasurePresenter::OnWorkStatusChanged(WorkStatus status) } }, Qt::QueuedConnection); - // TCP模式下检测完成,发送所有结果 + // TCP模式下检测完成:顺序模式推进下一个相机,批处理模式直接发送结果 if (status == WorkStatus::Completed && m_tcpDetectionMode) { - LOG_INFO("TCP模式:所有相机检测完成,准备发送结果\n"); + if (!m_tcpScanList.empty()) { + // 顺序模式:推进到下一个相机 + m_tcpScanIndex++; + if (m_tcpScanIndex < m_tcpScanList.size()) { + LOG_INFO("TCP模式:当前相机扫描完成,启动下一个相机 (%zu/%zu)\n", + m_tcpScanIndex + 1, m_tcpScanList.size()); + QMetaObject::invokeMethod(this, [this]() { + startNextTCPCamera(); + }, Qt::QueuedConnection); + return; + } + } + // 顺序模式末尾 或 批处理模式所有批次完成 + LOG_INFO("TCP模式:所有相机扫描完成,准备发送结果\n"); QMetaObject::invokeMethod(this, [this]() { sendTCPMeasureResults(); }, Qt::QueuedConnection); @@ -923,15 +939,75 @@ bool WheelMeasurePresenter::onTCPDetectionTriggered(int param) // 清空之前的TCP结果缓存 m_tcpResults.clear(); m_tcpDetectionMode = true; + m_tcpScanList.clear(); + m_tcpScanIndex = 0; - // 启动所有相机的顺序检测 + // 统计启用的相机数量 + int enabledCount = 0; + for (const auto& cameraConfig : m_configResult.cameras) { + if (cameraConfig.enabled) ++enabledCount; + } + if (enabledCount == 0) { + LOG_WARNING("TCP检测触发:无启用的相机,无法启动检测\n"); + m_tcpDetectionMode = false; + return false; + } + + // 清空之前的测量结果显示 QMetaObject::invokeMethod(this, [this]() { - StartAllDetection(); + if (m_statusUpdate) { + m_statusUpdate->OnClearMeasureData(); + m_statusUpdate->OnStatusUpdate(QString("TCP触发:开始检测所有设备")); + } }, Qt::QueuedConnection); + int simCount = m_configResult.scanConfig.simultaneousCount; + + if (simCount == 1) { + // 顺序模式:应用层逐个调度相机(每次 StartDetection(具体索引) 走 branch 1) + for (int idx = 1; idx <= enabledCount; ++idx) { + m_tcpScanList.push_back(idx); + } + LOG_INFO("TCP检测顺序启动 %d 个相机 (simultaneousCount=1)\n", enabledCount); + QMetaObject::invokeMethod(this, [this]() { + startNextTCPCamera(); + }, Qt::QueuedConnection); + } else { + // 批处理模式:StartDetection(-1) 委托 BasePresenter 自动分批扫描所有相机 + // - simultaneousCount=0: 所有相机同时扫描 + // - simultaneousCount>1: 每批 N 个相机同时扫描 + LOG_INFO("TCP检测批处理启动 (simultaneousCount=%d, 启用相机=%d)\n", simCount, enabledCount); + QMetaObject::invokeMethod(this, [this]() { + StartDetection(-1); + }, Qt::QueuedConnection); + } + return true; } +void WheelMeasurePresenter::startNextTCPCamera() +{ + if (m_tcpScanIndex >= m_tcpScanList.size()) { + LOG_WARNING("startNextTCPCamera: 索引越界,直接发送结果\n"); + sendTCPMeasureResults(); + return; + } + + int cameraIdx = m_tcpScanList[m_tcpScanIndex]; + LOG_INFO("TCP扫描: 启动相机 %d (%zu/%zu)\n", + cameraIdx, m_tcpScanIndex + 1, m_tcpScanList.size()); + + if (m_statusUpdate) { + m_statusUpdate->OnStatusUpdate(QString("TCP扫描相机 %1 (%2/%3)") + .arg(cameraIdx) + .arg(m_tcpScanIndex + 1) + .arg(m_tcpScanList.size())); + } + + // 调用 BasePresenter::StartDetection 指定相机扫描(branch 1: 单相机模式) + StartDetection(cameraIdx); +} + void WheelMeasurePresenter::sendTCPMeasureResults() { // 计算期望的相机数量 @@ -970,4 +1046,6 @@ void WheelMeasurePresenter::sendTCPMeasureResults() // 清空缓存和标志 m_tcpResults.clear(); m_tcpDetectionMode = false; + m_tcpScanList.clear(); + m_tcpScanIndex = 0; } diff --git a/App/WheelMeasure/WheelMeasureApp/Version.h b/App/WheelMeasure/WheelMeasureApp/Version.h index ae74c0cd..0c8459bc 100644 --- a/App/WheelMeasure/WheelMeasureApp/Version.h +++ b/App/WheelMeasure/WheelMeasureApp/Version.h @@ -3,7 +3,7 @@ #define WHEELMEASURE_APP_NAME "轮眉高度测量" -#define WHEELMEASURE_VERSION_STRING "1.1.6" +#define WHEELMEASURE_VERSION_STRING "1.2.0" #define WHEELMEASURE_BUILD_STRING "1" #define WHEELMEASURE_FULL_VERSION_STRING "V" WHEELMEASURE_VERSION_STRING "_" WHEELMEASURE_BUILD_STRING diff --git a/App/WheelMeasure/WheelMeasureApp/Version.md b/App/WheelMeasure/WheelMeasureApp/Version.md index 0f24187e..f7956f68 100644 --- a/App/WheelMeasure/WheelMeasureApp/Version.md +++ b/App/WheelMeasure/WheelMeasureApp/Version.md @@ -1,3 +1,7 @@ +# 1.2.0 +## build_1 2026-05-17 +1. 多相机并行扫描 + # 1.1.6 ## build_1 2026-04-25 1. 优化存储数据 diff --git a/AppUtils/AppCommon/Inc/BasePresenter.h b/AppUtils/AppCommon/Inc/BasePresenter.h index 288c1b63..c3b611a8 100644 --- a/AppUtils/AppCommon/Inc/BasePresenter.h +++ b/AppUtils/AppCommon/Inc/BasePresenter.h @@ -661,7 +661,7 @@ protected: int m_batchStartIndex = 0; // 当前批次起始位置 int m_batchSize = 0; // 当前批次相机数 int m_batchFinishedCount = 0; // 当前批次已完成计数 - bool m_batchInProgress = false; // 是否正在分批扫描 + std::atomic m_batchInProgress{false}; // 是否正在分批扫描(决定数据/状态回调的分流路径) std::mutex m_batchStateMutex; // 保护分批调度状态 private: diff --git a/AppUtils/AppCommon/Src/BasePresenter.cpp b/AppUtils/AppCommon/Src/BasePresenter.cpp index ad21be3b..0a1ad920 100644 --- a/AppUtils/AppCommon/Src/BasePresenter.cpp +++ b/AppUtils/AppCommon/Src/BasePresenter.cpp @@ -196,7 +196,7 @@ int BasePresenter::StartDetection(int cameraIndex, bool isAuto) LOG_INFO("[BasePresenter] 进入多相机分批扫描模式\n"); // 停止当前正在进行的检测 - if (m_batchInProgress || m_bAlgoDetectThreadRunning) { + if (m_batchInProgress.load() || m_bAlgoDetectThreadRunning) { StopDetection(); } @@ -566,7 +566,7 @@ void BasePresenter::AlgoDetectThreadFunc() break; } - if (m_scanConfig.simultaneousCount > 1 || m_scanConfig.simultaneousCount == 0) { + if (m_batchInProgress.load()) { // 多相机分批模式:检查批次是否完成并处理 ProcessBatchIfReady(); } else { @@ -657,7 +657,7 @@ int BasePresenter::DetectTask() // 批量模式下不在这里设置Completed,由ProcessBatchIfReady统一设置 { std::lock_guard lock(m_batchStateMutex); - if (!m_batchInProgress) { + if (!m_batchInProgress.load()) { SetWorkStatus(WorkStatus::Completed); } } @@ -800,8 +800,8 @@ void BasePresenter::_StaticDetectionCallback(EVzResultDataType eDataType, SVzLas lineData.bEndOnceScan = pLaserLinePoint->bEndOnceScan; // 根据扫描模式分流存储 - if (pThis->m_scanConfig.simultaneousCount > 1 || pThis->m_scanConfig.simultaneousCount == 0) { - // 多相机同时扫描模式:存入该相机的独立缓存 + if (pThis->m_batchInProgress.load()) { + // 多相机分批扫描模式:存入该相机的独立缓存 pThis->AddDetectionDataToCameraCache(cameraIndex, eDataType, lineData); } else { // 单相机模式:存入共享缓存 @@ -846,8 +846,8 @@ void BasePresenter::_StaticCameraStatusCallback(EVzDeviceWorkStatus eStatus, voi { LOG_INFO("[BasePresenter Camera Status Callback] Camera %d scan finished\n", cameraIndex); - // 多相机模式下记录批次完成 - if (pThis->m_scanConfig.simultaneousCount > 1 || pThis->m_scanConfig.simultaneousCount == 0) { + // 分批模式下记录批次完成 + if (pThis->m_batchInProgress.load()) { pThis->OnCameraScanFinished(cameraIndex); } @@ -1131,7 +1131,7 @@ void BasePresenter::ProcessBatchIfReady() bool batchComplete = false; { std::lock_guard lock(m_batchStateMutex); - if (!m_batchInProgress) return; + if (!m_batchInProgress.load()) return; batchComplete = (m_batchFinishedCount >= m_batchSize); }