EquipmentExecutor.cs 12.3 KB
using HaHRCS.Rcs.Dal.Repository;
using HaHRCS.Rcs.Model.Entities;
using HHECS.BllModel;
using HHECS.Communication;
using HHECS.Communication.PLC;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Rcs.Executor.PLC;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace HaHRCS.Rcs.Executor.PLC
{
    public class EquipmentExecutor : BackgroundService
    {
        #region 属性
        /// <summary>
        /// 设备
        /// </summary>
        public List<Equipment> equipment { get; set; }
        /// <summary>
        /// PLC交互属性
        /// </summary>
        public EquipmentCommunicationHub EquipmentCommunicationHub { get; set; }


        public List<StationExecute> StationExecutes { get; private set; } = new List<StationExecute>();

        public Guid InstanceId { get; } = Guid.NewGuid();

        public object WriteFlag { get; set; } = false;

        #endregion



        private EquipmentRepository _equipmentRepository;
        private EquipmentPropRepository _equipmentPropRepository;
        private EquipmentTypeRepository _equipmentTypeRepository;
        private EquipmentTypePropTemplateRepository _EquipmentTypePropTemplateRepository;

        public EquipmentExecutor(EquipmentRepository equipmentRepository, EquipmentPropRepository equipmentPropRepository, EquipmentTypeRepository equipmentTypePropTemplate, EquipmentTypePropTemplateRepository equipmentTypePropTemplateRepository)
        {
            _equipmentRepository = equipmentRepository;
            _equipmentPropRepository = equipmentPropRepository;
            _equipmentTypeRepository = equipmentTypePropTemplate;
            _EquipmentTypePropTemplateRepository = equipmentTypePropTemplateRepository;
        }




        public BllResult<List<Equipment>> InitEquipment()
        {
            try
            {

                var equipments = _equipmentRepository.Where(t => t.Disable == false).ToList();
                var equipmentProps = _equipmentPropRepository.Where(t => true).ToList();
                var equipmentTypes = _equipmentTypeRepository.Where(t => true).ToList();
                var equipmentTypePropTemplates = _EquipmentTypePropTemplateRepository.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);

                });
                //判断逻辑外键是否组合完毕
                if (equipments.Count(t => t.EquipmentType == null || t.EquipmentProps.Count == 0) > 0)
                {
                    return BllResultFactory.Error<List<Equipment>>("初始化设备信息失败,请检查基础数据", "ERROR");
                }
                //EquipmentList = equipments;
                return BllResultFactory.Success(equipments);
            }
            catch (Exception ex)
            {
                return BllResultFactory.Exception<List<Equipment>>(ex, "初始化设备信息出错:" + ex.Message, "ERROR");
            }
        }
        /// <summary>
        /// 执行线程
        /// </summary>
        private void Excuting()
        {
            var groups = equipment.GroupBy(t => new { t.WarehouseCode, t.IP }).ToList();
            foreach (var group in groups)
            {
                TaskExcutorModel taskExcutorModelMonitor = new TaskExcutorModel();
                taskExcutorModelMonitor.EquipmentCodes = group.ToList().Select(t => t.Code).Aggregate((a, b) => a + "," + b);
                taskExcutorModelMonitor.ExcuteTask = Task.Factory.StartNew(async () =>
                {
                    Stopwatch stopwatch = new Stopwatch();
                    while (true)
                    {
                        //TestExcute(item.Key.IP);
                        await Task.Delay(100);
                        stopwatch.Restart();
                        var result = Excute(group.ToList(), group.Key.IP);
                        stopwatch.Stop();
                        taskExcutorModelMonitor.Time = stopwatch.ElapsedMilliseconds;
                    }
                }, TaskCreationOptions.LongRunning).Unwrap();
            }
        }

        private BllResult Excute(List<Equipment> equipments, string ip)
        {
            try
            {
                List<Equipment> tempEquipments = equipments;
                if (EquipmentCommunicationHub == null)
                {
                    return BllResultFactory.Error($"PLC为空", "Error01");
                }
                if (!EquipmentCommunicationHub.GetConnectStatus(ip).Success)
                {
                    EquipmentCommunicationHub.DisConnect(ip);
                    var result2 = EquipmentCommunicationHub.Connect(ip);
                    if (!result2.Success)
                    {
                        return BllResultFactory.Error($"重新连接打开IP为{ip}的PLC连接失败:{result2.Msg};请检查网络是否断开", "Error02");
                    }
                }
                var readEquipments = tempEquipments.SelectMany(t => t.EquipmentProps)
                                                .Where(a => a.EquipmentTypePropTemplate.PropType == EquipmentPropType.ECSReadAddress.ToString() ||
                                                          //   a.EquipmentTypePropTemplate.PropType == EquipmentPropType.ECSWriteAddress.ToString() ||
                                                             a.EquipmentTypePropTemplate.PropType == EquipmentPropType.PLCAlarmAddress.ToString() ||
                                                             a.EquipmentTypePropTemplate.PropType == EquipmentPropType.PLCCollectionAddress.ToString())
                                                .ToArray();


                lock (WriteFlag)
                {
                    var writeAddress = tempEquipments.SelectMany(t => t.EquipmentProps)
                                                    .Where(a => a.EquipmentTypePropTemplate.PropType == EquipmentPropType.ECSWriteAddress.ToString())
                                                    .ToArray();
                    var res= EquipmentCommunicationHub.Reads(writeAddress);

                }

                var result = EquipmentCommunicationHub.Reads(readEquipments);

                #region 心跳
                if (ip == "192.168.30.10")
                {
                    var heartbeat = tempEquipments.Find(t => t.EquipmentType.Code == EquipmentTypeConst.PLCHeartbeat.ToString() && t.IP == ip);
                    if (heartbeat == null)
                    {
                        return BllResultFactory.Error($"IP为{ip}的PLC没有配置心跳连接");
                    }
                    //var readProp = heartbeat.EquipmentProps.Find(t => t.EquipmentTypePropTemplateCode == PLCHeartProps.PLCWrite.ToString());
                    var writeProp = heartbeat.EquipmentProps.Find(t => t.EquipmentTypePropTemplateCode == PLCHeartProps.PLCWrite.ToString());
                    var wcsProp = heartbeat.EquipmentProps.Find(t => t.EquipmentTypePropTemplateCode == PLCHeartProps.WCSWrite.ToString());

                    if (writeProp == null || wcsProp == null)
                    {
                        return BllResultFactory.Error("心跳属性配置缺失");
                    }
                    var readResult = EquipmentCommunicationHub.Reads(writeProp);
                    if (readResult.Success && writeProp.Value == "True")
                    {
                        wcsProp.Value = wcsProp.Value == "True" ? "False" : "True";
                        EquipmentCommunicationHub.Writes(wcsProp);
                    }
                    var deviceSafetyList = tempEquipments
                     .Where(t => t.EquipmentType.Code == EquipmentTypeConst.Conving.ToString()
                              && t.IP == ip)
                     .ToList();
                    if (!deviceSafetyList.Any())
                    {
                        return BllResultFactory.Error($"IP为{ip}没有对应的安全信号配置");
                    }
                    foreach (var deviceSafety in deviceSafetyList)
                    {
                        // 查找设备属性
                        var readProp1 = deviceSafety.EquipmentProps
                            .FirstOrDefault(t => t.EquipmentTypePropTemplateCode == StationProps.Devicessafety.ToString());
                        if (readProp1 == null)
                            continue;
                        var readResult1 = EquipmentCommunicationHub.Reads(readProp1);
                        if (readResult.Success)
                        {
                            readProp1.Value = "True";
                            EquipmentCommunicationHub.Writes(readProp1);
                        }
                    }
                }
               
                //else
                //{
                //    //表示心跳断开,排除其IP对应的设备
                //    //var prop = heartbeat.EquipmentProps.Find(t => t.EquipmentTypePropTemplateCode == PLCHeartProps.WCSWrite.ToString());
                //    //prop.Value = "False";
                //    //EquipmentCommunicationHub.Writes(prop);
                //    tempEquipments = tempEquipments.Where(t => t.IP != heartbeat.IP).ToList();
                //}
                #endregion
                //result.Success = true;
                #region 站台、设备 处理
                StationExecutes.ForEach(t =>
                {
                    t.Excute(tempEquipments.Where(a => a.EquipmentType.Id == t.EquipmentType.Id).ToList(), EquipmentCommunicationHub, equipment);
                });
                #endregion              
                if (!result.Success)
                {
                    return BllResultFactory.Error($"读取IP为{ip}的PLC地址错误:{result.Msg},如果此问题一直存在,请检查数据地址或网络配置", "Error03");
                }

                return BllResultFactory.Success("读取PLC成功");
            }
            catch (Exception ex)
            {

                return BllResultFactory.Error("程序处理出现异常");
            }
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            var result = EquipmentCommunicationHubBuilder.Build("HubBuilder3.x.json");
            if (!result.Success)
            {
                result.Msg = $"初始化PLC失败:{result.Msg}";
                return;
            }
            EquipmentCommunicationHub = result.Data;
            var resut2 = InitEquipment();
            if (!resut2.Success)
            {
                return;
            }
            equipment = resut2.Data;
            equipment.Select(t => t.EquipmentType).Distinct().ToList().ForEach(t =>
            {
                if (t.Code == EquipmentTypeConst.Conving.ToString())
                {
                    var conving = new ConvingExecute(t);
                    StationExecutes.Add(conving);
                }
                if (t.Code == EquipmentTypeConst.Cylinder.ToString())
                {
                    var conving = new CylinderExecute(t);
                    StationExecutes.Add(conving);
                }
                if (t.Code == EquipmentTypeConst.Gating.ToString())
                {
                    var conving = new GatingExecute(t);
                    StationExecutes.Add(conving);
                }
            });
            //equipment.Select(t => t.EquipmentType).Distinct().ToList().ForEach(t =>
            //{
            //    if (t.Code == EquipmentTypeConst.Cylinder.ToString())
            //    {
            //        var conving = new CylinderExecute(t);
            //        StationExecutes.Add(conving);
            //    }
            //});
            Excuting();
        }
    }
}