Zum Inhalt springen

Anleitung

Werte lesen und schreiben

Werte einzelner und mehrerer Nodes lesen und schreiben, andere Attribute und Teile von Arrays ansprechen und Ergebnisse mit Status auswerten.

Anleitung

Werte lesen und schreiben ​

Werte lesen ​

Beteiligte TypenOpcClientOpcNodeIdOpcValueOpcAttributeOpcReadNode

Die NodeId (OpcNodeId) legt fest, welchen Node der Client liest. Standardmäßig liest der Client immer den aktuellen Wert des Value-Attributs. Der gelesene OpcValue enthält neben dem Wert zwei Zeitstempel. SourceTimestamp gibt an, wann die Quelle den Wert festgestellt hat. ServerTimestamp gibt an, wann der Server den Wert erfasst hat. Wenn Sie ein anderes Attribut des Nodes lesen, geben Sie das passende OpcAttribute beim Aufruf von ReadNode oder in der jeweiligen Instanz von OpcReadNode an.

Den Wert des Value-Attributs eines einzelnen Nodes lesen:

csharp
OpcValue isRunning = client.ReadNode("ns=2;s=Machine/IsRunning");
vbnet
Dim isRunning As OpcValue = client.ReadNode("ns=2;s=Machine/IsRunning")

Die Werte des Value-Attributs mehrerer Nodes lesen:

csharp
OpcReadNode[] commands = new OpcReadNode[] {
    new OpcReadNode("ns=2;s=Machine/Job/Number"),
    new OpcReadNode("ns=2;s=Machine/Job/Name"),
    new OpcReadNode("ns=2;s=Machine/Job/Speed")
};

IEnumerable<OpcValue> job = client.ReadNodes(commands);
vbnet
Dim commands As OpcReadNode() = New OpcReadNode() { _
    New OpcReadNode("ns=2;s=Machine/Job/Number"), _
    New OpcReadNode("ns=2;s=Machine/Job/Name"), _
    New OpcReadNode("ns=2;s=Machine/Job/Speed") _
}

Dim job As IEnumerable(Of OpcValue) = client.ReadNodes(commands)

Den Wert des DisplayName-Attributs eines einzelnen Nodes lesen:

csharp
OpcValue isRunningDisplayName = client.ReadNode("ns=2;s=Machine/IsRunning", OpcAttribute.DisplayName);
vbnet
Dim isRunningDisplayName As OpcValue = client.ReadNode("ns=2;s=Machine/IsRunning", OpcAttribute.DisplayName)

Die Werte des DisplayName-Attributs mehrerer Nodes lesen:

csharp
OpcReadNode[] commands = new OpcReadNode[] {
    new OpcReadNode("ns=2;s=Machine/Job/Number", OpcAttribute.DisplayName),
    new OpcReadNode("ns=2;s=Machine/Job/Name", OpcAttribute.DisplayName),
    new OpcReadNode("ns=2;s=Machine/Job/Speed", OpcAttribute.DisplayName)
};
 
IEnumerable<OpcValue> jobDisplayNames = client.ReadNodes(commands);
vbnet
Dim commands As OpcReadNode() = New OpcReadNode() { _
    New OpcReadNode("ns=2;s=Machine/Job/Number", OpcAttribute.DisplayName), _
    New OpcReadNode("ns=2;s=Machine/Job/Name", OpcAttribute.DisplayName), _
    New OpcReadNode("ns=2;s=Machine/Job/Speed", OpcAttribute.DisplayName) _
}

Dim jobDisplayNames As IEnumerable(Of OpcValue) = client.ReadNodes(commands)

Werte schreiben ​

Beteiligte TypenOpcClientOpcNodeIdOpcValueOpcAttributeOpcStatusOpcStatusCollectionOpcWriteNode

Die NodeId (OpcNodeId) legt fest, welchen Node der Client schreibt. Standardmäßig schreibt der Client immer den aktuellen Wert des Value-Attributs. Als Zeitstempel der Quelle (SourceTimestamp) sendet der Client standardmäßig den Zeitstempel des übergebenen OpcValue. Wenn Sie nur einen Wert übergeben, sendet er keinen Zeitstempel. Wie sich das ändern lässt, zeigt der Abschnitt Zeitstempel beim Schreiben. Wenn Sie ein anderes Attribut des Nodes schreiben, geben Sie das passende OpcAttribute beim Aufruf von WriteNode oder in der jeweiligen Instanz von OpcWriteNode an.

