Skip to content

How-to guide

Edit the address space

Create and delete nodes and references in the address space of a server from the client.

This content was machine translated and may contain errors. Read in German

How-to guide

Edit the address space ​

Create nodes ​

Types usedOpcClientOpcAddNodeOpcAddNodeResultOpcAddNodeResultCollectionOpcAddDataItemNodeOpcAddAnalogItemNodeOpcAddObjectNodeOpcAddFolderNodeOpcAddDataVariableNodeOpcAddPropertyNode

A server provides its clients with a predefined set of standard nodes. A client can make the server provide additional nodes. For this, the client uses the AddNodes interface of the server. For type-specific nodes, the SDK provides many subclasses of the OpcAddNode class. To create a new folder node:

csharp
OpcAddNodeResult result = client.AddNode(new OpcAddFolderNode(
    name: "Jobs",
    nodeId: OpcNodeId.Null,
    parentNodeId: "ns=2;s=Machine"));
vbnet
Dim result As OpcAddNodeResult = client.AddNode(New OpcAddFolderNode( _
        name:="Jobs", _
        nodeId:=OpcNodeId.Null, _
        parentNodeId:="ns=2;s=Machine"))

The parameters in the example contain the minimum required information. The first parameter, name, sets the name (property Name, the BrowseName of the node) and the display name (property DisplayName) of the node. To set a description, use the Description property. The second parameter, nodeId, tells the server which identifier to assign to the node. If another node in the address space of the server already uses this identifier, the server does not create the node. A server developed with the SDK then returns the code BadNodeIdRejected; other servers might return BadNodeIdExists. If you pass OpcNodeId.Null as in the example, the server generates a new identifier itself and assigns it to the node. Finally, the parentNodeId parameter sets the identifier of the parent node under which the server creates the new node in the tree. If you do not specify a parent node, the server creates the node below the ObjectsFolder.

The AddNode method returns an instance of the OpcAddNodeResult class. Besides the outcome of the operation, it contains the identifier the server actually used for the new node:

csharp
if (result.IsGood)
    Console.WriteLine("NodeId of 'Jobs': {0}", result.NodeId);
else
    Console.WriteLine("Failed to add node: {0}", result.Description);
vbnet
If result.IsGood Then
    Console.WriteLine("NodeId of 'Jobs': {0}", result.NodeId)
Else
    Console.WriteLine("Failed to add node: {0}", result.Description)
End If

To create multiple nodes at once:

csharp
OpcNodeId jobsNodeId = result.NodeId;
 
OpcAddNodeResultCollection results = client.AddNodes(
        new OpcAddDataVariableNode<string>("CurrentJob", jobsNodeId),
        new OpcAddDataVariableNode<string>("NextJob", jobsNodeId),
        new OpcAddDataVariableNode<int>("NumberOfJobs", jobsNodeId));
vbnet
Dim jobsNodeId As OpcNodeId = result.NodeId

Dim results As OpcAddNodeResultCollection = client.AddNodes( _
        New OpcAddDataVariableNode(Of String)("CurrentJob", jobsNodeId), _
        New OpcAddDataVariableNode(Of String)("NextJob", jobsNodeId), _
        New OpcAddDataVariableNode(Of Integer)("NumberOfJobs", jobsNodeId))

The AddNodes method returns an instance of the OpcAddNodeResultCollection class. It contains instances of OpcAddNodeResult, which you evaluate and process as described above.

You can also pass entire trees of nodes to the AddNode and AddNodes methods:

