TcpListenerService.cs 12.8 KB
using HHECS.BllModel;
using HHECS.RobotTool.Common;
using HHECS.RobotTool.Dto;
using HHECS.RobotTool.Dto.WeldMonitor;
using HHECS.RobotTool.Utils;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Xml.Serialization;

namespace HHECS.RobotTool.Service
{
    public class TcpListenerService
    {
        private TcpListener _tcpServer = null!;
        private readonly SystemLog _logger = SystemLog.GetInstance();
        private readonly GrooveService _grooveService;

        public event Action<WeldMonitorModel>? WeldMonitor;

        public TcpListenerService(GrooveService grooveService)
        {
            _grooveService = grooveService;
        }

        public BllResult Start(int port = 59152)
        {
            try
            {
                _tcpServer = new TcpListener(IPAddress.Any, port);
                _tcpServer.Start();
                _tcpServer.BeginAcceptTcpClient(DoAcceptTcpClient, _tcpServer);
                return BllResultFactory.Success();
            }
            catch (Exception ex)
            {
                return BllResultFactory.Error(ex.Message);
            }
        }

        private void DoAcceptTcpClient(IAsyncResult ar)
        {
            try
            {
                var server = (TcpListener)ar.AsyncState!;
                var tcpClient = server.EndAcceptTcpClient(ar);
                _logger.LogInfo($"[客户端[{tcpClient.Client.RemoteEndPoint}]已成功建立连接");
                Receive(tcpClient);
                server.BeginAcceptTcpClient(DoAcceptTcpClient, server);
            }
            catch (Exception ex)
            {
                _logger.LogError($"[TcpServer]异常:{ex.Message}");
            }
        }

        private void Receive(TcpClient tcpClient)
        {
            Task.Run(() =>
            {
                var remoteEndPoint = tcpClient.Client.RemoteEndPoint;
                while (tcpClient.Connected)
                {
                    try
                    {
                        var buffer = new byte[8192];
                        var stream = tcpClient.GetStream();
                        //接收客户端数据
                        stream.Read(buffer, 0, buffer.Length);
                        var bufferString = Encoding.Default.GetString(buffer).TrimEnd('\0');

                        //无数据则跳过
                        if (string.IsNullOrWhiteSpace(bufferString))
                        {
                            continue;
                        }

                        _logger.LogInfo($"接收到客户端[{remoteEndPoint}]报文:{bufferString}");

                        const string kukaAckFlag1 = "<Robot>";
                        const string kukaAckFlag2 = "</Robot>";
                        //库卡机器人
                        if (bufferString.StartsWith(kukaAckFlag1, StringComparison.OrdinalIgnoreCase)
                        && bufferString.EndsWith(kukaAckFlag2, StringComparison.OrdinalIgnoreCase))
                        {
                            var kukaHandleResult = KukaTcpHandle(bufferString, stream, remoteEndPoint);
                            if (!kukaHandleResult.Success)
                            {
                                _logger.LogError($"响应客户端[{remoteEndPoint}]请求失败:{kukaHandleResult.Msg}");
                                continue;
                            }
                            _logger.LogSuccess($"响应客户端[{remoteEndPoint}]请求成功");
                            continue;
                        }

                        //Fanuc机器人
                        if (bufferString.Split(',').Length == 5)
                        {
                            var fanucHandleResult = FanucTcpHandle(bufferString, stream, remoteEndPoint);
                            if (!fanucHandleResult.Success)
                            {
                                _logger.LogError($"响应客户端[{remoteEndPoint}]请求失败:{fanucHandleResult.Msg}");
                                continue;
                            }
                            _logger.LogSuccess($"响应客户端[{remoteEndPoint}]请求成功");
                            continue;
                        }
                        //其他
                        _logger.LogInfo($"收到客户端[{remoteEndPoint}]报文:{bufferString}");
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError($"客户端[{remoteEndPoint}]:{ex.InnerException?.Message ?? ex.Message}");
                    }
                }
            });
        }

