CenterService.cs 6.26 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;

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();
        private List<ICommunication> communications = new();
        private CancellationTokenSource cts = new();

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

        /// <summary>
        /// 重新加载设备信息并开始采集数据
        /// </summary>
        /// <returns></returns>
        public void Start()
        {
            cts = new();
            try
            {
                _equipments = _context.Equipment.Where(x => x.Enable).IncludeMany(x => x.EquipmentProperties).ToList();
                if (_equipments.Count == 0)
                {
                    _log.LogWarning($"设备数据为空,请配置数据后操作!");
                    cts.Cancel();
                    return;
                }
                communications = InitialCommunication(_context.CommunicationConfigs.Where(x => x.Enable).ToList());
                //采集数据
                foreach (var item in communications)
                {
                    _ = Task.Run(async () =>
                    {
                        while (!cts.IsCancellationRequested)
                        {
                            try
                            {
                                var equipmentCaches = _equipments.Where(x => x.CommunicationConfig?.Id == item.CommunicationId).ToList();
                                item.Read(equipmentCaches.SelectMany(x => x.EquipmentProperties));
                            }
                            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.EquipmentProperties.Select(p => new TagItem
                                    {
                                        Tag = p.DataAddress,
                                        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);
        }
    }
}