/// <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> /// 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 } }