GrabBag/AppUtils/AppCommon/Src/BasePresenter.cpp

710 lines
25 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "BasePresenter.h"
#include "VrLog.h"
#include "VrError.h"
#include <fstream>
#include <QFileInfo>
#include <QString>
#include "PathManager.h"
BasePresenter::BasePresenter(QObject *parent)
: QObject(parent)
, m_currentCameraIndex(0)
, m_bCameraConnected(false)
, m_bAlgoDetectThreadRunning(false)
, m_pCameraReconnectTimer(nullptr)
{
// 创建相机重连定时器
m_pCameraReconnectTimer = new QTimer(this);
m_pCameraReconnectTimer->setInterval(2000); // 默认2秒
connect(m_pCameraReconnectTimer, &QTimer::timeout, this, &BasePresenter::OnCameraReconnectTimer);
}
BasePresenter::~BasePresenter()
{
// 停止检测线程
StopAlgoDetectThread();
// 停止重连定时器
StopCameraReconnectTimer();
// 清理相机设备
for (auto& camera : m_vrEyeDeviceList) {
if (camera.second) {
camera.second->CloseDevice();
delete camera.second;
camera.second = nullptr;
}
}
m_vrEyeDeviceList.clear();
}
int BasePresenter::Init(const std::string &sName)
{
LOG_INFO("BasePresenter::Init()\n");
// 初始化 PathManager 单例
PathManager::Initialize(sName);
int nRet = SUCCESS;
nRet = InitApp();
ERR_CODE_RETURN(nRet);
// 初始化算法参数
nRet = InitAlgoParams();
LOG_INFO("Algorithm parameters initialization result : %d\n", nRet);
return nRet;
}
int BasePresenter::StartDetection(int cameraIndex, bool isAuto)
{
LOG_INFO("[BasePresenter] StartDetection - cameraIndex=%d, isAuto=%d\n", cameraIndex, isAuto);
// 设置当前相机索引
if (cameraIndex >= 0 && cameraIndex != -1) {
m_currentCameraIndex = cameraIndex;
}
int currentCamera = m_currentCameraIndex;
// 检查相机列表是否为空
if (m_vrEyeDeviceList.empty()) {
LOG_ERROR("[BasePresenter] No camera device found\n");
return ERR_CODE(DEV_NOT_FIND);
}
// 清空检测数据缓存
ClearDetectionDataCache();
int nRet = SUCCESS;
// 启动指定相机cameraIndex为相机ID从1开始编号
int arrayIndex = currentCamera - 1; // 转换为数组索引从0开始
// 检查相机是否连接
if (arrayIndex < 0 || arrayIndex >= static_cast<int>(m_vrEyeDeviceList.size()) ||
m_vrEyeDeviceList[arrayIndex].second == nullptr) {
LOG_ERROR("[BasePresenter] Camera %d is not connected or invalid\n", currentCamera);
return ERR_CODE(DEV_NOT_FIND);
}
IVrEyeDevice* pDevice = m_vrEyeDeviceList[arrayIndex].second;
// 获取数据类型(由子类决定)
EVzResultDataType eDataType = GetDetectionDataType();
// 设置状态回调
VzNL_OnNotifyStatusCBEx statusCallback = GetCameraStatusCallback();
pDevice->SetStatusCallback(statusCallback, this);
// 获取检测回调函数(由子类提供)
VzNL_AutoOutputLaserLineExCB detectCallback = GetDetectionCallback();
// 开始检测
nRet = pDevice->StartDetect(detectCallback, eDataType, this);
LOG_INFO("[BasePresenter] Camera %d start detection result: %d\n", currentCamera, nRet);
if (nRet == SUCCESS) {
// 启动算法检测线程
StartAlgoDetectThread();
}
return nRet;
}
int BasePresenter::StopDetection()
{
LOG_INFO("[BasePresenter] StopDetection\n");
// 停止所有相机的检测
for (size_t i = 0; i < m_vrEyeDeviceList.size(); ++i) {
IVrEyeDevice* pDevice = m_vrEyeDeviceList[i].second;
if (pDevice) {
int ret = pDevice->StopDetect();
if (ret == 0) {
LOG_INFO("[BasePresenter] Camera %zu stop detection successfully\n", i + 1);
} else {
LOG_WARNING("[BasePresenter] Camera %zu stop detection failed, error code: %d\n", i + 1, ret);
}
}
}
// 停止算法检测线程
StopAlgoDetectThread();
return SUCCESS;
}
int BasePresenter::GetDetectionDataCacheSize() const
{
std::lock_guard<std::mutex> lock(const_cast<std::mutex&>(m_detectionDataMutex));
return static_cast<int>(m_detectionDataCache.size());
}
int BasePresenter::SaveDetectionDataToFile(const std::string& filePath)
{
LOG_INFO("[BasePresenter] 保存检测数据到文件: %s\n", filePath.c_str());
std::lock_guard<std::mutex> lock(m_detectionDataMutex);
if(m_detectionDataCache.empty()){
LOG_WARNING("[BasePresenter] 检测数据缓存为空,无数据可保存\n");
return ERR_CODE(DATA_ERR_INVALID);
}
int lineNum = static_cast<int>(m_detectionDataCache.size());
float scanSpeed = 0.0f;
int maxTimeStamp = 0;
int clockPerSecond = 0;
int result = m_dataLoader.SaveLaserScanData(filePath, m_detectionDataCache, lineNum, scanSpeed, maxTimeStamp, clockPerSecond);
if (result == SUCCESS) {
LOG_INFO("[BasePresenter] 成功保存 %d 行检测数据到文件: %s\n", lineNum, filePath.c_str());
} else {
LOG_ERROR("[BasePresenter] 保存检测数据失败,错误: %s\n", m_dataLoader.GetLastError().c_str());
}
return result;
}
int BasePresenter::LoadDebugDataAndDetect(const std::string& filePath)
{
LOG_INFO("[BasePresenter] Loading debug data from file: %s\n", filePath.c_str());
std::string fileName = QFileInfo(QString::fromStdString(filePath)).fileName().toStdString();
OnStatusUpdate(QString("加载文件:%1").arg(fileName.c_str()).toStdString());
SetWorkStatus(WorkStatus::Working);
int lineNum = 0;
float scanSpeed = 0.0f;
int maxTimeStamp = 0;
int clockPerSecond = 0;
int result = SUCCESS;
// 1. 清空现有的检测数据缓存
ClearDetectionDataCache();
// 2. 加载数据到缓存
{
std::lock_guard<std::mutex> lock(m_detectionDataMutex);
result = m_dataLoader.LoadLaserScanData(filePath, m_detectionDataCache, lineNum, scanSpeed, maxTimeStamp, clockPerSecond);
}
LOG_DEBUG("\n");
if (result != SUCCESS) {
LOG_ERROR("[BasePresenter] 加载调试数据失败: %s\n", m_dataLoader.GetLastError().c_str());
OnStatusUpdate("调试数据加载失败");
return result;
}
OnStatusUpdate(QString("成功加载 %1 行调试数据").arg(lineNum).toStdString());
LOG_INFO("[BasePresenter] 成功加载 %d 行调试数据\n", lineNum);
// 3. 执行检测任务
result = DetectTask();
return result;
}
void BasePresenter::SetCameraStatusCallback(VzNL_OnNotifyStatusCBEx fNotify, void* param)
{
for (size_t i = 0; i < m_vrEyeDeviceList.size(); i++) {
IVrEyeDevice* pDevice = m_vrEyeDeviceList[i].second;
if (pDevice) {
pDevice->SetStatusCallback(fNotify, param);
LOG_DEBUG("[BasePresenter] Status callback set for camera %zu\n", i + 1);
}
}
}
void BasePresenter::SetWorkStatus(WorkStatus status)
{
if (m_currentWorkStatus != status) {
m_currentWorkStatus = status;
LOG_INFO("[BasePresenter] Work status changed to: %s\n", WorkStatusToString(status).c_str());
// 调用虚函数通知子类子类可以在此调用UI回调
OnWorkStatusChanged(status);
}
}
// ============ InitCamera 完整实现 ============
int BasePresenter::InitCamera(std::vector<DeviceInfo>& cameraList, bool bRGB, bool bSwing)
{
LOG_INFO("[BasePresenter] InitCamera\n");
m_bRGB = bRGB;
m_bSwing = bSwing;
// 保存相机配置信息,用于重连尝试
m_expectedList = cameraList;
// 通知UI相机个数
int cameraCount = cameraList.size();
OnCameraCountChanged(cameraCount);
// 初始化相机列表,预分配空间
m_vrEyeDeviceList.resize(cameraCount, std::make_pair("", nullptr));
for(int i = 0; i < cameraCount; i++)
{
m_vrEyeDeviceList[i] = std::make_pair(cameraList[i].name, nullptr);
}
LOG_INFO("[BasePresenter] camera count : %d\n", cameraCount);
// 尝试初始化所有相机
bool allCamerasConnected = true;
if(cameraCount > 0){
// 循环打开所有配置的相机
for (int i = 0; i < cameraCount; i++) {
int cameraIndex = i + 1; // 相机索引从1开始
int nRet = OpenDevice(cameraIndex, cameraList[i].name.c_str(), cameraList[i].ip.c_str(), bRGB, bSwing);
bool isConnected = (nRet == SUCCESS);
// 通知相机状态变化
OnCameraStatusChanged(cameraIndex, isConnected);
if (!isConnected) {
allCamerasConnected = false;
LOG_WARNING("[BasePresenter] 相机%d (%s) 连接失败\n", cameraIndex, cameraList[i].name.c_str());
} else {
LOG_INFO("[BasePresenter] 相机%d (%s) 连接成功\n", cameraIndex, cameraList[i].name.c_str());
}
}
} else {
// 没有配置相机,创建一个默认项
m_vrEyeDeviceList.resize(1, std::make_pair("", nullptr));
DeviceInfo devInfo;
devInfo.index = 1;
devInfo.ip = "";
devInfo.name = "相机";
m_expectedList.push_back(devInfo);
int nRet = OpenDevice(1, "相机", nullptr, bRGB, bSwing);
if (nRet != SUCCESS) {
allCamerasConnected = false;
}
// 通知相机状态变化
OnCameraStatusChanged(1, SUCCESS == nRet);
}
// 检查连接状态
int connectedCount = 0;
for (const auto& device : m_vrEyeDeviceList) {
if (device.second != nullptr) {
connectedCount++;
}
}
m_bCameraConnected = (connectedCount > 0); // 至少有一个相机连接成功
// 设置默认相机索引为第一个连接的相机
m_currentCameraIndex = 1; // 默认从1开始
for (int i = 0; i < static_cast<int>(m_vrEyeDeviceList.size()); i++) {
if (m_vrEyeDeviceList[i].second != nullptr) {
m_currentCameraIndex = i + 1; // 找到第一个连接的相机
break;
}
}
LOG_INFO("[BasePresenter] 相机初始化完成: %d/%d 台相机连接成功, 默认相机索引: %d\n",
connectedCount, m_expectedList.size(), m_currentCameraIndex);
// 如果不是所有期望的相机都连接成功,启动重连定时器
if (!allCamerasConnected && !m_expectedList.empty()) {
LOG_INFO("[BasePresenter] 部分相机未连接 (%d/%d),启动重连定时器\n", connectedCount, m_expectedList.size());
StartCameraReconnectTimer();
} else if (allCamerasConnected) {
LOG_INFO("[BasePresenter] 所有相机连接成功\n");
// 确保定时器停止
StopCameraReconnectTimer();
} else {
LOG_WARNING("[BasePresenter] 没有配置相机 (expectedCount=%d)\n", m_expectedList.size());
}
return SUCCESS;
}
// ============ OpenDevice 完整实现 ============
int BasePresenter::OpenDevice(int cameraIndex, const char* cameraName, const char* cameraIp, bool bRGB, bool bSwing)
{
LOG_INFO("[BasePresenter] OpenDevice - index %d (%s, %s)\n", cameraIndex, cameraName, cameraIp ? cameraIp : "NULL");
// 1. 创建相机设备对象
IVrEyeDevice* pDevice = nullptr;
IVrEyeDevice::CreateObject(&pDevice);
if (!pDevice) {
LOG_ERROR("[BasePresenter] Failed to create IVrEyeDevice object\n");
return ERR_CODE(DEV_OPEN_ERR);
}
// 2. 初始化设备
int nRet = pDevice->InitDevice();
if(nRet != SUCCESS){
delete pDevice;
LOG_ERROR("[BasePresenter] InitDevice failed, error code: %d\n", nRet);
}
ERR_CODE_RETURN(nRet);
// 3. 打开相机设备
nRet = pDevice->OpenDevice(cameraIp, bRGB, bSwing);
LOG_INFO("[BasePresenter] OpenDevice camera %d (%s/%s) result: %d \n", cameraIndex,
bRGB ? "RGB" : "Normal", bSwing ? "Swing" : "Normal", nRet);
// 4. 处理打开结果
bool cameraConnected = (SUCCESS == nRet);
if(!cameraConnected){
delete pDevice; // 释放失败的设备
pDevice = nullptr;
} else {
// 设置状态回调(调用子类提供的回调函数)
VzNL_OnNotifyStatusCBEx callback = GetCameraStatusCallback();
nRet = pDevice->SetStatusCallback(callback, this);
LOG_DEBUG("[BasePresenter] SetStatusCallback result: %d\n", nRet);
if (nRet != SUCCESS) {
delete pDevice;
pDevice = nullptr;
}
}
LOG_DEBUG("[BasePresenter] Camera %d (%s) connected %s\n", cameraIndex, cameraName, cameraConnected ? "success" : "failed");
// 6. 存储到设备列表
int arrIdx = cameraIndex - 1;
if(m_vrEyeDeviceList.size() > static_cast<size_t>(arrIdx)){
m_vrEyeDeviceList[arrIdx] = std::make_pair(cameraName, pDevice);
} else {
LOG_WARNING("[BasePresenter] Camera index %d out of range, list size: %zu\n", cameraIndex, m_vrEyeDeviceList.size());
}
return nRet;
}
// ============ AlgoDetectThreadFunc 实现 ============
void BasePresenter::AlgoDetectThreadFunc()
{
LOG_INFO("[BasePresenter] 算法检测线程启动\n");
while(m_bAlgoDetectThreadRunning)
{
std::unique_lock<std::mutex> lock(m_algoDetectMutex);
// 等待检测触发(子类需要调用 m_algoDetectCondition.notify_one() 来触发)
m_algoDetectCondition.wait(lock);
if(!m_bAlgoDetectThreadRunning){
break;
}
LOG_INFO("[BasePresenter] 检测线程被唤醒,开始执行检测任务\n");
// 执行检测任务
int nRet = DetectTask();
if(nRet != SUCCESS){
LOG_ERROR("[BasePresenter] 检测任务执行失败,错误码: %d\n", nRet);
} else {
LOG_INFO("[BasePresenter] 检测任务执行成功\n");
}
}
LOG_INFO("[BasePresenter] 算法检测线程退出\n");
}
// ============ DetectTask 实现 ============
int BasePresenter::DetectTask()
{
LOG_INFO("[BasePresenter] DetectTask - 开始执行检测任务\n");
// 1. 验证检测数据缓存
{
std::lock_guard<std::mutex> lock(m_detectionDataMutex);
if (m_detectionDataCache.empty()) {
LOG_WARNING("[BasePresenter] 检测数据缓存为空\n");
return ERR_CODE(DEV_DATA_INVALID);
}
LOG_INFO("[BasePresenter] 检测数据缓存大小: %zu\n", m_detectionDataCache.size());
}
// 2. 调用子类实现的算法检测,传入缓存数据引用
LOG_INFO("[BasePresenter] 调用 ProcessAlgoDetection 执行算法检测\n");
int nRet = ProcessAlgoDetection(m_detectionDataCache);
if (nRet != SUCCESS) {
LOG_ERROR("[BasePresenter] ProcessAlgoDetection 执行失败,错误码: %d\n", nRet);
return nRet;
}
LOG_INFO("[BasePresenter] DetectTask - 检测任务执行成功\n");
return SUCCESS;
}
void BasePresenter::StartAlgoDetectThread()
{
if (m_bAlgoDetectThreadRunning) {
LOG_WARNING("[BasePresenter] 算法检测线程已经在运行\n");
return;
}
m_bAlgoDetectThreadRunning = true;
// 启动检测线程
m_algoDetectThread = std::thread(&BasePresenter::AlgoDetectThreadFunc, this);
m_algoDetectThread.detach(); // 分离线程,让其独立运行
LOG_INFO("[BasePresenter] 算法检测线程已启动\n");
}
void BasePresenter::StopAlgoDetectThread()
{
if (!m_bAlgoDetectThreadRunning) {
return;
}
LOG_INFO("[BasePresenter] 正在停止算法检测线程...\n");
m_bAlgoDetectThreadRunning = false;
// 唤醒可能在等待的线程
m_algoDetectCondition.notify_all();
// 注意:因为线程使用了 detach(),所以不需要 join()
LOG_INFO("[BasePresenter] 算法检测线程已停止\n");
}
void BasePresenter::ClearDetectionDataCache()
{
std::lock_guard<std::mutex> lock(m_detectionDataMutex);
m_detectionDataCache.clear();
LOG_DEBUG("[BasePresenter] 检测数据缓存已清空\n");
}
void BasePresenter::AddDetectionDataToCache(EVzResultDataType dataType, const SVzLaserLineData& laserData)
{
std::lock_guard<std::mutex> lock(m_detectionDataMutex);
m_detectionDataCache.push_back(std::make_pair(dataType, laserData));
}
// 通用的静态检测数据回调函数实现
void BasePresenter::_StaticDetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint, void* pUserData)
{
// 验证输入参数
if (!pLaserLinePoint) {
LOG_WARNING("[BasePresenter Detection Callback] pLaserLinePoint is null\n");
return;
}
if (pLaserLinePoint->nPointCount <= 0) {
LOG_WARNING("[BasePresenter Detection Callback] Point count is zero or negative: %d\n", pLaserLinePoint->nPointCount);
return;
}
if (!pLaserLinePoint->p3DPoint) {
LOG_WARNING("[BasePresenter Detection Callback] p3DPoint is null\n");
return;
}
// 获取 BasePresenter 实例指针
BasePresenter* pThis = reinterpret_cast<BasePresenter*>(pUserData);
if (!pThis) {
LOG_ERROR("[BasePresenter Detection Callback] pUserData is null\n");
return;
}
// 创建 SVzLaserLineData 副本
SVzLaserLineData lineData;
memset(&lineData, 0, sizeof(SVzLaserLineData));
// 根据数据类型分配和复制点云数据
if (eDataType == keResultDataType_Position) {
// 复制 SVzNL3DPosition 数据
if (pLaserLinePoint->p3DPoint && pLaserLinePoint->nPointCount > 0) {
lineData.p3DPoint = new SVzNL3DPosition[pLaserLinePoint->nPointCount];
if (lineData.p3DPoint) {
memcpy(lineData.p3DPoint, pLaserLinePoint->p3DPoint, sizeof(SVzNL3DPosition) * pLaserLinePoint->nPointCount);
}
lineData.p2DPoint = new SVzNL2DPosition[pLaserLinePoint->nPointCount];
if (lineData.p2DPoint) {
memcpy(lineData.p2DPoint, pLaserLinePoint->p2DPoint, sizeof(SVzNL2DPosition) * pLaserLinePoint->nPointCount);
}
}
} else if (eDataType == keResultDataType_PointXYZRGBA) {
// 复制 SVzNLPointXYZRGBA 数据
if (pLaserLinePoint->p3DPoint && pLaserLinePoint->nPointCount > 0) {
lineData.p3DPoint = new SVzNLPointXYZRGBA[pLaserLinePoint->nPointCount];
if (lineData.p3DPoint) {
memcpy(lineData.p3DPoint, pLaserLinePoint->p3DPoint, sizeof(SVzNLPointXYZRGBA) * pLaserLinePoint->nPointCount);
}
lineData.p2DPoint = new SVzNL2DLRPoint[pLaserLinePoint->nPointCount];
if (lineData.p2DPoint) {
memcpy(lineData.p2DPoint, pLaserLinePoint->p2DPoint, sizeof(SVzNL2DLRPoint) * pLaserLinePoint->nPointCount);
}
}
}
// 复制其他字段
lineData.nPointCount = pLaserLinePoint->nPointCount;
lineData.llTimeStamp = pLaserLinePoint->llTimeStamp;
lineData.llFrameIdx = pLaserLinePoint->llFrameIdx;
lineData.nEncodeNo = pLaserLinePoint->nEncodeNo;
lineData.fSwingAngle = pLaserLinePoint->fSwingAngle;
lineData.bEndOnceScan = pLaserLinePoint->bEndOnceScan;
// 添加到检测数据缓存
pThis->AddDetectionDataToCache(eDataType, lineData);
}
// 通用的静态相机状态回调函数实现
void BasePresenter::_StaticCameraStatusCallback(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam)
{
LOG_DEBUG("[BasePresenter Camera Status Callback] received: status=%d\n", (int)eStatus);
// 获取 BasePresenter 实例指针
BasePresenter* pThis = reinterpret_cast<BasePresenter*>(pInfoParam);
if (!pThis) {
LOG_ERROR("[BasePresenter Camera Status Callback] pInfoParam is null\n");
return;
}
switch (eStatus) {
case EVzDeviceWorkStatus::keDeviceWorkStatus_Offline:
{
LOG_WARNING("[BasePresenter Camera Status Callback] Camera device offline/disconnected\n");
// 更新相机连接状态
pThis->m_bCameraConnected = false;
// 通知子类相机状态变更这里暂时通知相机1实际应用中可能需要区分
pThis->OnCameraStatusChanged(1, false);
break;
}
case EVzDeviceWorkStatus::keDeviceWorkStatus_Eye_Reconnect:
{
LOG_INFO("[BasePresenter Camera Status Callback] Camera device online/connected\n");
// 更新相机连接状态
pThis->m_bCameraConnected = true;
// 通知子类相机状态变更
pThis->OnCameraStatusChanged(1, true);
break;
}
case EVzDeviceWorkStatus::keDeviceWorkStatus_Device_Swing_Finish:
{
LOG_INFO("[BasePresenter Camera Status Callback] Received scan finish signal from camera\n");
// 通知算法检测线程开始处理
pThis->m_algoDetectCondition.notify_one();
break;
}
default:
break;
}
}
void BasePresenter::StartCameraReconnectTimer()
{
LOG_DEBUG("[BasePresenter] StartCameraReconnectTimer called\n");
// 使用QMetaObject::invokeMethod确保在正确的线程中操作定时器
QMetaObject::invokeMethod(this, [this]() {
if (!m_pCameraReconnectTimer) {
LOG_ERROR("[BasePresenter] m_pCameraReconnectTimer is nullptr!\n");
return;
}
if (m_pCameraReconnectTimer->isActive()) {
LOG_DEBUG("[BasePresenter] 相机重连定时器已在运行\n");
return;
}
m_pCameraReconnectTimer->start();
LOG_INFO("[BasePresenter] 启动相机重连定时器(间隔: %d ms\n", m_pCameraReconnectTimer->interval());
}, Qt::QueuedConnection);
}
void BasePresenter::StopCameraReconnectTimer()
{
// 使用QMetaObject::invokeMethod确保在正确的线程中操作定时器
QMetaObject::invokeMethod(this, [this]() {
if (m_pCameraReconnectTimer && m_pCameraReconnectTimer->isActive()) {
m_pCameraReconnectTimer->stop();
LOG_INFO("[BasePresenter] 停止相机重连定时器\n");
}
}, Qt::QueuedConnection);
}
// ============ OnCameraReconnectTimer 实现 ============
void BasePresenter::OnCameraReconnectTimer()
{
// 调用子类实现的重连逻辑
bool allConnected = TryReconnectCameras();
if (allConnected) {
LOG_INFO("[BasePresenter] 所有相机重连成功,停止定时器\n");
StopCameraReconnectTimer();
}
}
// ============ TryReconnectCameras 默认实现 ============
bool BasePresenter::TryReconnectCameras()
{
LOG_DEBUG("[BasePresenter] TryReconnectCameras all %zd \n", m_expectedList.size());
bool allConnected = true;
int connectedCount = 0;
// 遍历所有配置的相机,尝试重连失败的相机
for (int i = 0; i < static_cast<int>(m_expectedList.size()); i++) {
// 检查该位置的相机是否已连接
if (i < static_cast<int>(m_vrEyeDeviceList.size()) && m_vrEyeDeviceList[i].second != nullptr) {
// 相机已连接,跳过
connectedCount++;
continue;
}
// 尝试重连相机
int cameraIndex = i + 1; // 相机索引从1开始
const DeviceInfo& cameraInfo = m_expectedList[i];
LOG_DEBUG("[BasePresenter] 尝试重连相机 %d (%s, %s)\n", cameraIndex, cameraInfo.name.c_str(), cameraInfo.ip.c_str());
// 调用 OpenDevice 重连(使用初始化时的 RGB/Swing 参数)
int nRet = OpenDevice(cameraIndex, cameraInfo.name.c_str(), cameraInfo.ip.c_str(), m_bRGB, m_bSwing);
OnCameraStatusChanged(cameraIndex, SUCCESS == nRet);
if (nRet == SUCCESS) {
LOG_INFO("[BasePresenter] 相机 %d (%s) 重连成功\n", cameraIndex, cameraInfo.name.c_str());
connectedCount++;
} else {
LOG_DEBUG("[BasePresenter] 相机 %d (%s) 重连失败,错误码: %d\n", cameraIndex, cameraInfo.name.c_str(), nRet);
allConnected = false;
}
}
// 更新相机连接状态
m_bCameraConnected = (connectedCount > 0);
// 更新默认相机索引为第一个连接的相机
for (int i = 0; i < static_cast<int>(m_vrEyeDeviceList.size()); i++) {
if (m_vrEyeDeviceList[i].second != nullptr) {
m_currentCameraIndex = i + 1;
break;
}
}
LOG_INFO("[BasePresenter] 相机重连尝试完成: %d/%d 台相机已连接\n", connectedCount, m_expectedList.size());
return (connectedCount == m_expectedList.size() && allConnected);
}