PLCCore.cs 7.69 KB
using Hh.Mes.POJO.BllModel;
using Hh.Mes.POJO.Entity;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace HHECS.Model.PLCHelper.Interfaces
{
    public class PLCCore
    {
        /// <summary>
        /// 开启并行读取的限制数目,于此相关的均需要实际测试性能情况。
        /// </summary>
        const int ParaInt = 3;

        public List<IPLC> PLCs { get; set; } = new List<IPLC>();

        public PLCCore(List<IPLC> ps)
        {
            PLCs = ps;
        }

        public PLCCore()
        {
        }


        /// <summary>
        /// 连接,通常指定PLC的初始化请在连接中进行
        /// </summary>
        /// <returns></returns>
        public BllResult Connect()
        {
            foreach (var item in PLCs)
            {
                var result = item.Connect();
                if (!result.Success)
                {
                    return BllResultFactory.Error($"连接PLC{item.IP}失败:{result.Msg}");
                }
            }
            return BllResultFactory.Success();
        }

        /// <summary>
        /// 连接,连接指定IP的PLC
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public BllResult Connect(string ip)
        {
            var plc = PLCs.FirstOrDefault(t => t.IP == ip);
            if (plc == null)
            {
                return BllResultFactory.Error($"未找到IP为{ip}的PLC配置");
            }

            return plc.Connect();
        }

        /// <summary>
        /// 断开,通常在断开之前请先停止逻辑处理,延迟后再调用
        /// </summary>
        /// <returns></returns>
        public BllResult DisConnect()
        {
            foreach (var item in PLCs)
            {
                item.DisConnect();
            }
            return BllResultFactory.Success();
        }

        /// <summary>
        /// 断开,断开指定IP的PLC连接
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public BllResult DisConnect(string ip)
        {
            var plc = PLCs.FirstOrDefault(t => t.IP == ip);
            if (plc == null)
            {
                return BllResultFactory.Error($"未找到IP为{ip}的PLC配置");
            }

            return plc.DisConnect();
        }

        /// <summary>
        /// 获取连接状态
        /// hack:对于使用OPC实现,此链接状态指示为client与OPC服务器的连接状态;所以使用OPC的情况下需要额外检测读写是否正确。
        /// </summary>
        /// <returns></returns>
        public BllResult GetConnectStatus()
        {
            foreach (var item in PLCs)
            {
                var result = item.GetConnectStatus();
                if (!result.Success)
                {
                    return BllResultFactory.Error($"PLC{item.IP}失去连接:{result.Msg}");
                }
            }
            return BllResultFactory.Success();
        }

        /// <summary>
        /// 获取指定IPPlc的连接状态
        /// hack:对于使用OPC实现,此链接状态指示为client与OPC服务器的连接状态;所以使用OPC的情况下需要额外检测读写是否正确。
        /// </summary>
        /// <returns></returns>
        public BllResult GetConnectStatus(string ip)
        {
            var plc = PLCs.FirstOrDefault(t => t.IP == ip);
            if (plc == null)
            {
                return BllResultFactory.Error($"未找到IP为{ip}的PLC配置");
            }

            return plc.GetConnectStatus();
        }

        /// <summary>
        /// 读取地址
        /// </summary>
        /// <param name="equipmentProps"></param>
        /// <returns></returns>
        public BllResult Reads(List<base_equipment_prop> equipmentProps)
        {
            var propGroup = equipmentProps.GroupBy(t => t.Equipment.ip);
            foreach (var item in propGroup)
            {
                var plc = PLCs.FirstOrDefault(t => t.IP == item.Key);
                if (plc == null)
                {
                    return BllResultFactory.Error($"未找到IP为{item.Key}的PLC的配置");
                }
            }
            if (propGroup.Count() > ParaInt)
            {
                List<Task> tasks = new List<Task>();
                foreach (var item in propGroup)
                {
                    var plc = PLCs.FirstOrDefault(t => t.IP == item.Key);
                    tasks.Add(Task.Run<BllResult>(() =>
                    {
                        return plc.Reads(item.ToList());
                    }));
                }
                Task.WaitAll(tasks.ToArray());
                foreach (var item in tasks)
                {
                    var result = item.AsyncState as BllResult;
                    if (result != null)
                    {
                        if (!result.Success)
                        {
                            return result;
                        }
                    }
                    else
                    {
                        return BllResultFactory.Error($"读取失败:读取结果返回了null值,请检查PLC读取实现类");
                    }
                }
                return BllResultFactory.Success();
            }
            else
            {
                foreach (var item in propGroup)
                {
                    var plc = PLCs.FirstOrDefault(t => t.IP == item.Key);
                    var result = plc.Reads(item.ToList());
                    if (!result.Success)
                    {
                        return result;
                    }
                }
            }
            return BllResultFactory.Success();
        }

        /// <summary>
        /// 写入地址
        /// 注意:写入值不做线程优化处理,请误大量频繁写入
        /// </summary>
        /// <param name="equipmentProps"></param>
        /// <returns></returns>
        public BllResult Writes(List<base_equipment_prop> equipmentProps)
        {
            var propGroup = equipmentProps.GroupBy(t => t.Equipment.ip);
            foreach (var item in propGroup)
            {
                var plc = PLCs.FirstOrDefault(t => t.IP == item.Key);
                if (plc == null)
                {
                    return BllResultFactory.Error($"未找到IP为{item.Key}的PLC的配置");
                }
                var result = plc.Writes(item.ToList());
                if (!result.Success)
                {
                    return result;
                }
            }
            return BllResultFactory.Success();
        }

        /// <summary>
        /// 读取单个地址
        /// </summary>
        /// <param name="equipmentProp"></param>
        /// <returns></returns>
        public BllResult Read(base_equipment_prop equipmentProp)
        {
            var plc = PLCs.FirstOrDefault(t => t.IP == equipmentProp.Equipment.ip);
            if (plc == null)
            {
                return BllResultFactory.Error($"未找到IP为{equipmentProp.Equipment.ip}的PLC的配置");
            }
            return plc.Read(equipmentProp);
        }

        /// <summary>
        /// 写入单个地址
        /// </summary>
        /// <param name="equipmentProp"></param>
        /// <returns></returns>
        public BllResult Write(base_equipment_prop equipmentProp)
        {
            var plc = PLCs.FirstOrDefault(t => t.IP == equipmentProp.Equipment.ip);
            if (plc == null)
            {
                return BllResultFactory.Error($"未找到IP为{equipmentProp.Equipment.ip}的PLC的配置");
            }
            return plc.Write(equipmentProp);
        }

    }
}