using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Runtime.InteropServices; using Aitex.Core.RT.IOCore; using Aitex.Core.RT.Log; using Aitex.Core.Util; using Aitex.Triton160.RT; using Aitex.Triton160.RT.PLC; namespace Aitex.Core.RT.PLC { public enum BlockType { CIO = 0x30, WR = 0x31, D = 0x82, } public class GroupFinsDataDevice : IDataDevice { private Dictionary _devices = new Dictionary() { {"local", new FinsDataDevice(RtInstance.LocalPlcIpAddress, RtInstance.LocalPlcIoBaseDi, RtInstance.LocalPlcDiBlockLength, RtInstance.LocalPlcDiType, RtInstance.LocalPlcIoBaseDo, RtInstance.LocalPlcDoBlockLength, RtInstance.LocalPlcDoType, RtInstance.LocalPlcIoBaseAi, RtInstance.LocalPlcAiBlockLength, RtInstance.LocalPlcAiType, RtInstance.LocalPlcIoBaseAo, RtInstance.LocalPlcAoBlockLength, RtInstance.LocalPlcAoType )}, }; public bool IsOpened { get { foreach (var device in _devices) { if (!device.Value.IsOpened) return false; } return true; } } public bool Open() { foreach (var device in _devices) { if (!device.Value.Open()) return false; } return true; } public void Close() { foreach (var device in _devices) { device.Value.Close(); } } public object Read(string type) { if (!_devices.ContainsKey(type)) { LOG.Error("read undefined PLC type " + type); return null; } return _devices[type].Read(); } public bool Write(string type, T buffer) { if (!_devices.ContainsKey(type)) { LOG.Error("write undefined PLC type " + type); return false; } return _devices[type].Write(buffer); } public List GetTypes() { return _devices.Keys.ToList(); } public bool IsOpen(string type) { return _devices[type].IsOpen(type); } public bool Open(string type) { return _devices[type].Open(type); } public void Close(string type) { _devices[type].Close(type); } } public class FinsDataDevice : IDataDevice { public bool IsOpened { get { return _isOpened; } } private TcpClient msender; private Socket msock; private byte[] Client, Server; private bool _isOpened = false; private string _ip = "192.168.10.10"; private int port = 9600; private int _diStartPosition; private int _diLength; private BlockType _diBlockType; private int _doStartPosition; private int _doLength; private BlockType _doBlockType; private int _aiStartPosition; private int _aiLength; private BlockType _aiBlockType; private int _aoStartPosition; private int _aoLength; private BlockType _aoBlockType; private R_TRIG _failedTrigger = new R_TRIG(); private DeviceTimer _timerWrite = new DeviceTimer(); private DeviceTimer _timerRead = new DeviceTimer(); public FinsDataDevice(string ip, int diStartPosition, int diLength, BlockType diBlockType, int doStartPosition, int doLength, BlockType doBlockType, int aiStartPosition, int aiLength, BlockType aiBlockType, int aoStartPosition, int aoLength, BlockType aoBlockType) { _ip = ip; _diStartPosition = diStartPosition; _diLength = diLength; _diBlockType = diBlockType; _doStartPosition = doStartPosition; _doLength = doLength; _doBlockType = doBlockType; _aiStartPosition = aiStartPosition; _aiLength = aiLength; _aiBlockType = aiBlockType; _aoStartPosition = aoStartPosition; _aoLength = aoLength; _aoBlockType = aoBlockType; } public bool Open() { if (string.IsNullOrEmpty(_ip)) return true; try { Close(); _isOpened = false; msender = new TcpClient(_ip, port); msock = msender.Client; msock.Send(HandShake()); byte[] buffer = new byte[24]; msock.Receive(buffer, SocketFlags.None); { Client = new byte[4]; Client[0] = buffer[16]; Client[1] = buffer[17]; Client[2] = buffer[18]; Client[3] = buffer[19]; Server = new byte[4]; Server[0] = buffer[20]; Server[1] = buffer[21]; Server[2] = buffer[22]; Server[3] = buffer[23]; } _isOpened = true; } catch (Exception ex) { _failedTrigger.CLK = true; if (_failedTrigger.Q) { LOG.Write(ex, String.Format("Communication failed with PLC {0}:{1}", _ip, port)); } return false; } _failedTrigger.RST = true; _isOpened = true; LOG.Write(String.Format("连接成功,PLC {0}:{1}", _ip, port)); return true; } public void Close() { if (string.IsNullOrEmpty(_ip)) return; try { if (_isOpened) { LOG.Write(String.Format("关闭连接,PLC {0}:{1}", _ip, port)); _isOpened = false; msender.Close(); } } catch (Exception ex) { LOG.Write(ex); } } public object Read() { PLC_INPUT_DATA buf = new PLC_INPUT_DATA(); buf.DI = new Byte[IOGroupManager.DioBlockLength]; buf.AI = new float[IOGroupManager.AioBlockLength]; if (string.IsNullOrEmpty(_ip)) return buf; try { ReadBlock(_diBlockType, (ushort)_diStartPosition, (ushort)_diLength, ref buf.DI); ReadBlock_float(_aiBlockType, (ushort)_aiStartPosition, (ushort)_aiLength, ref buf.AI); return buf; } catch (Exception ex) { LOG.Error(String.Format("PLC ({0}) Read exception.", _ip), ex); Close(); } return null; } public bool Write(T buffer) { if (string.IsNullOrEmpty(_ip)) return true; try { _timerWrite.Start(0); PLC_OUTPUT_DATA buf = (PLC_OUTPUT_DATA)(object)buffer; WriteBlock_hex(_aoBlockType, (ushort)_aoStartPosition, (ushort)_aoLength, buf.AO); WriteBlock_Byte(_doBlockType, (ushort)_doStartPosition, (ushort)_doLength, buf.DO); //WriteBlock_float(_aoBlockType, (ushort)_aoStartPosition, (ushort)_aoLength, buf.AO); //double interval = _timerWrite.GetElapseTime(); //if (interval > _averageWriteTime) //{ // LOG.Write(_ip + ":Max write PLC interval : " + interval); // _averageWriteTime = interval; //} return true; } catch (Exception ex) { LOG.Error(String.Format("PLC ({0})Write exception.", _ip), ex); Close(); return false; } } private void ReadBlock(BlockType type, ushort addr, ushort len, ref T[] data) { byte[] FullCmd = new byte[34]; //TCP FINS header FullCmd[0] = 0x46;//F FullCmd[1] = 0x49;//I FullCmd[2] = 0x4e;//N FullCmd[3] = 0x53;//S FullCmd[4] = 0;//cmd length FullCmd[5] = 0; FullCmd[6] = 0; FullCmd[7] = 0x1A; FullCmd[8] = 0;//frame command FullCmd[9] = 0; FullCmd[10] = 0; FullCmd[11] = 0x02; FullCmd[12] = 0;//err FullCmd[13] = 0; FullCmd[14] = 0; FullCmd[15] = 0; //command frame header FullCmd[16] = 0x80;//ICF FullCmd[17] = 0x00;//RSV FullCmd[18] = 0x02;//GCT, less than 8 network layers FullCmd[19] = 0x00;//DNA, local network FullCmd[20] = Server[3];//DA1 FullCmd[21] = 0x00;//DA2, CPU unit FullCmd[22] = 0x00;//SNA, local network FullCmd[23] = Client[3];//SA1 FullCmd[24] = 0x00;//SA2, CPU unit FullCmd[25] = Convert.ToByte(21);//SID FullCmd[26] = 0x01; //FINS CMD Main Request Code 0101 Read IO Area FullCmd[27] = 0x01; //Sub Request Code //Parameter FullCmd[28] = (byte)type; FullCmd[29] = (byte)((addr >> 8) & 0xFF); //Block Add FullCmd[30] = (byte)(addr & 0xFF); FullCmd[31] = 0; //Bit Add FullCmd[32] = (byte)((len >> 8) & 0xFF); ; //Read Count FullCmd[33] = (byte)(len & 0xFF); msock.Send(FullCmd, SocketFlags.None); byte[] buffer = new byte[len + 30]; msock.Receive(buffer); bool Succeed = true; if (buffer[11] == 3) Succeed = CheckHeadError(buffer[15]); if (Succeed)//no header error { T[] buf = new T[len]; Array.Copy(buffer, 30, buf, 0, len); if (CheckEndCode(buffer[28], buffer[29])) { for (int i = 0; i < len; i++) { data[i] = buf[i]; } } } } private void ReadBlock_float(BlockType type, ushort addr, ushort len, ref float[] data) { byte[] FullCmd = new byte[34]; //TCP FINS header FullCmd[0] = 0x46;//F FullCmd[1] = 0x49;//I FullCmd[2] = 0x4e;//N FullCmd[3] = 0x53;//S FullCmd[4] = 0;//cmd length FullCmd[5] = 0; FullCmd[6] = 0; FullCmd[7] = 0x1A; FullCmd[8] = 0;//frame command FullCmd[9] = 0; FullCmd[10] = 0; FullCmd[11] = 0x02; FullCmd[12] = 0;//err FullCmd[13] = 0; FullCmd[14] = 0; FullCmd[15] = 0; //command frame header FullCmd[16] = 0x80;//ICF FullCmd[17] = 0x00;//RSV FullCmd[18] = 0x02;//GCT, less than 8 network layers FullCmd[19] = 0x00;//DNA, local network FullCmd[20] = Server[3];//DA1 FullCmd[21] = 0x00;//DA2, CPU unit FullCmd[22] = 0x00;//SNA, local network FullCmd[23] = Client[3];//SA1 FullCmd[24] = 0x00;//SA2, CPU unit FullCmd[25] = Convert.ToByte(21);//SID FullCmd[26] = 0x01; //FINS CMD Main Request Code 0101 Read IO Area FullCmd[27] = 0x01; //Sub Request Code //Parameter FullCmd[28] = (byte)type; FullCmd[29] = (byte)((addr >> 8) & 0xFF); //Block Add FullCmd[30] = (byte)(addr & 0xFF); FullCmd[31] = 0; //Bit Add int count = len * 2; FullCmd[32] = (byte)((count >> 8) & 0xFF); ; //Read Count FullCmd[33] = (byte)(count & 0xFF); msock.Send(FullCmd, SocketFlags.None); byte[] buffer = new byte[31 + len * 4]; msock.Receive(buffer); bool Succeed = true; if (buffer[11] == 3) Succeed = CheckHeadError(buffer[15]); if (Succeed)//no header error { if (CheckEndCode(buffer[28], buffer[29])) { byte[] buf = new byte[4]; for (int i = 0; i < len; i++) { buf[0] = buffer[30 + i * 4 + 1]; buf[1] = buffer[30 + i * 4 + 0]; buf[2] = buffer[30 + i * 4 + 3]; buf[3] = buffer[30 + i * 4 + 2]; data[i] = BitConverter.ToSingle(buf, 0); } } } } private void WriteBlock_Byte(BlockType type, ushort addr, ushort len, byte[] data) { byte[] FullCmd = new byte[34 + len]; //TCP FINS header FullCmd[0] = 0x46;//F FullCmd[1] = 0x49;//I FullCmd[2] = 0x4e;//N FullCmd[3] = 0x53;//S int cmdLen = 26 + len; FullCmd[4] = 0;//cmd length FullCmd[5] = 0; FullCmd[6] = (byte)((cmdLen >> 8) & 0xFF); FullCmd[7] = (byte)(cmdLen & 0xFF); FullCmd[8] = 0;//frame command FullCmd[9] = 0; FullCmd[10] = 0; FullCmd[11] = 0x02; FullCmd[12] = 0;//err FullCmd[13] = 0; FullCmd[14] = 0; FullCmd[15] = 0; //command frame header FullCmd[16] = 0x80;//ICF FullCmd[17] = 0x00;//RSV FullCmd[18] = 0x02;//GCT, less than 8 network layers FullCmd[19] = 0x00;//DNA, local network FullCmd[20] = Server[3];//DA1 FullCmd[21] = 0x00;//DA2, CPU unit FullCmd[22] = 0x00;//SNA, local network FullCmd[23] = Client[3];//SA1 FullCmd[24] = 0x00;//SA2, CPU unit FullCmd[25] = Convert.ToByte(21);//SID FullCmd[26] = 0x01; //FINS CMD Main Request Code 0101 Read IO Area FullCmd[27] = 0x02; //Sub Request Code //Parameter FullCmd[28] = (byte)type; FullCmd[29] = (byte)((addr >> 8) & 0xFF); //Block Add FullCmd[30] = (byte)(addr & 0xFF); FullCmd[31] = 0; //Bit Add FullCmd[32] = (byte)((len >> 8) & 0xFF); ; //Write Count FullCmd[33] = (byte)(len & 0xFF); for (int i = 0; i < len; i++) { FullCmd[34 + i] = data[i]; } msock.Send(FullCmd, SocketFlags.None); byte[] buffer = new byte[len + 34]; msock.Receive(buffer); bool Succeed = true; if (buffer[11] == 3) Succeed = CheckHeadError(buffer[15]); if (Succeed)//no header error { if (CheckEndCode(buffer[28], buffer[29])) { //do nothing } } } private void WriteBlock_float(BlockType type, ushort addr, ushort len, float[] data) { byte[] FullCmd = new byte[34 + len * 4]; //TCP FINS header FullCmd[0] = 0x46;//F FullCmd[1] = 0x49;//I FullCmd[2] = 0x4e;//N FullCmd[3] = 0x53;//S int cmdLen = 26 + len * 4; FullCmd[4] = 0;//cmd length FullCmd[5] = 0; FullCmd[6] = (byte)((cmdLen >> 8) & 0xFF); FullCmd[7] = (byte)(cmdLen & 0xFF); FullCmd[8] = 0;//frame command FullCmd[9] = 0; FullCmd[10] = 0; FullCmd[11] = 0x02; FullCmd[12] = 0;//err FullCmd[13] = 0; FullCmd[14] = 0; FullCmd[15] = 0; //command frame header FullCmd[16] = 0x80;//ICF FullCmd[17] = 0x00;//RSV FullCmd[18] = 0x02;//GCT, less than 8 network layers FullCmd[19] = 0x00;//DNA, local network FullCmd[20] = Server[3];//DA1 FullCmd[21] = 0x00;//DA2, CPU unit FullCmd[22] = 0x00;//SNA, local network FullCmd[23] = Client[3];//SA1 FullCmd[24] = 0x00;//SA2, CPU unit FullCmd[25] = Convert.ToByte(21);//SID FullCmd[26] = 0x01; //FINS CMD Main Request Code 0101 Read IO Area FullCmd[27] = 0x02; //Sub Request Code //Parameter FullCmd[28] = (byte)type; FullCmd[29] = (byte)((addr >> 8) & 0xFF); //Block Add FullCmd[30] = (byte)(addr & 0xFF); FullCmd[31] = 0; //Bit Add int count = len * 2; FullCmd[32] = (byte)((count >> 8) & 0xFF); ; //Write Count FullCmd[33] = (byte)(count & 0xFF); try { for (int i = 0; i < len; i++) { byte[] buf = BitConverter.GetBytes(data[i]); FullCmd[34 + i * 4 + 0] = buf[1]; FullCmd[34 + i * 4 + 1] = buf[0]; FullCmd[34 + i * 4 + 2] = buf[3]; FullCmd[34 + i * 4 + 3] = buf[2]; } } catch (Exception ex) { LOG.Write(ex); } msock.Send(FullCmd, SocketFlags.None); byte[] buffer = new byte[31 + len * 4]; msock.Receive(buffer); bool Succeed = true; if (buffer[11] == 3) Succeed = CheckHeadError(buffer[15]); if (Succeed)//no header error { if (CheckEndCode(buffer[28], buffer[29])) { //do nothing } } } private void WriteBlock_hex(BlockType type, ushort addr, ushort len, float[] data) { byte[] FullCmd = new byte[34 + len * 4]; //TCP FINS header FullCmd[0] = 0x46;//F FullCmd[1] = 0x49;//I FullCmd[2] = 0x4e;//N FullCmd[3] = 0x53;//S int cmdLen = 26 + len * 4; FullCmd[4] = 0;//cmd length FullCmd[5] = 0; FullCmd[6] = (byte)((cmdLen >> 8) & 0xFF); FullCmd[7] = (byte)(cmdLen & 0xFF); FullCmd[8] = 0;//frame command FullCmd[9] = 0; FullCmd[10] = 0; FullCmd[11] = 0x02; FullCmd[12] = 0;//err FullCmd[13] = 0; FullCmd[14] = 0; FullCmd[15] = 0; //command frame header FullCmd[16] = 0x80;//ICF FullCmd[17] = 0x00;//RSV FullCmd[18] = 0x02;//GCT, less than 8 network layers FullCmd[19] = 0x00;//DNA, local network FullCmd[20] = Server[3];//DA1 FullCmd[21] = 0x00;//DA2, CPU unit FullCmd[22] = 0x00;//SNA, local network FullCmd[23] = Client[3];//SA1 FullCmd[24] = 0x00;//SA2, CPU unit FullCmd[25] = Convert.ToByte(21);//SID FullCmd[26] = 0x01; //FINS CMD Main Request Code 0101 Read IO Area FullCmd[27] = 0x02; //Sub Request Code //Parameter FullCmd[28] = (byte)type; FullCmd[29] = (byte)((addr >> 8) & 0xFF); //Block Add FullCmd[30] = (byte)(addr & 0xFF); FullCmd[31] = 0; //Bit Add int count = len * 2; FullCmd[32] = (byte)((count >> 8) & 0xFF); ; //Write Count FullCmd[33] = (byte)(count & 0xFF); try { for (int i = 0; i < len; i++) { byte[] buf = BitConverter.GetBytes(data[i]); FullCmd[34 + i * 4 + 0] = buf[1]; FullCmd[34 + i * 4 + 1] = buf[0]; FullCmd[34 + i * 4 + 2] = buf[3]; FullCmd[34 + i * 4 + 3] = buf[2]; } } catch (Exception ex) { LOG.Write(ex); } msock.Send(FullCmd, SocketFlags.None); byte[] buffer = new byte[31 + len * 4]; msock.Receive(buffer); bool Succeed = true; if (buffer[11] == 3) Succeed = CheckHeadError(buffer[15]); if (Succeed)//no header error { if (CheckEndCode(buffer[28], buffer[29])) { //do nothing } } } private byte[] HandShake() { //handshake byte[] Handshake = new byte[20]; Handshake[0] = 0x46; Handshake[1] = 0x49; Handshake[2] = 0x4e; Handshake[3] = 0x53; Handshake[4] = 0; Handshake[5] = 0; Handshake[6] = 0; Handshake[7] = 0x0c; Handshake[8] = 0; Handshake[9] = 0; Handshake[10] = 0; Handshake[11] = 0; Handshake[12] = 0; Handshake[13] = 0; Handshake[14] = 0; Handshake[15] = 0; Handshake[16] = 0; Handshake[17] = 0; Handshake[18] = 0; Handshake[19] = 0;//ask for client and server node number, the client node will allocated automatically return Handshake; } /// /// (若返回的头指令为3)检查命令头中的错误代码 /// /// 错误代码 /// 指示程序是否可以继续进行 bool CheckHeadError(byte Code) { switch (Code) { case 0x00: return true; case 0x01: RaiseException("the head is not 'FINS'"); return false; case 0x02: RaiseException("the data length is too long"); return false; case 0x03: RaiseException("the command is not supported"); return false; } //no hit RaiseException("unknown exception"); return false; } private void RaiseException(string p) { _isOpened = false; } /// /// 检查命令帧中的EndCode /// /// 主码 /// 副码 /// 指示程序是否可以继续进行 bool CheckEndCode(byte Main, byte Sub) { switch (Main) { case 0x00: switch (Sub) { case 0x00: return true;//the only situation of success case 0x01: RaiseException("service canceled"); return false; } break; case 0x01: switch (Sub) { case 0x01: RaiseException("local node not in network"); return false; case 0x02: RaiseException("token timeout"); return false; case 0x03: RaiseException("retries failed"); return false; case 0x04: RaiseException("too many send frames"); return false; case 0x05: RaiseException("node address range error"); return false; case 0x06: RaiseException("node address duplication"); return false; } break; case 0x02: switch (Sub) { case 0x01: RaiseException("destination node not in network"); return false; case 0x02: RaiseException("unit missing"); return false; case 0x03: RaiseException("third node missing"); return false; case 0x04: RaiseException("destination node busy"); return false; case 0x05: RaiseException("response timeout"); return false; } break; case 0x03: switch (Sub) { case 0x01: RaiseException("communications controller error"); return false; case 0x02: RaiseException("CPU unit error"); return false; case 0x03: RaiseException("controller error"); return false; case 0x04: RaiseException("unit number error"); return false; } break; case 0x04: switch (Sub) { case 0x01: RaiseException("undefined command"); return false; case 0x02: RaiseException("not supported by model/version"); return false; } break; case 0x05: switch (Sub) { case 0x01: RaiseException("destination address setting error"); return false; case 0x02: RaiseException("no routing tables"); return false; case 0x03: RaiseException("routing table error"); return false; case 0x04: RaiseException("too many relays"); return false; } break; case 0x10: switch (Sub) { case 0x01: RaiseException("command too long"); return false; case 0x02: RaiseException("command too short"); return false; case 0x03: RaiseException("elements/data don't match"); return false; case 0x04: RaiseException("command format error"); return false; case 0x05: RaiseException("header error"); return false; } break; case 0x11: switch (Sub) { case 0x01: RaiseException("area classification missing"); return false; case 0x02: RaiseException("access size error"); return false; case 0x03: RaiseException("address range error"); return false; case 0x04: RaiseException("address range exceeded"); return false; case 0x06: RaiseException("program missing"); return false; case 0x09: RaiseException("relational error"); return false; case 0x0a: RaiseException("duplicate data access"); return false; case 0x0b: RaiseException("response too long"); return false; case 0x0c: RaiseException("parameter error"); return false; } break; case 0x20: switch (Sub) { case 0x02: RaiseException("protected"); return false; case 0x03: RaiseException("table missing"); return false; case 0x04: RaiseException("data missing"); return false; case 0x05: RaiseException("program missing"); return false; case 0x06: RaiseException("file missing"); return false; case 0x07: RaiseException("data mismatch"); return false; } break; case 0x21: switch (Sub) { case 0x01: RaiseException("read-only"); return false; case 0x02: RaiseException("protected , cannot write data link table"); return false; case 0x03: RaiseException("cannot register"); return false; case 0x05: RaiseException("program missing"); return false; case 0x06: RaiseException("file missing"); return false; case 0x07: RaiseException("file name already exists"); return false; case 0x08: RaiseException("cannot change"); return false; } break; case 0x22: switch (Sub) { case 0x01: RaiseException("not possible during execution"); return false; case 0x02: RaiseException("not possible while running"); return false; case 0x03: RaiseException("wrong PLC mode"); return false; case 0x04: RaiseException("wrong PLC mode"); return false; case 0x05: RaiseException("wrong PLC mode"); return false; case 0x06: RaiseException("wrong PLC mode"); return false; case 0x07: RaiseException("specified node not polling node"); return false; case 0x08: RaiseException("step cannot be executed"); return false; } break; case 0x23: switch (Sub) { case 0x01: RaiseException("file device missing"); return false; case 0x02: RaiseException("memory missing"); return false; case 0x03: RaiseException("clock missing"); return false; } break; case 0x24: switch (Sub) { case 0x01: RaiseException("table missing"); return false; } break; case 0x25: switch (Sub) { case 0x02: RaiseException("memory error"); return false; case 0x03: RaiseException("I/O setting error"); return false; case 0x04: RaiseException("too many I/O points"); return false; case 0x05: RaiseException("CPU bus error"); return false; case 0x06: RaiseException("I/O duplication"); return false; case 0x07: RaiseException("CPU bus error"); return false; case 0x09: RaiseException("SYSMAC BUS/2 error"); return false; case 0x0a: RaiseException("CPU bus unit error"); return false; case 0x0d: RaiseException("SYSMAC BUS No. duplication"); return false; case 0x0f: RaiseException("memory error"); return false; case 0x10: RaiseException("SYSMAC BUS terminator missing"); return false; } break; case 0x26: switch (Sub) { case 0x01: RaiseException("no protection"); return false; case 0x02: RaiseException("incorrect password"); return false; case 0x04: RaiseException("protected"); return false; case 0x05: RaiseException("service already executing"); return false; case 0x06: RaiseException("service stopped"); return false; case 0x07: RaiseException("no execution right"); return false; case 0x08: RaiseException("settings required before execution"); return false; case 0x09: RaiseException("necessary items not set"); return false; case 0x0a: RaiseException("number already defined"); return false; case 0x0b: RaiseException("error will not clear"); return false; } break; case 0x30: switch (Sub) { case 0x01: RaiseException("no access right"); return false; } break; case 0x40: switch (Sub) { case 0x01: RaiseException("service aborted"); return false; } break; } //no hit RaiseException("unknown exception"); return false; } public object Read(string type) { throw new NotImplementedException(); } public bool Write(string type, T buffer) { throw new NotImplementedException(); } public List GetTypes() { throw new NotImplementedException(); } public bool IsOpen(string type) { if (string.IsNullOrEmpty(_ip)) return true; return IsOpened; } public bool Open(string type) { if (string.IsNullOrEmpty(_ip)) return true; return Open(); } public void Close(string type) { if (string.IsNullOrEmpty(_ip)) return; Close(); } } public class Converter { public static byte[] StructToBytes(object obj) { int rawsize = Marshal.SizeOf(obj); IntPtr buffer = Marshal.AllocHGlobal(rawsize); Marshal.StructureToPtr(obj, buffer, false); byte[] rawdatas = new byte[rawsize]; Marshal.Copy(buffer, rawdatas, 0, rawsize); Marshal.FreeHGlobal(buffer); return rawdatas; } public static object BytesToStruct(byte[] buf, int len, Type type) { object rtn; IntPtr buffer = Marshal.AllocHGlobal(len); Marshal.Copy(buf, 0, buffer, len); rtn = Marshal.PtrToStructure(buffer, type); Marshal.FreeHGlobal(buffer); return rtn; } public static void BytesToStruct(byte[] buf, int len, object rtn) { IntPtr buffer = Marshal.AllocHGlobal(len); Marshal.Copy(buf, 0, buffer, len); Marshal.PtrToStructure(buffer, rtn); Marshal.FreeHGlobal(buffer); } public static void BytesToStruct(byte[] buf, object rtn) { BytesToStruct(buf, buf.Length, rtn); } public static object BytesToStruct(byte[] buf, Type type) { return BytesToStruct(buf, buf.Length, type); } } }