        /// <summary>
        /// Fanuc机器人交互
        /// </summary>
        /// <param name="bufferString"></param>
        /// <param name="stream"></param>
        /// <param name="remoteEndPoint"></param>
        /// <returns></returns>
        private BllResult FanucTcpHandle(string bufferString, NetworkStream stream, EndPoint? remoteEndPoint)
        {
            try
            {
                var dataArray = bufferString.Split(',');
                _ = float.TryParse(dataArray[0], out var grooveWidth);
                _ = float.TryParse(dataArray[1], out var grooveDepth);
                _ = int.TryParse(dataArray[2], out var type);
                _ = int.TryParse(dataArray[3], out var layer);
                _ = int.TryParse(dataArray[4], out var channel);
                var robotAddress = ((IPEndPoint)remoteEndPoint!).Address.ToString();
                var inputParameterResult = _grooveService.GetInputParameterDefault(robotAddress);
                if (!inputParameterResult.Success)
                {
                    return inputParameterResult;
                }

                var inputParameter = inputParameterResult.Data;
                //参数赋值
                inputParameter.GrooveWidth = grooveWidth;//坡口宽度BC
                inputParameter.GrooveDepth = grooveDepth;//坡口深度H

                //计算
                var result = GrooveComputerTool.GetComputedData(inputParameter);
                if (!result.Success)
                {
                    return BllResultFactory.Error($"计算出现异常:{result.Msg}");
                }
                var outputParameter = result.Data;
                if (outputParameter.Layers < layer)
                {
                    return BllResultFactory.Error($"请求参数不正确,当前请求层{layer},总层数:{outputParameter.Layers}");
                }

                var currentLayer = outputParameter.LayerModels.Where(x => x.CurrentLayer == layer).FirstOrDefault();
                if (currentLayer == null)
                {
                    return BllResultFactory.Error($"{layer}层输出参数为空!");
                }

                var currentChannel = currentLayer.ChannelModels.Where(x => x.CurrentChannel == channel).FirstOrDefault();
                if (currentChannel == null)
                {
                    return BllResultFactory.Error($"{layer}层{channel}道输出参数为空!");
                }

                var layers = outputParameter.Layers;//总层数
                var LayerStartingPoint = currentChannel.StartingPoint;//焊接起点
                var layerEndingPoint = currentChannel.EndingPoint;//焊接终点
                var layerWeldAttitudeAngle = Math.Round(currentChannel.WeldAttitudeAngle, 3);//焊接姿态角 theta
                var layerWeldSpeed = Math.Round(currentChannel.WeldSpeed, 3);//焊接速度(m / s) v11
                var weldAmplitude = Math.Round(currentChannel.WeldAmplitude, 3);//振幅(mm)
                var weldSwingFrequency = Math.Round(currentLayer.WeldSwingFrequency, 3);//摆动频率(Hz)
                var leftAndRightDwellTime = Math.Round(currentLayer.LeftAndRightDwellTime, 3);//左右停留时间(s)
                var multiChannel = currentLayer.ChannelModels.Count;//当前层焊接道数

                //结果
                var ackObj = new List<object>
                {
                    layers,
                    $"{LayerStartingPoint.X},{LayerStartingPoint.Y},{LayerStartingPoint.Z}",
                    $"{layerEndingPoint.X},{layerEndingPoint.Y},{layerEndingPoint.Z}",
                    layerWeldAttitudeAngle,
                    layerWeldSpeed,
                    weldAmplitude,
                    weldSwingFrequency,
                    leftAndRightDwellTime,
                    multiChannel,
                };

                var message = string.Join(',', ackObj);
                var bytes2 = Encoding.ASCII.GetBytes(message);
                stream.Write(bytes2, 0, bytes2.Length);
                Task.Delay(200).Wait();
                var weldMonitor = new WeldMonitorModel
                {
                    EquipmentIPAddress = robotAddress,
                    CurrentLayer = layer,
                    CurrentChannel = channel,
                    RobotInputParameter = inputParameter,
                    RobotOutputParameter = outputParameter,
                    UpdateTime = DateTime.Now,
                };
                WeldMonitor?.Invoke(weldMonitor);
                _logger.LogInfo($"发送至[{remoteEndPoint}]报文:{message}");
                return BllResultFactory.Success();
            }
            catch (Exception ex)
            {
                return BllResultFactory.Error(ex.Message);
            }
        }

