EquipmentExecutor.cs 9.8 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 心跳
                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 readProp = heartbeat.EquipmentProps.Find(t => t.EquipmentTypePropTemplateCode == PLCHeartProps.PLCWrite.ToString());
                var readResult = EquipmentCommunicationHub.Reads(readProp);
                if (readResult.Success && readProp.Value == "True")
                {
                    //回复一个
                    var prop = heartbeat.EquipmentProps.Find(t => t.EquipmentTypePropTemplateCode == PLCHeartProps.WCSWrite.ToString());
                    prop.Value = "True";
                    EquipmentCommunicationHub.Writes(prop);

                }
                else
                {
                    //表示心跳断开,排除其IP对应的设备
                    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);
                }
            });
            Excuting();
        }
    }
}