示例#1
0
 /// <summary>
 /// Does any processing after a monitored item is deleted.
 /// </summary>
 protected override void OnDeleteMonitoredItem(
     ISystemContext systemContext,
     MonitoredNode monitoredNode,
     DataChangeMonitoredItem monitoredItem)
 {
     // TBD
 }
 /// <summary>
 /// Constructs a new instance.
 /// </summary>
 public DataChangeMonitoredItem(
     MonitoredNode source,
     uint id,
     uint attributeId,
     NumericRange indexRange,
     QualifiedName dataEncoding,
     DiagnosticsMasks diagnosticsMasks,
     TimestampsToReturn timestampsToReturn,
     MonitoringMode monitoringMode,
     uint clientHandle,
     double samplingInterval,
     bool alwaysReportUpdates)
 {
     m_source = source;
     m_id = id;
     m_attributeId = attributeId;
     m_indexRange = indexRange;
     m_dataEncoding = dataEncoding;
     m_timestampsToReturn = timestampsToReturn;
     m_diagnosticsMasks = diagnosticsMasks;
     m_monitoringMode = monitoringMode;
     m_clientHandle = clientHandle;
     m_samplingInterval = samplingInterval;
     m_nextSampleTime = DateTime.UtcNow.Ticks;
     m_readyToPublish = false;
     m_readyToTrigger = false;
     m_alwaysReportUpdates = alwaysReportUpdates;
 }
示例#3
0
 /// <summary>
 /// Does any processing after a monitored item is deleted.
 /// </summary>
 protected override void OnDeleteMonitoredItem(
     ISystemContext systemContext,
     MonitoredNode monitoredNode,
     DataChangeMonitoredItem monitoredItem)
 {
     StopMonitoring(systemContext, monitoredNode);
 }
示例#4
0
        /// <summary>
        /// Returns true if the system must be scanning to provide updates for the monitored item.
        /// </summary>
        private void StopMonitoring(ISystemContext context, MonitoredNode monitoredNode)
        {
            // find the root.
            NodeState root = monitoredNode.Node.GetHierarchyRoot();

            // check for areas.
            AreaState area = root as AreaState;

            if (area != null)
            {
                if (m_system.MonitorArea(area, true) == 0)
                {
                    RemoveNodeHierarchyFromCache(context, area);
                }

                return;
            }

            // check for controllers.
            ControllerState controller = root as ControllerState;

            if (controller != null)
            {
                if (m_system.MonitorController(controller, true) == 0)
                {
                    RemoveNodeHierarchyFromCache(context, controller);
                }

                return;
            }
        }
示例#5
0
        /// <summary>
        /// Returns true if the system must be scanning to provide updates for the monitored item.
        /// </summary>
        private void StartMonitoring(ISystemContext context, MonitoredNode monitoredNode)
        {
            // find the root.
            NodeState root = monitoredNode.Node.GetHierarchyRoot();

            // check for areas.
            AreaState area = root as AreaState;

            if (area != null)
            {
                m_system.MonitorArea(area, false);

                if (!m_cache.ContainsKey(area.NodeId))
                {
                    AddNodeHierarchyToCache(context, area);
                }

                return;
            }

            // check for controllers.
            ControllerState controller = root as ControllerState;

            if (controller != null)
            {
                m_system.MonitorController(controller, false);

                if (!m_cache.ContainsKey(controller.NodeId))
                {
                    AddNodeHierarchyToCache(context, controller);
                }

                return;
            }
        }
示例#6
0
 /// <summary>
 /// Does any processing after a monitored item is created.
 /// </summary>
 protected override void OnCreateMonitoredItem(
     ISystemContext systemContext,
     MonitoredItemCreateRequest itemToCreate,
     MonitoredNode monitoredNode,
     DataChangeMonitoredItem monitoredItem)
 {
     // TBD
 }
