/// <summary> /// Creates a snapshot of a node. /// </summary> /// <param name="context">The context.</param> /// <param name="state">The state.</param> /// <returns>A snapshot of a node.</returns> private ChildNode CreateChildNode(ISystemContext context, BaseInstanceState state) { ChildNode node = new ChildNode(); node.NodeClass = state.NodeClass; node.BrowseName = state.BrowseName; BaseVariableState variable = state as BaseVariableState; if (variable != null) { if (!StatusCode.IsBad(variable.StatusCode)) { node.Value = Utils.Clone(variable.Value); } } BaseObjectState instance = state as BaseObjectState; if (instance != null) { node.Value = instance.NodeId; } node.Children = CreateChildNodes(context, state); return(node); }
/// <summary> /// Initializes the instance from another instance. /// </summary> protected override void Initialize(ISystemContext context, NodeState source) { BaseObjectState instance = source as BaseObjectState; if (instance != null) { m_eventNotifier = instance.m_eventNotifier; } base.Initialize(context, source); }
/// <summary> /// Creates a new instance. /// </summary> /// <param name="context">The current context.</param> /// <param name="parent">The parent.</param> /// <param name="nodeClass">The node class.</param> /// <param name="browseName">The browse name.</param> /// <param name="referenceTypeId">The reference type between the parent and the node.</param> /// <param name="typeDefinitionId">The type definition.</param> /// <returns>Returns null if the type is not known.</returns> public virtual NodeState CreateInstance( ISystemContext context, NodeState parent, NodeClass nodeClass, QualifiedName browseName, NodeId referenceTypeId, NodeId typeDefinitionId) { NodeState child = null; if (m_types != null && !NodeId.IsNull(typeDefinitionId)) { Type type = null; if (m_types.TryGetValue(typeDefinitionId, out type)) { return(Activator.CreateInstance(type, parent) as NodeState); } } switch (nodeClass) { case NodeClass.Variable: { if (context.TypeTable != null && context.TypeTable.IsTypeOf(referenceTypeId, ReferenceTypeIds.HasProperty)) { child = new PropertyState(parent); break; } child = new BaseDataVariableState(parent); break; } case NodeClass.Object: { child = new BaseObjectState(parent); break; } case NodeClass.Method: { child = new MethodState(parent); break; } case NodeClass.ReferenceType: { child = new ReferenceTypeState(); break; } case NodeClass.ObjectType: { child = new BaseObjectTypeState(); break; } case NodeClass.VariableType: { child = new BaseDataVariableTypeState(); break; } case NodeClass.DataType: { child = new DataTypeState(); break; } case NodeClass.View: { child = new ViewState(); break; } default: { child = null; break; } } return(child); }
/// <summary> /// Initializes the instance from an event notification. /// </summary> /// <param name="context">The context.</param> /// <param name="fields">The fields selected for the event notification.</param> /// <param name="e">The event notification.</param> /// <remarks> /// This method creates components based on the browse paths in the event field and sets /// the NodeId or Value based on values in the event notification. /// </remarks> public void Update( ISystemContext context, SimpleAttributeOperandCollection fields, EventFieldList e) { for (int ii = 0; ii < fields.Count; ii++) { SimpleAttributeOperand field = fields[ii]; object value = e.EventFields[ii].Value; // check if value provided. if (value == null) { continue; } // extract the NodeId for the event. if (field.BrowsePath.Count == 0) { if (field.AttributeId == Attributes.NodeId) { this.NodeId = value as NodeId; continue; } } // extract the type definition for the event. if (field.BrowsePath.Count == 1) { if (field.AttributeId == Attributes.Value) { if (field.BrowsePath[0] == BrowseNames.EventType) { m_typeDefinitionId = value as NodeId; continue; } } } // save value for child node. NodeState parent = this; for (int jj = 0; jj < field.BrowsePath.Count; jj++) { // find a predefined child identified by the browse name. BaseInstanceState child = parent.CreateChild(context, field.BrowsePath[jj]); // create a placeholder for unknown children. if (child == null) { if (field.AttributeId == Attributes.Value) { child = new BaseDataVariableState(parent); } else { child = new BaseObjectState(parent); } parent.AddChild(child); } // ensure the browse name is set. if (QualifiedName.IsNull(child.BrowseName)) { child.BrowseName = field.BrowsePath[jj]; } // ensure the display name is set. if (LocalizedText.IsNullOrEmpty(child.DisplayName)) { child.DisplayName = child.BrowseName.Name; } // process next element in path. if (jj < field.BrowsePath.Count-1) { parent = child; continue; } // save the variable value. if (field.AttributeId == Attributes.Value) { BaseVariableState variable = child as BaseVariableState; if (variable != null && field.AttributeId == Attributes.Value) { try { variable.WrappedValue = e.EventFields[ii]; } catch (Exception) { variable.Value = null; } } break; } // save the node id. child.NodeId = value as NodeId; } } }
/// <summary> /// Initializes the instance from an event notification. /// </summary> /// <param name="context">The context.</param> /// <param name="fields">The fields selected for the event notification.</param> /// <param name="e">The event notification.</param> /// <remarks> /// This method creates components based on the browse paths in the event field and sets /// the NodeId or Value based on values in the event notification. /// </remarks> public void Update( ISystemContext context, SimpleAttributeOperandCollection fields, EventFieldList e) { for (int ii = 0; ii < fields.Count; ii++) { SimpleAttributeOperand field = fields[ii]; object value = e.EventFields[ii].Value; // check if value provided. if (value == null) { continue; } // extract the NodeId for the event. if (field.BrowsePath.Count == 0) { if (field.AttributeId == Attributes.NodeId) { this.NodeId = value as NodeId; continue; } } // extract the type definition for the event. if (field.BrowsePath.Count == 1) { if (field.AttributeId == Attributes.Value) { if (field.BrowsePath[0] == BrowseNames.EventType) { m_typeDefinitionId = value as NodeId; continue; } } } // save value for child node. NodeState parent = this; for (int jj = 0; jj < field.BrowsePath.Count; jj++) { // find a predefined child identified by the browse name. BaseInstanceState child = parent.CreateChild(context, field.BrowsePath[jj]); // create a placeholder for unknown children. if (child == null) { if (field.AttributeId == Attributes.Value) { child = new BaseDataVariableState(parent); } else { child = new BaseObjectState(parent); } parent.AddChild(child); } // ensure the browse name is set. if (QualifiedName.IsNull(child.BrowseName)) { child.BrowseName = field.BrowsePath[jj]; } // ensure the display name is set. if (LocalizedText.IsNullOrEmpty(child.DisplayName)) { child.DisplayName = child.BrowseName.Name; } // process next element in path. if (jj < field.BrowsePath.Count - 1) { parent = child; continue; } // save the variable value. if (field.AttributeId == Attributes.Value) { BaseVariableState variable = child as BaseVariableState; if (variable != null && field.AttributeId == Attributes.Value) { try { variable.WrappedValue = e.EventFields[ii]; } catch (Exception) { variable.Value = null; } } break; } // save the node id. child.NodeId = value as NodeId; } } }
/// <summary> /// Creates a new well. /// </summary> private void CreateWell(SystemContext context, BaseObjectState area, string wellId, string wellName) { WellState well = new WellState(null); well.NodeId = new NodeId(wellId, NamespaceIndex); well.BrowseName = new QualifiedName(wellName, NamespaceIndex); well.DisplayName = wellName; well.EventNotifier = EventNotifiers.SubscribeToEvents | EventNotifiers.HistoryRead | EventNotifiers.HistoryWrite; well.TypeDefinitionId = new NodeId(ObjectTypes.WellType, NamespaceIndex); area.AddNotifier(SystemContext, Opc.Ua.ReferenceTypeIds.HasNotifier, false, well); well.AddNotifier(SystemContext, Opc.Ua.ReferenceTypeIds.HasNotifier, true, area); AddPredefinedNode(SystemContext, well); }
/// <summary> /// Verifies that the specified node exists. /// </summary> protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary<NodeId, NodeState> cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } // lookup in operation cache. NodeState target = FindNodeInCache(context, handle, cache); if (target != null) { handle.Node = target; handle.Validated = true; return handle.Node; } try { Opc.Ua.Client.Session client = GetClientSession(context); // get remote node. NodeId targetId = m_mapper.ToRemoteId(handle.NodeId); ILocalNode node = client.ReadNode(targetId) as ILocalNode; if (node == null) { return null; } // map remote node to local object. switch (node.NodeClass) { case NodeClass.ObjectType: { BaseObjectTypeState value = new BaseObjectTypeState(); value.IsAbstract = ((IObjectType)node).IsAbstract; target = value; break; } case NodeClass.VariableType: { BaseVariableTypeState value = new BaseDataVariableTypeState(); value.IsAbstract = ((IVariableType)node).IsAbstract; value.Value = m_mapper.ToLocalValue(((IVariableType)node).Value); value.DataType = m_mapper.ToLocalId(((IVariableType)node).DataType); value.ValueRank = ((IVariableType)node).ValueRank; value.ArrayDimensions = new ReadOnlyList<uint>(((IVariableType)node).ArrayDimensions); target = value; break; } case NodeClass.DataType: { DataTypeState value = new DataTypeState(); value.IsAbstract = ((IDataType)node).IsAbstract; target = value; break; } case NodeClass.ReferenceType: { ReferenceTypeState value = new ReferenceTypeState(); value.IsAbstract = ((IReferenceType)node).IsAbstract; value.InverseName = ((IReferenceType)node).InverseName; value.Symmetric = ((IReferenceType)node).Symmetric; target = value; break; } case NodeClass.Object: { BaseObjectState value = new BaseObjectState(null); value.EventNotifier = ((IObject)node).EventNotifier; target = value; break; } case NodeClass.Variable: { BaseDataVariableState value = new BaseDataVariableState(null); value.Value = m_mapper.ToLocalValue(((IVariable)node).Value); value.DataType = m_mapper.ToLocalId(((IVariable)node).DataType); value.ValueRank = ((IVariable)node).ValueRank; value.ArrayDimensions = new ReadOnlyList<uint>(((IVariable)node).ArrayDimensions); value.AccessLevel = ((IVariable)node).AccessLevel; value.UserAccessLevel = ((IVariable)node).UserAccessLevel; value.Historizing = ((IVariable)node).Historizing; value.MinimumSamplingInterval = ((IVariable)node).MinimumSamplingInterval; target = value; break; } case NodeClass.Method: { MethodState value = new MethodState(null); value.Executable = ((IMethod)node).Executable; value.UserExecutable = ((IMethod)node).UserExecutable; target = value; break; } case NodeClass.View: { ViewState value = new ViewState(); value.ContainsNoLoops = ((IView)node).ContainsNoLoops; target = value; break; } } target.NodeId = handle.NodeId; target.BrowseName = m_mapper.ToLocalName(node.BrowseName); target.DisplayName = node.DisplayName; target.Description = node.Description; target.WriteMask = node.WriteMask; target.UserWriteMask = node.UserWriteMask; target.Handle = node; target.OnCreateBrowser = OnCreateBrowser; } // ignore errors. catch { return null; } // put root into operation cache. if (cache != null) { cache[handle.NodeId] = target; } handle.Node = target; handle.Validated = true; return handle.Node; }
/// <summary> /// Finds the child with the specified browse name. /// </summary> protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Quickstarts.Views.BrowseNames.WaterIn: { if (createOrReplace) { if (WaterIn == null) { if (replacement == null) { WaterIn = new BaseObjectState(this); } else { WaterIn = (BaseObjectState)replacement; } } } instance = WaterIn; break; } case Quickstarts.Views.BrowseNames.SteamOut: { if (createOrReplace) { if (SteamOut == null) { if (replacement == null) { SteamOut = new BaseObjectState(this); } else { SteamOut = (BaseObjectState)replacement; } } } instance = SteamOut; break; } case Quickstarts.Views.BrowseNames.Drum: { if (createOrReplace) { if (Drum == null) { if (replacement == null) { Drum = new BaseObjectState(this); } else { Drum = (BaseObjectState)replacement; } } } instance = Drum; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); }
/// <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) { BaseObjectState trigger = new BaseObjectState(null); trigger.NodeId = new NodeId(1, NamespaceIndex); trigger.BrowseName = new QualifiedName("Trigger", NamespaceIndex); trigger.DisplayName = trigger.BrowseName.Name; trigger.TypeDefinitionId = ObjectTypeIds.BaseObjectType; // ensure trigger can be found via the server object. IList<IReference> references = null; if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) { externalReferences[ObjectIds.ObjectsFolder] = references = new List<IReference>(); } trigger.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, trigger.NodeId)); PropertyState property = new PropertyState(trigger); property.NodeId = new NodeId(2, NamespaceIndex); property.BrowseName = new QualifiedName("Matrix", NamespaceIndex); property.DisplayName = property.BrowseName.Name; property.TypeDefinitionId = VariableTypeIds.PropertyType; property.ReferenceTypeId = ReferenceTypeIds.HasProperty; property.DataType = DataTypeIds.Int32; property.ValueRank = ValueRanks.TwoDimensions; property.ArrayDimensions = new ReadOnlyList<uint>(new uint[] { 2, 2 }); trigger.AddChild(property); // save in dictionary. AddPredefinedNode(SystemContext, trigger); ReferenceTypeState referenceType = new ReferenceTypeState(); referenceType.NodeId = new NodeId(3, NamespaceIndex); referenceType.BrowseName = new QualifiedName("IsTriggerSource", NamespaceIndex); referenceType.DisplayName = referenceType.BrowseName.Name; referenceType.InverseName = new LocalizedText("IsSourceOfTrigger"); referenceType.SuperTypeId = ReferenceTypeIds.NonHierarchicalReferences; if (!externalReferences.TryGetValue(ObjectIds.Server, out references)) { externalReferences[ObjectIds.Server] = references = new List<IReference>(); } trigger.AddReference(referenceType.NodeId, false, ObjectIds.Server); references.Add(new NodeStateReference(referenceType.NodeId, true, trigger.NodeId)); // save in dictionary. AddPredefinedNode(SystemContext, referenceType); } }
/// <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) { // create a object to represent the process being controlled. BaseObjectState process = new BaseObjectState(null); process.NodeId = new NodeId(1, NamespaceIndex); process.BrowseName = new QualifiedName("My Process", NamespaceIndex); process.DisplayName = process.BrowseName.Name; process.TypeDefinitionId = ObjectTypeIds.BaseObjectType; // ensure the process object can be found via the server object. IList<IReference> references = null; if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) { externalReferences[ObjectIds.ObjectsFolder] = references = new List<IReference>(); } process.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, process.NodeId)); // a property to report the process state. PropertyState<string> state = new PropertyState<string>(process); state.NodeId = new NodeId(2, NamespaceIndex); state.BrowseName = new QualifiedName("LogFilePath", NamespaceIndex); state.DisplayName = state.BrowseName.Name; state.TypeDefinitionId = VariableTypeIds.PropertyType; state.ReferenceTypeId = ReferenceTypeIds.HasProperty; state.DataType = DataTypeIds.String; state.ValueRank = ValueRanks.Scalar; state.AccessLevel = AccessLevels.CurrentReadOrWrite; state.UserAccessLevel = AccessLevels.CurrentRead; state.Value = ".\\Log.txt"; process.AddChild(state); state.OnReadUserAccessLevel = OnReadUserAccessLevel; state.OnSimpleWriteValue = OnWriteValue; // save in dictionary. AddPredefinedNode(SystemContext, process); } }
/// <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); #region Task #A1 - Create Root Folder // create the root folder. FolderState root = new FolderState(null); root.NodeId = GenerateNodeId(); root.BrowseName = new QualifiedName("Root", NamespaceIndex); root.DisplayName = root.BrowseName.Name; root.TypeDefinitionId = ObjectTypeIds.FolderType; // ensure root can be found via the server object. IList<IReference> references = null; if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) { externalReferences[ObjectIds.ObjectsFolder] = references = new List<IReference>(); } root.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, root.NodeId)); // save the node for later lookup. AddPredefinedNode(SystemContext, root); #endregion #region Task #A2 - Create Object Instance with a Property // create the folder object. BaseObjectState instance = new BaseObjectState(null); instance.NodeId = GenerateNodeId(); instance.BrowseName = new QualifiedName("Object", NamespaceIndex); instance.DisplayName = instance.BrowseName.Name; instance.TypeDefinitionId = ObjectTypeIds.BaseObjectType; // create a losely coupled relationship with the root object. root.AddReference(ReferenceTypeIds.Organizes, false, instance.NodeId); instance.AddReference(ReferenceTypeIds.Organizes, true, root.NodeId); // create a property. PropertyState<int> property = new PropertyState<int>(instance); property.NodeId = GenerateNodeId(); property.BrowseName = new QualifiedName("Property", NamespaceIndex); property.DisplayName = property.BrowseName.Name; property.TypeDefinitionId = VariableTypeIds.PropertyType; property.DataType = DataTypeIds.Int32; property.ValueRank = ValueRanks.Scalar; property.MinimumSamplingInterval = MinimumSamplingIntervals.Continuous; property.AccessLevel = AccessLevels.CurrentReadOrWrite; property.UserAccessLevel = AccessLevels.CurrentReadOrWrite; property.Historizing = false; property.ReferenceTypeId = ReferenceTypeIds.HasProperty; // create a property that is tightly coupled. instance.AddChild(property); // save the node for later lookup (all tightly coupled children are added with this call). AddPredefinedNode(SystemContext, instance); #endregion #region Task #A3 - Create a Variable using the Built-in Type Model // create the variable. AnalogItemState<double> variable = new AnalogItemState<double>(instance); // add optional properties. variable.InstrumentRange = new PropertyState<Range>(variable); // instantiate based on the type model. assigns ids automatically using SystemContext.NodeIdFactory variable.Create( SystemContext, GenerateNodeId(), new QualifiedName("Variable", NamespaceIndex), null, true); // set default values. variable.EURange.Value = new Range(90, 10); variable.InstrumentRange.Value = new Range(100, 0); // tightly coupled. instance.AddChild(variable); // need to add it manually since its parent was already added. AddPredefinedNode(SystemContext, variable); #endregion #region Task #A4 - Add Dynamic Behavoir by Updating In-Memory Nodes m_property = property; m_simulationTimer = new Timer(DoSimulation, null, 1000, 1000); #endregion #region Task #A5 - Add Support for External Nodes // External nodes are nodes that reference an entity which stored elsewhere. // These nodes use no memory in the server unless they are accessed. // The NodeId is a string that is used to create the external node on demand. root.AddReference(ReferenceTypeIds.Organizes, false, CreateNodeId("Alpha")); root.AddReference(ReferenceTypeIds.Organizes, false, CreateNodeId("Omega")); #endregion #region Task #A7 - Add Support for Method MethodState method = new MethodState(instance); method.NodeId = GenerateNodeId(); method.BrowseName = new QualifiedName("Method", NamespaceIndex); method.DisplayName = method.BrowseName.Name; method.Executable = true; method.UserExecutable = true; method.ReferenceTypeId = ReferenceTypeIds.HasComponent; instance.AddChild(method); // create the input arguments. PropertyState<Argument[]> inputArguments = new PropertyState<Argument[]>(method); inputArguments.NodeId = GenerateNodeId(); inputArguments.BrowseName = new QualifiedName(BrowseNames.InputArguments); inputArguments.DisplayName = inputArguments.BrowseName.Name; inputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; inputArguments.DataType = DataTypeIds.Argument; inputArguments.ValueRank = ValueRanks.OneDimension; inputArguments.MinimumSamplingInterval = MinimumSamplingIntervals.Continuous; inputArguments.AccessLevel = AccessLevels.CurrentRead; inputArguments.UserAccessLevel = AccessLevels.CurrentRead; inputArguments.Historizing = false; inputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; inputArguments.Value = new Argument[] { new Argument() { Name = "CurrentCount", Description = "The current count.", DataType = DataTypeIds.Int32, ValueRank = ValueRanks.Scalar } }; method.InputArguments = inputArguments; // create the output arguments. PropertyState<Argument[]> outputArguments = new PropertyState<Argument[]>(method); outputArguments.NodeId = GenerateNodeId(); outputArguments.BrowseName = new QualifiedName(BrowseNames.OutputArguments); outputArguments.DisplayName = outputArguments.BrowseName.Name; outputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; outputArguments.DataType = DataTypeIds.Argument; outputArguments.ValueRank = ValueRanks.OneDimension; outputArguments.MinimumSamplingInterval = MinimumSamplingIntervals.Continuous; outputArguments.AccessLevel = AccessLevels.CurrentRead; outputArguments.UserAccessLevel = AccessLevels.CurrentRead; outputArguments.Historizing = false; outputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; outputArguments.Value = new Argument[] { new Argument() { Name = "NewCount", Description = "The new count.", DataType = DataTypeIds.Int32, ValueRank = ValueRanks.Scalar } }; method.OutputArguments = outputArguments; // save the node for later lookup (all tightly coupled children are added with this call). AddPredefinedNode(SystemContext, instance); // register handler. method.OnCallMethod = new GenericMethodCalledEventHandler(DoMethodCall); #endregion #region Task #D6 - Add Support for Notifiers // enable subscriptions. root.EventNotifier = EventNotifiers.SubscribeToEvents; // creating notifier ensures events propogate up the hierarchy when the are produced. AddRootNotifier(root); // add link to server object. if (!externalReferences.TryGetValue(ObjectIds.Server, out references)) { externalReferences[ObjectIds.Server] = references = new List<IReference>(); } references.Add(new NodeStateReference(ReferenceTypeIds.HasNotifier, false, root.NodeId)); // add sub-notifiers. instance.EventNotifier = EventNotifiers.SubscribeToEvents; instance.AddNotifier(SystemContext, ReferenceTypeIds.HasNotifier, true, root); root.AddNotifier(SystemContext, ReferenceTypeIds.HasNotifier, false, instance); #endregion } }
/// <summary> /// Creates a new object. /// </summary> private BaseObjectState CreateObject(NodeState parent, string path, string name) { BaseObjectState folder = new BaseObjectState(parent); folder.SymbolicName = name; folder.ReferenceTypeId = ReferenceTypes.Organizes; folder.TypeDefinitionId = ObjectTypeIds.BaseObjectType; folder.NodeId = new NodeId(path, NamespaceIndex); folder.BrowseName = new QualifiedName(name, NamespaceIndex); folder.DisplayName = folder.BrowseName.Name; folder.WriteMask = AttributeWriteMask.None; folder.UserWriteMask = AttributeWriteMask.None; folder.EventNotifier = EventNotifiers.None; if (parent != null) { parent.AddChild(folder); } return folder; }
/// <summary> /// Finds the child with the specified browse name. /// </summary> protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Opc.Ua.Di.BrowseNames.ParameterSet: { if (createOrReplace) { if (ParameterSet == null) { if (replacement == null) { ParameterSet = new BaseObjectState(this); } else { ParameterSet = (BaseObjectState)replacement; } } } instance = ParameterSet; break; } case Opc.Ua.Di.BrowseNames.MethodSet: { if (createOrReplace) { if (MethodSet == null) { if (replacement == null) { MethodSet = new BaseObjectState(this); } else { MethodSet = (BaseObjectState)replacement; } } } instance = MethodSet; break; } case Opc.Ua.Di.BrowseNames.Identification: { if (createOrReplace) { if (Identification == null) { if (replacement == null) { Identification = new FunctionalGroupState(this); } else { Identification = (FunctionalGroupState)replacement; } } } instance = Identification; break; } case Opc.Ua.Di.BrowseNames.Lock: { if (createOrReplace) { if (Lock == null) { if (replacement == null) { Lock = new LockingServicesState(this); } else { Lock = (LockingServicesState)replacement; } } } instance = Lock; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); }
/// <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) { // create a object to represent the process being controlled. BaseObjectState process = new BaseObjectState(null); process.NodeId = new NodeId(1, NamespaceIndex); process.BrowseName = new QualifiedName("My Process", NamespaceIndex); process.DisplayName = process.BrowseName.Name; process.TypeDefinitionId = ObjectTypeIds.BaseObjectType; // ensure the process object can be found via the server object. IList<IReference> references = null; if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) { externalReferences[ObjectIds.ObjectsFolder] = references = new List<IReference>(); } process.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, process.NodeId)); // a property to report the process state. PropertyState<uint> state = m_stateNode = new PropertyState<uint>(process); state.NodeId = new NodeId(2, NamespaceIndex); state.BrowseName = new QualifiedName("State", NamespaceIndex); state.DisplayName = state.BrowseName.Name; state.TypeDefinitionId = VariableTypeIds.PropertyType; state.ReferenceTypeId = ReferenceTypeIds.HasProperty; state.DataType = DataTypeIds.UInt32; state.ValueRank = ValueRanks.Scalar; process.AddChild(state); // a method to start the process. MethodState start = new MethodState(process); start.NodeId = new NodeId(3, NamespaceIndex); start.BrowseName = new QualifiedName("Start", NamespaceIndex); start.DisplayName = start.BrowseName.Name; start.ReferenceTypeId = ReferenceTypeIds.HasComponent; start.UserExecutable = true; start.Executable = true; // add input arguments. start.InputArguments = new PropertyState<Argument[]>(start); start.InputArguments.NodeId = new NodeId(4, NamespaceIndex); start.InputArguments.BrowseName = BrowseNames.InputArguments; start.InputArguments.DisplayName = start.InputArguments.BrowseName.Name; start.InputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; start.InputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; start.InputArguments.DataType = DataTypeIds.Argument; start.InputArguments.ValueRank = ValueRanks.OneDimension; Argument[] args = new Argument[2]; args[0] = new Argument(); args[0].Name = "Initial State"; args[0].Description = "The initialize state for the process."; args[0].DataType = DataTypeIds.UInt32; args[0].ValueRank = ValueRanks.Scalar; args[1] = new Argument(); args[1].Name = "Final State"; args[1].Description = "The final state for the process."; args[1].DataType = DataTypeIds.UInt32; args[1].ValueRank = ValueRanks.Scalar; start.InputArguments.Value = args; // add output arguments. start.OutputArguments = new PropertyState<Argument[]>(start); start.OutputArguments.NodeId = new NodeId(5, NamespaceIndex); start.OutputArguments.BrowseName = BrowseNames.OutputArguments; start.OutputArguments.DisplayName = start.OutputArguments.BrowseName.Name; start.OutputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; start.OutputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; start.OutputArguments.DataType = DataTypeIds.Argument; start.OutputArguments.ValueRank = ValueRanks.OneDimension; args = new Argument[2]; args[0] = new Argument(); args[0].Name = "Revised Initial State"; args[0].Description = "The revised initialize state for the process."; args[0].DataType = DataTypeIds.UInt32; args[0].ValueRank = ValueRanks.Scalar; args[1] = new Argument(); args[1].Name = "Revised Final State"; args[1].Description = "The revised final state for the process."; args[1].DataType = DataTypeIds.UInt32; args[1].ValueRank = ValueRanks.Scalar; start.OutputArguments.Value = args; process.AddChild(start); // save in dictionary. AddPredefinedNode(SystemContext, process); // set up method handlers. start.OnCallMethod = new GenericMethodCalledEventHandler(OnStart); } }
/// <summary> /// Creates a new area. /// </summary> private BaseObjectState CreateArea(SystemContext context, BaseObjectState platforms, string areaName) { FolderState area = new FolderState(null); area.NodeId = new NodeId(areaName, NamespaceIndex); area.BrowseName = new QualifiedName(areaName, NamespaceIndex); area.DisplayName = area.BrowseName.Name; area.EventNotifier = EventNotifiers.SubscribeToEvents | EventNotifiers.HistoryRead | EventNotifiers.HistoryWrite; area.TypeDefinitionId = Opc.Ua.ObjectTypeIds.FolderType; platforms.AddNotifier(SystemContext, Opc.Ua.ReferenceTypeIds.HasNotifier, false, area); area.AddNotifier(SystemContext, Opc.Ua.ReferenceTypeIds.HasNotifier, true, platforms); AddPredefinedNode(SystemContext, area); return area; }
/// <summary> /// Gets the supported aggregates. /// </summary> public BaseObjectState[] GetSupportedAggregates(ushort namespaceIndex) { string methodName = "IOPCHDA_Server.GetAggregates"; int pdwCount; IntPtr ppdwAggrID; IntPtr ppszAggrName; IntPtr ppszAggrDesc; try { IOPCHDA_Server server = BeginComCall<IOPCHDA_Server>(methodName, true); server.GetAggregates( out pdwCount, out ppdwAggrID, out ppszAggrName, out ppszAggrDesc); } catch (Exception e) { ComCallError(methodName, e); return null; } finally { EndComCall(methodName); } int[] aggregateIds = ComUtils.GetInt32s(ref ppdwAggrID, pdwCount, true); string[] names = ComUtils.GetUnicodeStrings(ref ppszAggrName, pdwCount, true); string[] descriptions = ComUtils.GetUnicodeStrings(ref ppszAggrDesc, pdwCount, true); BaseObjectState[] results = new BaseObjectState[pdwCount]; for (int ii = 0; ii < results.Length; ii++) { BaseObjectState aggregate = results[ii] = new BaseObjectState(null); aggregate.NodeId = HdaModelUtils.ConstructIdForHdaAggregate(Utils.ToUInt32(aggregateIds[ii]), namespaceIndex); aggregate.SymbolicName = aggregateIds[ii].ToString(); aggregate.BrowseName = new QualifiedName(aggregate.SymbolicName, namespaceIndex); aggregate.DisplayName = names[ii]; aggregate.Description = descriptions[ii]; aggregate.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasComponent; aggregate.TypeDefinitionId = Opc.Ua.ObjectTypeIds.AggregateFunctionType; aggregate.Handle = (uint)aggregateIds[ii]; } return results; }
/// <summary> /// Converts a ReferenceDescription to an IReference. /// </summary> private IReference ToReference(ReferenceDescription reference) { if (reference.NodeId.IsAbsolute || reference.TypeDefinition.IsAbsolute) { return new NodeStateReference(reference.ReferenceTypeId, !reference.IsForward, reference.NodeId); } if (m_source != null && (reference.NodeId == ObjectIds.ObjectsFolder || reference.NodeId == ObjectIds.Server)) { return new NodeStateReference(reference.ReferenceTypeId, !reference.IsForward, m_rootId); } NodeState target = null; switch (reference.NodeClass) { case NodeClass.DataType: { target = new DataTypeState(); break; } case NodeClass.Method: { target = new MethodState(null); break; } case NodeClass.Object: { target = new BaseObjectState(null); break; } case NodeClass.ObjectType: { target = new BaseObjectTypeState(); break; } case NodeClass.ReferenceType: { target = new ReferenceTypeState(); break; } case NodeClass.Variable: { target = new BaseDataVariableState(null); break; } case NodeClass.VariableType: { target = new BaseDataVariableTypeState(); break; } case NodeClass.View: { target = new ViewState(); break; } } target.NodeId = m_mapper.ToLocalId((NodeId)reference.NodeId); target.BrowseName = m_mapper.ToLocalName(reference.BrowseName); target.DisplayName = reference.DisplayName; if (target is BaseInstanceState) { ((BaseInstanceState)target).TypeDefinitionId = m_mapper.ToLocalId((NodeId)reference.TypeDefinition); } return new NodeStateReference(reference.ReferenceTypeId, !reference.IsForward, target); }