A aggregate filter with additional state information.
Inheritance: AggregateFilter
コード例 #1
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.BadFilterNotAllowed;
                }
                
                range = property.Value as Range;
                
                if (range == null)
                {
                    return StatusCodes.BadFilterNotAllowed;
                }

                filterToUse = deadbandFilter;

                return StatusCodes.Good;
            }

            // no other type of filter supported.
            return StatusCodes.BadFilterNotAllowed;
        }
コード例 #2
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;
        }
コード例 #3
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 filter is acceptable.</returns>
        protected override StatusCode ReviseAggregateFilter(
            ServerSystemContext context,
            NodeHandle handle,
            double samplingInterval,
            uint queueSize,
            ServerAggregateFilter filterToUse)
        {
            // use the sampling interval to limit the processing interval.
            if (filterToUse.ProcessingInterval < samplingInterval)
            {
                filterToUse.ProcessingInterval = samplingInterval;
            }

            // check if an archive item.
            ArchiveItemState item = handle.Node as ArchiveItemState;

            if (item == null)
            {
                // no historial data so must start in the future.
                while (filterToUse.StartTime < DateTime.UtcNow)
                {
                    filterToUse.StartTime = filterToUse.StartTime.AddMilliseconds(filterToUse.ProcessingInterval);
                }

                // use suitable defaults for values which are are not archived items.
                filterToUse.AggregateConfiguration.UseServerCapabilitiesDefaults = false;
                filterToUse.AggregateConfiguration.UseSlopedExtrapolation = false;
                filterToUse.AggregateConfiguration.TreatUncertainAsBad = false;
                filterToUse.AggregateConfiguration.PercentDataBad = 100;
                filterToUse.AggregateConfiguration.PercentDataGood = 100;
                filterToUse.Stepped = true;
            }
            else
            {
                // use the archive acquisition sampling interval to limit the processing interval.
                if (filterToUse.ProcessingInterval < item.ArchiveItem.SamplingInterval)
                {
                    filterToUse.ProcessingInterval = item.ArchiveItem.SamplingInterval;
                }

                // ensure the buffer does not get overfilled.
                while (filterToUse.StartTime.AddMilliseconds(queueSize*filterToUse.ProcessingInterval) < DateTime.UtcNow)
                {
                    filterToUse.StartTime = filterToUse.StartTime.AddMilliseconds(filterToUse.ProcessingInterval);
                }

                filterToUse.Stepped = item.ArchiveItem.Stepped;

                // revise the configration.
                ReviseAggregateConfiguration(context, item, filterToUse.AggregateConfiguration);
            }

            return StatusCodes.Good;
        }