/// <summary> /// Creates a <c>BidMessage</c> object with its encoding in a byte array. /// </summary> /// <param name="function">the message's function code.</param> /// <param name="message">the message encoded in a byte array.</param> /// <param name="offset">the start index in the byte array.</param> /// <param name="count">the actual length of message.</param> /// <returns>An initialized <c>BidMessage</c> object.</returns> /// <exception cref="System.NotSupportedException"><c>function</c> is not supported or the message is malformed.</exception> public static BidMessage Create(FunctionCodes function, byte[] message, int offset, int count) { BidMessage result = null; switch (function) { case FunctionCodes.Quote: result = CreateQuoteMessage(message, offset, count); break; case FunctionCodes.SessionKeyReply: result = new SessionKeyReplyMessage(message, offset); break; case FunctionCodes.LoginReply: result = new LoginReplyMessage(message, offset); break; default: throw new NotSupportedException("Unsuppoted message function code."); } Debug.Assert(result != null); return(result); }
public MessageFormat(byte unitId, FunctionCodes code, byte[] data) { this.UnitID = unitId; this.FunctionCode = code; this.Rawdata = new byte[data.Length]; Array.Copy(data, 0, this.Rawdata, 0, this.Rawdata.Length); }
public bool IsInFunction(string function) { if (FunctionCodes.Any(r => function.Contains(r))) { return(true); } else { return(false); } }
/// <summary>按功能码读取</summary> /// <param name="code"></param> /// <param name="host"></param> /// <param name="address"></param> /// <param name="count"></param> /// <returns></returns> /// <exception cref="NotSupportedException"></exception> public virtual Byte[] Read(FunctionCodes code, Byte host, UInt16 address, UInt16 count) { switch (code) { case FunctionCodes.ReadCoil: return(ReadCoil(host, address, count)); case FunctionCodes.ReadDiscrete: return(ReadDiscrete(host, address, count)); case FunctionCodes.ReadRegister: return(ReadRegister(host, address, count)); case FunctionCodes.ReadInput: return(ReadInput(host, address, count)); default: break; } throw new NotSupportedException(); }
/// <summary>按功能码写入</summary> /// <param name="code"></param> /// <param name="host"></param> /// <param name="address"></param> /// <param name="values"></param> /// <returns></returns> public virtual Byte[] Write(FunctionCodes code, Byte host, UInt16 address, UInt16[] values) { switch (code) { case FunctionCodes.WriteCoil: return(WriteCoil(host, address, values[0])); case FunctionCodes.WriteRegister: return(WriteRegister(host, address, values[0])); case FunctionCodes.WriteCoils: return(WriteCoils(host, address, values)); case FunctionCodes.WriteRegisters: return(WriteRegisters(host, address, values)); default: break; } throw new NotSupportedException(); }
/// <summary>发送两字节命令,并接收返回</summary> /// <param name="host"></param> /// <param name="code"></param> /// <param name="address"></param> /// <param name="value"></param> /// <returns></returns> public override Byte[] SendCommand(Byte host, FunctionCodes code, UInt16 address, Object value) { Open(); var cmd = new Byte[8]; cmd[0] = host; cmd[1] = (Byte)code; cmd[2] = (Byte)(address >> 8); cmd[3] = (Byte)(address & 0xFF); if (value is UInt16 v) { cmd[4] = (Byte)(v >> 8); cmd[5] = (Byte)(v & 0xFF); } var crc = Crc(cmd, 0, cmd.Length - 2); cmd[6] = (Byte)(crc & 0xFF); cmd[7] = (Byte)(crc >> 8); { using var span = Tracer?.NewSpan("modbus:SendCommand", cmd.ToHex()); WriteLog("{0}=> {1}", PortName, cmd.ToHex("-")); _port.Write(cmd, 0, cmd.Length); Thread.Sleep(10); } // 串口速度较慢,等待收完数据 WaitMore(_port); try { using var span = Tracer?.NewSpan("modbus:ReceiveCommand"); var rs = new Byte[32]; var c = _port.Read(rs, 0, rs.Length); rs = rs.ReadBytes(0, c); WriteLog("{0}<= {1}", PortName, rs.ToHex("-")); if (span != null) { span.Tag = rs.ToHex(); } if (rs.Length < 2 + 2) { return(null); } // 校验Crc crc = Crc(rs, 0, rs.Length - 2); var crc2 = rs.ToUInt16(rs.Length - 2); if (crc != crc2) { WriteLog("Crc Error {0:X4}!={1:X4} !", crc, crc2); } return(rs.ReadBytes(2, rs.Length - 2 - 2)); } catch (TimeoutException) { return(null); } }
/// <summary>发送两字节命令,并接收返回</summary> /// <param name="host"></param> /// <param name="code"></param> /// <param name="address"></param> /// <param name="value"></param> /// <returns></returns> public override Byte[] SendCommand(Byte host, FunctionCodes code, UInt16 address, Object value) { Open(); var tid = Interlocked.Increment(ref _transactionId); var msg = new ModbusMessage { TransactionId = (UInt16)tid, ProtocolId = ProtocolId, Host = host, Code = code, Address = address, //Count = value }; if (value is UInt16 v) { msg.Count = v; } else if (value is Packet pk) { msg.Payload = pk; } else if (value is Byte[] buf) { msg.Payload = buf; } WriteLog("=> {0}", msg); var cmd = msg.ToPacket().ToArray(); { using var span = Tracer?.NewSpan("modbus:SendCommand", cmd.ToHex()); _stream.Write(cmd, 0, cmd.Length); Thread.Sleep(10); } using var span2 = Tracer?.NewSpan("modbus:ReceiveCommand"); try { var buf = new Byte[BufferSize]; var c = _stream.Read(buf, 0, buf.Length); buf = buf.ReadBytes(0, c); if (span2 != null) { span2.Tag = buf.ToHex(); } var rs = ModbusMessage.Read(buf, true); if (rs == null) { return(null); } WriteLog("<= {0}", rs); return(rs.Payload?.ToArray()); } catch (Exception ex) { span2?.SetError(ex, null); if (ex is TimeoutException) { return(null); } throw; } }
/// <summary>发送两字节命令,并接收返回</summary> /// <param name="host">主机。一般是1</param> /// <param name="code">功能码</param> /// <param name="address">地址。例如0x0002</param> /// <param name="value">数据值</param> /// <returns></returns> public abstract Byte[] SendCommand(Byte host, FunctionCodes code, UInt16 address, Object value);