/// <summary> /// Derives measurement value, downsampling if needed. /// </summary> /// <param name="measurement">New <see cref="IMeasurement"/> value.</param> /// <returns>New derived <see cref="IMeasurement"/> value, or null if value should not be assigned to <see cref="IFrame"/>.</returns> public IMeasurement DeriveMeasurementValue(IMeasurement measurement) { IMeasurement derivedMeasurement; List<IMeasurement> values; switch (m_downsamplingMethod) { case DownsamplingMethod.LastReceived: // Keep track of total number of derived measurements m_derivedMeasurements++; // This is the simplest case, just apply latest value return measurement; case DownsamplingMethod.Closest: // Get tracked measurement values if (m_measurements.TryGetValue(measurement.Key, out values)) { if ((object)values != null && values.Count > 0) { // Get first tracked value (should only be one for "Closest") derivedMeasurement = values[0]; if ((object)derivedMeasurement != null) { // Determine if new measurement's timestamp is closer to frame if (measurement.Timestamp < derivedMeasurement.Timestamp && measurement.Timestamp >= m_timestamp) { // This measurement came in out-of-order and is closer to frame timestamp, so // we sort this measurement instead of the original values[0] = measurement; // Keep track of total number of derived measurements m_derivedMeasurements++; return measurement; } // Prior measurement is closer to frame than new one return null; } } } // No prior measurement exists, track this initial one values = new List<IMeasurement> { measurement }; m_measurements[measurement.Key] = values; // Keep track of total number of derived measurements m_derivedMeasurements++; return measurement; case DownsamplingMethod.Filtered: // Get tracked measurement values if (m_measurements.TryGetValue(measurement.Key, out values)) { if ((object)values != null && values.Count > 0) { // Get first tracked value - we clone the measurement since we are updating its value derivedMeasurement = Measurement.Clone(values[0]); if ((object)derivedMeasurement != null) { // Get function defined for measurement value filtering MeasurementValueFilterFunction measurementValueFilter = derivedMeasurement.MeasurementValueFilter; // Default to average value filter if none is specified if (measurementValueFilter == null) measurementValueFilter = Measurement.AverageValueFilter; // Add new measurement to tracking collection if ((object)measurement != null) values.Add(measurement); // Perform filter calculation as specified by device measurement if (values.Count > 1) { derivedMeasurement.Value = measurementValueFilter(values); // Keep track of total number of derived measurements m_derivedMeasurements++; return derivedMeasurement; } // No change from existing measurement return null; } } } // No prior measurement exists, track this initial one values = new List<IMeasurement> { measurement }; m_measurements[measurement.Key] = values; // Keep track of total number of derived measurements m_derivedMeasurements++; return measurement; case DownsamplingMethod.BestQuality: // Get tracked measurement values if (m_measurements.TryGetValue(measurement.Key, out values)) { if ((object)values != null && values.Count > 0) { // Get first tracked value (should only be one for "BestQuality") derivedMeasurement = values[0]; if ((object)derivedMeasurement != null) { // Determine if new measurement's quality is better than existing one or if new measurement's timestamp is closer to frame if ( ( (!derivedMeasurement.ValueQualityIsGood() || !derivedMeasurement.TimestampQualityIsGood()) && (measurement.ValueQualityIsGood() || measurement.TimestampQualityIsGood()) ) || ( measurement.Timestamp < derivedMeasurement.Timestamp && measurement.Timestamp >= m_timestamp ) ) { // This measurement has a better quality or came in out-of-order and is closer to frame timestamp, so // we sort this measurement instead of the original values[0] = measurement; // Keep track of total number of derived measurements m_derivedMeasurements++; return measurement; } // Prior measurement is closer to frame than new one return null; } } } // No prior measurement exists, track this initial one values = new List<IMeasurement> { measurement }; m_measurements[measurement.Key] = values; // Keep track of total number of derived measurements m_derivedMeasurements++; return measurement; } return null; }
/// <summary> /// Gets a <see cref="Quality"/> value from a <see cref="IMeasurement"/> value. /// </summary> /// <param name="measurement"><see cref="IMeasurement"/> value to interpret.</param> /// <returns><see cref="Quality"/> value from a <see cref="IMeasurement"/> value.</returns> public static Quality HistorianQuality(this IMeasurement measurement) { return(measurement.IsDiscarded() ? Quality.DeletedFromProcessing : (measurement.ValueQualityIsGood() ? (measurement.TimestampQualityIsGood() ? Quality.Good : Quality.Old) : Quality.SuspectData)); }
/// <summary> /// Derives measurement value, downsampling if needed. /// </summary> /// <param name="measurement">New <see cref="IMeasurement"/> value.</param> /// <returns>New derived <see cref="IMeasurement"/> value, or null if value should not be assigned to <see cref="IFrame"/>.</returns> public IMeasurement DeriveMeasurementValue(IMeasurement measurement) { IMeasurement derivedMeasurement; List <IMeasurement> values; switch (m_downsamplingMethod) { case DownsamplingMethod.LastReceived: // Keep track of total number of derived measurements m_derivedMeasurements++; // This is the simplest case, just apply latest value return(measurement); case DownsamplingMethod.Closest: // Get tracked measurement values if (m_measurements.TryGetValue(measurement.Key, out values)) { if ((object)values != null && values.Count > 0) { // Get first tracked value (should only be one for "Closest") derivedMeasurement = values[0]; if ((object)derivedMeasurement != null) { // Determine if new measurement's timestamp is closer to frame if (measurement.Timestamp < derivedMeasurement.Timestamp && measurement.Timestamp >= m_timestamp) { // This measurement came in out-of-order and is closer to frame timestamp, so // we sort this measurement instead of the original values[0] = measurement; // Keep track of total number of derived measurements m_derivedMeasurements++; return(measurement); } // Prior measurement is closer to frame than new one return(null); } } } // No prior measurement exists, track this initial one values = new List <IMeasurement> { measurement }; m_measurements[measurement.Key] = values; // Keep track of total number of derived measurements m_derivedMeasurements++; return(measurement); case DownsamplingMethod.Filtered: // Get tracked measurement values if (m_measurements.TryGetValue(measurement.Key, out values)) { if ((object)values != null && values.Count > 0) { // Get first tracked value - we clone the measurement since we are updating its value derivedMeasurement = Measurement.Clone(values[0]); if ((object)derivedMeasurement != null) { // Get function defined for measurement value filtering MeasurementValueFilterFunction measurementValueFilter = derivedMeasurement.MeasurementValueFilter; // Default to average value filter if none is specified if (measurementValueFilter == null) { measurementValueFilter = Measurement.AverageValueFilter; } // Add new measurement to tracking collection if ((object)measurement != null) { values.Add(measurement); } // Perform filter calculation as specified by device measurement if (values.Count > 1) { derivedMeasurement.Value = measurementValueFilter(values); // Keep track of total number of derived measurements m_derivedMeasurements++; return(derivedMeasurement); } // No change from existing measurement return(null); } } } // No prior measurement exists, track this initial one values = new List <IMeasurement> { measurement }; m_measurements[measurement.Key] = values; // Keep track of total number of derived measurements m_derivedMeasurements++; return(measurement); case DownsamplingMethod.BestQuality: // Get tracked measurement values if (m_measurements.TryGetValue(measurement.Key, out values)) { if ((object)values != null && values.Count > 0) { // Get first tracked value (should only be one for "BestQuality") derivedMeasurement = values[0]; if ((object)derivedMeasurement != null) { // Determine if new measurement's quality is better than existing one or if new measurement's timestamp is closer to frame if ( ( (!derivedMeasurement.ValueQualityIsGood() || !derivedMeasurement.TimestampQualityIsGood()) && (measurement.ValueQualityIsGood() || measurement.TimestampQualityIsGood()) ) || ( measurement.Timestamp < derivedMeasurement.Timestamp && measurement.Timestamp >= m_timestamp ) ) { // This measurement has a better quality or came in out-of-order and is closer to frame timestamp, so // we sort this measurement instead of the original values[0] = measurement; // Keep track of total number of derived measurements m_derivedMeasurements++; return(measurement); } // Prior measurement is closer to frame than new one return(null); } } } // No prior measurement exists, track this initial one values = new List <IMeasurement> { measurement }; m_measurements[measurement.Key] = values; // Keep track of total number of derived measurements m_derivedMeasurements++; return(measurement); } return(null); }