SystemBackgroundService.cs 12.2 KB
using DataAcquisition.Common.Communications;
using DataAcquisition.Common.Enums;
using DataAcquisition.Common.Utils;
using DataAcquisition.DataAccess;
using DataAcquisition.Models;
using DataAcquisition.Services.DataAnalysis;
using HslCommunication.Profinet.Siemens;
using Microsoft.EntityFrameworkCore;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace DataAcquisition.Services
{
    public class SystemBackgroundService : BackgroundService
    {
        private readonly IDbContextFactory<DataContext> _dbContextFactory;
        private readonly DataCacheService _dataCacheService;
        private readonly IEnumerable<IDataAnalysis> _dataAnalyses;
        private readonly IotService _iotService;
        private readonly IConfiguration _configuration;
        private readonly SystemLog systemLog = SystemLog.Instance;

        private readonly TcpListener _tcpServer;

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

        public SystemBackgroundService(IDbContextFactory<DataContext> dbContextFactory, DataCacheService dataCacheService, IEnumerable<IDataAnalysis> dataAnalyses, IotService iotService, IConfiguration configuration)
        {
            _tcpServer = new TcpListener(IPAddress.Any, 8001);
            _tcpServer.Start();
            _dbContextFactory = dbContextFactory;
            _dataCacheService = dataCacheService;
            _dataAnalyses = dataAnalyses;
            _iotService = iotService;
            _configuration = configuration;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            communications = Initial(_dataCacheService.Equipments.Select(x => x.CommunicationConfig).Distinct().ToList()!);
            _tcpServer.BeginAcceptTcpClient(DoAcceptTcpClient, _tcpServer);

            //采集数据
            foreach (var item in communications)
            {
                _ = Task.Run(async () =>
                {
                    do
                    {
                        try
                        {
                            var equipmentCaches = _dataCacheService.Equipments.Where(x => x.CommunicationConfig?.Id == item.CommunicationId).ToList();
                            item.Read(equipmentCaches.SelectMany(x => x.EquipmentProperties));
                        }
                        catch (Exception ex)
                        {
                            systemLog.LogError($"读取IP:{item.IpAddress}设备出现异常:{ex.Message}");
                        }
                        await Task.Delay(1000);
                    } while (!stoppingToken.IsCancellationRequested);
                }, stoppingToken);
            }

            //自动推送数据
            _ = bool.TryParse(_configuration.GetSection("AutoCommit").Value, out var autoCommit);
            if (autoCommit)
            {
                SendEquipmentData(_dataCacheService.Equipments, stoppingToken);
            }
            ClearRecords();

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    var dataAnalysesTasks = new List<Task>();
                    //数据解析
                    foreach (var item in _dataAnalyses)
                    {
                        dataAnalysesTasks.Add(Task.Run(() =>
                        {
                            item.Analysis(communications, _dataCacheService.Equipments);
                        }, stoppingToken));
                    }
                    Task.WaitAll(dataAnalysesTasks.ToArray(), stoppingToken);
                }
                catch (Exception ex)
                {
                    systemLog.LogError($"后台服务“{nameof(ExecuteAsync)}”方法出现异常:{ex.Message}");
                }
                await Task.Delay(1000, stoppingToken);
            }
            CloesAllConnection(communications);
        }

        private void ClearRecords()
        {
            try
            {
                var endTime = DateTime.Today.AddDays(1 - DateTime.Today.Day);
                var context = _dbContextFactory.CreateDbContext();
                var count = context.EquipmentPropertyRecords.Where(x => x.CreateTime < endTime).ExecuteDelete();
                if (count > 0)
                {
                    systemLog.LogInfo($"成功清除{count}条历史记录数据");
                }
            }
            catch (Exception ex)
            {
                systemLog.LogError($"清理历史状态记录出现异常:{ex.Message}");
            }
        }

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

        private void Receive(TcpClient tcpClient)
        {
            Task.Run(() =>
            {
                while (tcpClient.Connected)
                {
                    try
                    {
                        var buffer = new byte[8192];
                        var stream = tcpClient.GetStream();
                        stream.Read(buffer, 0, buffer.Length);
                        if (buffer.Length == 0) continue;

                        var bufferString = Encoding.Default.GetString(buffer);

                        const string kukaAckFlag1 = "<robot><ack>";
                        const string kukaAckFlag2 = "<ack><robot>";
                        if (bufferString.StartsWith(kukaAckFlag1) && bufferString.EndsWith(kukaAckFlag2))
                        {
                            ReceiveKukaData(bufferString);
                        }

                        //第一位等于02,且第二位等于01,则是设备推送给上位机的报文;否则,不做任何处理
                        if (buffer[0].ToString("X2") != "02" || buffer[1].ToString("X2") != "01" || buffer[126] != 0x0D || buffer[127] != 0x0A)
                        {
                            continue;
                        }
                        //_rgvService.Analysis(tcpClient, _equipmentExecutorService.Equipments, buffer);
                    }
                    catch (Exception ex)
                    {
                        systemLog.LogError(ex.Message);
                    }
                }
            });
        }

        private List<ICommunication> Initial(IList<CommunicationConfig> communicationConfigs)
        {
            var result = new List<ICommunication>();
            try
            {
                foreach (var item in communicationConfigs)
                {
                    ICommunication communication;
                    switch (item.CommunicationType)
                    {
                        case CommunicationTypeConst.None:
                        case CommunicationTypeConst.TcpServer:
                            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.ModbusTcp:
                            communication = new ModbusTcpCommunication(item.Id, item.IpAddress, item.Port);
                            result.Add(communication);
                            break;
                        case CommunicationTypeConst.TcpClient:
                            break;
                        default:
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                systemLog.LogError($"设备通讯初始化异常:{ex.Message}");
            }
            return result;
        }

        /// <summary>
        /// 接收库卡数据
        /// </summary>
        /// <param name="bufferString"></param>
        private void ReceiveKukaData(string bufferString)
        {
            var bufferData = bufferString.Split(',').ToArray();
            if (bufferString.Length == 26)
            {
                var kukaCode = bufferData[0];
                var kukaEquipment = _dataCacheService.Equipments.Where(x => x.Code == kukaCode).FirstOrDefault();
                if (kukaEquipment == null) return;
                //赋值
                kukaEquipment[RobotProps.BootFlag.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.WorkFlag.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.WeldFlag.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.WeldCompleteFlag.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Weld_V.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Weld_I.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Weld_Speed.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Weld_Gas.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Weld_CleanGun.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Alarm.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Work_Time.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Work_Mode.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Type.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Pos_X.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Pos_Y.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Pos_Z.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Pos_A.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Pos_B.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Pos_C.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Pos_E1.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Pos_E2.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Pos_E3.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Pos_E4.ToString()].Value = bufferData[0];
                kukaEquipment[RobotProps.Program_No.ToString()].Value = bufferData[0];

                //时间赋值
                foreach (var item in kukaEquipment.EquipmentProperties)
                {
                    item.UpdateTime = DateTime.Now;
                }
            }
        }

        private static void CloesAllConnection(IEnumerable<ICommunication> communications)
        {
            foreach (var item in communications)
            {
                item.ConnectClose();
            }
        }

        public void SendEquipmentData(IEnumerable<Equipment> equipments, CancellationToken stoppingToken)
        {
            _ = Task.Run(async () =>
            {
                while (!stoppingToken.IsCancellationRequested)
                {
                    var result = _iotService.SendEquipmentData(equipments);
                    if (result.Code == 200)
                    {
                        systemLog.LogSuccess($"数据推送成功,{result.Message}");
                    }
                    else
                    {
                        systemLog.LogError($"数据推送失败,{result.Message}");
                    }
                    await Task.Delay(1000);
                }
            }, stoppingToken);
        }
    }
}