// Static Methods /// <summary> /// Creates a new IEEE C37.118 <see cref="ConfigurationFrame2"/> based on provided protocol independent <paramref name="baseConfigurationFrame"/>. /// </summary> /// <param name="baseConfigurationFrame">Protocol independent <see cref="GSF.PhasorProtocols.Anonymous.ConfigurationFrame"/>.</param> /// <param name="timeBase">Timebase to use for fraction second resolution.</param> /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> to use for the new <see cref="ConfigurationFrame2"/></param>. /// <returns>A new IEEE C37.118 <see cref="ConfigurationFrame2"/>.</returns> public static ConfigurationFrame2 CreateConfigurationFrame(ConfigurationFrame baseConfigurationFrame, uint timeBase, LineFrequency nominalFrequency) { ConfigurationCell newCell; uint maskValue; // Create a new IEEE C37.118 configuration frame 2 using base configuration ConfigurationFrame2 configurationFrame = new ConfigurationFrame2(timeBase, baseConfigurationFrame.IDCode, DateTime.UtcNow.Ticks, baseConfigurationFrame.FrameRate); foreach (GSF.PhasorProtocols.Anonymous.ConfigurationCell baseCell in baseConfigurationFrame.Cells) { // Create a new IEEE C37.118 configuration cell (i.e., a PMU configuration) newCell = new ConfigurationCell(configurationFrame, baseCell.IDCode, nominalFrequency); // Update other cell level attributes newCell.StationName = baseCell.StationName; newCell.IDLabel = baseCell.IDLabel; newCell.PhasorDataFormat = baseCell.PhasorDataFormat; newCell.PhasorCoordinateFormat = baseCell.PhasorCoordinateFormat; newCell.FrequencyDataFormat = baseCell.FrequencyDataFormat; newCell.AnalogDataFormat = baseCell.AnalogDataFormat; // Add phasor definitions foreach (IPhasorDefinition phasorDefinition in baseCell.PhasorDefinitions) { newCell.PhasorDefinitions.Add(new PhasorDefinition(newCell, phasorDefinition.Label, phasorDefinition.ScalingValue, phasorDefinition.Offset, phasorDefinition.PhasorType, null)); } // Add frequency definition newCell.FrequencyDefinition = new FrequencyDefinition(newCell, baseCell.FrequencyDefinition.Label); // Add analog definitions foreach (IAnalogDefinition analogDefinition in baseCell.AnalogDefinitions) { newCell.AnalogDefinitions.Add(new AnalogDefinition(newCell, analogDefinition.Label, analogDefinition.ScalingValue, analogDefinition.Offset, analogDefinition.AnalogType)); } // Add digital definitions foreach (IDigitalDefinition digitalDefinition in baseCell.DigitalDefinitions) { // Attempt to derive user defined mask value if available DigitalDefinition anonymousDigitalDefinition = digitalDefinition as DigitalDefinition; if (anonymousDigitalDefinition != null) { maskValue = anonymousDigitalDefinition.MaskValue; } else { maskValue = 0U; } newCell.DigitalDefinitions.Add(new GSF.PhasorProtocols.IEEEC37_118.DigitalDefinition(newCell, digitalDefinition.Label, maskValue.LowWord(), maskValue.HighWord())); } // Add new PMU configuration (cell) to protocol specific configuration frame configurationFrame.Cells.Add(newCell); } return(configurationFrame); }
/// <summary> /// Converts given IEEE C37.118 type 2 <paramref name="sourceFrame"/> into a type 3 configuration frame. /// </summary> /// <param name="sourceFrame">Source configuration frame.</param> /// <returns>New <see cref="ConfigurationFrame3"/> frame based on source configuration.</returns> /// <remarks> /// This function allow an explicit downcast of a typical IEEE C37.118 configuration type 2 frame to a type 3 frame. /// </remarks> public static ConfigurationFrame3 CastToConfigurationFrame3(ConfigurationFrame2 sourceFrame) { ConfigurationFrame3 derivedFrame; // Create a new IEEE C37.118 configuration frame converted from equivalent configuration information derivedFrame = new ConfigurationFrame3(sourceFrame.Timebase, sourceFrame.IDCode, sourceFrame.Timestamp, sourceFrame.FrameRate); foreach (ConfigurationCell sourceCell in sourceFrame.Cells) { // Create new derived configuration cell ConfigurationCell derivedCell = new ConfigurationCell(derivedFrame, sourceCell.IDCode, sourceCell.NominalFrequency); string stationName = sourceCell.StationName; string idLabel = sourceCell.IDLabel; if (!string.IsNullOrWhiteSpace(stationName)) { derivedCell.StationName = stationName.TruncateLeft(derivedCell.MaximumStationNameLength); } if (!string.IsNullOrWhiteSpace(idLabel)) { derivedCell.IDLabel = idLabel.TruncateLeft(derivedCell.IDLabelLength); } derivedCell.PhasorCoordinateFormat = sourceCell.PhasorCoordinateFormat; derivedCell.PhasorAngleFormat = sourceCell.PhasorAngleFormat; derivedCell.PhasorDataFormat = sourceCell.PhasorDataFormat; derivedCell.FrequencyDataFormat = sourceCell.FrequencyDataFormat; derivedCell.AnalogDataFormat = sourceCell.AnalogDataFormat; // Create equivalent derived phasor definitions foreach (PhasorDefinition sourcePhasor in sourceCell.PhasorDefinitions) { derivedCell.PhasorDefinitions.Add(new PhasorDefinition(derivedCell, sourcePhasor.Label, sourcePhasor.ScalingValue, sourcePhasor.Offset, sourcePhasor.PhasorType, null)); } // Create equivalent derived frequency definition FrequencyDefinition sourceFrequency = sourceCell.FrequencyDefinition as FrequencyDefinition; derivedCell.FrequencyDefinition = new FrequencyDefinition(derivedCell, sourceFrequency?.Label); // Create equivalent derived analog definitions (assuming analog type = SinglePointOnWave) foreach (IAnalogDefinition sourceAnalog in sourceCell.AnalogDefinitions) { derivedCell.AnalogDefinitions.Add(new AnalogDefinition(derivedCell, sourceAnalog.Label, sourceAnalog.ScalingValue, sourceAnalog.Offset, sourceAnalog.AnalogType)); } // Create equivalent derived digital definitions foreach (IDigitalDefinition sourceDigital in sourceCell.DigitalDefinitions) { derivedCell.DigitalDefinitions.Add(new GSF.PhasorProtocols.IEEEC37_118.DigitalDefinition(derivedCell, sourceDigital.Label, 0, 0)); } // Add cell to frame derivedFrame.Cells.Add(derivedCell); } return(derivedFrame); }
/// <summary> /// Creates a new IEEE C37.118 specific <see cref="IConfigurationFrame"/> based on provided protocol independent <paramref name="baseConfigurationFrame"/>. /// </summary> /// <param name="baseConfigurationFrame">Protocol independent <see cref="GSF.PhasorProtocols.Anonymous.ConfigurationFrame"/>.</param> /// <returns>A new IEEE C37.118 specific <see cref="IConfigurationFrame"/>.</returns> protected override IConfigurationFrame CreateNewConfigurationFrame(ConfigurationFrame baseConfigurationFrame) { // Create a new IEEE C37.118 configuration frame 2 using base configuration ConfigurationFrame2 configurationFrame = CreateConfigurationFrame(baseConfigurationFrame, m_timeBase, base.NominalFrequency); // After system has started any subsequent changes in configuration get indicated in the outgoing data stream bool configurationChanged = (object)m_configurationFrame != null; // Cache new IEEE C7.118 for later use Interlocked.Exchange(ref m_configurationFrame, configurationFrame); if (configurationChanged) { // Start adding configuration changed notification flag to data cells m_configurationChanged = true; m_notificationStartTime = DateTime.UtcNow.Ticks; } return(configurationFrame); }