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); } } }