/// <summary> /// 处理数据 /// </summary> /// <param name="buffer"></param> /// <param name="count"></param> /// <param name="msg"></param> private void ProcessData(SiemensMessage msg) { switch (msg.Type) { case CommandType.Head1: response.Type = CommandType.Head2; SendData(headData.plcHead2); //Console.WriteLine("Head1"); break; case CommandType.Head2: Connected = true; //Console.WriteLine("Head2"); break; case CommandType.Read: case CommandType.Write: response.Success = msg.Success; response.Message = msg.Message; response.DataValue = msg.DataValue; //Console.WriteLine("Read | Write " + Common.BytesToShort(msg.DataValue).ToString()); break; default: break; } }
/// <summary> /// 解码 /// </summary> /// <param name="buffer">报文</param> /// <param name="length">报文长度</param> /// <returns></returns> public SiemensMessage Decode(byte[] buffer, int length) { SiemensMessage msg = null; if (buffer[0] == 3 && buffer[1] == 0) { short messageLength = Common.BytesToShort(buffer, 2); //2-3 是报文长度 if (messageLength == length) { int type = buffer[11]; msg = new SiemensMessage(); switch (type) { case 0xC0: msg.Type = CommandType.Head1; break; case 0x04: msg.Type = CommandType.Head2; break; default: ReadOrWrite(buffer, msg); break; } } } return(msg); }
/// <summary> /// 连接 /// </summary> /// <param name="type"></param> /// <param name="host"></param> public void Connect(SiemensPLCS type, string host) { if (start) { return; } plcType = type; plcIP = host; headData.SetPlcType(type); try { tcpsend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { NoDelay = true }; tcpsend.ReceiveTimeout = timeOut * 1000; tcpsend.SendTimeout = timeOut * 1000; var remotepoint = new IPEndPoint(IPAddress.Parse(host), plcPort); tcpsend.Connect(remotepoint); response = new SiemensMessage(); start = true; Active(); } catch (Exception ex) { Connected = false; start = false; ErrorMsg("Connect:" + ex.Message); } }
/// <summary> /// 读取PLC数据 /// </summary> /// <param name="address"></param> /// <param name="count"></param> /// <returns></returns> public ResultData ReadBytes(string address, int count) { ResultData rd = new ResultData { Connected = false, Message = "当前与PLC通信断开!", Success = false }; if (this.Connected) { SiemensMessage msg = Common.GetAddress(address); if (msg == null) { rd.Message = "请输入正确的PLC地址!"; return(rd); } try { msg.Type = CommandType.Read; if (count > 0) { if (msg.DataType != DataType.Byte) { rd.Success = false; rd.Message = "对不起,请输入Byte类型地址!"; return(rd); } msg.DataType = DataType.Bytes; msg.DataLength = count; } else { msg.DataLength = (int)msg.DataType; } SiemensMessage result = plc.Send(msg); if (result.Success) { var value = GetValue(result.DataValue, result.DataType, result.DataLength); rd.Value = value; } rd.Success = result.Success; if (Connected) { rd.Message = result.Message; } rd.Connected = Connected; } catch (Exception e) { rd.Message = e.Message; } } return(rd); }
/// <summary> /// 第一次连接 /// </summary> private void Active() { var msg = new SiemensMessage { Type = CommandType.Head1, DataValue = headData.plcHead1 }; Send(msg); }
/// <summary> /// 读写数据 /// </summary> /// <param name="buffer"></param> /// <param name="msg"></param> private void ReadOrWrite(byte[] buffer, SiemensMessage msg) { int endLength = buffer[16]; //获取结尾报文长度 int type = buffer[19]; //结果类型 05写入返回 04 读取返回 int code = buffer[21]; //返回结果 0xFF 代表无错 byte[] value = null; var errorMsg = type == 4 ? "读取数据失败!" : "写入数据失败!"; if (code == 0xFF) { //0x05 是写入返回 0x04 是读取返回 switch (type) { case 0x04: msg.Type = CommandType.Read; int bType = buffer[22]; int dataLength = Common.BytesToShort(buffer, 23); //结果数据长度 if (bType == 4) //03 代表返回是bit 04代表byte { dataLength = dataLength / 8; //结果数据长度 / 8 bit } byte[] buf = new byte[dataLength]; Array.Copy(buffer, 25, buf, 0, dataLength); value = buf; break; case 0x05: msg.Type = CommandType.Write; break; default: errorMsg = "发现错误读写类型:" + type; break; } errorMsg = null; } msg.Success = string.IsNullOrEmpty(errorMsg); msg.Message = errorMsg; msg.DataValue = value; }
/// <summary> /// 写入数据 /// </summary> /// <param name="address"></param> /// <param name="value"></param> /// <returns></returns> public ResultData Write(string address, byte[] value) { ResultData rd = new ResultData { Connected = false, Success = false, Message = "当前与PLC通信断开!" }; if (this.Connected) { rd.Connected = true; SiemensMessage msg = Common.GetAddress(address); if (msg == null) { rd.Message = "当前PLC地址不正确!"; return(rd); } msg.Type = CommandType.Write; msg.DataValue = value; msg.DataLength = value.Length; try { SiemensMessage result = plc.Send(msg); if (Connected) { rd.Message = result.Message; } rd.Success = result.Success; rd.Value = result.DataValue; rd.Connected = Connected; } catch (Exception e) { rd.Message = e.Message; } } return(rd); }
/// <summary> /// 发送数据 /// </summary> /// <param name="message"></param> /// <returns></returns> public SiemensMessage Send(SiemensMessage message) { lock (objLock) { response = new SiemensMessage { Type = message.Type, IsByte = message.IsByte, DataValue = message.DataValue, DataLength = message.DataLength, DataAddress = message.DataAddress, DataType = message.DataType, DbBlockNo = message.DbBlockNo, FnCode = message.FnCode }; var data = plcEncoder.Encode(message); SendData(data); return(response); } }
/// <summary> /// 获取PLC地址信息 /// </summary> /// <param name="addr"></param> /// <returns></returns> public static SiemensMessage GetAddress(string addr) { SiemensMessage msg = null; string address = addr.ToUpper(); //地址不能为空,并且字符串长度不能少于2位 if (!string.IsNullOrEmpty(address) && address.Length > 2) { address = address.Replace("DBX", ""); // DB1.DBX0.0 => DB1.0.0 address = address.Replace("DB", "E"); // DB1.DBB0 => E1.EB0 address = address.Replace("DW", "L"); // MDW0 => ML0 IDW0 => IL0 var arr = address.Split('.'); //DB1.DBX0.0 M0.0 I0.0 int arrLength = arr.Length; FnCode fnCode = GetFnCode(arr[0]); //获取功能码 DataType dataType = DataType.None; int addressStart = 0; int dbNumber = 0; bool isByte = true; if (arrLength == 1) { //IB0 QW0 MD0 dataType = GetDataType(arr[0]); addressStart = GetAddressStart(arr[0]); } else if (arrLength == 2) { //I0.0 Q0.0 DB1.DBB0 DB1.DBB20 if (fnCode != FnCode.DB) { isByte = false; dataType = DataType.Bit; addressStart = GetBitStart(arr[0], arr[1]); } else { dataType = GetDataType(arr[1]); addressStart = GetAddressStart(arr[1]); dbNumber = GetDBNumber(arr[0]); } } else if (arrLength == 3 && fnCode == FnCode.DB) { //DB1.0.0 isByte = false; dbNumber = GetDBNumber(arr[0]); addressStart = GetBitStart(arr[1], arr[2]); //有问题 dataType = DataType.Bit; } if (FnCode.None != fnCode && dataType != DataType.None && addressStart >= 0 && dbNumber >= 0) { msg = new SiemensMessage { FnCode = fnCode, DbBlockNo = dbNumber, DataType = dataType, DataAddress = addressStart, IsByte = isByte }; } } return(msg); }
/// <summary> /// 编码 /// </summary> /// <param name="msg"></param> /// <returns></returns> public byte[] Encode(SiemensMessage msg) { int dataAddress = 0; sendData.Clear(); switch (msg.Type) { case CommandType.Head1: case CommandType.Head2: sendData.AddRange(msg.DataValue); break; case CommandType.Read: sendData.Add(3); sendData.Add(0); sendData.Add(0); sendData.Add(0x1F); //长度 sendData.Add(0x02); sendData.Add(0xF0); sendData.Add(0x80); sendData.Add(0x32); sendData.Add(0x01); sendData.Add(0); sendData.Add(0); sendData.Add(0); sendData.Add(0x01); sendData.Add(0); sendData.Add(0x0E); sendData.Add(0); sendData.Add(0); sendData.Add(0x04); sendData.Add(0x01); sendData.Add(0x12); sendData.Add(0x0A); sendData.Add(0x10); //--------------------------- sendData.Add(msg.IsByte ? (byte)2 : (byte)1); //1 为bool 2为byte //读取类型长度 byte =1 , shot = 2 int = 4; string 先读前2位,获取字符串长度,然后在读 sendData.Add((byte)(msg.DataLength >> 8 & 0xFF)); sendData.Add((byte)(msg.DataLength & 0xFF)); //DB块编号 sendData.Add((byte)(msg.DbBlockNo >> 8 & 0xFF)); sendData.Add((byte)(msg.DbBlockNo & 0xFF)); //I/Q/M/DB 功能代码 sendData.Add((byte)msg.FnCode); if (msg.DataType == DataType.Bit) { dataAddress = msg.DataAddress; } else { dataAddress = msg.DataAddress * 8; //长度 byte * 8 } sendData.Add((byte)(dataAddress >> 16 & 0xFF)); sendData.Add((byte)(dataAddress >> 8 & 0xFF)); sendData.Add((byte)(dataAddress & 0xFF)); break; case CommandType.Write: int dataLength = msg.DataLength; sendData.Add(3); sendData.Add(0); //数据长度 sendData.Add((byte)(0x23 + dataLength >> 8 & 0xFF)); sendData.Add((byte)(0x23 + dataLength & 0xFF)); sendData.Add(0x02); sendData.Add(0xF0); sendData.Add(0x80); sendData.Add(0x32); sendData.Add(0x01); sendData.Add(0); sendData.Add(0); sendData.Add(0); sendData.Add(0x01); sendData.Add(0); sendData.Add(0x0E); sendData.Add(0); sendData.Add((byte)(4 + dataLength)); sendData.Add(0x05); sendData.Add(0x01); sendData.Add(0x12); sendData.Add(0x0A); sendData.Add(0x10); //--------------------------- sendData.Add(msg.IsByte ? (byte)2 : (byte)1); //1 为bool 2为byte //数据长度 sendData.Add((byte)(dataLength >> 8 & 0xFF)); sendData.Add((byte)(dataLength & 0xFF)); //DB块编号 sendData.Add((byte)(msg.DbBlockNo >> 8 & 0xFF)); sendData.Add((byte)(msg.DbBlockNo & 0xFF)); //I/Q/M/DB 功能代码 sendData.Add((byte)msg.FnCode); if (msg.DataType == DataType.Bit) { dataAddress = msg.DataAddress; } else { dataAddress = msg.DataAddress * 8; //长度 byte * 8 } sendData.Add((byte)(dataAddress >> 16 & 0xFF)); sendData.Add((byte)(dataAddress >> 8 & 0xFF)); sendData.Add((byte)(dataAddress & 0xFF)); sendData.Add(0); sendData.Add(msg.IsByte ? (byte)4 : (byte)3); //bit 为3 byte 为 4 //类型长度 var dtl = msg.DataType == DataType.Bit ? 1 : dataLength * 8; sendData.Add((byte)(dtl >> 8 & 0xFF)); sendData.Add((byte)(dtl & 0xFF)); sendData.AddRange(msg.DataValue); // 写入数据 break; default: break; } return(sendData.ToArray()); }