using CompressorXN_Common; using CompressorXN_Model.ViewModel.Plc; using HslCommunication; using HslCommunication.Profinet.Omron; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; namespace CompressorXN_Communication.MyPlc { public class OmronCIPHelper { private static OmronCipNet omronCipNet = null; /// /// 获取欧姆龙PLC连接对象 /// /// /// /// /// public static OmronCipNet GetOmronCipNet(string plcIp, int plcPort, int connectTimeOut = 10000) { omronCipNet = new OmronCipNet(plcIp, plcPort) { ConnectTimeOut = connectTimeOut }; var connect = omronCipNet.ConnectServer(); isConnected = connect.IsSuccess; if (connect.IsSuccess) { return omronCipNet; } else { return null; } } /// /// 链接状态 /// private static bool isConnected = false; public static bool IsConnected { get { return isConnected; } } /// /// 获取PLC值--单点位 /// /// 点位地址 /// 数据类型 /// 读取长度 /// public static (bool ok, string val) SingleReadPlcVal(string pointAddress, string dataType, int length = 1, Encoding encoding = null) { var strVal = string.Empty; try { if (!isConnected || omronCipNet == null) { return (false, strVal); } switch (dataType) { case "bool": var operateBoolResult = omronCipNet.ReadBool(pointAddress); if (!operateBoolResult.IsSuccess) { return (false, strVal); } else { var boolVal = operateBoolResult.Content; strVal = boolVal.ToString(); return (true, strVal); } case "int": var operateIntResult = omronCipNet.ReadInt32(pointAddress); if (!operateIntResult.IsSuccess) { return (false, strVal); } else { var intVal = operateIntResult.Content; strVal = intVal.ToString(); return (true, strVal); } case "short": var operateShortResult = omronCipNet.ReadInt16(pointAddress); if (!operateShortResult.IsSuccess) { return (false, strVal); } else { var shortVal = operateShortResult.Content; strVal = shortVal.ToString(); return (true, strVal); } case "ushort": var operateUshortResult = omronCipNet.ReadUInt16(pointAddress); if (!operateUshortResult.IsSuccess) { return (false, strVal); } else { var ushortVal = operateUshortResult.Content; strVal = ushortVal.ToString(); return (true, strVal); } case "float": var operateFloatResult = omronCipNet.ReadFloat(pointAddress); if (!operateFloatResult.IsSuccess) { return (false, strVal); } else { var floatVal = operateFloatResult.Content; strVal = floatVal.ToString("f3"); return (true, strVal); } case "string": var operateStringResult = omronCipNet.ReadString(pointAddress, (ushort)length, encoding == null ? Encoding.UTF8 : encoding); if (!operateStringResult.IsSuccess) { return (false, strVal); } else { strVal = operateStringResult.Content; return (true, strVal); } case "byte": var operateByteResult = omronCipNet.Read(pointAddress, (ushort)length); if (!operateByteResult.IsSuccess) { return (false, strVal); } else { if (encoding == null) { strVal = Encoding.ASCII.GetString(operateByteResult.Content); } else { strVal = encoding.GetString(operateByteResult.Content); } return (true, strVal); } default: return (false, strVal); } } catch (Exception) { return (false, strVal); } } /// /// 值写入PLC /// /// 点位地址 /// 数据类型 /// 值 /// 长度 /// 编码格式 /// public static (bool isOk, string msg) SingleWriteValToPlc(string pointAddress, string dataType, object value, int len = 1, Encoding encoding = null) { try { if (!isConnected || omronCipNet == null) { return (false, "PLC未连接"); } OperateResult operateResult = new OperateResult { IsSuccess = false }; switch (dataType) { case "bool": operateResult = omronCipNet.Write(pointAddress, Convert.ToBoolean(value)); break; case "int": operateResult = omronCipNet.Write(pointAddress, Convert.ToInt32(value)); break; case "short": operateResult = omronCipNet.Write(pointAddress, Convert.ToInt16(value)); break; case "ushort": operateResult = omronCipNet.Write(pointAddress, Convert.ToUInt16(value)); break; case "float": operateResult = omronCipNet.Write(pointAddress, Convert.ToSingle(value)); break; case "string": operateResult = omronCipNet.Write(pointAddress, value.ToString(), len, encoding ?? Encoding.ASCII); break; case "byte": var bytes = Encoding.ASCII.GetBytes(value.ToString()); operateResult = omronCipNet.WriteTag(pointAddress, 0xD1, bytes, len); break; } if (operateResult.IsSuccess) { return (operateResult.IsSuccess, "操作成功"); } return (operateResult.IsSuccess, operateResult.Message); } catch (Exception ex) { return (false, ex.Message); } } //private static Stopwatch stopwatch = new Stopwatch(); /// /// 不连续的地址批量读取 /// /// public static (bool isSucess, string msg) ReadPlcBatch(List variables, Encoding encoding = null) { try { foreach (var item in variables) { switch (item.DataType) { case "float": OperateResult read = omronCipNet.ReadFloat(item.VariableName); item.ReadVal = read.Content; break; } GlobalVar.deviceInfo.CommGroupList.FirstOrDefault().VariableList.FirstOrDefault(m => m.VariableName == item.VariableName).ReadVal = item.ReadVal; } return (true, string.Empty); //var addressArrTest = new string[1] { "D770" }; //OperateResult readTest = omronCipNet.Read("D770", 4); //var aa = Encoding.ASCII.GetString(readTest.Content, 0, 4); //short占2字节,Real占4个字节,bool占2个字节 //stopwatch.Restart(); int readLen = 40;//每次读取40个地址 int plcPointTotalCount = variables.Count; int readCount = plcPointTotalCount / readLen;//轮询次数 int remainder = plcPointTotalCount % readLen;//余数 readCount = remainder > 0 ? readCount + 1 : readCount; string[] sourceAddressArr = variables.Select(m => m.VariableName).ToArray(); for (int i = 0; i < readCount; i++) { int surplusLen = sourceAddressArr.Length - i * readLen;//剩余长度 int subLen = surplusLen > readLen ? readLen : surplusLen;//应该Take的长度 //本次需要读取的地址数组 var addressArr = sourceAddressArr.Skip(i * readLen).Take(subLen).ToArray(); OperateResult read = omronCipNet.Read(addressArr); if (!read.IsSuccess) { return (read.IsSuccess, read.Message); } int startIndex = 0;//起始地址 for (int j = 0; j < addressArr.Length; j++) { var item = variables.First(m => m.VariableName == addressArr[j]); if (j > 0) { var lastItem = variables.First(m => m.VariableName == addressArr[j - 1]); startIndex = j == 0 ? 0 : startIndex + lastItem.Offset; } switch (item.DataType) { case "string": item.ReadVal = encoding == null ? Encoding.ASCII.GetString(read.Content, startIndex, item.Offset) : encoding.GetString(read.Content, startIndex, item.Offset); break; case "float": item.ReadVal = omronCipNet.ByteTransform.TransSingle(read.Content, startIndex).ToString("f3"); break; case "bool": item.ReadVal = GetBoolFromByte(read.Content, startIndex, item.Offset).ToString(); break; case "short": item.ReadVal = omronCipNet.ByteTransform.TransInt16(read.Content, startIndex).ToString(); break; case "ushort": item.ReadVal = omronCipNet.ByteTransform.TransUInt16(read.Content, startIndex).ToString(); break; case "byte": if (encoding == null) { item.ReadVal = Encoding.ASCII.GetString(read.Content, startIndex, item.Offset); } else { item.ReadVal = encoding.GetString(read.Content, startIndex, item.Offset); } break; } GlobalVar.deviceInfo.CommGroupList.FirstOrDefault().VariableList.FirstOrDefault(m => m.VariableName == item.VariableName).ReadVal = item.ReadVal; } } //stopwatch.Stop(); //Console.WriteLine($"读取PLC点位值耗时={stopwatch.ElapsedMilliseconds}ms"); return (true, string.Empty); } catch (Exception ex) { return (false, $"批量读取异常:{ex.Message}!"); } } /// /// 根据起始索引和长度截取字节数组 /// /// /// /// /// private static bool GetBoolFromByte(byte[] bytes, int startIndex, int len) { var getBytes = SubArray(bytes, startIndex, len); return BitConverter.ToBoolean(getBytes, 0); } /// /// 根据起始索引和截取长度获取新的数组 /// /// /// 原始数组 /// 起始索引 /// 长度 /// public static T[] SubArray(T[] data, int index, int length) { T[] result = new T[length]; Array.Copy(data, index, result, 0, length); return result; } } }