Anleitung
Node-Modelle
Mit OpcNodeModel festlegen, welche Kind-Nodes beim Erzeugen eines typisierten Nodes entstehen, und Startwerte aus der Typdefinition übernehmen.
Anleitung
Node-Modelle
Beteiligte TypenOpcNodeModelOpcModellingDirectiveOpcModellingRuleOpcNodeTypeInfoOpcNodeIOpcNodeInfo
Ein Objekttyp in OPC UA, zum Beispiel MachineIdentificationType aus OPC UA for Machinery, legt fest, welche Kind-Nodes eine Instanz dieses Typs besitzt. Ein Teil davon ist verpflichtend (Mandatory), ein anderer optional (Optional). Wenn Sie einen typisierten Node erzeugen, zum Beispiel über eine Node-Klasse eines Companion SDK, ist deshalb zu entscheiden, welche der optionalen Kind-Nodes tatsächlich entstehen. Das beschreibt ein OpcNodeModel.
Ein Node-Modell ist ein Baum, der für jeden Kind-Node des Typs eine Anweisung (OpcModellingDirective) enthält:
| Anweisung | Bedeutung |
|---|---|
Create | Der Kind-Node wird angelegt. |
Omit | Der Kind-Node wird nicht angelegt. Bei den Node-Klassen der Companion SDKs ist die zugehörige Eigenschaft dann null. |
Default | Es gilt das Standardverhalten der Node-Klasse (siehe Verhalten ohne Modell). |
Zusätzlich übernimmt ein Node-Modell Startwerte aus der Deklaration des Typs: den Anzeigenamen (DisplayName), die Beschreibung (Description) und die Schreibrechte (WriteAccess, UserWriteAccess). Bei Variablen kommen die Zugriffsrechte (AccessLevel, UserAccessLevel), der Rang (ValueRank), die Array-Dimensionen (ArrayDimensions) und der Standardwert (Value) hinzu. Das gilt, solange Sie beim Erzeugen keinen anderen Wert angeben.
Ein Modell erstellen
Ein Node-Modell entsteht immer aus der Beschreibung eines Typs (IOpcNodeTypeInfo) über OpcNodeModel.Of. Die Beschreibung liefert:
| Quelle | Methode |
|---|---|
| Server | OpcServer., nach dem Start des Servers |
| Kontext | OpcContext., zum Beispiel über server. |
| NodeSet | OpcNodeSet. |
| Client | OpcClient., für einen Typ des verbundenen Servers |
OpcNodeModel.Of legt für jeden Kind-Node des Typs, einschließlich der geerbten, ein Kind-Modell an. Kind-Nodes mit der Regel Mandatory oder MandatoryPlaceholder erhalten dabei fest die Anweisung Create, alle anderen die Anweisung Default.
Für Typen aus Companion SDKs rufen Sie die Beschreibung am besten über den Server nach dessen Start ab. Das Modell ordnet die Kind-Nodes über ihren Namen einschließlich des Namespace-Index zu. Diese Indizes stehen erst fest, wenn die Node-Manager ihre Namespaces aufgelöst haben.
Das folgende Beispiel gibt das Modell eines Typs aus. ToString liefert je Kind-Node den Namen, die Regel und die Anweisung (zum Beispiel 2:SerialNumber (Mandatory) -> Create):
OpcNodeTypeInfo nodeType = server.GetNodeType(OpcMachineryNodes.MachineIdentificationType);
OpcNodeModel model = OpcNodeModel.Of(nodeType);
foreach (OpcNodeModel child in model.Children())
Console.WriteLine(child);
foreach (OpcNodeModel optionalChild in model.ChildrenWith(OpcModellingRule.Optional))
Console.WriteLine("Optional: {0}", optionalChild.Name);Dim nodeType As OpcNodeTypeInfo = server.GetNodeType(OpcMachineryNodes.MachineIdentificationType)
Dim model As OpcNodeModel = OpcNodeModel.Of(nodeType)
For Each child As OpcNodeModel In model.Children()
Console.WriteLine(child)
Next
For Each optionalChild As OpcNodeModel In model.ChildrenWith(OpcModellingRule.Optional)
Console.WriteLine("Optional: {0}", optionalChild.Name)
NextKind-Nodes auswählen
| Methode | Wirkung |
|---|---|
OmitOptionals() | setzt alle optionalen Kind-Nodes (Regel Optional oder ohne Regel) auf Omit; Platzhalter bleiben unverändert |
Omit | wie OmitOptionals, im gesamten Teilbaum |
Create | setzt alle optionalen Kind-Nodes der ersten Ebene auf Create |
Create | setzt alle Kind-Nodes, deren Name die Bedingung erfüllt, auf Create |
CreateLike(node) | übernimmt die Struktur eines vorhandenen Nodes: legt dessen Kind-Nodes an, Kind-Nodes ohne Deklaration im Typ kommen hinzu |
Create, OmitByDefault() | legen fest, was mit Kind-Nodes geschieht, die nicht im Modell stehen (zum Beispiel weil eine Instanz zusätzliche Kind-Nodes besitzt); optional rekursiv |
Child(name), Children(), Children | liefern einzelne oder alle Kind-Modelle, auch gefiltert nach Regel |
Die Methoden liefern das Modell selbst zurück und lassen sich deshalb verketten. Pflicht-Kind-Nodes legt die Node-Klasse immer an.
Nur die Pflicht-Kind-Nodes und ausgewählte optionale Kind-Nodes anlegen: Übergeben Sie das Modell dem Konstruktor der Node-Klasse. Die Node-Klassen der Companion SDKs bieten dafür öffentliche Konstruktoren mit einem OpcNodeModel als erstem Parameter:
OpcNodeModel model = OpcNodeModel
.Of(server.GetNodeType(OpcMachineryNodes.MachineIdentificationType))
.OmitOptionals()
.CreateIf(name => name.Value == "YearOfConstruction" || name.Value == "Location");
var machine = new OpcObjectNode(machinery.Machines, "CNC-042");
var identification = new OpcMachineIdentificationNode(model, machine, "Identification");
identification.Manufacturer.Value = "Example Machines Ltd.";
identification.SerialNumber.Value = "SN-0042";
identification.ProductInstanceUri.Value = "urn:example:cnc-0042";
identification.YearOfConstruction.Value = 2026;
machinery.AddNode(server.SystemContext, machine);Dim model As OpcNodeModel = OpcNodeModel _
.Of(server.GetNodeType(OpcMachineryNodes.MachineIdentificationType)) _
.OmitOptionals() _
.CreateIf(Function(name) name.Value = "YearOfConstruction" OrElse name.Value = "Location")
Dim machine = New OpcObjectNode(machinery.Machines, "CNC-042")
Dim identification = New OpcMachineIdentificationNode(model, machine, "Identification")
identification.Manufacturer.Value = "Example Machines Ltd."
identification.SerialNumber.Value = "SN-0042"
identification.ProductInstanceUri.Value = "urn:example:cnc-0042"
identification.YearOfConstruction.Value = 2026
machinery.AddNode(server.SystemContext, machine)Alle optionalen Kind-Nodes im gesamten Teilbaum weglassen:
OpcNodeModel model = OpcNodeModel
.Of(server.GetNodeType(OpcMachineryNodes.MachineIdentificationType))
.OmitOptionals(recursive: true);Dim model As OpcNodeModel = OpcNodeModel _
.Of(server.GetNodeType(OpcMachineryNodes.MachineIdentificationType)) _
.OmitOptionals(recursive:=True)Kind-Nodes, die der Typ nicht deklariert, ebenfalls weglassen:
OpcNodeModel model = OpcNodeModel
.Of(server.GetNodeType(OpcMachineryNodes.MachineIdentificationType))
.OmitOptionals()
.OmitByDefault();Dim model As OpcNodeModel = OpcNodeModel _
.Of(server.GetNodeType(OpcMachineryNodes.MachineIdentificationType)) _
.OmitOptionals() _
.OmitByDefault()Die Struktur eines vorhandenen Nodes übernehmen: CreateLike akzeptiert jeden IOpcNodeInfo, zum Beispiel einen Node aus einem NodeSet (OpcNodeSet.GetNode, GetNodes) oder einen über OpcClient.BrowseNode gelesenen Node eines anderen Servers. So entsteht eine Instanz mit genau den Kind-Nodes einer Vorlage:
IOpcNodeInfo template = nodeSet.GetNode(templateId);
OpcNodeModel model = OpcNodeModel
.Of(server.GetNodeType(OpcMachineryNodes.MachineIdentificationType))
.OmitOptionals()
.CreateLike(template);Dim template As IOpcNodeInfo = nodeSet.GetNode(templateId)
Dim model As OpcNodeModel = OpcNodeModel _
.Of(server.GetNodeType(OpcMachineryNodes.MachineIdentificationType)) _
.OmitOptionals() _
.CreateLike(template)Verhalten ohne Modell
Wenn Sie einer Node-Klasse kein Modell übergeben, gilt die Anweisung Default:
- Die Node-Klassen der Companion SDKs legen dann alle Kind-Nodes ihres Typs an, auch alle optionalen.
- Die Node-Klassen des OPC UA .NET SDK selbst verwenden ihr bisheriges Standardverhalten. Beispiele sind
OpcDataItemNodemitDefinitionundValuePrecision,OpcAnalogItemNodemit EngineeringUnits, EURange und InstrumentRange oder die Zustandsautomaten mit AvailableStates, AvailableTransitions und LastTransition. Mit einem Modell legtCreateden Kind-Node an undOmitentfernt ihn.
Ein Kind-Node ohne eigenes Modell übernimmt das passende Kind-Modell seines Eltern-Nodes. Ein Modell, das Sie dem obersten Node übergeben, wirkt dadurch auf den gesamten Teilbaum.
Im Basis-SDK sind die Konstruktoren mit OpcNodeModel für abgeleitete Klassen gedacht (protected). Öffentlich nutzbar sind Node-Modelle damit vor allem mit den Node-Klassen der Companion SDKs sowie mit OpcHistoryConfigurationNode und OpcAggregateConfigurationNode. Die Companion SDKs beschreibt der Abschnitt Companion-Spezifikationen.
Das Modell eines Nodes abfragen
Über die Eigenschaft Model liefert jeder OpcNode das Modell, mit dem er erzeugt wurde, oder das Kind-Modell seines Eltern-Nodes. Ob ein optionaler Kind-Node angelegt wurde, zeigt bei den Node-Klassen der Companion SDKs zudem die zugehörige Eigenschaft (null, wenn er fehlt):
// MachineIdentificationType defines its own property "Model" (product model).
// The node model is available via the base class OpcNode.
OpcNodeModel nodeModel = ((OpcNode)identification).Model;
Console.WriteLine(nodeModel.Directive);
Console.WriteLine(identification.Location == null ? "Location omitted" : "Location created");'MachineIdentificationType defines its own property "Model" (product model).
'The node model is available via the base class OpcNode.
Dim nodeModel As OpcNodeModel = CType(identification, OpcNode).Model
Console.WriteLine(nodeModel.Directive)
Console.WriteLine(If(identification.Location Is Nothing, "Location omitted", "Location created"))Die Model-Eigenschaft bei DI-Typen
Eigenschaft Model in Typen aus OPC UA for Devices
Typen, die auf OPC UA for Devices (DI) aufbauen, besitzen einen Kind-Node namens Model (das Produktmodell). Die Node-Klassen dieser Typen stellen ihn als Eigenschaft Model bereit, die die gleichnamige Eigenschaft von OpcNode verdeckt. Das Node-Modell ist dann nur über die Basisklasse erreichbar: ((OpcNode)node).Model (in VB.NET CType(node, OpcNode).Model).
Namen, die das Modell nicht kennt
Verwenden Sie zum Auswählen einzelner Kind-Nodes CreateIf. Wenn Sie die Methode Create(name) mit einem Namen aufrufen, der im Modell nicht vorkommt, verändert sie kein Kind des Modells. Sie verändert stattdessen das gemeinsam genutzte Standardmodell für unbekannte Kind-Nodes und wirkt damit auf alle Nodes, die dieses Standardmodell erhalten. Beginnen Sie ein Modell außerdem immer mit OpcNodeModel.Of. Das leere Modell OpcNodeModel.None ist eine gemeinsam genutzte Instanz und nicht zum Bearbeiten gedacht.
Für eigene Node-Klassen mit eigenem Namespace können Sie Regeln auch für alle Instanzen einer Klasse festlegen. Die geschützte statische Methode DefineModel<T> legt im statischen Konstruktor der Klasse fest, welche Kind-Nodes als optional (Optional) entfallen oder als verpflichtend (Mandatory) entstehen. Das SDK führt die Regeln entlang der Vererbung zusammen. Sie gelten nur für Klassen außerhalb des SDK.

