/// <summary> /// Raises the <see cref="FrameParserBase{TypeIndentifier}.ReceivedConfigurationFrame"/> event. /// </summary> /// <param name="frame"><see cref="IConfigurationFrame"/> to send to <see cref="FrameParserBase{TypeIndentifier}.ReceivedConfigurationFrame"/> event.</param> protected override void OnReceivedConfigurationFrame(IConfigurationFrame frame) { // We override this method so we can cache configuration 2 frame when it's received base.OnReceivedConfigurationFrame(frame); // Cache new configuration frame for parsing subsequent data frames... ConfigurationFrame2 configurationFrame2 = frame as ConfigurationFrame2; if (configurationFrame2 != null) { m_configurationFrame2 = configurationFrame2; } // TODO: Add handler for config3 frame }
// Static Methods // Attempts to cast given frame into an IEEE C37.118 configuration frame - theoretically this will // allow the same configuration frame to be used for any protocol implementation internal static ConfigurationFrame2 CastToDerivedConfigurationFrame(IConfigurationFrame sourceFrame, DraftRevision draftRevision) { // See if frame is already an IEEE C37.118 configuration frame, type 2 (if so, we don't need to do any work) ConfigurationFrame2 derivedFrame = sourceFrame as ConfigurationFrame2; if (derivedFrame == null) { // Create a new IEEE C37.118 configuration frame converted from equivalent configuration information ConfigurationCell derivedCell; IFrequencyDefinition sourceFrequency; // Assuming configuration frame 2 and timebase = 100000 if (draftRevision == DraftRevision.Draft7) { derivedFrame = new ConfigurationFrame2(100000, sourceFrame.IDCode, sourceFrame.Timestamp, sourceFrame.FrameRate); } else { derivedFrame = new ConfigurationFrame2Draft6(100000, sourceFrame.IDCode, sourceFrame.Timestamp, sourceFrame.FrameRate); } foreach (IConfigurationCell sourceCell in sourceFrame.Cells) { // Create new derived configuration cell 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 (IPhasorDefinition sourcePhasor in sourceCell.PhasorDefinitions) { derivedCell.PhasorDefinitions.Add(new PhasorDefinition(derivedCell, sourcePhasor.Label, sourcePhasor.ScalingValue, sourcePhasor.Offset, sourcePhasor.PhasorType, null)); } // Create equivalent derived frequency definition sourceFrequency = sourceCell.FrequencyDefinition; if (sourceFrequency != null) { 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 DigitalDefinition(derivedCell, sourceDigital.Label, 0, 0)); } // Add cell to frame derivedFrame.Cells.Add(derivedCell); } } return(derivedFrame); }
/// <summary> /// Casts the parsed <see cref="IChannelFrame"/> to its specific implementation (i.e., <see cref="DataFrame"/>, <see cref="ConfigurationFrame"/>, <see cref="CommandFrame"/> or <see cref="HeaderFrame"/>). /// </summary> /// <param name="frame"><see cref="IChannelFrame"/> that was parsed by <see cref="FrameImageParserBase{TTypeIdentifier,TOutputType}"/> that implements protocol specific common frame header interface.</param> protected override void OnReceivedChannelFrame(IChannelFrame frame) { // Raise abstract channel frame events as a priority (i.e., IDataFrame, IConfigurationFrame, etc.) base.OnReceivedChannelFrame(frame); // Raise IEEE C37.118 specific channel frame events, if any have been subscribed if (frame != null && (ReceivedDataFrame != null || ReceivedConfigurationFrame2 != null || ReceivedConfigurationFrame1 != null || ReceivedHeaderFrame != null || ReceivedCommandFrame != null)) { DataFrame dataFrame = frame as DataFrame; if (dataFrame != null) { if (ReceivedDataFrame != null) { ReceivedDataFrame(this, new EventArgs <DataFrame>(dataFrame)); } } else { // Configuration frame type 2 is more specific than type 1 (and more common), so we check it first ConfigurationFrame2 configFrame2 = frame as ConfigurationFrame2; if (configFrame2 != null) { if (ReceivedConfigurationFrame2 != null) { ReceivedConfigurationFrame2(this, new EventArgs <ConfigurationFrame2>(configFrame2)); } } else { ConfigurationFrame1 configFrame1 = frame as ConfigurationFrame1; if (configFrame1 != null) { if (ReceivedConfigurationFrame1 != null) { ReceivedConfigurationFrame1(this, new EventArgs <ConfigurationFrame1>(configFrame1)); } } else { HeaderFrame headerFrame = frame as HeaderFrame; if (headerFrame != null) { if (ReceivedHeaderFrame != null) { ReceivedHeaderFrame(this, new EventArgs <HeaderFrame>(headerFrame)); } } else { CommandFrame commandFrame = frame as CommandFrame; if (commandFrame != null) { if (ReceivedCommandFrame != null) { ReceivedCommandFrame(this, new EventArgs <CommandFrame>(commandFrame)); } } } } } } } }
// 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; }