Stores information about a NodeId specified by the client.
A NodeHandle is created when GetManagerHandle is called and will only contain information found by parsing the NodeId. The ValidateNode method is used to verify that the NodeId refers to a real Node and find a NodeState object that can be used to access the Node.
コード例 #1
0
        /// <summary>
        /// Verifies that the specified node exists.
        /// </summary>
        protected override NodeState ValidateNode(
            ServerSystemContext context,
            Opc.Ua.Server.NodeHandle handle,
            IDictionary <NodeId, NodeState> cache)
        {
            // not valid if no root.
            if (handle == null)
            {
                return(null);
            }

            // check if previously validated.
            if (handle.Validated)
            {
                return(handle.Node);
            }

            // lookup in operation cache.
            NodeState target = FindNodeInCache(context, handle, cache);

            if (target == null)
            {
                // TBD
                return(null);
            }

            return(ValidationComplete(context, handle, target, cache));
        }
コード例 #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AeConditionState"/> class.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="handle">The handle.</param>
        /// <param name="acknowledgeMethod">The acknowledge method.</param>
        public AeConditionState(ISystemContext context, NodeHandle handle, AddCommentMethodState acknowledgeMethod)
        :
            base(null)
        {
            AeParsedNodeId parsedNodeId = (AeParsedNodeId)handle.ParsedNodeId;

            this.NodeId = handle.NodeId;

            this.TypeDefinitionId = AeParsedNodeId.Construct(
                Constants.CONDITION_EVENT, 
                parsedNodeId.CategoryId, 
                parsedNodeId.ConditionName, 
                parsedNodeId.NamespaceIndex);

            this.Acknowledge = acknowledgeMethod;
            this.AddChild(acknowledgeMethod);
        }
コード例 #3
0
        /// <summary>
        /// Returns a unique handle for the node.
        /// </summary>
        protected override Opc.Ua.Server.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);
                }

                NodeState node = null;

                // check cache (the cache is used because the same node id can appear many times in a single request).
                if (cache != null)
                {
                    if (cache.TryGetValue(nodeId, out node))
                    {
                        return(new Opc.Ua.Server.NodeHandle(nodeId, node));
                    }
                }

                // look up predefined node.
                if (PredefinedNodes.TryGetValue(nodeId, out node))
                {
                    Opc.Ua.Server.NodeHandle handle = new Opc.Ua.Server.NodeHandle(nodeId, node);

                    if (cache != null)
                    {
                        cache.Add(nodeId, node);
                    }

                    return(handle);
                }

                return(null);
            }
        }
