// Static Methods /// <summary> /// Creates a new IEC 61850-90-5 (i.e., IEEE C37.118) <see cref="ConfigurationFrame"/> 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="ConfigurationFrame"/></param>. /// <returns>A new IEEE C37.118 <see cref="ConfigurationFrame"/>.</returns> public static ConfigurationFrame CreateConfigurationFrame(GSF.PhasorProtocols.Anonymous.ConfigurationFrame baseConfigurationFrame, uint timeBase, LineFrequency nominalFrequency) { ConfigurationCell newCell; uint maskValue; // Create a new IEEE C37.118 configuration frame 2 using base configuration ConfigurationFrame configurationFrame = new ConfigurationFrame(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.IEC61850_90_5.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> /// 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(GSF.PhasorProtocols.Anonymous.ConfigurationFrame baseConfigurationFrame) { // Create a new IEEE C37.118 configuration frame 2 using base configuration ConfigurationFrame 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 = m_configurationFrame != null; // Cache new configuration frame for later use Interlocked.Exchange(ref m_configurationFrame, configurationFrame); m_configurationRevision++; if (configurationChanged) { // Start adding configuration changed notification flag to data cells m_configurationChanged = true; m_notificationStartTime = DateTime.UtcNow.Ticks; } return(configurationFrame); }
/// <summary> /// Creates a new BPA PDCstream 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 BPA PDCstream specific <see cref="IConfigurationFrame"/>.</returns> protected override IConfigurationFrame CreateNewConfigurationFrame(GSF.PhasorProtocols.Anonymous.ConfigurationFrame baseConfigurationFrame) { int count = 0; // Fix ID labels to use BPA PDCstream 4 character label foreach (GSF.PhasorProtocols.Anonymous.ConfigurationCell baseCell in baseConfigurationFrame.Cells) { baseCell.StationName = baseCell.IDLabel.TruncateLeft(baseCell.MaximumStationNameLength); baseCell.IDLabel = DataSource.Tables["OutputStreamDevices"].Select($"IDCode={baseCell.IDCode}")[0]["BpaAcronym"].ToNonNullString(baseCell.IDLabel).TruncateLeft(4); // If no ID label was provided, we default to first 4 characters of station name if (string.IsNullOrEmpty(baseCell.IDLabel)) { string stationName = baseCell.StationName; string pmuID = count.ToString(); if (string.IsNullOrEmpty(stationName)) { stationName = "PMU"; } baseCell.IDLabel = stationName.Substring(0, 4 - pmuID.Length).ToUpper() + pmuID; } count++; } // Create a default INI file if one doesn't exist if (!File.Exists(IniFileName)) { using (StreamWriter iniFile = File.CreateText(IniFileName)) { iniFile.Write(GSF.PhasorProtocols.BPAPDCstream.ConfigurationFrame.GetIniFileImage(baseConfigurationFrame)); } } // Create a new BPA PDCstream configuration frame using base configuration ConfigurationFrame configurationFrame = new ConfigurationFrame(DateTime.UtcNow.Ticks, IniFileName, 1, RevisionNumber.Revision2, StreamType.Compact); foreach (GSF.PhasorProtocols.Anonymous.ConfigurationCell baseCell in baseConfigurationFrame.Cells) { // Create a new BPA PDCstream configuration cell (i.e., a PMU configuration) ConfigurationCell newCell = new ConfigurationCell(configurationFrame, baseCell.IDCode, NominalFrequency) { // Update other cell level attributes StationName = baseCell.StationName, IDLabel = baseCell.IDLabel, PhasorDataFormat = DataFormat.FixedInteger, PhasorCoordinateFormat = CoordinateFormat.Rectangular, FrequencyDataFormat = DataFormat.FixedInteger, AnalogDataFormat = DataFormat.FixedInteger }; // 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) { newCell.DigitalDefinitions.Add(new DigitalDefinition(newCell, digitalDefinition.Label)); } // Add new PMU configuration (cell) to protocol specific configuration frame configurationFrame.Cells.Add(newCell); } // Setup new configuration cells with their proper INI file settings configurationFrame.Refresh(true); // Cache new BPA PDCstream for later use Interlocked.Exchange(ref m_configurationFrame, configurationFrame); return(configurationFrame); }