示例#7
0
        /// <summary>
        /// Returns a unique handle for the node.
        /// </summary>
        protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary <NodeId, NodeState> cache)
        {
            lock (Lock)
            {
                // quickly exclude nodes that are not in the namespace.
                if (!IsNodeIdInNamespace(nodeId))
                {
                    return(null);
                }

                // check for check for nodes that are being currently monitored.
                MonitoredNode monitoredNode = null;

                if (MonitoredNodes.TryGetValue(nodeId, out monitoredNode))
                {
                    NodeHandle handle = new NodeHandle();

                    handle.NodeId    = nodeId;
                    handle.Validated = true;
                    handle.Node      = monitoredNode.Node;

                    return(handle);
                }

                if (nodeId.IdType != IdType.String)
                {
                    NodeState node = null;

                    if (PredefinedNodes.TryGetValue(nodeId, out node))
                    {
                        NodeHandle handle = new NodeHandle();

                        handle.NodeId    = nodeId;
                        handle.Node      = node;
                        handle.Validated = true;

                        return(handle);
                    }
                }

                // parse the identifier.
                ParsedNodeId parsedNodeId = ParsedNodeId.Parse(nodeId);

                if (parsedNodeId != null)
                {
                    NodeHandle handle = new NodeHandle();

                    handle.NodeId       = nodeId;
                    handle.Validated    = false;
                    handle.Node         = null;
                    handle.ParsedNodeId = parsedNodeId;

                    return(handle);
                }

                return(null);
            }
        }
示例#8
0
 /// <summary>
 /// Does any processing after a monitored item is created.
 /// </summary>
 protected override void OnSetMonitoringMode(
     ISystemContext systemContext,
     MonitoredNode monitoredNode,
     DataChangeMonitoredItem monitoredItem,
     MonitoringMode previousMode,
     MonitoringMode currentMode)
 {
     // TBD
 }
示例#9
0
 /// <summary>
 /// Does any processing after a monitored item is created.
 /// </summary>
 protected override void OnModifyMonitoredItem(
     ISystemContext systemContext,
     MonitoredItemModifyRequest itemToModify,
     MonitoredNode monitoredNode,
     DataChangeMonitoredItem monitoredItem,
     double previousSamplingInterval)
 {
     // TBD
 }
示例#10
0
        /// <summary>
        /// Constructs a new instance.
        /// </summary>
        public DataChangeMonitoredItem(
            MonitoredNode source,
            uint id,
            uint attributeId,
            NumericRange indexRange,
            QualifiedName dataEncoding,
            DiagnosticsMasks diagnosticsMasks,
            TimestampsToReturn timestampsToReturn,
            MonitoringMode monitoringMode,
            uint clientHandle,
            double samplingInterval,
            uint queueSize,
            bool discardOldest,
            DataChangeFilter filter,
            Range range,
            bool alwaysReportUpdates)
        {
            m_source = source;
            m_id = id;
            m_attributeId = attributeId;
            m_indexRange = indexRange;
            m_dataEncoding = dataEncoding;
            m_timestampsToReturn = timestampsToReturn;
            m_diagnosticsMasks = diagnosticsMasks;
            m_monitoringMode = monitoringMode;
            m_clientHandle = clientHandle;
            m_samplingInterval = samplingInterval;
            m_nextSampleTime = DateTime.UtcNow.Ticks;
            m_readyToPublish = false;
            m_readyToTrigger = false;
            m_queue = null;
            m_filter = filter;
            m_range = 0;
            m_alwaysReportUpdates = alwaysReportUpdates;
        
            if (range != null)
            {
                m_range = range.High  - range.Low;
            }

            if (queueSize > 1)
            {
                m_queue = new MonitoredItemQueue();
                m_queue.SetQueueSize(queueSize, discardOldest, diagnosticsMasks);
                m_queue.SetSamplingInterval(samplingInterval);
            }
        }
        /// <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>
 /// Does any processing after a monitored item is created.
 /// </summary>
 protected virtual void OnSetMonitoringMode(
     ISystemContext systemContext,
     MonitoredNode monitoredNode,
     DataChangeMonitoredItem monitoredItem,
     MonitoringMode previousMode,
     MonitoringMode currentMode)
 {
     // does nothing.
 }
