GrabBag/App/BinocularMark/BinocularMarkApp/BinocularMarkTcpProtocol.h

430 lines
13 KiB
C
Raw Normal View History

2025-12-10 00:01:32 +08:00
#ifndef BINOCULARMARKTCPPROTOCOL_H
#define BINOCULARMARKTCPPROTOCOL_H
#include <QObject>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <QByteArray>
#include <QTimer>
#include <QMap>
#include <opencv2/opencv.hpp>
#include "IYTCPServer.h"
#include "binocularMarkCam_Export.h"
#include "SG_baseDataType.h"
// 帧格式定义
#define FRAME_HEADER "##START#" // 8字节帧头
#define FRAME_TAIL "#END" // 4字节帧尾
#define FRAME_HEADER_SIZE 8
#define FRAME_TAIL_SIZE 4
#define FRAME_LENGTH_SIZE 8 // 数据长度字段64位整数
/**
* @brief
*/
enum class MarkMessageType
{
UNKNOWN, // 未知消息类型
MARK_RESULT, // 标记检测结果上报(持续工作模式)
HEARTBEAT, // 心跳消息
HEARTBEAT_ACK, // 心跳应答
CMD_TRIGGER, // 触发检测命令(已废弃)
CMD_SINGLE_DETECTION, // 单次检测命令返回图像和Mark
SINGLE_DETECTION_RESULT, // 单次检测结果
CMD_SINGLE_IMAGE, // 单次图像命令
IMAGE_DATA, // 图像数据
CMD_START_WORK, // 开始持续工作命令
CMD_STOP_WORK, // 停止持续工作命令
2025-12-20 16:18:12 +08:00
CMD_START_CONTINUOUS_IMAGE, // 开始持续图像流命令
CMD_STOP_CONTINUOUS_IMAGE, // 停止持续图像流命令
CMD_SET_CALIBRATION, // 设置标定矩阵命令
2025-12-20 16:18:12 +08:00
CMD_GET_CALIBRATION, // 获取标定矩阵命令
CMD_SET_EXPOSURE_TIME, // 设置曝光时间命令
CMD_SET_GAIN, // 设置增益命令
2025-12-20 16:18:12 +08:00
CMD_GET_CAMERA_INFO, // 获取相机信息命令
CMD_RESPONSE = 200, // 命令应答
2025-12-10 00:01:32 +08:00
};
/**
* @brief BinocularMark TCP通信协议类
* TCP通信协议
*
*/
class BinocularMarkTcpProtocol : public QObject
{
Q_OBJECT
public:
explicit BinocularMarkTcpProtocol(QObject *parent = nullptr);
~BinocularMarkTcpProtocol();
/**
* @brief TCP服务器
* @param port TCP端口
* @return true-false-
*/
bool startServer(quint16 port);
/**
* @brief TCP服务器
*/
void stopServer();
/**
* @brief
* @param heartbeatInterval 30
*/
void startHeartbeat(int heartbeatInterval = 30);
/**
* @brief
*/
void stopHeartbeat();
2025-12-20 16:18:12 +08:00
signals:
/**
* @brief
*/
void triggerDetection();
/**
* @brief
* @param pClient
*/
void singleDetectionRequested(const TCPClient* pClient);
/**
* @brief
* @param pClient
*/
void singleImageRequested(const TCPClient* pClient);
/**
* @brief
*/
void startWorkRequested();
/**
* @brief
*/
void stopWorkRequested();
/**
* @brief
*/
void startContinuousImageRequested();
/**
* @brief
*/
void stopContinuousImageRequested();
/**
* @brief
* @param exposureTime
*/
void setExposureTimeRequested(double exposureTime);
/**
* @brief
* @param gain
*/
void setGainRequested(double gain);
/**
* @brief
* @param exposureTime
*/
void setLeftExposureTimeRequested(double exposureTime);
/**
* @brief
* @param exposureTime
*/
void setRightExposureTimeRequested(double exposureTime);
/**
* @brief
* @param gain
*/
void setLeftGainRequested(double gain);
/**
* @brief
* @param gain
*/
void setRightGainRequested(double gain);
/**
* @brief
* @param pClient
* @param camera ("left""right")
*/
void getCameraInfoRequested(const TCPClient* pClient, const QString& camera);
/**
* @brief
* @param pClient
*/
void getCalibrationRequested(const TCPClient* pClient);
/**
* @brief
* @param pClient
* @param calibrationXml XML内容
*/
void setCalibrationRequested(const TCPClient* pClient, const QString& calibrationXml);
public slots:
2025-12-10 00:01:32 +08:00
/**
* @brief
2025-12-10 00:01:32 +08:00
* @param marks 3D标记列表
* @param leftImage
* @param rightImage
* @param errorCode
*/
void sendMarkResult(const std::vector<SWD_charuco3DMark>& marks,
const cv::Mat& leftImage,
const cv::Mat& rightImage,
int errorCode);
/**
* @brief Mark
* @param pClient
* @param marks 3D标记列表
* @param leftImage
* @param rightImage
* @param errorCode
*/
void sendSingleDetectionResult(const TCPClient* pClient,
const std::vector<SWD_charuco3DMark>& marks,
const cv::Mat& leftImage,
const cv::Mat& rightImage,
int errorCode);
/**
* @brief
* @param pClient
* @param leftImage
* @param rightImage
*/
void sendImageData(const TCPClient* pClient, const cv::Mat& leftImage, const cv::Mat& rightImage);
/**
2025-12-20 16:18:12 +08:00
* @brief
* @param pClient
* @param camera ("left""right")
* @param serialNumber
* @param modelName
* @param displayName
* @param exposureTime
2025-12-20 16:18:12 +08:00
* @param gain
*/
2025-12-20 16:18:12 +08:00
void sendCameraInfoResponse(const TCPClient* pClient,
const QString& camera,
const QString& serialNumber,
const QString& modelName,
const QString& displayName,
double exposureTime,
double gain);
/**
2025-12-20 16:18:12 +08:00
* @brief
* @param pClient
* @param calibrationXml XML字符串
*/
2025-12-20 16:18:12 +08:00
void sendCalibrationMatrixResponse(const TCPClient* pClient, const QString& calibrationXml);
2025-12-10 00:01:32 +08:00
private slots:
/**
* @brief
*/
void onHeartbeatTimeout();
private:
/**
* @brief TCP服务器接收回调
*/
static void tcpRecvCallback(const TCPClient* pClient, const char* pData, const unsigned int nLen);
/**
* @brief TCP服务器事件回调
*/
static void tcpEventCallback(const TCPClient* pClient, TCPServerEventType eventType);
/**
* @brief
* @param pClient
* @param pData
* @param nLen
*/
void handleReceivedData(const TCPClient* pClient, const char* pData, unsigned int nLen);
/**
* @brief
* @param jsonData JSON数据
* @return +++
*/
QByteArray buildFrame(const QByteArray& jsonData);
/**
* @brief
* @param clientId ID
* @param data
* @param outJsonData JSON数据数组
* @return
*/
int parseFrames(const QString& clientId, const QByteArray& data, QList<QByteArray>& outJsonData);
/**
* @brief
* @param msgTypeStr
* @return
*/
MarkMessageType parseMessageType(const QString& msgTypeStr);
/**
* @brief JSON消息
* @param pClient
* @param jsonData JSON数据
*/
void handleJsonMessage(const TCPClient* pClient, const QByteArray& jsonData);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleHeartbeat(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleTriggerCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleSingleDetectionCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleSingleImageCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleStartWorkCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleStopWorkCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
2025-12-20 16:18:12 +08:00
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleStartContinuousImageCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleStopContinuousImageCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleSetCalibrationCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
2025-12-20 16:18:12 +08:00
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleGetCalibrationCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleSetExposureTimeCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleSetGainCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
2025-12-20 16:18:12 +08:00
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleGetCameraInfoCommand(const TCPClient* pClient, const QJsonObject& jsonObj);
2025-12-10 00:01:32 +08:00
/**
* @brief
* @param pClient
*/
void sendHeartbeatAck(const TCPClient* pClient);
/**
* @brief
* @param pClient
* @param cmdType
* @param result
* @param errorCode
* @param errorMsg
*/
void sendCommandResponse(const TCPClient* pClient, const QString& cmdType,
bool result, int errorCode, const QString& errorMsg);
/**
* @brief Base64
* @param image OpenCV图像
* @return Base64字符串
*/
QString imageToBase64(const cv::Mat& image);
/**
* @brief ID
* @param pClient
* @return ID
*/
QString generateClientId(const TCPClient* pClient);
private:
IYTCPServer* m_pTcpServer; // TCP服务器
QTimer* m_pHeartbeatTimer; // 心跳定时器
int m_nHeartbeatInterval; // 心跳间隔(秒)
quint16 m_nTcpPort; // TCP服务器端口
2025-12-20 16:18:12 +08:00
std::atomic<bool> m_bIsProcessingFrame; // 是否正在处理帧(用于丢帧)
2025-12-10 00:01:32 +08:00
// 客户端数据缓冲区(用于处理粘包)
QMap<QString, QByteArray> m_clientBuffers; // 客户端ID -> 数据缓冲区
static BinocularMarkTcpProtocol* s_pInstance; // 静态实例指针
};
#endif // BINOCULARMARKTCPPROTOCOL_H