コード例 #4
0
        /// <summary>
        /// Modifies the parameters for a monitored item.
        /// </summary>
        protected virtual ServiceResult ModifyMonitoredItem(
            ServerSystemContext context,
            DiagnosticsMasks diagnosticsMasks,
            TimestampsToReturn timestampsToReturn,
            IMonitoredItem monitoredItem,
            MonitoredItemModifyRequest itemToModify,
            NodeHandle handle,
            out MonitoringFilterResult filterResult)
        {
            filterResult = null;
            
            // check for valid monitored item.
            MonitoredItem datachangeItem = monitoredItem as MonitoredItem;

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

            double previousSamplingInterval = datachangeItem.SamplingInterval;
            
            // check if the variable needs to be sampled.
            double samplingInterval = itemToModify.RequestedParameters.SamplingInterval;

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

            // ensure minimum sampling interval is not exceeded.
            if (datachangeItem.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 = itemToModify.RequestedParameters.QueueSize;

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

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

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

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

            // modify the monitored item parameters.
            error = datachangeItem.ModifyAttributes(
                diagnosticsMasks,
                timestampsToReturn,
                itemToModify.RequestedParameters.ClientHandle,
                filterToUse,
                filterToUse,
                euRange,
                samplingInterval,
                queueSize,
                itemToModify.RequestedParameters.DiscardOldest);
            
            // report change.
            if (ServiceResult.IsGood(error))
            {
                OnMonitoredItemModified(context, handle, datachangeItem);
            }

            return error;
        }
コード例 #5
0
        /// <summary>
        /// Validates the monitoring filter specified by the client.
        /// </summary>
        protected virtual StatusCode ValidateMonitoringFilter(
            ServerSystemContext context,
            NodeHandle handle, 
            uint attributeId,
            double samplingInterval,
            uint queueSize,
            ExtensionObject filter,
            out MonitoringFilter filterToUse,
            out Range range,
            out MonitoringFilterResult result)
        {
            range = null;
            filterToUse = null;
            result = null;

            // nothing to do if the filter is not specified.
            if (ExtensionObject.IsNull(filter))
            {
                return StatusCodes.Good;
            }

            // extension objects wrap any data structure. must check that the client provided the correct structure.
            DataChangeFilter deadbandFilter = ExtensionObject.ToEncodeable(filter) as DataChangeFilter;

            if (deadbandFilter == null)
            {
                AggregateFilter aggregateFilter = ExtensionObject.ToEncodeable(filter) as AggregateFilter;

                if (aggregateFilter == null || attributeId != Attributes.Value)
                {
                    return StatusCodes.BadFilterNotAllowed;
                }

                if (!Server.AggregateManager.IsSupported(aggregateFilter.AggregateType))
                {
                    return StatusCodes.BadAggregateNotSupported;
                }

                ServerAggregateFilter revisedFilter = new ServerAggregateFilter();
                revisedFilter.AggregateType = aggregateFilter.AggregateType;
                revisedFilter.StartTime = aggregateFilter.StartTime;
                revisedFilter.ProcessingInterval = aggregateFilter.ProcessingInterval;
                revisedFilter.AggregateConfiguration = aggregateFilter.AggregateConfiguration;
                revisedFilter.Stepped = false;

                StatusCode error = ReviseAggregateFilter(context, handle, samplingInterval, queueSize, revisedFilter);

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

                AggregateFilterResult aggregateFilterResult = new AggregateFilterResult();
                aggregateFilterResult.RevisedProcessingInterval = aggregateFilter.ProcessingInterval;
                aggregateFilterResult.RevisedStartTime = aggregateFilter.StartTime;
                aggregateFilterResult.RevisedAggregateConfiguration = aggregateFilter.AggregateConfiguration;

                filterToUse = revisedFilter;
                result = aggregateFilterResult;
                return StatusCodes.Good;
            }

            // deadband filters only allowed for variable values.
            if (attributeId != Attributes.Value)
            {
                return StatusCodes.BadFilterNotAllowed;
            }

            BaseVariableState variable = handle.Node as BaseVariableState;

            if (variable == null)
            {
                return StatusCodes.BadFilterNotAllowed;
            }

            // check for status filter.
            if (deadbandFilter.DeadbandType == (uint)DeadbandType.None)
            {
                filterToUse = deadbandFilter;
                return StatusCodes.Good;
            }

            // deadband filters can only be used for numeric values.
            if (!Server.TypeTree.IsTypeOf(variable.DataType, DataTypeIds.Number))
            {
                return StatusCodes.BadFilterNotAllowed;
            }
            
            // nothing more to do for absolute filters.
            if (deadbandFilter.DeadbandType == (uint)DeadbandType.Absolute)
            {
                filterToUse = deadbandFilter;
                return StatusCodes.Good;
            }

            // need to look up the EU range if a percent filter is requested.
            if (deadbandFilter.DeadbandType == (uint)DeadbandType.Percent)
            {
                PropertyState property = handle.Node.FindChild(context, Opc.Ua.BrowseNames.EURange) as PropertyState;

                if (property == null)
                {
                    return StatusCodes.BadMonitoredItemFilterUnsupported;
                }
                
                range = property.Value as Range;
                
                if (range == null)
                {
                    return StatusCodes.BadMonitoredItemFilterUnsupported;
                }

                filterToUse = deadbandFilter;

                return StatusCodes.Good;
            }

            // no other type of filter supported.
            return StatusCodes.BadFilterNotAllowed;
        }
コード例 #6
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 cache.
                if (cache != null)
                {
                    NodeState node = null;

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

                NodeHandle handle = null;

                try
                {
                    // 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.
                    HdaParsedNodeId parsedNodeId = HdaParsedNodeId.Parse(nodeId);

                    if (parsedNodeId != 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;
            }
        }
コード例 #7
0
        /// <summary>
        /// Returns a unique handle for the node.
        /// </summary>
        protected override Opc.Ua.Server.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;
                }

                NodeState node = null;

                // check cache (the cache is used because the same node id can appear many times in a single request).
                if (cache != null)
                {
                    if (cache.TryGetValue(nodeId, out node))
                    {
                        return new Opc.Ua.Server.NodeHandle(nodeId, node);
                    }
                }

                // look up predefined node.
                if (PredefinedNodes.TryGetValue(nodeId, out node))
                {
                    Opc.Ua.Server.NodeHandle handle = new Opc.Ua.Server.NodeHandle(nodeId, node);

                    if (cache != null)
                    {
                        cache.Add(nodeId, node);
                    }

                    return handle;
                }

                return null;
            } 
        }
コード例 #8
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;
        }
コード例 #9
0
        /// <summary>
        /// Called after deleting a MonitoredItem.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="handle">The handle for the node.</param>
        /// <param name="monitoredItem">The monitored item.</param>
        protected override void OnMonitoredItemDeleted(
            ServerSystemContext context,
            NodeHandle handle,
            MonitoredItem monitoredItem)
        {
            // check if diagnostics collection needs to be turned off.
            if (IsDiagnosticsNode(handle.Node))
            {
                if (monitoredItem.MonitoringMode != MonitoringMode.Disabled)
                {
                    m_diagnosticsMonitoringCount--;

                    if (m_diagnosticsMonitoringCount == 0 && m_diagnosticsScanTimer != null)
                    {
                        m_diagnosticsScanTimer.Dispose();
                        m_diagnosticsScanTimer = null;
                    }

                    if (m_diagnosticsScanTimer != null)
                    {
                        DoScan(true);
                    }
                }
            }

            // check if sampling needs to be turned off.
            if (monitoredItem.AttributeId == Attributes.Value)
            {
                BaseVariableState variable = handle.Node as BaseVariableState;

                if (variable != null && variable.MinimumSamplingInterval > 0)
                {
                    DeleteSampledItem(monitoredItem);
                }
            }
        }
