#ifndef BINOCULARMARKTCPPROTOCOL_H #define BINOCULARMARKTCPPROTOCOL_H #include #include #include #include #include #include #include #include #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 { MARK_RESULT, // 标记检测结果上报 HEARTBEAT, // 心跳消息 HEARTBEAT_ACK, // 心跳应答 CMD_TRIGGER, // 触发检测命令 CMD_RESPONSE, // 命令应答 UNKNOWN // 未知消息类型 }; /** * @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(); /** * @brief 发送标记检测结果 * @param marks 检测到的3D标记列表 * @param leftImage 左相机图像 * @param rightImage 右相机图像 * @param errorCode 错误码 */ void sendMarkResult(const std::vector& marks, const cv::Mat& leftImage, const cv::Mat& rightImage, int errorCode); signals: /** * @brief 触发检测信号 */ void triggerDetection(); 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& 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 客户端指针 */ 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服务器端口 // 客户端数据缓冲区(用于处理粘包) QMap m_clientBuffers; // 客户端ID -> 数据缓冲区 static BinocularMarkTcpProtocol* s_pInstance; // 静态实例指针 }; #endif // BINOCULARMARKTCPPROTOCOL_H