#ifndef DRONESCREW_ZMQ_PROTOCOL_H #define DRONESCREW_ZMQ_PROTOCOL_H #include #include #include #include #include #include #include #include #include "IVrZeroMQServer.h" #include "IVrZeroMQPubSub.h" #include "Algo/IDroneScrewAlgo.h" #include "IMvsDevice.h" class QUdpSocket; /** * @brief 板一 ZMQ 协议层 * * - REP socket:接收板二的同步控制指令(启停、单次检测、参数调整、获取信息) * - PUB socket:异步发布检测结果,板二订阅显示 * * 协议消息使用 JSON 编码(可在后续替换为 Protobuf)。 * * 控制指令格式: * { "cmd": "start" } * { "cmd": "stop" } * { "cmd": "single" } * { "cmd": "set_exposure", "value": 10000 } * { "cmd": "set_gain", "value": 1.0 } * { "cmd": "set_algo_params", "score": 0.5, "nms": 0.45, "width": 640, "height": 640 } * { "cmd": "swap_cameras" } * { "cmd": "get_info" } * * 应答统一格式: * { "ok": true, "code": 0, "msg": "", ... } * * 结果发布主题: * topic: "result" * payload: { "frameId": .., "ts": .., "boxes": [ {cls,score,x,y,w,h}, ... ] } */ class DroneScrewZmqProtocol : public QObject { Q_OBJECT public: explicit DroneScrewZmqProtocol(QObject* parent = nullptr); ~DroneScrewZmqProtocol() override; /** * @brief 启动 ZMQ 协议层 * @param controlPort REQ-REP 控制端口 * @param resultPort PUB 检测结果端口 (topic="result") * @param rawImagePort PUB 原始图像端口 (topic="raw"),<=0 表示不启用 */ bool startServer(int controlPort, int resultPort, int rawImagePort); void stopServer(); void setRtspUrl(const QString& url) { m_rtspUrl = url; } void setSingleDetectionHandler(std::function handler) { m_singleDetectionHandler = std::move(handler); } void setStartWorkHandler(std::function handler) { m_startWorkHandler = std::move(handler); } void setStopWorkHandler(std::function handler) { m_stopWorkHandler = std::move(handler); } void setFinalDetectionResultProvider(std::function provider) { m_finalDetectionResultProvider = std::move(provider); } void setStartLiveStreamHandler(std::function handler) { m_startLiveStreamHandler = std::move(handler); } void setStopLiveStreamHandler(std::function handler) { m_stopLiveStreamHandler = std::move(handler); } void setSwapCameraRolesHandler(std::function handler) { m_swapCameraRolesHandler = std::move(handler); } void setServerInfoProvider(std::function provider) { m_serverInfoProvider = std::move(provider); } void setCalibrationInfoProvider(std::function provider) { m_calibrationInfoProvider = std::move(provider); } int controlPort() const { return m_controlPort; } int resultPort() const { return m_resultPort; } int rawImagePort() const { return m_rawImagePort; } signals: void rawImagePublishEnabledRequested(bool enabled); void detectModeRequested(const std::string& mode); void setExposureRequested(double exposureTime); void setGainRequested(double gain); void updateAlgoParamsRequested(const DroneScrewAlgoParams& params); public slots: /** * @brief 接收 presenter 信号,封装为 ZMQ 发布(topic="result") */ void publishDetectionResult(const DroneScrewResult& result); /** * @brief 接收 presenter 采集到的双目原始相机帧并以 ZMQ PUB(topic="raw")广播 * * payload = WDRemoteBinocularRawImageHeader(88B) + left raw bytes + right raw bytes */ void publishRawImage(const MvsImageData& left, const MvsImageData& right); private: QByteArray handleControlMessage(const QByteArray& reqData); bool startDiscoveryServer(); void stopDiscoveryServer(); void handleDiscoveryDatagrams(); private: IVrZeroMQServer* m_pZmqServer{nullptr}; IVrZeroMQPublisher* m_pZmqPublisher{nullptr}; // topic="result" IVrZeroMQPublisher* m_pZmqRawPublisher{nullptr}; // topic="raw" QUdpSocket* m_pDiscoverySocket{nullptr}; // UDP broadcast discovery std::atomic m_bRunning{false}; QString m_rtspUrl; int m_controlPort{0}; int m_resultPort{0}; int m_rawImagePort{0}; std::mutex m_pubMutex; std::mutex m_rawMutex; std::mutex m_singleMutex; std::function m_singleDetectionHandler; std::function m_startWorkHandler; std::function m_stopWorkHandler; std::function m_finalDetectionResultProvider; std::function m_startLiveStreamHandler; std::function m_stopLiveStreamHandler; std::function m_swapCameraRolesHandler; std::function m_serverInfoProvider; std::function m_calibrationInfoProvider; }; #endif // DRONESCREW_ZMQ_PROTOCOL_H