コード例 #10
0
        /// <summary>
        /// Removes a reference to a component in thecache.
        /// </summary>
        protected void RemoveNodeFromComponentCache(ISystemContext context, NodeHandle handle)
        {
            lock (Lock)
            {
                if (handle == null)
                {
                    return;
                }

                if (m_componentCache != null)
                {
                    NodeId nodeId = handle.NodeId;

                    if (!String.IsNullOrEmpty(handle.ComponentPath))
                    {
                        nodeId = handle.RootId;
                    }

                    CacheEntry entry = null;

                    if (m_componentCache.TryGetValue(nodeId, out entry))
                    {
                        entry.RefCount--;

                        if (entry.RefCount == 0)
                        {
                            m_componentCache.Remove(nodeId);
                        }
                    }
                }
            }
        }
コード例 #11
0
        /// <summary>
        /// Called after changing the MonitoringMode for a MonitoredItem.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="handle">The handle for the node.</param>
        /// <param name="monitoredItem">The monitored item.</param>
        /// <param name="previousMode">The previous monitoring mode.</param>
        /// <param name="monitoringMode">The current monitoring mode.</param>
        protected override void OnMonitoringModeChanged(
            ServerSystemContext context,
            NodeHandle handle,
            MonitoredItem monitoredItem,
            MonitoringMode previousMode,
            MonitoringMode monitoringMode)
        {
            if (SystemScanRequired(handle.MonitoredNode, monitoredItem))
            {
                BaseVariableState source = handle.Node as BaseVariableState;

                if (previousMode != MonitoringMode.Disabled && monitoredItem.MonitoringMode == MonitoringMode.Disabled)
                {
                    m_system.StopMonitoringValue(monitoredItem.Id);
                }

                if (previousMode == MonitoringMode.Disabled && monitoredItem.MonitoringMode != MonitoringMode.Disabled)
                {
                    m_system.StartMonitoringValue(monitoredItem.Id, monitoredItem.SamplingInterval, source);
                }
            }
        }
コード例 #12
0
 /// <summary>
 /// Called after changing the MonitoringMode for a MonitoredItem.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="handle">The handle for the node.</param>
 /// <param name="monitoredItem">The monitored item.</param>
 /// <param name="previousMode">The previous monitoring mode.</param>
 /// <param name="monitoringMode">The current monitoring mode.</param>
 protected virtual void OnMonitoringModeChanged(
     ServerSystemContext context,
     NodeHandle handle,
     MonitoredItem monitoredItem,
     MonitoringMode previousMode,
     MonitoringMode monitoringMode)
 {
     // overridden by the sub-class.
 }
コード例 #13
0
        /// <summary>
        /// Looks up a component in cache.
        /// </summary>
        protected NodeState LookupNodeInComponentCache(ISystemContext context, NodeHandle handle)
        {
            lock (Lock)
            {
                if (m_componentCache == null)
                {
                    return null;
                }

                CacheEntry entry = null;

                if (!String.IsNullOrEmpty(handle.ComponentPath))
                {
                    if (m_componentCache.TryGetValue(handle.RootId, out entry))
                    {
                        return entry.Entry.FindChildBySymbolicName(context, handle.ComponentPath);
                    }
                }
                else
                {
                    if (m_componentCache.TryGetValue(handle.NodeId, out entry))
                    {
                        return entry.Entry;
                    }
                }

                return null;
            }
        }
コード例 #14
0
        /// <summary>
        /// Changes the monitoring mode for an item.
        /// </summary>
        protected virtual ServiceResult SetMonitoringMode(
            ServerSystemContext context,
            IMonitoredItem monitoredItem,
            MonitoringMode monitoringMode,
            NodeHandle handle)
        {
            // check for valid monitored item.
            MonitoredItem datachangeItem = monitoredItem as MonitoredItem;

            // update monitoring mode.
            MonitoringMode previousMode = datachangeItem.SetMonitoringMode(monitoringMode);

            // must send the latest value after enabling a disabled item.
            if (monitoringMode == MonitoringMode.Reporting && previousMode == MonitoringMode.Disabled)
            {
                handle.MonitoredNode.QueueValue(context, handle.Node, datachangeItem);
            }

            // report change.
            if (previousMode != monitoringMode)
            {
                OnMonitoringModeChanged(
                    context,
                    handle,
                    datachangeItem,
                    previousMode,
                    monitoringMode);
            }
            
            return ServiceResult.Good;
        }
コード例 #15
0
 /// <summary>
 /// Called after deleting a MonitoredItem.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="handle">The handle for the node.</param>
 /// <param name="monitoredItem">The monitored item.</param>
 protected virtual void OnMonitoredItemDeleted(
     ServerSystemContext context,
     NodeHandle handle,
     MonitoredItem monitoredItem)
 {
     // overridden by the sub-class.
 }
