# Node types

> How-to guide: Work with method, file, data type, variable, and data item nodes, including analog values.

> This content was machine translated and may contain errors. [Read in German](https://www.traeger.de/docs/development/opcua/client/node-types)

**Sample applications:**

- Client.MethodNode ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Nodes/Client.MethodNode), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Nodes/Client.MethodNode)): This sample demonstrates how to access and work with method nodes.
- Client.Methods ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Basic/Client.Methods), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Basic/Client.Methods)): This sample demonstrates how to perform method calls using the OPC UA server provided method nodes.
- Client.DataTypeNode ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Nodes/Client.DataTypeNode), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Nodes/Client.DataTypeNode)): This sample demonstrates how to access and work with nodes which use custom data types.
- Client.AnalogItemNode ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Nodes/Client.AnalogItemNode), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Nodes/Client.AnalogItemNode)): This sample demonstrates how to access and work with nodes of the AnalogItemType.

## Call methods

Types used: `OpcClient`, `OpcNodeId`, `OpcCallMethod`

The NodeId defines which method node the client calls. You pass the parameters a method expects when you call `CallMethod` or in the respective `OpcCallMethod` instance. Always specify the NodeId of the owner of the method first, then the NodeId of the method itself. The NodeId of the owner is the identifier of the object node or object type node that references the method through a HasComponent reference.

**Call a single method node without parameters** (the method has no IN arguments):

```csharp
// The result array contains the values of the OUT arguments offered by the method.
object[] result = client.CallMethod(
        "ns=2;s=Machine",                  /* NodeId of Owner Node */
        "ns=2;s=Machine/StartMachine"      /* NodeId of Method Node*/);

```

```vbnet
'The result array contains the values of the OUT arguments offered by the method.
Dim result As Object() = client.CallMethod( _
        "ns=2;s=Machine", _                     'NodeId of Owner Node
        "ns=2;s=Machine/StartMachine")          'NodeId of Method Node

```

**Call a single method node with parameters** (the method has IN arguments):

```csharp
// The result array contains the values of the OUT arguments offered by the method.
object[] result = client.CallMethod(
        "ns=2;s=Machine",                  /* NodeId of Owner Node */
        "ns=2;s=Machine/StopMachine",      /* NodeId of Method Node */
        "Job Change",                      /* Parameter 1: 'reason' */
        10023,                             /* Parameter 2: 'reasonCode' */
        DateTime.Now                       /* Parameter 3: 'scheduleDate' */);

```

```vbnet
'The result array contains the values of the OUT arguments offered by the method.
Dim result As Object() = client.CallMethod( _
        "ns=2;s=Machine", _                     'NodeId of Owner Node
        "ns=2;s=Machine/StopMachine", _         'NodeId of Method Node
        "Job Change", _                         'Parameter 1: 'reason'
        10023, _                                'Parameter 2: 'reasonCode'
        DateTime.Now)                           'Parameter 3: 'scheduleDate'

```

**Call multiple method nodes without parameters** (the methods have no IN arguments):

```csharp
OpcCallMethod[] commands = new OpcCallMethod[] {
    new OpcCallMethod("ns=2;s=Machine", "ns=2;s=Machine/StopMachine"),
    new OpcCallMethod("ns=2;s=Machine", "ns=2;s=Machine/ScheduleJob"),
    new OpcCallMethod("ns=2;s=Machine", "ns=2;s=Machine/StartMachine")
};
 
// The result array contains the values of the OUT arguments offered by the methods.
object[][] results = client.CallMethods(commands);

```

```vbnet
Dim commands As OpcCallMethod() = New OpcCallMethod() { _
    New OpcCallMethod("ns=2;s=Machine", "ns=2;s=Machine/StopMachine"), _
    New OpcCallMethod("ns=2;s=Machine", "ns=2;s=Machine/ScheduleJob"), _
    New OpcCallMethod("ns=2;s=Machine", "ns=2;s=Machine/StartMachine") _
}

'The result array contains the values of the OUT arguments offered by the methods.
Dim results As Object()() = client.CallMethods(commands)

```

**Call multiple method nodes with parameters** (the methods have IN arguments):

```csharp
OpcCallMethod[] commands = new OpcCallMethod[] {
    new OpcCallMethod(
            "ns=2;s=Machine",              /* NodeId of Owner Node */ 
            "ns=2;s=Machine/StopMachine",  /* NodeId of Method Node */
            "Job Change",                  /* Parameter 1: 'reason' */
            10023,                         /* Parameter 2: 'reasonCode' */
            DateTime.Now                   /* Parameter 3: 'scheduleDate' */),
    new OpcCallMethod(
            "ns=2;s=Machine",              /* NodeId of Owner Node */
            "ns=2;s=Machine/ScheduleJob",  /* NodeId of Method Node */
            "MAN_F01_78910"                /* Parameter 1: 'jobSerial' */),
    new OpcCallMethod(
            "ns=2;s=Machine",              /* NodeId of Owner Node */
            "ns=2;s=Machine/StartMachine", /* NodeId of Method Node */
            10021                          /* Parameter 1: 'reasonCode' */)
};
 
// The result array contains the values of the OUT arguments offered by the methods.
object[][] results = client.CallMethods(commands);

```

