#ifndef BAGTHREADPOSITIONPRESENTER_H #define BAGTHREADPOSITIONPRESENTER_H #include #include #include #include #include #include "BasePresenter.h" #include "IVrEyeDevice.h" #include "ConfigManager.h" #include "IVrConfig.h" #include "IYBagThreadPositionStatus.h" #include "SG_baseDataType.h" #include "VrConvert.h" #include "LaserDataLoader.h" #include "CommonDialogCameraLevel.h" // 引入通用对话框的接口 #include "IYModbusTCPClient.h" // ModbusTCP客户端接口 #include #include #include #include #include #include // Forward declarations class DetectPresenter; class BagThreadPositionPresenter : public BasePresenter, public IVrConfigChangeNotify, public ICameraLevelCalculator, public ICameraLevelResultSaver { Q_OBJECT public: explicit BagThreadPositionPresenter(QObject *parent = nullptr); ~BagThreadPositionPresenter(); // 初始化 int InitApp() override; // 反初始化 void DeinitApp(); // 触发检测 bool TriggerDetection(int cameraIndex = -1); // 加载文件并检测 int LoadAndDetect(const QString& fileName); // 重连相机 void ReconnectCamera(); // 获取/设置算法参数 struct AlgoParams { VrThreadParam threadParam; VrCornerParam cornerParam; VrOutlierFilterParam filterParam; VrTreeGrowParam growParam; }; AlgoParams GetAlgoParams() const; void SetAlgoParams(const AlgoParams& params); // 获取配置管理器 ConfigManager* GetConfigManager() { return m_pConfigManager; } // 应用基准距离到指定相机设备 void ApplyBaseDistance(int cameraIndex, double baseDistance); // 应用ModbusTCP配置(IP和大小端) void ApplyModbusConfig(const std::string& ip, bool bigEndian); // 手眼标定矩阵管理 CalibMatrix GetClibMatrix(int index) const; // 面标定辅助函数 SSG_planeCalibPara GetBaseCalibPara(const std::vector>& scanData); // 实现IVrConfigChangeNotify接口 virtual void OnConfigChanged(const ConfigResult& configResult) override; // ============ 实现 ICameraLevelCalculator 接口 ============ /** * @brief 计算平面调平参数 */ bool CalculatePlaneCalibration( const std::vector>& scanData, double planeCalib[9], double& planeHeight, double invRMatrix[9]) override; // ============ 实现 ICameraLevelResultSaver 接口 ============ /** * @brief 保存相机调平结果到配置文件 */ bool SaveLevelingResults(double planeCalib[9], double planeHeight, double invRMatrix[9], int cameraIndex, const QString& cameraName) override; /** * @brief 从配置文件加载相机调平结果 */ bool LoadLevelingResults(int cameraIndex, const QString& cameraName, double planeCalib[9], double& planeHeight, double invRMatrix[9]) override; protected: // ============ 实现 BasePresenter 纯虚函数 ============ /** * @brief 初始化算法参数(实现纯虚函数) */ int InitAlgoParams() override; /** * @brief 执行算法检测(实现纯虚函数) * @param detectionDataCache 检测数据缓存的引用 */ int ProcessAlgoDetection(std::vector>& detectionDataCache) override; /** * @brief 获取检测数据类型(实现纯虚函数) * 包裹拆线位置定位项目只使用Position点云数据 */ EVzResultDataType GetDetectionDataType() override { return keResultDataType_Position; } /** * @brief 相机状态变化通知(实现纯虚函数) */ void OnCameraStatusChanged(int cameraIndex, bool isConnected) override; /** * @brief 工作状态变化通知(重写虚函数) */ void OnWorkStatusChanged(WorkStatus status) override; /** * @brief 相机数量变化通知(重写虚函数) */ void OnCameraCountChanged(int count) override; /** * @brief 状态文字更新通知(重写虚函数) */ void OnStatusUpdate(const std::string& statusMessage) override; /** * @brief ModbusTCP连接状态变化通知(重写虚函数) */ void OnModbusServerStatusChanged(bool isConnected) override; /** * @brief 创建设备对象(重写虚函数) * BagThreadPosition项目使用GlLineLaserDevice */ int CreateDevice(IVrEyeDevice** ppDevice) override; /** * @brief 跳过BasePresenter的ModbusTCP Server启动 * BagThreadPosition使用Client模式主动连接PLC */ bool ShouldStartModbusServer() const override { return false; } private: // 连接状态检查和更新 void CheckAndUpdateWorkStatus(); // 根据相机索引获取调平参数 SSG_planeCalibPara _GetCameraCalibParam(int cameraIndex); // 发送检测结果到ModbusTCP寄存器 void _SendDetectionResultToModbus(const DetectionResult& detectionResult); // Float转寄存器(支持大小端切换) void _FloatToRegisters(float value, uint16_t* regs, bool bigEndian); // ============ ModbusTCP Client 方法 ============ // 初始化ModbusTCP客户端 void InitModbusClient(const std::string& ip, uint16_t port, int pollingInterval); // 关闭ModbusTCP客户端 void ShutdownModbusClient(); // 启动轮询线程 void StartModbusPolling(); // 停止轮询线程 void StopModbusPolling(); // 轮询线程函数 void ModbusPollingThreadFunc(); // 检查连接状态 bool CheckModbusConnection(); // 尝试连接 bool TryConnectModbus(); // 读取扫描请求寄存器 int ReadScanRequest(); // 写入远端PLC多个寄存器 bool WriteRemoteRegisters(uint16_t startAddress, const std::vector& values); // 写入远端PLC单个寄存器 bool WriteRemoteSingleRegister(uint16_t address, uint16_t value); // 检查ModbusTCP客户端是否已连接 bool IsModbusClientConnected() const; private: // BagThreadPositionPresenter 特有的成员变量 ConfigManager* m_pConfigManager = nullptr; // 检测处理器 DetectPresenter* m_pDetectPresenter = nullptr; // 手眼标定矩阵列表(从独立文件加载,暂时保留在Presenter中) std::vector m_clibMatrixList; // ModbusTCP协议相关 DetectionResult m_lastDetectionResult; // 最新的检测结果 std::mutex m_modbusResultMutex; // 保护检测结果的互斥锁 bool m_modbusBigEndian = true; // ModbusTCP大小端配置 // ============ ModbusTCP Client 成员 ============ IYModbusTCPClient* m_modbusClient = nullptr; // Modbus客户端实例 std::string m_modbusClientIP; // 远端PLC IP uint16_t m_modbusClientPort = 502; // 远端PLC端口 int m_modbusPollingInterval = 200; // 轮询间隔(毫秒) std::thread m_modbusPollingThread; // 轮询线程 std::atomic m_modbusPollingRunning{false}; // 轮询线程运行标志 std::atomic m_modbusPollingPaused{false}; // 轮询暂停标志(检测期间暂停) std::atomic m_modbusShutdownRequested{false}; // 关闭请求标志 mutable std::mutex m_modbusClientMutex; // 保护 m_modbusClient bool m_lastScanRequestState = false; // 上次扫描请求状态(边沿检测) bool m_lastModbusConnectedState = false; // 上次连接状态 int m_modbusReconnectAttempts = 0; // 重连次数 int m_modbusReadFailCount = 0; // 连续读取失败次数 static constexpr int MAX_READ_FAIL_COUNT = 3; // 最大连续失败次数,超过则断开重连 }; #endif // BAGTHREADPOSITIONPRESENTER_H