コード例 #16
0
        /// <summary>
        /// Deletes a monitored item.
        /// </summary>
        protected virtual ServiceResult DeleteMonitoredItem(
            ServerSystemContext context,
            IMonitoredItem monitoredItem,
            NodeHandle handle)
        {
            // check for valid monitored item.
            MonitoredItem datachangeItem = monitoredItem as MonitoredItem;

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

            if (m_monitoredNodes.TryGetValue(handle.NodeId, out monitoredNode))
            {
                monitoredNode.Remove(datachangeItem);

                // check if node is no longer being monitored.
                if (!monitoredNode.HasMonitoredItems)
                {
                    MonitoredNodes.Remove(handle.NodeId);
                }
            }
            
            // remove the monitored item.
            m_monitoredItems.Remove(monitoredItem.Id);

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

            return ServiceResult.Good;
        }
コード例 #17
0
 /// <summary>
 /// Called after creating a MonitoredItem.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="handle">The handle for the node.</param>
 /// <param name="monitoredItem">The monitored item.</param>
 protected override void OnMonitoredItemCreated(
     ServerSystemContext context,
     NodeHandle handle,
     MonitoredItem monitoredItem)
 {
     if (SystemScanRequired(handle.MonitoredNode, monitoredItem))
     {
         if (monitoredItem.MonitoringMode != MonitoringMode.Disabled)
         {
             m_system.StartMonitoringValue(
                 monitoredItem.Id, 
                 monitoredItem.SamplingInterval, 
                 handle.Node as BaseVariableState);
         }
     }    
 }
コード例 #18
0
        /// <summary>
        /// Adds a node to the component cache.
        /// </summary>
        protected NodeState AddNodeToComponentCache(ISystemContext context, NodeHandle handle, NodeState node)
        {
            lock (Lock)
            {
                if (handle == null)
                {
                    return node;
                }

                if (m_componentCache == null)
                {
                    m_componentCache = new Dictionary<NodeId, CacheEntry>();
                }

                // check if a component is actually specified.
                if (!String.IsNullOrEmpty(handle.ComponentPath))
                {
                    CacheEntry entry = null;

                    if (m_componentCache.TryGetValue(handle.RootId, out entry))
                    {
                        entry.RefCount++;

                        if (!String.IsNullOrEmpty(handle.ComponentPath))
                        {
                            return entry.Entry.FindChildBySymbolicName(context, handle.ComponentPath);
                        }

                        return entry.Entry;
                    }

                    NodeState root = node.GetHierarchyRoot();

                    if (root != null)
                    {
                        entry = new CacheEntry();
                        entry.RefCount = 1;
                        entry.Entry = root;
                        m_componentCache.Add(handle.RootId, entry);
                    }
                }

                // simply add the node to the cache.
                else
                {
                    CacheEntry entry = null;

                    if (m_componentCache.TryGetValue(handle.NodeId, out entry))
                    {
                        entry.RefCount++;
                        return entry.Entry;
                    }

                    entry = new CacheEntry();
                    entry.RefCount = 1;
                    entry.Entry = node;
                    m_componentCache.Add(handle.NodeId, entry);
                }

                return node;
            }
        }
コード例 #19
0
 /// <summary>
 /// Called after deleting a MonitoredItem.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="handle">The handle for the node.</param>
 /// <param name="monitoredItem">The monitored item.</param>
 protected override void OnMonitoredItemDeleted(
     ServerSystemContext context,
     NodeHandle handle,
     MonitoredItem monitoredItem)
 {
     // check for variables that need to be scanned.
     if (SystemScanRequired(handle.MonitoredNode, monitoredItem))
     {
         m_system.StopMonitoringValue(monitoredItem.Id);
     }
 }
コード例 #20
0
        /// <summary>
        /// Returns a unique handle for the node.
        /// </summary>
        protected virtual NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary<NodeId,NodeState> cache)
        {
            if (!IsNodeIdInNamespace(nodeId))
            {
                return null;
            }

            if (m_predefinedNodes != null)
            {
                NodeState node = null;

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

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

                    return handle;
                }
            }

            return null;
        }
