/// <summary> /// Does any initialization required before the address space can be used. /// </summary> /// <remarks> /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// </remarks> public override void CreateAddressSpace(IDictionary <NodeId, IList <IReference> > externalReferences) { lock (Lock) { base.CreateAddressSpace(externalReferences); NodeState root = FindPredefinedNode(new NodeId(Quickstarts.Views.Objects.Plant, NamespaceIndex), typeof(NodeState)); Quickstarts.Views.BoilerState boiler1 = new Quickstarts.Views.BoilerState(null); ParsedNodeId pnd1 = new ParsedNodeId() { NamespaceIndex = NamespaceIndex, RootId = "Boiler #1" }; boiler1.Create( SystemContext, pnd1.Construct(), new QualifiedName("Boiler #1", NamespaceIndex), null, true); boiler1.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, true, root.NodeId); root.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, false, boiler1.NodeId); AddPredefinedNode(SystemContext, boiler1); Quickstarts.Views.BoilerState boiler2 = new Quickstarts.Views.BoilerState(null); ParsedNodeId pnd2 = new ParsedNodeId() { NamespaceIndex = NamespaceIndex, RootId = "Boiler #2" }; boiler2.Create( SystemContext, pnd2.Construct(), new QualifiedName("Boiler #2", NamespaceIndex), null, true); boiler2.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, true, root.NodeId); root.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, false, boiler2.NodeId); AddPredefinedNode(SystemContext, boiler2); } }
//// Objects // /// <summary> /// Helper to create an Object-Node. Note: __NO__ NodeId is created by the default! Must be done by outer /// functionality!! /// </summary> /// <param name="parent">Parent node</param> /// <param name="mode">Type or instance</param> /// <param name="browseDisplayName">Name displayed in the node tree</param> /// <param name="referenceTypeFromParentId"></param> /// <param name="typeDefinitionId">Type of the Object</param> /// <param name="modellingRule">Modeling Rule, if not None</param> /// <param name="extraName"></param> /// <returns>The node</returns> public BaseObjectState CreateAddObject( NodeState parent, AasUaBaseEntity.CreateMode mode, string browseDisplayName, NodeId referenceTypeFromParentId = null, NodeId typeDefinitionId = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None, string extraName = null) { var x = AasUaNodeHelper.CreateObject(parent, browseDisplayName, typeDefinitionId: typeDefinitionId, modellingRule: modellingRule, extraName: extraName); x.NodeId = nodeMgr.NewFromParent(nodeMgr.SystemContext, mode, x, parent); nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, x); if (parent != null) { parent.AddChild(x); } if (referenceTypeFromParentId != null) { if (parent != null) { if (!parent.ReferenceExists(referenceTypeFromParentId, false, x.NodeId)) { parent.AddReference(referenceTypeFromParentId, false, x.NodeId); } if (referenceTypeFromParentId == ReferenceTypeIds.HasComponent) { x.AddReference(referenceTypeFromParentId, true, parent.NodeId); } if (referenceTypeFromParentId == ReferenceTypeIds.HasProperty) { x.AddReference(referenceTypeFromParentId, true, parent.NodeId); } } //// nodeMgr.AddReference(parentNodeId, new AasReference(referenceTypeId, false, x.NodeId)); } //// if (typeDefinitionId != null) //// { //// x.TypeDefinitionId = typeDefinitionId; //// x.AddReference(ReferenceTypeIds.HasTypeDefinition, false, typeDefinitionId); //// // nodeMgr.AddReference(x.NodeId, new AasReference(ReferenceTypeIds.HasTypeDefinition, false, //// // typeDefinitionId)); //// } return(x); }
/// <summary> /// Appply modelling rule to an arbitrary node /// </summary> public static NodeState CheckSetModellingRule(ModellingRule modellingRule, NodeState o) { if (o == null || modellingRule == ModellingRule.None) { return(o); } if (modellingRule == ModellingRule.Optional) { o.AddReference(ReferenceTypeIds.HasModellingRule, false, ObjectIds.ModellingRule_Optional); } if (modellingRule == ModellingRule.OptionalPlaceholder) { o.AddReference(ReferenceTypeIds.HasModellingRule, false, ObjectIds.ModellingRule_OptionalPlaceholder); } if (modellingRule == ModellingRule.Mandatory) { o.AddReference(ReferenceTypeIds.HasModellingRule, false, ObjectIds.ModellingRule_Mandatory); } if (modellingRule == ModellingRule.MandatoryPlaceholder) { o.AddReference(ReferenceTypeIds.HasModellingRule, false, ObjectIds.ModellingRule_MandatoryPlaceholder); } return(o); }
public void addNode(BaseInstanceState node, NodeId parentId) { NodeState parent = Find(parentId); if (Find(node.NodeId) != null) { node.NodeId = getFreeNodeId(node.NodeId.NamespaceIndex, node.NodeId.Identifier.GetType() == typeof(int)?(uint)node.NodeId.Identifier:10000); } parent.AddChild(node); AddPredefinedNode(SystemContext, parent); parent.AddReference(ReferenceTypes.HasComponent, true, node.NodeId); IDictionary <NodeId, List <IReference> > refs = new Dictionary <NodeId, List <IReference> >(); //IReference iref = parent.ref; //refs.Add(parent.NodeId, parent.GetReferences(SystemContext)); //AddReferences(); }
/// <summary> /// Adds a root notifier. /// </summary> /// <param name="notifier">The notifier.</param> /// <remarks> /// A root notifier is a notifier owned by the NodeManager that is not the target of a /// HasNotifier reference. These nodes need to be linked directly to the Server object. /// </remarks> protected override void AddRootNotifier(NodeState notifier) { if (_rootNotifiers == null) { _rootNotifiers = new List <NodeState>(); } for (int ii = 0; ii < _rootNotifiers.Count; ii++) { if (Object.ReferenceEquals(notifier, _rootNotifiers[ii])) { return; } } _rootNotifiers.Add(notifier); // need to prevent recursion with the server object. if (notifier.NodeId != ObjectIds.Server) { notifier.OnReportEvent = OnReportEvent; if (!notifier.ReferenceExists(ReferenceTypeIds.HasNotifier, true, ObjectIds.Server)) { notifier.AddReference(ReferenceTypeIds.HasNotifier, true, ObjectIds.Server); } } // subscribe to existing events. if (_server.EventManager != null) { IList <IEventMonitoredItem> monitoredItems = _server.EventManager.GetMonitoredItems(); for (int ii = 0; ii < monitoredItems.Count; ii++) { if (monitoredItems[ii].MonitoringAllEvents) { SubscribeToEvents( SystemContext, notifier, monitoredItems[ii], true); } } } }
/// <summary> /// Creates a boiler and adds it to the address space. /// </summary> /// <param name="context">The context to use.</param> /// <param name="unitNumber">The unit number for the boiler.</param> private void CreateBoiler(SystemContext context, int unitNumber) { BoilerState boiler = new BoilerState(null); string name = Utils.Format("Boiler #{0}", unitNumber); boiler.Create( context, null, new QualifiedName(name, m_namespaceIndex), null, true); NodeState folder = (NodeState)FindPredefinedNode( ExpandedNodeId.ToNodeId(ObjectIds.Boilers, Server.NamespaceUris), typeof(NodeState)); folder.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, false, boiler.NodeId); boiler.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, true, folder.NodeId); string unitLabel = Utils.Format("{0}0", unitNumber); UpdateDisplayName(boiler.InputPipe, unitLabel); UpdateDisplayName(boiler.Drum, unitLabel); UpdateDisplayName(boiler.OutputPipe, unitLabel); UpdateDisplayName(boiler.LevelController, unitLabel); UpdateDisplayName(boiler.FlowController, unitLabel); UpdateDisplayName(boiler.CustomController, unitLabel); m_boilers.Add(boiler); AddPredefinedNode(context, boiler); // Autostart boiler simulation state machine MethodState start = (MethodState)boiler.Simulation.FindChild(context, Opc.Ua.BrowseNames.Start); if (start != null) { IList <Variant> inputArguments = new List <Variant>(); IList <Variant> outputArguments = new List <Variant>(); List <ServiceResult> errors = new List <ServiceResult>(); start.Call(context, boiler.NodeId, inputArguments, errors, outputArguments); } }
public MethodState CreateAddMethodState( NodeState parent, AasUaBaseEntity.CreateMode mode, string browseDisplayName, Argument[] inputArgs = null, Argument[] outputArgs = null, NodeId referenceTypeFromParentId = null, NodeId methodDeclarationId = null, GenericMethodCalledEventHandler onCalled = null) { // method node var m = new MethodState(parent); m.BrowseName = "" + browseDisplayName; m.DisplayName = "" + browseDisplayName; m.Description = new LocalizedText("en", browseDisplayName); m.NodeId = nodeMgr.New(nodeMgr.SystemContext, mode, m); if (methodDeclarationId != null) { m.MethodDeclarationId = methodDeclarationId; } m.Executable = true; m.UserExecutable = true; nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, m); if (parent != null) { parent.AddChild(m); } if (referenceTypeFromParentId != null) { if (parent != null) { parent.AddReference(referenceTypeFromParentId, false, m.NodeId); if (referenceTypeFromParentId == ReferenceTypeIds.HasComponent) { m.AddReference(referenceTypeFromParentId, true, parent.NodeId); } if (referenceTypeFromParentId == ReferenceTypeIds.HasProperty) { m.AddReference(referenceTypeFromParentId, true, parent.NodeId); } } } // can have inputs, outputs for (int i = 0; i < 2; i++) { // pretty argument list var arguments = (i == 0) ? inputArgs : outputArgs; if (arguments == null || arguments.Length < 1) { continue; } // make a property for this var prop = CreateAddPropertyState <Argument[]>( m, mode, (i == 0) ? "InputArguments" : "OutputArguments", DataTypeIds.Argument, arguments, ReferenceTypeIds.HasProperty, typeDefinitionId: VariableTypeIds.PropertyType, valueRank: 1); // explicitely add arguments ass well? if (i == 0) { m.InputArguments = prop; } if (i == 1) { m.OutputArguments = prop; } } // event handler if (onCalled != null) { m.OnCallMethod = onCalled; } return(m); }
//// Properties // /// <summary> /// Helper to create an PropertyState-Node for a certain type and add it to the information model. /// Note: __NO__ NodeId is created by the default! Must be done by outer functionality!! /// </summary> /// <typeparam name="T">C# type of the proprty</typeparam> /// <param name="parent">Parent node</param> /// <param name="mode">Type or instance</param> /// <param name="browseDisplayName">Name displayed in the node tree</param> /// <param name="dataTypeId">Data type, such as String.. Given by DataTypeIds...</param> /// <param name="value">Value of the type T or Null</param> /// <param name="referenceTypeFromParentId"></param> /// <param name="typeDefinitionId">Type definition; independent from DataType!</param> /// <param name="valueRank">-1 or e.g. 1 for array</param> /// <param name="defaultSettings">Apply default settings for a normal Property</param> /// <param name="modellingRule">Modeling Rule, if not None</param> /// <returns>NodeState</returns> public PropertyState <T> CreateAddPropertyState <T>( NodeState parent, AasUaBaseEntity.CreateMode mode, string browseDisplayName, NodeId dataTypeId, T value, NodeId referenceTypeFromParentId = null, NodeId typeDefinitionId = null, int valueRank = -2, bool defaultSettings = false, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) { // apply cumulative settings if (defaultSettings) { referenceTypeFromParentId = ReferenceTypeIds.HasProperty; typeDefinitionId = VariableTypeIds.PropertyType; if (valueRank == -2) { valueRank = -1; } } // make Property var x = new PropertyState <T>(parent); x.BrowseName = "" + browseDisplayName; x.DisplayName = "" + browseDisplayName; x.Description = new LocalizedText("en", browseDisplayName); x.DataType = dataTypeId; if (valueRank > -2) { x.ValueRank = valueRank; } // ReSharper disable once RedundantCast x.Value = (T)value; AasUaNodeHelper.CheckSetModellingRule(modellingRule, x); x.NodeId = nodeMgr.New(nodeMgr.SystemContext, mode, x); // add Node nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, x); if (parent != null) { parent.AddChild(x); } // set relations if (referenceTypeFromParentId != null) { if (parent != null) { parent.AddReference(referenceTypeFromParentId, false, x.NodeId); if (referenceTypeFromParentId == ReferenceTypeIds.HasComponent) { x.AddReference(referenceTypeFromParentId, true, parent.NodeId); } if (referenceTypeFromParentId == ReferenceTypeIds.HasProperty) { x.AddReference(referenceTypeFromParentId, true, parent.NodeId); } } } if (typeDefinitionId != null) { x.TypeDefinitionId = typeDefinitionId; } x.AccessLevel = AccessLevels.CurrentReadOrWrite; x.UserAccessLevel = AccessLevels.CurrentReadOrWrite; return(x); }
/// <summary> /// Imports a node from the set. /// </summary> private NodeState Import(ISystemContext context, UANode node) { NodeState importedNode = null; NodeClass nodeClass = NodeClass.Unspecified; if (node is UAObject) { nodeClass = NodeClass.Object; } else if (node is UAVariable) { nodeClass = NodeClass.Variable; } else if (node is UAMethod) { nodeClass = NodeClass.Method; } else if (node is UAObjectType) { nodeClass = NodeClass.ObjectType; } else if (node is UAVariableType) { nodeClass = NodeClass.VariableType; } else if (node is UADataType) { nodeClass = NodeClass.DataType; } else if (node is UAReferenceType) { nodeClass = NodeClass.ReferenceType; } else if (node is UAView) { nodeClass = NodeClass.View; } switch (nodeClass) { case NodeClass.Object: { UAObject o = (UAObject)node; BaseObjectState value = new BaseObjectState(null); value.EventNotifier = o.EventNotifier; importedNode = value; break; } case NodeClass.Variable: { UAVariable o = (UAVariable)node; NodeId typeDefinitionId = null; if (node.References != null) { for (int ii = 0; ii < node.References.Length; ii++) { Opc.Ua.NodeId referenceTypeId = ImportNodeId(node.References[ii].ReferenceType, context.NamespaceUris, true); bool isInverse = !node.References[ii].IsForward; Opc.Ua.ExpandedNodeId targetId = ImportExpandedNodeId(node.References[ii].Value, context.NamespaceUris, context.ServerUris); if (referenceTypeId == ReferenceTypeIds.HasTypeDefinition && !isInverse) { typeDefinitionId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); break; } } } BaseVariableState value = null; if (typeDefinitionId == Opc.Ua.VariableTypeIds.PropertyType) { value = new PropertyState(null); } else { value = new BaseDataVariableState(null); } value.DataType = ImportNodeId(o.DataType, context.NamespaceUris, true); value.ValueRank = o.ValueRank; value.ArrayDimensions = ImportArrayDimensions(o.ArrayDimensions); value.AccessLevelEx = o.AccessLevel; value.UserAccessLevel = (byte)(o.AccessLevel & 0xFF); value.MinimumSamplingInterval = o.MinimumSamplingInterval; value.Historizing = o.Historizing; if (o.Value != null) { XmlDecoder decoder = CreateDecoder(context, o.Value); TypeInfo typeInfo = null; value.Value = decoder.ReadVariantContents(out typeInfo); decoder.Close(); } importedNode = value; break; } case NodeClass.Method: { UAMethod o = (UAMethod)node; MethodState value = new MethodState(null); value.Executable = o.Executable; value.UserExecutable = o.Executable; value.TypeDefinitionId = ImportNodeId(o.MethodDeclarationId, context.NamespaceUris, true); importedNode = value; break; } case NodeClass.View: { UAView o = (UAView)node; ViewState value = new ViewState(); value.ContainsNoLoops = o.ContainsNoLoops; importedNode = value; break; } case NodeClass.ObjectType: { UAObjectType o = (UAObjectType)node; BaseObjectTypeState value = new BaseObjectTypeState(); value.IsAbstract = o.IsAbstract; importedNode = value; break; } case NodeClass.VariableType: { UAVariableType o = (UAVariableType)node; BaseVariableTypeState value = new BaseDataVariableTypeState(); value.IsAbstract = o.IsAbstract; value.DataType = ImportNodeId(o.DataType, context.NamespaceUris, true); value.ValueRank = o.ValueRank; value.ArrayDimensions = ImportArrayDimensions(o.ArrayDimensions); if (o.Value != null) { XmlDecoder decoder = CreateDecoder(context, o.Value); TypeInfo typeInfo = null; value.Value = decoder.ReadVariantContents(out typeInfo); decoder.Close(); } importedNode = value; break; } case NodeClass.DataType: { UADataType o = (UADataType)node; DataTypeState value = new DataTypeState(); value.IsAbstract = o.IsAbstract; Opc.Ua.DataTypeDefinition dataTypeDefinition = Import(o, o.Definition, context.NamespaceUris); value.DataTypeDefinition = new ExtensionObject(dataTypeDefinition); value.Purpose = o.Purpose; value.DataTypeModifier = DataTypeModifier.None; if (o.Definition != null) { if (o.Definition.IsOptionSet) { value.DataTypeModifier = DataTypeModifier.OptionSet; } else if (o.Definition.IsUnion) { value.DataTypeModifier = DataTypeModifier.Union; } } importedNode = value; break; } case NodeClass.ReferenceType: { UAReferenceType o = (UAReferenceType)node; ReferenceTypeState value = new ReferenceTypeState(); value.IsAbstract = o.IsAbstract; value.InverseName = Import(o.InverseName); value.Symmetric = o.Symmetric; importedNode = value; break; } } importedNode.NodeId = ImportNodeId(node.NodeId, context.NamespaceUris, false); importedNode.BrowseName = ImportQualifiedName(node.BrowseName, context.NamespaceUris); importedNode.DisplayName = Import(node.DisplayName); if (importedNode.DisplayName == null) { importedNode.DisplayName = new Ua.LocalizedText(importedNode.BrowseName.Name); } importedNode.Description = Import(node.Description); importedNode.Categories = (node.Category != null && node.Category.Length > 0) ? node.Category : null; importedNode.ReleaseStatus = node.ReleaseStatus; importedNode.WriteMask = (AttributeWriteMask)node.WriteMask; importedNode.UserWriteMask = (AttributeWriteMask)node.UserWriteMask; importedNode.Extensions = node.Extensions; if (!String.IsNullOrEmpty(node.SymbolicName)) { importedNode.SymbolicName = node.SymbolicName; } if (node.References != null) { BaseInstanceState instance = importedNode as BaseInstanceState; BaseTypeState type = importedNode as BaseTypeState; for (int ii = 0; ii < node.References.Length; ii++) { Opc.Ua.NodeId referenceTypeId = ImportNodeId(node.References[ii].ReferenceType, context.NamespaceUris, true); bool isInverse = !node.References[ii].IsForward; Opc.Ua.ExpandedNodeId targetId = ImportExpandedNodeId(node.References[ii].Value, context.NamespaceUris, context.ServerUris); if (instance != null) { if (referenceTypeId == ReferenceTypeIds.HasModellingRule && !isInverse) { instance.ModellingRuleId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); continue; } if (referenceTypeId == ReferenceTypeIds.HasTypeDefinition && !isInverse) { instance.TypeDefinitionId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); continue; } } if (type != null) { if (referenceTypeId == ReferenceTypeIds.HasSubtype && isInverse) { type.SuperTypeId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); continue; } } importedNode.AddReference(referenceTypeId, isInverse, targetId); } } return(importedNode); }
/// <summary> /// Adds a root notifier. /// </summary> /// <param name="notifier">The notifier.</param> /// <remarks> /// A root notifier is a notifier owned by the NodeManager that is not the target of a /// HasNotifier reference. These nodes need to be linked directly to the Server object. /// </remarks> protected virtual void AddRootNotifier(NodeState notifier) { if (m_rootNotifiers == null) { m_rootNotifiers = new List<NodeState>(); } for (int ii = 0; ii < m_rootNotifiers.Count; ii++) { if (Object.ReferenceEquals(notifier, m_rootNotifiers[ii])) { return; } } m_rootNotifiers.Add(notifier); // need to prevent recursion with the server object. if (notifier.NodeId != ObjectIds.Server) { notifier.OnReportEvent = OnReportEvent; if (!notifier.ReferenceExists(ReferenceTypeIds.HasNotifier, true, ObjectIds.Server)) { notifier.AddReference(ReferenceTypeIds.HasNotifier, true, ObjectIds.Server); } } // subscribe to existing events. if (m_server.EventManager != null) { IList<IEventMonitoredItem> monitoredItems = m_server.EventManager.GetMonitoredItems(); for (int ii = 0; ii < monitoredItems.Count; ii++) { if (monitoredItems[ii].MonitoringAllEvents) { SubscribeToEvents( SystemContext, notifier, monitoredItems[ii], true); } } } }
/// <summary> /// Creates a new view. /// </summary> private ViewState CreateView(NodeState parent, IDictionary<NodeId, IList<IReference>> externalReferences, string path, string name) { ViewState type = new ViewState(); type.SymbolicName = name; type.NodeId = new NodeId(path, NamespaceIndex); type.BrowseName = new QualifiedName(name, NamespaceIndex); type.DisplayName = type.BrowseName.Name; type.WriteMask = AttributeWriteMask.None; type.UserWriteMask = AttributeWriteMask.None; type.ContainsNoLoops = true; IList<IReference> references = null; if (!externalReferences.TryGetValue(ObjectIds.ViewsFolder, out references)) { externalReferences[ObjectIds.ViewsFolder] = references = new List<IReference>(); } type.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ViewsFolder); references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, type.NodeId)); if (parent != null) { parent.AddReference(ReferenceTypes.Organizes, false, type.NodeId); type.AddReference(ReferenceTypes.Organizes, true, parent.NodeId); } AddPredefinedNode(SystemContext, type); return type; }
/// <summary> /// Creates a new reference type. /// </summary> private ReferenceTypeState CreateReferenceType(NodeState parent, IDictionary<NodeId, IList<IReference>> externalReferences, string path, string name) { ReferenceTypeState type = new ReferenceTypeState(); type.SymbolicName = name; type.SuperTypeId = ReferenceTypeIds.NonHierarchicalReferences; type.NodeId = new NodeId(path, NamespaceIndex); type.BrowseName = new QualifiedName(name, NamespaceIndex); type.DisplayName = type.BrowseName.Name; type.WriteMask = AttributeWriteMask.None; type.UserWriteMask = AttributeWriteMask.None; type.IsAbstract = false; type.Symmetric = true; type.InverseName = name; IList<IReference> references = null; if (!externalReferences.TryGetValue(ReferenceTypeIds.NonHierarchicalReferences, out references)) { externalReferences[ReferenceTypeIds.NonHierarchicalReferences] = references = new List<IReference>(); } references.Add(new NodeStateReference(ReferenceTypeIds.HasSubtype, false, type.NodeId)); if (parent != null) { parent.AddReference(ReferenceTypes.Organizes, false, type.NodeId); type.AddReference(ReferenceTypes.Organizes, true, parent.NodeId); } AddPredefinedNode(SystemContext, type); return type; }
/// <summary> /// Creates a new variable type. /// </summary> private BaseVariableTypeState CreateVariableType(NodeState parent, IDictionary<NodeId, IList<IReference>> externalReferences, string path, string name, BuiltInType dataType, int valueRank) { BaseDataVariableTypeState type = new BaseDataVariableTypeState(); type.SymbolicName = name; type.SuperTypeId = VariableTypeIds.BaseDataVariableType; type.NodeId = new NodeId(path, NamespaceIndex); type.BrowseName = new QualifiedName(name, NamespaceIndex); type.DisplayName = type.BrowseName.Name; type.WriteMask = AttributeWriteMask.None; type.UserWriteMask = AttributeWriteMask.None; type.IsAbstract = false; type.DataType = (uint)dataType; type.ValueRank = valueRank; type.Value = null; IList<IReference> references = null; if (!externalReferences.TryGetValue(VariableTypeIds.BaseDataVariableType, out references)) { externalReferences[VariableTypeIds.BaseDataVariableType] = references = new List<IReference>(); } references.Add(new NodeStateReference(ReferenceTypes.HasSubtype, false, type.NodeId)); if (parent != null) { parent.AddReference(ReferenceTypes.Organizes, false, type.NodeId); type.AddReference(ReferenceTypes.Organizes, true, parent.NodeId); } AddPredefinedNode(SystemContext, type); return type; }