#ifndef BASEPRESENTER_H #define BASEPRESENTER_H #include #include #include #include #include #include #include #include #include #include "IVrEyeDevice.h" #include "VZNL_Types.h" #include "VrCommonConfig.h" // 包含公共配置结构体 #include "LaserDataLoader.h" // 激光数据加载器 #include "IVisionApplicationStatus.h" // 工作状态枚举 /** * @brief 基础Presenter类 * * 提取各应用Presenter的共同功能: * - 相机设备管理(InitCamera) * - 算法参数初始化(InitAlgoParams - 纯虚函数) * - 检测线程管理(DetectTask) * - 检测数据缓存 * - 相机重连机制 * * 子类需要实现的纯虚函数: * - InitAlgoParams(): 初始化算法参数 * - ProcessAlgoDetection(): 执行具体的算法检测 * - OpenDevice(): 打开相机设备 * - TryReconnectCameras(): 尝试重连相机 * - OnCameraStatusChanged(): 相机状态变化通知 * * 用法示例: * @code * class GrabBagPresenter : public BasePresenter { * protected: * int InitAlgoParams() override { ... } * int ProcessAlgoDetection() override { ... } * int OpenDevice(int cameraIndex, ...) override { ... } * }; * @endcode */ class BasePresenter : public QObject { Q_OBJECT public: explicit BasePresenter(QObject *parent = nullptr); virtual ~BasePresenter(); /** * @brief 公用的初始化 * @return */ int Init(const std::string& sName); /** * @brief 开始检测 * @param cameraIndex 相机索引(-1表示所有相机) * @param isAuto 是否自动模式 * @return 0: 成功, 其他: 错误码 */ virtual int StartDetection(int cameraIndex = -1, bool isAuto = true); /** * @brief 停止检测 * @return 0: 成功, 其他: 错误码 */ virtual int StopDetection(); /** * @brief 获取相机列表 * @return 相机列表(IP地址和设备指针的pair) */ std::vector> GetCameraList() const { return m_vrEyeDeviceList; } /** * @brief 设置默认相机索引 * @param cameraIndex 相机索引 */ void SetDefaultCameraIndex(int cameraIndex) { m_currentCameraIndex = cameraIndex; } /** * @brief 获取默认相机索引 * @return 相机索引 */ int GetDetectIndex() const { return m_currentCameraIndex; } /** * @brief 获取检测数据缓存大小 * @return 缓存中的数据个数 */ int GetDetectionDataCacheSize() const; /** * @brief 保存当前缓存的检测数据到文件(便捷方法) * * 直接保存内部缓存的数据,无需传入参数 * * @param filePath 文件路径 * @return 0: 成功, 其他: 错误码 */ virtual int SaveDetectionDataToFile(const std::string& filePath); /** * @brief 加载调试数据并执行检测(virtual,子类可重写添加状态更新) * * 从文件加载激光扫描数据到缓存,然后执行算法检测 * * @param filePath 文件路径 * @return 0: 成功, 其他: 错误码 */ virtual int LoadDebugDataAndDetect(const std::string& filePath); /** * @brief 为所有相机设置状态回调 * * 遍历所有相机设备,为每个设备设置状态回调函数 * * @param fNotify 状态回调函数指针 * @param param 回调函数的用户参数 */ void SetCameraStatusCallback(VzNL_OnNotifyStatusCBEx fNotify, void* param); /** * @brief 获取当前工作状态 * @return 当前工作状态 */ WorkStatus GetCurrentWorkStatus() const { return m_currentWorkStatus; } /** * @brief 设置工作状态(会触发状态回调通知) * @param status 新的工作状态 */ void SetWorkStatus(WorkStatus status); /** * @brief 设置状态回调接口(模板方法) * * 存储状态回调接口指针,用于通知UI状态变化 * 子类可以直接调用此方法设置自己的状态回调接口 * * @tparam StatusCallbackType 状态回调接口类型 * @param statusCallback 状态回调接口指针 */ template void SetStatusCallback(StatusCallbackType* statusCallback) { m_pStatusCallback = static_cast(statusCallback); } /** * @brief 获取状态回调接口(模板方法) * * 获取之前设置的状态回调接口指针 * * @tparam StatusCallbackType 状态回调接口类型 * @return 状态回调接口指针 */ template StatusCallbackType* GetStatusCallback() const { return static_cast(m_pStatusCallback); } /** * @brief 通用的静态检测数据回调函数 * * 此静态函数可被所有子类使用,将检测数据添加到缓存 * 子类的 GetDetectionCallback() 可以直接返回此函数 * * @param eDataType 数据类型 * @param pLaserLinePoint 激光线数据指针 * @param pUserData 用户数据(BasePresenter实例指针) */ static void _StaticDetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint, void* pUserData); /** * @brief 通用的静态相机状态回调函数 * * 此静态函数可被所有子类使用,处理相机状态变化 * 子类的 GetCameraStatusCallback() 可以直接返回此函数 * * @param eStatus 相机工作状态 * @param pExtData 扩展数据 * @param nDataLength 数据长度 * @param pInfoParam 参数(BasePresenter实例指针) */ static void _StaticCameraStatusCallback(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam); protected: // ============ 纯虚函数 - 子类必须实现 ============ /** * @brief 私有初始化子类应该重写此方法 * @return 0: 成功, 其他: 错误码 */ virtual int InitApp() = 0; /** * @brief 初始化算法参数(纯虚函数) * * 子类需要在此方法中: * - 加载算法参数配置 * - 初始化算法库 * - 加载标定参数 * * @return 0: 成功, 其他: 错误码 */ virtual int InitAlgoParams() = 0; /** * @brief 执行算法检测(纯虚函数) * * 子类需要在此方法中: * - 使用传入的点云数据进行算法检测 * - 调用具体的算法库进行检测 * - 返回检测结果 * * @param detectionDataCache 检测数据缓存的引用 * @return 0: 成功, 其他: 错误码 */ virtual int ProcessAlgoDetection(std::vector>& detectionDataCache) = 0; /** * @brief 获取相机状态回调函数(虚函数,提供默认实现) * * 默认返回 BasePresenter 的通用静态回调函数 * 子类如果需要自定义相机状态处理,可以重写此方法 * * @return 相机状态回调函数指针 */ virtual VzNL_OnNotifyStatusCBEx GetCameraStatusCallback() { return &BasePresenter::_StaticCameraStatusCallback; } /** * @brief 获取检测数据回调函数(虚函数,提供默认实现) * * 默认返回 BasePresenter 的通用静态回调函数 * 子类如果需要自定义检测数据处理,可以重写此方法 * * @return 检测数据回调函数指针 */ virtual VzNL_AutoOutputLaserLineExCB GetDetectionCallback() { return &BasePresenter::_StaticDetectionCallback; } /** * @brief 获取检测数据类型(纯虚函数) * * 子类需要返回项目使用的数据类型,例如: * - keResultDataType_Position (只要XYZ位置) * - keResultDataType_PointXYZRGBA (需要RGBA颜色) * * @return 数据类型 */ virtual EVzResultDataType GetDetectionDataType() = 0; /** * @brief 尝试重连相机(虚函数,提供默认实现) * * 基类提供通用的重连逻辑: * - 遍历所有配置的相机 * - 检查是否已连接 * - 尝试调用 OpenDevice 重连 * - 调用 OnCameraStatusChanged 通知状态变化 * - 更新相机连接状态和默认相机索引 * * 子类通常不需要重写此方法,除非有特殊的重连逻辑 * * @return true: 所有相机已连接, false: 仍有相机未连接 */ virtual bool TryReconnectCameras(); /** * @brief 相机状态变化通知(纯虚函数) * * @param cameraIndex 相机索引 * @param isConnected 是否连接 */ virtual void OnCameraStatusChanged(int cameraIndex, bool isConnected) = 0; /** * @brief 工作状态变化通知(虚函数,子类可选择重写) * * 当工作状态改变时,BasePresenter 会调用此方法通知子类 * 子类应在此方法中调用状态回调接口的 OnWorkStatusChanged * * @param status 新的工作状态 */ virtual void OnWorkStatusChanged(WorkStatus status) { // 默认空实现,子类可以重写以调用UI回调 } /** * @brief 相机数量变化通知(虚函数,子类可选择重写) * * 当相机初始化时,BasePresenter 会调用此方法通知子类相机数量 * 子类应在此方法中调用状态回调接口的 OnCameraCountChanged * * @param count 相机数量 */ virtual void OnCameraCountChanged(int count) { // 默认空实现,子类可以重写以调用UI回调 } /** * @brief 状态文字更新通知(虚函数,子类可选择重写) * * 当需要更新状态文字时,BasePresenter 会调用此方法 * 子类应在此方法中调用状态回调接口的 OnStatusUpdate * * @param statusMessage 状态消息 */ virtual void OnStatusUpdate(const std::string& statusMessage) { // 默认空实现,子类可以重写以调用UI回调 } // ============ 公共实现方法 ============ /** * @brief 初始化相机设备(公共实现) * * 此方法实现了通用的相机初始化逻辑: * - 保存相机配置 * - 初始化相机列表 * - 调用 OpenDevice 打开每个相机 * - 启动重连定时器(如果需要) * * @param cameraList 相机配置列表 * @return 0: 成功, 其他: 错误码 */ virtual int InitCamera(std::vector& cameraList, bool bRGB, bool bSwing); /** * @brief 清空检测数据缓存(virtual允许子类重写以添加特殊清理逻辑) */ virtual void ClearDetectionDataCache(); /** * @brief 添加检测数据到缓存 * @param dataType 数据类型 * @param laserData 激光数据 */ void AddDetectionDataToCache(EVzResultDataType dataType, const SVzLaserLineData& laserData); /** * @brief 获取检测数据缓存的引用(用于批量加载数据) * * 提供线程安全的方式访问缓存进行批量操作 * 调用者需要在调用此方法的作用域内完成所有操作 * * @param func 操作函数,接收缓存引用作为参数,返回操作结果 * @return func 的返回值 */ template int AccessDetectionDataCache(Func func) { std::lock_guard lock(m_detectionDataMutex); return func(m_detectionDataCache); } private: /** * @brief 打开相机设备(公共实现) * * 此方法实现了通用的相机打开逻辑: * - 创建 IVrEyeDevice 对象 * - 初始化设备 * - 设置状态回调(调用 GetCameraStatusCallback) * - 打开相机(使用 GetOpenDeviceMode) * - 存储到设备列表 * * @param cameraIndex 相机索引(从1开始) * @param cameraName 相机名称 * @param cameraIp 相机IP地址 * @return 0: 成功, 其他: 错误码 */ int OpenDevice(int cameraIndex, const char* cameraName, const char* cameraIp, bool bRGB, bool bSwing); /** * @brief 算法检测线程函数 * * 实现了通用的检测线程循环: * - 等待检测触发 * - 调用 ProcessAlgoDetection 执行算法 * - 处理检测结果 */ void AlgoDetectThreadFunc(); /** * @brief 检测任务主流程 * * 实现了通用的检测任务流程: * - 验证数据缓存 * - 调用 ProcessAlgoDetection 执行算法 * - 更新工作状态 * * @return 0: 成功, 其他: 错误码 */ int DetectTask(); /** * @brief 启动算法检测线程 */ void StartAlgoDetectThread(); /** * @brief 停止算法检测线程 */ void StopAlgoDetectThread(); /** * @brief 启动相机重连定时器 */ void StartCameraReconnectTimer(); /** * @brief 停止相机重连定时器 */ void StopCameraReconnectTimer(); private slots: /** * @brief 相机重连定时器触发 */ void OnCameraReconnectTimer(); protected: // 相机设备列表 std::vector> m_vrEyeDeviceList; // 当前相机索引 int m_currentCameraIndex = 0; // 连接状态标志 bool m_bCameraConnected = false; // 算法检测线程相关 std::atomic m_bAlgoDetectThreadRunning; std::mutex m_algoDetectMutex; std::condition_variable m_algoDetectCondition; std::thread m_algoDetectThread; // 检测数据缓存 std::mutex m_detectionDataMutex; std::vector> m_detectionDataCache; // 激光数据加载器 LaserDataLoader m_dataLoader; // 相机重连定时器 QTimer* m_pCameraReconnectTimer; std::vector m_expectedList; bool m_bRGB{false}; bool m_bSwing{true}; // 工作状态管理 WorkStatus m_currentWorkStatus = WorkStatus::InitIng; // 状态回调接口(使用void*存储,避免模板化整个类) void* m_pStatusCallback = nullptr; }; #endif // BASEPRESENTER_H