88 lines
2.9 KiB
C
88 lines
2.9 KiB
C
|
|
#ifndef RODWELDSEAMTCPPROTOCOL_H
|
|||
|
|
#define RODWELDSEAMTCPPROTOCOL_H
|
|||
|
|
|
|||
|
|
#include <atomic>
|
|||
|
|
#include <cstddef>
|
|||
|
|
#include <cstdint>
|
|||
|
|
#include <functional>
|
|||
|
|
#include <map>
|
|||
|
|
#include <mutex>
|
|||
|
|
#include <set>
|
|||
|
|
#include <string>
|
|||
|
|
|
|||
|
|
#include <QByteArray>
|
|||
|
|
|
|||
|
|
#include "IYTCPServer.h"
|
|||
|
|
#include "RobotPose6D.h"
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 钢筋焊缝定位文本 TCP 协议服务端。
|
|||
|
|
*
|
|||
|
|
* 请求格式:W{camera}_X_Y_Z_A_B_C\r\n
|
|||
|
|
*
|
|||
|
|
* 协议层只负责报文收发和解析,不依赖 Presenter 或检测结果类型。检测完成后,
|
|||
|
|
* 上层通过 SendTextResult() 传入不含行结束符的结果正文,协议层追加 CRLF 并
|
|||
|
|
* 广播给当前所有客户端。
|
|||
|
|
*/
|
|||
|
|
class RodWeldSeamTCPProtocol
|
|||
|
|
{
|
|||
|
|
public:
|
|||
|
|
using ConnectionCallback = std::function<void(bool connected)>;
|
|||
|
|
using DetectionTriggerCallback = std::function<bool(int cameraIndex,
|
|||
|
|
const RobotPose6D& robotPose)>;
|
|||
|
|
|
|||
|
|
RodWeldSeamTCPProtocol();
|
|||
|
|
~RodWeldSeamTCPProtocol();
|
|||
|
|
|
|||
|
|
RodWeldSeamTCPProtocol(const RodWeldSeamTCPProtocol&) = delete;
|
|||
|
|
RodWeldSeamTCPProtocol& operator=(const RodWeldSeamTCPProtocol&) = delete;
|
|||
|
|
|
|||
|
|
int Initialize(uint16_t port = 7800);
|
|||
|
|
void Deinitialize();
|
|||
|
|
|
|||
|
|
bool IsRunning() const;
|
|||
|
|
std::size_t ClientCount() const;
|
|||
|
|
|
|||
|
|
void SetConnectionCallback(const ConnectionCallback& callback);
|
|||
|
|
void SetDetectionTriggerCallback(const DetectionTriggerCallback& callback);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 广播已格式化的结果正文。
|
|||
|
|
* @param text 不含 CR/LF 行结束符的结果正文。
|
|||
|
|
* @return 0=成功,-1=服务未运行,-2=发送失败。
|
|||
|
|
*/
|
|||
|
|
int SendTextResult(const std::string& text);
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
static constexpr std::size_t kMaxClientBufferBytes = 64U * 1024U;
|
|||
|
|
|
|||
|
|
void OnTCPEvent(const TCPClient* client, TCPServerEventType eventType);
|
|||
|
|
void OnTCPDataReceived(const TCPClient* client, const char* data, unsigned int length);
|
|||
|
|
void ParseTextCommand(const TCPClient* client, const QByteArray& line);
|
|||
|
|
|
|||
|
|
int SendTextToClient(const TCPClient* client, const std::string& text);
|
|||
|
|
void NotifyConnectionChanged(bool connected);
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
// Initialize/Deinitialize 可能由配置更新和析构路径分别调用,需串行化生命周期。
|
|||
|
|
mutable std::mutex m_lifecycleMutex;
|
|||
|
|
// 保护服务指针以及发送操作;停止服务前先把 running 置为 false,避免发送/释放竞争。
|
|||
|
|
mutable std::mutex m_sendMutex;
|
|||
|
|
// TCP 底层可能从多个工作线程回调,不同客户端的缓存和集合共用此锁。
|
|||
|
|
mutable std::mutex m_clientMutex;
|
|||
|
|
mutable std::mutex m_callbackMutex;
|
|||
|
|
|
|||
|
|
IYTCPServer* m_tcpServer = nullptr;
|
|||
|
|
std::atomic<bool> m_serverRunning{false};
|
|||
|
|
std::atomic<std::size_t> m_clientCount{0};
|
|||
|
|
uint16_t m_port = 7800;
|
|||
|
|
|
|||
|
|
std::map<const TCPClient*, QByteArray> m_clientBuffers;
|
|||
|
|
std::set<const TCPClient*> m_clients;
|
|||
|
|
|
|||
|
|
ConnectionCallback m_connectionCallback;
|
|||
|
|
DetectionTriggerCallback m_detectionTriggerCallback;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
#endif // RODWELDSEAMTCPPROTOCOL_H
|