#include "StatorWorkpiecePositionPresenter.h" #include "VrLog.h" #include "VrError.h" #include namespace { QString NumberField(double value) { return QString::number(value, 'f', 3); } QString IntField(int value) { return QString::number(value); } void AppendPoseFields(QStringList& fields, const WorkpiecePosition& position, int poseOutputOrder) { switch (poseOutputOrder) { case POSE_ORDER_RPY: fields << NumberField(position.roll) << NumberField(position.pitch) << NumberField(position.yaw); break; case POSE_ORDER_RYP: fields << NumberField(position.roll) << NumberField(position.yaw) << NumberField(position.pitch); break; case POSE_ORDER_PRY: fields << NumberField(position.pitch) << NumberField(position.roll) << NumberField(position.yaw); break; case POSE_ORDER_PYR: fields << NumberField(position.pitch) << NumberField(position.yaw) << NumberField(position.roll); break; case POSE_ORDER_YRP: fields << NumberField(position.yaw) << NumberField(position.roll) << NumberField(position.pitch); break; case POSE_ORDER_YPR: fields << NumberField(position.yaw) << NumberField(position.pitch) << NumberField(position.roll); break; default: fields << NumberField(position.roll) << NumberField(position.pitch) << NumberField(position.yaw); break; } } } // namespace // 初始化TCP服务器 int StatorWorkpiecePositionPresenter::InitTCPServer() { LOG_DEBUG("Start initializing TCP server\n"); if (m_pTCPServer) { LOG_WARNING("TCP server already initialized\n"); return 0; } // 创建TCP服务器协议实例 m_pTCPServer = new TCPServerProtocol(); // Register callbacks before Initialize() starts the listening thread. // Otherwise an immediate client connection/request can be lost. m_pTCPServer->SetConnectionCallback([this](bool connected) { this->OnTCPConnectionChanged(connected); }); m_pTCPServer->SetDetectionTriggerCallback([this](bool startWork, int cameraIndex, qint64 timestamp) { return this->OnTCPDetectionTrigger(startWork, cameraIndex, timestamp); }); m_pTCPServer->SetBinDetectionTriggerCallback([this](int cameraIndex, qint64 timestamp) { return this->OnTCPBinDetectionTrigger(cameraIndex, timestamp); }); // 从配置获取 TCP/IP 协议端口,默认 7800。 // Modbus TCP Server 端口固定为 5020,不使用此配置项。 int port = 7800; if (m_pConfigManager) { const ConfigResult configResult = m_pConfigManager->GetConfigResult(); const int configuredPort = configResult.plcRobotServerConfig.robotServerPort; if (configuredPort > 0 && configuredPort <= 65535) { port = configuredPort; } } // 初始化TCP服务器 int nRet = m_pTCPServer->Initialize(port); if (nRet != 0) { LOG_ERROR("Failed to initialize TCP server, return code: %d\n", nRet); delete m_pTCPServer; m_pTCPServer = nullptr; return nRet; } LOG_INFO("TCP server protocol initialized successfully on port %d\n", port); return 0; } // TCP连接状态改变回调 void StatorWorkpiecePositionPresenter::OnTCPConnectionChanged(bool connected) { LOG_DEBUG("TCP connection status changed: %s\n", connected ? "connected" : "disconnected"); m_bTCPConnected.store(connected); // 通知状态更新 if (auto pStatus = GetStatusCallback()) { if (connected) { pStatus->OnStatusUpdate("TCP客户端已连接"); } else { pStatus->OnStatusUpdate("TCP客户端已断开"); } // 更新机械臂连接状态 pStatus->OnRobotConnectionChanged(connected); } // 更新工作状态 CheckAndUpdateWorkStatus(); } // TCP检测触发回调 bool StatorWorkpiecePositionPresenter::OnTCPDetectionTrigger(bool startWork, int cameraIndex, qint64 timestamp) { LOG_DEBUG("TCP detection trigger: startWork=%s, cameraIndex=%d, timestamp=%lld\n", startWork ? "true" : "false", cameraIndex, timestamp); // 通知UI接收到TCP扫描请求 if (auto pStatus = GetStatusCallback()) { pStatus->OnStatusUpdate("【TCP协议】接收到工件检测请求"); } if (!startWork) { LOG_WARNING("Received stop work signal, ignoring\n"); return false; } // 检查相机连接状态 if (!m_bCameraConnected) { LOG_ERROR("Camera not connected, cannot start detection\n"); if (auto pStatus = GetStatusCallback()) { pStatus->OnStatusUpdate("【TCP协议】相机未连接,无法启动检测"); } return false; } m_pendingDetectionTask.store(DETECTION_TASK_WORKPIECE); // 启动检测 int result = StartDetection(cameraIndex, false); // false表示手动触发 bool success = (result == 0); if (success) { LOG_DEBUG("Detection started successfully via TCP trigger\n"); if (auto pStatus = GetStatusCallback()) { pStatus->OnStatusUpdate("开始执行扫描检测..."); } } else { LOG_ERROR("Failed to start detection via TCP trigger, error code: %d\n", result); if (auto pStatus = GetStatusCallback()) { pStatus->OnStatusUpdate("检测启动失败"); } } return success; } bool StatorWorkpiecePositionPresenter::OnTCPBinDetectionTrigger(int cameraIndex, qint64 timestamp) { LOG_DEBUG("TCP bin detection trigger: cameraIndex=%d, timestamp=%lld\n", cameraIndex, timestamp); if (auto pStatus = GetStatusCallback()) { pStatus->OnStatusUpdate("【TCP协议】接收到料框检测请求"); } if (!m_bCameraConnected) { if (auto pStatus = GetStatusCallback()) { pStatus->OnStatusUpdate("【TCP协议】相机未连接,无法启动料框检测"); } return false; } m_pendingDetectionTask.store(DETECTION_TASK_BIN); const int result = StartDetection(cameraIndex, false); if (result != SUCCESS) { m_pendingDetectionTask.store(DETECTION_TASK_WORKPIECE); } return result == SUCCESS; } // 发送检测结果给TCP客户端 void StatorWorkpiecePositionPresenter::_SendDetectionResultToTCP(const StatorWorkpiecePositionDetectionResult& detectionResult, int cameraIndex) { if (!m_pTCPServer || !m_bTCPConnected.load()) { LOG_DEBUG("TCP server not available, skipping result transmission\n"); return; } LOG_DEBUG("Sending detection result to TCP clients, camera index: %d\n", cameraIndex); QStringList fields; if (detectionResult.errorCode != SUCCESS || detectionResult.positions.empty()) { fields << "0"; } else { int poseOutputOrder = POSE_ORDER_RPY; if (m_pConfigManager) { poseOutputOrder = m_pConfigManager->GetConfigResult().plcRobotServerConfig.poseOutputOrder; } fields << IntField(static_cast(detectionResult.positions.size())); for (const WorkpiecePosition& position : detectionResult.positions) { fields << IntField(position.workpieceType) << NumberField(position.x) << NumberField(position.y) << NumberField(position.z); AppendPoseFields(fields, position, poseOutputOrder); } } const int sendResult = m_pTCPServer->SendTextFrame(fields.join(QStringLiteral("_")).toUtf8()); if (sendResult == 0) { LOG_INFO("Detection result sent to TCP clients successfully\n"); if (auto pStatus = GetStatusCallback()) { pStatus->OnStatusUpdate("【TCP协议】已发送工件检测结果"); } } else { LOG_ERROR("Failed to send detection result to TCP clients, error code: %d\n", sendResult); } } void StatorWorkpiecePositionPresenter::_SendBinInfoToTCP(const WD_HRM_BinInfo& binInfo, int cameraIndex, int errorCode) { (void)binInfo; (void)cameraIndex; (void)errorCode; LOG_DEBUG("Bin detection has no TCP result frame\n"); } void StatorWorkpiecePositionPresenter::_SendDetectionErrorToTCP(int errorCode, int cameraIndex) { if (!m_pTCPServer || !m_bTCPConnected.load()) { LOG_DEBUG("TCP server not available, skipping detection error transmission\n"); return; } (void)cameraIndex; const QString frame = QString("Error_%1_检测失败").arg(errorCode); const int sendResult = m_pTCPServer->SendTextFrame(frame.toUtf8()); if (sendResult != 0) { LOG_ERROR("Failed to send detection error to TCP clients, error code: %d\n", sendResult); } }