csharp
OpcAddNodeResultCollection results = client.AddNodes(
        new OpcAddObjectNode(
                "JOB001",
                nodeId: OpcNodeId.Null,
                parentNodeId: jobsNodeId,
                new OpcAddDataVariableNode<sbyte>("Status", -1),
                new OpcAddDataVariableNode<string>("Serial", "J01-DX-11.001"),
                new OpcAddAnalogItemNode<float>("Speed", 1200f) {
                    EngineeringUnit = new OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
                    EngineeringUnitRange = new OpcValueRange(5400, 0),
                    Definition = "DB100.DBW 0"
                },
                new OpcAddObjectNode(
                        "Setup",
                        new OpcAddPropertyNode<bool>("UseCutter"),
                        new OpcAddPropertyNode<bool>("UseDrill")),
                new OpcAddObjectNode(
                        "Schedule",
                        new OpcAddPropertyNode<DateTime>("EarliestStartTime"),
                        new OpcAddPropertyNode<DateTime>("LatestStartTime"),
                        new OpcAddPropertyNode<TimeSpan>("EstimatedRunTime"))),
        new OpcAddObjectNode(
                "JOB002",
                nodeId: OpcNodeId.Null,
                parentNodeId: jobsNodeId,
                new OpcAddDataVariableNode<sbyte>("Status", -1),
                new OpcAddDataVariableNode<string>("Serial", "J01-DX-53.002"),
                new OpcAddAnalogItemNode<float>("Speed", 3210f) {
                    EngineeringUnit = new OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
                    EngineeringUnitRange = new OpcValueRange(5400, 0),
                    Definition = "DB200.DBW 0"
                },
                new OpcAddObjectNode(
                        "Setup",
                        new OpcAddPropertyNode<bool>("UseCutter"),
                        new OpcAddPropertyNode<bool>("UseDrill")),
                new OpcAddObjectNode(
                        "Schedule",
                        new OpcAddPropertyNode<DateTime>("EarliestStartTime"),
                        new OpcAddPropertyNode<DateTime>("LatestStartTime"),
                        new OpcAddPropertyNode<TimeSpan>("EstimatedRunTime"))));
vbnet
Dim results As OpcAddNodeResultCollection = client.AddNodes( _
        New OpcAddObjectNode( _
                "JOB001", _
                nodeId:=OpcNodeId.Null, _
                parentNodeId:=jobsNodeId, _
                New OpcAddDataVariableNode(Of SByte)("Status", -1), _
                New OpcAddDataVariableNode(Of String)("Serial", "J01-DX-11.001"), _
                New OpcAddAnalogItemNode(Of Single)("Speed", 1200F) With {
                    .EngineeringUnit = New OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
                    .EngineeringUnitRange = New OpcValueRange(5400, 0),
                    .Definition = "DB100.DBW 0"
                }, _
                New OpcAddObjectNode( _
                        "Setup", _
                        New OpcAddPropertyNode(Of Boolean)("UseCutter"), _
                        New OpcAddPropertyNode(Of Boolean)("UseDrill")), _
                New OpcAddObjectNode( _
                        "Schedule", _
                        New OpcAddPropertyNode(Of DateTime)("EarliestStartTime"), _
                        New OpcAddPropertyNode(Of DateTime)("LatestStartTime"), _
                        New OpcAddPropertyNode(Of TimeSpan)("EstimatedRunTime"))), _
        New OpcAddObjectNode( _
                "JOB002", _
                nodeId:=OpcNodeId.Null, _
                parentNodeId:=jobsNodeId, _
                New OpcAddDataVariableNode(Of SByte)("Status", -1), _
                New OpcAddDataVariableNode(Of String)("Serial", "J01-DX-53.002"), _
                New OpcAddAnalogItemNode(Of Single)("Speed", 3210F) With {
                    .EngineeringUnit = New OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
                    .EngineeringUnitRange = New OpcValueRange(5400, 0),
                    .Definition = "DB200.DBW 0" _
                }, _
                New OpcAddObjectNode( _
                        "Setup", _
                        New OpcAddPropertyNode(Of Boolean)("UseCutter"), _
                        New OpcAddPropertyNode(Of Boolean)("UseDrill")), _
                New OpcAddObjectNode( _
                        "Schedule", _
                        New OpcAddPropertyNode(Of DateTime)("EarliestStartTime"), _
                        New OpcAddPropertyNode(Of DateTime)("LatestStartTime"), _
                        New OpcAddPropertyNode(Of TimeSpan)("EstimatedRunTime"))))

You can also build such a tree through the corresponding properties:

csharp
var jobsNodeId = result.NodeId;
 
var job = new OpcAddObjectNode(
        name: "JOB003",
        nodeId: OpcNodeId.Null,
        parentNodeId: jobsNodeId);
 
job.Children.Add(new OpcAddDataVariableNode<sbyte>("Status", -1));
job.Children.Add(new OpcAddDataVariableNode<string>("Serial", "J01-DX-78.003"));
job.Children.Add(new OpcAddAnalogItemNode<float>("Speed", 1200f) {
    EngineeringUnit = new OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
    EngineeringUnitRange = new OpcValueRange(5400, 0),
    Definition = "DB100.DBW 0"
});
 
var setup = new OpcAddObjectNode("Setup");
setup.Children.Add(new OpcAddPropertyNode<bool>("UseCutter"));
setup.Children.Add(new OpcAddPropertyNode<bool>("UseDrill"));
 
