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:
OpcValue isRunning = client.ReadNode("ns=2;s=Machine/IsRunning");Dim isRunning As OpcValue = client.ReadNode("ns=2;s=Machine/IsRunning")Die Werte des Value-Attributs mehrerer Nodes lesen:
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);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:
OpcValue isRunningDisplayName = client.ReadNode("ns=2;s=Machine/IsRunning", OpcAttribute.DisplayName);Dim isRunningDisplayName As OpcValue = client.ReadNode("ns=2;s=Machine/IsRunning", OpcAttribute.DisplayName)Die Werte des DisplayName-Attributs mehrerer Nodes lesen:
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);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:
OpcStatus result = client.WriteNode("ns=2;s=Machine/Job/Cancel", true);Dim result As OpcStatus = client.WriteNode("ns=2;s=Machine/Job/Cancel", True)Die Werte mehrerer Nodes schreiben:
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);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:
client.WriteNode("ns=2;s=Machine/IsRunning", OpcAttribute.DisplayName, "IsActive");client.WriteNode("ns=2;s=Machine/IsRunning", OpcAttribute.DisplayName, "IsActive")Die Werte des DisplayName-Attributs mehrerer Nodes schreiben:
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);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:
// Always send the current time as the source timestamp of the values to write.
client.Services.WriteNodes.TimestampSource = OpcTimestampSource.UtcNow;'Always send the current time as the source timestamp of the values to write.
client.Services.WriteNodes.TimestampSource = OpcTimestampSource.UtcNowTeilbereiche 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:
// 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));'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:
// 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 });'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:
OpcValue value = client.ReadNode("ns=2;s=Machine/Job/Speed");Dim value As OpcValue = client.ReadNode("ns=2;s=Machine/Job/Speed")Das Ergebnis der Leseanforderung prüfen:
if (value.Status.IsGood) {
// Your code to operate on the value.
}If value.Status.IsGood Then
'Your code to operate on the value.
End IfDen skalaren Wert des OpcValue abrufen:
int intValue = (int)value.Value;Dim intValue As Integer = CInt(value.Value)Den Arraywert des OpcValue abrufen:
int[] intValues = (int[])value.Value;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:
OpcStatus status = client.WriteNode("ns=2;s=Machine/Job/Speed", 1200);Dim status As OpcStatus = client.WriteNode("ns=2;s=Machine/Job/Speed", 1200)Den Arraywert eines einzelnen Nodes schreiben:
int[] values = new int[3] { 1200, 1350, 1780 };
OpcStatus status = client.WriteNode("ns=2;s=Machine/Job/Speeds", values);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:
if (!status.IsGood) {
// Your code to handle a failed write operation.
}If Not status.IsGood Then
'Your code to handle a failed write operation.
End IfWenn 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:
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!");
}
}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 UsingWerte 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:
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);
}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 IfMehrere typisierte Werte liest der Client mit einem einzigen Aufruf von ReadNodes:
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);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:
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];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:
OpcValue speed = client.ReadNode("nsu=http://example.com/machine/;s=Machine/Speed");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:
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);
}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 IfHä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:
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);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)
