Dreamine.IO.Fastech.Ethernet 1.0.1
Dreamine.IO.Fastech.Ethernet 산업 자동화 및 I/O 기능을 제공합니다.
로딩중...
검색중...
일치하는것 없음
FastechEthernetIoController.cs
이 파일의 문서화 페이지로 가기
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;
10
12
21public sealed class FastechEthernetIoController : IIoController
22{
58 private bool _disposed;
59
93 : this(
94 options,
95 CreateTransport(options),
97 {
98 }
99
143 : this(options, CreateTransport(options), protocol)
144 {
145 }
146
191 {
192 _options = options ?? throw new ArgumentNullException(nameof(options));
193 _transport = transport ?? throw new ArgumentNullException(nameof(transport));
194 _protocol = protocol ?? throw new ArgumentNullException(nameof(protocol));
195
200 }
201
211
220 public IoConnectionState State { get; private set; } = IoConnectionState.Disconnected;
221
230 public event EventHandler<IoConnectionState>? StateChanged;
231
240 public IDigitalInputChannel DigitalInputs { get; }
241
250 public IDigitalOutputChannel DigitalOutputs { get; }
251
260 public IAnalogInputChannel AnalogInputs { get; }
261
270 public IAnalogOutputChannel AnalogOutputs { get; }
271
304 public async Task<IoResult> ConnectAsync(CancellationToken cancellationToken = default)
305 {
307 SetState(IoConnectionState.Connecting);
308
309 var result = await _transport.ConnectAsync(cancellationToken).ConfigureAwait(false);
310 SetState(result.IsSuccess ? IoConnectionState.Connected : IoConnectionState.Faulted);
311
312 return result;
313 }
314
347 public async Task<IoResult> DisconnectAsync(CancellationToken cancellationToken = default)
348 {
350 SetState(IoConnectionState.Disconnecting);
351
352 var result = await _transport.DisconnectAsync(cancellationToken).ConfigureAwait(false);
353 SetState(result.IsSuccess ? IoConnectionState.Disconnected : IoConnectionState.Faulted);
354
355 return result;
356 }
357
390 internal Task<IoResult<bool[]>> ReadDigitalInputsAsync(
391 IReadOnlyList<IoPoint> points,
392 CancellationToken cancellationToken)
393 {
394 return SendReadAsync(
395 points,
397 response => _protocol.ParseDigitalInputs(response, points.Count),
398 cancellationToken);
399 }
400
433 internal Task<IoResult<bool[]>> ReadDigitalOutputsAsync(
434 IReadOnlyList<IoPoint> points,
435 CancellationToken cancellationToken)
436 {
437 return SendReadAsync(
438 points,
440 response => _protocol.ParseDigitalOutputs(response, points.Count),
441 cancellationToken);
442 }
443
476 internal Task<IoResult> WriteDigitalOutputsAsync(
477 IReadOnlyDictionary<IoPoint, bool> values,
478 CancellationToken cancellationToken)
479 {
480 return SendWriteAsync(
481 values,
484 cancellationToken);
485 }
486
519 internal Task<IoResult<double[]>> ReadAnalogInputsAsync(
520 IReadOnlyList<AnalogIoPoint> points,
521 CancellationToken cancellationToken)
522 {
523 return SendReadAsync(
524 points,
526 response => _protocol.ParseAnalogInputs(response, points.Count),
527 cancellationToken);
528 }
529
562 internal Task<IoResult<double[]>> ReadAnalogOutputsAsync(
563 IReadOnlyList<AnalogIoPoint> points,
564 CancellationToken cancellationToken)
565 {
566 return SendReadAsync(
567 points,
569 response => _protocol.ParseAnalogOutputs(response, points.Count),
570 cancellationToken);
571 }
572
605 internal Task<IoResult> WriteAnalogOutputsAsync(
606 IReadOnlyDictionary<AnalogIoPoint, double> values,
607 CancellationToken cancellationToken)
608 {
609 return SendWriteAsync(
610 values,
613 cancellationToken);
614 }
615
632 public async ValueTask DisposeAsync()
633 {
634 if (_disposed)
635 {
636 return;
637 }
638
639 await _transport.DisposeAsync().ConfigureAwait(false);
640 _disposed = true;
641 SetState(IoConnectionState.Disconnected);
642
643 GC.SuppressFinalize(this);
644 }
645
718 private async Task<IoResult<TValue[]>> SendReadAsync<TPoint, TValue>(
719 IReadOnlyList<TPoint> points,
720 Func<IReadOnlyList<TPoint>, byte[]> buildRequest,
721 Func<IReadOnlyList<byte>, IoResult<TValue[]>> parseResponse,
722 CancellationToken cancellationToken)
723 {
724 ArgumentNullException.ThrowIfNull(points);
725
726 if (points.Count == 0)
727 {
728 return IoResult<TValue[]>.Failure("At least one I/O point is required.");
729 }
730
731 byte[] request;
732 try
733 {
734 request = buildRequest(points);
735 }
736 catch (Exception ex)
737 {
738 return IoResult<TValue[]>.Failure(ex.Message);
739 }
740
741 var response = await SendAsync(request, cancellationToken).ConfigureAwait(false);
742 if (!response.IsSuccess || response.Value is null)
743 {
744 return IoResult<TValue[]>.Failure(response.Message ?? "Failed to receive the Fastech Ethernet I/O response.", response.ErrorCode);
745 }
746
747 try
748 {
749 return parseResponse(response.Value);
750 }
751 catch (Exception ex)
752 {
753 return IoResult<TValue[]>.Failure(ex.Message);
754 }
755 }
756
829 private async Task<IoResult> SendWriteAsync<TKey, TValue>(
830 IReadOnlyDictionary<TKey, TValue> values,
831 Func<IReadOnlyDictionary<TKey, TValue>, byte[]> buildRequest,
832 Func<IReadOnlyList<byte>, IoResult> parseResponse,
833 CancellationToken cancellationToken)
834 where TKey : notnull
835 {
836 ArgumentNullException.ThrowIfNull(values);
837
838 if (values.Count == 0)
839 {
840 return IoResult.Failure("At least one I/O value is required.");
841 }
842
843 byte[] request;
844 try
845 {
846 request = buildRequest(values);
847 }
848 catch (Exception ex)
849 {
850 return IoResult.Failure(ex.Message);
851 }
852
853 var response = await SendAsync(request, cancellationToken).ConfigureAwait(false);
854 if (!response.IsSuccess || response.Value is null)
855 {
856 return IoResult.Failure(response.Message ?? "Failed to receive the Fastech Ethernet I/O response.", response.ErrorCode);
857 }
858
859 try
860 {
861 return parseResponse(response.Value);
862 }
863 catch (Exception ex)
864 {
865 return IoResult.Failure(ex.Message);
866 }
867 }
868
909 private async Task<IoResult<byte[]>> SendAsync(byte[] request, CancellationToken cancellationToken)
910 {
912
913 if (State != IoConnectionState.Connected || !_transport.IsConnected)
914 {
915 return IoResult<byte[]>.Failure("The Fastech Ethernet I/O controller is not connected.");
916 }
917
918 IoResult<byte[]>? lastResult = null;
919
920 for (var attempt = 0; attempt <= _options.RetryCount; attempt++)
921 {
922 lastResult = await _transport.SendAndReceiveAsync(
923 request,
924 _options.ReceiveTimeoutMs,
925 _options.ExpectedResponseLength,
926 cancellationToken).ConfigureAwait(false);
927
928 if (lastResult.IsSuccess)
929 {
930 return lastResult;
931 }
932 }
933
934 return lastResult ?? IoResult<byte[]>.Failure("The Fastech Ethernet I/O request was not sent.");
935 }
936
953 private void SetState(IoConnectionState state)
954 {
955 if (State == state)
956 {
957 return;
958 }
959
960 State = state;
961 StateChanged?.Invoke(this, state);
962 }
963
980 private void ThrowIfDisposed()
981 {
982 ObjectDisposedException.ThrowIf(_disposed, this);
983 }
984
1026 {
1027 ArgumentNullException.ThrowIfNull(options);
1028
1029 return options.TransportType switch
1030 {
1033 _ => throw new ArgumentOutOfRangeException(nameof(options), options.TransportType, "Unsupported Fastech Ethernet I/O transport type.")
1034 };
1035 }
1036}
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)
async Task< IoResult > ConnectAsync(CancellationToken cancellationToken=default)
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)
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)