```vbnet
Dim commands As OpcCallMethod() = New OpcCallMethod() { _
    New OpcCallMethod( _
            "ns=2;s=Machine", _                 'NodeId of Owner Node
            "ns=2;s=Machine/StopMachine", _     'NodeId of Method Node
            "Job Change", _                     'Parameter 1: 'reason'
            10023, _                            'Parameter 2: 'reasonCode'
            DateTime.Now), _                    'Parameter 3: 'scheduleDate'
    New OpcCallMethod( _
            "ns=2;s=Machine", _                 'NodeId of Owner Node
            "ns=2;s=Machine/ScheduleJob", _     'NodeId of Method Node
            "MAN_F01_78910"), _                 'Parameter 1: 'jobSerial'
    New OpcCallMethod( _
            "ns=2;s=Machine", _                 'NodeId of Owner Node
            "ns=2;s=Machine/StartMachine", _    'NodeId of Method Node
            10021) _                            'Parameter 1: 'reasonCode'
}

'The result array contains the values of the OUT arguments offered by the methods.
Dim results As Object()() = client.CallMethods(commands)

```

**Call method nodes in a typed way**: For methods without OUT arguments, `OpcClient` provides the `CallAction` method. For methods with OUT arguments, it provides the `CallFunc` method. The type parameters define the types of the IN arguments, and the last type parameter defines the type of the return value. The method returns the value of the first OUT argument:

```csharp
// Call a method without IN and OUT arguments.
client.CallAction("ns=2;s=Machine", "ns=2;s=Machine/StartMachine");
 
// Call a method with two IN arguments and return the value of its first OUT argument.
int jobId = client.CallFunc<string, int, int>(
        "ns=2;s=Machine",
        "ns=2;s=Machine/StartJob",
        "JOB001",
        10023);
```

```vbnet
'Call a method without IN and OUT arguments.
client.CallAction("ns=2;s=Machine", "ns=2;s=Machine/StartMachine")

'Call a method with two IN arguments and return the value of its first OUT argument.
Dim jobId As Integer = client.CallFunc(Of String, Integer, Integer)( _
        "ns=2;s=Machine", _
        "ns=2;s=Machine/StartJob", _
        "JOB001", _
        10023)
```

## File nodes

