using Newtonsoft.Json.Linq; using System; using System.Collections; using System.Collections.Generic; using System.Drawing; using System.Dynamic; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security.Policy; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Forms; using System.Xml.Linq; using static System.Net.Mime.MediaTypeNames; using static System.Windows.Forms.VisualStyles.VisualStyleElement; namespace EIP_Protocol { #region MES与PLC通讯结构 public enum eMachineState:short { Uninitialized=0, //未初始化状态 Initializing, //初始化中... Initialized, //初始化完成 Running, //运行中 Paused, //暂停状态 Fault, //故障状态 Alarm //报警状态 } public enum eMesCmd:byte { none=0, InStation = 1, //1:工站进站申请 OutStation =2 //2:工站出站申请 } public enum eAgvCmd { RequestPassingIn = 1, // = 1, AGV请求进料 ConfirmPassInFinish = 2, //= 2, AGV请求进料完成确认 RequestPassingOut = 3, //=3, AGV请求出料 ConfrimPassingOutFinish = 4 //= 4, AGV请求出料完成确认 } //图⽚命名需要遵循⼩⽶标准 //[项⽬]_[⼯站]_[SN]_[物料-功能]_[测试时间]_[定位/检测/测量结果]_[是否原图-当前第⼏张-共⼏张] [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct CommandToPLC { [MarshalAs(UnmanagedType.U1)] public byte cmd; //1:AGV请求进料 2:AGV请求进料完成确认 3:AGV请求出料 4:AGV请求出料完成确认 PLC:成功回被PC清零 [MarshalAs(UnmanagedType.I2)] public short cmdParam; //1:左边接口 2:右边接口 [MarshalAs(UnmanagedType.I2)] public short cmdResult; //指令执行结果 1:OK 110:失败 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct CommandFromPLC { [MarshalAs(UnmanagedType.U1)] public byte cmd; //1:工站进站申请 2:工站出站申请 [MarshalAs(UnmanagedType.I2)] public short cmdParam; //指令参数 [MarshalAs(UnmanagedType.I2)] public short cmdResult; //指令执行结果 1:OK 110:失败 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP10_From_PLC { [MarshalAs(UnmanagedType.I4)] public int nThrowCount; //抛料次数 [MarshalAs(UnmanagedType.R4)] public float fCleanAirPress; //清洁气压 [MarshalAs(UnmanagedType.R4)] public float fCleanSpeed; //清洁速度mm/s [MarshalAs(UnmanagedType.R4)] public float fWindBladeHeight; //风刀高度mm [MarshalAs(UnmanagedType.R4)] public float fCleanTime; //清洁时间S [MarshalAs(UnmanagedType.I4)] public int nCleanCount; //清洁次数 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP10_DataSet_t { [MarshalAs(UnmanagedType.I4)] public int nThrowCount; //抛料次数 [MarshalAs(UnmanagedType.R4)] public float fCleanAirPress; //清洁气压 [MarshalAs(UnmanagedType.R4)] public float fCleanSpeed; //清洁速度mm/s [MarshalAs(UnmanagedType.R4)] public float fWindBladeHeight; //风刀高度mm [MarshalAs(UnmanagedType.R4)] public float fCleanTime; //清洁时间S [MarshalAs(UnmanagedType.I4)] public int nCleanCount; //清洁次数 [MarshalAs(UnmanagedType.I4)] public int nRemainCount; //外壳体余料数 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct IoT_DataSet_t { [MarshalAs(UnmanagedType.I2)] public short machineState; //设备状态 [MarshalAs(UnmanagedType.I2)] public short work_type; //作业类型:=1 PRESSURE_TEST(压测),=2 POINT_CHECK(点检),=3 OUT_STATION(正常跑料数据) [MarshalAs(UnmanagedType.I2)] public short testStatus; //测试状态:=1 PASS 0=FAIL [MarshalAs(UnmanagedType.I2)] public short BeatAction; //节拍动作 1:上料开始 2:上料结束 3:作业开始 4:作业结束 5:下料开始 6:下料结束 [MarshalAs(UnmanagedType.I2)] //节拍返回 1:OK 2:NG public short beatReturn; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] //一个单独的位代表一个报警32*10=320 public uint[] fault_codes; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP20_DataSet_t { [MarshalAs(UnmanagedType.I4)] public int nThrowCount; //抛料次数 [MarshalAs(UnmanagedType.I4)] public int nRemainCount; //上盖余料数 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP30_DataSet_t //站数据集 { [MarshalAs(UnmanagedType.R4)] public float fGlueSupplySpeed; //供胶速度 [MarshalAs(UnmanagedType.R4)] public float fAB_AirPress; //AB管气压 [MarshalAs(UnmanagedType.R4)] public float fAB_AirPressDiff; //AB管气压差 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public float[] fMesHeightInfos; //产品测高信息--点胶前的测高(mm) [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public float[] fIntervalWeights; //可能没有:定期称重数据 A胶,B胶 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public float[] fRemainGlues; //剩余胶量A:0 B:1 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP30_stnDataSet_t { public BarcodeSet_t BarcodeSet; //条码集合 public CommandFromPLC mesCommFrmPLC; //MES通讯 public OP30_DataSet_t mesData; public IoT_DataSet_t iotData; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP40_DataSet_t { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] public float[] fGluePosX; //胶线位置X偏差 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] public float[] fGluePosY; //胶线位置Y偏差 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] public float[] fGlue_Areas; //胶线面积 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] public float[] fGlue_Heights; //胶线高度 [MarshalAs(UnmanagedType.I4)] public int nResult; //胶线检测结果 1:OK 非1:NG //public Image TestPic; //测试照片 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP50_DataSet_t { [MarshalAs(UnmanagedType.I4)] public int nIsAddPCBAsmOK; //是否组装到位 [MarshalAs(UnmanagedType.I4)] public int nHaveAddPCB; //是否有ADD板 [MarshalAs(UnmanagedType.R4)] public float fForceAddPCB; //装ADD板的压力 [MarshalAs(UnmanagedType.I4)] public int nRemainCount; //ADD板余料数 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP60_DataSet_t { [MarshalAs(UnmanagedType.I4)] public int nIsTopCoverAsmOK; //是否组装到位 [MarshalAs(UnmanagedType.I4)] public int nHaveTopCover; //是否有上盖板 [MarshalAs(UnmanagedType.R4)] public float fForceTopCover; //装上盖板的压力 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP70_DataSet_t { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public float[] fScrewTimes; //锁附时间 PLC 14颗螺丝 预留6 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public short[] nScrewOrders; //锁附顺序 PLC 锁螺丝的标号 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public short[] nScrewResults; //锁附结果 PLC [MarshalAs(UnmanagedType.I4)] public int nRemainCount; //螺丝余料数 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP70_ScrewDataSet_t { [MarshalAs(UnmanagedType.R4)] public float fTorque; //上位机传到PLC的锁螺丝扭力 每次读到阿特拉斯的数据都传一次 [MarshalAs(UnmanagedType.R4)] public float fCircles; //上位机传到PLC的锁螺丝圈数 每次读到阿特拉斯的数据都传一次 } public class OP70_PC_CollectDataSet_t { //需要自己收集 public float[] fScrewTorques; //锁附扭力 public float[] fScrewCircles; //锁附圈数 public float[][] fTorqueCurve; //扭力曲线 } public struct OP70_stnDataSet_t { public BarcodeSet_t BarcodeSet; //条码集合 public CommandFromPLC mesCommFrmPLC; //MES通讯 public OP70_DataSet_t mesData; public IoT_DataSet_t iotData; public OP70_ScrewDataSet_t screwDataToPLC; //传到PLC的锁螺丝数据,用于HMI显示用 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct BarcodeSet_t { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 51)] //载具条码 public string strCarrierBarcode; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 101)] //产品条码 public string strProductBarcode; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 101)] //工位零部件条码 public string strPartBarcode; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP10_MesData_t { public BarcodeSet_t BarcodeSet; //条码集合 public CommandToPLC agvCommToPLC; //AGV通讯 public CommandFromPLC mesCommFrmPLC; //MES通讯 public OP10_DataSet_t mesData; public IoT_DataSet_t iotData; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP20_MesData_t { public BarcodeSet_t BarcodeSet; //条码集合 public CommandToPLC agvCommToPLC; //AGV通讯 public CommandFromPLC mesCommFrmPLC; //MES通讯 public OP20_DataSet_t mesData; public IoT_DataSet_t iotData; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP30_MesData_t { public OP30_stnDataSet_t Left; public OP30_stnDataSet_t Right; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP40_MesData_t { public BarcodeSet_t BarcodeSet; //条码集合 public CommandFromPLC mesCommFrmPLC; //MES通讯 public OP40_DataSet_t mesData; public IoT_DataSet_t iotData; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP50_MesData_t { public BarcodeSet_t BarcodeSet; //条码集合 public CommandToPLC agvCommToPLC; //AGV通讯 public CommandFromPLC mesCommFrmPLC; //MES通讯 public OP50_DataSet_t mesData; public IoT_DataSet_t iotData; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP60_MesData_t { public BarcodeSet_t BarcodeSet; //条码集合 public CommandFromPLC mesCommFrmPLC; //MES通讯 public OP60_DataSet_t mesData; public IoT_DataSet_t iotData; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP70_iotDataSet_t { public IoT_DataSet_t Left; public IoT_DataSet_t Right; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP70_MesData_t { public OP70_stnDataSet_t Left; public OP70_stnDataSet_t Right; } public struct OP80_DataSet_t { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public float[] fScrewHeights; //螺丝高度 PLC 14颗螺丝 预留6 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public short[] nScrewResults; //螺丝检测结果 PLC 1:OK 0:NG } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP80_MesData_t { public BarcodeSet_t BarcodeSet; //条码集合 public CommandFromPLC mesCommFrmPLC; //MES通讯 public OP80_DataSet_t mesData; public IoT_DataSet_t iotData; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP90_DataSet_t { [MarshalAs(UnmanagedType.I4)] public int nThrowCount; //抛料次数 [MarshalAs(UnmanagedType.I4)] public int nRemainCount; //料箱余料数 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)] public struct OP90_MesData_t { public BarcodeSet_t BarcodeSet; //条码集合 public CommandToPLC agvCommToPLC; //AGV通讯 public CommandFromPLC mesCommFrmPLC; //MES通讯 public OP90_DataSet_t mesData; public IoT_DataSet_t iotData; } #endregion MES与PLC通讯结构 public class Inovance_EIP { private string strTagPrefix = "Application.GVL."; //标签前缀,80站是Application.GVL_HMI.,不知道为什么反正就是这样 private object m_objLock = new object(); bool isStart = false; string strClaimedComputerIP = ""; //PC的IP地址 - private实际IP private int m_nInstanceId = 0; //实例ID public bool m_bConnected = false; public string _pcIPStr = string.Empty; //PC的IP地址 public string _plcIPStr = string.Empty; //PLC的IP地址 public bool IsConnected { get { return m_bConnected; } } public void Config_TagPrefix(string TagPrefix) { strTagPrefix = TagPrefix; } #region 自定义的结构 public enum ERROR_NO : int { ERR_EIP_STOPED = -2,//协议栈未开启 OTHER_ERROR = -1, SUCCESS = 0, ERRI_INVALID_CONNECTION_INSTANCE_SPECIFIED = 1,//连接的实例ID与已有的ID重复或超过最大值 ERRI_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH,//连接的网络路径格式错误,无法检测出来目标IP离线等错误 ERRI_CONNECTION_COUNT_LIMIT_REACHED,//达到最大连接数量 ERRI_OUT_OF_MEMORY,//内存溢出,缓冲区已满 ERRR_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH, //连接的网络地址无效 ERRR_CONN_CONFIG_FAILED_NO_RESPONSE, //连接无响应 ERRR_CONN_CONFIG_FAILED_ERROR_RESPONSE,//连接响应错误 ERRR_INVALID_DESTINATION, //目标标签不存在 ERRR_TAGNAME_TOO_LONG, //标签名超过255字节 ERRR_REQUEST_DATA_TOO_LARGE, //请求数据超限 ERRR_CONN_CONNECTION_TIMED_OUT, //活动连接响应超时,请检查目标IP是否离线 ERRR_TAGNAME_CONVERT_FAILED, //标签名解析错误 ERRR_WRITE_DATASIZE_UNCONSISTENT, //数据长度与标签实际长度不一致 ERRR_SCAN_ERROR, //扫描标签信息失败 }; public enum TAG_TYPE : int { TAG_TYPE_UNDEFINE = -1, TAG_TYPE_BOOL = 0xC1, //新增 TAG_TYPE_SINT = 0xC2, TAG_TYPE_INT = 0xC3, TAG_TYPE_DINT = 0xC4, TAG_TYPE_LINT = 0xC5, TAG_TYPE_USINT = 0xC6, TAG_TYPE_UINT = 0xC7, TAG_TYPE_UDINT = 0xC8, TAG_TYPE_ULINT = 0xC9, TAG_TYPE_REAL = 0xCA, TAG_TYPE_LREAL = 0xCB, TAG_TYPE_STRING = 0xD0, //新增 TAG_TYPE_BYTE = 0xD1, TAG_TYPE_WORD = 0xD2, TAG_TYPE_DWORD = 0xD3, TAG_TYPE_LWORD = 0xD4, TAG_TYPE_STRUCT = 0xA2, //新增 TAG_TYPE_ARRAY = 0xA3 }; enum EtIPConnectionState : int { ConnectionNonExistent = 0x0, //该实例未有连接 ConnectionConfiguring = 0x1, //连接正在打开过程中 ConnectionEstablished = 0x3, //连接已成功建立并在活动中 ConnectionTimedOut = 0x4, //连接超时 ConnectionClosing = 0x6 //连接正在关闭中 }; public const uint INVALID_MEMBER = 0xffffffff; //Member is not valid flag should be used when no member should be specified in the UCMM public struct tagTagReadData { public string pName; public int nElementCount; public int nArrayPos; }; public struct tagTagReadDataBase { public string pName; public int nElementCount; }; public struct tagTagRetValue { public IntPtr pData; public TAG_TYPE pType; public int nDataLength; //tagTagRetValue() //{ // pData = NULL; // pType = TAG_TYPE_UNDEFINE; // nDataLength = 0; //} //~tagTagRetValue() //{ // if (pData) // { // delete pData; // pData = NULL; // } //} }; [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct tagTagWriteData { public string pName; public IntPtr pData; public TAG_TYPE pType; public int nArrayPos; public int nDataLength; public int nElementCount; }; public struct tagTagWriteDataBase { public string pName; public IntPtr pData; public TAG_TYPE pType; public int nDataLength; public int nElementCount; }; public class MySerializationBinder : SerializationBinder { public override Type BindToType(string assemblyName, string typeName) { // 如果类型名称是"MyNamespace.MyUnsupportedType",则将其转换为"MyNamespace.MySupportType" if (typeName == "MyNamespace.MyUnsupportedType") { return Type.GetType("MyNamespace.MySupportType"); } // 否则返回null,表示无法进行转换 return null; } } #endregion 自定义的结构 #region 动态类型 public class DynamicMethodProvider { public dynamic GetDynamicValue(string propertyName) { dynamic result; switch (propertyName) { case "Name": result = "John Doe"; break; case "Age": result = 30; break; default: result = new ExpandoObject(); ((IDictionary)result).Add("UnknownProperty", "UnknownValue"); break; } return result; } } public static T CreateElement() { Type t = typeof(T); return (T)t.Assembly.CreateInstance(t.FullName); } public static dynamic CreateElement(string typename) { Type t = GetTypeByName(typename); return t.Assembly.CreateInstance(t.FullName); } public static Type GetTypeByName(string typename) { Type t = null; string source = typename; try { t = Type.GetType(source); if (t != null) { return t; } Assembly[] assembly = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly ass in assembly) { t = ass.GetType(source); if (t != null) { return t; } Type[] ts = ass.GetTypes(); foreach (Type st in ts) { if (Regex.IsMatch(st.FullName, @"\." + source + @"(`?\d+)?$")) { return st; } } } } catch (Exception ex) { } return t; } public static Type GetTypeByName2(string typename) { Type t = null; string source = typename; if (source.IndexOf('<') > 0) { List lv = new List(); while (Regex.IsMatch(source, @"<[^<>]+>")) { lv.Add(Regex.Match(source, @"(?<=<)[^<>]+(?=>)").Value); source = Regex.Replace(source, @"<[^<>]+>", "/" + (lv.Count - 1)); } List args = new List(); for (int i = 0; i < lv.Count; i++) { List arg = new List(); string[] sp = lv[i].Split(','); for (int j = 0; j < sp.Length; j++) { string s = sp[j].Trim(); if (!string.IsNullOrEmpty(s)) { if (Regex.IsMatch(s, @"/\d+$")) { Match m = Regex.Match(s, @"^([^/\s]+)\s*/(\d+)$"); if (!m.Success) { throw new Exception(""); } Type p = GetTypeByName(m.Groups[1].Value); Type c = p.MakeGenericType(args[Convert.ToInt32(m.Groups[2].Value)]); arg.Add(c); } else { arg.Add(GetTypeByName(s)); } } } args.Add(arg.ToArray()); } Match f = Regex.Match(source, @"^([^/\s]+)\s*/(\d+)$"); if (!f.Success) { throw new Exception(""); } Type fp = GetTypeByName(f.Groups[1].Value); Type fc = fp.MakeGenericType(args[Convert.ToInt32(f.Groups[2].Value)]); return fc; } else { try { t = Type.GetType(source); if (t != null) { return t; } Assembly[] assembly = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly ass in assembly) { t = ass.GetType(source); if (t != null) { return t; } Type[] ts = ass.GetTypes(); foreach (Type st in ts) { //if (Regex.IsMatch(st.FullName, @"\." + Regex.FormatRegEx(source) + @"(`?\d+)?$")) if (Regex.IsMatch(st.FullName, @"\." + source + @"(`?\d+)?$")) { return st; } } } } catch (Exception ex) { } } return t; } #endregion 动态类型 #region DLL [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern void EipStart(); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern void EipStop(); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int EipOpenConnection(string ipAddress, IntPtr instanceID); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int EipCloseConnection(int nID); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int EipReadTag(int instanceID, string tagName, IntPtr type, byte[] dest, int dataLength, ushort elementCount = 1, uint nPos = INVALID_MEMBER); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int EipWriteTag(int instanceID, string tagName, int type, byte[] source, int dataLength, ushort elementCount = 1, uint nPos = INVALID_MEMBER/*, uint strLen = 0*/); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int EipGetConnectionState(int nID); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern bool EipStartExt(string ipAddress, uint nPort = 0); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int EipReadTagList(int instanceID, int nNumOfTags, tagTagReadData[] pTagList, ref tagTagRetValue pdest); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern ERROR_NO EipWriteTagList(int instanceID, int nNumOfTags, tagTagWriteData[] pTagWritenData); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern bool DeleteTagListStru(ref tagTagRetValue pRetValue, int nNumOfTags); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int EipReadTagExt(int instanceID, string tagName, IntPtr type, byte[] dest, int dataLength, ushort elementCount = 1); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int EipWriteTagExt(int instanceID, string tagName, int type, byte[] source, int dataLength, ushort elementCount = 1); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int EipReadTagListExt(int instanceID, int nNumOfTags, tagTagReadDataBase[] pTagList, ref tagTagRetValue pdest, bool bScan = false); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern ERROR_NO EipWriteTagListExt(int instanceID, int nNumOfTags, tagTagWriteDataBase[] pTagWritenData, bool bScan = false); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern ERROR_NO EipReadTagExt2(int iInstanceID, tagTagReadDataBase[] pTagList, ref tagTagRetValue pDest); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern ERROR_NO EipWriteTagExt2(int iInstanceID, tagTagWriteDataBase[] pTagWritenData); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern void ResetTagInfo(); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern ERROR_NO EipReadTagRaw(int iInstanceID, tagTagReadDataBase[] pTagList, ref tagTagRetValue pDest); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern ERROR_NO EipWriteTagRaw(int iInstanceID, tagTagWriteDataBase[] pTagWritenData); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int EipReadTagListRaw(int instanceID, int nNumOfTags, tagTagReadDataBase[] pTagList, ref tagTagRetValue pdest); [DllImport("EipTagSimple.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern ERROR_NO EipWriteTagListRaw(int instanceID, int nNumOfTags, tagTagWriteDataBase[] pTagWritenData); #endregion DLL #region private方法 private string getTypeString(TAG_TYPE eType) { string strType = ""; switch (eType) { case TAG_TYPE.TAG_TYPE_SINT: strType = "SINT"; break; case TAG_TYPE.TAG_TYPE_INT: strType = "INT"; break; case TAG_TYPE.TAG_TYPE_DINT: strType = "DINT"; break; case TAG_TYPE.TAG_TYPE_LINT: strType = "LINT"; break; case TAG_TYPE.TAG_TYPE_USINT: strType = "USINT"; break; case TAG_TYPE.TAG_TYPE_UINT: strType = "UINT"; break; case TAG_TYPE.TAG_TYPE_UDINT: strType = "UDINT"; break; case TAG_TYPE.TAG_TYPE_ULINT: strType = "ULINT"; break; case TAG_TYPE.TAG_TYPE_REAL: strType = "REAL"; break; case TAG_TYPE.TAG_TYPE_LREAL: strType = "LREAL"; break; case TAG_TYPE.TAG_TYPE_BYTE: strType = "BYTE"; break; case TAG_TYPE.TAG_TYPE_WORD: strType = "WORD"; break; case TAG_TYPE.TAG_TYPE_DWORD: strType = "DWORD"; break; case TAG_TYPE.TAG_TYPE_LWORD: strType = "LWORD"; break; case TAG_TYPE.TAG_TYPE_BOOL: strType = "BOOL"; break; case TAG_TYPE.TAG_TYPE_STRING: strType = "STRING"; break; case TAG_TYPE.TAG_TYPE_STRUCT: strType = "STRUCT"; break; default: break; } return strType; } private byte[] StringToBytes(string s) { string[] str = s.Split(' '); int n = str.Length; byte[] cmdBytes = null; int p = 0; for (int k = 0; k < n; k++) { int sLen = str[k].Length; int bytesLen = sLen / 2; int position = 0; byte[] bytes = new byte[bytesLen]; for (int i = 0; i < bytesLen; i++) { string abyte = str[k].Substring(position, 2); bytes[i] = Convert.ToByte(abyte, 16); position += 2; } if (position >= 2) { byte[] cmdBytes2 = new byte[p + bytesLen]; if (cmdBytes != null) { Array.Copy(cmdBytes, 0, cmdBytes2, 0, p); } Array.Copy(bytes, 0, cmdBytes2, p, bytesLen); cmdBytes = cmdBytes2; p += bytesLen; } } return cmdBytes; } private (int,string) OpenEip(string strLocalComputerIp) { //limit input of controller bool blnTest = false; bool bValidIP = true; Regex regex = new Regex("^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"); blnTest = regex.IsMatch(strLocalComputerIp); if (blnTest == true) { string[] strTemp = strLocalComputerIp.Split(new char[] { '.' }); if (strTemp.Length < 4) { bValidIP = false; return (-1, "不符合IP格式"); } for (int i = 0; (i < strTemp.Length) && bValidIP; i++) { if (Convert.ToInt32(strTemp[i]) > 255) { //大于255则提示,不符合IP格式 bValidIP = false; return (-2, "IP大于255,不符合IP格式"); } } } else { //输入非数字则提示,不符合IP格式 bValidIP = false; return (-3, "输入非数字,不符合IP格式"); } if (bValidIP) { if (!isStart) { if (EipStartExt(strLocalComputerIp, 0)) { isStart = true; strClaimedComputerIP = strLocalComputerIp; return (0, "EIP协议栈开启成功"); } else { isStart = false; return (1, "EIP协议栈开启失败"); } } else { if (string.Compare(strClaimedComputerIP, strLocalComputerIp) != 0) { return (2,"更改上位机IP时需先关闭协议栈,再开启"); } else { return (3, "EIP协议栈已经开启"); } } } return (-4, "无效IP"); } private (bool,string) CloseEip() { if (isStart) { EipStop(); isStart = false; return (true, "EIP协议栈关闭"); } else { return (false, "EIP协议栈未开启,请先开启"); } } #endregion private方法 #region 连接/断开 #region 连接方式 一 public Inovance_EIP() { } /// /// 连接PLC /// /// PC的IP地址 /// PLC的IP地址 /// 成功:True 失败:False public (int,string) Connect(string strComputerIp,string strPlcIp) { _pcIPStr = strComputerIp; _plcIPStr = strPlcIp; lock (m_objLock) { string strRet = ""; int nRet = 0; if (!isStart) (nRet, strRet) = OpenEip(strComputerIp); if (nRet != 0) return (nRet, strRet); bool blnTest = false; bool bValidIP = true; Regex regex = new Regex("^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"); blnTest = regex.IsMatch(strPlcIp); if (blnTest == true) { string[] strTemp = strPlcIp.Split(new char[] { '.' }); for (int i = 0; i < strTemp.Length; i++) { if (Convert.ToInt32(strTemp[i]) > 255) { bValidIP = false; return (-10, "PLC IP 大于255,不符合IP格式"); } } } else { bValidIP = false; return (-11, "PLC IP输入非数字,不符合IP格式"); } if (bValidIP) { if (strPlcIp.CompareTo(strClaimedComputerIP) == 0) { string strLog = ""; strLog += "上位机IP与PLC IP相同,请重新输入"; return (-20, strLog); } if (strPlcIp.CompareTo(strComputerIp) == 0) { string strLog = ""; strLog += "上位机IP与PLC IP相同,请重新输入"; return (-21, strLog); } int instanceId = 0; ERROR_NO errorNo; unsafe { errorNo = (ERROR_NO)EipOpenConnection(strPlcIp, (IntPtr)(&instanceId)); } m_nInstanceId = instanceId; string str = ""; str += "\n请求创建PLC连接 ip:"; str += strPlcIp; str += " "; if (errorNo != ERROR_NO.SUCCESS) { m_bConnected = false; str += ("失败 "); switch (errorNo) { case ERROR_NO.ERR_EIP_STOPED: str += ("协议栈未开启"); break; case ERROR_NO.ERRI_INVALID_CONNECTION_INSTANCE_SPECIFIED: str += ("连接的实例ID与已有的ID重复或超过最大值"); break; case ERROR_NO.ERRI_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: str += ("连接的网络路径格式错误,无法检测出来目标IP离线等错误"); break; case ERROR_NO.ERRI_CONNECTION_COUNT_LIMIT_REACHED: str += ("达到最大连接数量"); break; case ERROR_NO.ERRI_OUT_OF_MEMORY: str += ("内存溢出,缓冲区已满"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: str += ("连接的网络地址无效"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_NO_RESPONSE: str += ("连接无响应"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_ERROR_RESPONSE: str += ("连接响应错误"); break; default: str += ("其他错误"); break; } } else { str += "成功"; str += " 分配的实例ID 为 "; str += instanceId.ToString(); m_bConnected = true; return (0, str); } str += "\n"; return (100 + (int)errorNo, str); } } return (1000, "Error"); } #endregion 连接方式 一 #region 连接方式 二 /// /// /// /// PC的IP地址 /// PLC的IP地址 public Inovance_EIP(string strComputerIp, string strPlcIp) { _pcIPStr = strComputerIp; _plcIPStr = strPlcIp; } /// /// 连接PLC /// /// 成功:True 失败:False public (int, string) Connect() { lock (m_objLock) { string strRet = ""; int nRet = 0; if (!isStart) (nRet, strRet) = OpenEip(_pcIPStr); if (nRet != 0) return (nRet, strRet); bool blnTest = false; bool bValidIP = true; Regex regex = new Regex("^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"); blnTest = regex.IsMatch(_plcIPStr); if (blnTest == true) { string[] strTemp = _plcIPStr.Split(new char[] { '.' }); for (int i = 0; i < strTemp.Length; i++) { if (Convert.ToInt32(strTemp[i]) > 255) { bValidIP = false; return (-10, "PLC IP 大于255,不符合IP格式"); } } } else { bValidIP = false; return (-11, "PLC IP输入非数字,不符合IP格式"); } if (bValidIP) { if (_plcIPStr.CompareTo(strClaimedComputerIP) == 0) { string strLog = ""; strLog += "上位机IP与PLC IP相同,请重新输入"; return (-20, strLog); } if (_plcIPStr.CompareTo(_pcIPStr) == 0) { string strLog = ""; strLog += "上位机IP与PLC IP相同,请重新输入"; return (-21, strLog); } int instanceId = 0; ERROR_NO errorNo; unsafe { errorNo = (ERROR_NO)EipOpenConnection(_plcIPStr, (IntPtr)(&instanceId)); } m_nInstanceId = instanceId; string str = ""; str += "\n请求创建PLC连接 ip:"; str += _plcIPStr; str += " "; if (errorNo != ERROR_NO.SUCCESS) { m_bConnected = false; str += ("失败 "); switch (errorNo) { case ERROR_NO.ERR_EIP_STOPED: str += ("协议栈未开启"); break; case ERROR_NO.ERRI_INVALID_CONNECTION_INSTANCE_SPECIFIED: str += ("连接的实例ID与已有的ID重复或超过最大值"); break; case ERROR_NO.ERRI_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: str += ("连接的网络路径格式错误,无法检测出来目标IP离线等错误"); break; case ERROR_NO.ERRI_CONNECTION_COUNT_LIMIT_REACHED: str += ("达到最大连接数量"); break; case ERROR_NO.ERRI_OUT_OF_MEMORY: str += ("内存溢出,缓冲区已满"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: str += ("连接的网络地址无效"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_NO_RESPONSE: str += ("连接无响应"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_ERROR_RESPONSE: str += ("连接响应错误"); break; default: str += ("其他错误"); break; } } else { str += "成功"; str += " 分配的实例ID 为 "; str += instanceId.ToString(); m_bConnected = true; return (0, str); } str += "\n"; return (100 + (int)errorNo, str); } } return (1000, "Error"); } #endregion 连接方式 二 /// /// 断开连接 /// /// 成功:True 失败:False public bool Disconnect() { lock (m_objLock) { if (m_nInstanceId == 0 || !m_bConnected) { m_nInstanceId = 0; m_bConnected = false; return true; } ERROR_NO errorNo = (ERROR_NO)EipCloseConnection(m_nInstanceId); //string str = ""; if (errorNo != ERROR_NO.SUCCESS) { //str += "失败"; m_bConnected = false; m_nInstanceId = 0; return false; } else { //str += "成功"; m_bConnected = false; m_nInstanceId = 0; CloseEip(); return true; } } } #endregion 连接/断开 public (int,string) Read_Tag(string strTagName, int nCount, out byte[] pBuf) { pBuf = null; string strType = ""; lock (m_objLock) { if (!m_bConnected) return (-1,"未连接"); string tagName = strTagName; byte[] tagNameUTF8 = Encoding.UTF8.GetBytes(tagName); if (m_nInstanceId <= 0) { return (-2, "实例ID需大于0"); } if (tagNameUTF8.Length > 255) { return (-3, "标签名长度超过255字节"); } ushort elementCount = (ushort)nCount; if (elementCount > 0) { int destLength = 1400; byte[] dest = new byte[destLength]; char[] cChar = Encoding.ASCII.GetChars(dest); //TAG_TYPE type = TAG_TYPE.TAG_TYPE_UNDEFINE; //int returnLength = 0; tagTagReadDataBase[] pTaglist = new tagTagReadDataBase[1]; pTaglist[0].pName = tagName; pTaglist[0].nElementCount = elementCount; tagTagRetValue[] tagValue = new tagTagRetValue[1]; ERROR_NO errorNo = ERROR_NO.OTHER_ERROR; unsafe { errorNo = EipReadTagExt2(m_nInstanceId, pTaglist, ref tagValue[0]); } string strLog = ""; strLog += "读取请求"; if (/*returnLength < 0*/errorNo != ERROR_NO.SUCCESS) { strLog += " 失败 标签名:" + tagName + " 实例ID:" + m_nInstanceId.ToString() + " "; switch (/*returnLength*/errorNo) { //case -1: // strLog += ("其他错误"); // break; //case -2: // strLog += ("协议栈未开启"); // break; //case -3: // strLog += ("实例id小于或等于0"); // break; //case -4: // strLog += ("标签名长度大于255字节"); // break; //case -5: // strLog += ("目标标签不存在"); // break; //case -6: // strLog += ("响应超时,请检查设备是否离线"); // break; //case -7: // strLog += ("标签名解析错误"); // break; //case -8: // strLog += ("扫描标签信息失败"); // break; //default: // strLog += ("其他错误"); // break; case ERROR_NO.ERR_EIP_STOPED: strLog += ("协议栈未开启"); break; case ERROR_NO.ERRI_INVALID_CONNECTION_INSTANCE_SPECIFIED: strLog += ("连接的实例ID与已有的ID重复或超过最大值"); break; case ERROR_NO.ERRI_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: strLog += ("连接的网络路径格式错误,无法检测出来目标IP离线等错误"); break; case ERROR_NO.ERRI_CONNECTION_COUNT_LIMIT_REACHED: strLog += ("达到最大连接数量"); break; case ERROR_NO.ERRI_OUT_OF_MEMORY: strLog += ("内存溢出,缓冲区已满"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: strLog += ("连接的网络地址无效"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_NO_RESPONSE: strLog += ("连接无响应"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_ERROR_RESPONSE: strLog += ("连接响应错误"); break; case ERROR_NO.ERRR_INVALID_DESTINATION: strLog += ("目标标签不存在"); break; case ERROR_NO.ERRR_TAGNAME_TOO_LONG: strLog += ("标签名超过255字节"); break; case ERROR_NO.ERRR_REQUEST_DATA_TOO_LARGE: strLog += ("请求数据超限"); break; case ERROR_NO.ERRR_CONN_CONNECTION_TIMED_OUT: strLog += ("响应超时,请检查设备是否离线"); break; case ERROR_NO.ERRR_TAGNAME_CONVERT_FAILED: strLog += ("标签名解析错误"); break; case ERROR_NO.ERRR_SCAN_ERROR: strLog += ("扫描标签信息失败"); break; default: strLog += ("其他错误"); break; } strLog += "\n"; return (10,strLog); } else { switch (/*type*/tagValue[0].pType) { case TAG_TYPE.TAG_TYPE_BOOL: strType += "Boolean"; break; case TAG_TYPE.TAG_TYPE_SINT: strType += "SByte"; break; case TAG_TYPE.TAG_TYPE_INT: strType += "Int16"; break; case TAG_TYPE.TAG_TYPE_DINT: strType += "Int32"; break; case TAG_TYPE.TAG_TYPE_LINT: strType += "Int64"; break; case TAG_TYPE.TAG_TYPE_USINT: strType += "Byte"; break; case TAG_TYPE.TAG_TYPE_UINT: strType += "UInt16"; break; case TAG_TYPE.TAG_TYPE_UDINT: strType += "UInt32"; break; case TAG_TYPE.TAG_TYPE_ULINT: strType += "UInt64"; break; case TAG_TYPE.TAG_TYPE_REAL: strType += "Single"; break; case TAG_TYPE.TAG_TYPE_LREAL: strType += "Double"; break; case TAG_TYPE.TAG_TYPE_STRING: strType += "String"; break; case TAG_TYPE.TAG_TYPE_BYTE: strType += "Byte"; break; case TAG_TYPE.TAG_TYPE_WORD: strType += "UInt16"; break; case TAG_TYPE.TAG_TYPE_DWORD: strType += "UInt32"; break; case TAG_TYPE.TAG_TYPE_LWORD: strType += "UInt64"; break; case TAG_TYPE.TAG_TYPE_STRUCT: strType += "STRUCT"; break; case TAG_TYPE.TAG_TYPE_ARRAY: strType += "ARRAY"; break; default: break; } pBuf = new byte[tagValue[0].nDataLength]; unsafe { byte* memBytePtr = (byte*)tagValue[0].pData.ToPointer(); for (int j = 0; j < tagValue[0].nDataLength; j++) { pBuf[j] = memBytePtr[j]; //string str = ""; //str += j.ToString() + ": "; //str += "0x" + String.Format("{0:X2}", memBytePtr[j]) + "\n"; } } DeleteTagListStru(ref tagValue[0], 1); //调用接口释放内存 } } else { return (-10, "元素个数参数错误,必须>0"); } return (0, strType); } } public (int, string) Write_Tag(string strTagName, int nCount, byte[] pBuf) { lock (m_objLock) { if (!m_bConnected) return (-1, "未连接"); string tagName = strTagName; byte[] tagNameUTF8 = Encoding.UTF8.GetBytes(tagName); if (m_nInstanceId <= 0) { return (-2, "实例ID需大于0"); } if (tagNameUTF8.Length > 255) { return (-3, "标签名长度超过255字节"); } ushort elementCount = (ushort)nCount; if ((pBuf.Length < 1) || (elementCount < 1)) { return (-4, "请求个数必须大于0,请重新输入"); } if (pBuf.Length > 1400) { return (-5, "标签数据长度超过1400字节,请重新输入"); } int dataLength = pBuf.Length; tagTagWriteDataBase[] pTaglist = new tagTagWriteDataBase[1]; //标签1属性 pTaglist[0].pName = tagName; pTaglist[0].nElementCount = elementCount; pTaglist[0].pType = TAG_TYPE.TAG_TYPE_UNDEFINE; pTaglist[0].pData = Marshal.AllocHGlobal(1400); pTaglist[0].nDataLength = dataLength; byte temp = 0; for (int i = 0; i < dataLength; ++i) { temp = pBuf[i]; Marshal.WriteByte(pTaglist[0].pData + i * sizeof(byte), temp); } //ERROR_NO errorNo = (ERROR_NO)EipWriteTag(m_nInstanceId, tagName, (int)type, source, dataLength, elementCount, arrayPos/*, strLen*/); //ERROR_NO errorNo = (ERROR_NO)EipWriteTagExt(m_nInstanceId, tagName, (int)type, source, dataLength, elementCount); ERROR_NO errorNo = EipWriteTagExt2(m_nInstanceId, pTaglist); //ERROR_NO errorNo = EipWriteTagRaw(instanceId, pTaglist); string strLog = ""; strLog += "\n写入请求 "; if (errorNo != ERROR_NO.SUCCESS) { strLog += " 失败 标签名:" + tagName + " 实例ID:" + m_nInstanceId.ToString() + " "; switch (errorNo) { case ERROR_NO.ERR_EIP_STOPED: strLog += ("协议栈未开启"); break; case ERROR_NO.ERRI_INVALID_CONNECTION_INSTANCE_SPECIFIED: strLog += ("连接的实例ID与已有的ID重复或超过最大值"); break; case ERROR_NO.ERRI_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: strLog += ("连接的网络路径格式错误,无法检测出来目标IP离线等错误"); break; case ERROR_NO.ERRI_CONNECTION_COUNT_LIMIT_REACHED: strLog += ("达到最大连接数量"); break; case ERROR_NO.ERRI_OUT_OF_MEMORY: strLog += ("内存溢出,缓冲区已满"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: strLog += ("连接的网络地址无效"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_NO_RESPONSE: strLog += ("连接无响应"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_ERROR_RESPONSE: strLog += ("连接响应错误"); break; case ERROR_NO.ERRR_INVALID_DESTINATION: strLog += ("目标标签不存在"); break; case ERROR_NO.ERRR_TAGNAME_TOO_LONG: strLog += ("标签名超过255字节"); break; case ERROR_NO.ERRR_REQUEST_DATA_TOO_LARGE: strLog += ("请求数据超限"); break; case ERROR_NO.ERRR_CONN_CONNECTION_TIMED_OUT: strLog += ("响应超时,请检查设备是否离线"); break; case ERROR_NO.ERRR_TAGNAME_CONVERT_FAILED: strLog += ("标签名解析错误"); break; case ERROR_NO.ERRR_WRITE_DATASIZE_UNCONSISTENT: strLog += ("写入数据长度与标签实际长度不一致"); break; case ERROR_NO.ERRR_SCAN_ERROR: strLog += ("扫描标签信息失败"); break; default: strLog += ("其他错误"); break; } strLog += "\n"; return (10, strLog); } else { return (0, "OK"); } } } /// /// 标签结构 /// public struct StructTag { public string strTagName; public Type tTagType; public int nCount; } /// /// 一次读取多个标签 /// /// 多个标签的列表 /// 多个标签的返回值 /// 函数执行结构值,非零异常,零成功 public (int, string) Read_Tags(List stTagList, out byte[][] pBuf) { pBuf = null; string strType = ""; lock (m_objLock) { if (!m_bConnected) return (-1, "未连接"); if (m_nInstanceId <= 0) { return (-2, "实例ID需大于0"); } if (stTagList == null) return (-3, "标签列表空"); int nNumOfTags = stTagList.Count; if (nNumOfTags < 1) return (-4, "标签列表长度空"); for (int i = 0; i < nNumOfTags; i++) { byte[] tagNameUTF8 = Encoding.UTF8.GetBytes(stTagList[i].strTagName); if (tagNameUTF8.Length > 255) { return (-5, "标签名长度超过255字节"); } if (stTagList[i].nCount < 1) return (-6, "标签读取长度小于1"); } tagTagReadDataBase[] pTaglist = new tagTagReadDataBase[nNumOfTags]; for (int i = 0; i < nNumOfTags; i++) { pTaglist[i].pName = stTagList[i].strTagName; pTaglist[i].nElementCount = stTagList[i].nCount; } tagTagRetValue[] pTagsValue = new tagTagRetValue[nNumOfTags]; pBuf = new byte[nNumOfTags][]; if (pBuf == null) return (-7, "分配内存失败,可能内存不足"); //ERROR_NO errorNo = (ERROR_NO)EipReadTagList(m_nInstanceId, nNumOfTags, pTaglist, ref pTagsValue[0]); ERROR_NO errorNo = (ERROR_NO)EipReadTagListExt(m_nInstanceId, nNumOfTags, pTaglist, ref pTagsValue[0], true); //ERROR_NO errorNo = (ERROR_NO)EipReadTagListRaw(m_nInstanceId, nNumOfTags, pTaglist, ref pTagsValue[0]); string strLog = ""; strLog += "\n读取请求"; if (errorNo != ERROR_NO.SUCCESS) { strLog += " 失败 标签个数:" + nNumOfTags.ToString() + " 实例ID:" + m_nInstanceId.ToString() + " "; switch (errorNo) { case ERROR_NO.ERR_EIP_STOPED: strLog += ("协议栈未开启"); break; case ERROR_NO.ERRI_INVALID_CONNECTION_INSTANCE_SPECIFIED: strLog += ("连接的实例ID与已有的ID重复或超过最大值"); break; case ERROR_NO.ERRI_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: strLog += ("连接的网络路径格式错误,无法检测出来目标IP离线等错误"); break; case ERROR_NO.ERRI_CONNECTION_COUNT_LIMIT_REACHED: strLog += ("达到最大连接数量"); break; case ERROR_NO.ERRI_OUT_OF_MEMORY: strLog += ("内存溢出,缓冲区已满"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: strLog += ("连接的网络地址无效"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_NO_RESPONSE: strLog += ("连接无响应"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_ERROR_RESPONSE: strLog += ("连接响应错误"); break; case ERROR_NO.ERRR_INVALID_DESTINATION: strLog += ("目标标签不存在"); break; case ERROR_NO.ERRR_TAGNAME_TOO_LONG: strLog += ("标签名超过255字节"); break; case ERROR_NO.ERRR_REQUEST_DATA_TOO_LARGE: strLog += ("请求数据超限"); break; case ERROR_NO.ERRR_CONN_CONNECTION_TIMED_OUT: strLog += ("响应超时,请检查设备是否离线"); break; case ERROR_NO.ERRR_TAGNAME_CONVERT_FAILED: strLog += ("标签名解析错误"); break; case ERROR_NO.ERRR_SCAN_ERROR: strLog += ("扫描标签信息失败"); break; default: strLog += ("其他错误"); break; } strLog += "\n"; return (-10, strLog); } else { for (int i = 0; i < nNumOfTags; i++) { strType += "\n标签名:" + pTaglist[i].pName + " 类型:"; switch (pTagsValue[i].pType) { case TAG_TYPE.TAG_TYPE_BOOL: strType += "BOOL"; break; case TAG_TYPE.TAG_TYPE_SINT: strType += "SINT"; break; case TAG_TYPE.TAG_TYPE_INT: strType += "INT"; break; case TAG_TYPE.TAG_TYPE_DINT: strType += "DINT"; break; case TAG_TYPE.TAG_TYPE_LINT: strType += "LINT"; break; case TAG_TYPE.TAG_TYPE_USINT: strType += "USINT"; break; case TAG_TYPE.TAG_TYPE_UINT: strType += "UINT"; break; case TAG_TYPE.TAG_TYPE_UDINT: strType += "UDINT"; break; case TAG_TYPE.TAG_TYPE_ULINT: strType += "ULINT"; break; case TAG_TYPE.TAG_TYPE_REAL: strType += "REAL"; break; case TAG_TYPE.TAG_TYPE_LREAL: strType += "LREAL"; break; case TAG_TYPE.TAG_TYPE_STRING: strType += "STRING"; break; case TAG_TYPE.TAG_TYPE_BYTE: strType += "BYTE"; break; case TAG_TYPE.TAG_TYPE_WORD: strType += "WORD"; break; case TAG_TYPE.TAG_TYPE_DWORD: strType += "DWORD"; break; case TAG_TYPE.TAG_TYPE_LWORD: strType += "LWORD"; break; case TAG_TYPE.TAG_TYPE_STRUCT: strType += "STRUCT"; break; case TAG_TYPE.TAG_TYPE_ARRAY: strType += "ARRAY"; break; default: strType += pTagsValue[i].pType.ToString(); break; } strType += " 元素个数:" + pTaglist[i].nElementCount.ToString(); strType += " 数据长度:" + pTagsValue[i].nDataLength.ToString() + "\n"; unsafe { byte* memBytePtr = (byte*)pTagsValue[i].pData.ToPointer(); pBuf[i] = new byte[pTagsValue[i].nDataLength]; for (int j = 0; j < pTagsValue[i].nDataLength; j++) { pBuf[i][j] = memBytePtr[j]; //string str = ""; ///str += j.ToString() + ": "; //str += "0x" + String.Format("{0:X2}", memBytePtr[j]) + "\n"; } } } } DeleteTagListStru(ref pTagsValue[0], nNumOfTags); //调用接口释放内存 return (0, strType); } } /// /// 一次写多个标签 /// /// 将写入的标签列表 /// 与标签列表对应的值对象 /// public (int, string) Write_Tags(List TagList, List ObjList) { int size = 0; byte[] pBuf = null; int nRet = 0; string strRet = ""; if (!m_bConnected) return (-1, "未连接"); if (m_nInstanceId <= 0) return (-2, "实例ID需大于0"); if (ObjList.Count != TagList.Count) return (-3, "标签列表和数据列表不一致"); int nLen = TagList.Count; int nNumOfTags = TagList.Count; tagTagWriteDataBase[] pTaglist = new tagTagWriteDataBase[nNumOfTags]; try { for (int i = 0; i < nLen; i++) { if (TagList[i].strTagName.Length > 255) return (-4, "标签名称长度超过255字节"); if (TagList[i].tTagType == null) return (-5, "标签类型不能空"); //标签属性 pTaglist[i].pName = TagList[i].strTagName; pTaglist[i].nElementCount = TagList[i].nCount; pTaglist[i].pType = TAG_TYPE.TAG_TYPE_UNDEFINE; pTaglist[i].pData = Marshal.AllocHGlobal(1400); //标签写入的数据 size = 0; string str = TagList[i].tTagType.Name; string[] substrings = { "Boolean", "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Single", "Double", "String" }; bool containsAny = substrings.Any(substring => str.Contains(substring)); if (containsAny) { Type type = ObjList[i].GetType(); if (str != type.Name) return (120, "变量类型不一致"); } if (str == "String") { string data = ObjList[i] as string; pBuf = System.Text.Encoding.Default.GetBytes(data); size = pBuf.Length; if (size > 1400) { return (110, "数据长度超过1400字节,请重新输入"); } } else { if (TagList[i].tTagType.Name == "Boolean") { pBuf = new byte[1]; Type targetType = TagList[i].tTagType; if ((bool)Convert.ChangeType(ObjList[i], targetType)) { pBuf[0] = 1; } else { pBuf[0] = 0; } size = 1; } else { size = Marshal.SizeOf(TagList[i].tTagType); pBuf = StructToBytes(ObjList[i], size); } } //填充数据 for (int j = 0; j < size; j++) { Marshal.WriteByte(pTaglist[i].pData + j * sizeof(byte), pBuf[j]); } pTaglist[i].nDataLength = size; } ERROR_NO errorNo = ERROR_NO.SUCCESS; lock (m_objLock) { //errorNo = EipWriteTagList(m_nInstanceId, nNumOfTags, pTaglist); errorNo = EipWriteTagListExt(m_nInstanceId, nNumOfTags, pTaglist, true); //errorNo = EipWriteTagListRaw(m_nInstanceId, nNumOfTags, pTaglist); } string strLog = ""; strLog += "\n写入请求"; if (errorNo != ERROR_NO.SUCCESS) { strLog += " 失败 标签个数:" + nNumOfTags.ToString() + " 实例ID:" + m_nInstanceId.ToString() + " "; switch (errorNo) { case ERROR_NO.ERR_EIP_STOPED: strLog += ("协议栈未开启"); break; case ERROR_NO.ERRI_INVALID_CONNECTION_INSTANCE_SPECIFIED: strLog += ("连接的实例ID与已有的ID重复或超过最大值"); break; case ERROR_NO.ERRI_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: strLog += ("连接的网络路径格式错误,无法检测出来目标IP离线等错误"); break; case ERROR_NO.ERRI_CONNECTION_COUNT_LIMIT_REACHED: strLog += ("达到最大连接数量"); break; case ERROR_NO.ERRI_OUT_OF_MEMORY: strLog += ("内存溢出,缓冲区已满"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_INVALID_NETWORK_PATH: strLog += ("连接的网络地址无效"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_NO_RESPONSE: strLog += ("连接无响应"); break; case ERROR_NO.ERRR_CONN_CONFIG_FAILED_ERROR_RESPONSE: strLog += ("连接响应错误"); break; case ERROR_NO.ERRR_INVALID_DESTINATION: strLog += ("目标标签不存在"); break; case ERROR_NO.ERRR_TAGNAME_TOO_LONG: strLog += ("标签名超过255字节"); break; case ERROR_NO.ERRR_REQUEST_DATA_TOO_LARGE: strLog += ("请求数据超限"); break; case ERROR_NO.ERRR_CONN_CONNECTION_TIMED_OUT: strLog += ("响应超时,请检查设备是否离线"); break; case ERROR_NO.ERRR_TAGNAME_CONVERT_FAILED: strLog += ("标签名解析错误"); break; case ERROR_NO.ERRR_WRITE_DATASIZE_UNCONSISTENT: strLog += ("写入数据长度与标签实际长度不一致"); break; case ERROR_NO.ERRR_SCAN_ERROR: strLog += ("扫描标签信息失败"); break; default: strLog += ("其他错误"); break; } strLog += "\n"; strRet = strLog; nRet = -10; } else { //成功 strRet = "OK"; nRet = 0; } } catch (Exception ex) { nRet = 120; strRet = ex.ToString(); } finally { for (int i = 0; i < nLen; i++) { if (pTaglist[i].pData != ((IntPtr)0)) { Marshal.FreeHGlobal(pTaglist[i].pData); pTaglist[i].pData = (IntPtr)0; } } } return (nRet, strRet); } /// /// 一次读取Bool标签或Bool数组标签 /// /// 标签的名称 /// 读取的标签个数 /// 相应标签的返回值 /// 函数返回结果 public (int, string) Read_Bool_Tag(string strTagName, int nCount, out bool[] boolBuf) { byte[] pBuf = null; boolBuf = null; int nRet = 0; string strRet = ""; (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet != 0) return (nRet, strRet); return Parse_Bool_Tag(pBuf, out boolBuf); } /// /// 一次写入Bool标签或Bool数组标签 /// /// 标签的名称 /// 标签个数 /// 相应标签的写入值 /// 函数返回结果 public (int, string) Write_Bool_Tag(string strTagName, int nCount, bool[] boolBuf) { byte[] pBuf = null; int nRet = 0; string strRet = ""; pBuf = BoolToBytes(boolBuf); if (pBuf == null) return (1, "缓存区空"); (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } //将转换为Byte数组 public static byte[] BoolToBytes(bool[] boolBuf) { if (boolBuf==null) return null; int nNum = 0; nNum = boolBuf.Length; if (nNum < 1) return null; byte[] bytes = new byte[nNum]; for (int i = 0; i < nNum; i++) { if (boolBuf[i]) bytes[i] = 1; else bytes[i] = 0; } return bytes; } public (int, string) Parse_Bool_Tag(byte[] pBuf, out bool[] boolBuf) { boolBuf = null; int nNum = 0; nNum = pBuf.Length; if (nNum < 1) return (1, "Parse Failed"); boolBuf = new bool[nNum]; for (int i = 0; i < nNum; i++) { byte[] databuf = new byte[1] {0}; databuf[0] = pBuf[i]; bool iTemp = BitConverter.ToBoolean(databuf, 0); boolBuf[i] = iTemp; } return (0, "OK"); } public (int, string) Read_Byte_Tag(string strTagName, int nCount, out byte[] pBuf) { return Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); } public (int, string) Write_Byte_Tag(string strTagName, int nCount, byte[] pBuf) { return Write_Tag(strTagPrefix + strTagName, nCount, pBuf); } public (int, string) Read_SInt_Tag(string strTagName, int nCount, out sbyte[] sintBuf) { byte[] pBuf = null; sintBuf = null; int nRet = 0; string strRet = ""; (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet != 0) return (nRet, strRet); return Parse_SInt_Tag(pBuf, out sintBuf); } public (int, string) Write_SInt_Tag(string strTagName, int nCount, sbyte[] DataBuf) { byte[] pBuf = null; int nRet = 0; string strRet = ""; pBuf = SByteToBytes(DataBuf); if (pBuf == null) return (1, "pBuf is Null"); (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } //将转换为Byte数组 public static byte[] SByteToBytes(sbyte[] DataBuf) { if (DataBuf == null || DataBuf.Length <= 0) return null; int nNum = 0; nNum = DataBuf.Length; if (nNum < 1) return null; byte[] bytes = new byte[nNum]; for (int i = 0; i < nNum; i++) { byte[] databuf = BitConverter.GetBytes(DataBuf[i]); bytes[i] = databuf[0]; } return bytes; } public (int, string) Parse_SInt_Tag(byte[] pBuf, out sbyte[] sintBuf) { sintBuf = null; int nNum = 0; nNum = pBuf.Length; if (nNum < 1) return (1, "Parse Failed"); sintBuf = new sbyte[nNum]; for (int i = 0; i < nNum; i++) { sintBuf[i] = (sbyte)pBuf[i]; } return (0, "OK"); } public (int, string) Read_String_Tag(string strTagName, int nCount, out string strBuf) { int nRet=0; string strRet = ""; byte[] pBuf = null; strBuf = ""; (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet == 0) strBuf = System.Text.Encoding.UTF8.GetString(pBuf); return (nRet, strRet); } public (int, string) Write_String_Tag(string strTagName, int nCount, string strBuf) { int nRet = 0; string strRet = ""; byte[] pBuf = null; if (string.IsNullOrEmpty(strBuf)) return (1, "string is null"); pBuf = System.Text.Encoding.UTF8.GetBytes(strBuf); if (pBuf == null || pBuf.Length == 0 ) return (2, "pBuf is null"); (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } public (int, string) Parse_String_Tag(byte[] pBuf, out string strBuf) { int nRet = 0; string strRet = ""; strBuf = ""; strBuf = System.Text.Encoding.UTF8.GetString(pBuf); return (nRet, strRet); } public (int, string) Read_Word_Tag(string strTagName, int nCount, out ushort[] wordBuf) { return Read_UInt_Tag(strTagName, nCount, out wordBuf); } public (int, string) Write_Word_Tag(string strTagName, int nCount, ushort[] wordBuf) { return Write_UInt_Tag(strTagName, nCount, wordBuf); } public (int, string) Read_DWord_Tag(string strTagName, int nCount, out uint[] dwordBuf) { return Read_UDInt_Tag(strTagName, nCount, out dwordBuf); } public (int, string) Write_DWord_Tag(string strTagName, int nCount, uint[] dwordBuf) { return Write_UDInt_Tag(strTagName, nCount, dwordBuf); } public (int, string) Read_LWord_Tag(string strTagName, int nCount, out ulong[] lwordBuf) { return Read_ULInt_Tag(strTagName, nCount, out lwordBuf); } public (int, string) Write_LWord_Tag(string strTagName, int nCount, ulong[] lwordBuf) { return Write_ULInt_Tag(strTagName, nCount, lwordBuf); } /// /// read 16bit int /// /// /// /// /// public (int, string) Read_Int_Tag(string strTagName, int nCount, out short[] intBuf) { byte[] pBuf = null; intBuf = null; int nRet=0; string strRet = ""; (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet != 0) return (nRet, strRet); return Parse_Int_Tag(pBuf, out intBuf); } public (int, string) Parse_Int_Tag(byte[] pBuf, out short[] intBuf) { intBuf = null; int nNum = 0; nNum = pBuf.Length / 2; if (nNum < 1) return (1, "Parse Failed"); intBuf = new short[nNum]; for (int i = 0; i < nNum; i++) { byte[] databuf = new byte[2] { 0, 0 }; databuf[0] = pBuf[i * 2]; databuf[1] = pBuf[i * 2 + 1]; short iTemp = BitConverter.ToInt16(databuf, 0); intBuf[i] = iTemp; } return (0, "OK"); } public (int, string) Write_Int_Tag(string strTagName, int nCount, short[] DataBuf) { byte[] pBuf = null; int nRet = 0; string strRet = ""; pBuf = ShortToBytes(DataBuf); if (pBuf == null ) return (1, "pBuf is Null"); (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } //将转换为Byte数组 public static byte[] ShortToBytes(short[] DataBuf) { if (DataBuf == null || DataBuf.Length<=0) return null; int nNum = 0; //int size = Marshal.SizeOf(typeof(short)); //int size = sizeof(short); nNum = DataBuf.Length; if (nNum < 1) return null; byte[] bytes = new byte[nNum*2]; for (int i = 0; i < nNum; i++) { byte[] databuf = BitConverter.GetBytes(DataBuf[i]); bytes[i * 2] = databuf[0]; bytes[i * 2 + 1] = databuf[1]; } return bytes; } /// /// 16bit uint /// /// /// /// /// public (int, string) Read_UInt_Tag(string strTagName, int nCount, out UInt16[] uintBuf) { byte[] pBuf = null; uintBuf = null; int nRet = 0; string strRet = ""; (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet != 0) return (nRet, strRet); return Parse_UInt_Tag(pBuf, out uintBuf); } public (int, string) Write_UInt_Tag(string strTagName, int nCount, ushort[] DataBuf) { byte[] pBuf = null; int nRet = 0; string strRet = ""; pBuf = UShortToBytes(DataBuf); if (pBuf == null) return (1, "pBuf is Null"); (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } //将转换为Byte数组 public static byte[] UShortToBytes(ushort[] DataBuf) { if (DataBuf == null || DataBuf.Length <= 0) return null; int nNum = 0; //int size = Marshal.SizeOf(typeof(short)); //int size = sizeof(short); nNum = DataBuf.Length; if (nNum < 1) return null; byte[] bytes = new byte[nNum*2]; for (int i = 0; i < nNum; i++) { byte[] databuf = BitConverter.GetBytes(DataBuf[i]); bytes[i * 2] = databuf[0]; bytes[i * 2 + 1] = databuf[1]; } return bytes; } public (int, string) Parse_UInt_Tag(byte[] pBuf, out UInt16[] uintBuf) { uintBuf = null; int nNum = 0; nNum = pBuf.Length / 2; if (nNum < 1) return (1, "Parse Failed"); uintBuf = new UInt16[nNum]; for (int i = 0; i < nNum; i++) { byte[] databuf = new byte[2] { 0, 0 }; databuf[0] = pBuf[i * 2]; databuf[1] = pBuf[i * 2 + 1]; UInt16 iTemp = BitConverter.ToUInt16(databuf, 0); uintBuf[i] = iTemp; } return (0, "OK"); } /// /// 32bits int /// /// /// /// /// public (int, string) Read_DInt_Tag(string strTagName, int nCount, out int[] intBuf) { byte[] pBuf = null; intBuf = null; int nRet = 0; string strRet = ""; (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet != 0) return (nRet, strRet); return Parse_DInt_Tag(pBuf, out intBuf); } public (int, string) Write_DInt_Tag(string strTagName, int nCount, int[] DataBuf) { byte[] pBuf = null; int nRet = 0; string strRet = ""; pBuf = DIntToBytes(DataBuf); if (pBuf == null) return (1, "pBuf is Null"); (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } //将转换为Byte数组 public static byte[] DIntToBytes(int[] DataBuf) { if (DataBuf == null || DataBuf.Length <= 0) return null; int nNum = 0; nNum = DataBuf.Length; if (nNum < 1) return null; byte[] bytes = new byte[nNum*4]; for (int i = 0; i < nNum; i++) { byte[] databuf = BitConverter.GetBytes(DataBuf[i]); bytes[i * 4] = databuf[0]; bytes[i * 4 + 1] = databuf[1]; bytes[i * 4 + 2] = databuf[2]; bytes[i * 4 + 3] = databuf[3]; } return bytes; } public (int, string) Parse_DInt_Tag(byte[] pBuf, out int[] intBuf) { intBuf = null; int nNum = 0; nNum = pBuf.Length / 4; if (nNum < 1) return (1, "Parse Failed"); intBuf = new int[nNum]; for (int i = 0; i < nNum; i++) { byte[] databuf = new byte[4] { 0, 0, 0, 0 }; databuf[0] = pBuf[i * 4]; databuf[1] = pBuf[i * 4 + 1]; databuf[2] = pBuf[i * 4 + 2]; databuf[3] = pBuf[i * 4 + 3]; int iTemp = BitConverter.ToInt32(databuf, 0); intBuf[i] = iTemp; } return (0, "OK"); } /// /// 无符号32位整数 /// /// /// /// /// public (int, string) Read_UDInt_Tag(string strTagName, int nCount, out uint[] uintBuf) { byte[] pBuf = null; uintBuf = null; int nRet = 0; string strRet = ""; (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet != 0) return (nRet, strRet); return Parse_UDInt_Tag(pBuf, out uintBuf); } public (int, string) Write_UDInt_Tag(string strTagName, int nCount, uint[] DataBuf) { byte[] pBuf = null; int nRet = 0; string strRet = ""; pBuf = UDIntToBytes(DataBuf); if (pBuf == null) return (1, "pBuf is Null"); (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } //将转换为Byte数组 public static byte[] UDIntToBytes(uint[] DataBuf) { if (DataBuf == null || DataBuf.Length <= 0) return null; int nNum = 0; nNum = DataBuf.Length; if (nNum < 1) return null; byte[] bytes = new byte[nNum * 4]; for (int i = 0; i < nNum; i++) { byte[] databuf = BitConverter.GetBytes(DataBuf[i]); bytes[i * 4] = databuf[0]; bytes[i * 4 + 1] = databuf[1]; bytes[i * 4 + 2] = databuf[2]; bytes[i * 4 + 3] = databuf[3]; } return bytes; } public (int, string) Parse_UDInt_Tag(byte[] pBuf, out uint[] uintBuf) { uintBuf = null; int nNum = 0; nNum = pBuf.Length / 4; if (nNum < 1) return (1, "Parse Failed"); uintBuf = new uint[nNum]; for (int i = 0; i < nNum; i++) { byte[] databuf = new byte[4] { 0, 0, 0, 0 }; databuf[0] = pBuf[i * 4]; databuf[1] = pBuf[i * 4 + 1]; databuf[2] = pBuf[i * 4 + 2]; databuf[3] = pBuf[i * 4 + 3]; uint iTemp = BitConverter.ToUInt32(databuf, 0); uintBuf[i] = iTemp; } return (0, "OK"); } public (int, string) Read_LInt_Tag(string strTagName, int nCount, out long[] longBuf) { byte[] pBuf = null; longBuf = null; int nRet = 0; string strRet = ""; (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet != 0) return (nRet, strRet); return Parse_LInt_Tag(pBuf, out longBuf); } public (int, string) Write_LInt_Tag(string strTagName, int nCount, long[] DataBuf) { byte[] pBuf = null; int nRet = 0; string strRet = ""; pBuf = LIntToBytes(DataBuf); if (pBuf == null) return (1, "pBuf is Null"); (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } //将转换为Byte数组 public static byte[] LIntToBytes(long[] DataBuf) { if (DataBuf == null || DataBuf.Length <= 0) return null; int nNum = 0; nNum = DataBuf.Length; if (nNum < 1) return null; byte[] bytes = new byte[nNum * 8]; for (int i = 0; i < nNum; i++) { byte[] databuf = BitConverter.GetBytes(DataBuf[i]); bytes[i * 4] = databuf[0]; bytes[i * 4 + 1] = databuf[1]; bytes[i * 4 + 2] = databuf[2]; bytes[i * 4 + 3] = databuf[3]; bytes[i * 4 + 4] = databuf[4]; bytes[i * 4 + 5] = databuf[5]; bytes[i * 4 + 6] = databuf[6]; bytes[i * 4 + 7] = databuf[7]; } return bytes; } public (int, string) Parse_LInt_Tag(byte[] pBuf, out long[] longBuf) { longBuf = null; int nNum = 0; nNum = pBuf.Length / 8; if (nNum < 1) return (1, "Parse Failed"); longBuf = new long[nNum]; for (int i = 0; i < nNum; i++) { byte[] databuf = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }; databuf[0] = pBuf[i * 4]; databuf[1] = pBuf[i * 4 + 1]; databuf[2] = pBuf[i * 4 + 2]; databuf[3] = pBuf[i * 4 + 3]; databuf[4] = pBuf[i * 4 + 4]; databuf[5] = pBuf[i * 4 + 5]; databuf[6] = pBuf[i * 4 + 6]; databuf[7] = pBuf[i * 4 + 7]; long iTemp = BitConverter.ToInt64(databuf, 0); longBuf[i] = iTemp; } return (0, "OK"); } /// /// 无符号64整数 /// /// /// /// /// public (int, string) Read_ULInt_Tag(string strTagName, int nCount, out ulong[] ulongBuf) { byte[] pBuf = null; ulongBuf = null; int nRet = 0; string strRet = ""; (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet != 0) return (nRet, strRet); return Parse_ULInt_Tag(pBuf, out ulongBuf); } public (int, string) Write_ULInt_Tag(string strTagName, int nCount, ulong[] DataBuf) { byte[] pBuf = null; int nRet = 0; string strRet = ""; pBuf = ULIntToBytes(DataBuf); if (pBuf == null) return (1, "pBuf is Null"); (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } //将转换为Byte数组 public static byte[] ULIntToBytes(ulong[] DataBuf) { if (DataBuf == null || DataBuf.Length <= 0) return null; int nNum = 0; nNum = DataBuf.Length; if (nNum < 1) return null; byte[] bytes = new byte[nNum * 8]; for (int i = 0; i < nNum; i++) { byte[] databuf = BitConverter.GetBytes(DataBuf[i]); bytes[i * 4] = databuf[0]; bytes[i * 4 + 1] = databuf[1]; bytes[i * 4 + 2] = databuf[2]; bytes[i * 4 + 3] = databuf[3]; bytes[i * 4 + 4] = databuf[4]; bytes[i * 4 + 5] = databuf[5]; bytes[i * 4 + 6] = databuf[6]; bytes[i * 4 + 7] = databuf[7]; } return bytes; } public (int, string) Parse_ULInt_Tag(byte[] pBuf, out ulong[] ulongBuf) { ulongBuf = null; int nNum = 0; nNum = pBuf.Length / 8; if (nNum < 1) return (1, "Parse Failed"); ulongBuf = new ulong[nNum]; for (int i = 0; i < nNum; i++) { byte[] databuf = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }; databuf[0] = pBuf[i * 4]; databuf[1] = pBuf[i * 4 + 1]; databuf[2] = pBuf[i * 4 + 2]; databuf[3] = pBuf[i * 4 + 3]; databuf[4] = pBuf[i * 4 + 4]; databuf[5] = pBuf[i * 4 + 5]; databuf[6] = pBuf[i * 4 + 6]; databuf[7] = pBuf[i * 4 + 7]; ulong iTemp = BitConverter.ToUInt64(databuf, 0); ulongBuf[i] = iTemp; } return (0, "OK"); } public (int, string) Read_Real_Tag(string strTagName, int nCount, out float[] floatBuf) { floatBuf = null; byte[] pBuf = null; int nRet = 0; string strRet = ""; (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet != 0) return (nRet, strRet); return Parse_Real_Tag(pBuf, out floatBuf); } public (int, string) Write_Real_Tag(string strTagName, int nCount, float[] DataBuf) { byte[] pBuf = null; int nRet = 0; string strRet = ""; pBuf = RealToBytes(DataBuf); if (pBuf == null) return (1, "pBuf is Null"); (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } //将转换为Byte数组 public static byte[] RealToBytes(float[] DataBuf) { if (DataBuf == null || DataBuf.Length <= 0) return null; int nNum = 0; nNum = DataBuf.Length; if (nNum < 1) return null; byte[] bytes = new byte[nNum * 4]; for (int i = 0; i < nNum; i++) { byte[] databuf = BitConverter.GetBytes(DataBuf[i]); bytes[i * 4] = databuf[0]; bytes[i * 4 + 1] = databuf[1]; bytes[i * 4 + 2] = databuf[2]; bytes[i * 4 + 3] = databuf[3]; } return bytes; } public (int, string) Parse_Real_Tag(byte[] pBuf, out float[] floatBuf) { floatBuf = null; int nNum = 0; nNum = pBuf.Length / 4; floatBuf = new float[nNum]; if (nNum < 1) return (1, "Parse Failed"); for (int i = 0; i < nNum; i++) { byte[] databuf = new byte[4] { 0, 0, 0, 0 }; databuf[0] = pBuf[i * 4]; databuf[1] = pBuf[i * 4 + 1]; databuf[2] = pBuf[i * 4 + 2]; databuf[3] = pBuf[i * 4 + 3]; float fTemp = BitConverter.ToSingle(databuf, 0); floatBuf[i] = fTemp; } return (0, "OK"); } public (int, string) Read_LReal_Tag(string strTagName, int nCount, out double[] doubleBuf) { doubleBuf = null; byte[] pBuf = null; int nRet = 0; string strRet = ""; (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet != 0) return (nRet, strRet); return Parse_LReal_Tag(pBuf, out doubleBuf); } public (int, string) Write_LReal_Tag(string strTagName, int nCount, double[] DataBuf) { byte[] pBuf = null; int nRet = 0; string strRet = ""; pBuf = LRealToBytes(DataBuf); if (pBuf == null) return (1, "pBuf is Null"); (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } //将转换为Byte数组 public static byte[] LRealToBytes(double[] DataBuf) { if (DataBuf == null || DataBuf.Length <= 0) return null; int nNum = 0; nNum = DataBuf.Length; if (nNum < 1) return null; byte[] bytes = new byte[nNum * 8]; for (int i = 0; i < nNum; i++) { byte[] databuf = BitConverter.GetBytes(DataBuf[i]); bytes[i * 4] = databuf[0]; bytes[i * 4 + 1] = databuf[1]; bytes[i * 4 + 2] = databuf[2]; bytes[i * 4 + 3] = databuf[3]; bytes[i * 4 + 4] = databuf[4]; bytes[i * 4 + 5] = databuf[5]; bytes[i * 4 + 6] = databuf[6]; bytes[i * 4 + 7] = databuf[7]; } return bytes; } public (int, string) Parse_LReal_Tag(byte[] pBuf, out double[] doubleBuf) { doubleBuf = null; int nNum = 0; nNum = pBuf.Length / 8; if (nNum < 1) return (1, "Parse Failed"); doubleBuf = new double[nNum]; for (int i = 0; i < nNum; i++) { byte[] databuf = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }; databuf[0] = pBuf[i * 8]; databuf[1] = pBuf[i * 8 + 1]; databuf[2] = pBuf[i * 8 + 2]; databuf[3] = pBuf[i * 8 + 3]; databuf[4] = pBuf[i * 8 + 4]; databuf[5] = pBuf[i * 8 + 5]; databuf[6] = pBuf[i * 8 + 6]; databuf[7] = pBuf[i * 8 + 7]; double dTemp = BitConverter.ToDouble(databuf, 0); doubleBuf[i] = dTemp; } return (0, "OK"); } #region 对象与字节数组转化 //将结构体类型转换为Byte数组 public static byte[] StructToBytes(object structObj, int size) { byte[] bytes = new byte[size]; IntPtr structPtr = Marshal.AllocHGlobal(size); try { //将结构体拷到分配好的内存空间 Marshal.StructureToPtr(structObj, structPtr, false); //从内存空间拷贝到byte 数组 Marshal.Copy(structPtr, bytes, 0, size); } finally { //释放内存空间 Marshal.FreeHGlobal(structPtr); } return bytes; } //将Byte转换为结构体类型 public static object ByteToStruct(byte[] bytes, Type type) { int size = Marshal.SizeOf(type); if (type.Name == "Boolean") size = 1; if (size > bytes.Length) { return null; } //分配结构体内存空间 IntPtr structPtr = Marshal.AllocHGlobal(size); object obj = null; try { //将byte数组拷贝到分配好的内存空间 Marshal.Copy(bytes, 0, structPtr, size); //将内存空间转换为目标结构体 obj = Marshal.PtrToStructure(structPtr, type); } finally { //释放内存空间 Marshal.FreeHGlobal(structPtr); } return obj; } //将Byte转换为结构体类型 public static Object ByteToStruct2(byte[] bytes, Type type) { int size = Marshal.SizeOf(type); if (type.Name == "Boolean") size = 1; if (size > bytes.Length) { return null; } //分配结构体内存空间 IntPtr structPtr = Marshal.AllocHGlobal(size); object obj = null; try { //将byte数组拷贝到分配好的内存空间 Marshal.Copy(bytes, 0, structPtr, size); //将内存空间转换为目标结构体 obj = Marshal.PtrToStructure(structPtr, type); } finally { //释放内存空间 Marshal.FreeHGlobal(structPtr); } return obj; } public static T ConvertBytesToStruct(byte[] bytes) { // 将字节数组转换为结构体 GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); T myStruct = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); handle.Free(); return myStruct; } #endregion 对象与字节数组转化 /// /// 一次读取单个标签 /// /// 需要读取的标签结构 /// 需要读取的标签名 /// 读取标签的个数 /// 返回相应标签值对象 /// public (int, string) Read_SingleTag(string strTagName, int nCount, out T outObj, Control uiControl) { // 初始化输出参数 outObj = default(T); byte[] pBuf = null; int nRet = 0; string strRet = ""; try { // 创建一个标志变量,用于判断是否需要显示提示框 bool isProcessingDialogShown = false; // 启动一个后台任务执行核心逻辑 Task<(int, string)> readTask = Task.Run(() => { return Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); }); // 启动一个计时器任务,用于检测是否超过 5 秒 Task delayTask = Task.Delay(5000); // 等待两个任务中的任意一个完成 Task completedTask = Task.WhenAny(readTask, delayTask).Result; if (completedTask == delayTask) { // 如果超时,则显示提示框 ShowProcessingDialog(uiControl); isProcessingDialogShown = true; // 继续等待读取任务完成 readTask.Wait(); } // 获取读取结果 (nRet, strRet) = readTask.Result; // 检查类型并处理数据 string str = typeof(T).Name; string[] substrings = { "Boolean", "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Single", "Double", "String" }; bool containsAny = substrings.Any(substring => str.Contains(substring)); if (containsAny) { if (str != strRet) return (120, "变量类型不一致"); } if (str == "String") { outObj = (T)(object)System.Text.Encoding.UTF8.GetString(pBuf); } else { outObj = (T)ByteToStruct(pBuf, typeof(T)); } // 如果显示了提示框,则关闭它 if (isProcessingDialogShown) { CloseProcessingDialog(uiControl); } } catch (Exception ex) { // 异常处理 return (110, ex.ToString()); } return (nRet, "OK"); } private Form _processingForm; private void ShowProcessingDialog(Control uiControl) { if (uiControl == null) { throw new ArgumentNullException(nameof(uiControl), "UI 控件不能为空。"); } // 确保在主线程上更新 UI if (uiControl.InvokeRequired) { uiControl.Invoke(new Action(() => ShowProcessingDialog(uiControl))); return; } // 创建并显示提示框 Form processingForm = new Form { Text = "请稍候", Size = new Size(300, 100), StartPosition = FormStartPosition.CenterScreen, FormBorderStyle = FormBorderStyle.FixedDialog, ControlBox = false, TopMost = true }; Label label = new Label { Text = "正在读取中,请稍后...", Dock = DockStyle.Fill, TextAlign = ContentAlignment.MiddleCenter }; processingForm.Controls.Add(label); processingForm.Show(); // 保存提示框引用以便后续关闭 _processingForm = processingForm; } private void CloseProcessingDialog(Control uiControl) { if (uiControl == null) { return; } // 确保在主线程上更新 UI if (uiControl.InvokeRequired) { uiControl.Invoke(new Action(() => CloseProcessingDialog(uiControl))); return; } // 关闭提示框 _processingForm?.Close(); _processingForm = null; } /* public (int, string) Read_SingleTag(string strTagName, int nCount, out T outObj) { outObj = default(T); byte[] pBuf = null; int nRet = 0; string strRet = ""; try { (nRet, strRet) = Read_Tag(strTagPrefix + strTagName, nCount, out pBuf); if (nRet != 0) return (nRet, strRet); string str = typeof(T).Name; string[] substrings = { "Boolean", "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Single", "Double", "String" }; bool containsAny = substrings.Any(substring => str.Contains(substring)); if (containsAny) { if (str != strRet) return (120, "变量类型不一致"); } if (str == "String") { outObj = (T)(object)System.Text.Encoding.UTF8.GetString(pBuf); return (0, "OK"); } outObj = (T)ByteToStruct(pBuf, typeof(T)); } catch (Exception ex) { return (110, ex.ToString()); } return (0, "OK"); }*/ public (int, string) Write_SingleTag(string strTagName, int nCount, T inObj) { byte[] pBuf = null; int nRet = 0; string strRet = ""; int size = 0; try { string str = typeof(T).Name; string[] substrings = { "Boolean", "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Single", "Double", "String" }; bool containsAny = substrings.Any(substring => str.Contains(substring)); if (containsAny) { Type type = inObj.GetType(); if (str != type.Name) return (120, "变量类型不一致"); } if (str == "String") { //size = inObj.ToString().Length + 1; string wtStr= inObj as string; pBuf = System.Text.Encoding.Default.GetBytes(wtStr); size = pBuf.Length; } else { if (typeof(T).Name == "Boolean") { //pBuf = new byte[1]; //Type targetType = typeof(T); //if ((bool)Convert.ChangeType(inObj, targetType)) //{ // pBuf[0] = 1; //} //else //{ // pBuf[0] = 0; //} size = 1; } else { size = Marshal.SizeOf(typeof(T)); } pBuf = StructToBytes(inObj, size); } (nRet, strRet) = Write_Tag(strTagPrefix + strTagName, nCount, pBuf); return (nRet, strRet); } catch (Exception ex) { return (110, ex.ToString()); } } /// /// 一次读取多个标签 /// /// 需要读取的标签列表信息 /// 返回的相应标签对象 /// 执行是否成功,非0不成功,以及显示相应的失败信息 public (int, string) Read_MultiTags(List stTagList, out List outObj) { outObj = new List(); byte[][] pBuf = null; int nRet = 0; string strRet = ""; int nLen = stTagList.Count; List TagList=new List(); try { foreach(StructTag tag in stTagList) { TagList.Add(new StructTag {strTagName= strTagPrefix + tag.strTagName,tTagType=tag.tTagType,nCount=tag.nCount}); } (nRet, strRet) = Read_Tags(TagList, out pBuf); if (nRet != 0) return (nRet, strRet); for (int i = 0; i < nLen; i++) { //需要调用的方法 //MethodInfo mi = typeof(Inovance_EIP).GetMethod("ByteToStruct"); //该方法的泛型类型Type->typeof(int) //MethodInfo miConstructed = mi.MakeGenericMethod(strTagList[i].TagType); //var arg = { pBuf[i]}; //执行调用 //miConstructed.Invoke(null, args); //outObj.Add(Convert.ChangeType(ByteToStruct2(pBuf[i], targetType), targetType)); Type targetType = TagList[i].tTagType; if (targetType != null) { object obj = ByteToStruct(pBuf[i], targetType); //if (obj != null) outObj.Add(obj); } } } catch (Exception ex) { return (110, ex.ToString()); } return (0, "OK"); } /// /// 一次写多个标签 /// /// 需要写入的标签列表信息 /// 写入的相应标签对象 /// 执行是否成功,非0不成功,以及显示相应的失败信息 public (int, string) Write_MultiTags(List stTagList, List ObjList) { int nRet = 0; string strRet = ""; int nLen = stTagList.Count; if (ObjList.Count != nLen) return (10, "标签列表和对象列表长度不一致"); List TagList = new List(); try { foreach (StructTag tag in stTagList) { TagList.Add(new StructTag { strTagName = strTagPrefix + tag.strTagName, tTagType = tag.tTagType, nCount = tag.nCount }); } (nRet, strRet) = Write_Tags(TagList, ObjList); return (nRet, strRet); } catch (Exception ex) { return (110, ex.ToString()); } } #region 清除标签缓存 /// /// 清除标签缓存 /// public void Clear_TagCache() { ResetTagInfo(); } #endregion 清除标签缓存 } }