SystemBackgroundService.cs 10.1 KB
using HHECS.RobotTool.Common.Communications;
using HHECS.RobotTool.Common.Utils;
using HHECS.RobotTool.DataAccess;
using HHECS.RobotTool.Dto;
using HHECS.RobotTool.Model;
using HHECS.RobotTool.Services.Analysis;
using HslCommunication.Profinet.Siemens;
using Microsoft.EntityFrameworkCore;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Xml.Serialization;

namespace HHECS.RobotTool.Services
{
    public class SystemBackgroundService : BackgroundService
    {
        private readonly SystemLog _logger = SystemLog.Instance;
        private readonly GrooveService _grooveService;
        private readonly IDbContextFactory<DataContext> _dbContextFactory;
        private readonly DataCacheService _dataCacheService;
        private readonly IAnalysis _analyse;
        private readonly TcpListener _tcpServer;

        private List<ICommunication> _communications = new List<ICommunication>();

        public SystemBackgroundService(GrooveService grooveService, IDbContextFactory<DataContext> dbContextFactory, DataCacheService dataCacheService, IAnalysis analyse)
        {
            _tcpServer = new TcpListener(IPAddress.Any, 59152);
            _tcpServer.Start();
            _grooveService = grooveService;
            _dbContextFactory = dbContextFactory;
            _dataCacheService = dataCacheService;
            _analyse = analyse;
        }

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

            using var context = _dbContextFactory.CreateDbContext();
            var configs = context.CommunicationConfigs.Where(x => x.Enable).ToList();
            _communications = InitialCommunications(configs);
            foreach (var item in _communications)
            {
                _ = Task.Run(async () =>
                {
                    while (!stoppingToken.IsCancellationRequested)
                    {
                        var cacheData = _dataCacheService.Equipments.Where(x => x.CommunicationId.Equals(item.CommunicationId)).SelectMany(x => x.EquipmentProperties).ToList();
                        item.Read(cacheData);
                        await Task.Delay(1000);
                    }
                }, stoppingToken);
            }

            while (!stoppingToken.IsCancellationRequested)
            {
                foreach (var communication in _communications)
                {
                    var equipments = _dataCacheService.Equipments.Where(x => x.CommunicationId.Equals(communication.CommunicationId)).ToList();
                    _analyse.Execute(communication, equipments);
                }
                await Task.Delay(1000, stoppingToken);
            }
        }

        private List<ICommunication> InitialCommunications(IEnumerable<CommunicationConfig> communicationConfigs)
        {
            var result = new List<ICommunication>();
            try
            {
                foreach (var item in communicationConfigs)
                {
                    ICommunication communication;
                    switch (item.CommunicationType)
                    {
                        case CommunicationTypeConst.None:
                            break;
                        //case CommunicationTypeConst.KukaVarProxy:
                        //    communication = new KukaAvarProxyCommunication(item.Id, item.IpAddress, item.Port);
                        //    result.Add(communication);
                        //    break;
                        case CommunicationTypeConst.Siemens_S1200:
                            communication = new SiemensS7Communication(item.Id, SiemensPLCS.S1200, item.IpAddress);
                            result.Add(communication);
                            break;
                        case CommunicationTypeConst.Siemens_S1500:
                            communication = new SiemensS7Communication(item.Id, SiemensPLCS.S1500, item.IpAddress);
                            result.Add(communication);
                            break;
                        case CommunicationTypeConst.TcpClient:
                            break;
                        default:
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"设备通讯初始化异常:{ex.Message}");
            }
            return result;
        }

        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))
                        {
                            KukaTcpHandle(bufferString, stream, remoteEndPoint);
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError($"客户端[{remoteEndPoint}]:{ex.InnerException?.Message ?? ex.Message}");
                    }
                }
            });
        }

        /// <summary>
        /// Kuka Tcp交互处理
        /// </summary>
        /// <param name="bufferString"></param>
        /// <param name="stream"></param>
        /// <param name="remoteEndPoint"></param>
        private void KukaTcpHandle(string bufferString, NetworkStream stream, EndPoint? remoteEndPoint)
        {
            //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
                {
                    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.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}");
            }
        }
    }
}