/// <summary> /// 调用读写函数前的校验,此过程包含了解析地址并缓存 /// </summary> /// <param name="equipmentProps"></param> /// <returns></returns> private BllResult <List <string> > Validation(List <EquipmentProp> equipmentProps) { if (equipmentProps == null || equipmentProps.Count() == 0) { return(BllResultFactory.Error <List <string> >($"未传递属性")); } //选取设备类 var ips = equipmentProps.Select(t => t.Equipment).Select(t => t.IP).Distinct().ToList(); //是否存在没有对应的PLC var temp = ips.Where(t => !siemensTcpNets.Exists(a => a.IpAddress == t)).ToArray(); if (temp.Length > 0) { return(BllResultFactory.Error <List <string> >($"存在IP为{string.Join(",", temp)}没有对应的PLC实例,请检查PLC的IP配置")); } //缓存中未存在的属性 var tempProps = equipmentProps.Where(t => !_hslSiemensDataEntities.Exists(a => a.OPCAddressId == t.Id)).ToList(); //解析属性并加入缓存 foreach (var item in tempProps) { var result = SiemensHelper.ParseAddress(item); if (!result.Success) { return(BllResultFactory.Error <List <string> >($"解析地址错误:{result.Msg}")); } _hslSiemensDataEntities.Add(result.Data); } return(BllResultFactory.Sucess(ips)); }
/// <summary> /// 写入多个属性 /// </summary> /// <param name="equipmentProps"></param> /// <returns></returns> public BllResult Writes(List <EquipmentProp> equipmentProps) { var valiResult = Validation(equipmentProps); if (!valiResult.Success) { return(BllResultFactory.Error(valiResult.Msg)); } var ips = valiResult.Data; foreach (var ip in ips) { //此IP对应的PLC var client = siemensTcpNets.Find(t => t.IpAddress == ip); //此IP下的属性 var props = equipmentProps.Where(t => t.Equipment.IP == ip).ToList(); List <HslSiemensDataEntity> list = new List <HslSiemensDataEntity>(); //缓存中已经存在的,改为这样写是为了保持和equipmentProps一样的顺序 foreach (var prop in props) { var item = _hslSiemensDataEntities.FirstOrDefault(t => t.OPCAddressId == prop.Id); if (item != null) { list.Add(item); } } ////缓存中已经存在的 //list.AddRange(_hslSiemensDataEntities.Where(t => props.Exists(a => a.Id == t.OPCAddressId)).ToList()); //对于写入,由于地址可能不连续且写入地址不多,会导致覆盖问题,这里不使用批量写入 foreach (var item in list) { var prop = props.Find(t => t.Id == item.OPCAddressId); var transResult = SiemensHelper.TransferStringToBuffer(item.DataType, prop.Value); if (!transResult.Success) { return(BllResultFactory.Error($"转换到PLC数据类型失败,IP:{ip},地址:{prop.Address}:{transResult.Msg}")); } var buffer = transResult.Data; //如果不是bool,我们都是写字节,如果是bool,我们需要写位,这个调用具体方法实现 //浮点型暂不考虑 OperateResult result = null; if (item.DataType != PLCComponent.PLCDataType.BOOL) { result = client.Write(item.Address, buffer); } else { result = client.Write(item.AddressX, bool.Parse(prop.Value)); } if (result.IsSuccess) { if (prop.EquipmentTypeTemplateCode != "WCSHeartBeat" && prop.EquipmentTypeTemplateCode != "WCSWrite") { if (prop.Equipment != null && prop.EquipmentTypeTemplate != null) { Common.Logger.Log($"写入PLC成功,ip:[{ip}],设备:[{prop.Equipment.Name}],模板名称:[{prop.EquipmentTypeTemplate.Name}],设备属性id:[{prop.Id}],地址:[{prop.Address}],数据:[{prop.Value}]", Enums.LogLevel.PLC); } else { Common.Logger.Log($"写入PLC成功,ip:[{ip}],地址:[{prop.Address}],设备属性备注:[{prop.Remark}],数据:[{prop.Value}],但是找不到设备属性id[{prop.Id}]对应的设备和模板,需要核查配置!", Enums.LogLevel.PLC); } } } else { Common.Logger.Log($"写入PLC失败:ip:[{ip}],地址:[{prop.Address}],设备属性备注:[{prop.Remark}],数据:[{prop.Value}]失败,需要核查配置!", Enums.LogLevel.Error); return(BllResultFactory.Error($"写入PLC失败:[{ip}],地址:[{prop.Address}],数据:[{prop.Value}]:{result.Message}")); } //switch (item.DataType) //{ // case PLCComponent.PLCDataType.BYTE: // var result = client.Write(item.Address,buffer); // if (!result.IsSuccess) // { // return BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result.Message}"); // } // prop.Value = ((int)result.Content).ToString(); // break; // case PLCComponent.PLCDataType.BOOL: // var result2 = client.ReadBool(item.AddressX); // if (!result2.IsSuccess) // { // return BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result2.Message}"); // } // prop.Value = result2.Content.ToString(); // break; // case PLCComponent.PLCDataType.DWORD: // var result3 = client.ReadUInt32(item.Address); // if (!result3.IsSuccess) // { // return BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result3.Message}"); // } // prop.Value = result3.Content.ToString(); // break; // case PLCComponent.PLCDataType.WORD: // var result4 = client.ReadUInt16(item.Address); // if (!result4.IsSuccess) // { // return BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result4.Message}"); // } // prop.Value = result4.Content.ToString(); // break; // case PLCComponent.PLCDataType.INT: // var result5 = client.ReadInt16(item.Address); // if (!result5.IsSuccess) // { // return BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result5.Message}"); // } // prop.Value = result5.Content.ToString(); // break; // case PLCComponent.PLCDataType.DINT: // var result6 = client.ReadInt32(item.Address); // if (!result6.IsSuccess) // { // return BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result6.Message}"); // } // prop.Value = result6.Content.ToString(); // break; // case PLCComponent.PLCDataType.CHAR: // var result7 = client.ReadString(item.Address, item.ByteSize); // if (!result7.IsSuccess) // { // return BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result7.Message}"); // } // prop.Value = result7.Content.ToString(); // break; // default: // return BllResultFactory.Error($"未识别的数据类型:{item.DataType}"); //} } } return(BllResultFactory.Sucess("写入成功")); }
/// <summary> /// 读取多个属性 /// </summary> /// <param name="equipmentProps"></param> /// <returns></returns> public BllResult Reads(List <EquipmentProp> equipmentProps) { var valiResult = Validation(equipmentProps); if (!valiResult.Success) { return(BllResultFactory.Error(valiResult.Msg)); } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); var ips = valiResult.Data; List <Task <BllResult> > tasks = new List <Task <BllResult> >(); foreach (var ip in ips) { var task = Task.Run <BllResult>(() => { //此IP对应的PLC var client = siemensTcpNets.Find(t => t.IpAddress == ip); //此IP下的属性 var props = equipmentProps.Where(t => t.Equipment.IP == ip).ToList(); List <HslSiemensDataEntity> list = new List <HslSiemensDataEntity>(); //缓存中已经存在的 list.AddRange(_hslSiemensDataEntities.Where(t => props.Exists(a => a.Id == t.OPCAddressId)).ToList()); if (props.Count > READLIMIT) { //进行批量读取 //构造地址数组与对应字节长度数据 var adds = new List <string>(); var sizes = new List <ushort>(); foreach (var item in list) { adds.Add(item.Address); sizes.Add(item.ByteSize); } var result = client.Read(adds.ToArray(), sizes.ToArray()); if (!result.IsSuccess) { return(BllResultFactory.Error($"读取错误,IP:{ip},参考信息:{result.Message}")); } //获取读取后的数组结果 var bytes = result.Content.ToList(); foreach (var item in list) { //此数据的buffer var buffer = bytes.Take(item.ByteSize); if (buffer.Count() != (int)item.ByteSize) { //如果没有提取出等量的字节 return(BllResultFactory.Error($"获取的字节序列个数与属性需求字节个数不匹配")); } //剩余待解析 item.Buffer = buffer.ToArray(); var prop = props.Find(t => t.Id == item.OPCAddressId); bytes = bytes.Skip(item.ByteSize).ToList(); var transResult = SiemensHelper.TransferBufferToString(item); if (!transResult.Success) { return(BllResultFactory.Error($"读取时,IP:{ip},地址{prop.Address},转换数据失败:{transResult.Msg}")); } prop.Value = transResult.Data; } return(BllResultFactory.Sucess("读取成功")); } else { //进行单个读取 foreach (var item in list) { var prop = props.Find(t => t.Id == item.OPCAddressId); switch (item.DataType) { case PLCComponent.PLCDataType.BYTE: var result = client.ReadByte(item.Address); if (!result.IsSuccess) { return(BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result.Message}")); } prop.Value = ((int)result.Content).ToString(); break; case PLCComponent.PLCDataType.BOOL: var result2 = client.ReadBool(item.AddressX); if (!result2.IsSuccess) { return(BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result2.Message}")); } prop.Value = result2.Content.ToString(); break; case PLCComponent.PLCDataType.DWORD: var result3 = client.ReadUInt32(item.Address); if (!result3.IsSuccess) { return(BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result3.Message}")); } prop.Value = result3.Content.ToString(); break; case PLCComponent.PLCDataType.WORD: var result4 = client.ReadUInt16(item.Address); if (!result4.IsSuccess) { return(BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result4.Message}")); } prop.Value = result4.Content.ToString(); break; case PLCComponent.PLCDataType.INT: var result5 = client.ReadInt16(item.Address); if (!result5.IsSuccess) { return(BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result5.Message}")); } prop.Value = result5.Content.ToString(); break; case PLCComponent.PLCDataType.DINT: var result6 = client.ReadInt32(item.Address); if (!result6.IsSuccess) { return(BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result6.Message}")); } prop.Value = result6.Content.ToString(); break; case PLCComponent.PLCDataType.CHAR: var result7 = client.ReadString(item.Address, item.ByteSize); if (!result7.IsSuccess) { return(BllResultFactory.Error($"读取IP:{ip},地址{prop.Address}发生错误:{result7.Message}")); } prop.Value = result7.Content.ToString(); break; default: return(BllResultFactory.Error($"未识别的数据类型:{item.DataType}")); } } return(BllResultFactory.Sucess("读取成功")); } }); tasks.Add(task); } Task.WaitAll(tasks.ToArray()); var errors = tasks.Where(t => t.Result.Success != true).ToList(); if (errors.Count > 0) { return(BllResultFactory.Error($"存在读取错误:{string.Join(";", errors.Select(t => t.Result.Msg).ToList())}")); } stopwatch.Stop(); long runtime = stopwatch.ElapsedMilliseconds; return(BllResultFactory.Sucess("读取成功")); }