Read/Write primitive values

Reading writing Values from ADS Devices is the most essential part of the communication API. There are several options for communication with your application.

  • Accessing by IndexGroup / IndexOffset
  • Symbolic access by instance path and optionally use handles for the symbol
  • Holding the overall Symbolic information in the SymbolLoader and use easy access via symbol objects.
  • Usage the symbolic interface ITcAdsSymbol when complete SymbolLoading by SymbolLoaders is not appropriate.
  • Reading / Writing values as .NET managed Types (primitive types or compound primitive types called ANY_TYPES), or complex dynamic types typesafe generated at runtime.

The following section shows the different scenarios as code snippets.

HowTo Read/Write Values

Read/Write AnyType by IndexGroup/IndexOffset (asynchronously)

using (AdsClient client = new AdsClient())
{
    CancellationToken cancel = CancellationToken.None;

    uint valueToRead = 0;
    uint valueToWrite = 42;

    client.Connect(AmsNetId.Local, 851);
    ResultWrite resultWrite = await client.WriteAnyAsync(0x4020, 0x0, valueToWrite,cancel);
    bool succeeded = resultWrite.Succeeded;

    ResultValue<uint> resultRead = await client.ReadAnyAsync<uint>(0x4020, 0x0, cancel);

    if(resultRead.Succeeded)
    {
    valueToRead = (uint)resultRead.Value;
    }
}

Read/Write AnyType by IndexGroup/IndexOffset (synchronously)

using (AdsClient client = new AdsClient())
{
    uint valueToRead = 0;
    uint valueToWrite = 42;

    client.Connect(AmsNetId.Local, 851);
    adsClient.WriteAny(0x4020, 0x0, valueToWrite);
    valueToRead = (uint)adsClient.ReadAny(0x4020, 0x0, typeof(uint));
}

Read/Write AnyType by variable handle (asynchronously)

using (AdsClient client = new AdsClient())
{
    CancellationToken cancel = CancellationToken.None;
    uint varHandle = 0;
    client.Connect(AmsNetId.Local, 851);

    uint valueToRead = 0;
    uint valueToWrite = 42;

    ResultHandle resultHandle = await client.CreateVariableHandleAsync("MAIN.nCounter", cancel);
    varHandle = resultHandle.Handle;

    if (resultHandle.Succeeded)
    {
    try
    {
        ResultWrite resultWrite = await client.WriteAnyAsync(varHandle, valueToWrite, cancel);
        ResultValue<uint> resultRead = await client.ReadAnyAsync<uint>(varHandle, cancel);

        if (resultRead.Succeeded)
        valueToRead = resultRead.Value;
    }
    finally
    {
        // Unregister VarHandle after Use
        ResultAds result = await client.DeleteVariableHandleAsync(varHandle,cancel);
    }
    }
}

Read/Write AnyType by variable handle (synchronously)

using (AdsClient client = new AdsClient())
{
    uint varHandle = 0;
    client.Connect(AmsNetId.Local, 851);
    try
    {
    uint valueToRead = 0;
    uint valueToWrite = 42;

    varHandle = client.CreateVariableHandle("MAIN.nCounter");
    adsClient.WriteAny(varHandle, valueToWrite);
    valueToRead = (uint)adsClient.ReadAny(varHandle, typeof(uint));
    }
    finally
    {
    // Unregister VarHandle after Use
    client.DeleteVariableHandle(varHandle);
    }
}

Read/Write AnyType by instance/symbol path (asynchronously)

using (AdsClient client = new AdsClient())
{
    CancellationToken cancel = CancellationToken.None;
    uint valueToRead = 0;
    uint valueToWrite = 42;

    client.Connect(AmsNetId.Local, 851);

    ResultWrite resultWrite = await client.WriteValueAsync("MAIN.nCounter", valueToWrite, cancel);
    ResultValue<uint> resultRead = await client.ReadValueAsync<uint>("MAIN.nCounter",cancel);

    if (resultRead.Succeeded)
    valueToRead = resultRead.Value;
}

Read/Write AnyType by instance/symbol path (synchronously)

using (AdsClient client = new AdsClient())
{
    uint valueToRead = 0;
    uint valueToWrite = 42;

    client.Connect(AmsNetId.Local, 851);
    client.WriteValue("MAIN.nCounter", valueToWrite);
    valueToRead = (uint)client.ReadValue("MAIN.nCounter", typeof(uint));
}

Read/Write AnyType by IAdsSymbol (asynchronously)

using (AdsClient client = new AdsClient())
{
    CancellationToken cancel = CancellationToken.None;

    uint valueToRead = 0;
    uint valueToWrite = 42;

    client.Connect(AmsNetId.Local, 851);

    ResultValue<IAdsSymbol> resultSymbol = await client.ReadSymbolAsync("MAIN.nCounter",cancel);

    if (resultSymbol.Succeeded)
    {
    ResultWrite resultWrite = await client.WriteValueAsync(resultSymbol.Value, valueToWrite, cancel);
    bool succeeded = resultWrite.Succeeded;

    ResultValue<uint> resultValue = await client.ReadValueAsync<uint>(resultSymbol.Value,cancel);

    if (resultValue.Succeeded)
        valueToRead = resultValue.Value;
    }
}

Read/Write AnyType by IAdsSymbol (synchronously)

using (AdsClient client = new AdsClient())
{
    uint valueToRead = 0;
    uint valueToWrite = 42;

    client.Connect(AmsNetId.Local, 851);

    IAdsSymbol symbol = adsClient.ReadSymbol("MAIN.nCounter");
    adsClient.WriteValue(symbol, valueToWrite);
    valueToRead = (uint)adsClient.ReadValue(symbol);
}

