150 lines
4.9 KiB
C
150 lines
4.9 KiB
C
|
|
#ifndef DRONESCREW_ZMQ_PROTOCOL_H
|
|||
|
|
#define DRONESCREW_ZMQ_PROTOCOL_H
|
|||
|
|
|
|||
|
|
#include <QObject>
|
|||
|
|
#include <QString>
|
|||
|
|
#include <QByteArray>
|
|||
|
|
#include <QJsonObject>
|
|||
|
|
#include <atomic>
|
|||
|
|
#include <functional>
|
|||
|
|
#include <memory>
|
|||
|
|
#include <mutex>
|
|||
|
|
|
|||
|
|
#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<DroneScrewResult()> handler)
|
|||
|
|
{
|
|||
|
|
m_singleDetectionHandler = std::move(handler);
|
|||
|
|
}
|
|||
|
|
void setStartWorkHandler(std::function<int()> handler)
|
|||
|
|
{
|
|||
|
|
m_startWorkHandler = std::move(handler);
|
|||
|
|
}
|
|||
|
|
void setStopWorkHandler(std::function<int()> handler)
|
|||
|
|
{
|
|||
|
|
m_stopWorkHandler = std::move(handler);
|
|||
|
|
}
|
|||
|
|
void setStartLiveStreamHandler(std::function<int()> handler)
|
|||
|
|
{
|
|||
|
|
m_startLiveStreamHandler = std::move(handler);
|
|||
|
|
}
|
|||
|
|
void setStopLiveStreamHandler(std::function<int()> handler)
|
|||
|
|
{
|
|||
|
|
m_stopLiveStreamHandler = std::move(handler);
|
|||
|
|
}
|
|||
|
|
void setSwapCameraRolesHandler(std::function<int()> handler)
|
|||
|
|
{
|
|||
|
|
m_swapCameraRolesHandler = std::move(handler);
|
|||
|
|
}
|
|||
|
|
void setServerInfoProvider(std::function<QJsonObject()> provider)
|
|||
|
|
{
|
|||
|
|
m_serverInfoProvider = std::move(provider);
|
|||
|
|
}
|
|||
|
|
void setCalibrationInfoProvider(std::function<QJsonObject()> 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<bool> 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<DroneScrewResult()> m_singleDetectionHandler;
|
|||
|
|
std::function<int()> m_startWorkHandler;
|
|||
|
|
std::function<int()> m_stopWorkHandler;
|
|||
|
|
std::function<int()> m_startLiveStreamHandler;
|
|||
|
|
std::function<int()> m_stopLiveStreamHandler;
|
|||
|
|
std::function<int()> m_swapCameraRolesHandler;
|
|||
|
|
std::function<QJsonObject()> m_serverInfoProvider;
|
|||
|
|
std::function<QJsonObject()> m_calibrationInfoProvider;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
#endif // DRONESCREW_ZMQ_PROTOCOL_H
|