Connectivity Software User's Guide and Reference
Variable Data Type Considerations
OPC Wizard > Concepts > OPC Wizard Operation Model > Data Variable Configuration > Variable Data Type Considerations
In This Topic

The Variant OPC UA Data Type

In OPC UA, Variant is a built-in type that can hold any data type (an instance of any type derived from BaseDataType, which is at the root of the data type hierarchy). In its default state (without further configuration), every UADataVariable has its DataTypeId Property set to BaseDataType, indicating the use of the Variant built-in type. Such variables can therefore hold value of any OPC UA type.

Unless you have a specific need that requires the use of the Variant OPC UA data type, it is strongly recommended that you always set the data type of the variable to a more specific data type. The data type provides useful information to other OPC UA applications, and with the use of Variant, is is effectively lost.

Example: Installed Examples - Server Library - UAServerDemoLibrary

Data Types in Data Provision

Because the data type model in OPC UA is not identical with the .NET type model, you need to understand what the type correspondences are, and in some cases the OPC UA data types are represented by .NET types that differ from intuitive expectations. To learn about the representation of OPC UA data types in Connectivity Software, see Data Types in OPC-UA.

Pull Data Provision Model

When you use the extension method for Data Variable Configuration, and provide a function that handles the Read request, OPC Wizard determines the OPC UA data type of the variable (and its value rank) from the .NET type of the function argument. For example, if you use the simplest ReadValueFunction method overload and simply pass it a function that returns System.Int32 type, the OPC UA data type (the DataTypeId Property of the data variable) will be automatically determined to be UADataTypeIds.Int32.

There are cases, however, when this automatic mechanism is not suitable; if so, you can still use the extension methods for data variable configuration, but you have to specify the desired data type in some additional ways. This happens e.g. when multiple OPC UA data types are mapped to a single .NET type (as per Data Types in OPC-UA article). In the example given above, OPC Wizard uses System.Int32 not only for OPC UA Int32 data type, but also for UInt16 (this is for it to be CLS-compliant and usable from languages like VB.NET; similarly with some other integer types). If you want your data variable be of OPC UA SByte, UInt16, UInt32 or UInt64 data type, you can do it similarly to the following example.

Example: Examples - Server OPC UA - Data variable UInt16 value, reading using a function

Also, in OPC UA, there is a ByteString type. According to newer OPC UA specifications, this type should be handled interchangeably with a single-dimensional array of Byte. When OPC Wizard methods encounter a .NET array of bytes, they prefer to choose the OPC UA ByteString data type for it, unless specified otherwise. The following example illustrates an implementation of a readable data variable with OPC UA data type ByteString.

Example: Examples - Server OPC UA - Data variable ByteString value, reading using a function

Push Data Provision Model

In the Push Data Provision Model, the concerns described above with the Pull Data Provision Model still apply. However, since in the configuration methods there is no function provided with an argument from which the data type can be automatically determined, you will end up specifying the data type yourself, typically by some overload of the ValueType Method.

Example

.NET

// This example shows how to update the read value in the push data provision model. In this model, your code pushes the
// data into the server, and the server then makes the data available to OPC clients.
// You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-ConnectivityStudio/Latest/examples.html .
// OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-ConnectivityStudio-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.NodeSpace;
using Timer = System.Timers.Timer;

namespace UAServerDocExamples._UADataVariable
{
    class UpdateReadAttributeData
    {
        public static void Main1()
        {
            // Instantiate the server object.
            // By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            var server = new EasyUAServer();

            // Create a read-only data variable.
            var dataVariable = UADataVariable.CreateIn(server.Objects, "ReadThisVariable")
                .ValueType<int>()
                .Writable(false);

            // Create a timer for pushing the data for OPC reads. In a real server the activity may also come from other
            // sources.
            var timer = new Timer
            {
                Interval = 1000,
                AutoReset = true,
            };

            // Set the read attribute data of the data variable to a random value whenever the timer interval elapses.
            var random = new Random();
            timer.Elapsed += (sender, args) => dataVariable.UpdateReadAttributeData(random.Next());
            timer.Start();

            // Start the server.
            Console.WriteLine("The server is starting...");
            server.Start();

            Console.WriteLine("The server is started.");
            Console.WriteLine();

            // Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...");
            Console.ReadLine();

            // Stop the server.
            Console.WriteLine("The server is stopping...");
            server.Stop();

            // Stop the timer.
            timer.Stop();

            Console.WriteLine("The server is stopped.");
        }
    }
}
# This example shows how to update the read value in the push data provision model. In this model, your code pushes the
# data into the server, and the server then makes the data available to OPC clients.
# You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-ConnectivityStudio-CSharp .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.

#requires -Version 5.1
using namespace OpcLabs.EasyOpc.UA
using namespace OpcLabs.EasyOpc.UA.NodeSpace
using namespace OpcLabs.PowerShellManagement

# The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows .
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.ServerOpcUAComponents.dll"
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.PowerShellManagement.dll"