コード例 #21
0
        /// <summary>
        /// Verifies that the specified node exists.
        /// </summary>
        protected override NodeState ValidateNode(
            ServerSystemContext context,
            NodeHandle handle,
            IDictionary<NodeId, NodeState> cache)
        {
            // not valid if no root.
            if (handle == null)
            {
                return null;
            }

            // check if previously validated.
            if (handle.Validated)
            {
                return handle.Node;
            }

            NodeState target = null;

            // check if already in the cache.
            if (cache != null)
            {
                if (cache.TryGetValue(handle.NodeId, out target))
                {
                    // nulls mean a NodeId which was previously found to be invalid has been referenced again.
                    if (target == null)
                    {
                        return null;
                    }

                    handle.Node = target;
                    handle.Validated = true;
                    return handle.Node;
                }

                target = null;
            }

            try
            {
                // check if the node id has been parsed.
                DaParsedNodeId parsedNodeId = handle.ParsedNodeId as DaParsedNodeId;

                if (parsedNodeId == null)
                {
                    return null;
                }

                NodeState root = null;
                DaElement element = null;
                ComDaClient client = m_system.SelectClient(context, false);

                // validate a branch or item.
                if (parsedNodeId.RootType == DaModelUtils.DaElement)
                {
                    element = client.FindElement(parsedNodeId.RootId);

                    // branch does not exist.
                    if (element == null)
                    {
                        return null;
                    }

                    // create a temporary object to use for the operation.
                    root = DaModelUtils.ConstructElement(context, element, NamespaceIndex);
                    root.Handle = element;

                    AddAdditionalElementReferences(SystemContext, root);
                }

                // validate an property.
                else if (parsedNodeId.RootType == DaModelUtils.DaProperty)
                {
                    element = client.FindElement(parsedNodeId.RootId);

                    // branch does not exist.
                    if (element == null)
                    {
                        return null;
                    }

                    // validate the property.
                    DaProperty property = client.FindProperty(parsedNodeId.RootId, parsedNodeId.PropertyId);

                    // property does not exist.
                    if (property == null)
                    {
                        return null;
                    }

                    // create a temporary object to use for the operation.
                    root = DaModelUtils.ConstructProperty(context, element.ItemId, property, NamespaceIndex);
                    root.Handle = property;

                    AddAdditionalElementReferences(SystemContext, root);
                }

                // unknown root type.
                else
                {
                    return null;
                }

                // all done if no components to validate.
                if (String.IsNullOrEmpty(parsedNodeId.ComponentPath))
                {
                    handle.Validated = true;
                    handle.Node = target = root;
                    return handle.Node;
                }

                // validate component.
                NodeState component = root.FindChildBySymbolicName(context, parsedNodeId.ComponentPath);

                // component does not exist.
                if (component == null)
                {
                    return null;
                }

                // found a valid component.
                handle.Validated = true;
                handle.Node = target = component;
                return handle.Node;
            }
            finally
            {
                // store the node in the cache to optimize subsequent lookups.
                if (cache != null)
                {
                    cache.Add(handle.NodeId, target);
                }
            }
        }
コード例 #22
0
        /// <summary>
        /// Verifies that the specified node exists.
        /// </summary>
        protected override NodeState ValidateNode(
            ServerSystemContext context,
            NodeHandle handle,
            IDictionary<NodeId, NodeState> cache)
        {
            // not valid if no root.
            if (handle == null)
            {
                return null;
            }

            // check if previously validated.
            if (handle.Validated)
            {
                return handle.Node;
            }

            // lookup in operation cache.
            NodeState target = FindNodeInCache(context, handle, cache);

            if (target != null)
            {
                handle.Node = target;
                handle.Validated = true;
                return handle.Node;
            }

            // put root into operation cache.
            if (cache != null)
            {
                cache[handle.NodeId] = target;
            }

            handle.Node = target;
            handle.Validated = true;
            return handle.Node;
        }
コード例 #23
0
        /// <summary>
        /// Called after creating a MonitoredItem.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="handle">The handle for the node.</param>
        /// <param name="monitoredItem">The monitored item.</param>
        protected override void OnMonitoredItemCreated(
            ServerSystemContext context,
            NodeHandle handle,
            MonitoredItem monitoredItem)
        {
            // check if the variable needs to be sampled.
            if (monitoredItem.AttributeId == Attributes.Value)
            {
                BaseVariableState variable = handle.Node as BaseVariableState;

                if (variable != null && variable.MinimumSamplingInterval > 0)
                {
                    CreateSampledItem(monitoredItem.SamplingInterval, monitoredItem);
                }
            }
            
            // check if diagnostics collection needs to be turned one.
            if (IsDiagnosticsNode(handle.Node))
            {
                monitoredItem.AlwaysReportUpdates = IsDiagnosticsStructureNode(handle.Node);
  
                if (monitoredItem.MonitoringMode != MonitoringMode.Disabled)
                {
                    m_diagnosticsMonitoringCount++;

                    if (m_diagnosticsScanTimer == null)
                    {
                        m_diagnosticsScanTimer = new Timer(DoScan, null, 1000, 1000);
                    }

                    DoScan(true);
                }
            }
        }
