Zum Inhalt springen

Anleitung

Werte gebündelt verarbeiten

Tausende Werte mit einem Aufruf lesen, schreiben und abonnieren: wie das SDK große Anfragen an die Grenzen des Servers anpasst und was sich wann lohnt.

Anleitung

Werte gebündelt verarbeiten ​

Jeder Aufruf von ReadNode oder WriteNode ist eine eigene Anfrage an den Server mit eigener Netzwerklaufzeit. Wer viele Werte in einer Schleife einzeln liest, verliert dadurch schnell Sekunden. Die Methoden ReadNodes, WriteNodes und SubscribeNodes nehmen stattdessen beliebig viele Befehle in einem Aufruf an. Das SDK teilt sie selbst so auf, dass der Server sie annimmt, und fügt die Antworten in der Reihenfolge der Befehle wieder zusammen.

Viele Werte mit einem Aufruf lesen ​

Beteiligte TypenOpcClientOpcReadNodeOpcValue

Die Ergebnisse stehen in derselben Reihenfolge wie die Befehle. Werten Sie den Status jedes Werts einzeln aus. Ein ungültiger Node bricht den Aufruf nicht ab:

csharp
var commands = new OpcReadNode[5000];
 
for (int index = 0; index < commands.Length; index++)
    commands[index] = new OpcReadNode("ns=2;s=Sensors/Sensor" + (index + 1));
 
IEnumerable<OpcValue> values = client.ReadNodes(commands);
vbnet
Dim commands = New OpcReadNode(4999) {}

For index As Integer = 0 To commands.Length - 1
    commands(index) = New OpcReadNode("ns=2;s=Sensors/Sensor" & (index + 1))
Next

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

Viele Werte mit einem Aufruf schreiben ​

Beteiligte TypenOpcClientOpcWriteNodeOpcStatusOpcStatusCollection

Auch beim Schreiben gibt es je Befehl ein Ergebnis. Über den Index ordnen Sie jedem Ergebnis den zugehörigen Befehl zu:

csharp
var commands = new OpcWriteNode[5000];
 
for (int index = 0; index < commands.Length; index++)
    commands[index] = new OpcWriteNode("ns=2;s=Setpoints/Setpoint" + (index + 1), value: 0.0);
 
OpcStatusCollection results = client.WriteNodes(commands);
 
for (int index = 0; index < results.Count; index++) {
    if (results[index].IsBad)
        Console.WriteLine("{0}: {1}", commands[index].NodeId, results[index].Description);
}
vbnet
Dim commands = New OpcWriteNode(4999) {}

For index As Integer = 0 To commands.Length - 1
    commands(index) = New OpcWriteNode("ns=2;s=Setpoints/Setpoint" & (index + 1), value:=0.0)
Next

Dim results As OpcStatusCollection = client.WriteNodes(commands)

For index As Integer = 0 To results.Count - 1
    If results(index).IsBad Then
        Console.WriteLine("{0}: {1}", commands(index).NodeId, results(index).Description)
    End If
Next

Wie das SDK große Anfragen aufteilt ​

Beteiligte TypenOpcClientOpcClientServices

Server begrenzen, wie viele Nodes eine einzelne Anfrage enthalten darf, und melden diese Grenzen unter Server/ServerCapabilities/OperationLimits. Wenn ein Aufruf mehr als einen Befehl enthält, geht der Client so vor:

  1. Beim ersten solchen Aufruf liest er die Grenze des Servers für den jeweiligen Dienst (MaxNodesPerRead, MaxNodesPerWrite, MaxNodesPerBrowse und MaxNodesPerTranslateBrowsePathsToNodeIds). Wenn der Server keine Grenze meldet (0), verwendet der Client 1000.
  2. Wenn für den Dienst eine eigene Grenze gesetzt ist, gilt der kleinere der beiden Werte.
  3. Der Client merkt sich den Wert und teilt alle weiteren Aufrufe danach auf mehrere Anfragen auf. Die Antworten fügt er in der Reihenfolge der Befehle zusammen.