        /// <summary>
        /// Kuka Tcp交互处理
        /// </summary>
        /// <param name="bufferString"></param>
        /// <param name="stream"></param>
        private BllResult KukaTcpHandle(string bufferString, NetworkStream stream, EndPoint? remoteEndPoint)
        {
            var inputXmlSerializer = new XmlSerializer(typeof(KukaRequestDto));
            var outputXmlSerializer = new XmlSerializer(typeof(KukaResponseDto));
            using var ms = new MemoryStream();
            var writer = new StreamWriter(ms);
            writer.Write(bufferString.Trim());
            writer.Flush();
            ms.Position = 0;
            var reader = new StreamReader(ms);
            try
            {
                var request = (KukaRequestDto)inputXmlSerializer.Deserialize(reader)!;

                _ = int.TryParse(request.Code, out var robotNo);
                var robotAddress = ((IPEndPoint)remoteEndPoint!).Address.ToString();
                var result = _grooveService.GetComputedData(robotAddress, request.GrooveWidth, request.GrooveDepth);
                if (!result.Success)
                {
                    return BllResultFactory.Error($"数据计算出现异常:{result.Msg}");
                }
                var outputParameter = result.Data;

                var resultData = new KukaResponseDto
                {
                    //Weld_Num = outputParameter.Weld_Num,
                    //WeldHeightAfterWelding = outputParameter.WeldHeightAfterWelding,
                    //WeldWidthAfterWelding = outputParameter.WeldWidthAfterWelding,
                    //GrooveCrossSectionalArea = outputParameter.GrooveCrossSectionalArea,
                    //OneLayerWireFeedingSpeed = outputParameter.OneLayerWireFeedingSpeed,
                    //OneLayerCurrent = outputParameter.OneLayerCurrent,

                    //CoverWireFeedingSpeed = outputParameter.CoverWireFeedingSpeed,
                    //CoverWireFeedingCurrent = outputParameter.CoverWireFeedingCurrent,
                    //WeldingWireCrossSectionalArea = outputParameter.WeldingWireCrossSectionalArea,
                    //Layers = outputParameter.Layers,
                    //TotalDepositionAmount = outputParameter.TotalDepositionAmount,
                    //WeldingWireLengthAndUsage = outputParameter.WeldingWireLengthAndUsage,
                    //TotalDepositionTime = outputParameter.TotalDepositionTime,

                    //WeldingWire = inputParameter.WeldingWire,
                    //ReservedGapForGroove = inputParameter.ReservedGap,
                    //SizeOfTheBluntEdgeOfTheGroove = inputParameter.BluntEdgeSize,
                    //WeldLength = inputParameter.WeldLength,
                    //AdditionalWidthRequiredOnOneSideAfterCovering = inputParameter.WeldWidth,
                    //WeldReinforcementRequiredAfterCovering = inputParameter.WeldHeight
                };

                using var sw = new StringWriter();
                outputXmlSerializer.Serialize(sw, resultData);
                var response = sw.ToString();
                stream.Write(Encoding.Default.GetBytes(response));
                _logger.LogInfo($"响应客户端[{remoteEndPoint}]请求报文:{response}");
                return BllResultFactory.Success();
            }
            catch (Exception ex)
            {
                return BllResultFactory.Error(ex.Message);
            }
        }

        public void Stop()
        {
            _tcpServer.Stop();
        }
    }
}