コード例 #24
0
        /// <summary>
        /// Verifies that the specified node exists.
        /// </summary>
        protected override NodeState ValidateNode(
            ServerSystemContext context,
            NodeHandle handle,
            IDictionary<NodeId, NodeState> cache)
        {
            // not valid if no root.
            if (handle == null)
            {
                return null;
            }

            // check if previously validated.
            if (handle.Validated)
            {
                return handle.Node;
            }

            // lookup in operation cache.
            NodeState target = FindNodeInCache(context, handle, cache);

            if (target != null)
            {
                handle.Node = target;
                handle.Validated = true;
                return handle.Node;
            }

            try
            {
                Opc.Ua.Client.Session client = GetClientSession(context);

                // get remote node.
                NodeId targetId = m_mapper.ToRemoteId(handle.NodeId);
                ILocalNode node = client.ReadNode(targetId) as ILocalNode;

                if (node == null)
                {
                    return null;
                }

                // map remote node to local object.
                switch (node.NodeClass)
                {
                    case NodeClass.ObjectType:
                    {
                        BaseObjectTypeState value = new BaseObjectTypeState();
                        value.IsAbstract = ((IObjectType)node).IsAbstract;
                        target = value;
                        break;
                    }

                    case NodeClass.VariableType:
                    {
                        BaseVariableTypeState value = new BaseDataVariableTypeState();
                        value.IsAbstract = ((IVariableType)node).IsAbstract;
                        value.Value = m_mapper.ToLocalValue(((IVariableType)node).Value);
                        value.DataType = m_mapper.ToLocalId(((IVariableType)node).DataType);
                        value.ValueRank = ((IVariableType)node).ValueRank;
                        value.ArrayDimensions = new ReadOnlyList<uint>(((IVariableType)node).ArrayDimensions);
                        target = value;
                        break;
                    }

                    case NodeClass.DataType:
                    {
                        DataTypeState value = new DataTypeState();
                        value.IsAbstract = ((IDataType)node).IsAbstract;
                        target = value;
                        break;
                    }

                    case NodeClass.ReferenceType:
                    {
                        ReferenceTypeState value = new ReferenceTypeState();
                        value.IsAbstract = ((IReferenceType)node).IsAbstract;
                        value.InverseName = ((IReferenceType)node).InverseName;
                        value.Symmetric = ((IReferenceType)node).Symmetric;
                        target = value;
                        break;
                    }

                    case NodeClass.Object:
                    {
                        BaseObjectState value = new BaseObjectState(null);
                        value.EventNotifier = ((IObject)node).EventNotifier;
                        target = value;
                        break;
                    }

                    case NodeClass.Variable:
                    {
                        BaseDataVariableState value = new BaseDataVariableState(null);
                        value.Value = m_mapper.ToLocalValue(((IVariable)node).Value);
                        value.DataType = m_mapper.ToLocalId(((IVariable)node).DataType);
                        value.ValueRank = ((IVariable)node).ValueRank;
                        value.ArrayDimensions = new ReadOnlyList<uint>(((IVariable)node).ArrayDimensions);
                        value.AccessLevel = ((IVariable)node).AccessLevel;
                        value.UserAccessLevel = ((IVariable)node).UserAccessLevel;
                        value.Historizing = ((IVariable)node).Historizing;
                        value.MinimumSamplingInterval = ((IVariable)node).MinimumSamplingInterval;
                        target = value;
                        break;
                    }

                    case NodeClass.Method:
                    {
                        MethodState value = new MethodState(null);
                        value.Executable = ((IMethod)node).Executable;
                        value.UserExecutable = ((IMethod)node).UserExecutable;
                        target = value;
                        break;
                    }

                    case NodeClass.View:
                    {
                        ViewState value = new ViewState();
                        value.ContainsNoLoops = ((IView)node).ContainsNoLoops;
                        target = value;
                        break;
                    }
                }

                target.NodeId = handle.NodeId;
                target.BrowseName = m_mapper.ToLocalName(node.BrowseName);
                target.DisplayName = node.DisplayName;
                target.Description = node.Description;
                target.WriteMask = node.WriteMask;
                target.UserWriteMask = node.UserWriteMask;
                target.Handle = node;
                target.OnCreateBrowser = OnCreateBrowser;
            }

            // ignore errors.
            catch
            {
                return null;
            }

            // put root into operation cache.
            if (cache != null)
            {
                cache[handle.NodeId] = target;
            }

            handle.Node = target;
            handle.Validated = true;
            return handle.Node;
        }
コード例 #25
0
        /// <summary>
        /// Called after changing the MonitoringMode for a MonitoredItem.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="handle">The handle for the node.</param>
        /// <param name="monitoredItem">The monitored item.</param>
        /// <param name="previousMode">The previous monitoring mode.</param>
        /// <param name="monitoringMode">The current monitoring mode.</param>
        protected override void OnMonitoringModeChanged(
            ServerSystemContext context,
            NodeHandle handle,
            MonitoredItem monitoredItem,
            MonitoringMode previousMode,
            MonitoringMode monitoringMode)
        {
            if (previousMode != MonitoringMode.Disabled)
            {
                m_diagnosticsMonitoringCount--;
            }

            if (monitoringMode != MonitoringMode.Disabled)
            {
                m_diagnosticsMonitoringCount++;
            }
                
            if (m_diagnosticsMonitoringCount == 0 && m_diagnosticsScanTimer != null)
            {
                if (m_diagnosticsScanTimer != null)
                {
                    m_diagnosticsScanTimer.Dispose();
                    m_diagnosticsScanTimer = null;
                }
            }
            else
            {
                if (m_diagnosticsScanTimer != null)
                {
                    m_diagnosticsScanTimer = new Timer(DoScan, null, 1000, 1000);
                }
            }
        }
