1using System.Globalization;
2using System.Runtime.InteropServices;
3using Dreamine.PLC.Abstractions.Devices;
4using Dreamine.PLC.Abstractions.Results;
5using Dreamine.PLC.Core.Clients;
113 _options = options ??
throw new ArgumentNullException(nameof(options));
114 _factory = factory ??
throw new ArgumentNullException(nameof(factory));
177 cancellationToken.ThrowIfCancellationRequested();
180 ComInvoker.SetProperty(
_component,
"ActLogicalStationNumber",
_options.LogicalStationNumber);
182 var resultCode = ComInvoker.ToReturnCode(ComInvoker.Invoke(
_component,
_options.OpenMethodName));
183 return Task.FromResult(
ToResult(resultCode,
"MX Component open failed."));
228 cancellationToken.ThrowIfCancellationRequested();
232 return Task.FromResult(PlcResult.Success());
235 var resultCode = ComInvoker.ToReturnCode(ComInvoker.Invoke(
_component,
_options.CloseMethodName));
237 return Task.FromResult(
ToResult(resultCode,
"MX Component close failed."));
307 CancellationToken cancellationToken)
311 var buffer =
new short[count];
312 var args =
new object?[] { device, count, buffer };
316 cancellationToken.ThrowIfCancellationRequested();
318 var resultCode = ComInvoker.ToReturnCode(ComInvoker.InvokeWithByRef(component,
_options.ReadDeviceBlock2MethodName, args, 2));
321 return Task.FromResult(PlcResult<
bool[]>.Success(values));
324 catch (MissingMethodException)
332 catch (InvalidOperationException ex) when (ex.InnerException is COMException)
407 CancellationToken cancellationToken)
411 var buffer =
new short[count];
412 var args =
new object?[] { device, count, buffer };
416 cancellationToken.ThrowIfCancellationRequested();
418 var resultCode = ComInvoker.ToReturnCode(ComInvoker.InvokeWithByRef(component,
_options.ReadDeviceBlock2MethodName, args, 2));
421 return Task.FromResult(PlcResult<
short[]>.Success(values));
424 catch (MissingMethodException)
432 catch (InvalidOperationException ex) when (ex.InnerException is COMException)
498 IReadOnlyList<bool> values,
499 CancellationToken cancellationToken)
503 for (var index = 0; index < values.Count; index++)
505 cancellationToken.ThrowIfCancellationRequested();
507 var resultCode = ComInvoker.ToReturnCode(ComInvoker.Invoke(
511 values[index] ? 1 : 0));
515 return Task.FromResult(
ToResult(resultCode,
"MX Component bit write failed."));
519 return Task.FromResult(PlcResult.Success());
580 IReadOnlyList<short> values,
581 CancellationToken cancellationToken)
585 var data = values.ToArray();
589 cancellationToken.ThrowIfCancellationRequested();
591 var resultCode = ComInvoker.ToReturnCode(ComInvoker.InvokeWithByRef(
593 _options.WriteDeviceBlock2MethodName,
594 [device, values.Count, data],
599 return Task.FromResult(PlcResult.Success());
602 catch (MissingMethodException)
610 catch (InvalidOperationException ex) when (ex.InnerException is COMException)
615 for (var index = 0; index < values.Count; index++)
617 cancellationToken.ThrowIfCancellationRequested();
619 var resultCode = ComInvoker.ToReturnCode(ComInvoker.Invoke(
627 return Task.FromResult(
ToResult(resultCode,
"MX Component word write failed."));
631 return Task.FromResult(PlcResult.Success());
652 await base.DisposeAsync().ConfigureAwait(
false);
724 CancellationToken cancellationToken)
726 var values =
new short[count];
728 for (var index = 0; index < count; index++)
730 cancellationToken.ThrowIfCancellationRequested();
732 var args =
new object?[]
738 var resultCode = ComInvoker.ToReturnCode(ComInvoker.InvokeWithByRef(component,
_options.ReadDeviceMethodName, args, 1));
741 return Task.FromResult(PlcResult<
short[]>.Failure($
"MX Component word read failed. code={resultCode}", resultCode));
744 values[index] = Convert.ToInt16(args[1], CultureInfo.InvariantCulture);
747 return Task.FromResult(PlcResult<
short[]>.Success(values));
818 CancellationToken cancellationToken)
820 var values =
new bool[count];
822 for (var index = 0; index < count; index++)
824 cancellationToken.ThrowIfCancellationRequested();
826 var args =
new object?[]
832 var resultCode = ComInvoker.ToReturnCode(ComInvoker.InvokeWithByRef(component,
_options.ReadDeviceMethodName, args, 1));
835 return Task.FromResult(PlcResult<
bool[]>.Failure($
"MX Component bit read failed. code={resultCode}", resultCode));
838 values[index] = Convert.ToInt32(args[1], CultureInfo.InvariantCulture) != 0;
841 return Task.FromResult(PlcResult<
bool[]>.Success(values));
870 return _component ??
throw new InvalidOperationException(
"MX Component is not connected.");
888 if (OperatingSystem.IsWindows() && Marshal.IsComObject(
_component))
928 private static PlcResult
ToResult(
int resultCode,
string message)
930 return resultCode == 0
931 ? PlcResult.Success()
932 : PlcResult.Failure($
"{message} code={resultCode}", resultCode);
985 values =
new short[count];
989 case short[] shorts when shorts.Length >= count:
990 Array.Copy(shorts, values, count);
992 case int[] integers when integers.Length >= count:
993 for (var index = 0; index < count; index++)
995 values[index] = Convert.ToInt16(integers[index], CultureInfo.InvariantCulture);
999 case Array array when array.Length >= count:
1000 for (var index = 0; index < count; index++)
1002 values[index] = Convert.ToInt16(array.GetValue(index), CultureInfo.InvariantCulture);
1069 values =
new bool[count];
1073 case bool[] booleans when booleans.Length >= count:
1074 Array.Copy(booleans, values, count);
1076 case short[] shorts when shorts.Length >= count:
1077 for (var index = 0; index < count; index++)
1079 values[index] = shorts[index] != 0;
1083 case int[] integers when integers.Length >= count:
1084 for (var index = 0; index < count; index++)
1086 values[index] = integers[index] != 0;
1090 case Array array when array.Length >= count:
1091 for (var index = 0; index < count; index++)
1093 values[index] = Convert.ToInt32(array.GetValue(index), CultureInfo.InvariantCulture) != 0;
override Task< PlcResult > DisconnectCoreAsync(CancellationToken cancellationToken)
MitsubishiMxComponentPlcClient(MitsubishiMxComponentOptions options)
override Task< PlcResult > WriteWordsCoreAsync(PlcAddress address, IReadOnlyList< short > values, CancellationToken cancellationToken)
override Task< PlcResult< bool[]> > ReadBitsCoreAsync(PlcAddress address, int count, CancellationToken cancellationToken)
static bool TryExtractShortArray(object? source, int count, out short[] values)
MitsubishiMxComponentOptions Options
readonly IComObjectFactory _factory
static bool TryExtractBoolArray(object? source, int count, out bool[] values)
Task< PlcResult< short[]> > ReadWordsOneByOne(object component, PlcAddress address, int count, CancellationToken cancellationToken)
override async ValueTask DisposeAsync()
MitsubishiMxComponentPlcClient(MitsubishiMxComponentOptions options, IComObjectFactory factory)
override Task< PlcResult< short[]> > ReadWordsCoreAsync(PlcAddress address, int count, CancellationToken cancellationToken)
Task< PlcResult< bool[]> > ReadBitsOneByOne(object component, PlcAddress address, int count, CancellationToken cancellationToken)
object RequireComponent()
static PlcResult ToResult(int resultCode, string message)
override Task< PlcResult > WriteBitsCoreAsync(PlcAddress address, IReadOnlyList< bool > values, CancellationToken cancellationToken)
readonly MitsubishiMxComponentOptions _options
override Task< PlcResult > ConnectCoreAsync(CancellationToken cancellationToken)
static string Format(PlcAddress address)
static string FormatOffset(PlcAddress address, int delta)