Zum Inhalt springen

Anleitung

Adressraum bearbeiten

Nodes und Verweise im Adressraum eines Servers vom Client aus erstellen und löschen.

Anleitung

Adressraum bearbeiten ​

Nodes anlegen ​

Beteiligte TypenOpcClientOpcAddNodeOpcAddNodeResultOpcAddNodeResultCollectionOpcAddDataItemNodeOpcAddAnalogItemNodeOpcAddObjectNodeOpcAddFolderNodeOpcAddDataVariableNodeOpcAddPropertyNode

Ein Server stellt seinen Clients einen vordefinierten Satz an Standard-Nodes bereit. Ein Client kann den Server veranlassen, weitere Nodes bereitzustellen. Dafür nutzt er die Schnittstelle AddNodes des Servers. Für typspezifische Nodes bietet das SDK zahlreiche Unterklassen der Klasse OpcAddNode. So legen Sie einen neuen Ordner-Node an:

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"))

Die Parameter im Beispiel enthalten die mindestens nötigen Angaben. Der erste Parameter name legt den Namen (Eigenschaft Name, der BrowseName des Nodes) und den Anzeigenamen (Eigenschaft DisplayName) des Nodes fest. Eine Beschreibung legen Sie über die Eigenschaft Description fest. Der zweite Parameter nodeId gibt dem Server vor, welchen Identifier er dem Node zuweisen soll. Wenn ein anderer Node im Adressraum des Servers diesen Identifier bereits verwendet, legt der Server den Node nicht an. Ein mit dem SDK entwickelter Server liefert dann den Code BadNodeIdRejected, andere Server liefern unter Umständen BadNodeIdExists. Wenn Sie wie im Beispiel OpcNodeId.Null übergeben, erzeugt der Server selbst einen neuen Identifier und weist ihn dem Node zu. Der Parameter parentNodeId legt schließlich den Identifier des Eltern-Nodes fest, unter dem der Server den neuen Node im Baum anlegt. Wenn kein Eltern-Node angegeben ist, legt der Server den Node unterhalb des ObjectsFolder an.

Der Aufruf der Methode AddNode liefert eine Instanz der Klasse OpcAddNodeResult. Sie enthält neben dem Ausgang der Operation auch den Identifier, den der Server tatsächlich für den neuen Node verwendet hat:

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

So legen Sie mehrere Nodes gleichzeitig an:

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))

Der Aufruf der Methode AddNodes liefert eine Instanz der Klasse OpcAddNodeResultCollection. Sie enthält Instanzen von OpcAddNodeResult, die Sie wie oben beschrieben auswerten und weiterverarbeiten.

Den Methoden AddNode und AddNodes können Sie auch ganze Bäume von Nodes übergeben:

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"))))

Einen solchen Baum können Sie auch über die zugehörigen Eigenschaften aufbauen:

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)

Wenn Sie andere Typdefinitionen verwenden möchten als die der Unterklassen von OpcAddNode, legen Sie Objekt- und Variablen-Nodes anhand ihrer Typdefinition an:

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

Neben den von der Foundation definierten Typdefinitionen können Sie Nodes auch anhand des Identifiers ihrer Typdefinition anlegen. Dazu deklarieren Sie den Typ vorab über eine objekt- beziehungsweise variablenspezifische Typdefinition. OpcNodeId.Parse erzeugt den Identifier der Typdefinition aus seiner Zeichenfolge. Diesen Identifier verwenden Sie beliebig oft, um weitere Nodes dieses Typs zu erstellen:

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")))

Nodes löschen ​

Beteiligte TypenOpcClientOpcDeleteNodeOpcStatusOpcStatusCollection

Über die Schnittstelle DeleteNodes des Servers löschen Sie sowohl vom Server bereitgestellte als auch von einem Client erstellte Nodes. Dafür benötigen Sie vor allem den Identifier des Nodes, den Sie löschen möchten:

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

Das Beispiel oben löscht mit einer Instanz der Klasse OpcDeleteNode. Sie löscht standardmäßig auch alle Verweise, die auf den Node zeigen. Wenn die Verweise auf den Node bestehen bleiben sollen, setzen Sie zusätzlich den Parameter includeTargetReferences auf 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)

So löschen Sie mehrere Nodes gleichzeitig:

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"))

Verweise anlegen ​

Beteiligte TypenOpcClientOpcAddReferenceOpcStatusOpcStatusCollection

Nodes im Adressraum eines Servers können unterschiedliche Beziehungen zueinander haben. Der Adressraum beschreibt diese Beziehungen über Verweise (engl. References). Neben der Einordnung als Eltern- oder Kind-Node können zwischen Nodes weitere logische Beziehungen bestehen. Diese Beziehungen beschreiben genauer, welche Funktion die Nodes haben und wie sie voneinander abhängen. Außerdem lassen sich über Verweise weitere Bäume im Adressraum des Servers definieren, ohne vorhandene Nodes neu zu organisieren.

Um einen Verweis anzulegen, nutzt der Client die Schnittstelle AddReferences des Servers:

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)

Das Beispiel erzeugt einen Verweis vom Typ Organizes, der vom Node mit dem Identifier ns=2;s=Plant zum Node ns=2;s=Machines/MAC01 führt. Standardmäßig verwendet der Client den Verweistyp Organizes und die Richtung OpcReferenceDirection.ParentToChild. Bei dieser Richtung wird der erste Node zum Eltern-Node. Die Anweisung führt damit zum selben Ergebnis wie das folgende Beispiel:

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)

Der erste Identifier gibt immer den Quell-Node an, der Parameter targetNodeId den Identifier des Ziel-Nodes. Mit der Richtung OpcReferenceDirection.ChildToParent legt der Client den Verweis stattdessen vom Ziel-Node zum Quell-Node an. Der zusätzliche Parameter targetNodeCategory muss der Eigenschaft Category des Ziel-Nodes entsprechen, in der Spezifikation die NodeClass. Anhand dieses Werts stellt der Server sicher, dass der gewünschte Ziel-Node ausreichend bekannt ist.

So legen Sie mehrere Verweise gleichzeitig an:

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))

Das Beispiel oben ordnet drei Nodes zusätzlich unterhalb der Nodes „Plant01“ und „Plant02“ ein. Jeder dieser Nodes repräsentiert eine Maschine und liegt unterhalb des Nodes „Machines“. Durch den standardmäßig verwendeten Verweistyp Organizes bleiben die Nodes weiterhin unterhalb von „Machines“ verfügbar. Zusätzlich erscheinen „MAC01“ und „MAC02“ unterhalb von „Plant01“ und „MAC03“ unterhalb von „Plant02“.

Verweise löschen ​

Beteiligte TypenOpcClientOpcDeleteReferenceOpcStatusOpcStatusCollection

Bestehende Verweise zwischen Nodes im Adressraum des Servers löschen Sie über die Schnittstelle DeleteReferences des Servers:

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")

Das Beispiel löscht alle Organizes-Verweise zwischen den Nodes mit den Identifiern ns=2;s=Machines/MAC03 und ns=2;s=Plant, und zwar in beiden Richtungen. So löschen Sie nur die Organizes-Verweise in einer bestimmten Richtung vom Quell- zum Ziel-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)

Um Verweise eines anderen Typs als Organizes zu löschen, geben Sie den Typ über den zusätzlichen Parameter referenceType beziehungsweise referenceTypeId an:

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)

So löschen Sie mehrere Verweise gleichzeitig:

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"))