job.Children.Add(setup);
 
var schedule = new OpcAddObjectNode("Schedule");
schedule.Children.Add(new OpcAddPropertyNode<DateTime>("EarliestStartTime"));
schedule.Children.Add(new OpcAddPropertyNode<DateTime>("LatestStartTime"));
schedule.Children.Add(new OpcAddPropertyNode<TimeSpan>("EstimatedRunTime"));
 
job.Children.Add(schedule);
 
OpcAddNodeResult result = client.AddNode(job);
vbnet
Dim jobsNodeId = result.NodeId
 
Dim job = New OpcAddObjectNode( _
        name:="JOB003", _
        nodeId:=OpcNodeId.Null, _
        parentNodeId:=jobsNodeId)
 
job.Children.Add(New OpcAddDataVariableNode(Of SByte)("Status", -1))
job.Children.Add(New OpcAddDataVariableNode(Of String)("Serial", "J01-DX-78.003"))
job.Children.Add(new OpcAddAnalogItemNode(Of Single)("Speed", 1200f) With {
    .EngineeringUnit = new OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
    .EngineeringUnitRange = new OpcValueRange(5400, 0),
    .Definition = "DB100.DBW 0" _
})
 
Dim setup = New OpcAddObjectNode("Setup")
setup.Children.Add(New OpcAddPropertyNode(Of Boolean)("UseCutter"))
setup.Children.Add(New OpcAddPropertyNode(Of Boolean)("UseDrill"))

job.Children.Add(setup)

Dim schedule = New OpcAddObjectNode("Schedule")
schedule.Children.Add(New OpcAddPropertyNode(Of DateTime)("EarliestStartTime"))
schedule.Children.Add(New OpcAddPropertyNode(Of DateTime)("LatestStartTime"))
schedule.Children.Add(New OpcAddPropertyNode(Of TimeSpan)("EstimatedRunTime"))

job.Children.Add(schedule)

Dim result As OpcAddNodeResult = client.AddNode(job)

To use type definitions other than those of the OpcAddNode subclasses, create object and variable nodes based on their type definition:

csharp
client.AddObjectNode(OpcObjectType.DeviceFailureEventType, "FailureInfo");
client.AddVariableNode(OpcVariableType.XYArrayItem, "Coordinates");
vbnet
client.AddObjectNode(OpcObjectType.DeviceFailureEventType, "FailureInfo")
client.AddVariableNode(OpcVariableType.XYArrayItem, "Coordinates")

Besides the type definitions defined by the OPC Foundation, you can also create nodes based on the identifier of their type definition. To do this, declare the type in advance through an object-specific or variable-specific type definition. OpcNodeId.Parse creates the identifier of the type definition from its string. You can use this identifier as often as you like to create more nodes of this type:

csharp
// Declare Job Type
var jobType = OpcAddObjectNode.OfType(OpcNodeId.Parse("ns=2;s=Types/JobType"));
 
client.AddNodes(
        jobType.Create("JOB001", nodeId: OpcNodeId.Null, parentNodeId: jobsNodeId),
        jobType.Create("JOB002", nodeId: OpcNodeId.Null, parentNodeId: jobsNodeId),
        jobType.Create("JOB003", nodeId: OpcNodeId.Null, parentNodeId: jobsNodeId),
        jobType.Create("JOB004", nodeId: OpcNodeId.Null, parentNodeId: jobsNodeId));
 
var scheduleNodeId = OpcNodeId.Parse("ns=2;s=Machine/JOB002/Schedule");
 
// Declare Shift Time Type
var shiftTimeType = OpcAddVariableNode.OfType(OpcNodeId.Parse("ns=2;s=Types/ShiftTimeType"));
 
OpcAddNodeResult result = client.AddNode(new OpcAddObjectNode(
        "ShiftPlanning",
        nodeId: OpcNodeId.Null,
        parentNodeId: scheduleNodeId,
        shiftTimeType.Create("Early"),
        shiftTimeType.Create("Noon"),
        shiftTimeType.Create("Late")));
vbnet
'Declare Job Type
Dim jobType = OpcAddObjectNode.OfType(OpcNodeId.Parse("ns=2;s=Types/JobType"))

