/// <summary> /// Creates a new <see cref="FrameParser"/>. /// </summary> /// <param name="checkSumValidationFrameTypes">Frame types that should perform check-sum validation; default to <see cref="GSF.PhasorProtocols.CheckSumValidationFrameTypes.AllFrames"/></param> /// <param name="trustHeaderLength">Determines if header lengths should be trusted over parsed byte count.</param> /// <param name="draftRevision">The <see cref="IEEEC37_118.DraftRevision"/> of this <see cref="FrameParser"/>.</param> public FrameParser(CheckSumValidationFrameTypes checkSumValidationFrameTypes = CheckSumValidationFrameTypes.AllFrames, bool trustHeaderLength = true, DraftRevision draftRevision = DraftRevision.Std2005) : base(checkSumValidationFrameTypes, trustHeaderLength) { // Initialize protocol synchronization bytes for this frame parser base.ProtocolSyncBytes = new[] { GemstonePhasorProtocolls.Common.SyncByte }; DraftRevision = draftRevision; }
/// <summary> /// Gets the version number for a given <see cref="DraftRevision"/>. /// </summary> /// <param name="revision">Target <see cref="DraftRevision"/>.</param> /// <returns>Version number for the specified <paramref name="revision"/>.</returns> public static string ToVersionString(this DraftRevision revision) { return(revision switch { DraftRevision.Draft6 => "Draft 6", DraftRevision.Std2005 => "2005", DraftRevision.Std2011 => "2011", _ => "Unknown", });
/// <summary> /// Gets the version number for a given <see cref="DraftRevision"/>. /// </summary> /// <param name="revision">Target <see cref="DraftRevision"/>.</param> /// <returns>Version number for the specified <paramref name="revision"/>.</returns> public static string ToVersionString(this DraftRevision revision) { switch (revision) { case DraftRevision.Draft6: return("Draft 6"); case DraftRevision.Std2005: return("2005"); case DraftRevision.Std2011: return("2011"); default: return("Unknown"); } }
/// <summary> /// Creates a new <see cref="CommonFrameHeader"/> from specified parameters. /// </summary> /// <param name="configurationFrame">IEEE C37.118 <see cref="ConfigurationFrame1"/> if available.</param> /// <param name="typeID">The IEEE C37.118 specific frame type of this frame.</param> /// <param name="idCode">The ID code of this frame.</param> /// <param name="timestamp">The timestamp of this frame.</param> /// <param name="version">The target version for this IEEE C37.118 frame.</param> public CommonFrameHeader(ConfigurationFrame1 configurationFrame, FrameType typeID, ushort idCode, Ticks timestamp, DraftRevision version) { m_frameType = typeID; m_idCode = idCode; m_timestamp = timestamp; m_version = (byte)version; m_timebase = (UInt24)100000; if (configurationFrame is null) { return; } // Hang on to configured frame rate and ticks per frame m_framesPerSecond = configurationFrame.FrameRate; m_ticksPerFrame = Ticks.PerSecond / (double)m_framesPerSecond; }
// 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); }