Nodes of the type FileType provide the content of a file, which the client accesses like a file in the file system. The page [Read and write files](https://www.traeger.de/en/docs/development/opcua/client/file-access) describes how to read and write such files.

## Query data types

Types used: `OpcClient`, `OpcNodeId`, `OpcNodeInfo`, `OpcTypeNodeInfo`

A server can provide a node that describes a data type defined by the server in more detail. The client might have to retrieve and process this information. Browsing is the easiest way to do this. For data type nodes, the SDK therefore provides a specialization of the `OpcNodeInfo` class: the `OpcTypeNodeInfo` class. Through its properties, the client retrieves additional information about the user-defined data type, for example, whether the data type is an enumeration. If it is, the client also retrieves the enum entries of this type:

```csharp
var machineStatusNode = client.BrowseNode("ns=2;s=MachineStatus") as OpcTypeNodeInfo;
 
if (machineStatusNode != null && machineStatusNode.IsEnum) {
    var members = machineStatusNode.GetEnumMembers();
 
    foreach (var member in members)
        Console.WriteLine(member.Name);
}

```

```vbnet
Dim machineStatusNode = TryCast(client.BrowseNode("ns=2;s=MachineStatus"), OpcTypeNodeInfo)

If machineStatusNode IsNot Nothing AndAlso machineStatusNode.IsEnum Then
    Dim members = machineStatusNode.GetEnumMembers()

    For Each member In members
        Console.WriteLine(member.Name)
    Next
End If

```

## Variables

Types used: `OpcClient`, `OpcNodeId`, `OpcNodeInfo`, `OpcVariableNodeInfo`

Working with variable nodes is often limited to reading and writing the Value attribute. This works the same way as for all nodes, see [Read values](https://www.traeger.de/en/docs/development/opcua/client/read-write-values#read-values) and [Write values](https://www.traeger.de/en/docs/development/opcua/client/read-write-values#write-values). If the client needs more information than the value, it requests it from the server in one step by browsing. This includes, for example, `DataType`, `AccessLevel`, `IsArray`, `ArrayDimensions`, or `IsHistorizing` of the `OpcVariableNodeInfo` class. Separate requests with `ReadNode` are then not necessary. The following example shows this:

```csharp
var machineStatusNode = client.BrowseNode("ns=2;s=Machine/Status") as OpcVariableNodeInfo;
 
if (machineStatusNode != null) {
    Console.WriteLine($"AccessLevel: {machineStatusNode.AccessLevel}");
    Console.WriteLine($"UserAccessLevel: {machineStatusNode.UserAccessLevel}");
    ...
}

```

```vbnet
Dim machineStatusNode = TryCast(client.BrowseNode("ns=2;s=Machine/Status"), OpcVariableNodeInfo)

If machineStatusNode IsNot Nothing Then
    Console.WriteLine("AccessLevel: {0}", machineStatusNode.AccessLevel)
    Console.WriteLine("UserAccessLevel: {0}", machineStatusNode.UserAccessLevel)
    ...
End If

```

The client can also continue browsing directly at the data type node that the variable node uses:

```csharp
var dataTypeNode = machineStatusNode.DataType;
 
if (dataTypeNode.IsSystemType) {
    ...
}

```

```vbnet
Dim dataTypeNode = machineStatusNode.DataType

If dataTypeNode.IsSystemType Then
    ...
End If

```

## Large binary values as a stream

Types used: `OpcClient`, `OpcNodeStream`

The client reads variables with large ByteString values (for example, images, recipes, or logs) through an `OpcNodeStream` like a file, for example, with `CopyTo`. The stream first tries to read the whole value. If that fails, for example, because the value exceeds the data transfer limits, it reads the value in chunks through ranges of the value. The chunk size depends on `MaxByteStringLength`. The stream supports reading only and requires that the node allows reading (AccessLevel `CurrentRead`):

```csharp
using (var source = new OpcNodeStream(client, "ns=2;s=Machine/Snapshot"))
using (var target = File.Create("snapshot.bin")) {
    source.CopyTo(target);
}

```

```vbnet
Using source = New OpcNodeStream(client, "ns=2;s=Machine/Snapshot")
    Using target = IO.File.Create("snapshot.bin")
        source.CopyTo(target)
    End Using
End Using
```

## Data items

Types used: `OpcClient`, `OpcNodeId`

Data item nodes that a server provides as `OpcDataItemNode` extend a simple `OpcDataVariableNode`. They also mainly provide values. In addition, they supply further useful metadata. Most important is the "Definition" property, which is a property node below this node. It helps to interpret and process the data of the node correctly. Its vendor-specific value describes how the value of the node is determined. Apart from that, the operations from [Read and write values](https://www.traeger.de/en/docs/development/opcua/client/read-write-values) also work for this specialization. The client reads "Definition" like any other child node, for example, through `Child("Definition")` when browsing or through `ReadNode` with the identifier of the property node.

## Analog items

Types used: `OpcClient`, `OpcNodeId`, `OpcNodeInfo`, `OpcAnalogItemNodeInfo`

Analog items are a specialization of the data item node `OpcDataItemNode`. Their values are mainly analog. The additional properties `InstrumentRange`, `EngineeringUnit`, and `EngineeringUnitRange` describe them in more detail. `InstrumentRange` describes the value range of the analog data of the source. `EngineeringUnit` defines the unit of measure of the value the node provides. In normal operation, the determined value lies within the value range defined by the `EngineeringUnitRange` property. The unit of measure in the `EngineeringUnit` property follows UNECE Recommendation No. 20. These recommendations are based on the International System of Units (SI units). To make this additional information easier to process, the `OpcAnalogItemNodeInfo` class provides the corresponding interface when browsing:

```csharp
var temperatureNode = client.BrowseNode("ns=2;s=Machine/Temperature") as OpcAnalogItemNodeInfo;
 
if (temperatureNode != null) {
    Console.WriteLine($"InstrumentRange: {temperatureNode.InstrumentRange}");
 
    Console.WriteLine($"EngineeringUnit: {temperatureNode.EngineeringUnit}");
    Console.WriteLine($"EngineeringUnitRange: {temperatureNode.EngineeringUnitRange}");
}

```

```vbnet
Dim temperatureNode = TryCast(client.BrowseNode("ns=2;s=Machine/Temperature"), OpcAnalogItemNodeInfo)

If temperatureNode IsNot Nothing Then
    Console.WriteLine("InstrumentRange: {0}", temperatureNode.InstrumentRange)

    Console.WriteLine("EngineeringUnit: {0}", temperatureNode.EngineeringUnit)
    Console.WriteLine("EngineeringUnitRange: {0}", temperatureNode.EngineeringUnitRange)
End If

```

The information contained in an `OpcEngineeringUnitInfo` describes a unit of measure from the UNECE table of units of measure. You can look up the possible units at the OPC Foundation: [UNECE units of measure in OPC UA (currently unavailable)](http://www.opcfoundation.org/UA/EngineeringUnits/UNECE/UNECE_to_OPCUA.csv). Alternatively, the MTConnect Institute also provides the UNECE table on GitHub: [UNECE units of measure in OPC UA (MTConnect@GitHub)](https://github.com/mtconnect/opc_ua_architecture/blob/master/UNECE_to_OPCUA.csv).