client.AddNodes( _
        jobType.Create("JOB001", nodeId:=OpcNodeId.Null, parentNodeId:=jobsNodeId), _
        jobType.Create("JOB002", nodeId:=OpcNodeId.Null, parentNodeId:=jobsNodeId), _
        jobType.Create("JOB003", nodeId:=OpcNodeId.Null, parentNodeId:=jobsNodeId), _
        jobType.Create("JOB004", nodeId:=OpcNodeId.Null, parentNodeId:=jobsNodeId))

Dim scheduleNodeId = OpcNodeId.Parse("ns=2;s=Machine/JOB002/Schedule")

'Declare Shift Time Type
Dim shiftTimeType = OpcAddVariableNode.OfType(OpcNodeId.Parse("ns=2;s=Types/ShiftTimeType"))

Dim result As OpcAddNodeResult = client.AddNode(New OpcAddObjectNode( _
        "ShiftPlanning", _
        nodeId:=OpcNodeId.Null, _
        parentNodeId:=scheduleNodeId, _
        shiftTimeType.Create("Early"), _
        shiftTimeType.Create("Noon"), _
        shiftTimeType.Create("Late")))

Delete nodes ​

Types usedOpcClientOpcDeleteNodeOpcStatusOpcStatusCollection

Through the DeleteNodes interface of the server, you can delete both nodes provided by the server and nodes created by a client. Above all, you need the identifier of the node you want to delete:

csharp
OpcStatus result = client.DeleteNode("ns=2;s=Machine/Jobs");
vbnet
Dim result As OpcStatus = client.DeleteNode("ns=2;s=Machine/Jobs")

The example above deletes the node with an instance of the OpcDeleteNode class. By default, it also deletes all references that point to the node. To keep the references to the node, also set the includeTargetReferences parameter to false:

csharp
OpcStatus result = client.DeleteNode(
        "ns=2;s=Machine/Jobs",
        includeTargetReferences: false);
vbnet
Dim result As OpcStatus = client.DeleteNode( _
        "ns=2;s=Machine/Jobs", _
        includeTargetReferences:=False)

To delete multiple nodes at once:

csharp
OpcStatusCollection results = client.DeleteNodes(
        new OpcDeleteNode("ns=2;s=Machine/Jobs/JOB001"),
        new OpcDeleteNode("ns=2;s=Machine/Jobs/JOB002"),
        new OpcDeleteNode("ns=2;s=Machine/Jobs/JOB003"));
vbnet
Dim results As OpcStatusCollection = client.DeleteNodes( _
        New OpcDeleteNode("ns=2;s=Machine/Jobs/JOB001"), _
        New OpcDeleteNode("ns=2;s=Machine/Jobs/JOB002"), _
        New OpcDeleteNode("ns=2;s=Machine/Jobs/JOB003"))

Create references ​

Types usedOpcClientOpcAddReferenceOpcStatusOpcStatusCollection

Nodes in the address space of a server can relate to each other in different ways. The address space describes these relationships through references. Besides the parent-child arrangement, nodes can have further logical relationships. These relationships describe in more detail what function the nodes have and how they depend on each other. References also let you define additional trees in the address space of the server without reorganizing existing nodes.

To create a reference, the client uses the AddReferences interface of the server:

csharp
client.AddReference(
        "ns=2;s=Plant",
        targetNodeId: "ns=2;s=Machines/MAC01",
        targetNodeCategory: OpcNodeCategory.Object);
vbnet
client.AddReference( _
        "ns=2;s=Plant", _
        targetNodeId:="ns=2;s=Machines/MAC01", _
        targetNodeCategory:=OpcNodeCategory.Object)

The example creates a reference of the type Organizes that leads from the node with the identifier ns=2;s=Plant to the node ns=2;s=Machines/MAC01. By default, the client uses the reference type Organizes and the direction OpcReferenceDirection.ParentToChild. With this direction, the first node becomes the parent node. The statement therefore has the same result as the following example:

csharp
client.AddReference(
        "ns=2;s=Plant",
        targetNodeId: "ns=2;s=Machines/MAC01",
        targetNodeCategory: OpcNodeCategory.Object,
        direction: OpcReferenceDirection.ParentToChild,
        referenceType: OpcReferenceType.Organizes);
vbnet
client.AddReference( _
        "ns=2;s=Plant", _
        targetNodeId:="ns=2;s=Machines/MAC01", _
        targetNodeCategory:=OpcNodeCategory.Object, _
        direction:=OpcReferenceDirection.ParentToChild, _
        referenceType:=OpcReferenceType.Organizes)

