1using Dreamine.IO.Abstractions.Channels;
2using Dreamine.IO.Abstractions.Controllers;
3using Dreamine.IO.Abstractions.Enums;
4using Dreamine.IO.Abstractions.Models;
5using Dreamine.IO.Abstractions.Results;
192 _options = options ??
throw new ArgumentNullException(nameof(options));
193 _transport = transport ??
throw new ArgumentNullException(nameof(transport));
194 _protocol = protocol ??
throw new ArgumentNullException(nameof(protocol));
220 public IoConnectionState
State {
get;
private set; } = IoConnectionState.Disconnected;
304 public async Task<IoResult>
ConnectAsync(CancellationToken cancellationToken =
default)
307 SetState(IoConnectionState.Connecting);
309 var result = await
_transport.ConnectAsync(cancellationToken).ConfigureAwait(
false);
310 SetState(result.IsSuccess ? IoConnectionState.Connected : IoConnectionState.Faulted);
347 public async Task<IoResult>
DisconnectAsync(CancellationToken cancellationToken =
default)
350 SetState(IoConnectionState.Disconnecting);
352 var result = await
_transport.DisconnectAsync(cancellationToken).ConfigureAwait(
false);
353 SetState(result.IsSuccess ? IoConnectionState.Disconnected : IoConnectionState.Faulted);
390 internal Task<IoResult<bool[]>> ReadDigitalInputsAsync(
391 IReadOnlyList<IoPoint> points,
392 CancellationToken cancellationToken)
394 return SendReadAsync(
433 internal Task<IoResult<bool[]>> ReadDigitalOutputsAsync(
434 IReadOnlyList<IoPoint> points,
435 CancellationToken cancellationToken)
437 return SendReadAsync(
476 internal Task<IoResult> WriteDigitalOutputsAsync(
477 IReadOnlyDictionary<IoPoint, bool> values,
478 CancellationToken cancellationToken)
480 return SendWriteAsync(
519 internal Task<IoResult<double[]>> ReadAnalogInputsAsync(
520 IReadOnlyList<AnalogIoPoint> points,
521 CancellationToken cancellationToken)
523 return SendReadAsync(
562 internal Task<IoResult<double[]>> ReadAnalogOutputsAsync(
563 IReadOnlyList<AnalogIoPoint> points,
564 CancellationToken cancellationToken)
566 return SendReadAsync(
605 internal Task<IoResult> WriteAnalogOutputsAsync(
606 IReadOnlyDictionary<AnalogIoPoint, double> values,
607 CancellationToken cancellationToken)
609 return SendWriteAsync(
639 await
_transport.DisposeAsync().ConfigureAwait(
false);
641 SetState(IoConnectionState.Disconnected);
643 GC.SuppressFinalize(
this);
719 IReadOnlyList<TPoint> points,
720 Func<IReadOnlyList<TPoint>,
byte[]> buildRequest,
721 Func<IReadOnlyList<byte>, IoResult<TValue[]>> parseResponse,
722 CancellationToken cancellationToken)
724 ArgumentNullException.ThrowIfNull(points);
726 if (points.Count == 0)
728 return IoResult<TValue[]>.Failure(
"At least one I/O point is required.");
734 request = buildRequest(points);
738 return IoResult<TValue[]>.Failure(ex.Message);
741 var response = await
SendAsync(request, cancellationToken).ConfigureAwait(
false);
742 if (!response.IsSuccess || response.Value is
null)
744 return IoResult<TValue[]>.Failure(response.Message ??
"Failed to receive the Fastech Ethernet I/O response.", response.ErrorCode);
749 return parseResponse(response.Value);
753 return IoResult<TValue[]>.Failure(ex.Message);
830 IReadOnlyDictionary<TKey, TValue> values,
831 Func<IReadOnlyDictionary<TKey, TValue>,
byte[]> buildRequest,
832 Func<IReadOnlyList<byte>, IoResult> parseResponse,
833 CancellationToken cancellationToken)
836 ArgumentNullException.ThrowIfNull(values);
838 if (values.Count == 0)
840 return IoResult.Failure(
"At least one I/O value is required.");
846 request = buildRequest(values);
850 return IoResult.Failure(ex.Message);
853 var response = await
SendAsync(request, cancellationToken).ConfigureAwait(
false);
854 if (!response.IsSuccess || response.Value is
null)
856 return IoResult.Failure(response.Message ??
"Failed to receive the Fastech Ethernet I/O response.", response.ErrorCode);
861 return parseResponse(response.Value);
865 return IoResult.Failure(ex.Message);
909 private async Task<IoResult<byte[]>>
SendAsync(
byte[] request, CancellationToken cancellationToken)
915 return IoResult<byte[]>.Failure(
"The Fastech Ethernet I/O controller is not connected.");
918 IoResult<byte[]>? lastResult =
null;
920 for (var attempt = 0; attempt <=
_options.RetryCount; attempt++)
922 lastResult = await
_transport.SendAndReceiveAsync(
926 cancellationToken).ConfigureAwait(
false);
928 if (lastResult.IsSuccess)
934 return lastResult ?? IoResult<byte[]>.Failure(
"The Fastech Ethernet I/O request was not sent.");
982 ObjectDisposedException.ThrowIf(
_disposed,
this);
1027 ArgumentNullException.ThrowIfNull(options);
1029 return options.TransportType
switch
1033 _ =>
throw new ArgumentOutOfRangeException(nameof(options), options.
TransportType,
"Unsupported Fastech Ethernet I/O transport type.")
FastechEthernetIoOptions Options
async ValueTask DisposeAsync()
async Task< IoResult > DisconnectAsync(CancellationToken cancellationToken=default)
async Task< IoResult< TValue[]> > SendReadAsync< TPoint, TValue >(IReadOnlyList< TPoint > points, Func< IReadOnlyList< TPoint >, byte[]> buildRequest, Func< IReadOnlyList< byte >, IoResult< TValue[]> > parseResponse, CancellationToken cancellationToken)
FastechEthernetIoController(FastechEthernetIoOptions options, IFastechEthernetIoProtocol protocol)
FastechEthernetIoController(FastechEthernetIoOptions options, IFastechEthernetIoTransport transport, IFastechEthernetIoProtocol protocol)
async Task< IoResult< byte[]> > SendAsync(byte[] request, CancellationToken cancellationToken)
FastechEthernetIoController(FastechEthernetIoOptions options)
async Task< IoResult > ConnectAsync(CancellationToken cancellationToken=default)
void SetState(IoConnectionState state)
readonly IFastechEthernetIoProtocol _protocol
IDigitalInputChannel DigitalInputs
IAnalogInputChannel AnalogInputs
IDigitalOutputChannel DigitalOutputs
readonly FastechEthernetIoOptions _options
static IFastechEthernetIoTransport CreateTransport(FastechEthernetIoOptions options)
async Task< IoResult > SendWriteAsync< TKey, TValue >(IReadOnlyDictionary< TKey, TValue > values, Func< IReadOnlyDictionary< TKey, TValue >, byte[]> buildRequest, Func< IReadOnlyList< byte >, IoResult > parseResponse, CancellationToken cancellationToken)
IAnalogOutputChannel AnalogOutputs
EventHandler< IoConnectionState >? StateChanged
readonly IFastechEthernetIoTransport _transport
FastechEthernetIoTransportType TransportType
IoResult< double[]> ParseAnalogOutputs(IReadOnlyList< byte > responseFrame, int count)
byte[] BuildReadDigitalOutputs(IReadOnlyList< IoPoint > points)
byte[] BuildReadDigitalInputs(IReadOnlyList< IoPoint > points)
IoResult< bool[]> ParseDigitalOutputs(IReadOnlyList< byte > responseFrame, int count)
IoResult< bool[]> ParseDigitalInputs(IReadOnlyList< byte > responseFrame, int count)
byte[] BuildWriteDigitalOutputs(IReadOnlyDictionary< IoPoint, bool > values)
IoResult< double[]> ParseAnalogInputs(IReadOnlyList< byte > responseFrame, int count)
byte[] BuildReadAnalogInputs(IReadOnlyList< AnalogIoPoint > points)
IoResult ParseWriteResponse(IReadOnlyList< byte > responseFrame)
byte[] BuildReadAnalogOutputs(IReadOnlyList< AnalogIoPoint > points)
byte[] BuildWriteAnalogOutputs(IReadOnlyDictionary< AnalogIoPoint, double > values)