我正在编写一个 ADS 客户端,它应该通过它们的类型名订阅任何符号(例如 ST_TestData)。当尝试仅使用 SymbolsLoadMode.DynamicTree 设置选项使用 SymbolLoaderFactory 时,它工作正常,但我的 ENUM 只获得 RAW-Value。
调查它,我发现了以下设置选项:
//Use IEnumValue on EnumTypes instead of .NET Primitives
TwinCAT.ValueAccess.ValueCreationModes.Enums
考虑以下代码(使用 .NET 5):
AdsClient client = new();
client.Connect("10.0.2.15.1.1", 851);
SymbolLoaderSettings setting = new( SymbolsLoadMode.DynamicTree,
TwinCAT.ValueAccess.ValueCreationModes.Enums,
TwinCAT.Ads.ValueAccess.ValueAccessMode.Default );
IDynamicSymbolLoader loader = (IDynamicSymbolLoader)SymbolLoaderFactory.Create(client, setting);
IDynamicSymbolsCollection symbols = loader.SymbolsDynamic;
foreach(DynamicSymbol symbol in symbols)
{
if (symbol.InstanceName == "GVL_Datatypes")
{
foreach(DynamicSymbol s in symbol?.SubSymbols)
{
if (s.DataType.Name == "ST_ValveData")
s.ValueChanged += ClientAdsNotification;
}
}
}
Console.ReadKey();
while (!client.IsDisposed)
{
client.Dispose();
}
}
private static void ClientAdsNotification(object sender, ValueChangedEventArgs e)
{
object val = e.Value;
string json = JsonConvert.SerializeObject((DynamicValue)e.Value);
Console.WriteLine(json);
}
GVL“GVL_Datatypes”中“ST_ValveData”类型的每个符号都将被订阅,但是当我尝试访问 EventHandler 通知时,出现以下异常:
plc中的结构定义:
TYPE ST_ValveData :
stHeader : ST_Header;
stPayload : ST_ValveDataPayload;
END_STRUCT
END_TYPE
TYPE ST_Header :
STRUCT
nModule : UINT;
nStation : UINT;
sUnit : STRING(1);
sBmk : STRING(20);
eElementType : E_ElementType;
END_STRUCT
END_TYPE
TYPE ST_ValveDataPayload :
STRUCT
eState : E_State;
eValvePosReq : E_ValvePosition;
eValvePosRes : E_ValvePosition;
END_STRUCT
END_TYPE
TYPE E_ValvePosition :
(
Init := 0,
Home,
Work
);
END_TYPE
例外:
System.InvalidCastException: 'Object must implement IConvertible.'
This exception was originally thrown at this call stack:
[External Code]
TestAppSymbolLoader.Program.ClientAdsNotification(object, TwinCAT.TypeSystem.ValueChangedEventArgs) in Program.cs
[External Code]
堆栈跟踪:
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at System.Convert.ChangeType(Object value, Type conversionType)
at TwinCAT.TypeSystem.EnumValueFactory.Create[X](IEnumType enumType, Object value)
at TwinCAT.TypeSystem.EnumValueFactory.Create(IEnumType enumType, Object value)
at TwinCAT.ValueAccess.DynamicValueFactory.CreateValue(ISymbol symbol, ReadOnlyMemory`1 sourceData, IValue parent, DateTimeOffset timeStamp)
at TwinCAT.TypeSystem.DynamicValue.ReadMember(ISymbol memberInstance)
at TwinCAT.TypeSystem.DynamicValue.TryGetMemberValue(String name, Object& result)
at TwinCAT.TypeSystem.DynamicValue.TryGetMember(GetMemberBinder binder, Object& result)
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at Microsoft.CSharp.RuntimeBinder.DynamicMetaObjectProviderDebugView.TryGetMemberValue(Object obj, String name, Boolean ignoreException)
at Microsoft.CSharp.RuntimeBinder.DynamicMetaObjectProviderDebugView.QueryDynamicObject(Object obj)
at Microsoft.CSharp.RuntimeBinder.DynamicMetaObjectProviderDebugView.get_Items()
我究竟做错了什么?