Opc.Ua.Server.AggregateCalculator.GetRegionsInValueSet C# (CSharp) Method

GetRegionsInValueSet() protected method

Returns the values in the list with simple bounds.
protected GetRegionsInValueSet ( List values, bool ignoreBadData, bool useSteppedCalculations ) : List
values List
ignoreBadData bool
useSteppedCalculations bool
return List
        protected List<SubRegion> GetRegionsInValueSet(List<DataValue> values, bool ignoreBadData, bool useSteppedCalculations)
        {
            // nothing to do if no data.
            if (values == null)
            {
                return null;
            }

            SubRegion currentRegion = null;
            List<SubRegion> regions = new List<SubRegion>();

            for (int ii = 0; ii < values.Count; ii++)
            {
                double currentValue = 0;
                DateTime currentTime = values[ii].SourceTimestamp;
                StatusCode currentStatus = values[ii].StatusCode;

                // convert to doubles to facilitate numeric calculations.
                if (StatusCode.IsNotBad(currentStatus))
                {
                    try
                    {
                        currentValue = CastToDouble(values[ii]);
                    }
                    catch (Exception)
                    {
                        currentStatus = StatusCodes.BadTypeMismatch;
                    }
                }
                else
                {
                    // use the previous value if end of region is bad.
                    if (currentRegion != null)
                    {
                        currentValue = currentRegion.StartValue;
                    }
                }

                // some aggregates ignore bad data so remove them from the set.
                if (ignoreBadData)
                {
                    // always keep the first region.
                    if (currentRegion != null)
                    {
                        if (!IsGood(values[ii]))
                        {
                            // set the status to sub normal if bad end data ignored.
                            if (StatusCode.IsNotBad(currentRegion.StatusCode))
                            {
                                currentRegion.StatusCode = StatusCodes.UncertainDataSubNormal;
                            }

                            // skip everything but the endpoint.
                            if (ii < values.Count - 1)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            if (!useSteppedCalculations && StatusCode.IsNotGood(values[ii].StatusCode))
                            {
                                currentRegion.StatusCode = StatusCodes.UncertainDataSubNormal;
                            }
                        }
                    }
                }

                if (currentRegion != null)
                {
                    // if using stepped calculations the end value is not used.
                    if (useSteppedCalculations)
                    {
                        currentRegion.EndValue = currentRegion.StartValue;
                    }

                    // using interpolated calculations means the end affects the status of the current region.
                    else
                    {
                        if (IsGood(values[ii]))
                        {
                            // handle case with uncertain end point.
                            if (StatusCode.IsNotGood(values[ii].StatusCode) && StatusCode.IsNotBad(currentRegion.StatusCode))
                            {
                                currentRegion.StatusCode = StatusCodes.UncertainDataSubNormal;
                            }

                            currentRegion.EndValue = currentValue;
                        }
                        else
                        {
                            if (StatusCode.IsNotBad(currentRegion.StatusCode))
                            {
                                currentRegion.StatusCode = StatusCodes.UncertainDataSubNormal;
                            }

                            if (ignoreBadData && StatusCode.IsNotBad(currentStatus))
                            {
                                currentRegion.EndValue = currentValue;
                            }
                        }
                    }

                    // if at end of data then duration is 1 tick.
                    // must be end of data if start of region is good yet end bound is bad.
                    if (!ignoreBadData && currentRegion != null && IsGood(currentRegion.DataPoint) && currentStatus == StatusCodes.BadNoData && ii == values.Count - 1)
                    {
                        currentRegion.Duration = 1;
                    }

                    // calculate region span.
                    else
                    {
                        // set uncertain status to bad if treat uncertain as bad is true.
                        if (StatusCode.IsUncertain(currentStatus) && !IsGood(values[ii]))
                        {
                            currentStatus = StatusCodes.BadNoData;
                        }

                        currentRegion.Duration = (currentTime - currentRegion.StartTime).TotalMilliseconds;
                    }
                     
                    regions.Add(currentRegion);
                }

                // start a new region.
                currentRegion = new SubRegion();
                currentRegion.StartValue = currentValue;
                currentRegion.EndValue = currentValue;
                currentRegion.StartTime = currentTime;
                currentRegion.StatusCode = currentStatus;
                currentRegion.DataPoint = values[ii];
            }

            return regions;
        }