Den Wert eines einzelnen Nodes schreiben:

csharp
OpcStatus result = client.WriteNode("ns=2;s=Machine/Job/Cancel", true);
vbnet
Dim result As OpcStatus = client.WriteNode("ns=2;s=Machine/Job/Cancel", True)

Die Werte mehrerer Nodes schreiben:

csharp
OpcWriteNode[] commands = new OpcWriteNode[] {
    new OpcWriteNode("ns=2;s=Machine/Job/Number", "0002"),
    new OpcWriteNode("ns=2;s=Machine/Job/Name", "MAN_F01_78910"),
    new OpcWriteNode("ns=2;s=Machine/Job/Speed", 1220.5)
};
 
OpcStatusCollection results = client.WriteNodes(commands);
vbnet
Dim commands As OpcWriteNode() = New OpcWriteNode() { _
    New OpcWriteNode("ns=2;s=Machine/Job/Number", "0002"), _
    New OpcWriteNode("ns=2;s=Machine/Job/Name", "MAN_F01_78910"), _
    New OpcWriteNode("ns=2;s=Machine/Job/Speed", 1220.5) _
}

Dim results As OpcStatusCollection = client.WriteNodes(commands)

Den Wert des DisplayName-Attributs eines einzelnen Nodes schreiben:

csharp
client.WriteNode("ns=2;s=Machine/IsRunning", OpcAttribute.DisplayName, "IsActive");
vbnet
client.WriteNode("ns=2;s=Machine/IsRunning", OpcAttribute.DisplayName, "IsActive")

Die Werte des DisplayName-Attributs mehrerer Nodes schreiben:

csharp
OpcWriteNode[] commands = new OpcWriteNode[] {
    new OpcWriteNode("ns=2;s=Machine/Job/Number", OpcAttribute.DisplayName, "Serial"),
    new OpcWriteNode("ns=2;s=Machine/Job/Name", OpcAttribute.DisplayName, "Description"),
    new OpcWriteNode("ns=2;s=Machine/Job/Speed", OpcAttribute.DisplayName, "Rotations per Second")
};
 
OpcStatusCollection results = client.WriteNodes(commands);
vbnet
Dim commands As OpcWriteNode() = New OpcWriteNode() { _
    New OpcWriteNode("ns=2;s=Machine/Job/Number", OpcAttribute.DisplayName, "Serial"), _
    New OpcWriteNode("ns=2;s=Machine/Job/Name", OpcAttribute.DisplayName, "Description"), _
    New OpcWriteNode("ns=2;s=Machine/Job/Speed", OpcAttribute.DisplayName, "Rotations per Second") _
}

Dim results As OpcStatusCollection = client.WriteNodes(commands)

Zeitstempel beim Schreiben ​

Beteiligte TypenOpcClientOpcTimestampSource

Manche Server lehnen das Schreiben eines Werts mit dem Status BadWriteNotSupported ab, wenn der mitgesendete Zeitstempel nicht ihren Erwartungen entspricht. In diesem Fall versucht der Client das Schreiben automatisch nacheinander mit den übrigen Werten der Enumeration OpcTimestampSource (MinValue, UtcNow, Now und MaxValue). Den ersten Wert, den der Server akzeptiert, verwendet er für alle weiteren Schreibvorgänge der Sitzung. Wenn Sie den Zeitstempel stattdessen fest vorgeben möchten, legen Sie die gewünschte Quelle so fest:

csharp
// Always send the current time as the source timestamp of the values to write.
client.Services.WriteNodes.TimestampSource = OpcTimestampSource.UtcNow;
vbnet
'Always send the current time as the source timestamp of the values to write.
client.Services.WriteNodes.TimestampSource = OpcTimestampSource.UtcNow

Teilbereiche von Arrays lesen und schreiben ​

Beteiligte TypenOpcClientOpcNodeIdOpcRangeOpcValueOpcStatus

