Zum Inhalt springen

Anleitung

Node-Typen

Methoden-, Datei-, Datentyp-, Variablen- und Datenpunkt-Nodes im Server anlegen und implementieren, auch für analoge Werte.

Anleitung

Node-Typen ​

Methoden bereitstellen ​

Beteiligte TypenOpcNodeManagerOpcMethodNodeOpcMethodContextOpcArgumentAttribute

Codeabschnitte, die eine für sich abgeschlossene Aufgabe erfüllen, heißen in der Programmierung Unterprogramme. Häufig heißen sie auch einfach Funktionen oder Methoden. In OPC UA lassen sich solche Methoden über Methoden-Nodes aufrufen. Einen Methoden-Node definieren Sie mit der Klasse OpcMethodNode. Ein OPC UA Client ruft ihn über den serverseitigen Call-Service auf.

Das OPC UA .NET SDK setzt einen Funktionszeiger (in C# einen Delegaten) 1:1 in einen Node der Kategorie OpcNodeCategory.Method um. Dazu untersucht das SDK per .NET Reflection die Struktur des Delegaten. Daraus definiert es den Methoden-Node mit seinen IN- und OUT-Argumenten.

So definieren Sie einen Methoden-Node im Node-Manager:

1. durch eine Methode ohne Parameter:

csharp
var startMethodNode = new OpcMethodNode(
        machineNode,
        "StartMachine",
        new Action(this.StartMachine));
...
private void StartMachine()
{
    // Your code to execute.
}
vbnet
Dim startMethodNode = New OpcMethodNode( _
        machineNode, _
        "StartMachine", _
        New Action(AddressOf Me.StartMachine))
...
Private Sub StartMachine()
    'Your code to execute.
End Sub

2. durch eine Methode mit Parameter:

csharp
var startMethodNode = new OpcMethodNode(
        machineNode,
        "StartMachine",
        new Action<int>(this.StartMachine));
...
private void StartMachine(int reasonNumber)
{
    // Your code to execute.
}
vbnet
Dim startMethodNode = New OpcMethodNode( _
        machineNode, _
        "StartMachine", _
        New Action(Of Integer)(AddressOf Me.StartMachine))
...
Private Sub StartMachine(ByVal reasonNumber As Integer)
    'Your code to execute.
End Sub

3. durch eine Methode mit Rückgabewert:

csharp
var startMethodNode = new OpcMethodNode(
        machineNode,
        "StartMachine",
        new Func<int>(this.StartMachine));
...
private int StartMachine()
{
    // Your code to execute.
    return statusCode;
}
vbnet
Dim startMethodNode = New OpcMethodNode( _
        machineNode, _
        "StartMachine", _
        New Func(Of Integer)(AddressOf Me.StartMachine))
...
Private Function StartMachine() As Integer
    'Your code to execute.
    Return statusCode
End Function

4. durch eine Methode mit Parameter und Rückgabewert:

csharp
var startMethodNode = new OpcMethodNode(
        machineNode,
        "StartMachine",
        new Func<int, string, int>(this.StartMachine));
...
private int StartMachine(int reasonNumber, string operatorName)
{
    // Your code to execute.
    return statusCode;
}
vbnet
Dim startMethodNode = New OpcMethodNode( _
        machineNode, _
        "StartMachine", _
        New Func(Of Integer, String, Integer)(AddressOf Me.StartMachine))
...
Private Function StartMachine( _
        ByVal reasonNumber As Integer, _
        ByVal operatorName As String) As Integer
    'Your code to execute.
    Return statusCode
End Function

5. durch eine Methode, die Zugriff auf kontextbezogene Informationen des aktuellen Call-Aufrufs benötigt. Der erste Parameter muss dann vom Typ OpcMethodContext sein:

csharp
var startMethodNode = new OpcMethodNode(
        machineNode,
        "StartMachine",
        new Func<OpcMethodContext, int, int>(this.StartMachine));
...
private int StartMachine(OpcMethodContext context, int reasonNumber)
{
    // Your code to execute.
 
    this.machineStateVariable.Value = "Started";
    this.machineStateVariable.ApplyChanges(context);
 
    return statusCode;
}
vbnet
Dim startMethodNode = New OpcMethodNode( _
        machineNode, _
        "StartMachine", _
        New Func(Of OpcMethodContext, Integer, Integer)(AddressOf Me.StartMachine))
...
Private Function StartMachine( _
        ByVal context As OpcMethodContext, _
        ByVal reasonNumber As Integer) As Integer
    'Your code to execute.

    Me.machineStateVariable.Value = "Started"
    Me.machineStateVariable.ApplyChanges(context)

    Return statusCode
End Function

Über das Attribut OpcArgument können Sie dem SDK zusätzliche Informationen über die Argumente einer Methode bereitstellen, also über Rückgabewerte und Parameter. Das SDK übernimmt diese Informationen in die Argumente des Methoden-Nodes. Jeder Client erhält sie beim Browsen des Nodes. So sehen solche zusätzlichen Informationen aus:

csharp
[return: OpcArgument("Result", Description = "The result code of the machine driver.")]
private int StartMachine(
        [OpcArgument("ReasonNumber", Description = "0: Maintenance, 1: Manufacturing, 2: Service")]
        int reasonNumber,
        [OpcArgument("OperatorName", Description = "Optional. Name of the operator of the current shift.")]
        string operatorName)
{
    // Your code to execute.
    return 10;
}
vbnet
Private Function StartMachine( _
        <OpcArgument("ReasonNumber", Description:="0: Maintenance, 1: Manufacturing, 2: Service")> _
        ByVal reasonNumber As Integer, _
        <OpcArgument("OperatorName", Description:="Optional. Name of the operator of the current shift.")> _
        ByVal operatorName As String) _
        As <OpcArgument("Result", Description:="The result code of the machine driver.")> Integer
    'Your code to execute.
    Return 10
End Function

Methoden-Nodes über einen Befehl definieren: Statt über einen Delegaten können Sie einen Methoden-Node auch über einen Befehl (IOpcMethodCommand) definieren. Die Argumente geben Sie dann ausdrücklich als Instanzen von OpcArgument an. Die Methode erhält die Werte der Eingangsargumente als Liste. Die Liste der Ausgangsargumente ist bereits mit der Anzahl der definierten Ausgangsargumente angelegt. Einen Befehl erzeugt die Methode OpcMethodCommands.Execute. Eine eigene Implementierung der Schnittstelle IOpcMethodCommand legt zudem über CanExecute und CanUserExecute fest, ob die Methode ausführbar ist, auch für den aktuellen Benutzer:

csharp
var startMethodNode = new OpcMethodNode(
        machineNode,
        "StartMachine",
        OpcMethodCommands.Execute(this.StartMachine),
        new OpcArgument[] {
            new OpcArgument("ReasonNumber", typeof(int), description: "0: Maintenance, 1: Manufacturing")
        },
        new OpcArgument[] {
            new OpcArgument("Result", typeof(int), description: "The result code of the machine driver.")
        });
...
private OpcResult StartMachine(
        OpcMethodContext context,
        IList<object> inputArguments,
        IList<object> outputArguments)
{
    var reasonNumber = (int)inputArguments[0];
 
    // Your code to execute.
    outputArguments[0] = statusCode;
    return new OpcResult(OpcStatusCode.Good);
}
vbnet
Dim startMethodNode = New OpcMethodNode( _
        machineNode, _
        "StartMachine", _
        OpcMethodCommands.Execute(AddressOf Me.StartMachine), _
        New OpcArgument() { _
            New OpcArgument("ReasonNumber", GetType(Integer), description:="0: Maintenance, 1: Manufacturing") _
        }, _
        New OpcArgument() { _
            New OpcArgument("Result", GetType(Integer), description:="The result code of the machine driver.") _
        })
...
Private Function StartMachine( _
        ByVal context As OpcMethodContext, _
        ByVal inputArguments As IList(Of Object), _
        ByVal outputArguments As IList(Of Object)) As OpcResult
    Dim reasonNumber = CInt(inputArguments(0))

    'Your code to execute.
    outputArguments(0) = statusCode
    Return New OpcResult(OpcStatusCode.Good)
End Function

Asynchrone Methoden ​

Eine Anfrage eines Clients kann mehrere Methodenaufrufe enthalten. Synchrone Methoden darin führt der Server nacheinander aus. Eine Methode, die lange läuft, zum Beispiel weil sie auf die Maschine wartet, hält damit die weiteren Aufrufe derselben Anfrage auf.

Mehrere Anfragen verarbeitet der Server dagegen parallel, jede in einem eigenen Task. Die Sperre des Node-Managers umfasst nur das Auflösen der Methode, nicht ihren Aufruf. Dieselbe Methode kann deshalb gleichzeitig für mehrere Anfragen laufen. Schreiben Sie die Callbacks von Methoden threadsicher (siehe Gleichzeitige Anfragen behandeln).

Wenn der Delegat eines Methoden-Nodes einen Task beziehungsweise Task<T> liefert, führt der Server die Methode auch innerhalb einer Anfrage parallel zu anderen Aufrufen aus. Der Rückgabewert des Task<T> wird wie bei synchronen Methoden zum Ausgangsargument:

csharp
var startJobNode = new OpcMethodNode(
        machine,
        "StartJob",
        new Func<string, Task<int>>(StartJobAsync));
vbnet
Dim startJobNode = New OpcMethodNode( _
        machine, _
        "StartJob", _
        New Func(Of String, Task(Of Integer))(AddressOf StartJobAsync))
csharp
private static async Task<int> StartJobAsync(string jobName)
{
    // Long running work, e.g. waiting for the machine.
    await Task.Delay(TimeSpan.FromSeconds(5));
    return 42;
}
vbnet
Private Shared Async Function StartJobAsync(ByVal jobName As String) As Task(Of Integer)
    'Long running work, e.g. waiting for the machine.
    Await Task.Delay(TimeSpan.FromSeconds(5))
    Return 42
End Function

Wenn der Server auch synchrone Methoden innerhalb einer Anfrage parallel ausführen soll, überschreiben Sie im Node-Manager die Eigenschaft UseAsyncMethodCalls (Standardwert false). Für alle Node-Manager des Servers gleichzeitig steuert das die statische Eigenschaft OpcAutomatism.UseAsyncMethodCalls:

csharp
public class JobNodeManager : OpcNodeManager
{
    public JobNodeManager()
        : base("http://example.com/jobs")
    {
    }
 
    protected override bool UseAsyncMethodCalls
    {
        get { return true; }
    }
}
vbnet
Public Class JobNodeManager
    Inherits OpcNodeManager

    Public Sub New()
        MyBase.New("http://example.com/jobs")
    End Sub

    Protected Overrides ReadOnly Property UseAsyncMethodCalls As Boolean
        Get
            Return True
        End Get
    End Property
End Class

Gemeinsam genutzte Daten muss die Implementierung in jedem Fall selbst vor gleichzeitigen Änderungen schützen, auch ohne UseAsyncMethodCalls.

Datei-Nodes ​

Beteiligte TypenOpcNodeManagerOpcFileNode

Nodes vom Typ FileType definieren laut OPC-UA-Spezifikation bestimmte Eigenschaften (Property-Nodes) und Methoden (Methoden-Nodes). Über sie greift ein Client auf einen Datenstrom (engl. data stream) so zu wie auf eine Datei im Dateisystem. Der Node stellt ausschließlich Informationen über den Inhalt der logischen oder physikalischen Datei bereit. Einen eventuell vorhandenen Pfad zur Datei gibt er gemäß der Spezifikation nicht heraus. Auf die Datei selbst greift der Client mit Open, Close, Read, Write, GetPosition und SetPosition zu. Die Daten sind dabei stets binär. Wie auf jeder anderen Plattform kann der Client auch in OPC UA beim Aufruf von Open einen Modus angeben, der die Art des geplanten Dateizugriffs vorgibt. Auch in OPC UA kann er den exklusiven Zugriff auf eine Datei anfordern. Nach dem Aufruf von Open erhält der Client einen numerischen Schlüssel für den weiteren Dateizugriff (engl. file handle). Diesen Schlüssel muss er bei Read, Write, GetPosition und SetPosition stets mit übergeben. Eine geöffnete Datei muss der Client wieder schließen, sobald er sie nicht mehr benötigt.

Statt einer Instanz von FileInfo können Sie auch den Pfad zur Datei als Zeichenkette übergeben. Wenn der Inhalt nicht aus einer Datei, sondern aus einer anderen Quelle stammen soll (zum Beispiel aus dem Speicher), übergeben Sie eine eigene Implementierung der Schnittstelle IOpcFileInfo. So definieren Sie einen Datei-Node im Node-Manager:

csharp
var protocolFileNode = new OpcFileNode(
        machineNode,
        "Protocol.txt",
        new FileInfo(@"..\Protocol.log"));
vbnet
Dim protocolFileNode = New OpcFileNode( _
        machineNode, _
        "Protocol.txt", _
        New FileInfo("..\Protocol.log"))

Alle weiteren Operationen, um mit der repräsentierten Datei zu arbeiten, stellt bereits die Klasse OpcFileNode bereit.

Datentypen bereitstellen ​

Beteiligte TypenOpcNodeManagerOpcNodeIdOpcDataTypeAttributeOpcDataTypeNodeOpcEnumAttributeOpcEnumMemberAttribute

Manchmal muss der Server seine Daten mit einem benutzerdefinierten Datentyp beschreiben. Ein solcher Datentyp kann zum Beispiel eine Enumeration sein. Jeder Eintrag ist über seinen Namen von allen anderen unterscheidbar. Er steht für einen eigenen Wert oder für eine Kombination von Werten, die wiederum andere Einträge repräsentieren können. Im letzten Fall heißt die Enumeration Flag-Enumeration. Wenn die Bits eines Enum-Eintrags in einem Flag-Enumerationswert gesetzt sind, gilt der Eintrag. Das gilt auch, wenn der gesamte Wert nicht genau dem Wert des Eintrags entspricht, weil gleichzeitig andere Enum-Einträge gelten sollen. Der Server muss die gültigen Werte und Kombinationen deshalb als Name-Wert-Paare unter einer bestimmten ID bereitstellen. Damit übermitteln Lese- und Schreibzugriffe auf Nodes, die den Typ der Enumeration verwenden, gültige Werte an den Server. Damit der Server eine benutzerdefinierte Enumeration auch als Enumeration in seinem Adressraum veröffentlicht, braucht die Enumeration das OpcDataTypeAttribute. Über dieses Attribut legen Sie die Angaben der OpcNodeId fest, die für den Datentyp gilt. Abschließend veröffentlichen Sie den benutzerdefinierten Datentyp über einen der Node-Manager des Servers.

Das folgende Codebeispiel zeigt die Umsetzung im Detail:

csharp
// Define the node identifier associated with the custom data type.
[OpcDataType(id: "MachineStatus", namespaceIndex: 2)]
internal enum MachineStatus : int
{
    Unknown = 0,
    Stopped = 1,
    Started = 2,
    Waiting = 3,
    Suspended = 4
}
 
...
 
// MyNodeManager.cs
protected override IEnumerable<IOpcNode> CreateNodes(OpcNodeReferenceCollection references)
{
    ...
 
    // Publish a new data type node using the custom type.
    return new IOpcNode[] { ..., new OpcDataTypeNode<MachineStatus>() };
}
vbnet
'Define the node identifier associated with the custom data type.
<OpcDataType("MachineStatus", 2)>
Friend Enum MachineStatus As Integer
    Unknown = 0
    Stopped = 1
    Started = 2
    Waiting = 3
    Suspended = 4
End Enum

...

'MyNodeManager.vb
Protected Overrides Function CreateNodes( _
        ByVal references As OpcNodeReferenceCollection) As IEnumerable(Of IOpcNode)
    ...

    'Publish a new data type node using the custom type.
    Return New IOpcNode() { ..., New OpcDataTypeNode(Of MachineStatus)() }
End Function

Weitere Informationen über die einzelnen Enum-Einträge legen Sie über das OpcEnumMemberAttribute fest. Sein Parameter legt den Namen des Eintrags fest. Alternativ bestimmt das EnumMemberAttribute den Namen, ansonsten der Name des Feldes. Die optionale Eigenschaft Description wirkt nur, wenn die Enumeration ihre Einträge als Name-Wert-Paare (EnumValues) bereitstellt. Das ist standardmäßig bei Flag-Enumerationen der Fall. Andere Enumerationen stellen nur ihre Namen (EnumStrings) bereit, außer Sie legen über das OpcEnumAttribute die Art OpcEnumType.Values fest. So könnte die oben dargestellte Enumeration dann aussehen:

csharp
[OpcDataType(id: "MachineStatus", namespaceIndex: 2)]
[OpcEnum(OpcEnumType.Values)]
internal enum MachineStatus : int
{
    Unknown = 0,
    Stopped = 1,
    Started = 2,
 
    [OpcEnumMember("WaitingForOrders", Description = "Paused by Job")]
    WaitingForOrders = 3,
 
    [OpcEnumMember("Suspended", Description = "Paused by Operator")]
    Suspended = 4
}
vbnet
<OpcDataType("MachineStatus", 2)>
<OpcEnum(OpcEnumType.Values)>
Friend Enum MachineStatus As Integer
    Unknown = 0
    Stopped = 1
    Started = 2

    <OpcEnumMember("WaitingForOrders", Description:="Paused by Job")>
    WaitingForOrders = 3

    <OpcEnumMember("Suspended", Description:="Paused by Operator")>
    Suspended = 4
End Enum

Wie Sie Datentypen nicht über .NET-Typen, sondern erst zur Laufzeit festlegen, beschreibt die Seite Datentypen zur Laufzeit.

Variablen ​

Beteiligte TypenOpcNodeManagerOpcDataVariableNode

Mit der Klasse OpcDataVariableNode stellen Sie sowohl einfache skalare als auch komplexe Datenstrukturen bereit. Diese selbstbeschreibenden Nodes liefern neben dem Wert auch Informationen über den Datentyp des Werts. Dazu gehört zum Beispiel die Länge eines Arrays.

So legen Sie einen Variablen-Node an:

csharp
// Node of the type Int32
var variable1Node = new OpcDataVariableNode<int>(machineNode, "Var1");

// Node of the type Int16
var variable2Node = new OpcDataVariableNode<short>(machineNode, "Var2");

// Node of the type String
var variable3Node = new OpcDataVariableNode<string>(machineNode, "Var3");

// Node of the type float-array
var variable4Node = new OpcDataVariableNode<float[]>(machineNode, "Var4", new float[] { 0.1f, 0.5f });

// Node of the type MachineStatus enum
var variable5Node = new OpcDataVariableNode<MachineStatus>(machineNode, "Var5");
vbnet
' Node of the type Int32
Dim variable1Node As New OpcDataVariableNode(Of Integer)(machineNode, "Var1")

' Node of the type Int16
Dim variable2Node As New OpcDataVariableNode(Of Short)(machineNode, "Var2")

' Node of the type String
Dim variable3Node As New OpcDataVariableNode(Of String)(machineNode, "Var3")

' Node of the type float-array
Dim variable4Node As New OpcDataVariableNode(Of Single())(machineNode, "Var4", New Single() {0.1F, 0.5F})

' Node of the type MachineStatus enum
Dim variable5Node As New OpcDataVariableNode(Of MachineStatus)(machineNode, "Var5")

Arrays und Matrizen ​

Ein Variablen-Node kann auch ein- und mehrdimensionale Arrays bereitstellen. Den Rang des Wertes (ValueRank) leitet das SDK aus dem .NET-Typ ab. Ein mehrdimensionales Array (zum Beispiel double[,]) stellt der Server als Matrix nach OPC UA bereit. Sie müssen die Werte dafür nicht in ein flaches Array umwandeln:

csharp
var profile = new OpcDataVariableNode<double[]>(
        machine,
        "Profile",
        value: new double[100]);
 
var heatMap = new OpcDataVariableNode<double[,]>(
        machine,
        "HeatMap",
        value: new double[16, 16]);
vbnet
Dim profile = New OpcDataVariableNode(Of Double())( _
        machine, _
        "Profile", _
        value:=New Double(99) {})

Dim heatMap = New OpcDataVariableNode(Of Double(,))( _
        machine, _
        "HeatMap", _
        value:=New Double(15, 15) {})

Um einzelne Elemente zu ändern, bearbeiten Sie das Array, weisen es wieder zu und übernehmen die Änderung mit ApplyChanges:

csharp
double[,] values = heatMap.Value;
values[3, 4] = 72.5;
 
heatMap.Value = values;
heatMap.ApplyChanges(server.SystemContext);
vbnet
Dim values As Double(,) = heatMap.Value
values(3, 4) = 72.5

heatMap.Value = values
heatMap.ApplyChanges(server.SystemContext)

Clients können solche Werte vollständig oder in Teilbereichen lesen und schreiben. Das beschreibt im Client-Kapitel der Abschnitt Teilbereiche von Arrays lesen und schreiben.

Datenpunkte ​

Beteiligte TypenOpcNodeManagerOpcDataItemNode

Die Daten eines OPC UA Servers kommen häufig nicht direkt 1:1 aus dem zugrunde liegenden System. Diese Datenvariablen lassen sich zwar mit Instanzen von OpcDataVariableNode bereitstellen. Für die korrekte Weiterverarbeitung und Interpretation ist aber ihr Ursprung von Interesse, also die Definition, wie ein Wert eines Datenpunkts zustande kommt. Vor allem wenn Dritte die Daten nutzen, ist diese Information nicht nur Teil der Dokumentation, sondern hilft auch bei der internen Datenverarbeitung. Hier setzt die Klasse OpcDataItemNode an: Ihre Eigenschaft Definition beschreibt, wie die Werte des Datenpunkt-Nodes zustande kommen. Zusätzlich gibt die Eigenschaft ValuePrecision an, wie genau die Werte sein können.

So definieren Sie diesen Node:

csharp
var statusNode = new OpcDataItemNode<int>(machineNode, "Status");
statusNode.Definition = "Status Code in low word, Progress Code in high word encoded in BCD";
vbnet
Dim statusNode As New OpcDataItemNode(Of Integer)(machineNode, "Status")
statusNode.Definition = "Status Code in low word, Progress Code in high word encoded in BCD"

Der Wert der Eigenschaft Definition ist herstellerabhängig.

Analoge Datenpunkte ​

Beteiligte TypenOpcNodeManagerOpcAnalogItemNodeOpcValueRangeOpcEngineeringUnitInfo

Nodes vom Typ AnalogItemType sind eine Spezialisierung der Klasse OpcDataItemNode. Ihre zusätzlichen Eigenschaften beschreiben die analogen Werte genauer. Die Eigenschaft InstrumentRange definiert den Wertebereich, den die Quelle der analogen Daten verwendet. Die Eigenschaft EngineeringUnit klassifiziert die Maßeinheit des Werts gemäß den UNECE-Empfehlungen N° 20. Diese Empfehlungen basieren auf dem Internationalen Einheitensystem (engl. International System of Units, kurz SI Units). Ergänzend stellt die Eigenschaft EngineeringUnitRange den Wertebereich bereit, der im normalen Betrieb gilt, angegeben in der Einheit aus EngineeringUnit.

Der Konstruktor der Klasse OpcValueRange erwartet zuerst die obere und dann die untere Grenze. So definieren Sie einen solchen Node im Node-Manager:

csharp
var temperatureNode = new OpcAnalogItemNode<float>(machineNode, "Temperature");

temperatureNode.InstrumentRange = new OpcValueRange(80.0, -40.0);
temperatureNode.EngineeringUnit = new OpcEngineeringUnitInfo(4408652, "°C", "degree Celsius");
temperatureNode.EngineeringUnitRange = new OpcValueRange(70.8, 5.0);
vbnet
Dim temperatureNode As New OpcAnalogItemNode(Of Single)(machineNode, "Temperature")

temperatureNode.InstrumentRange = New OpcValueRange(80.0, -40.0)
temperatureNode.EngineeringUnit = New OpcEngineeringUnitInfo(4408652, "°C", "degree Celsius")
temperatureNode.EngineeringUnitRange = New OpcValueRange(70.8, 5.0)

Die UnitID, die der Konstruktor von OpcEngineeringUnitInfo erwartet, finden Sie in der UNECE-Tabelle für Maßeinheiten bei der OPC Foundation: UNECE-Maßeinheiten in OPC UA (aktuell nicht verfügbar). Alternativ bietet auch das MTConnect-Institut die UNECE-Tabelle auf GitHub an: UNECE-Maßeinheiten in OPC UA (MTConnect@GitHub). Daneben gibt es einen Konstruktor, der nur die UnitID erwartet.

Diskrete Datenpunkte ​

Beteiligte TypenOpcNodeManagerOpcTwoStateDiscreteNodeOpcMultiStateDiscreteNodeOpcMultiStateValueDiscreteNodeOpcEnumValue

Wenn der Wert eines Datenpunkts nur eine bestimmte Anzahl von Zuständen annehmen kann, stehen die diskreten Datenpunkt-Nodes zur Verfügung:

  • OpcTwoStateDiscreteNode (TwoStateDiscreteType): ein boolescher Wert mit Texten für die beiden Zustände (TrueState, FalseState).
  • OpcMultiStateDiscreteNode<T> (MultiStateDiscreteType): ein ganzzahliger Wert, der den Index in eine Liste von Texten (EnumStrings) angibt.
  • OpcMultiStateValueDiscreteNode<T> (MultiStateValueDiscreteType): ein ganzzahliger Wert, zu dem eine Liste von Name-Wert-Paaren (EnumValues) gehört; die Werte müssen nicht fortlaufend sein.
csharp
var doorNode = new OpcTwoStateDiscreteNode(machineNode, "DoorOpen", value: false);
doorNode.TrueState = "Open";
doorNode.FalseState = "Closed";
 
var modeNode = new OpcMultiStateDiscreteNode<uint>(machineNode, "Mode", value: 0u);
modeNode.EnumStrings = new OpcText[] { "Manual", "Automatic", "Service" };
 
var errorNode = new OpcMultiStateValueDiscreteNode<int>(machineNode, "Error", value: 0);
errorNode.EnumValues = new OpcEnumValue[] {
    new OpcEnumValue("None", value: 0),
    new OpcEnumValue("Overheated", value: 10)
};
vbnet
Dim doorNode = New OpcTwoStateDiscreteNode(machineNode, "DoorOpen", value:=False)
doorNode.TrueState = "Open"
doorNode.FalseState = "Closed"

Dim modeNode = New OpcMultiStateDiscreteNode(Of UInteger)(machineNode, "Mode", value:=0UI)
modeNode.EnumStrings = New OpcText() {"Manual", "Automatic", "Service"}

Dim errorNode = New OpcMultiStateValueDiscreteNode(Of Integer)(machineNode, "Error", value:=0)
errorNode.EnumValues = New OpcEnumValue() { _
    New OpcEnumValue("None", value:=0), _
    New OpcEnumValue("Overheated", value:=10) _
}

Datenpunkte mit Maßeinheit ​

Beteiligte TypenOpcNodeManagerOpcAnalogUnitNodeOpcAnalogUnitRangeNodeOpcEngineeringUnitInfo

Wenn für einen analogen Wert nur die Maßeinheit, aber kein Wertebereich bekannt ist, verwenden Sie die Klasse OpcAnalogUnitNode (AnalogUnitType). Bei ihr ist die Eigenschaft EngineeringUnit Pflicht. Die Klasse OpcAnalogUnitRangeNode (AnalogUnitRangeType) bietet zusätzlich den Wertebereich (EngineeringUnitRange):

csharp
var speedNode = new OpcAnalogUnitNode<double>(machineNode, "Speed", value: 0.0);
 
speedNode.EngineeringUnit = new OpcEngineeringUnitInfo(
        unitId: 5067859,
        displayName: "m/s",
        description: "metre per second");
vbnet
Dim speedNode = New OpcAnalogUnitNode(Of Double)(machineNode, "Speed", value:=0.0)

speedNode.EngineeringUnit = New OpcEngineeringUnitInfo( _
        unitId:=5067859, _
        displayName:="m/s", _
        description:="metre per second")