private AFValue Calculate(AFTime time, AFAttributeList inputAttributes, AFValues inputValues) { if (time == null) { throw new ArgumentException("No timestamp"); } if (inputAttributes == null || inputAttributes.Count == 0) { throw new ArgumentException("No input attributes"); } if (inputValues == null || inputValues.Count == 0) { throw new ArgumentException(Resources.ERR_NoInputValues); } AFValue inVal; if (inputAttributes.Count > 0) { inVal = inputAttributes[0].GetValue(time); if (inVal == null) { throw new ApplicationException("Input value is null"); } else { AFEnumerationValue enumValue = inVal.Value as AFEnumerationValue; if (enumValue != null && enumValue.Value == 248) { // Attempting to handle an error when the output value is 248 instead of the NoData state return(AFValue.CreateSystemStateValue(this.Attribute, AFSystemStateCode.NoData, time)); } else { double keyValue = (double)inVal.Value; double resultValue = GetCalibratedValue(keyValue); if (!double.IsNaN(resultValue)) { return(new AFValue(this.Attribute, resultValue, inVal.Timestamp, this.Attribute.DefaultUOM)); } else { return(AFValue.CreateSystemStateValue(this.Attribute, AFSystemStateCode.NoData, time)); } } } } else { throw new ApplicationException(string.Format("Input attribute not found (#{0}", 1)); } }
private AFValue Calculation(AFTime time, AFValue measurement, AFValue low, AFValue high, AFValue lowlow, AFValue highhigh) { // Our custom ToDouble returns double.NaN for null, missing, bad data, or bad conversions. var numericMeasurement = ToDouble(measurement); if (double.IsNaN(numericMeasurement)) { // https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/M_OSIsoft_AF_Asset_AFValue_CreateSystemStateValue.htm return(AFValue.CreateSystemStateValue(Attribute, AFSystemStateCode.NoResult, time)); } // Remember: any or all of the limits could be null. In those bad cases, a double.NaN is sent. var calc = Calculation(numericMeasurement, ToDouble(low), ToDouble(high), ToDouble(lowlow), ToDouble(highhigh)); return(new AFValue(Attribute, calc, time)); }
private AFValue Calculate(AFTime time, AFAttributeList inputAttributes, AFValues inputValues) { if (time == null) { throw new ArgumentException("No timestamp"); } if (inputValues.Count == 0) { throw new ArgumentException(Resources.ERR_NoInputValues); } int bit; if (!int.TryParse(fBit, out bit)) { throw new ArgumentException(Resources.ERR_NoBitSpecified); } if (bit < 0 || bit > (int)BitEnum.bit31) { throw new ArgumentException(Resources.ERR_InvalidBit); } AFValue inVal = inputValues[0]; object objVal = inVal.Value; if (inVal.IsGood && objVal != null) { if (BitmaskCore.IsIntVal(objVal)) { ulong curVal = (ulong)BitmaskCore.ConvertToType(objVal, TypeCode.UInt64); int tempVal = BitmaskCore.GetBit(curVal, (byte)bit); return(new AFValue(base.Attribute, tempVal, inVal.Timestamp, Attribute.DefaultUOM)); } else { throw new ArgumentException(Resources.ERR_SourceAttributeMustBeAnIntegerType); } } else { return(AFValue.CreateSystemStateValue(Attribute, AFSystemStateCode.BadInput, inVal.Timestamp)); } }
private AFValue Calculate(AFValues inputValues) { MethodEnum method; if (!Enum.TryParse(ConvertMethod, out method)) { throw new ArgumentException(Resources.ERR_NoBitSpecified); } if (inputValues == null || inputValues.Count == 0) { throw new ArgumentException(Resources.ERR_NoInputValues); } AFValue inVal = inputValues[0]; AFDatabase db = inVal.Attribute.Database; if (db == null) { throw new ArgumentException("No db found"); } object objVal = inVal.Value; if (inVal.IsGood && objVal != null) { if (TransformerCore.IsNumericVal(objVal)) { AFValue newVal; switch (method) { default: case MethodEnum.None: newVal = new AFValue(objVal, inVal.Timestamp, inVal.UOM); break; case MethodEnum.Simple: var targetUOMAttrS = AFAttribute.FindAttribute("UOM", Attribute); newVal = Convert(inVal, db, targetUOMAttrS); break; case MethodEnum.Full: var sourceUOMAttr = AFAttribute.FindAttribute("UOM", inVal.Attribute); newVal = Convert(inVal, db, sourceUOMAttr); var targetUOMAttrF = AFAttribute.FindAttribute("UOM", Attribute); newVal = Convert(newVal, db, targetUOMAttrF); break; } return(newVal); } else { throw new ArgumentException(Resources.ERR_SourceAttributeMustBeAnIntegerType); } } else { return(AFValue.CreateSystemStateValue(Attribute, AFSystemStateCode.BadInput, inVal.Timestamp)); } }
public static AFValue CreateBadValue(this AFAttribute attribute, AFTime time) { return(AFValue.CreateSystemStateValue(attribute, AFSystemStateCode.NoResult, time)); }
private static void RecordedBulk( IEnumerable <PIPoint> PiPoints, AFTimeRange timeRange, int bulkPageSize, bool insertNoData, Action <List <AFValue> > insertData) { _logger.WarnFormat("QUERY (BULK) # - PERIOD: {1} to {2}, TAG_PAGE_SIZE {0},", bulkPageSize, timeRange.StartTime, timeRange.EndTime); PIPagingConfiguration pagingConfiguration = new PIPagingConfiguration(PIPageType.TagCount, bulkPageSize); PIPointList pointList = new PIPointList(PiPoints); try { // _logger.InfoFormat("Bulk query"); IEnumerable <AFValues> data = pointList.RecordedValues(timeRange, AFBoundaryType.Inside, String.Empty, false, pagingConfiguration).ToList(); _logger.InfoFormat("READ Recorded values between {0:G} and {1:G}. {2} values found", timeRange.StartTime.LocalTime, timeRange.EndTime.LocalTime, data.Sum(x => x.Count)); List <AFValue> singleListData = new List <AFValue>(); // inserting no data when backfilling if no data is found in the period if (insertNoData) { foreach (var valuesInPoint in data) { if (valuesInPoint.Count == 0) { var value = AFValue.CreateSystemStateValue(AFSystemStateCode.NoData, timeRange.EndTime); value.PIPoint = valuesInPoint.PIPoint; singleListData.Add(value); } } } singleListData.AddRange(data.SelectMany(x => x).ToList()); if (singleListData.Count == 0) { return; } insertData(singleListData); _logger.DebugFormat("returned {0} values to be written", singleListData.Count); } catch (OperationCanceledException ex) { _logger.Error(ex); _logger.Error(pagingConfiguration.Error); } catch (Exception ex) { _logger.Error(ex); } }
/// <summary> /// This method splits a point list into severall smaller lists and perform bulk calls on each list /// In parallel. /// </summary> private static void RecordedBulkParallel( IEnumerable <PIPoint> PiPoints, AFTimeRange timeRange, int maxDegOfParallel, int bulkParallelChunkSize, int bulkPageSize, bool insertNoData, Action <List <AFValue> > insertData, CancellationToken cancelToken) { _logger.WarnFormat("QUERY (BULK-P) # - PERIOD: {3} to {4} - MAX DEG. PAR. {0}, TAG_CHUNK_SIZE {1}, TAG_PAGE_SIZE {2},", maxDegOfParallel, bulkParallelChunkSize, bulkPageSize, timeRange.StartTime, timeRange.EndTime); // PARALLEL bulk var pointListList = PiPoints.ToList().ChunkBy(bulkParallelChunkSize); Parallel.ForEach(pointListList, new ParallelOptions { MaxDegreeOfParallelism = maxDegOfParallel, CancellationToken = cancelToken }, (pts, state, index) => { PIPagingConfiguration pagingConfiguration = new PIPagingConfiguration(PIPageType.TagCount, bulkPageSize); PIPointList pointList = new PIPointList(pts); try { // _logger.InfoFormat("Bulk query"); IEnumerable <AFValues> data = pointList.RecordedValues(timeRange, AFBoundaryType.Inside, String.Empty, false, pagingConfiguration).ToList(); _logger.InfoFormat("READ Recorded values between {0:G} and {1:G}. {2} values found", timeRange.StartTime.LocalTime, timeRange.EndTime.LocalTime, data.Sum(x => x.Count)); List <AFValue> singleListData = new List <AFValue>(); // inserting no data when backfilling if no data is found in the period if (insertNoData) { foreach (var valuesInPoint in data) { if (valuesInPoint.Count == 0) { var value = AFValue.CreateSystemStateValue(AFSystemStateCode.NoData, timeRange.EndTime); value.PIPoint = valuesInPoint.PIPoint; singleListData.Add(value); } } } singleListData.AddRange(data.SelectMany(x => x).ToList()); if (singleListData.Count == 0) { return; } insertData(singleListData); _logger.DebugFormat("returned {0} values to be written", singleListData.Count); } catch (OperationCanceledException ex) { _logger.Error(ex); _logger.Error(pagingConfiguration.Error); } catch (Exception ex) { _logger.Error(ex); } }); }
public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues) { if (!fChecked) { CheckConfig(); } try { // Note that timeContext is an object. // We need to examine it further in order to resolve it to an AFTime. AFTime time; if (timeContext is AFTime) { time = (AFTime)timeContext; } else if (timeContext is AFTimeRange) { var timeRange = (AFTimeRange)timeContext; time = (Attribute.Element is AFEventFrame) ? timeRange.StartTime : timeRange.EndTime; } else { time = AFTime.NowInWholeSeconds; } // Important to note that the order of inputValues matches the order of inputAttributes. if (inputAttributes == null || inputAttributes.Count == 0) { throw new ArgumentException("No input attributes"); } if (inputValues == null || inputValues.Count == 0) { throw new ArgumentException(Resources.ERR_NoInputValues); } if (TimestampType == "Attribute") { if (inputValues.Count > 1) { AFValue tsVal = inputValues[1]; object objVal = tsVal.Value; if (objVal != null) { if (Extensions.IsDateTimeVal(objVal)) { time = new AFTime(objVal); } else { throw new ApplicationException(string.Format("Timestamp attribute must be datetime type {0}", objVal.ToString())); } } else { throw new ApplicationException("Timestamp value is null"); } } else { throw new ApplicationException(string.Format("Input value not found (#{0}", 2)); } } if (inputAttributes.Count > 0) { AFValue inVal = inputAttributes[0].GetValue(time); if (inVal == null) { throw new ApplicationException("Input value is null"); } else { AFEnumerationValue enumValue = inVal.Value as AFEnumerationValue; if (enumValue != null && enumValue.Value == 248) { // Attempting to handle an error when the output value is 248 instead of the NoData state return(AFValue.CreateSystemStateValue(Attribute, AFSystemStateCode.NoData, time)); } else { return(new AFValue(Attribute, inVal.Value, inVal.Timestamp, Attribute.DefaultUOM)); } } } else { throw new ApplicationException(string.Format("Input attribute not found (#{0}", 1)); } } catch (Exception) { UnloadParameters(); throw; } }
public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues) { // Important to note that the order of inputValues matches the order of inputAttributes. // Note that timeContext is an object. // We need to examine it further in order to resolve it to an AFTime. AFTime time; if (timeContext is AFTime) { time = (AFTime)timeContext; } else if (timeContext is AFTimeRange) { var timeRange = (AFTimeRange)timeContext; time = (Attribute.Element is AFEventFrame) ? timeRange.StartTime : timeRange.EndTime; } else { time = AFTime.NowInWholeSeconds; } AFValue measurement = null; AFValue low = null; AFValue high = null; AFValue lowlow = null; AFValue highhigh = null; for (var i = 0; i < inputAttributes.Count; i++) { var inAttrTrait = inputAttributes[i].Trait; var inVal = inputValues[i]; if (i == 0) { measurement = inVal; } else if (inAttrTrait == AFAttributeTrait.LimitLo) { low = inVal; } else if (inAttrTrait == AFAttributeTrait.LimitHi) { high = inVal; } else if (inAttrTrait == AFAttributeTrait.LimitLoLo) { lowlow = inVal; } else if (inAttrTrait == AFAttributeTrait.LimitHiHi) { highhigh = inVal; } } // Remember any of the passed AFValues could be null if the limit trait is not defined. // This is a fact of life and reflects the many possibilities within a given process unit. // Our custom ToDouble returns double.NaN for null, missing, bad data, or bad conversions. var dMeasurement = ToDouble(measurement); if (double.IsNaN(dMeasurement)) { return(AFValue.CreateSystemStateValue(Attribute, AFSystemStateCode.NoResult, time)); } // Remember: any or all of the limits could be null. In those bad cases, a double.NaN is sent. double dLow = ToDouble(low); double dHigh = ToDouble(high); double dLowLow = ToDouble(lowlow); double dHighHigh = ToDouble(highhigh); int result; // If any limits were missing or bad, they will be a NaN here. // A NaN used in comparisons will return false, which is what we want below. That is, // a comparison will return true only if the limit is not NaN and the limit has been met. if (dMeasurement >= dHighHigh) { result = TripState.HighHigh; } else if (dMeasurement <= dLowLow) { result = TripState.LowLow; } else if (dMeasurement >= dHigh) { result = TripState.High; } else if (dMeasurement <= dLow) { result = TripState.Low; } else { result = TripState.None; } return(new AFValue(Attribute, result, time, Attribute.DefaultUOM, AFValueStatus.Good)); }