using System; using System.IO; using Mesnac.Equips; using Mesnac.Equips.BaseInfo; using System.Runtime.InteropServices; namespace Mesnac.Equip.AllenBradley.AB500.Default { public class Equip : BaseEquip { private IntPtr structToIntPtr(T[] lst) { int nSizeOfT = Marshal.SizeOf(typeof(T)); int nSizeOfIntPtr = Marshal.SizeOf(typeof(IntPtr)); IntPtr Result = Marshal.AllocHGlobal(nSizeOfIntPtr * lst.Length); for (int i = 0; i < lst.Length; i++) { Marshal.StructureToPtr(lst[i], (IntPtr)((UInt32)Result + i * nSizeOfIntPtr), true); } return Result; } private T[] IntPtrTostruct(IntPtr p, T[] lst) { int nSizeOfIntPtr = Marshal.SizeOf(typeof(IntPtr)); for (int i = 0; i < lst.Length; i++) { T r = (T)Marshal.PtrToStructure((IntPtr)((UInt32)p + i * nSizeOfIntPtr), typeof(T)); lst[i] = r; } return lst; } private string getDriveNameFileFullName() { return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log", "AB500.DriverName.bin"); } private void saveDriveName(string name) { if (string.IsNullOrWhiteSpace(name)) { return; } string path = getDriveNameFileFullName(); FileInfo fi = new FileInfo(path); if (!fi.Directory.Exists) { fi.Directory.Create(); } if (fi.Exists) { fi.Delete(); } System.IO.StreamWriter sw = new System.IO.StreamWriter(fi.FullName, false); sw.WriteLine(name); sw.Close(); } private string getDriveName() { string path = getDriveNameFileFullName(); FileInfo fi = new FileInfo(path); if (!fi.Directory.Exists) { fi.Directory.Create(); } if (!fi.Exists) { return string.Empty; } System.IO.StreamReader sw = new System.IO.StreamReader(fi.FullName); string ss = sw.ReadToEnd(); sw.Close(); return ss; } public override bool Open() { lock (this) { try { this.State = false; Logger.Instance.Info("DTL_INIT"); int iResult = 0; uint id = 0; iResult = DTL32.DTL_INIT(2048); Logger.Instance.Info("DTL_INIT Result=" + iResult.ToString()); if ((iResult != 0) && (iResult != 39)) // 39已经初始化 { this.State = false; return this.State; } string driveName = getDriveName(); if (string.IsNullOrWhiteSpace(driveName)) { Logger.Instance.Info("get szDriverName"); uint drivers = 0; DTL32.DtlDriver[] dtlDriver = new DTL32.DtlDriver[16]; IntPtr pDriver = structToIntPtr(dtlDriver); Logger.Instance.Info("DTL_DRIVER_LIST"); iResult = DTL32.DTL_DRIVER_LIST(pDriver, ref drivers, 1000); Logger.Instance.Info("DTL_DRIVER_LIST Result=" + iResult.ToString()); dtlDriver = IntPtrTostruct(pDriver, dtlDriver); Logger.Instance.Info("IntPtrTostruct"); driveName = new string(dtlDriver[id].szDriverName); Logger.Instance.Info("szDriverName=" + driveName); saveDriveName(driveName); Marshal.FreeHGlobal(pDriver); Logger.Instance.Info("FreeHGlobal"); if ((iResult != 0)) { this.State = false; return this.State; } } iResult = DTL32.DTL_DRIVER_OPEN(id, driveName, 5000); Logger.Instance.Info("DTL_DRIVER_OPEN Result=" + iResult.ToString()); if ((iResult == 0) || (iResult == 47)) // 47已经连接上 { this.State = true; } return this.State; } catch (Exception ex) { ICSharpCode.Core.LoggingService.Error(String.Format("打开PLC(AB500)设备连接失败-({0})!", ex.Message)); this.State = false; return this.State; } } } /// /// PLC数据读取方法 /// /// 要读取的块号 /// 要读取的起始字 /// 要读取的长度,最大255,超过255则不读取 /// /// public override bool Read(string block, int start, int len, out object[] buff) { lock (this) { buff = new object[len]; try { if (len > 256) { for (int i = 0; i < len; i++) { buff[i] = 0; } base.State = false; return false; } int maxOneLen = 100; //单次允许读取的最大长度,AB500限制为100个字 int count = len / maxOneLen; //要读取的次数 int mod = len % maxOneLen; //剩余的长度 bool flag = true; //保存读取标志 for (int i = 0; i < count; i++) { object[] _buff = new object[maxOneLen]; flag = this.ReadByLen(block, start + i * maxOneLen, maxOneLen, out _buff); if (flag == false) { base.State = flag; return false; } for (int k = i * maxOneLen; k < (i + 1) * maxOneLen; k++) { buff[k] = _buff[k - i * maxOneLen]; } } if (mod > 0) { object[] _buff = new object[mod]; flag = this.ReadByLen(block, start + count * maxOneLen, mod, out _buff); if (flag == false) { base.State = flag; return false; } for (int k = count * maxOneLen; k < count * maxOneLen + mod; k++) { buff[k] = _buff[k - count * maxOneLen]; } } base.State = flag; return flag; } catch (Exception ex) { //ICSharpCode.Core.LoggingService.Error(String.Format("读取PLC(AB500)设备失败-({0})!", ex.Message)); base.State = false; return false; } } } /// /// 单次读取最长100个字的方法 /// /// 块号 /// 起始字 /// 长度,最长不超过100 /// 数据缓冲区,存放读取的数据 /// 读取成功返回true,读取失败返回false private bool ReadByLen(string block, int start, int len, out object[] buff) { lock (this) { buff = new object[len]; if (!this.Open()) { return false; } int state = 0; ushort[] _buff = new ushort[len]; string ss = "$N" + block.ToString() + ":" + start.ToString() + "," + len.ToString() + ",WORD,READ,AB:LOCAL,1,SLC500,0"; //ICSharpCode.Core.LoggingService.Info("DTL_C_DEFINE=" + ss); uint id = 0; int iResult = DTL32.DTL_C_DEFINE(ref id, ss); //ICSharpCode.Core.LoggingService.Info("DTL_C_DEFINE Result=" + iResult.ToString()); if (iResult != 0) { return false; } iResult = DTL32.DTL_READ_W(id, _buff, ref state, 1000); //ICSharpCode.Core.LoggingService.Info("DTL_READ_W Result=" + iResult.ToString()); DTL32.DTL_UNDEF(id); if (iResult != 0) { return false; } for (int i = 0; i < len; i++) { int value = _buff[i]; if (value > ushort.MaxValue) { value = ushort.MaxValue - value; } buff[i] = value; } return true; } } private ushort ToValue(object obj, ushort defaultValue) { ushort result = 0; if (obj != null && obj != DBNull.Value && ushort.TryParse(obj.ToString(), out result)) { return result; } return defaultValue; } /// /// PLC数据写入方法 /// /// 要写入的块号 /// 起始字 /// 要写入PLC的数据 /// 写入成功返回true,失败返回false public override bool Write(int block, int start, object[] buff) { lock (this) { try { if (buff.Length > 256) { return false; } int len = buff.Length; int maxOneLen = 100; //单次允许读取的最大长度,AB500限制为100个字 int count = len / maxOneLen; //要读取的次数 int mod = len % maxOneLen; //剩余的长度 bool flag = true; //保存写入标志 for (int i = 0; i < count; i++) { object[] _buff = new object[maxOneLen]; for (int k = i * maxOneLen; k < (i + 1) * maxOneLen; k++) { _buff[k - i * maxOneLen] = buff[k]; } flag = this.WriteMax100(block, start + i * maxOneLen, _buff); if (flag == false) { return false; } } if (mod > 0) { object[] _buff = new object[mod]; for (int k = count * maxOneLen; k < count * maxOneLen + mod; k++) { _buff[k - count * maxOneLen] = buff[k]; } flag = this.WriteMax100(block, start + count * maxOneLen, _buff); } return flag; } catch (Exception ex) { //ICSharpCode.Core.LoggingService.Error(String.Format("写入PLC(AB500)设备失败-({0})!", ex.Message)); return false; } } } /// /// 单次写入最多100个字至PLC /// /// 要写入的块号 /// 要写入的起始字 /// 要写入的数据 /// 写入成功返回true,失败返回false private bool WriteMax100(int block, int start, object[] buff) { lock (this) { if (buff.Length == 0) { return true; } Logger.Instance.Info("Open"); if (!this.Open()) { return false; } int state = 0; ushort[] _buff = new ushort[buff.Length]; for (int i = 0; i < buff.Length; i++) { _buff[i] = ToValue(buff[i], 0); } string ss = "$N" + block.ToString() + ":" + start.ToString() + "," + buff.Length.ToString() + ",WORD,MODIFY,AB:LOCAL,1,SLC500,0"; uint id = 0; int iResult = DTL32.DTL_C_DEFINE(ref id, ss); if (iResult != 0) { return false; } iResult = DTL32.DTL_WRITE_W(id, _buff, ref state, 1000); DTL32.DTL_UNDEF(id); if (iResult != 0) { return false; } return true; } } public override void Close() { lock (this) { try { DTL32.DTL_UNINIT(0); DTL32.DTL_UNDEF(0); DTL32.DTL_DRIVER_CLOSE(0, 100); this.State = false; } catch(Exception ex) { this.State = false; ICSharpCode.Core.LoggingService.Error(String.Format("关闭PLC(AB500)设备连接失败-({0})!", ex.Message)); //ICSharpCode.Core.LoggingService.Error(ex.StackTrace); } } } } }