Wenn ein Node ein Array als Wert bereitstellt, muss der Client nicht immer das gesamte Array lesen oder schreiben. Eine Instanz der Klasse OpcRange legt fest, welche Elemente des Arrays der Client liest oder schreibt. In OPC UA heißt dieser Bereich IndexRange. Der erste Wert gibt den Index des ersten Elements an, der zweite Wert den Index des letzten Elements.

Einen Teilbereich eines Arrays lesen:

csharp
// Read the elements with the index 2 to 4 of the array.
OpcValue speeds = client.ReadNode(
        "ns=2;s=Machine/Job/Speeds",
        new OpcRange(start: 2, end: 4));
vbnet
'Read the elements with the index 2 to 4 of the array.
Dim speeds As OpcValue = client.ReadNode( _
        "ns=2;s=Machine/Job/Speeds", _
        New OpcRange(start:=2, [end]:=4))

Einen Teilbereich eines Arrays schreiben:

csharp
// Write the elements with the index 2 to 4 of the array.
OpcStatus result = client.WriteNode(
        "ns=2;s=Machine/Job/Speeds",
        new OpcRange(start: 2, end: 4),
        new int[] { 1200, 1300, 1400 });
vbnet
'Write the elements with the index 2 to 4 of the array.
Dim result As OpcStatus = client.WriteNode( _
        "ns=2;s=Machine/Job/Speeds", _
        New OpcRange(start:=2, [end]:=4), _
        New Integer() {1200, 1300, 1400})

Für mehrdimensionale Arrays geben Sie je Dimension eine weitere Instanz von OpcRange an (OpcRange(start, end, next)). Ob ein Server das Lesen und Schreiben von Teilbereichen unterstützt, hängt vom jeweiligen Server ab.

Gelesene Werte auswerten ​

Beteiligte TypenOpcClientOpcNodeIdOpcValueOpcStatusOpcStatusCollection

Die Methoden ReadNode liefern immer einen OpcValue. Die Methoden ReadNodes liefern eine Auflistung mit einem OpcValue je gelesenem Node. Der gelesene Wert steht in der Eigenschaft Value. Das Ergebnis der Leseanforderung prüfen Sie über die Eigenschaft Status. Die Eigenschaft SourceTimestamp liefert den Zeitstempel, zu dem die Quelle den Wert festgestellt hat. Die Eigenschaft ServerTimestamp liefert den Zeitstempel, zu dem der Server den Wert erfasst hat.

Den Wert eines einzelnen Nodes lesen:

csharp
OpcValue value = client.ReadNode("ns=2;s=Machine/Job/Speed");
vbnet
Dim value As OpcValue = client.ReadNode("ns=2;s=Machine/Job/Speed")

Das Ergebnis der Leseanforderung prüfen:

csharp
if (value.Status.IsGood) {
    // Your code to operate on the value.
}
vbnet
If value.Status.IsGood Then
    'Your code to operate on the value.
End If

Den skalaren Wert des OpcValue abrufen:

csharp
int intValue = (int)value.Value;
vbnet
Dim intValue As Integer = CInt(value.Value)

Den Arraywert des OpcValue abrufen:

csharp
int[] intValues = (int[])value.Value;
vbnet
Dim intValues As Integer() = CType(value.Value, Integer())

Die Methoden WriteNode liefern immer einen OpcStatus. Die Methoden WriteNodes liefern eine OpcStatusCollection, die für jeden geschriebenen Node einen OpcStatus enthält. Das Ergebnis der Schreibanforderung prüfen Sie über die Eigenschaften der einzelnen OpcStatus.

Den skalaren Wert eines einzelnen Nodes schreiben:

csharp
OpcStatus status = client.WriteNode("ns=2;s=Machine/Job/Speed", 1200);
vbnet
Dim status As OpcStatus = client.WriteNode("ns=2;s=Machine/Job/Speed", 1200)

Den Arraywert eines einzelnen Nodes schreiben:

csharp
int[] values = new int[3] { 1200, 1350, 1780 };
OpcStatus status = client.WriteNode("ns=2;s=Machine/Job/Speeds", values);
vbnet
Dim values As Integer() = New Integer(2) {1200, 1350, 1780}
Dim status As OpcStatus = client.WriteNode("ns=2;s=Machine/Job/Speeds", values)

