123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- using System;
- using System.Net.Sockets;
- using System.Threading;
- namespace OmronFinsTCP.Net
- {
- public class EtherNetPLC
- {
- /// <summary>
- /// PLC节点号,调试方法,一般不需要使用
- /// </summary>
- public string PLCNode
- {
- get { return BasicClass.plcNode.ToString(); }
- }
- /// <summary>
- /// PC节点号,调试方法,一般不需要使用
- /// </summary>
- public string PCNode
- {
- get { return BasicClass.pcNode.ToString(); }
- }
- public bool IsConnect
- {
- get { return BasicClass.Client.Connected; }
- }
- /// <summary>
- /// 实例化PLC操作对象
- /// </summary>
- public EtherNetPLC()
- {
- BasicClass.Client = new TcpClient();
- }
- /// <summary>
- /// 与PLC建立TCP连接
- /// </summary>
- /// <param name="rIP">PLC的IP地址</param>
- /// <param name="rPort">端口号,默认9600</param>
- /// <param name="timeOut">超时时间,默认3000毫秒</param>
- /// <returns></returns>
- public short Link(string rIP, short rPort, short timeOut = 3000)
- {
- if(BasicClass.PingCheck(rIP,timeOut))
- {
- if(BasicClass.Client.Client==null)
- {
- BasicClass.Client = new TcpClient();
- }
- BasicClass.Client.Connect(rIP, (int)rPort);
- BasicClass.Stream = BasicClass.Client.GetStream();
- Thread.Sleep(10);
- if (BasicClass.SendData(FinsClass.HandShake()) != 0)
- {
- return -1;
- }
- else
- {
- //开始读取返回信号
- byte[] buffer = new byte[24];
- if (BasicClass.ReceiveData(buffer) != 0)
- {
- return -1;
- }
- else
- {
- if (buffer[15] != 0)//TODO:这里的15号是不是ERR信息暂时不能完全肯定
- return -1;
- else
- {
- BasicClass.pcNode = buffer[19];
- BasicClass.plcNode = buffer[23];
- return 0;
- }
- }
- }
- }
- else
- {
- BasicClass.Client?.Close();
- //连接超时
- return -1;
- }
- }
- /// <summary>
- /// 关闭PLC操作对象的TCP连接
- /// </summary>
- /// <returns></returns>
- public short Close()
- {
- try
- {
- BasicClass.Stream?.Close();
- BasicClass.Client?.Close();
- return 0;
- }
- catch
- {
- return -1;
- }
- }
- /// <summary>
- /// 读值方法(多个连续值)
- /// </summary>
- /// <param name="mr">地址类型枚举</param>
- /// <param name="ch">起始地址</param>
- /// <param name="cnt">地址个数</param>
- /// <param name="reData">返回值</param>
- /// <returns></returns>
- public short ReadWords(PlcMemory mr, short ch, short cnt, out short[] reData)
- {
- reData = new short[(int)(cnt)];//储存读取到的数据
- int num = (int)(30 + cnt * 2);//接收数据(Text)的长度,字节数
- byte[] buffer = new byte[num];//用于接收数据的缓存区大小
- byte[] array = FinsClass.FinsCmd(RorW.Read, mr, MemoryType.Word, ch, 00, cnt);
- if (BasicClass.SendData(array) == 0)
- {
- if (BasicClass.ReceiveData(buffer) == 0)
- {
- //命令返回成功,继续查询是否有错误码,然后在读取数据
- bool succeed = true;
- if (buffer[11] == 3)
- succeed = ErrorCode.CheckHeadError(buffer[15]);
- if (succeed)//no header error
- {
- //endcode为fins指令的返回错误码
- if (ErrorCode.CheckEndCode(buffer[28], buffer[29]))
- {
- //完全正确的返回,开始读取返回的具体数值
- for (int i = 0; i < cnt; i++)
- {
- //返回的数据从第30字节开始储存的,
- //PLC每个字占用两个字节,且是高位在前,这和微软的默认低位在前不同
- //因此无法直接使用,reData[i] = BitConverter.ToInt16(buffer, 30 + i * 2);
- //先交换了高低位的位置,然后再使用BitConverter.ToInt16转换
- byte[] temp = new byte[] { buffer[30 + i * 2 + 1], buffer[30 + i * 2] };
- reData[i] = BitConverter.ToInt16(temp, 0);
- }
- return 0;
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- /// <summary>
- /// 读单个字方法
- /// </summary>
- /// <param name="mr"></param>
- /// <param name="ch"></param>
- /// <param name="reData"></param>
- /// <returns></returns>
- public short ReadWord(PlcMemory mr, short ch, out short reData)
- {
- short[] temp;
- reData = new short();
- short re = ReadWords(mr, ch, (short)1, out temp);
- if (re != 0)
- return -1;
- else
- {
- reData = temp[0];
- return 0;
- }
- }
- /// <summary>
- /// 写值方法(多个连续值)
- /// </summary>
- /// <param name="mr">地址类型枚举</param>
- /// <param name="ch">起始地址</param>
- /// <param name="cnt">地址个数</param>
- /// <param name="inData">写入值</param>
- /// <returns></returns>
- public short WriteWords(PlcMemory mr, short ch, short cnt, short[] inData)
- {
- byte[] buffer = new byte[30];
- byte[] arrayhead = FinsClass.FinsCmd(RorW.Write, mr, MemoryType.Word, ch, 00, cnt);//前34字节和读指令基本一直,还需要拼接下面的输入数据数组
- byte[] wdata = new byte[(int)(cnt * 2)];
- //转换写入值到wdata数组
- for (int i = 0; i < cnt; i++)
- {
- byte[] temp = BitConverter.GetBytes(inData[i]);
- wdata[i * 2] = temp[1];//转换为PLC的高位在前储存方式
- wdata[i * 2 + 1] = temp[0];
- }
- //拼接写入数组
- byte[] array = new byte[(int)(cnt * 2 + 34)];
- arrayhead.CopyTo(array, 0);
- wdata.CopyTo(array, 34);
- if (BasicClass.SendData(array) == 0)
- {
- if (BasicClass.ReceiveData(buffer) == 0)
- {
- //命令返回成功,继续查询是否有错误码,然后在读取数据
- bool succeed = true;
- if (buffer[11] == 3)
- succeed = ErrorCode.CheckHeadError(buffer[15]);
- if (succeed)//no header error
- {
- //endcode为fins指令的返回错误码
- if (ErrorCode.CheckEndCode(buffer[28], buffer[29]))
- {
- //完全正确的返回0
- return 0;
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- /// <summary>
- /// 写单个字方法
- /// </summary>
- /// <param name="mr"></param>
- /// <param name="ch"></param>
- /// <param name="inData"></param>
- /// <returns></returns>
- public short WriteWord(PlcMemory mr, short ch, short inData)
- {
- short[] temp = new short[] { inData };
- short re = WriteWords(mr, ch, (short)1, temp);
- if (re != 0)
- return -1;
- else
- {
- return 0;
- }
- }
- /// <summary>
- /// 读值方法-按位bit(单个)
- /// </summary>
- /// <param name="mr">地址类型枚举</param>
- /// <param name="ch">地址000.00</param>
- /// <param name="bs">返回开关状态枚举EtherNetPLC.BitState,0/1</param>
- /// <returns></returns>
- public short GetBitState(PlcMemory mr, string ch, out short bs)
- {
- bs = new short();
- byte[] buffer = new byte[31];//用于接收数据的缓存区大小
- short cnInt = short.Parse(ch.Split('.')[0]);
- short cnBit = short.Parse(ch.Split('.')[1]);
- byte[] array = FinsClass.FinsCmd(RorW.Read, mr, MemoryType.Bit, cnInt, cnBit, 1);
- if (BasicClass.SendData(array) == 0)
- {
- if (BasicClass.ReceiveData(buffer) == 0)
- {
- //命令返回成功,继续查询是否有错误码,然后在读取数据
- bool succeed = true;
- if (buffer[11] == 3)
- succeed = ErrorCode.CheckHeadError(buffer[15]);
- if (succeed)//no header error
- {
- //endcode为fins指令的返回错误码
- if (ErrorCode.CheckEndCode(buffer[28], buffer[29]))
- {
- //完全正确的返回,开始读取返回的具体数值
- bs = (short)buffer[30];
- return 0;
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- /// <summary>
- /// 写值方法-按位bit(单个)
- /// </summary>
- /// <param name="mr">地址类型枚举</param>
- /// <param name="ch">地址000.00</param>
- /// <param name="bs">开关状态枚举EtherNetPLC.BitState,0/1</param>
- /// <returns></returns>
- public short SetBitState(PlcMemory mr, string ch, BitState bs)
- {
- byte[] buffer = new byte[30];
- short cnInt = short.Parse(ch.Split('.')[0]);
- short cnBit = short.Parse(ch.Split('.')[1]);
- byte[] arrayhead = FinsClass.FinsCmd(RorW.Write, mr, MemoryType.Bit, cnInt, cnBit, 1);
- byte[] array = new byte[35];
- arrayhead.CopyTo(array, 0);
- array[34] = (byte)bs;
- if (BasicClass.SendData(array) == 0)
- {
- if (BasicClass.ReceiveData(buffer) == 0)
- {
- //命令返回成功,继续查询是否有错误码,然后在读取数据
- bool succeed = true;
- if (buffer[11] == 3)
- succeed = ErrorCode.CheckHeadError(buffer[15]);
- if (succeed)//no header error
- {
- //endcode为fins指令的返回错误码
- if (ErrorCode.CheckEndCode(buffer[28], buffer[29]))
- {
- //完全正确的返回0
- return 0;
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- /// <summary>
- /// 读一个浮点数的方法,单精度,在PLC中占两个字
- /// </summary>
- /// <param name="mr">地址类型枚举</param>
- /// <param name="ch">起始地址,会读取两个连续的地址,因为单精度在PLC中占两个字</param>
- /// <param name="reData">返回一个float型</param>
- /// <returns></returns>
- public short ReadReal(PlcMemory mr, short ch,out float reData)
- {
- reData = new float();
- int num = (int)(30 + 2 * 2);//接收数据(Text)的长度,字节数
- byte[] buffer = new byte[num];//用于接收数据的缓存区大小
- byte[] array = FinsClass.FinsCmd(RorW.Read, mr, MemoryType.Word, ch, 00, 2);
- if (BasicClass.SendData(array) == 0)
- {
- if (BasicClass.ReceiveData(buffer) == 0)
- {
- //命令返回成功,继续查询是否有错误码,然后在读取数据
- bool succeed = true;
- if (buffer[11] == 3)
- succeed = ErrorCode.CheckHeadError(buffer[15]);
- if (succeed)//no header error
- {
- //endcode为fins指令的返回错误码
- if (ErrorCode.CheckEndCode(buffer[28], buffer[29]))
- {
- //完全正确的返回,开始读取返回的具体数值
- byte[] temp = new byte[] { buffer[30 + 1], buffer[30], buffer[30 + 3], buffer[30 + 2] };
- reData = BitConverter.ToSingle(temp, 0);
- return 0;
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- }
- }
|