/// <summary>
        /// Returns true if the system must be scanning to provide updates for the monitored item.
        /// </summary>
        private bool SystemScanRequired(MonitoredNode2 monitoredNode, IDataChangeMonitoredItem2 monitoredItem)
        {
            // ingore other types of monitored items.
            if (monitoredItem == null)
            {
                return(false);
            }

            // only care about variables.
            BaseDataVariableState source = monitoredNode.Node as BaseDataVariableState;

            if (source == null)
            {
                return(false);
            }

            // check for variables that need to be scanned.
            if (monitoredItem.AttributeId == Attributes.Value)
            {
                TestDataObjectState test = source.Parent as TestDataObjectState;

                if (test != null && test.SimulationActive.Value)
                {
                    return(true);
                }
            }

            return(false);
        }
Ejemplo n.º 2
0
        /// <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 override 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);
            }

            NodeState cachedNode = AddNodeToComponentCache(context, handle, handle.Node);

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

            if (!MonitoredNodes.TryGetValue(handle.Node.NodeId, out monitoredNode))
            {
                MonitoredNodes[handle.Node.NodeId] = monitoredNode = new MonitoredNode2(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 > MaxQueueSize)
            {
                queueSize = 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 ComMonitoredItem(
                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.
            MonitoredItems.Add(monitoredItemId, datachangeItem);
            monitoredNode.Add(datachangeItem);

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

            return(error);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Override ConditionRefresh.
        /// </summary>
        public override ServiceResult ConditionRefresh(
            OperationContext context,
            IList <IEventMonitoredItem> monitoredItems)
        {
            ServerSystemContext systemContext = SystemContext.Copy(context);

            for (int ii = 0; ii < monitoredItems.Count; ii++)
            {
                // the IEventMonitoredItem should always be MonitoredItems since they are created by the MasterNodeManager.
                MonitoredItem monitoredItem = monitoredItems[ii] as MonitoredItem;

                if (monitoredItem == null)
                {
                    continue;
                }

                List <IFilterTarget> events         = new List <IFilterTarget>();
                List <NodeState>     nodesToRefresh = new List <NodeState>();

                lock (Lock)
                {
                    // check for server subscription.
                    if (monitoredItem.NodeId == ObjectIds.Server)
                    {
                        if (RootNotifiers != null)
                        {
                            nodesToRefresh.AddRange(RootNotifiers);
                        }
                    }
                    else
                    {
                        // check for existing monitored node.
                        MonitoredNode2 monitoredNode = null;

                        if (!MonitoredNodes.TryGetValue(monitoredItem.NodeId, out monitoredNode))
                        {
                            continue;
                        }

                        // get the refresh events.
                        nodesToRefresh.Add(monitoredNode.Node);
                    }
                }

                // block and wait for the refresh.
                for (int jj = 0; jj < nodesToRefresh.Count; jj++)
                {
                    nodesToRefresh[jj].ConditionRefresh(systemContext, events, true);
                }

                lock (Lock)
                {
                    // This is where I can add branch events
                    GetBranchesForConditionRefresh(events);
                }

                // queue the events.
                for (int jj = 0; jj < events.Count; jj++)
                {
                    monitoredItem.QueueEvent(events[jj]);
                }
            }

            // all done.
            return(ServiceResult.Good);
        }
        /// <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 cache.
                if (cache != null)
                {
                    NodeState node = null;

                    if (cache.TryGetValue(nodeId, out node))
                    {
                        return(new NodeHandle(nodeId, node));
                    }
                }

                NodeHandle handle = null;

                try
                {
                    // check if node already being monitored.
                    if (MonitoredNodes != null)
                    {
                        MonitoredNode2 monitoredNode2 = null;

                        if (MonitoredNodes.TryGetValue(nodeId, out monitoredNode2))
                        {
                            handle = new NodeHandle(nodeId, monitoredNode2.Node);
                            handle.MonitoredNode = monitoredNode2;
                            return(handle);
                        }
                    }

                    // check for predefined nodes.
                    if (PredefinedNodes != null)
                    {
                        NodeState node = null;

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

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

                    if (parsedNodeId != null)
                    {
                        if (parsedNodeId.RootType == AeModelUtils.AeEventTypeMapping && m_typeCache != null)
                        {
                            AeEventTypeMappingState mappingNode = m_typeCache.GetMappingNode(SystemContext, nodeId);

                            if (mappingNode != null)
                            {
                                return(handle = new NodeHandle(nodeId, mappingNode));
                            }

                            return(null);
                        }

                        handle = new NodeHandle();

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

                        return(handle);
                    }
                }
                finally
                {
                    if (handle != null && handle.Node != null && cache != null)
                    {
                        cache.Add(nodeId, handle.Node);
                    }
                }

                return(null);
            }
        }
Ejemplo n.º 5
0
        /// <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);
        }