コード例 #26
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;
                }

                NodeState node = null;

                if (!PredefinedNodes.TryGetValue(nodeId, out node))
                {
                    return null;
                }

                NodeHandle handle = new NodeHandle();

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

                return handle;
            } 
        }
コード例 #27
0
        /// <summary>
        /// Verifies that the specified node exists.
        /// </summary>
        protected override NodeState ValidateNode(
            ServerSystemContext context,
            NodeHandle handle,
            IDictionary<NodeId, NodeState> cache)
        {
            // not valid if no root.
            if (handle == null)
            {
                return null;
            }

            // check if previously validated.
            if (handle.Validated)
            {
                return handle.Node;
            }

            NodeState target = null;

            // check if already in the cache.
            if (cache != null)
            {
                if (cache.TryGetValue(handle.NodeId, out target))
                {
                    // nulls mean a NodeId which was previously found to be invalid has been referenced again.
                    if (target == null)
                    {
                        return null;
                    }

                    handle.Node = target;
                    handle.Validated = true;
                    return handle.Node;
                }

                target = null;
            }

            try
            {
                // check if the node id has been parsed.
                HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId;

                if (parsedNodeId == null)
                {
                    return null;
                }

                ComHdaClient client = (ComHdaClient)m_system.SelectClient(context, false);

                switch (parsedNodeId.RootType)
                {
                    case HdaModelUtils.HdaBranch:
                    {
                        ComHdaBrowserClient browser = new ComHdaBrowserClient(client, null);
                        target = browser.FindBranch(context, parsedNodeId.RootId, NamespaceIndex);
                        browser.Dispose();
                        break;
                    }

                    case HdaModelUtils.HdaItem:
                    {
                        HdaItem[] items = client.GetItems(parsedNodeId.RootId);

                        if (items[0].Error < 0)
                        {
                            return null;
                        }

                        try
                        {
                            string browseName = null;

                            if (!m_configuration.ItemIdParser.Parse(client, m_configuration, parsedNodeId.RootId, out browseName))
                            {
                                HdaAttributeValue[] attributes = client.ReadAttributeValues(items[0].ServerHandle, OpcRcw.Hda.Constants.OPCHDA_ITEMID);
                                browseName = attributes[0].Value as string;
                            }

                            target = new HdaItemState(items[0].ItemId, browseName, NamespaceIndex);
                        }
                        finally
                        {
                            client.ReleaseItemHandles(items);
                        }

                        break;
                    }

                    case HdaModelUtils.HdaItemAttribute:
                    {
                        bool[] results = client.ValidateItemIds(parsedNodeId.RootId);

                        if (!results[0])
                        {
                            return null;
                        }

                        target = client.FindItemAttribute(parsedNodeId.RootId, parsedNodeId.AttributeId, NamespaceIndex);
                        break;
                    }

                    case HdaModelUtils.HdaItemAnnotations:
                    {
                        bool[] results = client.ValidateItemIds(parsedNodeId.RootId);

                        if (!results[0])
                        {
                            return null;
                        }

                        target = client.FindItemAnnotations(parsedNodeId.RootId, NamespaceIndex);
                        break;
                    }

                    case HdaModelUtils.HdaItemConfiguration:
                    {
                        bool[] results = client.ValidateItemIds(parsedNodeId.RootId);

                        if (results == null || !results[0])
                        {
                            return null;
                        }

                        target = HdaModelUtils.GetItemConfigurationNode(parsedNodeId.RootId, NamespaceIndex);
                        target.OnCreateBrowser = OnCreateItemConfigurationBrowser;
                        break;
                    }

                    case HdaModelUtils.HdaAggregate:
                    {
                        target = client.FindAggregate(parsedNodeId.AggregateId, NamespaceIndex);
                        break;
                    }
                }

                // check if found.
                if (target == null)
                {
                    return null;
                }

                // found a valid component.
                handle.Validated = true;
                handle.Node = target;

                return handle.Node;
            }
            finally
            {
                // store the node in the cache to optimize subsequent lookups.
                if (cache != null)
                {
                    cache.Add(handle.NodeId, target);
                }
            }
        }
コード例 #28
0
        /// <summary>
        /// Reads the initial value for a monitored item.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="handle">The item handle.</param>
        /// <param name="monitoredItem">The monitored item.</param>
        protected virtual void ReadInitialValue(
            ServerSystemContext context,
            NodeHandle handle,
            MonitoredItem monitoredItem)
        {
            DataValue initialValue = new DataValue();

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

            ServiceResult error = handle.Node.ReadAttribute(
                context,
                monitoredItem.AttributeId,
                monitoredItem.IndexRange,
                monitoredItem.DataEncoding,
                initialValue);

            monitoredItem.QueueValue(initialValue, error);
        }