Das Ergebnis der Schreibanforderung prüfen:

csharp
if (!status.IsGood) {
    // Your code to handle a failed write operation.
}
vbnet
If Not status.IsGood Then
    'Your code to handle a failed write operation.
End If

Wenn Sie nur einzelne Elemente ändern, ist das Schreiben eines Teilbereichs meist einfacher (Abschnitt Teilbereiche von Arrays lesen und schreiben). Mit den gezeigten Schritten für skalare Werte und Arraywerte ändern Sie den Arraywert eines Variablen-Nodes so:

csharp
using (var client = new OpcClient("opc.tcp://localhost:4840")) {
    client.Connect();
    OpcValue arrayValue = client.ReadNode("ns=2;s=Machine/Job/Speeds");
 
    if (arrayValue.Status.IsGood) {
        int[] intArrayValue = (int[])arrayValue.Value;
 
        intArrayValue[2] = 100;
        intArrayValue[4] = 200;
        intArrayValue[9] = 300;
 
        OpcStatus status = client.WriteNode("ns=2;s=Machine/Job/Speeds", intArrayValue);
 
        if (!status.IsGood)
            Console.WriteLine("Failed to write array value!");
    }
}
vbnet
Using client As New OpcClient("opc.tcp://localhost:4840")
    client.Connect()
    Dim arrayValue As OpcValue = client.ReadNode("ns=2;s=Machine/Job/Speeds")

    If arrayValue.Status.IsGood Then
        Dim intArrayValue As Integer() = CType(arrayValue.Value, Integer())

        intArrayValue(2) = 100
        intArrayValue(4) = 200
        intArrayValue(9) = 300

        Dim status As OpcStatus = client.WriteNode("ns=2;s=Machine/Job/Speeds", intArrayValue)

        If Not status.IsGood Then _
            Console.WriteLine("Failed to write array value!")
    End If
End Using

Werte typisiert lesen und schreiben ​

Beteiligte TypenOpcClientOpcNodeValueOpcStatus

Die Klasse OpcNodeValue<T> verbindet den Identifier eines Nodes mit dem .NET-Typ seines Werts. Read liefert den Wert direkt als T, ohne Umwandlung über OpcValue.Value. Write schreibt einen Wert dieses Typs. Wenn der gelesene Wert einen schlechten Status hat, liefert Read den Standardwert von T. Den Status hält das Objekt in seiner Eigenschaft Status. Prüfen Sie ihn deshalb, bevor Sie den Wert verwenden:

csharp
var speed = new OpcNodeValue<double>("ns=2;s=Machine/Speed");
 
double current = speed.Read(client);
 
if (speed.Status.IsGood) {
    OpcStatus result = speed.Write(client, current + 10);
}
vbnet
Dim speed = New OpcNodeValue(Of Double)("ns=2;s=Machine/Speed")

Dim current As Double = speed.Read(client)

If speed.Status.IsGood Then
    Dim result As OpcStatus = speed.Write(client, current + 10)
End If

Mehrere typisierte Werte liest der Client mit einem einzigen Aufruf von ReadNodes:

csharp
var temperatures = new OpcNodeValue<double>[] {
    new OpcNodeValue<double>("ns=2;s=Machine/Temperature1"),
    new OpcNodeValue<double>("ns=2;s=Machine/Temperature2"),
    new OpcNodeValue<double>("ns=2;s=Machine/Temperature3")
};
 
double[] values = temperatures.Read(client);
vbnet
Dim temperatures = New OpcNodeValue(Of Double)() { _
    New OpcNodeValue(Of Double)("ns=2;s=Machine/Temperature1"), _
    New OpcNodeValue(Of Double)("ns=2;s=Machine/Temperature2"), _
    New OpcNodeValue(Of Double)("ns=2;s=Machine/Temperature3") _
}

Dim values As Double() = temperatures.Read(client)

Mehrdimensionale Arrays ​

Beteiligte TypenOpcClientOpcValue

Werte mit mehr als einer Dimension (in OPC UA eine Matrix) liefert der Client als mehrdimensionales .NET-Array, zum Beispiel double[,]. Ebenso schreibt er ein mehrdimensionales Array als Matrix. Sie müssen die Dimensionen nicht getrennt verwalten:

