2026-03-26 08:30:31 +08:00

243 lines
7.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "TCPServerProtocol.h"
#include "VrLog.h"
#include <QString>
#include <QStringList>
TCPServerProtocol::TCPServerProtocol()
: m_pTCPServer(nullptr)
, m_bServerRunning(false)
, m_nPort(5020)
, m_connectionStatus(CONNECTION_DISCONNECTED)
{
}
TCPServerProtocol::~TCPServerProtocol()
{
Deinitialize();
}
int TCPServerProtocol::Initialize(uint16_t port)
{
LOG_DEBUG("Initializing TCP server protocol on port %d\n", port);
m_nPort = port;
if (!VrCreatYTCPServer(&m_pTCPServer)) {
LOG_ERROR("Failed to create TCP server instance\n");
return -1;
}
if (!m_pTCPServer->Init(port)) {
LOG_ERROR("Failed to initialize TCP server on port %d\n", port);
delete m_pTCPServer;
m_pTCPServer = nullptr;
return -2;
}
m_pTCPServer->SetEventCallback([this](const TCPClient* pClient, TCPServerEventType eventType) {
this->OnTCPEvent(pClient, eventType);
});
if (!m_pTCPServer->Start([this](const TCPClient* pClient, const char* pData, const unsigned int nLen) {
this->OnTCPDataReceived(pClient, pData, nLen);
})) {
LOG_ERROR("Failed to start TCP server\n");
m_pTCPServer->Close();
delete m_pTCPServer;
m_pTCPServer = nullptr;
return -3;
}
m_bServerRunning = true;
m_connectionStatus = CONNECTION_CONNECTED;
LOG_DEBUG("TCP server protocol initialized successfully on port %d\n", port);
return 0;
}
void TCPServerProtocol::Deinitialize()
{
if (m_pTCPServer) {
LOG_DEBUG("Stopping TCP server protocol\n");
m_bServerRunning = false;
m_connectionStatus = CONNECTION_DISCONNECTED;
m_pTCPServer->Stop();
m_pTCPServer->Close();
delete m_pTCPServer;
m_pTCPServer = nullptr;
m_clientBuffers.clear();
LOG_DEBUG("TCP server protocol stopped\n");
}
}
int TCPServerProtocol::SendTextResult(const std::string& text, const TCPClient* pClient)
{
if (!m_pTCPServer || !m_bServerRunning) {
LOG_ERROR("TCP server is not running\n");
return -1;
}
// 添加换行符作为消息分隔
std::string sendData = text + "\n";
bool success = false;
if (pClient) {
success = m_pTCPServer->SendData(pClient, sendData.c_str(), sendData.size());
LOG_DEBUG("Sent text result to specific client, size: %zu bytes\n", sendData.size());
} else {
success = m_pTCPServer->SendAllData(sendData.c_str(), sendData.size());
LOG_DEBUG("Sent text result to all clients, size: %zu bytes\n", sendData.size());
}
if (!success) {
LOG_ERROR("Failed to send text result\n");
return -2;
}
return 0;
}
TCPServerProtocol::TCPStatus TCPServerProtocol::GetConnectionStatus() const
{
return m_connectionStatus;
}
void TCPServerProtocol::SetConnectionCallback(const ConnectionCallback& callback)
{
m_connectionCallback = callback;
}
void TCPServerProtocol::SetDetectionTriggerCallback(const DetectionTriggerCallback& callback)
{
m_detectionTriggerCallback = callback;
}
bool TCPServerProtocol::IsRunning() const
{
return m_bServerRunning;
}
void TCPServerProtocol::OnTCPEvent(const TCPClient* pClient, TCPServerEventType eventType)
{
switch (eventType) {
case TCP_EVENT_CLIENT_CONNECTED:
LOG_DEBUG("TCP client connected: %p\n", pClient);
m_connectionStatus = CONNECTION_CONNECTED;
if (m_connectionCallback) {
m_connectionCallback(true);
}
break;
case TCP_EVENT_CLIENT_DISCONNECTED:
LOG_DEBUG("TCP client disconnected: %p\n", pClient);
// 清理该客户端的缓冲区
m_clientBuffers.erase(pClient);
if (m_connectionCallback) {
m_connectionCallback(false);
}
break;
case TCP_EVENT_CLIENT_EXCEPTION:
LOG_WARNING("TCP client exception: %p\n", pClient);
m_clientBuffers.erase(pClient);
if (m_connectionCallback) {
m_connectionCallback(false);
}
break;
}
}
void TCPServerProtocol::OnTCPDataReceived(const TCPClient* pClient, const char* pData, unsigned int nLen)
{
if (!pData || nLen == 0) {
LOG_WARNING("Received empty data from client %p\n", pClient);
return;
}
LOG_DEBUG("Received TCP data from client %p, size: %u bytes\n", pClient, nLen);
// 追加数据到该客户端的缓冲区
m_clientBuffers[pClient].append(pData, nLen);
// 按换行符分割完整行
QByteArray& buffer = m_clientBuffers[pClient];
while (true) {
int idx = buffer.indexOf('\n');
if (idx < 0) break;
QByteArray line = buffer.left(idx).trimmed();
buffer.remove(0, idx + 1);
if (!line.isEmpty()) {
ParseTextCommand(pClient, line);
}
}
}
void TCPServerProtocol::ParseTextCommand(const TCPClient* pClient, const QByteArray& line)
{
// 协议格式X1 RbtX-23.45 RbtY-23.45 RbtZ-23.45 RbtRoll-23.45 RbtPitch-123.45 RbtYaw-23.45
QString strLine = QString::fromUtf8(line);
QStringList tokens = strLine.split(' ', QString::SkipEmptyParts);
LOG_DEBUG("ParseTextCommand: line='%s', tokens=%d\n", strLine.toStdString().c_str(), tokens.size());
if (tokens.size() < 7) {
LOG_ERROR("Invalid command format, expected 7 tokens, got %d: %s\n",
tokens.size(), strLine.toStdString().c_str());
return;
}
// 解析相机索引X1 或 X2
QString cameraToken = tokens[0];
if (!cameraToken.startsWith('X') && !cameraToken.startsWith('x')) {
LOG_ERROR("Invalid camera token: %s\n", cameraToken.toStdString().c_str());
return;
}
int cameraIndex = cameraToken.mid(1).toInt();
if (cameraIndex < 1 || cameraIndex > 2) {
LOG_ERROR("Invalid camera index: %d\n", cameraIndex);
return;
}
// 解析机器人法兰位姿
// 每个 token 格式为 "RbtX-23.45",前缀为 RbtX/RbtY/RbtZ/RbtRoll/RbtPitch/RbtYaw
RobotFlangePose robotPose;
const QString prefixes[] = {"RbtX", "RbtY", "RbtZ", "RbtRoll", "RbtPitch", "RbtYaw"};
double* values[] = {&robotPose.x, &robotPose.y, &robotPose.z,
&robotPose.roll, &robotPose.pitch, &robotPose.yaw};
for (int i = 0; i < 6; i++) {
QString token = tokens[i + 1];
if (!token.startsWith(prefixes[i])) {
LOG_ERROR("Invalid token prefix at position %d: expected '%s', got '%s'\n",
i + 1, prefixes[i].toStdString().c_str(), token.toStdString().c_str());
return;
}
QString valueStr = token.mid(prefixes[i].length());
bool ok = false;
double val = valueStr.toDouble(&ok);
if (!ok) {
LOG_ERROR("Invalid numeric value at position %d: '%s'\n",
i + 1, valueStr.toStdString().c_str());
return;
}
*values[i] = val;
}
LOG_INFO("Parsed trigger: camera=%d, pose=(%.3f, %.3f, %.3f, %.3f, %.3f, %.3f)\n",
cameraIndex, robotPose.x, robotPose.y, robotPose.z,
robotPose.roll, robotPose.pitch, robotPose.yaw);
// 触发检测回调
if (m_detectionTriggerCallback) {
m_detectionTriggerCallback(cameraIndex, robotPose);
} else {
LOG_WARNING("Detection trigger callback not set\n");
}
}