CenterService.cs 8.73 KB
using HHECS.DAQClient.Common;
using HHECS.DAQClient.Model;
using HHECS.DAQClient.Communications;
using HHECS.DAQClient.DataAccess;
using HslCommunication.Profinet.Siemens;
using HHECS.DAQClient.Dto;
using HHECS.EquipmentModel;

namespace HHECS.DAQClient.Services
{
    internal class CenterService
    {
        private readonly SystemLog _log = SystemLog.GetInstance();
        private readonly DataContext _context;
        private readonly HttpService _httpService;
        private List<Equipment> _equipments = new List<Equipment>();
        private List<ICommunication> communications = new List<ICommunication>();
        private CancellationTokenSource cts = new CancellationTokenSource();

        public CenterService(DataContext dataContext, HttpService httpService)
        {
            _context = dataContext;
            _httpService = httpService;
        }

        /// <summary>
        /// 重新加载设备信息并开始采集数据
        /// </summary>
        /// <returns></returns>
        public void Start()
        {
            cts = new CancellationTokenSource();
            try
            {
                _equipments = _context.Equipment.Where(x => !x.Disable).ToList();
                if (_equipments.Count == 0)
                {
                    _log.LogWarning($"设备数据为空,请配置数据后操作!");
                    cts.Cancel();
                    return;
                }

                var equipmentProps = _context.EquipmentProp.Where(t => true).ToList();
                var equipmentTypes = _context.EquipmentType.Where(t => true).ToList();
                var equipmentTypePropTemplates = _context.EquipmentTypePropTemplate.Where(t => true).ToList();
                //组合逻辑外键
                _equipments.ForEach(t =>
                {
                    t.EquipmentType = equipmentTypes.FirstOrDefault(i => i.Id == t.EquipmentTypeId);
                    t.EquipmentProps = equipmentProps.Where(i => i.EquipmentId == t.Id).ToList();
                });
                equipmentProps.ForEach(t =>
                {
                    t.Equipment = _equipments.FirstOrDefault(i => i.Id == t.EquipmentId);
                    t.EquipmentTypePropTemplate = equipmentTypePropTemplates.FirstOrDefault(i => i.Id == t.EquipmentTypePropTemplateId);
                });

                var communicationConfigs = _context.CommunicationConfigs.Where(x => x.Enable).ToList();
                if (communicationConfigs.Count == 0)
                {
                    _log.LogWarning($"通讯配置数据为空,请配置数据后操作!");
                    cts.Cancel();
                    return;
                }

                communications = InitialCommunication(communicationConfigs);
                //采集数据
                foreach (var item in communications)
                {
                    _ = Task.Run(async () =>
                    {
                        while (!cts.IsCancellationRequested)
                        {
                            try
                            {
                                var equipmentCaches = _equipments.Where(x => x.IP == item.IpAddress).ToList();
                                var props = equipmentCaches.SelectMany(x => x.EquipmentProps).ToList();
                                var temps = props.Select(x => new DataItem
                                {
                                    Id = x.Id,
                                    Code = x.EquipmentTypePropTemplateCode,
                                    DataAddress = x.Address,
                                    DataType = x.EquipmentTypePropTemplate.DataType,
                                    Value = string.Empty
                                }).ToList();
                                //读取数据
                                var result = item.Read(temps);
                                if (!result.Success)
                                {
                                    _log.LogError(result.Msg);
                                    await Task.Delay(1000);
                                    continue;
                                }

                                //赋值
                                foreach (var item in props)
                                {
                                    item.Value = temps.Find(x => x.Id == item.Id).Value;
                                    item.Updated = DateTime.Now;
                                }
                                await Task.Delay(1000);
                            }
                            catch (Exception ex)
                            {
                                _log.LogError($"读取IP:{item.IpAddress}设备出现异常:{ex.Message}");
                            }
                            await Task.Delay(1000);
                        }
                    }, cts.Token);
                }

                _ = Task.Run(async () =>
                {
                    while (!cts.IsCancellationRequested)
                    {
                        var tasks = new List<Task>();
                        foreach (var item in _equipments.GroupBy(x => x.EquipmentType))
                        {
                            tasks.Add(Task.Run(() =>
                            {
                                var data = item.Select(x => new EquipmentDataDto
                                {
                                    Plmeid = Guid.NewGuid(),
                                    EquipmentSN = x.Code,
                                    Reported = x.EquipmentProps.Select(p => new TagItem
                                    {
                                        Tag = p.Address,
                                        Value = p.Value ?? string.Empty
                                    }).ToList(),
                                    Version = 1,
                                    SourceTimestamp = ConvertToTimestamp(DateTime.Now),
                                    Timestamp = ConvertToTimestamp(DateTime.Now)
                                });
                                _httpService.SendEquipmentData(data);
                            }));
                        }
                        Task.WaitAll(tasks.ToArray());
                        await Task.Delay(1000);
                    }
                }, cts.Token);
            }
            catch (Exception ex)
            {
                _log.LogException($"数据初始化失败:{ex.Message}");
            }
        }

        /// <summary>
        /// 停止PLC数据采集
        /// </summary>
        /// <returns></returns>
        public void Stop()
        {
            _log.Log("已停止采集!");
            cts.Cancel();//取消异步线程
        }

        private List<ICommunication> InitialCommunication(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:
                            communication = new TcpClientCommunication(item.Id, item.IpAddress, item.Port);
                            break;
                        default:
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                _log.LogError($"设备通讯初始化异常:{ex.Message}");
            }
            return result;
        }

        private static long ConvertToTimestamp(DateTime? dateTime)
        {
            if (dateTime == null)
            {
                return 0;
            }
            return Convert.ToInt64(((DateTime)dateTime - new DateTime(1970, 1, 1)).TotalSeconds);
        }
    }
}