csharp
var grid = new double[2, 3] { { 1, 2, 3 }, { 4, 5, 6 } };
client.WriteNode("ns=2;s=Machine/Grid", grid);
 
double[,] values = (double[,])client.ReadNode("ns=2;s=Machine/Grid").Value;
double value = values[1, 2];
vbnet
Dim grid = New Double(1, 2) {{1, 2, 3}, {4, 5, 6}}
client.WriteNode("ns=2;s=Machine/Grid", grid)

Dim values As Double(,) = CType(client.ReadNode("ns=2;s=Machine/Grid").Value, Double(,))
Dim value As Double = values(1, 2)

Nodes über die Namespace-URI adressieren ​

Beteiligte TypenOpcClientOpcNodeIdOpcNamespace

Der Namespace-Index in ns=2;s=... ist nur ein Verweis in die Namespace-Tabelle des Servers. Er kann sich je Server und nach einem Neustart des Servers ändern. Stabil ist dagegen die URI des Namespaces. Ein Identifier mit nsu= statt ns= nennt die URI. Der Client löst sie erst beim Senden der Anfrage gegen die aktuelle Namespace-Tabelle der Sitzung auf, auch nach einem Wiederverbinden:

csharp
OpcValue speed = client.ReadNode("nsu=http://example.com/machine/;s=Machine/Speed");
vbnet
Dim speed As OpcValue = client.ReadNode("nsu=http://example.com/machine/;s=Machine/Speed")

Alternativ liefert client.Namespaces.ResolveIndex den aktuellen Index einer Namespace-URI oder -1, wenn der Server den Namespace nicht kennt:

csharp
int index = client.Namespaces.ResolveIndex("http://example.com/machine/");
 
if (index >= 0) {
    var temperatureId = new OpcNodeId("Machine/Temperature", namespaceIndex: index);
    OpcValue temperature = client.ReadNode(temperatureId);
}
vbnet
Dim index As Integer = client.Namespaces.ResolveIndex("http://example.com/machine/")

If index >= 0 Then
    Dim temperatureId = New OpcNodeId("Machine/Temperature", namespaceIndex:=index)
    Dim temperature As OpcValue = client.ReadNode(temperatureId)
End If

Häufig gelesene Nodes registrieren ​

Beteiligte TypenOpcClientOpcNodeIdOpcNodeIdCollectionOpcReadNode

Wenn ein Client dieselben Nodes immer wieder liest oder schreibt, kann er sie beim Server registrieren. RegisterNodes liefert für jeden Node einen Identifier, den der Server für wiederholte Zugriffe optimieren kann. Ob und wie stark er das tut, hängt vom Server ab. Die registrierten Identifier gelten nur in der Sitzung, in der der Client sie registriert hat. Nach einer neuen Sitzung registrieren Sie sie neu (Abschnitt Was nach einer neuen Sitzung zu tun bleibt). Wenn Sie die Identifier nicht mehr brauchen, gibt UnregisterNodes sie frei:

csharp
OpcNodeIdCollection registeredNodeIds = client.RegisterNodes(
        "ns=2;s=Machine/Speed",
        "ns=2;s=Machine/Temperature");
 
var commands = new OpcReadNode[registeredNodeIds.Count];
 
for (int index = 0; index < commands.Length; index++)
    commands[index] = new OpcReadNode(registeredNodeIds[index]);
 
for (int cycle = 0; cycle < 10; cycle++)
    client.ReadNodes(commands);
 
client.UnregisterNodes(registeredNodeIds);
vbnet
Dim registeredNodeIds As OpcNodeIdCollection = client.RegisterNodes( _
        "ns=2;s=Machine/Speed", _
        "ns=2;s=Machine/Temperature")

Dim commands = New OpcReadNode(registeredNodeIds.Count - 1) {}

For index As Integer = 0 To commands.Length - 1
    commands(index) = New OpcReadNode(registeredNodeIds(index))
Next

For cycle As Integer = 0 To 9
    client.ReadNodes(commands)
Next

client.UnregisterNodes(registeredNodeIds)