/* TODO: Maybe find better spot */ public static void Save(string fileName, IMeasurement measurement) { var formatter = new BinaryFormatter(); using (var streamWriter = new StreamWriter(fileName, false)) { var amme = Encoding.ASCII.GetBytes(MeasurementFileMagicString); streamWriter.BaseStream.Write(amme, 0, MeasurementFileMagicString.Length); var version = Encoding.ASCII.GetBytes(Assembly.GetExecutingAssembly().GetName().Version.ToString().PadRight(16)); streamWriter.BaseStream.Write(version, 0, version.Length); var container = new MeasurementSerializationContainer() { TypeName = measurement.GetType().Name, Name = measurement.Name, Settings = measurement.Settings, Result = measurement.AnalysisResult }; formatter.Serialize(streamWriter.BaseStream, container); } }
/// <summary> /// Assign <see cref="IMeasurement"/> to its <see cref="IFrame"/>. /// </summary> /// <param name="frame"><see cref="IFrame"/> to assign <paramref name="measurement"/> to.</param> /// <param name="measurement"><see cref="IMeasurement"/> to assign to <paramref name="frame"/>.</param> /// <returns><c>true</c> if <see cref="IMeasurement"/> was successfully assigned to its <see cref="IFrame"/>.</returns> /// <remarks> /// In simple concentration scenarios all you need to do is assign a measurement to its frame based on /// time. In the case of a phasor data concentrator you need to assign a measurement to its particular /// location in its <see cref="IDataFrame"/> - so this method overrides the default behavior in order /// to accomplish this task. /// </remarks> protected override bool AssignMeasurementToFrame(IFrame frame, IMeasurement measurement) { // Make sure the measurement is a "SignalReferenceMeasurement" (it should be) SignalReferenceMeasurement signalMeasurement = measurement as SignalReferenceMeasurement; IDataFrame dataFrame = frame as IDataFrame; if (signalMeasurement != null && dataFrame != null) { PhasorValueCollection phasorValues; DigitalValueCollection digitalValues; AnalogValueCollection analogValues; SignalReference signal = signalMeasurement.SignalReference; IDataCell dataCell = dataFrame.Cells[signal.CellIndex]; int signalIndex = signal.Index; // Assign measurement to its destination field in the data cell based on signal type switch (signal.Type) { case SignalType.Angle: // Assign "phase angle" measurement to data cell phasorValues = dataCell.PhasorValues; if (phasorValues.Count >= signalIndex) phasorValues[signalIndex - 1].Angle = signalMeasurement.AdjustedValue; break; case SignalType.Magnitude: // Assign "phase magnitude" measurement to data cell phasorValues = dataCell.PhasorValues; if (phasorValues.Count >= signalIndex) phasorValues[signalIndex - 1].Magnitude = signalMeasurement.AdjustedValue; break; case SignalType.Frequency: // Assign "frequency" measurement to data cell dataCell.FrequencyValue.Frequency = signalMeasurement.AdjustedValue; break; case SignalType.DfDt: // Assign "dF/dt" measurement to data cell dataCell.FrequencyValue.DfDt = signalMeasurement.AdjustedValue; break; case SignalType.Status: // Assign "common status flags" measurement to data cell dataCell.CommonStatusFlags = unchecked((uint)signalMeasurement.AdjustedValue); break; case SignalType.Digital: // Assign "digital" measurement to data cell digitalValues = dataCell.DigitalValues; if (digitalValues.Count >= signalIndex) digitalValues[signalIndex - 1].Value = unchecked((ushort)signalMeasurement.AdjustedValue); break; case SignalType.Analog: // Assign "analog" measurement to data cell analogValues = dataCell.AnalogValues; if (analogValues.Count >= signalIndex) analogValues[signalIndex - 1].Value = signalMeasurement.AdjustedValue; break; } // Track total measurements sorted for frame - this will become total measurements published frame.PublishedMeasurements++; return true; } // This is not expected to occur - but just in case OnProcessException(new InvalidCastException(string.Format("Attempt was made to assign an invalid measurement to phasor data concentration frame, expected a \"SignalReferenceMeasurement\" but got a \"{0}\"", measurement.GetType().Name))); return false; }
/// <summary> /// Assign <see cref="IMeasurement"/> to its <see cref="IFrame"/>. /// </summary> /// <param name="frame"><see cref="IFrame"/> to assign <paramref name="measurement"/> to.</param> /// <param name="measurement"><see cref="IMeasurement"/> to assign to <paramref name="frame"/>.</param> /// <returns><c>true</c> if <see cref="IMeasurement"/> was successfully assigned to its <see cref="IFrame"/>.</returns> /// <remarks> /// In simple concentration scenarios all you need to do is assign a measurement to its frame based on /// time. In the case of a phasor data concentrator you need to assign a measurement to its particular /// location in its <see cref="IDataFrame"/> - so this method overrides the default behavior in order /// to accomplish this task. /// </remarks> protected override void AssignMeasurementToFrame(IFrame frame, IMeasurement measurement) { ConcurrentDictionary<MeasurementKey, IMeasurement> measurements = frame.Measurements; // Make sure the measurement is a "SignalReferenceMeasurement" (it should be) SignalReferenceMeasurement signalMeasurement = measurement as SignalReferenceMeasurement; IDataFrame dataFrame = frame as IDataFrame; if ((object)signalMeasurement != null && (object)dataFrame != null) { PhasorValueCollection phasorValues; SignalReference signal = signalMeasurement.SignalReference; IDataCell dataCell = dataFrame.Cells[signal.CellIndex]; int signalIndex = signal.Index; double signalValue = m_useAdjustedValue ? signalMeasurement.AdjustedValue : signalMeasurement.Value; // Assign measurement to its destination field in the data cell based on signal type switch (signal.Kind) { case SignalKind.Angle: // Assign "phase angle" measurement to data cell phasorValues = dataCell.PhasorValues; if (phasorValues.Count >= signalIndex) phasorValues[signalIndex - 1].Angle = Angle.FromDegrees(signalValue); break; case SignalKind.Magnitude: // Assign "phase magnitude" measurement to data cell phasorValues = dataCell.PhasorValues; if (phasorValues.Count >= signalIndex) phasorValues[signalIndex - 1].Magnitude = signalValue; break; case SignalKind.Frequency: // Assign "frequency" measurement to data cell dataCell.FrequencyValue.Frequency = signalValue; break; case SignalKind.DfDt: // Assign "dF/dt" measurement to data cell dataCell.FrequencyValue.DfDt = signalValue; break; case SignalKind.Status: // Assign "common status flags" measurement to data cell dataCell.CommonStatusFlags = unchecked((uint)signalValue); // Assign by arrival sorting flag for bad synchronization if (!dataCell.SynchronizationIsValid && AllowSortsByArrival && !IgnoreBadTimestamps) dataCell.DataSortingType = DataSortingType.ByArrival; break; case SignalKind.Digital: // Assign "digital" measurement to data cell DigitalValueCollection digitalValues = dataCell.DigitalValues; if (digitalValues.Count >= signalIndex) digitalValues[signalIndex - 1].Value = unchecked((ushort)signalValue); break; case SignalKind.Analog: // Assign "analog" measurement to data cell AnalogValueCollection analogValues = dataCell.AnalogValues; if (analogValues.Count >= signalIndex) analogValues[signalIndex - 1].Value = signalValue; break; case SignalKind.Quality: // Assign "quality flags" measurement to data frame dataFrame.QualityFlags = unchecked((uint)signalValue); break; } // So that we can accurately track the total measurements that were sorted into this frame, // we also assign measurement to frame's measurement dictionary - this is important since // in down-sampling scenarios more than one of the same measurement can be sorted into a frame // but this only needs to be counted as "one" sort so that when preemptive publishing is // enabled you can compare expected measurements to sorted measurements... measurements[measurement.Key] = measurement; return; } // This is not expected to occur - but just in case if ((object)signalMeasurement == null && (object)measurement != null) OnProcessException(new InvalidCastException(string.Format("Attempt was made to assign an invalid measurement to phasor data concentration frame, expected a \"SignalReferenceMeasurement\" but received a \"{0}\"", measurement.GetType().Name))); if ((object)dataFrame == null) OnProcessException(new InvalidCastException(string.Format("During measurement assignment, incoming frame was not a phasor data concentration frame, expected a type derived from \"IDataFrame\" but received a \"{0}\"", frame.GetType().Name))); }