# Instantiate the server object.
# By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
$server = New-Object EasyUAServer

# Create a read-only data variable.
$dataVariable = [UADataVariableExtension]::Writable([UADataVariableExtension]::ValueType([UADataVariable]::CreateIn($server.Objects, "ReadThisVariable"), [int]), $false)

# Create a timer for pushing the data for OPC reads. In a real server the activity may also come from other
# sources.
$timer = New-Object Timers.Timer -property @{
    Interval = 1000
    AutoReset = $true
}

# Set the read attribute data of the data variable to a random value whenever the timer interval elapses.
$random = New-Object System.Random
$timer.add_Elapsed([RunspacedDelegateFactory]::NewRunspacedDelegate([System.Timers.ElapsedEventHandler] { param ($sender, $e) $dataVariable.UpdateReadAttributeData($random.Next()) }))
$timer.Start()

# Start the server.
Write-Host "The server is starting..."
$server.Start()

Write-Host "The server is started."
Write-Host

# Let the user decide when to stop.
Write-Host "Press Enter to stop the server..."
Read-Host

# Stop the server.
Write-Host "The server is stopping..."
$server.Stop()

# Stop the timer.
$timer.Stop()

Write-Host "The server is stopped."
' This example shows how to update the read value in the push data provision model. In this model, your code pushes the
' data into the server, and the server then makes the data available to OPC clients.
' You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-ConnectivityStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-ConnectivityStudio-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports System
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.NodeSpace
Imports Timer = System.Timers.Timer

Namespace Global.UAServerDocExamples._UADataVariable
    Partial Friend Class UpdateReadAttributeData
        Shared Sub Main1()
            ' Instantiate the server object.
            ' By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            Dim server = New EasyUAServer()

            ' Create a read-only data variable.
            Dim dataVariable = UADataVariable.CreateIn(server.Objects, "ReadThisVariable") _
                .ValueType(Of Integer)() _
                .Writable(False)

            ' Create a timer for pushing the data for OPC reads. In a real server the activity may also come from other
            ' sources.
            Dim timer = New Timer With
            {
                .Interval = 1000,
                .AutoReset = True
            }

            ' Set the read attribute data of the data variable to a random value whenever the timer interval elapses.
            Dim random = New Random()
            AddHandler timer.Elapsed, Sub(sender, args) dataVariable.UpdateReadAttributeData(random.Next())
            timer.Start()

            ' Start the server.
            Console.WriteLine("The server is starting...")
            server.Start()

            Console.WriteLine("The server is started.")
            Console.WriteLine()

            ' Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...")
            Console.ReadLine()

            ' Stop the server.
            Console.WriteLine("The server is stopping...")
            server.Stop()

            Console.WriteLine("The server is stopped.")
        End Sub
    End Class
End Namespace

Data Types in Data Consumption

Because the data type model in OPC UA is not identical with the .NET type model, you need to understand what the type correspondences are, and in some cases the OPC UA data types are represented by .NET types that differ from intuitive expectations. To learn about the representation of OPC UA data types in Connectivity Software, see Data Types in OPC-UA.

Push Data Consumption Model

When you use some extension method for Data Variable Configuration, and provide a function (or action) that handles the Write request, OPC Wizard determines the OPC UA data type of the variable (and its value rank) from the .NET type of the function (or action) argument. For example, if you use the simplest WriteValueAction method overload and simply pass it an action that takes System.Int32 argument, the OPC UA data type (the DataTypeId Property of the data variable) will be automatically determined to be UADataTypeIds.Int32.

There are cases, however, when this automatic mechanism is not suitable; if so, you can still use the extension methods for data variable configuration, but you have to specify the desired data type in some additional ways. This happens e.g. when multiple OPC UA data types are mapped to a single .NET type (as per Data Types in OPC-UA article). In the example given above, OPC Wizard uses System.Int32 not only for OPC UA Int32 data type, but also for UInt16 (this is for it to be CLS-compliant and usable from languages like VB.NET; similarly with some other integer types). If you want your data variable be of OPC UA SByte, UInt16, UInt32 or UInt64 data type, you can do it similarly to the following example.

Example: Examples - Server OPC UA - Implement UInt16 value writing using an action

Also, in OPC UA, there is a ByteString type. According to newer OPC UA specifications, this type should be handled interchangeably with a single-dimensional array of Byte. When OPC Wizard methods encounter a .NET array of bytes, they prefer to choose the OPC UA ByteString data type for it, unless specified otherwise. The following example illustrates an implementation of a  writable data variable with OPC UA data type ByteString.

Example: Examples - Server OPC UA - Implement ByteString value writing using an action

Pull Data Consumption Model

In the Pull Data Consumption Model, the concerns described above with the Push Data Consumption Model still apply. However, since in the configuration methods there is no function or action provided with an argument from which the data type can be automatically determined, you will end up specifying the data type yourself, typically by some overload of the ValueType Method.

See Also

QuickOPC

Examples - Server OPC Unified Architecture

Reference

Installed Examples - Server Library