private T Write <T>(ModbusDevice device, ModbusFunctionCode functionCode, int zeroBasedOffset, Action <IMessageBufferWriter> writeAction, Func <IMessageBufferReader, T> readValueFunc) { var requestContext = new ModbusTransportContext() { TransactionIdentifier = GetTransactionIdentifier() }; ModbusTransport.SendMessage(requestContext, (writer) => { writer.Push(device.Address); writer.Push((byte)functionCode); writer.Push((byte)((zeroBasedOffset >> 8) & 0xFF)); writer.Push((byte)((zeroBasedOffset >> 0) & 0xFF)); writeAction(writer); }); T returnedValue = default; var responseContext = ModbusTransport.ReceiveMessage( (reader) => { if (reader.PushByteFromStream() != device.Address) { throw new InvalidOperationException(); } byte receivedFunctionCode = reader.PushByteFromStream(); if (receivedFunctionCode == ((byte)functionCode | 0x80)) { var exceptionCode = (ModbusExceptionCode)reader.PushByteFromStream(); throw new ModbusException(exceptionCode); } if (receivedFunctionCode != (byte)functionCode) { throw new InvalidOperationException(); } if ((ushort)((reader.PushByteFromStream() << 8) + (reader.PushByteFromStream() << 0)) != zeroBasedOffset) { throw new InvalidOperationException(); } returnedValue = readValueFunc(reader); }); if (requestContext.TransactionIdentifier != responseContext.TransactionIdentifier) { throw new InvalidOperationException(); } return(returnedValue !); }
private void Read(ModbusDevice device, ModbusFunctionCode functionCode, int zeroBasedOffset, int count, Action <MessageBufferSpan> actionWithReturnedBuffer) { var requestContext = new ModbusTransportContext() { TransactionIdentifier = GetTransactionIdentifier() }; ModbusTransport.SendMessage(requestContext, (writer) => { writer.Push(device.Address); writer.Push((byte)functionCode); writer.Push((byte)((zeroBasedOffset >> 8) & 0xFF)); writer.Push((byte)((zeroBasedOffset >> 0) & 0xFF)); writer.Push((byte)((count >> 8) & 0xFF)); writer.Push((byte)((count >> 0) & 0xFF)); }); MessageBufferSpan?receivedBuffer = null; var responseContext = ModbusTransport.ReceiveMessage( (reader) => { if (reader.PushByteFromStream() != device.Address) { throw new InvalidOperationException(); } byte receivedFunctionCode = reader.PushByteFromStream(); if (receivedFunctionCode == ((byte)functionCode | 0x80)) { var exceptionCode = (ModbusExceptionCode)reader.PushByteFromStream(); throw new ModbusException(exceptionCode); } if (receivedFunctionCode != (byte)functionCode) { throw new InvalidOperationException(); } var byteCount = reader.PushByteFromStream(); reader.PushFromStream(byteCount); receivedBuffer = new MessageBufferSpan(reader.Buffer, (ushort)(reader.Buffer.Length - byteCount), byteCount); }); if (responseContext.TransactionIdentifier != requestContext.TransactionIdentifier) { throw new InvalidOperationException(); } actionWithReturnedBuffer(receivedBuffer !); }
public void HandleRequest(params ModbusDevice[] devices) { if (devices is null) { throw new ArgumentNullException(nameof(devices)); } if (devices.Length == 0) { throw new ArgumentException(); } MessageHandler?messageHandler = null; ModbusDevice? device = null; var requestContext = ModbusTransport.ReceiveMessage(reader => { var deviceAddress = reader.PushByteFromStream(); device = devices.FirstOrDefault(_ => _.Address == deviceAddress); if (device == null) { throw new InvalidOperationException($"Received request for device with unknown address {deviceAddress}"); } var functionCode = (ModbusFunctionCode)reader.PushByteFromStream(); messageHandler = functionCode switch { ModbusFunctionCode.ReadDiscreteInputs => ReadDiscreteInputsHandler.Create(reader), ModbusFunctionCode.ReadCoils => ReadCoilsHandler.Create(reader), ModbusFunctionCode.ReadInputRegisters => ReadInputRegistersHandler.Create(reader), ModbusFunctionCode.ReadHoldingRegisters => ReadHoldingRegistersHandler.Create(reader), ModbusFunctionCode.WriteSingleCoil => WriteSingleCoilHandler.Create(reader), ModbusFunctionCode.WriteSingleRegister => WriteSingleRegisterHandler.Create(reader), ModbusFunctionCode.WriteMultipleCoils => WriteMultipleCoilsHandler.Create(reader), ModbusFunctionCode.WriteMultipleRegisters => WriteMultipleRegistersHandler.Create(reader), ModbusFunctionCode.ReadWriteMultipleRegisters => ReadWriteMultipleRegistersHandler.Create(reader), _ => throw new NotSupportedException($"Function {functionCode} not supported"), }; }); if (messageHandler is WriteHandler writeHandler) { writeHandler.UpdateMemory(device !); } ModbusTransport.SendMessage(requestContext, writer => { messageHandler !.WriteResponse(device !, writer); });