RobotBackgroundService.cs 5.16 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');

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

                        const string kukaAckFlag1 = "<Robot>";
                        const string kukaAckFlag2 = "</Robot>";
                        if (bufferString.StartsWith(kukaAckFlag1, StringComparison.OrdinalIgnoreCase) && bufferString.EndsWith(kukaAckFlag2))
                        {
                            var inputXmlSerializer = new XmlSerializer(typeof(InputParameter));
                            var outputXmlSerializer = new XmlSerializer(typeof(OutputParameter));
                            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 = (InputParameter)inputXmlSerializer.Deserialize(reader)!;
                                var (outputParameter, _) = _grooveService.GetExcelData(request);
                                using var sw = new StringWriter();
                                outputXmlSerializer.Serialize(sw, outputParameter);
                                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}");
                    }
                }
            });
        }
    }
}