SymbolLoaderFactoryCreate Method

Creates the specified Symbol loader


Namespace: TwinCAT.Ads.TypeSystem
Assembly: TwinCAT.Ads (in TwinCAT.Ads.dll) Version: 7.0.0+e56d35ccc4675faac24789a4aab60071fc61d470

Syntax

C#

public static ISymbolLoader Create(
    IConnection connection,
    ISymbolLoaderSettings settings
)

Parameters

connection  IConnection

The connection.

settings  ISymbolLoaderSettings

The settings.

Return Value

ISymbolLoader
ISymbolLoader.

Example

The following sample shows how to create a dynamic version of the SymbolLoader V2. The dynamic symbol loader makes use of the Dynamic Language Runtime (DLR) of the .NET Framework. That means Structures, Arrays and Enumeration types and instances are generated 'on-the-fly' during symbol Browsing. These created dynamic objects are a one to one representation of the Symbol Server target objects (e.g the IEC61131 types on the PLC). Dynamic language features are only available from .NET4 upwards.

Dynamic Tree Mode

namespace Sample
{
    using System;
    using System.Diagnostics;
    using System.Threading;
    using TwinCAT;
    using TwinCAT.Ads;
    using TwinCAT.Ads.TypeSystem;
    using TwinCAT.Ads.ValueAccess;
    using TwinCAT.TypeSystem;
    using TwinCAT.TypeSystem.Generic;
    using TwinCAT.ValueAccess;

    class SymbolBrowserProgramV2DynamicTree
    {

    #region CODE_SAMPLE_SIMPLEDYNAMIC
    /// <summary>
    /// Defines the entry point of the application.
    /// </summary>
    /// <param name="args">The arguments.</param>
    static async void Main(string[] args)
    {
        // Get the AdsAddress from command-line arguments
        AmsAddress address = ArgParser.Parse(args);

        CancellationTokenSource cancelSource = new CancellationTokenSource();
        CancellationToken cancel = cancelSource.Token;

        using (AdsClient client = new AdsClient())
        {
        // Connect to the target device
        client.Connect(address);

        // Usage of "dynamic" Type and Symbols (>= .NET4 only)
        SymbolLoaderSettings settings = new SymbolLoaderSettings(SymbolsLoadMode.DynamicTree);
        IAdsSymbolLoader dynLoader = (IAdsSymbolLoader)SymbolLoaderFactory.Create(client, settings);

        #endregion

        // Set the Default setting for Notifications
        dynLoader.DefaultNotificationSettings = new NotificationSettings(AdsTransMode.OnChange, 200, 2000);

        // Get the Symbols (Dynamic Symbols)
        var resultSymbols = await ((IDynamicSymbolLoader)dynLoader).GetDynamicSymbolsAsync(cancel);

        dynamic dynamicSymbols = resultSymbols.Symbols;
        dynamic adsPort = dynamicSymbols.TwinCAT_SystemInfoVarList._AppInfo.AdsPort;

        #region CODE_SAMPLE_SIMPLEDYNAMIC

        // Access Main Symbol with Dynamic Language Runtime support (DLR)
        // Dynamically created property "Main"
        //dynamic symMain = dynamicSymbols.Main;

        // Main is an 'VirtualSymbol' / Organizational unit that doesn't have a value
        // Calling ReadValue is not allowed
        //bool test = symMain.HasValue;
        //dynamic invalid = symMain.ReadValue();

        //Reading TaskInfo Value
        //With calling ReadValueAsync() a 'snapshot' of the Symbols Instance is taken (reading async)
        ResultReadValueAccess resultRead = await dynamicSymbols.TwinCAT_SystemInfoVarList._TaskInfo.ReadValueAsync(cancel);
        dynamic vTaskInfoArray = resultRead.Value;

        // Getting the Snapshot time in UTC format
        DateTimeOffset timeStamp1 = vTaskInfoArray.TimeStamp;

        // Getting TaskInfo Symbol for Task 1
        dynamic symTaskInfo1 = dynamicSymbols.TwinCAT_SystemInfoVarList._TaskInfo[1];

        // Getting CycleCount Symbol
        dynamic symCycleCount = symTaskInfo1.CycleCount;


        // Take Snapshot value of the ApplicationInfo struct
        resultRead = await dynamicSymbols.TwinCAT_SystemInfoVarList._AppInfo.ReadValueAsync(cancel);
        dynamic vAppInfo = resultRead.Value;

        // Get the UTC Timestamp of the snapshot
        DateTimeOffset timeStamp2 = vAppInfo.TimeStamp;

        // Access the ProjectName of the ApplicationInfo Snapshot (type-safe!)
        string projectNameValue = vAppInfo.ProjectName;

        // Reading the CycleCount Value
        resultRead = await symTaskInfo1.CycleCount.ReadValueAsync(cancel);     // Taking a Value Snapshot
        int cycleCountValue = (int)resultRead.Value;
        #endregion

        // Registering for dynamic "ValueChanged" events for the Values
        // Using Default Notification settings           
        symCycleCount.ValueChanged += new EventHandler<ValueChangedEventArgs>(cycleCount_ValueChanged);

        // Override default notification settings
        symTaskInfo1.NotificationSettings = new NotificationSettings(AdsTransMode.Cyclic, 500, 0);

        // Register for ValueChanged event.
        symTaskInfo1.ValueChanged += new EventHandler<ValueChangedEventArgs>(taskInfo1Value_ValueChanged); // Struct Type

        Thread.Sleep(10000); // Sleep main thread for 10 Seconds
        }
        Console.WriteLine("CycleCount Changed events received: {0}",_cycleCountEvents);
        Console.WriteLine("taskInfo1 Changed events received: {0}", _taskInfo1Events);

        Console.WriteLine("");
        Console.WriteLine("Press [Enter] for leave:");
        Console.ReadLine();
    }