示例#13
0
 public void Add(string nodeId, Uri incoming)
 {
     var node = new MonitoredNode(nodeId, incoming, _listener);
     _nodes[nodeId] = node;
 }
 /// <summary>
 /// Does any processing after a monitored item is created.
 /// </summary>
 protected virtual void OnModifyMonitoredItem(
     ISystemContext systemContext,
     MonitoredItemModifyRequest itemToModify,
     MonitoredNode monitoredNode,
     DataChangeMonitoredItem monitoredItem,
     double previousSamplingInterval)
 {
     // does nothing.
 }
 /// <summary>
 /// Does any processing after a monitored item is deleted.
 /// </summary>
 protected virtual void OnDeleteMonitoredItem(
     ISystemContext systemContext,
     MonitoredNode monitoredNode,
     DataChangeMonitoredItem monitoredItem)
 {
     // does nothing.
 }
        /// <summary>
        /// Creates a new set of monitored items for a set of variables.
        /// </summary>
        /// <remarks>
        /// This method only handles data change subscriptions. Event subscriptions are created by the SDK.
        /// </remarks>
        protected virtual ServiceResult CreateMonitoredItem(
            ISystemContext context,
            NodeState source,
            uint subscriptionId,
            double publishingInterval,
            DiagnosticsMasks diagnosticsMasks,
            TimestampsToReturn timestampsToReturn,
            MonitoredItemCreateRequest itemToCreate,
            ref long globalIdCounter,
            out MonitoringFilterResult filterError,
            out IMonitoredItem monitoredItem)
        {
            filterError = null;
            monitoredItem = null;
            ServiceResult error = null;
            
            // read initial value.
            DataValue initialValue = new DataValue();

            initialValue.Value = null;
            initialValue.ServerTimestamp = DateTime.UtcNow;
            initialValue.SourceTimestamp = DateTime.MinValue;
            initialValue.StatusCode = StatusCodes.Good;

            error = source.ReadAttribute(
                context,
                itemToCreate.ItemToMonitor.AttributeId,
                itemToCreate.ItemToMonitor.ParsedIndexRange,
                itemToCreate.ItemToMonitor.DataEncoding,
                initialValue);

            if (ServiceResult.IsBad(error))
            {
                return error;
            }
            
            // validate parameters.
            MonitoringParameters parameters = itemToCreate.RequestedParameters;

            // validate the data change filter.
            DataChangeFilter filter = null;
            Range range = null;

            if (!ExtensionObject.IsNull(parameters.Filter))
            {
                error = ValidateDataChangeFilter(
                    context,
                    source,
                    itemToCreate.ItemToMonitor.AttributeId,
                    parameters.Filter,
                    out filter,
                    out range);

                if (ServiceResult.IsBad(error))
                {
                    return error;
                }
            }

            // create monitored node.
            MonitoredNode monitoredNode = source.Handle as MonitoredNode;

            if (monitoredNode == null)
            {
                source.Handle = monitoredNode = new MonitoredNode(m_server, this, source);
            }

            // create a globally unique identifier.
            uint monitoredItemId = Utils.IncrementIdentifier(ref globalIdCounter);

            // determine the sampling interval.
            double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval;

            if (samplingInterval < 0)
            {
                samplingInterval = publishingInterval;
            }

            // check if the variable needs to be sampled.
            bool samplingRequired = false;

            if (itemToCreate.ItemToMonitor.AttributeId == Attributes.Value)
            {
                BaseVariableState variable = source as BaseVariableState;

                if (variable.MinimumSamplingInterval > 0)
                {
                    samplingInterval = CalculateSamplingInterval(variable, samplingInterval);
                    samplingRequired = true;
                }
            }

            // create the item.
            DataChangeMonitoredItem datachangeItem = monitoredNode.CreateDataChangeItem(
                context,
                monitoredItemId,
                itemToCreate.ItemToMonitor.AttributeId,
                itemToCreate.ItemToMonitor.ParsedIndexRange,
                itemToCreate.ItemToMonitor.DataEncoding,
                diagnosticsMasks,
                timestampsToReturn,
                itemToCreate.MonitoringMode,
                itemToCreate.RequestedParameters.ClientHandle,
                samplingInterval,
                itemToCreate.RequestedParameters.QueueSize,
                itemToCreate.RequestedParameters.DiscardOldest,
                filter,
                range,
                false);

            if (samplingRequired)
            {
                CreateSampledItem(samplingInterval, datachangeItem);
            }

            // report the initial value.
            datachangeItem.QueueValue(initialValue, null);

            // do any post processing.
            OnCreateMonitoredItem(context, itemToCreate, monitoredNode, datachangeItem);

            // update monitored item list.
            monitoredItem = datachangeItem;

            return ServiceResult.Good;
        }
 /// <summary>
 /// Does any processing after a monitored item is created.
 /// </summary>
 protected virtual void OnCreateMonitoredItem(
     ISystemContext systemContext,
     MonitoredItemCreateRequest itemToCreate,
     MonitoredNode monitoredNode, 
     DataChangeMonitoredItem monitoredItem)
 {
     // does nothing.
 }
 /// <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 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 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>
        /// Creates a new set of monitored items for a set of variables.
        /// </summary>
        /// <remarks>
        /// This method only handles data change subscriptions. Event subscriptions are created by the SDK.
        /// </remarks>
        protected virtual ServiceResult CreateMonitoredItem(
            ServerSystemContext context,
            NodeHandle handle,
            uint subscriptionId,
            double publishingInterval,
            DiagnosticsMasks diagnosticsMasks,
            TimestampsToReturn timestampsToReturn,
            MonitoredItemCreateRequest itemToCreate,
            ref long globalIdCounter,
            out MonitoringFilterResult filterResult,
            out IMonitoredItem monitoredItem)
        {
            filterResult = null;
            monitoredItem = null;

            // validate parameters.
            MonitoringParameters parameters = itemToCreate.RequestedParameters;

            // validate attribute.
            if (!Attributes.IsValid(handle.Node.NodeClass, itemToCreate.ItemToMonitor.AttributeId))
            {
                return StatusCodes.BadAttributeIdInvalid;
            }

            // check if the node is already being monitored.
            MonitoredNode monitoredNode = null;

            if (!m_monitoredNodes.TryGetValue(handle.Node.NodeId, out monitoredNode))
            {
                NodeState cachedNode = AddNodeToComponentCache(context, handle, handle.Node);
                m_monitoredNodes[handle.Node.NodeId] = monitoredNode = new MonitoredNode(this, cachedNode);
            }

            handle.Node = monitoredNode.Node;
            handle.MonitoredNode = monitoredNode;

            // create a globally unique identifier.
            uint monitoredItemId = Utils.IncrementIdentifier(ref globalIdCounter);

            // determine the sampling interval.
            double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval;

            if (samplingInterval < 0)
            {
                samplingInterval = publishingInterval;
            }

            // ensure minimum sampling interval is not exceeded.
            if (itemToCreate.ItemToMonitor.AttributeId == Attributes.Value)
            {
                BaseVariableState variable = handle.Node as BaseVariableState;

                if (variable != null && samplingInterval < variable.MinimumSamplingInterval)
                {
                    samplingInterval = variable.MinimumSamplingInterval;
                }
            }

            // put a large upper limit on sampling.
            if (samplingInterval == Double.MaxValue)
            {
                samplingInterval = 365 * 24 * 3600 * 1000.0;
            }

            // put an upper limit on queue size.
            uint queueSize = itemToCreate.RequestedParameters.QueueSize;

            if (queueSize > m_maxQueueSize)
            {
                queueSize = m_maxQueueSize;
            }

            // validate the monitoring filter.
            Range euRange = null;
            MonitoringFilter filterToUse = null;

            ServiceResult error = ValidateMonitoringFilter(
                context,
                handle,
                itemToCreate.ItemToMonitor.AttributeId,
                samplingInterval,
                queueSize,
                parameters.Filter,
                out filterToUse,
                out euRange,
                out filterResult);

            if (ServiceResult.IsBad(error))
            {
                return error;
            }

            // create the item.
            MonitoredItem datachangeItem = new MonitoredItem(
                Server,
                this,
                handle,
                subscriptionId,
                monitoredItemId,
                context.OperationContext.Session,
                itemToCreate.ItemToMonitor,
                diagnosticsMasks,
                timestampsToReturn,
                itemToCreate.MonitoringMode,
                itemToCreate.RequestedParameters.ClientHandle,
                filterToUse,
                filterToUse,
                euRange,
                samplingInterval,
                queueSize,
                itemToCreate.RequestedParameters.DiscardOldest,
                0);

            // report the initial value.
            ReadInitialValue(context, handle, datachangeItem);

            // update monitored item list.
            monitoredItem = datachangeItem;

            // save the monitored item.
            m_monitoredItems.Add(monitoredItemId, datachangeItem);
            monitoredNode.Add(datachangeItem);

            // report change.
            OnMonitoredItemCreated(context, handle, datachangeItem);

            return error;
        }
 /// <summary>
 /// Called after subscribing/unsubscribing to events.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="monitoredNode">The monitored node.</param>
 /// <param name="unsubscribe">if set to <c>true</c> unsubscribing.</param>
 protected virtual void OnSubscribeToEvents(
     ServerSystemContext context,
     MonitoredNode       monitoredNode, 
     bool                unsubscribe)
 {
     // defined by the sub-class
 }