Das gilt für ReadNodes, WriteNodes, das Browsen und TranslatePaths. Eine eigene, niedrigere Grenze ist sinnvoll, wenn einzelne Anfragen kürzer dauern sollen oder der Server trotz seiner gemeldeten Grenze an Antwortgrößen scheitert:

csharp
client.Services.ReadNodes.MaxNodesPerRead = 500;
client.Services.WriteNodes.MaxNodesPerWrite = 500;
client.Services.Browse.MaxNodesPerBrowse = 100;
vbnet
client.Services.ReadNodes.MaxNodesPerRead = 500
client.Services.WriteNodes.MaxNodesPerWrite = 500
client.Services.Browse.MaxNodesPerBrowse = 100

Welche Grenze der Client tatsächlich verwendet, zeigt die zugehörige Eigenschaft mit dem Präfix Used. Sie ist null, solange noch kein Aufruf mit mehreren Befehlen stattgefunden hat:

csharp
uint? nodesPerRead = client.Services.ReadNodes.UsedMaxNodesPerRead;
vbnet
Dim nodesPerRead As UInteger? = client.Services.ReadNodes.UsedMaxNodesPerRead

Unabhängig von der Anzahl der Nodes begrenzt der Client die Größe der übertragenen Daten. Wie sich diese Grenzen erhöhen lassen, beschreibt der Abschnitt Grenzen der Datenübertragung.

Viele Nodes abonnieren ​

Beteiligte TypenOpcClientOpcSubscribeDataChangeOpcSubscriptionOpcMonitoredItem

Wenn sich die Werte im Verhältnis zum Leseintervall selten ändern, ist eine Subscription günstiger als zyklisches Lesen, denn der Server meldet nur Änderungen. SubscribeNodes legt alle MonitoredItems in einer Subscription an. Im Handler ist der sender das MonitoredItem. Über dessen NodeId ordnen Sie die Benachrichtigung zu:

csharp
var commands = new OpcSubscribeDataChange[1000];
 
for (int index = 0; index < commands.Length; index++) {
    commands[index] = new OpcSubscribeDataChange(
            "ns=2;s=Sensors/Sensor" + (index + 1),
            HandleDataChanged);
}
 
OpcSubscription subscription = client.SubscribeNodes(commands);
...
private static void HandleDataChanged(
        object sender,
        OpcDataChangeReceivedEventArgs e)
{
    OpcMonitoredItem item = (OpcMonitoredItem)sender;
    Console.WriteLine("{0}: {1}", item.NodeId, e.Item.Value);
}
vbnet
Dim commands = New OpcSubscribeDataChange(999) {}

For index As Integer = 0 To commands.Length - 1
    commands(index) = New OpcSubscribeDataChange( _
            "ns=2;s=Sensors/Sensor" & (index + 1), _
            AddressOf HandleDataChanged)
Next

Dim subscription As OpcSubscription = client.SubscribeNodes(commands)
...
Private Shared Sub HandleDataChanged( _
        ByVal sender As Object, _
        ByVal e As OpcDataChangeReceivedEventArgs)
    Dim item As OpcMonitoredItem = CType(sender, OpcMonitoredItem)
    Console.WriteLine("{0}: {1}", item.NodeId, e.Item.Value)
End Sub

Die passende Zugriffsart wählen ​

SituationEmpfehlung
Werte werden einmalig oder selten benötigtReadNodes mit allen Nodes in einem Aufruf
dieselben Nodes werden zyklisch gelesen oder geschriebenNodes registrieren und mit den registrierten Identifiern ReadNodes oder WriteNodes aufrufen, siehe Häufig gelesene Nodes registrieren
Werte ändern sich selten, die Anwendung reagiert auf ÄnderungenSubscription mit allen Nodes über SubscribeNodes, siehe Subscriptions
sehr große Einzelwerte (Binärdaten)Werte als Stream lesen, siehe Große Binärwerte als Stream
Nodes sind nur über ihren Pfad bekannteinmal mit TranslatePaths auflösen, siehe Nodes über Pfade finden