//TODO: Evaluate ReadHoldingRegisters return type. Should this be words? Bytes? something else? // At the core of the protocol, this is really returning words. The words can be interpreted // as floating point, integers, unsigned, etc. public IEnumerable <Int16> ReadHoldingRegisters(Int16 startRegister, Int16 count) { List <byte> mbPacket = new List <byte>(); mbPacket.Add(0x03); mbPacket.AddRange(startRegister.GetBytes()); mbPacket.AddRange(count.GetBytes()); MBAP mbap = MBAP.Create((Int16)(mbPacket.Count + 1), 0); mbPacket.InsertRange(0, mbap.GetBytes()); tcpClient.GetStream().Write(mbPacket.ToArray(), 0, mbPacket.Count); byte[] readBuffer = new byte[500]; tcpClient.GetStream().Read(readBuffer, 0, 500); int returnCount = (int)readBuffer[8]; List <Int16> returnList = new List <short>(); for (int i = 9; i < 9 + returnCount; i += 2) { returnList.Add(Int16Extensions.FromBytes(readBuffer[i], readBuffer[i + 1])); } return(returnList); }
public void WriteMultipleRegisters(Int16 startRegister, IEnumerable <Int16> values) { List <byte> mbPacket = new List <byte>(); mbPacket.Add(0x10); mbPacket.AddRange(startRegister.GetBytes()); mbPacket.AddRange(((Int16)(values.Count())).GetBytes()); var data = values.SelectMany(v => new List <byte>() { v.HighByte(), v.LowByte() }); mbPacket.Add(((Int16)data.Count()).LowByte()); mbPacket.AddRange(data.ToArray()); MBAP mbap = MBAP.Create((Int16)(mbPacket.Count + 1), 0); mbPacket.InsertRange(0, mbap.GetBytes()); tcpClient.GetStream().Write(mbPacket.ToArray(), 0, mbPacket.Count); byte[] buffer = new byte[500]; //technically, the operation should be confirmed by examining the response tcpClient.GetStream().Read(buffer, 0, buffer.Length); //error function codes will be: (original function code) | (0x80) if ((buffer[7] & 0x80) > 0) { throw new Exception(); } }
public override ModbusTCPMessage Process(IMemoryModel memory) { int address = Int16Extensions.FromBytes(PDU.Data.First(), PDU.Data.Skip(1).First()); int length = Int16Extensions.FromBytes(PDU.Data.Skip(2).First(), PDU.Data.Skip(3).First()); try { var values = memory.Read4x(address, length); ProtocolDataUnit pdu = PDU.ValidResponse( new byte[] { (byte)(values.Count() * 2) } .Concat(values.SelectMany(v => v.GetBytes()))); ModbusTCPMessage reply = Create( MBAP.Create((byte)(pdu.GetBytes().Count() + 1), ApplicationHeader.UnitID), pdu); return(reply); } catch { ProtocolDataUnit pdu = PDU.ErrorResponse(new byte[] { 0x01 }); ModbusTCPMessage reply = Create( MBAP.Create((byte)(pdu.GetBytes().Count() + 1), ApplicationHeader.UnitID), pdu); return(reply); } }
public static ModbusTCPMessage Create(MBAP appHeader, ProtocolDataUnit pdu) { switch (pdu.FunctionCode) { case ModbusFunctionCodes.ReadHoldingRegisters: return(new ReadRegistersMessage(appHeader, pdu)); case ModbusFunctionCodes.PresetMultipleRegisters: return(new WriteHoldingRegistersMessage(appHeader, pdu)); default: return(new ModbusTCPMessage(appHeader, pdu)); } }
public override ModbusTCPMessage Process(IMemoryModel memory) { try { int address = StartAddress(); var values = ParseValues(); memory.Write4x(address, values); var pdu = PDU.ValidResponse(((Int16)values.Count()).GetBytes()); var reply = Create( MBAP.Create((byte)(pdu.GetBytes().Count() + 1), ApplicationHeader.UnitID), pdu); return(reply); } catch { var pdu = PDU.ErrorResponse(new byte[] { 0x01 }); ModbusTCPMessage reply = Create( MBAP.Create((byte)(pdu.GetBytes().Count() + 1), ApplicationHeader.UnitID), pdu); return(reply); } }
public ReadRegistersMessage(MBAP appHeader, ProtocolDataUnit pdu) : base(appHeader, pdu) { }
protected ModbusTCPMessage(IEnumerable <byte> messageBuffer) { ApplicationHeader = MBAP.ParseFromMessage(messageBuffer); PDU = new ProtocolDataUnit(messageBuffer); }
protected ModbusTCPMessage(MBAP appHeader, ProtocolDataUnit pdu) { ApplicationHeader = appHeader; PDU = pdu; }
public WriteHoldingRegistersMessage(MBAP appHeader, ProtocolDataUnit pdu) : base(appHeader, pdu) { }