RobotBackgroundService.cs 8.31 KB
using AutomaticGrooveCalculationTool.Common.Utils;
using AutomaticGrooveCalculationTool.Model;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Xml.Serialization;

namespace AutomaticGrooveCalculationTool.Services
{
    public class RobotBackgroundService : BackgroundService
    {
        private readonly SystemLog _logger = SystemLog.Instance;
        private readonly SiemensPLCService _siemensPLC;
        private readonly GrooveService _grooveService;
        private readonly TcpListener _tcpServer;

        public RobotBackgroundService(SiemensPLCService siemensPLC, GrooveService grooveService)
        {
            _tcpServer = new TcpListener(IPAddress.Any, 59152);
            _tcpServer.Start();
            _siemensPLC = siemensPLC;
            _grooveService = grooveService;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _tcpServer.BeginAcceptTcpClient(DoAcceptTcpClient, _tcpServer);

            while (!stoppingToken.IsCancellationRequested)
            {
                foreach (var item in _siemensPLC.Equipments.GroupBy(x => x.IP))
                {
                    var plcIP = item.Key;
                    try
                    {
                        var plc = _siemensPLC.Plcs.First(x => x.IP == plcIP);
                        if (!plc.IsConnected)
                        {
                            await plc.OpenAsync(stoppingToken);
                        }
                        if (!plc.IsConnected)
                        {
                            _logger.LogWarning($"PLC[{plcIP}]连接失败");
                            continue;
                        }
                        _siemensPLC.Read(item.SelectMany(x => x.EquipmentProps));
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError($"设备{item.Key}执行线程出现异常,{ex.Message}");
                    }
                }
                await Task.Delay(500, stoppingToken);
            }
        }

        private void DoAcceptTcpClient(IAsyncResult result)
        {
            var server = (TcpListener)result.AsyncState!;
            var tcpClient = server.EndAcceptTcpClient(result);
            _logger.LogInfo($"[客户端[{tcpClient.Client.RemoteEndPoint}]已成功建立连接");
            Receive(tcpClient);
            server.BeginAcceptTcpClient(DoAcceptTcpClient, server);
        }

        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))
                        {
                            //var str = $"<Ext><Msg>{Random.Shared.Next(100000, 999999)}</Msg></Ext>";
                            //stream.Write(Encoding.Default.GetBytes(str));
                            //_logger.LogSuccess($"响应[{remoteEndPoint}]报文:{str}");
                            //continue;

                            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)!;

                                //默认值
                                var inputParameter = new InputParameter
                                {
                                    WeldingWire = 1.2,
                                    ReservedGapForGroove = 0,
                                    SizeOfTheBluntEdgeOfTheGroove = 2,
                                    WeldLength = 1000,
                                    AdditionalWidthRequiredOnOneSideAfterCovering = 1.5,
                                    WeldReinforcementRequiredAfterCovering = 2
                                };

                                inputParameter.GrooveWidth = request.GrooveWidth;
                                inputParameter.GrooveDepth = request.GrooveDepth;

                                var (outputParameter, _) = _grooveService.GetExcelData(inputParameter);

                                var resultData = new KukaResponseDto
                                {
                                    TheNumberOfWeldingPasses = outputParameter.TheNumberOfWeldingPasses,
                                    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.ReservedGapForGroove,
                                    SizeOfTheBluntEdgeOfTheGroove = inputParameter.SizeOfTheBluntEdgeOfTheGroove,
                                    WeldLength = inputParameter.WeldLength,
                                    AdditionalWidthRequiredOnOneSideAfterCovering = inputParameter.AdditionalWidthRequiredOnOneSideAfterCovering,
                                    WeldReinforcementRequiredAfterCovering = inputParameter.WeldReinforcementRequiredAfterCovering
                                };

                                using var sw = new StringWriter();
                                outputXmlSerializer.Serialize(sw, resultData);
                                var response = sw.ToString();
                                stream.Write(Encoding.Default.GetBytes(response));
                                _logger.LogSuccess($"响应客户端[{remoteEndPoint}]请求成功,报文:{response}");
                            }
                            catch (Exception ex)
                            {
                                _logger.LogError($"响应客户端[{remoteEndPoint}]请求失败:{ex.Message}");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError($"客户端[{remoteEndPoint}]:{ex.InnerException?.Message ?? ex.Message}");
                    }
                }
            });
        }
    }
}