Zum Inhalt springen

Anleitung

Datentypen zur Laufzeit

Strukturen und Enumerationen erst zur Laufzeit definieren, im Adressraum veröffentlichen und ihre Werte ohne eigene .NET-Typen bereitstellen.

Anleitung

Datentypen zur Laufzeit ​

Beteiligte TypenOpcServerOpcStructOpcStructFieldOpcEnumOpcEnumFieldOpcDataTypeNodeOpcDataObject

Benutzerdefinierte Datentypen legen Sie üblicherweise über .NET-Typen und Attribute fest. Das beschreibt der Abschnitt Datentypen bereitstellen. Wenn die Datentypen erst zur Laufzeit feststehen, zum Beispiel weil sie aus einer Konfiguration oder einer angebundenen Steuerung stammen, definieren Sie sie stattdessen über die Klassen OpcStruct (Strukturen) und OpcEnum (Enumerationen). Die Werte solcher Datentypen stellt der Server als Instanzen von OpcDataObject bereit, ganz ohne eigene .NET-Typen.

Dynamische Datentypen aktivieren ​

Damit der Server Werte dynamisch definierter Datentypen kodieren kann, aktivieren Sie die Eigenschaft UseDynamic des Servers. Standardmäßig bestimmt sie OpcAutomatism.UseDynamic, das deaktiviert ist:

csharp
server.UseDynamic = true;
vbnet
server.UseDynamic = True

Strukturen definieren ​

Eine Struktur definieren Sie über die Methode DefineType der Klasse OpcStruct. Sie erhält die OpcNodeId und den Namen des Datentyps sowie seine Felder als Instanzen von OpcStructField. Jedes Feld besteht aus seinem Namen, der OpcNodeId seines Datentyps (zum Beispiel aus der Klasse OpcDataTypes) und optional einer Beschreibung. Die Methode AsArray macht ein Feld zum Array, die Methode AsOptional zu einem optionalen Feld:

csharp
var machineDataTypeId = new OpcNodeId("MachineData", namespaceIndex: 2);
 
var machineDataType = OpcStruct.DefineType(
        machineDataTypeId,
        new OpcName("MachineData", namespaceIndex: 2),
        new OpcStructField("Speed", OpcDataTypes.Int32),
        new OpcStructField("JobName", OpcDataTypes.String),
        new OpcStructField("Temperatures", OpcDataTypes.Double).AsArray(),
        new OpcStructField("Comment", OpcDataTypes.String, description: "Optional comment.")
                .AsOptional());
vbnet
Dim machineDataTypeId = New OpcNodeId("MachineData", namespaceIndex:=2)

Dim machineDataType = OpcStruct.DefineType( _
        machineDataTypeId, _
        New OpcName("MachineData", namespaceIndex:=2), _
        New OpcStructField("Speed", OpcDataTypes.Int32), _
        New OpcStructField("JobName", OpcDataTypes.String), _
        New OpcStructField("Temperatures", OpcDataTypes.Double).AsArray(), _
        New OpcStructField("Comment", OpcDataTypes.String, description:="Optional comment.") _
                .AsOptional())

Wenn eine Struktur eine andere erweitern soll, definieren Sie sie über die Methode DefineSubType und geben den Basistyp an:

csharp
var extendedDataType = OpcStruct.DefineSubType(
        machineDataTypeId,
        new OpcNodeId("ExtendedMachineData", namespaceIndex: 2),
        new OpcName("ExtendedMachineData", namespaceIndex: 2),
        new OpcStructField("Operator", OpcDataTypes.String));
vbnet
Dim extendedDataType = OpcStruct.DefineSubType( _
        machineDataTypeId, _
        New OpcNodeId("ExtendedMachineData", namespaceIndex:=2), _
        New OpcName("ExtendedMachineData", namespaceIndex:=2), _
        New OpcStructField("Operator", OpcDataTypes.String))

Enumerationen definieren ​

Eine Enumeration definieren Sie über die Klasse OpcEnum, und zwar auf eine von zwei Arten:

  • über die Methode DefineStrings als Liste von Namen (EnumStrings). Der Wert eines Eintrags ist sein Index.
  • über die Methode DefineValues als Liste von Name-Wert-Paaren (EnumValues). Die Werte müssen nicht fortlaufend sein, und jeder Eintrag kann eine Beschreibung erhalten.
csharp
var jobKindId = new OpcNodeId("JobKind", namespaceIndex: 2);
 
var jobKind = OpcEnum.DefineStrings(
        jobKindId,
        new OpcName("JobKind", namespaceIndex: 2),
        new OpcEnumField("Production"),
        new OpcEnumField("Maintenance"));
 
