0

我正在编写一个 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()

我究竟做错了什么?

4

0 回答 0