/// <summary> /// Subscribes or unsubscribes to events produced an event source. /// </summary> public override ServiceResult SubscribeToEvents( OperationContext context, object sourceId, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { ServerSystemContext systemContext = SystemContext.Copy(context); // send request to external system. try { MonitoredItem localItem = monitoredItem as MonitoredItem; if (localItem == null) { return ServiceResult.Good; } Opc.Ua.Client.Session client = GetClientSession(systemContext); if (unsubscribe) { lock (client) { // get the subscription. Opc.Ua.Client.Subscription target = null; foreach (Opc.Ua.Client.Subscription current in client.Subscriptions) { target = current; break; } if (target == null) { return ServiceResult.Good; } // find matching item. Opc.Ua.Client.MonitoredItem remoteItem = target.FindItemByClientHandle(monitoredItem.Id); if (remoteItem == null) { return ServiceResult.Good; } // apply changes. target.RemoveItem(remoteItem); target.ApplyChanges(); if (target.MonitoredItemCount == 0) { target.Session.RemoveSubscription(target); } } return ServiceResult.Good; } // create a request. Opc.Ua.Client.MonitoredItem request = new Opc.Ua.Client.MonitoredItem(localItem.Id); if (localItem.NodeId == ObjectIds.Server || localItem.NodeId == m_root.NodeId) { request.StartNodeId = ObjectIds.Server; } else { request.StartNodeId = m_mapper.ToRemoteId(localItem.NodeId); } request.AttributeId = Attributes.EventNotifier; request.MonitoringMode = localItem.MonitoringMode; request.SamplingInterval = (int)localItem.SamplingInterval; request.QueueSize = localItem.QueueSize; request.DiscardOldest = true; request.Filter = localItem.Filter; request.Handle = localItem; lock (client) { // create subscription. if (client.SubscriptionCount == 0) { Opc.Ua.Client.Subscription subscription = new Opc.Ua.Client.Subscription(); subscription.PublishingInterval = 250; subscription.KeepAliveCount = 100; subscription.LifetimeCount = 1000; subscription.MaxNotificationsPerPublish = 10000; subscription.Priority = 1; subscription.PublishingEnabled = true; subscription.TimestampsToReturn = TimestampsToReturn.Both; subscription.DisableMonitoredItemCache = true; subscription.FastDataChangeCallback = OnDataChangeNotification; subscription.FastEventCallback = OnEventNotification; client.AddSubscription(subscription); subscription.Create(); } // get the subscription. Opc.Ua.Client.Subscription target = null; foreach (Opc.Ua.Client.Subscription current in client.Subscriptions) { target = current; break; } if (target == null) { return ServiceResult.Good; } target.AddItem(request); target.ApplyChanges(); if (ServiceResult.IsBad(request.Status.Error)) { Utils.Trace((int)Utils.TraceMasks.Error, "Could not create event item. {0}", request.Status.Error.ToLongString()); } } } catch (Exception e) { Utils.Trace(e, "Could not access external system."); } return ServiceResult.Good; }
/// <summary> /// Reports an event produced by the object. /// </summary> public virtual void ReportEvent(BaseEvent e) { lock (DataLock) { if (m_reportEventsToParent) { ObjectSource parent = Parent as ObjectSource; if (parent != null) { parent.ReportEvent(e); } } List <IEventMonitoredItem> monitoredItems = new List <IEventMonitoredItem>(); if (MonitoredItems != null) { foreach (IMonitoredItem monitoredItem in MonitoredItems) { IEventMonitoredItem eventItem = monitoredItem as IEventMonitoredItem; if (eventItem != null) { monitoredItems.Add(eventItem); } } if (monitoredItems.Count > 0) { EventManager.ReportEvent(e, monitoredItems); } } } }
/// <summary> /// Called when a Node produces an event. /// </summary> /// <param name="context">The system context.</param> /// <param name="node">The affected node.</param> /// <param name="e">The event.</param> public void OnReportEvent(ISystemContext context, NodeState node, IFilterTarget e) { List <IEventMonitoredItem> eventMonitoredItems = new List <IEventMonitoredItem>(); lock (NodeManager.Lock) { if (EventMonitoredItems == null) { return; } for (int ii = 0; ii < EventMonitoredItems.Count; ii++) { IEventMonitoredItem monitoredItem = EventMonitoredItems[ii]; // enqueue event for role permission validation eventMonitoredItems.Add(monitoredItem); } } for (int ii = 0; ii < eventMonitoredItems.Count; ii++) { IEventMonitoredItem monitoredItem = eventMonitoredItems[ii]; #region Filter out audit events in case the Server_Auditing values is false or the channel is not encrypted if (e is AuditEventState) { // check Server.Auditing flag and skip if false if (!NodeManager.Server.Auditing) { continue; } else { // check if channel is not encrypted and skip if so if (monitoredItem?.Session?.EndpointDescription?.SecurityMode != MessageSecurityMode.SignAndEncrypt && monitoredItem?.Session?.EndpointDescription?.TransportProfileUri != Profiles.HttpsBinaryTransport) { continue; } } } #endregion // validate if the monitored item has the required role permissions to receive the event ServiceResult validationResult = NodeManager.ValidateEventRolePermissions(monitoredItem, e); if (ServiceResult.IsBad(validationResult)) { // skip event reporting for EventType without permissions continue; } lock (NodeManager.Lock) { // enqueue event monitoredItem?.QueueEvent(e); } } }
/// <summary> /// Modifies a monitored item. /// </summary> public void ModifyMonitoredItem( OperationContext context, IEventMonitoredItem monitoredItem, TimestampsToReturn timestampsToReturn, MonitoredItemModifyRequest itemToModify, EventFilter filter) { lock (m_lock) { // should never be called with items that it does not own. if (!m_monitoredItems.ContainsKey(monitoredItem.Id)) { return; } // limit the queue size. uint queueSize = itemToModify.RequestedParameters.QueueSize; if (queueSize > m_maxEventQueueSize) { queueSize = m_maxEventQueueSize; } // modify the attributes. monitoredItem.ModifyAttributes( context.DiagnosticsMask, timestampsToReturn, itemToModify.RequestedParameters.ClientHandle, filter, filter, null, itemToModify.RequestedParameters.SamplingInterval, queueSize, itemToModify.RequestedParameters.DiscardOldest); } }
/// <summary> /// Resends the events for any conditions belonging to the node or its children. /// </summary> /// <param name="context">The system context.</param> /// <param name="monitoredItem">The item to refresh.</param> public void ConditionRefresh( ISystemContext context, IEventMonitoredItem monitoredItem) { if (m_eventSubscriptions != null) { for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) { // only process items monitoring this node. if (!Object.ReferenceEquals(monitoredItem, m_eventSubscriptions[ii])) { continue; } // get the set of condition events for the node and its children. List <IFilterTarget> events = new List <IFilterTarget>(); m_node.ConditionRefresh(context, events, true); // report the events to the monitored item. for (int jj = 0; jj < events.Count; jj++) { monitoredItem.QueueEvent(events[jj]); } } } }
/// <summary> /// Adds the specified event monitored item. /// </summary> /// <param name="eventItem">The monitored item.</param> public void Add(IEventMonitoredItem eventItem) { if (EventMonitoredItems == null) { EventMonitoredItems = new List <IEventMonitoredItem>(); Node.OnReportEvent = OnReportEvent; } EventMonitoredItems.Add(eventItem); }
/// <summary> /// Called when a Node produces an event. /// </summary> /// <param name="context">The system context.</param> /// <param name="node">The affected node.</param> /// <param name="e">The event.</param> public void OnReportEvent(ISystemContext context, NodeState node, IFilterTarget e) { lock (NodeManager.Lock) { for (int ii = 0; ii < EventMonitoredItems.Count; ii++) { IEventMonitoredItem monitoredItem = EventMonitoredItems[ii]; monitoredItem.QueueEvent(e); } } }
/// <summary> /// Called when a Node produces an event. /// </summary> /// <param name="context">The system context.</param> /// <param name="node">The affected node.</param> /// <param name="e">The event.</param> public void OnReportEvent(ISystemContext context, NodeState node, IFilterTarget e) { List <IEventMonitoredItem> eventMonitoredItems = new List <IEventMonitoredItem>(); lock (NodeManager.Lock) { if (EventMonitoredItems == null) { return; } for (int ii = 0; ii < EventMonitoredItems.Count; ii++) { IEventMonitoredItem monitoredItem = EventMonitoredItems[ii]; // enqueue event for role permission validation eventMonitoredItems.Add(monitoredItem); } } for (int ii = 0; ii < eventMonitoredItems.Count; ii++) { IEventMonitoredItem monitoredItem = eventMonitoredItems[ii]; BaseEventState baseEventState = e as BaseEventState; if (baseEventState != null) { ServiceResult validationResult = NodeManager.ValidateRolePermissions(new OperationContext(monitoredItem), baseEventState?.EventType?.Value, PermissionType.ReceiveEvents); if (ServiceResult.IsBad(validationResult)) { // skip event reporting for EventType without permissions continue; } validationResult = NodeManager.ValidateRolePermissions(new OperationContext(monitoredItem), baseEventState?.SourceNode?.Value, PermissionType.ReceiveEvents); if (ServiceResult.IsBad(validationResult)) { // skip event reporting for SourceNode without permissions continue; } } lock (NodeManager.Lock) { // enqueue event monitoredItem?.QueueEvent(e); } } }
/// <summary> /// Removes the specified event monitored item. /// </summary> /// <param name="eventItem">The monitored item.</param> public void Remove(IEventMonitoredItem eventItem) { for (int ii = 0; ii < EventMonitoredItems.Count; ii++) { if (Object.ReferenceEquals(EventMonitoredItems[ii], eventItem)) { EventMonitoredItems.RemoveAt(ii); break; } } if (EventMonitoredItems.Count == 0) { EventMonitoredItems = null; Node.OnReportEvent = null; } }
/// <summary cref="IEventSource.SubscribeToEvents" /> public void SubscribeToEvents( OperationContext context, object notifier, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { lock (DataLock) { if (unsubscribe) { Unsubscribe(monitoredItem); } else { Subscribe(monitoredItem); } } }
/// <summary> /// Unsubscribes to events produced by the node. /// </summary> public void UnsubscribeToEvents(ISystemContext context, IEventMonitoredItem eventSubscription) { if (m_eventSubscriptions != null) { for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) { if (Object.ReferenceEquals(eventSubscription, m_eventSubscriptions[ii])) { m_eventSubscriptions.RemoveAt(ii); if (m_eventSubscriptions.Count == 0) { m_node.SetAreEventsMonitored(context, false, true); m_node.OnReportEvent = null; } break; } } } }
/// <summary> /// Subscribes to events produced by the node. /// </summary> public void SubscribeToEvents(ISystemContext context, IEventMonitoredItem eventSubscription) { if (m_eventSubscriptions == null) { m_eventSubscriptions = new List <IEventMonitoredItem>(); } if (m_eventSubscriptions.Count == 0) { m_node.OnReportEvent = OnReportEvent; m_node.SetAreEventsMonitored(context, true, true); } for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) { if (Object.ReferenceEquals(eventSubscription, m_eventSubscriptions[ii])) { return; } } m_eventSubscriptions.Add(eventSubscription); }
/// <summary cref="IEventSource.SubscribeToAllEvents" /> public void SubscribeToAllEvents( OperationContext context, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { if (context == null) { throw new ArgumentNullException("context"); } lock (DataLock) { if (unsubscribe) { Unsubscribe(monitoredItem); } else { Subscribe(monitoredItem); } } }
/// <summary> /// Subscribes to events produced by the node. /// </summary> public void SubscribeToEvents(ISystemContext context, IEventMonitoredItem eventSubscription) { if (_eventSubscriptions == null) { _eventSubscriptions = new List <IEventMonitoredItem>(); } if (_eventSubscriptions.Count == 0) { Node.OnReportEvent = OnReportEvent; Node.SetAreEventsMonitored(context, true, true); } for (var ii = 0; ii < _eventSubscriptions.Count; ii++) { if (ReferenceEquals(eventSubscription, _eventSubscriptions[ii])) { return; } } _eventSubscriptions.Add(eventSubscription); }
/// <summary> /// Called when a Node produces an event. /// </summary> /// <param name="context">The system context.</param> /// <param name="node">The affected node.</param> /// <param name="e">The event.</param> public void OnReportEvent(ISystemContext context, NodeState node, IFilterTarget e) { lock (NodeManager.Lock) { if (EventMonitoredItems == null) { return; } for (int ii = 0; ii < EventMonitoredItems.Count; ii++) { IEventMonitoredItem monitoredItem = EventMonitoredItems[ii]; BaseEventState baseEventState = e as BaseEventState; if (baseEventState != null) { ServiceResult validationResult = NodeManager.ValidateRolePermissions(new OperationContext(monitoredItem), baseEventState?.EventType?.Value, PermissionType.ReceiveEvents); if (ServiceResult.IsBad(validationResult)) { // ignore invalid permission type events continue; } validationResult = NodeManager.ValidateRolePermissions(new OperationContext(monitoredItem), baseEventState?.SourceNode?.Value, PermissionType.ReceiveEvents); if (ServiceResult.IsBad(validationResult)) { // ignore invalid permission type events continue; } // enque event monitoredItem.QueueEvent(e); } } } }
/// <summary> /// Subscribes or unsubscribes to events produced by all event sources. /// </summary> /// <remarks> /// This method is called when a event subscription is created or deleted. The node /// manager must start/stop reporting events for all objects that it manages. /// </remarks> public override ServiceResult SubscribeToAllEvents( Opc.Ua.Server.OperationContext context, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { ServerSystemContext serverSystemContext = SystemContext.Copy(context); lock (Lock) { // A client has subscribed to the Server object which means all events produced // by this manager must be reported. This is done by incrementing the monitoring // reference count for all root notifiers. if (_rootNotifiers != null) { for (int ii = 0; ii < _rootNotifiers.Count; ii++) { SubscribeToEvents(serverSystemContext, _rootNotifiers[ii], monitoredItem, unsubscribe); } } return(ServiceResult.Good); } }
/// <summary> /// Adds the specified event monitored item. /// </summary> /// <param name="eventItem">The monitored item.</param> public void Add(IEventMonitoredItem eventItem) { if (EventMonitoredItems == null) { EventMonitoredItems = new List<IEventMonitoredItem>(); Node.OnReportEvent = OnReportEvent; } EventMonitoredItems.Add(eventItem); }
/// <summary> /// Removes the specified event monitored item. /// </summary> /// <param name="eventItem">The monitored item.</param> public void Remove(IEventMonitoredItem eventItem) { for (int ii = 0; ii < EventMonitoredItems.Count; ii++) { if (Object.ReferenceEquals(EventMonitoredItems[ii], eventItem)) { EventMonitoredItems.RemoveAt(ii); break; } } if (EventMonitoredItems.Count == 0) { EventMonitoredItems = null; Node.OnReportEvent = null; } }
/// <summary> /// Resends the events for any conditions belonging to the node or its children. /// </summary> /// <param name="context">The system context.</param> /// <param name="monitoredItem">The item to refresh.</param> public void ConditionRefresh( ISystemContext context, IEventMonitoredItem monitoredItem) { if (m_eventSubscriptions != null) { for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) { // only process items monitoring this node. if (!Object.ReferenceEquals(monitoredItem, m_eventSubscriptions[ii])) { continue; } // get the set of condition events for the node and its children. List<IFilterTarget> events = new List<IFilterTarget>(); m_node.ConditionRefresh(context, events, true); // report the events to the monitored item. for (int jj = 0; jj < events.Count; jj++) { monitoredItem.QueueEvent(events[jj]); } } } }
/// <summary cref="IEventSource.SubscribeToAllEvents" /> public void SubscribeToAllEvents( OperationContext context, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { if (context == null) throw new ArgumentNullException("context"); lock (DataLock) { if (unsubscribe) { Unsubscribe(monitoredItem); } else { Subscribe(monitoredItem); } } }
/// <summary> /// Subscribes to events. /// </summary> protected override ServiceResult SubscribeToEvents( ServerSystemContext context, NodeState source, IEventMonitoredItem monitoredItem, bool unsubscribe) { ComAeClientManager system = (ComAeClientManager)this.SystemContext.SystemHandle; ComAeClient client = (ComAeClient)system.SelectClient(context, false); // need to wait until the cache is refreshed for the first time. if (!WaitForTypeCache()) { return StatusCodes.BadOutOfService; } lock (Lock) { SubscriptionIndex index = new SubscriptionIndex(); index.NodeId = source.NodeId; index.LocaleId = client.LocaleId; if (unsubscribe) { ComAeSubscriptionClient subscription = null; if (!m_monitoredItems.TryGetValue(monitoredItem.Id, out subscription)) { return ServiceResult.Good; } m_monitoredItems.Remove(monitoredItem.Id); // Utils.Trace("REMOVED ITEM {0}", monitoredItem.Id); if (subscription.RemoveItem(monitoredItem as MonitoredItem) == 0) { subscription.Delete(); m_subscriptions.Remove(index); // Utils.Trace("DELETED SUBSCRIPTION {0}", index.NodeId); } } else { ComAeSubscriptionClient subscription = null; if (!m_subscriptions.TryGetValue(index, out subscription)) { subscription = new ComAeSubscriptionClient(context, m_configuration, m_typeCache, NamespaceIndex, system, monitoredItem as MonitoredItem); m_subscriptions.Add(index, subscription); subscription.Create(); // Utils.Trace("ADDED NEW SUBSCRIPTION {0}", index.NodeId); } else { subscription.AddItem(monitoredItem as MonitoredItem); } m_monitoredItems[monitoredItem.Id] = subscription; // Utils.Trace("ADDED NEW ITEM {0}", monitoredItem.Id); } } // all done. return ServiceResult.Good; }
/// <summary> /// Does any processing after a monitored item is subscribed to. /// </summary> protected virtual void OnUnsubscribeToEvents( ISystemContext systemContext, MonitoredNode monitoredNode, IEventMonitoredItem monitoredItem) { // does nothing. }
/// <summary> /// Subscribes or unsubscribes to events produced by all event sources. /// </summary> /// <remarks> /// This method is called when a event subscription is created or deleted. The node /// manager must start/stop reporting events for all objects that it manages. /// </remarks> public virtual ServiceResult SubscribeToAllEvents( OperationContext context, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { ServerSystemContext systemContext = m_systemContext.Copy(context); IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>(); lock (Lock) { // update root notifiers. for (int ii = 0; ii < m_rootNotifiers.Count; ii++) { SubscribeToAllEvents( systemContext, monitoredItem, unsubscribe, m_rootNotifiers[ii]); } return ServiceResult.Good; } }
/// <summary> /// Subscribes or unsubscribes to events produced by the specified source. /// </summary> /// <remarks> /// This method is called when a event subscription is created or deletes. The node manager /// must start/stop reporting events for the specified object and all objects below it in /// the notifier hierarchy. /// </remarks> public virtual ServiceResult SubscribeToEvents( OperationContext context, object sourceId, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { ServerSystemContext systemContext = SystemContext.Copy(context); lock (Lock) { // check for valid handle. NodeHandle handle = IsHandleInNamespace(sourceId); if (handle == null) { return StatusCodes.BadNodeIdInvalid; } // check for valid node. NodeState source = ValidateNode(systemContext, handle, null); if (source == null) { return StatusCodes.BadNodeIdUnknown; } // subscribe to events. return SubscribeToEvents(systemContext, source, monitoredItem, unsubscribe); } }
/// <summary> /// Modifies a monitored item. /// </summary> public void ModifyMonitoredItem( OperationContext context, IEventMonitoredItem monitoredItem, TimestampsToReturn timestampsToReturn, MonitoredItemModifyRequest itemToModify, EventFilter filter) { lock (m_lock) { // should never be called with items that it does not own. if (!m_monitoredItems.ContainsKey(monitoredItem.Id)) { return; } // limit the queue size. uint queueSize = itemToModify.RequestedParameters.QueueSize; if (queueSize > m_maxEventQueueSize) { queueSize = m_maxEventQueueSize; } // modify the attributes. monitoredItem.ModifyAttributes( context.DiagnosticsMask, timestampsToReturn, itemToModify.RequestedParameters.ClientHandle, filter, filter, null, itemToModify.RequestedParameters.SamplingInterval, queueSize, itemToModify.RequestedParameters.DiscardOldest); } }
/// <summary> /// Subscribes or unsubscribes to events produced by all event sources. /// </summary> public override ServiceResult SubscribeToAllEvents( OperationContext context, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { return SubscribeToEvents(context, null, subscriptionId, monitoredItem, unsubscribe); }
/// <summary> /// Subscribes to events. /// </summary> protected override ServiceResult SubscribeToEvents( ServerSystemContext context, NodeState source, IEventMonitoredItem monitoredItem, bool unsubscribe) { ComAeClientManager system = (ComAeClientManager)this.SystemContext.SystemHandle; ComAeClient client = (ComAeClient)system.SelectClient(context, false); // need to wait until the cache is refreshed for the first time. if (!WaitForTypeCache()) { return(StatusCodes.BadOutOfService); } lock (Lock) { SubscriptionIndex index = new SubscriptionIndex(); index.NodeId = source.NodeId; index.LocaleId = client.LocaleId; if (unsubscribe) { ComAeSubscriptionClient subscription = null; if (!m_monitoredItems.TryGetValue(monitoredItem.Id, out subscription)) { return(ServiceResult.Good); } m_monitoredItems.Remove(monitoredItem.Id); // Utils.Trace("REMOVED ITEM {0}", monitoredItem.Id); if (subscription.RemoveItem(monitoredItem as MonitoredItem) == 0) { subscription.Delete(); m_subscriptions.Remove(index); // Utils.Trace("DELETED SUBSCRIPTION {0}", index.NodeId); } } else { ComAeSubscriptionClient subscription = null; if (!m_subscriptions.TryGetValue(index, out subscription)) { subscription = new ComAeSubscriptionClient(context, m_configuration, m_typeCache, NamespaceIndex, system, monitoredItem as MonitoredItem); m_subscriptions.Add(index, subscription); subscription.Create(); // Utils.Trace("ADDED NEW SUBSCRIPTION {0}", index.NodeId); } else { subscription.AddItem(monitoredItem as MonitoredItem); } m_monitoredItems[monitoredItem.Id] = subscription; // Utils.Trace("ADDED NEW ITEM {0}", monitoredItem.Id); } } // all done. return(ServiceResult.Good); }
/// <summary> /// Called when a Node produces an event. /// </summary> /// <param name="context">The system context.</param> /// <param name="node">The affected node.</param> /// <param name="e">The event.</param> public void OnReportEvent(ISystemContext context, NodeState node, IFilterTarget e) { List <IEventMonitoredItem> eventMonitoredItems = new List <IEventMonitoredItem>(); lock (NodeManager.Lock) { if (EventMonitoredItems == null) { return; } for (int ii = 0; ii < EventMonitoredItems.Count; ii++) { IEventMonitoredItem monitoredItem = EventMonitoredItems[ii]; // enqueue event for role permission validation eventMonitoredItems.Add(monitoredItem); } } for (int ii = 0; ii < eventMonitoredItems.Count; ii++) { IEventMonitoredItem monitoredItem = eventMonitoredItems[ii]; BaseEventState baseEventState = e as BaseEventState; if (baseEventState != null) { #region Filter out audit events in case the Server_Auditing values is false or the channel is not encrypted if (e is AuditEventState) { // check Server.Auditing flag and skip if false if (!NodeManager.Server.EventManager.ServerAuditing) { continue; } else { // check if channel is not encrypted and skip if so OperationContext operationContext = (context as SystemContext)?.OperationContext as OperationContext; if (operationContext != null && operationContext.ChannelContext.EndpointDescription.SecurityMode != MessageSecurityMode.SignAndEncrypt && operationContext.ChannelContext.EndpointDescription.TransportProfileUri != Profiles.HttpsBinaryTransport) { continue; } } } #endregion ServiceResult validationResult = NodeManager.ValidateRolePermissions(new OperationContext(monitoredItem), baseEventState?.EventType?.Value, PermissionType.ReceiveEvents); if (ServiceResult.IsBad(validationResult)) { // skip event reporting for EventType without permissions continue; } validationResult = NodeManager.ValidateRolePermissions(new OperationContext(monitoredItem), baseEventState?.SourceNode?.Value, PermissionType.ReceiveEvents); if (ServiceResult.IsBad(validationResult)) { // skip event reporting for SourceNode without permissions continue; } } lock (NodeManager.Lock) { // enqueue event monitoredItem?.QueueEvent(e); } } }
/// <see cref="INodeManager.SubscribeToAllEvents" /> public ServiceResult SubscribeToAllEvents( OperationContext context, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { if (context == null) throw new ArgumentNullException("context"); if (monitoredItem == null) throw new ArgumentNullException("monitoredItem"); #if LEGACY_CORENODEMANAGER try { m_lock.Enter(); foreach (IEventSource eventSource in m_eventSources.Values) { eventSource.SubscribeToAllEvents(context, subscriptionId, monitoredItem, unsubscribe); } return ServiceResult.Good; } finally { m_lock.Exit(); } #else return ServiceResult.Good; #endif }
/// <see cref="INodeManager.SubscribeToEvents" /> public ServiceResult SubscribeToEvents( OperationContext context, object sourceId, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { if (context == null) throw new ArgumentNullException("context"); if (sourceId == null) throw new ArgumentNullException("sourceId"); if (monitoredItem == null) throw new ArgumentNullException("monitoredItem"); lock (m_lock) { // validate the node. NodeMetadata metadata = GetNodeMetadata(context, sourceId, BrowseResultMask.NodeClass); if (metadata == null) { return StatusCodes.BadNodeIdUnknown; } // validate the node class. if (((metadata.NodeClass & NodeClass.Object | NodeClass.View)) == 0) { return StatusCodes.BadNotSupported; } // check that it supports events. if ((metadata.EventNotifier & EventNotifiers.SubscribeToEvents) == 0) { return StatusCodes.BadNotSupported; } #if LEGACY_CORENODEMANAGER // subscribe to all notifiers below the notifier. SubscribeToEvents( context, metadata.Handle as ILocalNode, subscriptionId, monitoredItem, unsubscribe); #endif return ServiceResult.Good; } }
/// <summary> /// Subscribes to events. /// </summary> /// <param name="context">The context.</param> /// <param name="source">The source.</param> /// <param name="monitoredItem">The monitored item.</param> /// <param name="unsubscribe">if set to <c>true</c> [unsubscribe].</param> /// <returns>Any error code.</returns> protected override ServiceResult SubscribeToEvents( ServerSystemContext context, NodeState source, IEventMonitoredItem monitoredItem, bool unsubscribe) { // handle unsubscribe. if (unsubscribe) { // check for existing monitored node. if (!MonitoredNodes.TryGetValue(source.NodeId, out MonitoredNode2 monitoredNode2)) { return(StatusCodes.BadNodeIdUnknown); } monitoredNode2.Remove(monitoredItem); // check if node is no longer being monitored. if (!monitoredNode2.HasMonitoredItems) { MonitoredNodes.Remove(source.NodeId); } // update flag. source.SetAreEventsMonitored(context, !unsubscribe, true); // call subclass. OnSubscribeToEvents(context, monitoredNode2, unsubscribe); // all done. return(ServiceResult.Good); } // only objects or views can be subscribed to. BaseObjectState instance = source as BaseObjectState; if (instance == null || (instance.EventNotifier & EventNotifiers.SubscribeToEvents) == 0) { ViewState view = source as ViewState; if (view == null || (view.EventNotifier & EventNotifiers.SubscribeToEvents) == 0) { return(StatusCodes.BadNotSupported); } } // check for existing monitored node. if (!MonitoredNodes.TryGetValue(source.NodeId, out MonitoredNode2 monitoredNode)) { MonitoredNodes[source.NodeId] = monitoredNode = new MonitoredNode2(this, source); } // this links the node to specified monitored item and ensures all events // reported by the node are added to the monitored item's queue. monitoredNode.Add(monitoredItem); // This call recursively updates a reference count all nodes in the notifier // hierarchy below the area. Sources with a reference count of 0 do not have // any active subscriptions so they do not need to report events. source.SetAreEventsMonitored(context, !unsubscribe, true); // signal update. OnSubscribeToEvents(context, monitoredNode, unsubscribe); // all done. return(ServiceResult.Good); }
/// <summary> /// Subscribes or unsubscribes to events produced by the specified source. /// </summary> /// <remarks> /// This method is called when a event subscription is created or deletes. The node manager /// must start/stop reporting events for the specified object and all objects below it in /// the notifier hierarchy. /// </remarks> public virtual ServiceResult SubscribeToEvents( OperationContext context, object sourceId, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { ServerSystemContext systemContext = m_systemContext.Copy(context); IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>(); lock (Lock) { // check for valid handle. NodeState source = IsHandleInNamespace(sourceId); if (source == null) { return StatusCodes.BadNodeIdInvalid; } // check if the object supports subscritions. BaseObjectState instance = sourceId as BaseObjectState; if (instance == null || instance.EventNotifier != EventNotifiers.SubscribeToEvents) { return StatusCodes.BadNotSupported; } MonitoredNode monitoredNode = instance.Handle as MonitoredNode; // handle unsubscribe. if (unsubscribe) { if (monitoredNode != null) { monitoredNode.UnsubscribeToEvents(systemContext, monitoredItem); // do any post processing. OnUnsubscribeToEvents(systemContext, monitoredNode, monitoredItem); } return ServiceResult.Good; } // subscribe to events. if (monitoredNode == null) { instance.Handle = monitoredNode = new MonitoredNode(m_server, this, source); } monitoredNode.SubscribeToEvents(systemContext, monitoredItem); // do any post processing. OnSubscribeToEvents(systemContext, monitoredNode, monitoredItem); return ServiceResult.Good; } }
/// <summary> /// Subscribes or unsubscribes to events produced by all event sources. /// </summary> /// <remarks> /// This method is called when a event subscription is created or deleted. The node /// manager must start/stop reporting events for all objects that it manages. /// </remarks> public virtual ServiceResult SubscribeToAllEvents( OperationContext context, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { ServerSystemContext systemContext = SystemContext.Copy(context); lock (Lock) { // A client has subscribed to the Server object which means all events produced // by this manager must be reported. This is done by incrementing the monitoring // reference count for all root notifiers. if (m_rootNotifiers != null) { for (int ii = 0; ii < m_rootNotifiers.Count; ii++) { SubscribeToEvents(systemContext, m_rootNotifiers[ii], monitoredItem, unsubscribe); } } return ServiceResult.Good; } }
/// <summary> /// Subscribes/unsubscribes to all events produced by the specified node. /// </summary> protected void SubscribeToAllEvents( ISystemContext systemContext, IEventMonitoredItem monitoredItem, bool unsubscribe, NodeState source) { MonitoredNode monitoredNode = source.Handle as MonitoredNode; // handle unsubscribe. if (unsubscribe) { if (monitoredNode != null) { monitoredNode.UnsubscribeToEvents(systemContext, monitoredItem); // do any post processing. OnUnsubscribeToEvents(systemContext, monitoredNode, monitoredItem); } return; } // subscribe to events. if (monitoredNode == null) { source.Handle = monitoredNode = new MonitoredNode(m_server, this, source); } monitoredNode.SubscribeToEvents(systemContext, monitoredItem); // do any post processing. OnSubscribeToEvents(systemContext, monitoredNode, monitoredItem); }
/// <summary> /// Subscribes to events. /// </summary> /// <param name="context">The context.</param> /// <param name="source">The source.</param> /// <param name="monitoredItem">The monitored item.</param> /// <param name="unsubscribe">if set to <c>true</c> [unsubscribe].</param> /// <returns>Any error code.</returns> protected virtual ServiceResult SubscribeToEvents( ServerSystemContext context, NodeState source, IEventMonitoredItem monitoredItem, bool unsubscribe) { MonitoredNode monitoredNode = null; // handle unsubscribe. if (unsubscribe) { // check for existing monitored node. if (!MonitoredNodes.TryGetValue(source.NodeId, out monitoredNode)) { return StatusCodes.BadNodeIdUnknown; } monitoredNode.Remove(monitoredItem); // check if node is no longer being monitored. if (!monitoredNode.HasMonitoredItems) { MonitoredNodes.Remove(source.NodeId); } // update flag. source.SetAreEventsMonitored(context, !unsubscribe, true); // call subclass. OnSubscribeToEvents(context, monitoredNode, unsubscribe); // all done. return ServiceResult.Good; } // only objects or views can be subscribed to. BaseObjectState instance = source as BaseObjectState; if (instance == null || (instance.EventNotifier & EventNotifiers.SubscribeToEvents) == 0) { ViewState view = source as ViewState; if (view == null || (view.EventNotifier & EventNotifiers.SubscribeToEvents) == 0) { return StatusCodes.BadNotSupported; } } // check for existing monitored node. if (!MonitoredNodes.TryGetValue(source.NodeId, out monitoredNode)) { MonitoredNodes[source.NodeId] = monitoredNode = new MonitoredNode(this, source); } // this links the node to specified monitored item and ensures all events // reported by the node are added to the monitored item's queue. monitoredNode.Add(monitoredItem); // This call recursively updates a reference count all nodes in the notifier // hierarchy below the area. Sources with a reference count of 0 do not have // any active subscriptions so they do not need to report events. source.SetAreEventsMonitored(context, !unsubscribe, true); // signal update. OnSubscribeToEvents(context, monitoredNode, unsubscribe); // all done. return ServiceResult.Good; }
/// <summary> /// Subscribes to events produced by the node. /// </summary> public void SubscribeToEvents(ISystemContext context, IEventMonitoredItem eventSubscription) { if (m_eventSubscriptions == null) { m_eventSubscriptions = new List<IEventMonitoredItem>(); } if (m_eventSubscriptions.Count == 0) { m_node.OnReportEvent = OnReportEvent; m_node.SetAreEventsMonitored(context, true, true); } for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) { if (Object.ReferenceEquals(eventSubscription, m_eventSubscriptions[ii])) { return; } } m_eventSubscriptions.Add(eventSubscription); }
/// <summary> /// Unsubscribes to events produced by the node. /// </summary> public void UnsubscribeToEvents(ISystemContext context, IEventMonitoredItem eventSubscription) { if (m_eventSubscriptions != null) { for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) { if (Object.ReferenceEquals(eventSubscription, m_eventSubscriptions[ii])) { m_eventSubscriptions.RemoveAt(ii); if (m_eventSubscriptions.Count == 0) { m_node.SetAreEventsMonitored(context, false, true); m_node.OnReportEvent = null; } break; } } } }
/// <summary> /// Recursively subscribes to events for the notifiers in the tree. /// </summary> private void SubscribeToEvents( OperationContext context, ILocalNode node, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { // find handle associated with the node. IEventSource eventSource = node as IEventSource; SourceHandle handle = node.Handle as SourceHandle; if (handle != null) { eventSource = handle.Source as IEventSource; } if (eventSource != null) { try { eventSource.SubscribeToEvents(context, (handle != null)?handle.Handle:null, subscriptionId, monitoredItem, unsubscribe); } catch (Exception e) { Utils.Trace(e, "Unexpected error calling SubscribeToEvents on an EventSource."); } } // find the child notifiers. IList<IReference> references = node.References.Find(ReferenceTypes.HasNotifier, false, true, m_server.TypeTree); for (int ii = 0; ii < references.Count; ii++) { if (!references[ii].TargetId.IsAbsolute) { ILocalNode target = GetManagerHandle(references[ii].TargetId) as ILocalNode; if (target == null) { continue; } // only object or views can produce events. if ((target.NodeClass & (NodeClass.Object | NodeClass.View)) == 0) { continue; } SubscribeToEvents(context, target, subscriptionId, monitoredItem, unsubscribe); } } }
/// <summary cref="IEventSource.SubscribeToEvents" /> public void SubscribeToEvents( OperationContext context, object notifier, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { lock (DataLock) { if (unsubscribe) { Unsubscribe(monitoredItem); } else { Subscribe(monitoredItem); } } }