public async Task WriteMultipleCoils(ushort address, bool[] states, CancellationToken token = default) { ThrowIfDisposed(); ThrowIfNotConnected(); if (token == null) { throw new ArgumentNullException(nameof(token)); } var header = CreateHeader(); var frame = new RequestAdu { Header = header, Pdu = new RequestWriteMultipleCoils { Address = address, CoilStates = states } }; var written = _writer.WriteFrame(frame); _connection.Transport.Output.Advance(written); var waitForResponse = WaitForResponse <ResponseWriteMultipleCoils>(frame, token).ConfigureAwait(false); var result = await _connection.Transport.Output.FlushAsync(token).ConfigureAwait(false); var response = await waitForResponse; // TODO: check if quantity and adress are correct? }
public async Task <bool> WriteSingleCoil(ushort address, bool state, CancellationToken token = default) { ThrowIfDisposed(); ThrowIfNotConnected(); if (token == null) { throw new ArgumentNullException(nameof(token)); } var header = CreateHeader(); var frame = new RequestAdu { Header = header, Pdu = new RequestWriteSingleCoil { Address = address, CoilState = state, } }; var written = _writer.WriteFrame(frame); _connection.Transport.Output.Advance(written); var waitForResponse = WaitForResponse <ResponseWriteSingleCoil>(frame, token).ConfigureAwait(false); var result = await _connection.Transport.Output.FlushAsync(token).ConfigureAwait(false); var response = await waitForResponse; return(response.Result); }
public async Task <ushort[]> ReadInputRegisters(ushort address, ushort quantity, CancellationToken token = default) { ThrowIfDisposed(); ThrowIfNotConnected(); if (token == null) { throw new ArgumentNullException(nameof(token)); } var header = CreateHeader(); var frame = new RequestAdu { Header = header, Pdu = new RequestReadInputRegisters { Address = address, Quantity = quantity, } }; var written = _writer.WriteFrame(frame); _connection.Transport.Output.Advance(written); var waitForResponse = WaitForResponse <ResponseReadInputRegisters>(frame, token).ConfigureAwait(false); var flushResult = await _connection.Transport.Output.FlushAsync(token).ConfigureAwait(false); var response = await waitForResponse; return(response.Results); }
public void ModbusFrameWriter_WriteFrame_CorrectlyWritesAReadInputRegistersRequest() { // Given var request = new RequestAdu { Header = new Header(transactionID: 1, unitID: 4), Pdu = new RequestReadInputRegisters { Address = 0x0040, Quantity = 0x000A, }, }; var arraybuffer = new ArrayBufferWriter <byte>(); // When var writer = new ModbusFrameWriter(arraybuffer); var position = writer.WriteFrame(request); arraybuffer.Advance(position); // Then var data = arraybuffer.WrittenSpan.ToArray(); Assert.Equal( new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x04, 0x04, 0x00, 0x40, 0x00, 0x0A }, data ); }
public void ModbusFrameWriter_WriteFrame_CorrectlyWritesAWriteSingleCoilRequest() { // Given var request = new RequestAdu { Header = new Header(transactionID: 1, unitID: 4), Pdu = new RequestWriteSingleCoil { Address = 0x0041, CoilState = true, }, }; var arraybuffer = new ArrayBufferWriter <byte>(); // When var writer = new ModbusFrameWriter(arraybuffer); var position = writer.WriteFrame(request); arraybuffer.Advance(position); // Then var data = arraybuffer.WrittenSpan.ToArray(); Assert.Equal( new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x04, 0x05, 0x00, 0x41, 0xFF, 0x00 }, data ); }
public async Task <List <bool> > ReadDiscreteInputs(ushort address, ushort quantity, CancellationToken token = default) { ThrowIfDisposed(); ThrowIfNotConnected(); if (token == null) { throw new ArgumentNullException(nameof(token)); } var header = CreateHeader(); var frame = new RequestAdu { Header = header, Pdu = new RequestReadDiscreteInputs { Address = address, Quantity = quantity, } }; var written = _writer.WriteFrame(frame); _connection.Transport.Output.Advance(written); var waitForResponse = WaitForResponse <ResponseReadDiscreteInputs>(frame, token).ConfigureAwait(false); var flushResult = await _connection.Transport.Output.FlushAsync(token).ConfigureAwait(false); var response = await waitForResponse; var bits = new BitArray(response.Coils); var result = new List <bool>(); for (var i = 0; i < quantity; i++) { result.Add(bits[i]); } return(result); }
private async Task <T> WaitForResponse <T>(RequestAdu request, CancellationToken token = default) where T : IResponsePdu { var header = request.Header; var source = new TaskCompletionSource <ResponseAdu>(TaskCreationOptions.RunContinuationsAsynchronously); if (!_transactions.TryAdd(header.TransactionID, source)) { throw new InvalidOperationException("Can't start transaction."); } var race = await Task.WhenAny(source.Task, Task.Delay(_timeout, token)).ConfigureAwait(false); if (race == source.Task) { var responseFrame = await source.Task; if (responseFrame.Pdu is T response) { return(response); } else if (responseFrame.Pdu is ResponseError error) { throw new ModbusRequestException(error.ErrorCode); } else { throw new ModbusRequestException("Unknown response"); } } else { source.SetCanceled(); _transactions.Remove(header.TransactionID, out var _); throw new TimeoutException(); } }
public int WriteFrame(RequestAdu frame) => frame.Pdu switch {