添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
using MaxwellFramework.Core.Attributes;
|
||||
using MainShell.Hardware;
|
||||
using MwFramework.Device;
|
||||
using System;
|
||||
|
||||
namespace MainShell.Hardware.Acs
|
||||
{
|
||||
public interface IAcsAddressAccessService
|
||||
{
|
||||
bool IsReady { get; }
|
||||
|
||||
object Read(AcsAddressDefinition addressDefinition);
|
||||
|
||||
object Read(AcsAddressDefinition addressDefinition, int index1, int index2);
|
||||
|
||||
object ReadRange(AcsAddressDefinition addressDefinition, int from1, int to1, int from2, int to2);
|
||||
|
||||
T Read<T>(AcsAddressDefinition addressDefinition);
|
||||
|
||||
bool Write(AcsAddressDefinition addressDefinition, object value);
|
||||
|
||||
bool Write(AcsAddressDefinition addressDefinition, object value, int index1, int index2);
|
||||
|
||||
bool WriteRange(AcsAddressDefinition addressDefinition, object value, int from1, int to1, int from2, int to2);
|
||||
}
|
||||
|
||||
[Singleton]
|
||||
public sealed class AcsAddressAccessService : IAcsAddressAccessService
|
||||
{
|
||||
private const int DefaultBufferId = -1;
|
||||
private readonly HardwareManager _hardwareManager;
|
||||
|
||||
public AcsAddressAccessService(HardwareManager hardwareManager)
|
||||
{
|
||||
_hardwareManager = hardwareManager ?? throw new ArgumentNullException(nameof(hardwareManager));
|
||||
}
|
||||
|
||||
public bool IsReady
|
||||
{
|
||||
get
|
||||
{
|
||||
return _hardwareManager.AcsCard != null
|
||||
&& _hardwareManager.AcsCard.Controller != null
|
||||
&& _hardwareManager.AcsCard.IsOpen;
|
||||
}
|
||||
}
|
||||
|
||||
public object Read(AcsAddressDefinition addressDefinition)
|
||||
{
|
||||
AcsAddressDefinition validatedAddress = ValidateAddress(addressDefinition);
|
||||
IMotionController controller = GetController();
|
||||
string variableName = ResolveVariableName(validatedAddress);
|
||||
bool result= controller.ReadVariableBuffer(DefaultBufferId, variableName,out object val);
|
||||
if (!result)
|
||||
{
|
||||
throw CreateReadWriteException("Read", validatedAddress);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public object Read(AcsAddressDefinition addressDefinition, int index1, int index2)
|
||||
{
|
||||
AcsAddressDefinition validatedAddress = ValidateAddress(addressDefinition);
|
||||
ValidateIndex(index1, nameof(index1));
|
||||
ValidateIndex(index2, nameof(index2));
|
||||
IMotionController controller = GetController();
|
||||
string variableName = ResolveVariableName(validatedAddress);
|
||||
bool result = controller.ReadVariableBuffer(DefaultBufferId, variableName, out object val, index1, index2);
|
||||
if (!result)
|
||||
{
|
||||
throw CreateReadWriteException("Read", validatedAddress);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public object ReadRange(AcsAddressDefinition addressDefinition, int from1, int to1, int from2, int to2)
|
||||
{
|
||||
AcsAddressDefinition validatedAddress = ValidateAddress(addressDefinition);
|
||||
ValidateRange(from1, to1, nameof(from1), nameof(to1));
|
||||
ValidateRange(from2, to2, nameof(from2), nameof(to2));
|
||||
|
||||
IMotionController controller = GetController();
|
||||
string variableName = ResolveVariableName(validatedAddress);
|
||||
object value;
|
||||
bool result = controller.ReadVariableBuffer(DefaultBufferId, variableName, out value, from1, to1, from2, to2);
|
||||
if (!result)
|
||||
{
|
||||
throw CreateReadWriteException("Read", validatedAddress);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public T Read<T>(AcsAddressDefinition addressDefinition)
|
||||
{
|
||||
AcsAddressDefinition validatedAddress = ValidateAddress(addressDefinition);
|
||||
ValidateTypeCompatibility(validatedAddress, typeof(T));
|
||||
object value = Read(validatedAddress);
|
||||
return ConvertValue<T>(value, validatedAddress);
|
||||
}
|
||||
|
||||
public bool Write(AcsAddressDefinition addressDefinition, object value)
|
||||
{
|
||||
AcsAddressDefinition validatedAddress = ValidateAddress(addressDefinition);
|
||||
ValidateWriteValue(validatedAddress, value);
|
||||
IMotionController controller = GetController();
|
||||
string variableName = ResolveVariableName(validatedAddress);
|
||||
bool result = controller.WriteVariableBuffer(DefaultBufferId, variableName, value);
|
||||
if (!result)
|
||||
{
|
||||
throw CreateReadWriteException("Write", validatedAddress);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Write(AcsAddressDefinition addressDefinition, object value, int index1, int index2)
|
||||
{
|
||||
AcsAddressDefinition validatedAddress = ValidateAddress(addressDefinition);
|
||||
ValidateWriteValue(validatedAddress, value);
|
||||
ValidateIndex(index1, nameof(index1));
|
||||
ValidateIndex(index2, nameof(index2));
|
||||
IMotionController controller = GetController();
|
||||
string variableName = ResolveVariableName(validatedAddress);
|
||||
bool result = controller.WriteVariableBuffer(DefaultBufferId, variableName, value, index1, index2);
|
||||
if (!result)
|
||||
{
|
||||
throw CreateReadWriteException("Write", validatedAddress);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool WriteRange(AcsAddressDefinition addressDefinition, object value, int from1, int to1, int from2, int to2)
|
||||
{
|
||||
AcsAddressDefinition validatedAddress = ValidateAddress(addressDefinition);
|
||||
ValidateWriteValue(validatedAddress, value);
|
||||
ValidateRange(from1, to1, nameof(from1), nameof(to1));
|
||||
ValidateRange(from2, to2, nameof(from2), nameof(to2));
|
||||
IMotionController controller = GetController();
|
||||
string variableName = ResolveVariableName(validatedAddress);
|
||||
bool result = controller.WriteVariableBuffer(DefaultBufferId, variableName, value, from1, to1, from2, to2);
|
||||
if (!result)
|
||||
{
|
||||
throw CreateReadWriteException("Write", validatedAddress);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private IMotionController GetController()
|
||||
{
|
||||
if (!IsReady)
|
||||
{
|
||||
throw new InvalidOperationException("ACS controller is not ready. Ensure AcsCard is initialized and opened.");
|
||||
}
|
||||
|
||||
return _hardwareManager.AcsCard.Controller;
|
||||
}
|
||||
|
||||
private static AcsAddressDefinition ValidateAddress(AcsAddressDefinition addressDefinition)
|
||||
{
|
||||
if (addressDefinition == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(addressDefinition));
|
||||
}
|
||||
|
||||
if (!addressDefinition.HasNumericAddress && !addressDefinition.HasSymbolicAddress)
|
||||
{
|
||||
throw new ArgumentException("ACS address definition does not contain a usable address.", nameof(addressDefinition));
|
||||
}
|
||||
|
||||
return addressDefinition;
|
||||
}
|
||||
|
||||
private static string ResolveVariableName(AcsAddressDefinition addressDefinition)
|
||||
{
|
||||
if (addressDefinition.HasSymbolicAddress)
|
||||
{
|
||||
return addressDefinition.SymbolicAddress;
|
||||
}
|
||||
|
||||
return addressDefinition.Address.Value.ToString();
|
||||
}
|
||||
|
||||
private static void ValidateTypeCompatibility(AcsAddressDefinition addressDefinition, Type targetType)
|
||||
{
|
||||
if (targetType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(targetType));
|
||||
}
|
||||
|
||||
Type nonNullableTargetType = Nullable.GetUnderlyingType(targetType) ?? targetType;
|
||||
if (nonNullableTargetType == typeof(object))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (addressDefinition.DataType == nonNullableTargetType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (addressDefinition.IsInteger && IsIntegerType(nonNullableTargetType))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (addressDefinition.IsFloatingPoint && IsFloatingPointType(nonNullableTargetType))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Address {addressDefinition.Name} is defined as {addressDefinition.DataType.Name} and cannot be read as {nonNullableTargetType.Name}.");
|
||||
}
|
||||
|
||||
private static T ConvertValue<T>(object value, AcsAddressDefinition addressDefinition)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
if (value is T typedValue)
|
||||
{
|
||||
return typedValue;
|
||||
}
|
||||
|
||||
Type targetType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
|
||||
try
|
||||
{
|
||||
if (targetType == typeof(bool))
|
||||
{
|
||||
return (T)(object)ConvertToBoolean(value);
|
||||
}
|
||||
|
||||
object convertedValue = Convert.ChangeType(value, targetType);
|
||||
return (T)convertedValue;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidCastException($"The value of address {addressDefinition.Name} cannot be converted to {targetType.Name}.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ConvertToBoolean(object value)
|
||||
{
|
||||
if (value is bool boolValue)
|
||||
{
|
||||
return boolValue;
|
||||
}
|
||||
|
||||
if (value is string stringValue)
|
||||
{
|
||||
if (string.Equals(stringValue, "1", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (string.Equals(stringValue, "0", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return Convert.ToDouble(value) != 0d;
|
||||
}
|
||||
|
||||
private static void ValidateWriteValue(AcsAddressDefinition addressDefinition, object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
if (addressDefinition.Length > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Type valueType = value.GetType();
|
||||
if (addressDefinition.DataType.IsAssignableFrom(valueType))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (addressDefinition.IsBoolean && IsBooleanCompatibleType(valueType))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (addressDefinition.IsInteger && IsIntegerType(valueType))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (addressDefinition.IsFloatingPoint && (IsFloatingPointType(valueType) || IsIntegerType(valueType)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Address {addressDefinition.Name} is defined as {addressDefinition.DataType.Name}, but the current value type is {valueType.Name}.");
|
||||
}
|
||||
|
||||
private static bool IsBooleanCompatibleType(Type type)
|
||||
{
|
||||
return type == typeof(bool) || IsIntegerType(type);
|
||||
}
|
||||
|
||||
private static bool IsIntegerType(Type type)
|
||||
{
|
||||
return type == typeof(byte)
|
||||
|| type == typeof(sbyte)
|
||||
|| type == typeof(short)
|
||||
|| type == typeof(ushort)
|
||||
|| type == typeof(int)
|
||||
|| type == typeof(uint)
|
||||
|| type == typeof(long)
|
||||
|| type == typeof(ulong);
|
||||
}
|
||||
|
||||
private static bool IsFloatingPointType(Type type)
|
||||
{
|
||||
return type == typeof(float)
|
||||
|| type == typeof(double)
|
||||
|| type == typeof(decimal);
|
||||
}
|
||||
|
||||
private static void ValidateIndex(int index, string parameterName)
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(parameterName, index, "ACS index cannot be less than 0.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateRange(int from, int to, string fromName, string toName)
|
||||
{
|
||||
ValidateIndex(from, fromName);
|
||||
ValidateIndex(to, toName);
|
||||
if (to < from)
|
||||
{
|
||||
throw new ArgumentException($"Parameter {toName} cannot be less than {fromName}.", toName);
|
||||
}
|
||||
}
|
||||
|
||||
private static Exception CreateReadWriteException(string operationName, AcsAddressDefinition addressDefinition)
|
||||
{
|
||||
string addressText = addressDefinition.HasSymbolicAddress
|
||||
? addressDefinition.SymbolicAddress
|
||||
: addressDefinition.Address.Value.ToString();
|
||||
return new InvalidOperationException($"{operationName} ACS address failed: {addressDefinition.Name}, address={addressText}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user