Read/Write AnyType by SymbolBrowser (asynchronously)

using (AdsClient client = new AdsClient())
{
    CancellationToken cancel = CancellationToken.None;

    uint valueToRead = 0;
    uint valueToWrite = 42;

    client.Connect(AmsNetId.Local, 851);

    // Load all Symbols + DataTypes
    ISymbolLoader loader = SymbolLoaderFactory.Create(client, SymbolLoaderSettings.Default);

    ResultSymbols resultSymbols  = await loader.GetSymbolsAsync(cancel);

    if (resultSymbols.Succeeded)
    {
    Symbol symbol = (Symbol)resultSymbols.Symbols["MAIN.nCounter"];

    // Works for ALL Primitive 'ANY TYPES' Symbols
    ResultWriteAccess resultWrite = await symbol.WriteValueAsync(valueToWrite, cancel);
    ResultReadValueAccess resultRead = await symbol.ReadValueAsync(cancel);

    if (resultRead.Succeeded)
        valueToRead = (uint)resultRead.Value;

    // Simple filtering of Symbols
    Regex filterExpression = new Regex(pattern: @"^MAIN.*"); // Everything that starts with "MAIN"

    // FilterFunction that filters for the InstancePath
    Func<ISymbol, bool> filter = s => filterExpression.IsMatch(s.InstancePath);
    SymbolIterator iterator = new SymbolIterator(symbols: resultSymbols.Symbols, recurse: true, predicate: filter);

    foreach (ISymbol filteredSymbol in iterator)
    {
        Console.WriteLine(filteredSymbol.InstancePath);
    }
    }
}

Read/Write AnyType by SymbolBrowser (synchronously)

using (AdsClient client = new AdsClient())
{
    uint valueToRead = 0;
    uint valueToWrite = 42;

    client.Connect(AmsNetId.Local, 851);

    // Load all Symbols + DataTypes
    ISymbolLoader loader = SymbolLoaderFactory.Create(client, SymbolLoaderSettings.Default);
    Symbol symbol = (Symbol)loader.Symbols["MAIN.nCounter"];

    // Works for ALL Primitive 'ANY TYPES' Symbols
    symbol.WriteValue(valueToWrite); 
    valueToRead = (uint)symbol.ReadValue();

    // Simple filtering of Symbols
    Regex filterExpression = new Regex(pattern: @"^MAIN.*"); // Everything that starts with "MAIN"

    // FilterFunction that filters for the InstancePath
    Func<ISymbol, bool> filter = s => filterExpression.IsMatch(s.InstancePath);
    SymbolIterator iterator = new SymbolIterator(symbols: loader.Symbols, recurse: true, predicate: filter);

    foreach (ISymbol filteredSymbol in iterator)
    {
    Console.WriteLine(filteredSymbol.InstancePath);
    }
}

Read/Write dynamic types by SymbolBrowser (asynchronously)

using (AdsClient client = new AdsClient())
{
    CancellationToken cancel = CancellationToken.None;

    uint valueToRead = 0;
    uint valueToWrite = 42;

    client.Connect(AmsNetId.Local, 851);

    // Load all Symbols + DataTypes
    // Primitive Parts will be automatically resolved to .NET Primitive types.
    IDynamicSymbolLoader loader = (IDynamicSymbolLoader)SymbolLoaderFactory.Create(client, SymbolLoaderSettings.DefaultDynamic);

    //dynamic symbols = loader.SymbolsDynamic;
    ResultDynamicSymbols resultSymbols = await loader.GetDynamicSymbolsAsync(cancel);
    if (resultSymbols.Succeeded)
    {
    dynamic symbols = resultSymbols.Symbols; // Symbols collection with 'dynamic' access.
    dynamic main = symbols.Main; // Get the 'dynamic' main FB as Property

    // Use typed object to use InfoTips instead of 'dynamic'
    DynamicSymbol nCounter = main.nCounter;
    // or to be fullDynamic 
    dynamic nCounter2 = main.nCounter;

    // Works for ALL sorts of types (not restricted to ANY_TYPE basing primitive types)
    ResultWriteAccess resultWrite = await nCounter.WriteValueAsync(valueToWrite,cancel);
    ResultReadValueAccess resultRead = await nCounter.ReadValueAsync(cancel);

    if (resultRead.Succeeded)
    {
        // Because the PLC value is defined as UDINT (32-Bit)
        // We get back an already Marshalled UInt32 here ...
        valueToRead = (uint)resultRead.Value;
    }
    }
}

Read/Write dynamic types by SymbolBrowser (synchronously)

using (AdsClient client = new AdsClient())
{
    uint valueToRead = 0;
    uint valueToWrite = 42;

    client.Connect(AmsNetId.Local, 851);

    // Load all Symbols + DataTypes
    // Primitive Parts will be automatically resolved to .NET Primitive types.
    IDynamicSymbolLoader loader = (IDynamicSymbolLoader)SymbolLoaderFactory.Create(client, SymbolLoaderSettings.DefaultDynamic);

    dynamic symbols = loader.SymbolsDynamic;
    dynamic main = symbols.Main;

    // Use typed object to use InfoTips
    DynamicSymbol nCounter = main.nCounter;

    // or to be fullDynamic 
    //dynamic nCounter = main.nCounter;

    // Works for ALL sorts of types (not restricted to ANY_TYPE basing primitive types)
    nCounter.WriteValue(valueToWrite);
    valueToRead = (uint)nCounter.ReadValue();
}