    static object _notificationSynchronizer = new object();
    static int _cycleCountEvents = 0;

    /// <summary>
    /// Handler function for the CycleCount ValueChanged event.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The e.</param>
    static void cycleCount_ValueChanged(object sender, ValueChangedEventArgs e)
    {
        lock(_notificationSynchronizer)
        {
        Interlocked.Increment(ref _cycleCountEvents);
        // val is a type safe value of int!
        dynamic val = e.Value;
        uint intVal = val;

        DateTimeOffset changedTime = e.DateTime.ToLocalTime(); // Convert UTC to local time
        Console.WriteLine("CycleCount changed to: {0}, TimeStamp: {1}", intVal, changedTime.ToString("HH:mm:ss:fff"));
        }
    }

    static int _taskInfo1Events = 0;

    /// <summary>
    /// Handler function for the TaskInfo ValueChanged event.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The e.</param>
    static void taskInfo1Value_ValueChanged(object sender, ValueChangedEventArgs e)
    {
        lock (_notificationSynchronizer)
        {
        Interlocked.Increment(ref _taskInfo1Events);
        dynamic val = e.Value;
        DateTimeOffset changedTime = e.DateTime.ToLocalTime(); // Convert to local time

        // Val is a during Runtime created struct type and contains
        // the same Properties as related PLC object.
        int cycleTime = val.CycleTime;
        Console.WriteLine("TaskInfo1Value changed TimeStamp: {0}", changedTime.ToString("HH:mm:ss:fff"));
        }
    }
    }
}

The following sample shows how to create a static (non dynamic) version of the SymbolLoader V2. The static symbol loader in version 2 is a nearly code compatible version of the Dynamic Loader, only the dynamic creation of objects is not available. The reason for supporting this mode is that .NET Framework Versions lower than Version 4.0 (CLR2) doesn't support the Dynamic Language Runtime (DLR). The SymbolLoader V2 static object is supported from .NET 2.0 on.

Virtual Tree Mode

using System;
using System.Threading;
using System.Diagnostics;
using TwinCAT;
using TwinCAT.Ads;
using TwinCAT.TypeSystem;
using TwinCAT.TypeSystem.Generic;
using TwinCAT.Ads.ValueAccess;
using TwinCAT.Ads.TypeSystem;
using TwinCAT.ValueAccess;

namespace Sample
{
    class SymbolBrowserProgramV2VirtualTree
    {
    /// <summary>
    /// Defines the entry point of the application.
    /// </summary>
    /// <param name="args">The arguments.</param>
    static void Main(string[] args)
    {
        ConsoleLogger logger = new ConsoleLogger();

        Console.WriteLine("");
        Console.WriteLine("Press [Enter] for start:");
        Console.ReadLine();

        //logger.Active = false;

        Stopwatch stopper = new Stopwatch();

        // Parse the command-line arguments
        AmsAddress address = ArgParser.Parse(args);

        stopper.Start();

        using (AdsClient client = new AdsClient())
        {
        //client.Synchronize = false;

        // Connect the AdsClient to the device target.
        client.Connect(address);

        // Creates the Symbol Objects as hierarchical tree        
        SymbolLoaderSettings settings = new SymbolLoaderSettings(SymbolsLoadMode.VirtualTree, ValueAccessMode.IndexGroupOffsetPreferred);
        ISymbolLoader symbolLoader = SymbolLoaderFactory.Create(client, settings);

        // Dump Datatypes from Target Device
        Console.WriteLine(string.Format("Dumping '{0}' DataTypes:", symbolLoader.DataTypes.Count));
        foreach (IDataType type in symbolLoader.DataTypes)
        {
            logger.DumpType(type);
        }
        Console.WriteLine("");

        // Dump Symbols from target device
        Console.WriteLine("Dumping '{0}' Symbols:", symbolLoader.Symbols.Count);
        foreach (ISymbol symbol in symbolLoader.Symbols)
        {
            logger.DumpSymbol(symbol,0);
        }
        }
        stopper.Stop();
        TimeSpan elapsed = stopper.Elapsed;

        Console.WriteLine("");
        Console.WriteLine("Browsing complete tree: {0},({1} DataTypes, {2} Symbols)",elapsed,logger.DataTypesCount,logger.DataTypesCount);
        Console.WriteLine("Press [Enter] for leave:");
        Console.ReadLine();
    }

Reference

SymbolLoaderFactory Class TwinCAT.Ads.TypeSystem Namespace

Beckhoff Automation GmbH & Co. KG 2001-2026