The first identifier always specifies the source node, the targetNodeId parameter the identifier of the target node. With the direction OpcReferenceDirection.ChildToParent, the client creates the reference from the target node to the source node instead. The additional targetNodeCategory parameter must match the Category property of the target node, the NodeClass in the specification. The server uses this value to make sure that it knows the requested target node well enough.

To create multiple references at once:

csharp
client.AddReferences(
        new OpcAddReference(
                "ns=2;s=Plant01",
                targetNodeId: "ns=2;s=Machines/MAC01",
                targetNodeCategory: OpcNodeCategory.Object),
        new OpcAddReference(
                "ns=2;s=Plant01",
                targetNodeId: "ns=2;s=Machines/MAC02",
                targetNodeCategory: OpcNodeCategory.Object),
        new OpcAddReference(
                "ns=2;s=Plant02",
                targetNodeId: "ns=2;s=Machines/MAC03",
                targetNodeCategory: OpcNodeCategory.Object));
vbnet
client.AddReferences( _
        New OpcAddReference( _
                "ns=2;s=Plant01", _
                targetNodeId:="ns=2;s=Machines/MAC01", _
                targetNodeCategory:=OpcNodeCategory.Object), _
        New OpcAddReference( _
                "ns=2;s=Plant01", _
                targetNodeId:="ns=2;s=Machines/MAC02", _
                targetNodeCategory:=OpcNodeCategory.Object), _
        New OpcAddReference( _
                "ns=2;s=Plant02", _
                targetNodeId:="ns=2;s=Machines/MAC03", _
                targetNodeCategory:=OpcNodeCategory.Object))

The example above also places three nodes below the nodes "Plant01" and "Plant02". Each of these nodes represents a machine and is located below the node "Machines". Because the default reference type is Organizes, the nodes remain available below "Machines". In addition, "MAC01" and "MAC02" appear below "Plant01", and "MAC03" appears below "Plant02".

Delete references ​

Types usedOpcClientOpcDeleteReferenceOpcStatusOpcStatusCollection

To delete existing references between nodes in the address space of the server, use the DeleteReferences interface of the server:

csharp
client.DeleteReference(
        nodeId: "ns=2;s=Machines/MAC03",
        targetNodeId: "ns=2;s=Plant");
vbnet
client.DeleteReference( _
        nodeId:="ns=2;s=Machines/MAC03", _
        targetNodeId:="ns=2;s=Plant")

The example deletes all Organizes references between the nodes with the identifiers ns=2;s=Machines/MAC03 and ns=2;s=Plant, in both directions. To delete only the Organizes references in one direction, from the source node to the target node:

csharp
client.DeleteReference(
        nodeId: "ns=2;s=Machines/MAC03",
        targetNodeId: "ns=2;s=Plant",
        direction: OpcReferenceDirection.ChildToParent);
vbnet
client.DeleteReference( _
        nodeId:="ns=2;s=Machines/MAC03", _
        targetNodeId:="ns=2;s=Plant", _
        direction:=OpcReferenceDirection.ChildToParent)

To delete references of a type other than Organizes, specify the type through the additional referenceType or referenceTypeId parameter:

csharp
client.DeleteReference(
        nodeId: "ns=2;s=Machines/MAC03",
        targetNodeId: "ns=2;s=Plant",
        direction: OpcReferenceDirection.ChildToParent, 
        referenceType: OpcReferenceType.HierarchicalReferences);
vbnet
client.DeleteReference( _
        nodeId:="ns=2;s=Machines/MAC03", _
        targetNodeId:="ns=2;s=Plant", _
        direction:=OpcReferenceDirection.ChildToParent, _
        referenceType:=OpcReferenceType.HierarchicalReferences)

To delete multiple references at once:

csharp
client.DeleteReferences(
        new OpcDeleteReference("ns=2;s=Machines/MAC01", "ns=2;s=Plant01"),
        new OpcDeleteReference("ns=2;s=Machines/MAC02", "ns=2;s=Plant01"),
        new OpcDeleteReference("ns=2;s=Machines/MAC03", "ns=2;s=Plant02"));
vbnet
client.DeleteReferences( _
        New OpcDeleteReference("ns=2;s=Machines/MAC01", "ns=2;s=Plant01"), _
        New OpcDeleteReference("ns=2;s=Machines/MAC02", "ns=2;s=Plant01"), _
        New OpcDeleteReference("ns=2;s=Machines/MAC03", "ns=2;s=Plant02"))