public static void test() { MyAccessDriver a = new MyAccessDriver("C:/Users/tzhou9/Desktop/Adpater Practice/Data/db1_0804_2015_010100.mdb"); string strCom = "Select * from FRURawData1026 where Index < 40000 and Index > 30000"; OleDbDataReader reader = a.ExecuteSQL(strCom); List<IMeasurement> measurements = new List<IMeasurement>(); while (reader.Read()) { DateTime sampleDateTime = DateTime.Parse(reader["Sample_Date&Time"].ToString()); double measurementValue = Convert.ToDouble(reader["FinalFreq"]); IMeasurement newMeasurement = new Measurement(); newMeasurement.Timestamp = new GSF.Ticks(sampleDateTime); measurements.Add(newMeasurement); //newMeasurement.AdjustedValue = measurementValue; //newMeasurement.Key = MeasurementKey.LookUpBySignalID(Guid.Parse("895ef95e-46a4-11e5-a8c0-b8ca3ab306c3")); //MessageBox.Show(MeasurementKey.LookUpBySignalID(Guid.Parse("895ef95e-46a4-11e5-a8c0-b8ca3ab306c3")).ID.ToString()); } LocalOutputAdapter local = new LocalOutputAdapter(); local.Run(measurements.ToArray()); Console.WriteLine("finish"); }
/// <summary> /// Initializes this <see cref="FileImporter"/>. /// </summary> public override void Initialize() { base.Initialize(); Dictionary<string, string> settings = Settings; string setting; // Load optional parameters if (settings.TryGetValue("importPath", out setting)) m_importPath = setting; else throw new InvalidOperationException("No import path was specified for EPRI file importer - this is a required setting."); if (settings.TryGetValue("inputInterval", out setting)) m_inputInterval = double.Parse(setting); if (settings.TryGetValue("measurementsPerInterval", out setting)) m_measurementsPerInterval = int.Parse(setting); if (settings.TryGetValue("simulateTimestamp", out setting)) m_simulateTimestamp = setting.ParseBoolean(); if (settings.TryGetValue("timestampFormat", out setting)) m_timestampFormat = setting; if (settings.TryGetValue("skipRows", out setting)) int.TryParse(setting, out m_skipRows); if (m_skipRows < 0) m_skipRows = 0; settings.TryGetValue("useHighResolutionInputTimer", out setting); if (string.IsNullOrEmpty(setting)) setting = "false"; UseHighResolutionInputTimer = setting.ParseBoolean(); if (!UseHighResolutionInputTimer) m_looseTimer = new Timer(); // Load column mappings: if (settings.TryGetValue("columnMappings", out setting)) { Dictionary<int, string> columnMappings = new Dictionary<int, string>(); int index; foreach (KeyValuePair<string, string> mapping in setting.ParseKeyValuePairs()) { if (int.TryParse(mapping.Key, out index)) columnMappings[index] = mapping.Value; } if (!m_simulateTimestamp && !columnMappings.Values.Contains("Timestamp", StringComparer.OrdinalIgnoreCase)) throw new InvalidOperationException("One of the column mappings must be defined as a \"Timestamp\": e.g., columnMappings={0=Timestamp; 1=PPA:12; 2=PPA13}."); // In transverse mode, maximum measurements per interval is set to maximum columns in input file m_measurementsPerInterval = columnMappings.Keys.Max(); // Auto-assign output measurements based on column mappings OutputMeasurements = columnMappings.Where(kvp => string.Compare(kvp.Value, "Timestamp", StringComparison.OrdinalIgnoreCase) != 0).Select(kvp => { string measurementID = kvp.Value; IMeasurement measurement = new Measurement(); MeasurementKey key; Guid id; if (Guid.TryParse(measurementID, out id)) { key = MeasurementKey.LookUpBySignalID(id); } else { MeasurementKey.TryParse(measurementID, out key); } if (key.SignalID != Guid.Empty) { measurement.Metadata = key.Metadata; // Associate measurement with column index m_columnMappings[kvp.Key] = measurement; } return measurement; }).ToArray(); int timestampColumn = columnMappings.First(kvp => string.Compare(kvp.Value, "Timestamp", StringComparison.OrdinalIgnoreCase) == 0).Key; // Reserve a column mapping for timestamp value IMeasurement timestampMeasurement = new Measurement { Metadata = new MeasurementMetadata(null, "Timestamp", 0, 1, null) }; m_columnMappings[timestampColumn] = timestampMeasurement; } // Override input interval based on temporal processing interval if it's not set to default if (ProcessingInterval > -1) m_inputInterval = ProcessingInterval == 0 ? 1 : ProcessingInterval; if ((object)m_looseTimer != null) { m_looseTimer.Interval = m_inputInterval; m_looseTimer.AutoReset = true; m_looseTimer.Elapsed += m_looseTimer_Elapsed; } m_fileSystemWatcher = new SafeFileWatcher(m_importPath, "EPRI-VS-Output-*.csv"); m_fileSystemWatcher.Created += m_fileSystemWatcher_Created; m_fileSystemWatcher.Renamed += m_fileSystemWatcher_Renamed; }
// Creates an alarm event from the given alarm and measurement. private IMeasurement CreateAlarmEvent(Ticks timestamp, Alarm alarm) { IMeasurement alarmEvent = new Measurement() { Timestamp = timestamp, Value = (int)alarm.State }; if ((object)alarm.AssociatedMeasurementID != null) { Guid alarmEventID = alarm.AssociatedMeasurementID.GetValueOrDefault(); alarmEvent.Key = MeasurementKey.LookUpBySignalID(alarmEventID); } return alarmEvent; }
private void PollingOperation() { if ((object)m_modbusConnection == null) { return; } try { Ticks timestamp = DateTime.UtcNow.Ticks; Dictionary <MeasurementKey, Measurement> measurements = OutputMeasurements.Select(measurement => Measurement.Clone(measurement, timestamp)).ToDictionary(measurement => measurement.Key, measurement => measurement); Group[] groups = m_sequences.SelectMany(sequence => sequence.Groups).ToArray(); int measurementsReceived = 0; int overallTasksCompleted = 0; int overallTasksCount = m_sequences.Count + 1; OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, true, "Starting polling operation...", overallTasksCompleted, overallTasksCount)); OnStatusMessage(MessageLevel.Info, $"Executing poll operation {m_pollOperations + 1}."); // Handle read/write operations for sequence groups try { foreach (Sequence sequence in m_sequences) { foreach (Group group in sequence.Groups) { OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, false, $"Executing poll for {sequence.Type.ToString().ToLowerInvariant()} sequence group \"{group.Type}@{group.StartAddress}\"...", 0, group.PointCount)); switch (group.Type) { case RecordType.DI: group.DataValues = ReadDiscreteInputs(group.StartAddress, group.PointCount); break; case RecordType.CO: if (sequence.Type == SequenceType.Read) { group.DataValues = ReadCoils(group.StartAddress, group.PointCount); } else { WriteCoils(group.StartAddress, group.DataValues); } break; case RecordType.IR: group.DataValues = ReadInputRegisters(group.StartAddress, group.PointCount); break; case RecordType.HR: if (sequence.Type == SequenceType.Read) { group.DataValues = ReadHoldingRegisters(group.StartAddress, group.PointCount); } else { WriteHoldingRegisters(group.StartAddress, group.DataValues); } break; } OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, false, $"Completed poll for {sequence.Type.ToString().ToLowerInvariant()} sequence group \"{group.Type}@{group.StartAddress}\".", group.PointCount, group.PointCount)); Thread.Sleep(m_interSequenceGroupPollDelay); } OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, true, null, ++overallTasksCompleted, overallTasksCount)); } } catch { m_deviceErrors++; throw; } OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, false, "Processing derived values...", 0, m_derivedValues.Count)); // Calculate derived values foreach (KeyValuePair <MeasurementKey, DerivedValue> item in m_derivedValues) { DerivedValue derivedValue = item.Value; ushort[] dataValues = derivedValue.GetDataValues(groups); Measurement measurement; if (measurements.TryGetValue(item.Key, out measurement)) { // TODO: Properly interpret measurement types after GSF data type transport update switch (derivedValue.Type) { case DerivedType.String: if (derivedValue.AddressRecords.Count > 0) { m_derivedStrings[item.Key] = DeriveString(dataValues); measurementsReceived++; } else { OnStatusMessage(MessageLevel.Warning, $"No address records defined for derived String value \"{item.Key}\"."); } break; case DerivedType.Single: if (derivedValue.AddressRecords.Count > 1) { measurement.Value = DeriveSingle(dataValues[0], dataValues[1]); measurementsReceived++; } else { OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived Single value \"{item.Key}\", expected 2."); } break; case DerivedType.Double: if (derivedValue.AddressRecords.Count > 3) { measurement.Value = DeriveDouble(dataValues[0], dataValues[1], dataValues[2], dataValues[3]); measurementsReceived++; } else { OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived Double value \"{item.Key}\", expected 4."); } break; case DerivedType.UInt16: if (derivedValue.AddressRecords.Count > 0) { measurement.Value = dataValues[0]; measurementsReceived++; } else { OnStatusMessage(MessageLevel.Warning, $"No address records defined for UInt16 value \"{item.Key}\"."); } break; case DerivedType.Int32: if (derivedValue.AddressRecords.Count > 1) { measurement.Value = DeriveInt32(dataValues[0], dataValues[1]); measurementsReceived++; } else { OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived Int32 value \"{item.Key}\", expected 2."); } break; case DerivedType.UInt32: if (derivedValue.AddressRecords.Count > 1) { measurement.Value = DeriveUInt32(dataValues[0], dataValues[1]); measurementsReceived++; } else { OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived UInt32 value \"{item.Key}\", expected 2."); } break; case DerivedType.Int64: if (derivedValue.AddressRecords.Count > 3) { measurement.Value = DeriveInt64(dataValues[0], dataValues[1], dataValues[2], dataValues[3]); measurementsReceived++; } else { OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived Int64 value \"{item.Key}\", expected 4."); } break; case DerivedType.UInt64: if (derivedValue.AddressRecords.Count > 3) { measurement.Value = DeriveUInt64(dataValues[0], dataValues[1], dataValues[2], dataValues[3]); measurementsReceived++; } else { OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived UInt64 value \"{item.Key}\", expected 4."); } break; } } if (measurementsReceived % 20 == 0) { OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, false, null, measurementsReceived, m_derivedValues.Count)); } } OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, false, "Completed derived value processing.", m_derivedValues.Count, m_derivedValues.Count)); OnProgressUpdated(this, new ProgressUpdate(ProgressState.Succeeded, true, "Polling operation complete.", overallTasksCount, overallTasksCount)); OnNewMeasurements(measurements.Values.ToArray()); m_measurementsReceived += measurementsReceived; m_pollOperations++; } catch (Exception ex) { OnProgressUpdated(this, new ProgressUpdate(ProgressState.Failed, true, $"Failed during poll operation: {ex.Message}", 0, 1)); // Restart connection cycle when an exception occurs Start(); throw; } finally { m_measurementsExpected += OutputMeasurements.Length; } }
private Measurement GetMeasurement(Guid signalID) { DataRow[] rows = DataSource.Tables["ActiveMeasurements"].Select($"SignalID = '{signalID}'"); if (!rows.Any()) return null; Measurement measurement = new Measurement { Key = MeasurementKey.LookUpBySignalID(signalID), TagName = rows[0]["PointTag"].ToString(), Adder = Convert.ToDouble(rows[0]["Adder"]), Multiplier = Convert.ToDouble(rows[0]["Multiplier"]) }; return measurement; }
// Attempt to read the next record private bool ReadNextRecord(long currentTime) { try { List<IMeasurement> newMeasurements = new List<IMeasurement>(); long fileTime = 0; int timestampColumn = 0; string[] fields = m_inStream.ReadLine().ToNonNullString().Split(','); if (m_inStream.EndOfStream || fields.Length < m_columns.Count) return false; // Read time from Timestamp column in transverse mode if (m_transverse) { if (m_simulateTimestamp) { fileTime = currentTime; } else { timestampColumn = m_columnMappings.First(kvp => string.Compare(kvp.Value.TagName, "Timestamp", StringComparison.OrdinalIgnoreCase) == 0).Key; fileTime = long.Parse(fields[timestampColumn]); } } for (int i = 0; i < m_measurementsPerInterval; i++) { IMeasurement measurement; if (m_transverse) { // No measurement will be defined for timestamp column if (i == timestampColumn) continue; if (m_columnMappings.TryGetValue(i, out measurement)) { measurement = Measurement.Clone(measurement); measurement.Value = double.Parse(fields[i]); } else { measurement = new Measurement(); measurement.Metadata = MeasurementKey.Undefined.Metadata; measurement.Value = double.NaN; } if (m_simulateTimestamp) measurement.Timestamp = currentTime; else if (m_columns.ContainsKey("Timestamp")) measurement.Timestamp = fileTime; } else { measurement = new Measurement(); if (m_columns.ContainsKey("Signal ID")) { Guid measurementID = new Guid(fields[m_columns["Signal ID"]]); if (m_columns.ContainsKey("Measurement Key")) measurement.Metadata = MeasurementKey.LookUpOrCreate(measurementID, fields[m_columns["Measurement Key"]]).Metadata; else measurement.Metadata = MeasurementKey.LookUpBySignalID(measurementID).Metadata; } else if (m_columns.ContainsKey("Measurement Key")) { measurement.Metadata = MeasurementKey.Parse(fields[m_columns["Measurement Key"]]).Metadata; } if (m_simulateTimestamp) measurement.Timestamp = currentTime; else if (m_columns.ContainsKey("Timestamp")) measurement.Timestamp = long.Parse(fields[m_columns["Timestamp"]]); if (m_columns.ContainsKey("Value")) measurement.Value = double.Parse(fields[m_columns["Value"]]); } newMeasurements.Add(measurement); } OnNewMeasurements(newMeasurements); } catch (Exception ex) { OnProcessException(MessageLevel.Warning, ex); } return true; }
private Measurement GetMeasurement(Guid signalID) { MeasurementKey key = MeasurementKey.LookUpBySignalID(signalID); if (key.SignalID == Guid.Empty) return null; Measurement measurement = new Measurement { Metadata = key.Metadata, }; return measurement; }
/// <summary> /// Returns a new measurement equivalent to the one being wrapped. /// </summary> /// <returns>The wrapped measurement.</returns> public IMeasurement GetMeasurement() { Guid signalID = Guid.Parse(SignalID); IMeasurement measurement = new Measurement() { Metadata = new MeasurementMetadata(MeasurementKey.LookUpOrCreate(signalID, Source, unchecked((uint)ID)), TagName, Adder, Multiplier, null), Timestamp = Timestamp, Value = Value }; return measurement; }
/// <summary> /// Runs a constant loop to pull data from PI /// </summary> private void QueryData() { DateTime currentTime = StartTimeConstraint; if (currentTime == DateTime.MinValue) // handle real-time IAON session currentTime = DateTime.UtcNow; while (currentTime <= StopTimeConstraint) { try { DateTime endTime = currentTime.AddSeconds(m_queryTimeSpan); if (endTime <= DateTime.UtcNow) { DateTime localCurrentTime = currentTime.ToLocalTime(); DateTime localEndTime = endTime.ToLocalTime(); List<IMeasurement> measToAdd = new List<IMeasurement>(); foreach (PIPoint point in m_points) { AFValues values = point.RecordedValues(new AFTimeRange(new AFTime(localCurrentTime), new AFTime(localEndTime)), AFBoundaryType.Inside, null, false); foreach (AFValue value in values) { Measurement measurement = new Measurement(); measurement.Key = m_tagKeyMap[point.Name]; measurement.Value = Convert.ToDouble(value.Value); measurement.Timestamp = value.Timestamp.UtcTime; measToAdd.Add(measurement); } } if (measToAdd.Any()) { lock (m_measurements) { foreach (IMeasurement meas in measToAdd) { m_measurements.Add(meas); m_processedMeasurements++; } } } currentTime = endTime; m_queryTime = currentTime; } } catch (ThreadAbortException) { throw; } catch (Exception e) { OnProcessException(e); } Thread.Sleep(33); } }
/// <summary> /// Publish frame of time-aligned collection of measurement values that arrived within the defined lag time. /// </summary> /// <param name="frame">Frame of measurements with the same timestamp that arrived within lag time that are ready for processing.</param> /// <param name="index">Index of frame within a second ranging from zero to frames per second - 1.</param> protected override void PublishFrame(IFrame frame, int index) { IMeasurement[] available = frame.Measurements.Values.ToArray(); List <Guid> availableGuids = available.Select(item => item.Key.SignalID).ToList(); List <IMeasurement> outputmeasurements = new List <IMeasurement>(); m_numberOfFrames++; foreach (ThreePhaseSet set in m_threePhaseComponent) { bool hasP = availableGuids.Contains(set.Positive.SignalID); bool hasN = availableGuids.Contains(set.Negative.SignalID); //bool hasZ = availableGuids.Contains(set.Zero.SignalID); if (hasP && hasN) { double v1P = available.FirstOrDefault(item => (item.Key?.SignalID ?? Guid.Empty) == set.Positive.SignalID)?.Value ?? 0.0D; double v2N = available.FirstOrDefault(item => (item.Key?.SignalID ?? Guid.Empty) == set.Negative.SignalID)?.Value ?? 0.0D; if (v1P != 0.0D) { double unbalanced = v2N / v1P; Measurement outputMeasurement = new Measurement { Metadata = set.OutMapping.Metadata }; if (m_saveStats) { m_statisticsMapping[set.Positive.SignalID].Count++; if (unbalanced > m_statisticsMapping[set.Positive.SignalID].Maximum) { m_statisticsMapping[set.Positive.SignalID].Maximum = unbalanced; } if (unbalanced < m_statisticsMapping[set.Positive.SignalID].Minimum) { m_statisticsMapping[set.Positive.SignalID].Minimum = unbalanced; } if (unbalanced > set.Threshold) { m_statisticsMapping[set.Positive.SignalID].AlertCount++; } m_statisticsMapping[set.Positive.SignalID].Summation += unbalanced; m_statisticsMapping[set.Positive.SignalID].SquaredSummation += unbalanced * unbalanced; } outputmeasurements.Add(Measurement.Clone(outputMeasurement, unbalanced * 100.0D, frame.Timestamp)); } } if (!m_saveStats) { m_numberOfFrames = 0; } } // Reporting if necessary if ((m_numberOfFrames >= ReportingInterval && m_saveStats) && (m_threePhaseComponent.Count > 0)) { foreach (ThreePhaseSet set in m_threePhaseComponent) { Guid key = set.Positive.SignalID; Measurement statisticMeasurement = new Measurement { Metadata = m_statisticsMapping[key].Sum.Metadata }; outputmeasurements.Add(Measurement.Clone(statisticMeasurement, m_statisticsMapping[key].Summation, frame.Timestamp)); statisticMeasurement = new Measurement { Metadata = m_statisticsMapping[key].SqrD.Metadata }; outputmeasurements.Add(Measurement.Clone(statisticMeasurement, m_statisticsMapping[key].SquaredSummation, frame.Timestamp)); statisticMeasurement = new Measurement { Metadata = m_statisticsMapping[key].Min.Metadata }; outputmeasurements.Add(Measurement.Clone(statisticMeasurement, m_statisticsMapping[key].Minimum, frame.Timestamp)); statisticMeasurement = new Measurement { Metadata = m_statisticsMapping[key].Max.Metadata }; outputmeasurements.Add(Measurement.Clone(statisticMeasurement, m_statisticsMapping[key].Maximum, frame.Timestamp)); statisticMeasurement = new Measurement { Metadata = m_statisticsMapping[key].Total.Metadata }; outputmeasurements.Add(Measurement.Clone(statisticMeasurement, m_statisticsMapping[key].Count, frame.Timestamp)); statisticMeasurement = new Measurement { Metadata = m_statisticsMapping[key].Alert.Metadata }; outputmeasurements.Add(Measurement.Clone(statisticMeasurement, m_statisticsMapping[key].AlertCount, frame.Timestamp)); m_statisticsMapping[key].Reset(); m_numberOfFrames = 0; } } OnNewMeasurements(outputmeasurements); }
/// <summary> /// Reads values from the connection string and prepares this <see cref="PIRTInputAdapter"/> for connecting to PI /// </summary> public override void Initialize() { base.Initialize(); m_measurements = new List<IMeasurement>(); Dictionary<string, string> settings = Settings; string setting; if (!settings.TryGetValue("ServerName", out m_serverName)) throw new InvalidOperationException("Server name is a required setting for PI connections. Please add a server in the format servername=myservername to the connection string."); if (settings.TryGetValue("UserName", out setting)) m_userName = setting; else m_userName = null; if (settings.TryGetValue("Password", out setting)) m_password = setting; else m_password = null; if (settings.TryGetValue("ConnectTimeout", out setting)) m_connectTimeout = Convert.ToInt32(setting); else m_connectTimeout = PIConnection.DefaultConnectTimeout; if (!settings.TryGetValue("AutoAddOutput", out setting)) AutoAddOutput = false; else AutoAddOutput = bool.Parse(setting); if (settings.TryGetValue("UseEventPipes", out setting)) UseEventPipes = bool.Parse(setting); else UseEventPipes = false; if (settings.TryGetValue("QueryTimeSpan", out setting)) QueryTimeSpan = Convert.ToInt32(setting); else QueryTimeSpan = 5; if (AutoAddOutput) { var measurements = from row in DataSource.Tables["ActiveMeasurements"].AsEnumerable() where row["PROTOCOL"].ToString() == "PI" select row; List<IMeasurement> outputMeasurements = new List<IMeasurement>(); foreach (DataRow row in measurements) { var measurement = new Measurement(); var signalID = new Guid(row["SIGNALID"].ToString()); measurement.Key = MeasurementKey.LookUpOrCreate(signalID, row["ID"].ToString()); outputMeasurements.Add(measurement); } OutputMeasurements = outputMeasurements.ToArray(); OnOutputMeasurementsUpdated(); } }
static void ProcessMeasurements(object state) { while (true) { List<Measurement> measurements = new List<Measurement>(); Measurement measurement; for (int i = 1; i <= MeasurementCount; i++) { measurement = new Measurement { //Key = MeasurementKey.LookUpOrCreate("PPA", (uint)i), Key = MeasurementKey.LookUpOrCreate("DEVARCHIVE", (uint)i), Value = Random.Between(-65535.0D, 65536.0D), Timestamp = DateTime.UtcNow.Ticks }; measurements.Add(measurement); } publisher.QueueMeasurementsForProcessing(measurements); Thread.Sleep(33); } }
/// <summary> /// Publish frame of time-aligned collection of measurement values that arrived within the defined lag time. /// </summary> /// <param name="frame">Frame of measurements with the same timestamp that arrived within lag time that are ready for processing.</param> /// <param name="index">Index of frame within a second ranging from zero to frames per second - 1.</param> protected override void PublishFrame(IFrame frame, int index) { m_numberOfFrames++; MeasurementKey[] availableKeys = frame.Measurements.Values.MeasurementKeys(); foreach (Guid key in m_dataWindow.Keys) { int keyIndex = availableKeys.IndexOf(item => item.SignalID == key); m_dataWindow[key].Add(keyIndex > -1 ? frame.Measurements[availableKeys[keyIndex]].Value : double.NaN); } if (Reference != null) { int keyIndex = availableKeys.IndexOf(item => item.SignalID == Reference.SignalID); m_refWindow.Add(keyIndex > -1 ? frame.Measurements[availableKeys[keyIndex]].Value : double.NaN); } int currentWindowLength = m_dataWindow.Keys.Select(key => m_dataWindow[key].Count).Max(); if (currentWindowLength >= WindowLength) { List <IMeasurement> outputmeasurements = new List <IMeasurement>(); List <Guid> Keys = m_dataWindow.Keys.ToList(); foreach (Guid key in Keys) { double snr = CalculateSignalToNoise(m_dataWindow[key], key); Measurement outputMeasurement = new Measurement { Metadata = m_outputMapping[key].Metadata }; if (!double.IsNaN(snr) && m_saveStats) { m_statisticsMapping[key].Count++; if (snr > m_statisticsMapping[key].Maximum) { m_statisticsMapping[key].Maximum = snr; } if (snr < m_statisticsMapping[key].Minimum) { m_statisticsMapping[key].Minimum = snr; } if (snr > m_threshold) { m_statisticsMapping[key].AlertCount++; } m_statisticsMapping[key].Summation += snr; m_statisticsMapping[key].SquaredSummation += snr * snr; } outputmeasurements.Add(Measurement.Clone(outputMeasurement, snr, frame.Timestamp)); m_dataWindow[key].RemoveAt(0); if (!m_saveStats) { m_numberOfFrames = 0; } } m_refWindow.RemoveAt(0);; // Reporting if necessary if (m_numberOfFrames >= ReportingInterval && m_saveStats) { m_numberOfFrames = 0; foreach (Guid key in Keys) { Measurement stateMeasurement = new Measurement { Metadata = m_statisticsMapping[key].Sum.Metadata }; outputmeasurements.Add(Measurement.Clone(stateMeasurement, m_statisticsMapping[key].Summation, frame.Timestamp)); stateMeasurement = new Measurement { Metadata = m_statisticsMapping[key].SqrD.Metadata }; outputmeasurements.Add(Measurement.Clone(stateMeasurement, m_statisticsMapping[key].SquaredSummation, frame.Timestamp)); stateMeasurement = new Measurement { Metadata = m_statisticsMapping[key].Min.Metadata }; outputmeasurements.Add(Measurement.Clone(stateMeasurement, m_statisticsMapping[key].Minimum, frame.Timestamp)); stateMeasurement = new Measurement { Metadata = m_statisticsMapping[key].Max.Metadata }; outputmeasurements.Add(Measurement.Clone(stateMeasurement, m_statisticsMapping[key].Maximum, frame.Timestamp)); stateMeasurement = new Measurement { Metadata = m_statisticsMapping[key].Total.Metadata }; outputmeasurements.Add(Measurement.Clone(stateMeasurement, m_statisticsMapping[key].Count, frame.Timestamp)); stateMeasurement = new Measurement { Metadata = m_statisticsMapping[key].Alert.Metadata }; outputmeasurements.Add(Measurement.Clone(stateMeasurement, m_statisticsMapping[key].AlertCount, frame.Timestamp)); m_statisticsMapping[key].Reset(); } } OnNewMeasurements(outputmeasurements); } }
/// <summary> /// Initializes this <see cref="MetricImporter"/>. /// </summary> public override void Initialize() { base.Initialize(); Dictionary<string, string> settings = Settings; string setting; // Load optional parameters if (settings.TryGetValue("importPath", out setting)) m_importPath = setting; else throw new InvalidOperationException("No import path was specified for EPRI metric importer - this is a required setting."); if (settings.TryGetValue("inputInterval", out setting)) m_inputInterval = double.Parse(setting); if (settings.TryGetValue("measurementsPerInterval", out setting)) m_measurementsPerInterval = int.Parse(setting); if (settings.TryGetValue("simulateTimestamp", out setting)) m_simulateTimestamp = setting.ParseBoolean(); if (settings.TryGetValue("timestampFormat", out setting)) m_timestampFormat = setting; if (settings.TryGetValue("skipRows", out setting)) int.TryParse(setting, out m_skipRows); if (m_skipRows < 0) m_skipRows = 0; settings.TryGetValue("useHighResolutionInputTimer", out setting); if (string.IsNullOrEmpty(setting)) setting = "false"; UseHighResolutionInputTimer = setting.ParseBoolean(); if (!UseHighResolutionInputTimer) m_looseTimer = new System.Timers.Timer(); // Load column mappings: if (settings.TryGetValue("columnMappings", out setting)) { Dictionary<int, string> columnMappings = new Dictionary<int, string>(); int index; foreach (KeyValuePair<string, string> mapping in setting.ParseKeyValuePairs()) { if (int.TryParse(mapping.Key, out index)) columnMappings[index] = mapping.Value; } if (!m_simulateTimestamp && !columnMappings.Values.Contains("Timestamp", StringComparer.OrdinalIgnoreCase)) throw new InvalidOperationException("One of the column mappings must be defined as a \"Timestamp\": e.g., columnMappings={1=Timestamp; 2=PPA:12; 3=PPA13}."); // In transverse mode, maximum measurements per interval is set to maximum columns in input file m_measurementsPerInterval = columnMappings.Keys.Max(); // Auto-assign output measurements based on column mappings OutputMeasurements = columnMappings.Where(kvp => string.Compare(kvp.Value, "Timestamp", true) != 0).Select(kvp => { string measurementID = kvp.Value; IMeasurement measurement = new Measurement(); MeasurementKey key; Guid id; if (Guid.TryParse(measurementID, out id)) { measurement.Key = MeasurementKey.LookUpBySignalID(id); } else if (MeasurementKey.TryParse(measurementID, out key)) { measurement.Key = key; } if (measurement.ID != Guid.Empty) { try { DataRow[] filteredRows = DataSource.Tables["ActiveMeasurements"].Select(string.Format("SignalID = '{0}'", measurement.ID)); if (filteredRows.Length > 0) { DataRow row = filteredRows[0]; // Assign other attributes measurement.TagName = row["PointTag"].ToNonNullString(); measurement.Multiplier = double.Parse(row["Multiplier"].ToString()); measurement.Adder = double.Parse(row["Adder"].ToString()); } } catch { // Failure to lookup extra metadata is not catastrophic } // Associate measurement with column index m_columnMappings[kvp.Key] = measurement; } return measurement; }).ToArray(); int timestampColumn = columnMappings.First(kvp => string.Compare(kvp.Value, "Timestamp", true) == 0).Key; // Reserve a column mapping for timestamp value IMeasurement timestampMeasurement = new Measurement() { TagName = "Timestamp" }; m_columnMappings[timestampColumn] = timestampMeasurement; } // Override input interval based on temporal processing interval if it's not set to default if (ProcessingInterval > -1) m_inputInterval = ProcessingInterval == 0 ? 1 : ProcessingInterval; if ((object)m_looseTimer != null) { m_looseTimer.Interval = m_inputInterval; m_looseTimer.AutoReset = true; m_looseTimer.Elapsed += m_looseTimer_Elapsed; } m_fileSystemWatcher = new SafeFileWatcher(m_importPath, "EPRI-VS-Metrics-*.csv"); m_fileSystemWatcher.Created += m_fileSystemWatcher_Created; m_fileSystemWatcher.Renamed += m_fileSystemWatcher_Renamed; }
/// <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); }
// PI data updated handler private void m_dataUpdateObserver_DataUpdated(object sender, EventArgs<AFValue> e) { OnStatusMessage("DEBUG: Data observer event handler called with a new value: {0:N3}...", Convert.ToDouble(e.Argument.Value)); AFValue value = e.Argument; MeasurementKey key; OnStatusMessage("DEBUG: Data observer event handler looking up point ID {0:N0} in table...", value.PIPoint.ID); if ((object)value != null && m_tagKeyMap.TryGetValue(value.PIPoint.ID, out key)) { OnStatusMessage("DEBUG: Data observer event handler found point ID {0:N0} in table: {1}...", value.PIPoint.ID, key); Measurement measurement = new Measurement(); measurement.Key = key; measurement.Value = Convert.ToDouble(value.Value); measurement.Timestamp = value.Timestamp.UtcTime; OnNewMeasurements(new[] { measurement }); m_lastReceivedTimestamp = measurement.Timestamp; m_lastReceivedValue = measurement.Value; } else { OnStatusMessage("DEBUG: Data observer event handler did not find point ID {0:N0} in table...", value.PIPoint.ID); } }
/// <summary> /// Returns a new measurement equivalent to the one being wrapped. /// </summary> /// <returns>The wrapped measurement.</returns> public IMeasurement GetMeasurement() { Guid signalID = Guid.Parse(SignalID); IMeasurement measurement = new Measurement() { Adder = Adder, Key = MeasurementKey.LookUpOrCreate(signalID, Source, unchecked((uint)ID)), Multiplier = Multiplier, TagName = TagName, Timestamp = Timestamp, Value = Value }; return measurement; }