var errorCode = OpcEnum.DefineValues(
        new OpcNodeId("ErrorCode", namespaceIndex: 2),
        new OpcName("ErrorCode", namespaceIndex: 2),
        new OpcEnumField("None", value: 0),
        new OpcEnumField("Overheated", value: 10, description: "The temperature exceeded the limit."),
        new OpcEnumField("OutOfMaterial", value: 20, description: "The material supply is empty."));
vbnet
Dim jobKindId = New OpcNodeId("JobKind", namespaceIndex:=2)

Dim jobKind = OpcEnum.DefineStrings( _
        jobKindId, _
        New OpcName("JobKind", namespaceIndex:=2), _
        New OpcEnumField("Production"), _
        New OpcEnumField("Maintenance"))

Dim errorCode = OpcEnum.DefineValues( _
        New OpcNodeId("ErrorCode", namespaceIndex:=2), _
        New OpcName("ErrorCode", namespaceIndex:=2), _
        New OpcEnumField("None", value:=0), _
        New OpcEnumField("Overheated", value:=10, description:="The temperature exceeded the limit."), _
        New OpcEnumField("OutOfMaterial", value:=20, description:="The material supply is empty."))

Variablen mit dynamischen Datentypen anlegen ​

Variablen, die einen dynamisch definierten Datentyp verwenden, legen Sie wie gewohnt im Node-Manager an. Ihren Datentyp legt die Eigenschaft DataTypeId fest:

csharp
// MyNodeManager.CreateNodes(...)
var machineDataNode = new OpcDataVariableNode(machineNode, "Data");
machineDataNode.DataTypeId = machineDataTypeId;
 
var jobKindNode = new OpcDataVariableNode(machineNode, "JobKind");
jobKindNode.DataTypeId = jobKindId;
vbnet
'MyNodeManager.CreateNodes(...)
Dim machineDataNode = New OpcDataVariableNode(machineNode, "Data")
machineDataNode.DataTypeId = machineDataTypeId

Dim jobKindNode = New OpcDataVariableNode(machineNode, "JobKind")
jobKindNode.DataTypeId = jobKindId

Datentypen veröffentlichen ​

Der Server veröffentlicht die Datentypen über Datentyp-Nodes. Diese Nodes erzeugt die Methode Create der Klasse OpcDataTypeNode aus der jeweiligen Definition. Weil der Server zum Erzeugen dieser Nodes die Datentypen der Felder auflöst, fügen Sie sie erst nach dem Start des Servers über die Methode AddNode des Node-Managers hinzu:

csharp
server.Start();
 
// The data type nodes are added after the server has been started.
nodeManager.AddNode(OpcDataTypeNode.Create(machineDataType));
nodeManager.AddNode(OpcDataTypeNode.Create(jobKind));
nodeManager.AddNode(OpcDataTypeNode.Create(errorCode));
vbnet
server.Start()

'The data type nodes are added after the server has been started.
nodeManager.AddNode(OpcDataTypeNode.Create(machineDataType))
nodeManager.AddNode(OpcDataTypeNode.Create(jobKind))
nodeManager.AddNode(OpcDataTypeNode.Create(errorCode))

Werte bereitstellen ​

Einen Wert einer Struktur erzeugen Sie als OpcDataObject. Den dazu benötigten Datentyp liefert die Methode GetDataType des Servers, sobald der Datentyp-Node veröffentlicht ist. Die Felder sprechen Sie über ihren Namen an. Optionale Felder, denen Sie keinen Wert zuweisen, bleiben leer. Der Wert einer Enumeration ist eine Zahl: bei EnumStrings der Index, bei EnumValues der Wert des Eintrags:

csharp
var dataType = server.GetDataType(machineDataTypeId);
var data = new OpcDataObject(dataType);
 
data["Speed"].Value = 1200;
data["JobName"].Value = "JOB0815";
data["Temperatures"].Value = new double[] { 20.5, 21.0, 21.3 };
 
machineDataNode.Value = data;
machineDataNode.ApplyChanges(server.SystemContext);
 
// Enumeration values are numbers (index or value of the field), here: Maintenance.
jobKindNode.Value = 1;
jobKindNode.ApplyChanges(server.SystemContext);
vbnet
Dim dataType = server.GetDataType(machineDataTypeId)
Dim data = New OpcDataObject(dataType)

data("Speed").Value = 1200
data("JobName").Value = "JOB0815"
data("Temperatures").Value = New Double() {20.5, 21.0, 21.3}

machineDataNode.Value = data
machineDataNode.ApplyChanges(server.SystemContext)

'Enumeration values are numbers (index or value of the field), here: Maintenance.
jobKindNode.Value = 1
jobKindNode.ApplyChanges(server.SystemContext)

Ein Client, der die Datentypen des Servers zur Laufzeit auflöst (zum Beispiel über OpcClient.UseDynamic), erhält die Werte der Struktur ebenfalls als OpcDataObject. Das beschreibt die Seite Strukturierte Daten.