コード例 #29
0
        /// <summary>
        /// Creates a new history request.
        /// </summary>
        private HistoryReadRequest CreateHistoryReadRequest(
            ServerSystemContext context,
            ReadEventDetails details,
            NodeHandle handle,
            HistoryReadValueId nodeToRead)
        {
            FilterContext filterContext = new FilterContext(context.NamespaceUris, context.TypeTable, context.PreferredLocales);
            LinkedList<BaseEventState> events = new LinkedList<BaseEventState>();

            for (ReportType ii = ReportType.FluidLevelTest; ii <= ReportType.InjectionTest; ii++)
            {
                DataView view = null;

                if (handle.Node is WellState)
                {
                    view = m_generator.ReadHistoryForWellId(
                        ii,
                        (string)handle.Node.NodeId.Identifier,
                        details.StartTime,
                        details.EndTime);
                }
                else
                {
                    view = m_generator.ReadHistoryForArea(
                        ii,
                        handle.Node.NodeId.Identifier as string,
                        details.StartTime,
                        details.EndTime);
                }

                LinkedListNode<BaseEventState> pos = events.First;
                bool sizeLimited = (details.StartTime == DateTime.MinValue || details.EndTime == DateTime.MinValue);

                foreach (DataRowView row in view)
                {
                    // check if reached max results.
                    if (sizeLimited)
                    {
                        if (events.Count >= details.NumValuesPerNode)
                        {
                            break;
                        }
                    }

                    BaseEventState e = m_generator.GetReport(context, NamespaceIndex, ii, row.Row);

                    if (details.Filter.WhereClause != null && details.Filter.WhereClause.Elements.Count > 0)
                    {
                        if (!details.Filter.WhereClause.Evaluate(filterContext, e))
                        {
                            continue;
                        }
                    }

                    bool inserted = false;

                    for (LinkedListNode<BaseEventState> jj = pos; jj != null; jj = jj.Next)
                    {
                        if (jj.Value.Time.Value > e.Time.Value)
                        {
                            events.AddBefore(jj, e);
                            pos = jj;
                            inserted = true;
                            break;
                        }
                    }

                    if (!inserted)
                    {
                        events.AddLast(e);
                        pos = null;
                    }
                }
            }

            HistoryReadRequest request = new HistoryReadRequest();
            request.Events = events;
            request.TimeFlowsBackward = details.StartTime == DateTime.MinValue || (details.EndTime != DateTime.MinValue && details.EndTime < details.StartTime);
            request.NumValuesPerNode = details.NumValuesPerNode;
            request.Filter = details.Filter;
            request.FilterContext = filterContext;
            return request;
        }
コード例 #30
0
        /// <summary>
        /// Revises an aggregate filter (may require knowledge of the variable being used). 
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="handle">The handle.</param>
        /// <param name="samplingInterval">The sampling interval for the monitored item.</param>
        /// <param name="queueSize">The queue size for the monitored item.</param>
        /// <param name="filterToUse">The filter to revise.</param>
        /// <returns>Good if the </returns>
        protected virtual StatusCode ReviseAggregateFilter(
            ServerSystemContext context,
            NodeHandle handle,
            double samplingInterval,
            uint queueSize,
            ServerAggregateFilter filterToUse)
        {
            if (filterToUse.ProcessingInterval < samplingInterval)
            {
                filterToUse.ProcessingInterval = samplingInterval;
            }

            if (filterToUse.ProcessingInterval < Server.AggregateManager.MinimumProcessingInterval)
            {
                filterToUse.ProcessingInterval = Server.AggregateManager.MinimumProcessingInterval;
            }

            DateTime earliestStartTime = DateTime.UtcNow.AddMilliseconds(-(queueSize - 1)*filterToUse.ProcessingInterval);

            if (earliestStartTime > filterToUse.StartTime)
            {
                filterToUse.StartTime = earliestStartTime;
            }

            if (filterToUse.AggregateConfiguration.UseServerCapabilitiesDefaults)
            {
                filterToUse.AggregateConfiguration = Server.AggregateManager.GetDefaultConfiguration(null);
            }

            return StatusCodes.Good;
        }
コード例 #31
0
        /// <summary>
        /// Verifies that the specified node exists.
        /// </summary>
        protected override NodeState ValidateNode(
            ServerSystemContext context,
            NodeHandle handle,
            IDictionary<NodeId, NodeState> cache)
        {
            // not valid if no root.
            if (handle == null)
            {
                return null;
            }

            // check if previously validated.
            if (handle.Validated)
            {
                return handle.Node;
            }
            
            // TBD

            return null;
        }
コード例 #32
0
        /// <summary>
        /// Verifies that the specified node exists.
        /// </summary>
        protected virtual NodeState ValidateNode(
            ServerSystemContext context, 
            NodeHandle handle,
            IDictionary<NodeId,NodeState> cache)
        {
            // lookup in cache.
            NodeState target = FindNodeInCache(context, handle, cache);

            if (target != null)
            {
                handle.Node = target;
                handle.Validated = true;
                return handle.Node;
            }

            // return default.
            return handle.Node;
        }