/// <summary> /// Creates a new alarm for the source. /// </summary> /// <param name="alarm">The alarm.</param> /// <param name="branchId">The branch id.</param> /// <returns>The new alarm.</returns> private AlarmConditionState CreateAlarm(UnderlyingSystemAlarm alarm, NodeId branchId) { ISystemContext context = m_nodeManager.SystemContext; AlarmConditionState node = null; // need to map the alarm type to a UA defined alarm type. switch (alarm.AlarmType) { case "HighAlarm": { ExclusiveDeviationAlarmState node2 = new ExclusiveDeviationAlarmState(this); node = node2; node2.HighLimit = new PropertyState<double>(node2); break; } case "HighLowAlarm": { NonExclusiveLevelAlarmState node2 = new NonExclusiveLevelAlarmState(this); node = node2; node2.HighHighLimit = new PropertyState<double>(node2); node2.HighLimit = new PropertyState<double>(node2); node2.LowLimit = new PropertyState<double>(node2); node2.LowLowLimit = new PropertyState<double>(node2); node2.HighHighState = new TwoStateVariableState(node2); node2.HighState = new TwoStateVariableState(node2); node2.LowState = new TwoStateVariableState(node2); node2.LowLowState = new TwoStateVariableState(node2); break; } case "TripAlarm": { node = new TripAlarmState(this); break; } default: { node = new AlarmConditionState(this); break; } } node.SymbolicName = alarm.Name; // add optional components. node.Comment = new ConditionVariableState<LocalizedText>(node); node.ClientUserId = new PropertyState<string>(node); node.AddComment = new AddCommentMethodState(node); node.ConfirmedState = new TwoStateVariableState(node); node.Confirm = new AddCommentMethodState(node); if (NodeId.IsNull(branchId)) { node.SuppressedState = new TwoStateVariableState(node); node.ShelvingState = new ShelvedStateMachineState(node); } // adding optional components to children is a little more complicated since the // necessary initilization strings defined by the class that represents the child. // in this case we pre-create the child, add the optional components // and call create without assigning NodeIds. The NodeIds will be assigned when the // parent object is created. node.EnabledState = new TwoStateVariableState(node); node.EnabledState.TransitionTime = new PropertyState<DateTime>(node.EnabledState); node.EnabledState.EffectiveDisplayName = new PropertyState<LocalizedText>(node.EnabledState); node.EnabledState.Create(context, null, BrowseNames.EnabledState, null, false); // same procedure add optional components to the ActiveState component. node.ActiveState = new TwoStateVariableState(node); node.ActiveState.TransitionTime = new PropertyState<DateTime>(node.ActiveState); node.ActiveState.EffectiveDisplayName = new PropertyState<LocalizedText>(node.ActiveState); node.ActiveState.Create(context, null, BrowseNames.ActiveState, null, false); // specify reference type between the source and the alarm. node.ReferenceTypeId = ReferenceTypeIds.HasComponent; // This call initializes the condition from the type model (i.e. creates all of the objects // and variables requried to store its state). The information about the type model was // incorporated into the class when the class was created. // // This method also assigns new NodeIds to all of the components by calling the INodeIdFactory.New // method on the INodeIdFactory object which is part of the system context. The NodeManager provides // the INodeIdFactory implementation used here. node.Create( context, null, new QualifiedName(alarm.Name, this.BrowseName.NamespaceIndex), null, true); // don't add branches to the address space. if (NodeId.IsNull(branchId)) { this.AddChild(node); } // initialize event information.node node.EventType.Value = node.TypeDefinitionId; node.SourceNode.Value = this.NodeId; node.SourceName.Value = this.SymbolicName; node.ConditionName.Value = node.SymbolicName; node.Time.Value = DateTime.UtcNow; node.ReceiveTime.Value = node.Time.Value; node.LocalTime.Value = Utils.GetTimeZoneInfo(); node.BranchId.Value = branchId; // set up method handlers. node.OnEnableDisable = OnEnableDisableAlarm; node.OnAcknowledge = OnAcknowledge; node.OnAddComment = OnAddComment; node.OnConfirm = OnConfirm; node.OnShelve = OnShelve; node.OnTimedUnshelve = OnTimedUnshelve; // return the new node. return node; }
/// <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) { // check if the type model needs to be loaded. if (NamespaceIndexes.Length > 1) { LoadPredefinedNodes(SystemContext, externalReferences); } IList<IReference> references = null; // create the root node. string serverName = m_configuration.ServerName; if (String.IsNullOrEmpty(serverName)) { serverName = "ComAeServer"; } AeAreaState root = new AeAreaState(SystemContext, String.Empty, serverName, NamespaceIndex); root.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); // link root to objects folder. if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) { externalReferences[ObjectIds.ObjectsFolder] = references = new List<IReference>(); } references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, root.NodeId)); // link root 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)); // create the status node. ComServerStatusState status = new ComServerStatusState(root); status.ReferenceTypeId = ReferenceTypeIds.Organizes; // get the type namepace for the browse name. int typeNamepaceIndex = Server.NamespaceUris.GetIndex(Namespaces.ComInterop); if (typeNamepaceIndex < 0) { typeNamepaceIndex = NamespaceIndex; } status.Create( SystemContext, AeModelUtils.ConstructIdForInternalNode("ServerStatus", NamespaceIndex), new QualifiedName("ServerStatus", (ushort)typeNamepaceIndex), null, true); root.AddChild(status); // store root folder in the pre-defined nodes. AddPredefinedNode(SystemContext, root); AddRootNotifier(root); // create the COM server. m_system.Initialize(SystemContext, m_configuration, status, Lock, OnServerReconnected); // create a template condition that can be used to initialize static metadata. m_templateAlarm = new AlarmConditionState(null); m_templateAlarm.SymbolicName = "TemplateAlarm"; m_templateAlarm.Create( SystemContext, null, new QualifiedName(m_templateAlarm.SymbolicName, NamespaceIndex), null, false); m_templateAlarm.Acknowledge.OnCall = OnAcknowledge; StartMetadataUpdates(DoMetadataUpdate, null, 5000, m_configuration.MaxReconnectWait); } }