Opc.Ua.Server.MinMaxAggregateCalculator.ComputeMinMax C# (CSharp) Method

ComputeMinMax() protected method

Calculate the Minimum, Maximum, MinimumActualTime and MaximumActualTime aggregates for the timeslice.
protected ComputeMinMax ( Opc.Ua.Server.TimeSlice slice, int valueType, bool returnActualTime ) : DataValue
slice Opc.Ua.Server.TimeSlice
valueType int
returnActualTime bool
return DataValue
        protected DataValue ComputeMinMax(TimeSlice slice, int valueType, bool returnActualTime)
        {
            // get the values in the slice.
            List<DataValue> values = GetValues(slice);

            // check for empty slice.
            if (values == null || values.Count == 0)
            {
                return GetNoDataValue(slice);
            }

            double minimumGoodValue = Double.MaxValue;
            double minimumUncertainValue = Double.MaxValue;
            double maximumGoodValue = Double.MinValue;
            double maximumUncertainValue = Double.MinValue;

            DateTime minimumGoodTimestamp = DateTime.MinValue;
            DateTime maximumGoodTimestamp = DateTime.MinValue;

            TypeInfo minimumOriginalType = null;
            TypeInfo maximumOriginalType = null;

            bool badValuesExist = false;
            bool duplicatesMinimumsExist = false;
            bool duplicatesMaximumsExist = false;
            bool goodValueExists = false;

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

                // ignore bad values.
                if (!IsGood(values[ii]))
                {
                    badValuesExist = true;
                    continue;
                }

                // convert to double.
                try
                {
                    currentValue = CastToDouble(values[ii]);
                }
                catch (Exception)
                {
                    badValuesExist = true;
                    continue;
                }

                // check for uncertain.
                if (StatusCode.IsUncertain(currentStatus))
                {
                    if (minimumUncertainValue > currentValue)
                    {
                        minimumUncertainValue = currentValue;
                    }

                    if (maximumUncertainValue < currentValue)
                    {
                        maximumUncertainValue = currentValue;
                    }

                    continue;
                }

                // check for new minimum.
                if (minimumGoodValue > currentValue)
                {
                    minimumGoodValue = currentValue;
                    minimumGoodTimestamp = currentTime;
                    minimumOriginalType = values[ii].WrappedValue.TypeInfo;
                    duplicatesMinimumsExist = false;
                    goodValueExists = true;
                }

                // check for duplicate minimums.
                else if (minimumGoodValue == currentValue)
                {
                    duplicatesMinimumsExist = true;
                }

                // check for new maximum.
                if (maximumGoodValue < currentValue)
                {
                    maximumGoodValue = currentValue;
                    maximumGoodTimestamp = currentTime;
                    maximumOriginalType = values[ii].WrappedValue.TypeInfo;
                    duplicatesMaximumsExist = false;
                    goodValueExists = true;
                }

                // check for duplicate maximums.
                else if (maximumGoodValue == currentValue)
                {
                    duplicatesMaximumsExist = true;
                }
            }

            // check if at least on good value exists.
            if (!goodValueExists)
            {
                return GetNoDataValue(slice);
            }

            // set the status code.
            StatusCode statusCode = StatusCodes.Good;

            // uncertain if any bad values exist.
            if (badValuesExist)
            {
                statusCode = StatusCodes.UncertainDataSubNormal;
            }

            // determine the calculated value to return.
            object processedValue = null;
            TypeInfo processedType = null;
            DateTime processedTimestamp = DateTime.MinValue;
            bool uncertainValueExists = false;
            bool duplicatesExist = false;

            if (valueType == 1)
            {
                processedValue = minimumGoodValue;
                processedTimestamp = minimumGoodTimestamp;
                processedType = minimumOriginalType;
                uncertainValueExists = minimumGoodValue > minimumUncertainValue;
                duplicatesExist = duplicatesMinimumsExist;
            }

            else if (valueType == 2)
            {
                processedValue = maximumGoodValue;
                processedTimestamp = maximumGoodTimestamp;
                processedType = maximumOriginalType;
                uncertainValueExists = maximumGoodValue < maximumUncertainValue;
                duplicatesExist = duplicatesMaximumsExist;
            }

            else if (valueType == 3)
            {
                processedValue = Math.Abs(maximumGoodValue - minimumGoodValue);
                processedType = TypeInfo.Scalars.Double;
                uncertainValueExists = maximumGoodValue < maximumUncertainValue || minimumGoodValue > minimumUncertainValue;
            }

            // set calculated if not returning actual time and value is not at the start time.
            if (!returnActualTime && processedTimestamp != slice.StartTime)
            {
                statusCode = statusCode.SetAggregateBits(AggregateBits.Calculated);
            }

            // set the multiple values flags.
            if (duplicatesExist)
            {
                statusCode = statusCode.SetAggregateBits(statusCode.AggregateBits | AggregateBits.MultipleValues);
            }

            // convert back to original datatype.
            if (processedType != null && processedType.BuiltInType != BuiltInType.Double)
            {
                processedValue = TypeInfo.Cast(processedValue, TypeInfo.Scalars.Double, processedType.BuiltInType);
            }
            else
            {
                processedType = TypeInfo.Scalars.Double;
            }

            // create processed value.
            DataValue value = new DataValue();
            value.WrappedValue = new Variant(processedValue, processedType);
            value.StatusCode = statusCode;

            if (returnActualTime)
            {
                value.SourceTimestamp = processedTimestamp;
                value.ServerTimestamp = processedTimestamp;
            }
            else
            {
                value.SourceTimestamp = GetTimestamp(slice);
                value.ServerTimestamp = GetTimestamp(slice);
            }

            return value;
        }