/// <summary> /// Raises the <see cref="ReceivedConfigurationFrame"/> event. /// </summary> /// <param name="frame"><see cref="IConfigurationFrame"/> to send to <see cref="ReceivedConfigurationFrame"/> event.</param> protected virtual void OnReceivedConfigurationFrame(IConfigurationFrame frame) { if ((object)ReceivedConfigurationFrame != null) { ReceivedConfigurationFrame(this, new EventArgs <IConfigurationFrame>(frame)); } }
private bool SaveDeviceConfiguration(IConfigurationFrame configFrame, ushort comPort, ushort idCode, ScanParameters scanParams) { try { AdoDataConnection connection = scanParams.Connection; TableOperations <SignalType> signalTypeTable = new(connection); string configConnectionMode = scanParams.ControllingConnection ? ControllingConnectionString : ListeningConnectionString; string connectionString = string.Format(ConnectionStringTemplate, comPort, Settings.BaudRate, Settings.Parity, Settings.StopBits, Settings.DataBits, Settings.DtrEnable, Settings.RtsEnable, configConnectionMode); ShowUpdateMessage($"{Tab2}Saving \"{configFrame.Cells[0].StationName}\" configuration received on COM{comPort} with ID code {idCode}..."); m_deviceSignalTypes ??= signalTypeTable.LoadSignalTypes("PMU").ToDictionary(key => key.Acronym, StringComparer.OrdinalIgnoreCase); m_phasorSignalTypes ??= signalTypeTable.LoadSignalTypes("Phasor").ToDictionary(key => key.Acronym, StringComparer.OrdinalIgnoreCase); SaveDeviceConnection(configFrame, connectionString, comPort, idCode, scanParams); return(true); } catch (Exception ex) { ShowUpdateMessage($"{Tab2}ERROR: Failed while saving \"{configFrame.Cells[0].StationName}\" configuration: {ex.Message}"); m_log.Publish(MessageLevel.Error, nameof(AutoConfigPortScanner), exception: ex); return(false); } }
/// <summary> /// Creates a new <see cref="ConfigurationCell3"/>. /// </summary> /// <param name="parent">The reference to parent <see cref="IConfigurationFrame"/> of this <see cref="ConfigurationCell3"/>.</param> public ConfigurationCell3(IConfigurationFrame parent) : base(parent, 0, Common.MaximumPhasorValues, Common.MaximumAnalogValues, Common.MaximumDigitalValues, false) { // Define new parsing state which defines constructors for key configuration values State = new ConfigurationCellParsingState( PhasorDefinition3.CreateNewDefinition, IEEEC37_118.FrequencyDefinition.CreateNewDefinition, AnalogDefinition3.CreateNewDefinition, DigitalDefinition3.CreateNewDefinition); }
/// <summary> /// Creates a new <see cref="DataFrameParsingState"/> from specified parameters. /// </summary> /// <param name="parsedBinaryLength">Binary length of the <see cref="IDataFrame"/> being parsed.</param> /// <param name="configurationFrame">Reference to the <see cref="IConfigurationFrame"/> associated with the <see cref="IDataFrame"/> being parsed.</param> /// <param name="createNewCellFunction">Reference to delegate to create new <see cref="IDataCell"/> instances.</param> /// <param name="trustHeaderLength">Determines if header lengths should be trusted over parsed byte count.</param> /// <param name="validateCheckSum">Determines if frame's check-sum should be validated.</param> public DataFrameParsingState(int parsedBinaryLength, IConfigurationFrame configurationFrame, CreateNewCellFunction <IDataCell> createNewCellFunction, bool trustHeaderLength, bool validateCheckSum) : base(parsedBinaryLength, createNewCellFunction, trustHeaderLength, validateCheckSum) { if (configurationFrame != null) { CellCount = configurationFrame.Cells.Count; m_configurationFrame = configurationFrame; } }
private void m_frameParser_ReceivedConfigurationFrame(object sender, EventArgs <IConfigurationFrame> e) { // Cache received configuration frame m_configurationFrame = e.Argument; ShowUpdateMessage($"{Tab2}Successfully received configuration frame!"); m_configurationWaitHandle.Set(); }
// Attempts to cast given frame into a Macrodyne configuration frame - theoretically this will // allow the same configuration frame to be used for any protocol implementation internal static ConfigurationFrame CastToDerivedConfigurationFrame(IConfigurationFrame sourceFrame, string configurationFileName, string deviceLabel) { // See if frame is already a Macrodyne frame (if so, we don't need to do any work) ConfigurationFrame derivedFrame = sourceFrame as ConfigurationFrame; if (derivedFrame == null) { // Create a new Macrodyne configuration frame converted from equivalent configuration information; Macrodyne only supports one device if (sourceFrame.Cells.Count > 0) { IConfigurationCell sourceCell = sourceFrame.Cells[0]; string stationName = sourceCell.StationName; if (string.IsNullOrEmpty(stationName)) { stationName = "Unit " + sourceCell.IDCode.ToString(); } stationName = stationName.TruncateLeft(8); derivedFrame = new ConfigurationFrame(Common.GetFormatFlagsFromPhasorCount(sourceFrame.Cells[0].PhasorDefinitions.Count), stationName, configurationFileName, deviceLabel); derivedFrame.IDCode = sourceFrame.IDCode; // Create new derived configuration cell ConfigurationCell derivedCell = new ConfigurationCell(derivedFrame); IFrequencyDefinition sourceFrequency; // Create equivalent derived phasor definitions foreach (IPhasorDefinition sourcePhasor in sourceCell.PhasorDefinitions) { derivedCell.PhasorDefinitions.Add(new PhasorDefinition(derivedCell, sourcePhasor.Label, sourcePhasor.PhasorType, null)); } // Create equivalent derived frequency definition sourceFrequency = sourceCell.FrequencyDefinition; if (sourceFrequency != null) { derivedCell.FrequencyDefinition = new FrequencyDefinition(derivedCell) { Label = sourceFrequency.Label }; } // Create equivalent derived digital definitions foreach (IDigitalDefinition sourceDigital in sourceCell.DigitalDefinitions) { derivedCell.DigitalDefinitions.Add(new DigitalDefinition(derivedCell, sourceDigital.Label)); } // Add cell to frame derivedFrame.Cells.Add(derivedCell); } } return(derivedFrame); }
/// <summary> /// Creates a new <see cref="ConfigurationCell"/>. /// </summary> /// <param name="parent">The reference to parent <see cref="IConfigurationFrame"/> of this <see cref="ConfigurationCell"/>.</param> public ConfigurationCell(IConfigurationFrame parent) : base(parent, 0, Common.MaximumPhasorValues, Common.MaximumAnalogValues, Common.MaximumDigitalValues) { // Define new parsing state which defines constructors for key configuration values State = new ConfigurationCellParsingState( Ieee1344.PhasorDefinition.CreateNewDefinition, Ieee1344.FrequencyDefinition.CreateNewDefinition, null, // IEEE 1344 doesn't define analogs Ieee1344.DigitalDefinition.CreateNewDefinition); }
/// <summary> /// Creates a new <see cref="ConfigurationCell"/>. /// </summary> /// <param name="parent">The reference to parent <see cref="IConfigurationFrame"/> of this <see cref="ConfigurationCell"/>.</param> public ConfigurationCell(IConfigurationFrame parent) : base(parent, 0, Common.MaximumPhasorValues, Common.MaximumAnalogValues, Common.MaximumDigitalValues) { // Define new parsing state which defines constructors for key configuration values State = new ConfigurationCellParsingState( BpaPdcStream.PhasorDefinition.CreateNewDefinition, BpaPdcStream.FrequencyDefinition.CreateNewDefinition, BpaPdcStream.AnalogDefinition.CreateNewDefinition, BpaPdcStream.DigitalDefinition.CreateNewDefinition); }
/// <summary> /// Creates a new <see cref="ConfigurationCell"/>. /// </summary> /// <param name="parent">The reference to parent <see cref="IConfigurationFrame"/> of this <see cref="ConfigurationCell"/>.</param> public ConfigurationCell(IConfigurationFrame parent) : base(parent, 0, Common.MaximumPhasorValues, Common.MaximumAnalogValues, Common.MaximumDigitalValues) { // Define new parsing state which defines constructors for key configuration values State = new ConfigurationCellParsingState( PhasorDefinition.CreateNewDefinition, IEEE1344.FrequencyDefinition.CreateNewDefinition, null, // IEEE 1344 doesn't define analogs DigitalDefinition.CreateNewDefinition); }
/// <summary> /// Creates a new <see cref="ConfigurationCellBase"/> from specified parameters. /// </summary> /// <param name="parent">The reference to parent <see cref="IConfigurationFrame"/> of this <see cref="ConfigurationCellBase"/>.</param> /// <param name="idCode">The numeric ID code for this <see cref="ConfigurationCellBase"/>.</param> /// <param name="maximumPhasors">Sets the maximum number of phasors for the <see cref="PhasorDefinitions"/> collection.</param> /// <param name="maximumAnalogs">Sets the maximum number of phasors for the <see cref="AnalogDefinitions"/> collection.</param> /// <param name="maximumDigitals">Sets the maximum number of phasors for the <see cref="DigitalDefinitions"/> collection.</param> /// <param name="fixedElementSize">Flag that indicates if collections elements have a fixed size.</param> protected ConfigurationCellBase(IConfigurationFrame parent, ushort idCode, int maximumPhasors, int maximumAnalogs, int maximumDigitals, bool fixedElementSize = true) : base(parent, idCode) { m_nominalFrequency = 60.0D; // Defaulting to 60Hz // We convert maximum counts to last valid indices (count - 1): m_phasorDefinitions = new PhasorDefinitionCollection(maximumPhasors - 1, fixedElementSize); m_analogDefinitions = new AnalogDefinitionCollection(maximumAnalogs - 1, fixedElementSize); m_digitalDefinitions = new DigitalDefinitionCollection(maximumDigitals - 1, fixedElementSize); }
/// <summary> /// Creates a new <see cref="ConfigurationCellBase"/> from specified parameters. /// </summary> /// <param name="parent">The reference to parent <see cref="IConfigurationFrame"/> of this <see cref="ConfigurationCellBase"/>.</param> /// <param name="idCode">The numeric ID code for this <see cref="ConfigurationCellBase"/>.</param> /// <param name="maximumPhasors">Sets the maximum number of phasors for the <see cref="PhasorDefinitions"/> collection.</param> /// <param name="maximumAnalogs">Sets the maximum number of phasors for the <see cref="AnalogDefinitions"/> collection.</param> /// <param name="maximumDigitals">Sets the maximum number of phasors for the <see cref="DigitalDefinitions"/> collection.</param> protected ConfigurationCellBase(IConfigurationFrame parent, ushort idCode, int maximumPhasors, int maximumAnalogs, int maximumDigitals) : base(parent, idCode) { m_nominalFrequency = LineFrequency.Hz60; // Defaulting to 60Hz // We convert maximum counts to last valid indicies (count - 1): m_phasorDefinitions = new PhasorDefinitionCollection(maximumPhasors - 1); m_analogDefinitions = new AnalogDefinitionCollection(maximumAnalogs - 1); m_digitalDefinitions = new DigitalDefinitionCollection(maximumDigitals - 1); }
private bool ScanPortWithIDCode(ushort comPort, ushort idCode, ScanParameters scanParams, CancellationToken cancellationToken) { string scanConnectionMode = scanParams.AutoStartParsingSequenceForScan ? ActiveScanConnectionString : PassiveScanConnectionString; string connectionString = string.Format(ConnectionStringTemplate, comPort, Settings.BaudRate, Settings.Parity, Settings.StopBits, Settings.DataBits, Settings.DtrEnable, Settings.RtsEnable, scanConnectionMode); ShowUpdateMessage($"{Tab1}Scanning COM{comPort} with ID code {idCode}..."); IConfigurationFrame configFrame = RequestDeviceConfiguration(connectionString, idCode, scanParams, cancellationToken); return(configFrame is not ConfigurationErrorFrame && SaveDeviceConfiguration(configFrame, comPort, idCode, scanParams)); }
public IEnumerable <AdaptSignal> GetSignals() { if (!m_ConfigFrameSource.Task.IsCompleted && m_ConfigFrameSource.Task.Status != TaskStatus.WaitingForActivation) { return(new List <AdaptSignal>()); } IConfigurationFrame configuration = m_ConfigFrameSource.Task.Result; if (configuration == null) { return(new List <AdaptSignal>()); } IEnumerable <AdaptSignal> analogs = configuration.Cells.SelectMany(cell => cell.AnalogDefinitions .Select(aD => new AdaptSignal(cell.IDCode.ToString() + ":" + aD.Label, aD.Label, cell.IDCode.ToString(), cell.FrameRate) { FramesPerSecond = cell.FrameRate, Phase = Phase.NONE, Type = MeasurementType.Analog })); IEnumerable <AdaptSignal> digitals = configuration.Cells.SelectMany(cell => cell.DigitalDefinitions .Select(aD => new AdaptSignal(cell.IDCode.ToString() + ":" + aD.Label, aD.Label, cell.IDCode.ToString(), cell.FrameRate) { FramesPerSecond = cell.FrameRate, Phase = Phase.NONE, Type = MeasurementType.Digital })); IEnumerable <AdaptSignal> phases = configuration.Cells.SelectMany(cell => cell.PhasorDefinitions .Select(aD => new AdaptSignal(cell.IDCode.ToString() + ":" + aD.Label + "-Ph", aD.Label + " Phase", cell.IDCode.ToString(), cell.FrameRate) { FramesPerSecond = cell.FrameRate, Phase = Phase.NONE, Type = aD.PhasorType == Gemstone.Numeric.EE.PhasorType.Current? MeasurementType.CurrentPhase : MeasurementType.VoltagePhase })); IEnumerable <AdaptSignal> magnitudes = configuration.Cells.SelectMany(cell => cell.PhasorDefinitions .Select(aD => new AdaptSignal(cell.IDCode.ToString() + ":" + aD.Label + "-Mag", aD.Label + " Magnitude", cell.IDCode.ToString(), cell.FrameRate) { FramesPerSecond = cell.FrameRate, Phase = Phase.NONE, Type = aD.PhasorType == Gemstone.Numeric.EE.PhasorType.Current ? MeasurementType.CurrentMagnitude : MeasurementType.VoltageMagnitude })); IEnumerable <AdaptSignal> frequency = configuration.Cells.Select(cell => new AdaptSignal(cell.IDCode.ToString() + cell.FrequencyDefinition.Label, cell.FrequencyDefinition.Label ?? "Frequency", cell.IDCode.ToString(), cell.FrameRate) { FramesPerSecond = cell.FrameRate, Phase = Phase.NONE, Type = MeasurementType.Frequency, }); return(magnitudes.Concat(phases).Concat(digitals).Concat(analogs).Concat(frequency)); }
/// <summary> /// Deserializes cached configuration, if available. /// </summary> /// <param name="configurationName">Name of the configuration to get file name for.</param> /// <param name="fromCache">Set to True retrieve from cache, False to retrieve from specified file name in <paramref name="configurationName"/></param> /// <returns>Cached configuration frame, or null if not available.</returns> public static IConfigurationFrame GetCachedConfiguration(string configurationName, bool fromCache) { IConfigurationFrame configFrame = null; string configFileName = fromCache ? GetConfigurationCacheFileName(configurationName) : configurationName; if (File.Exists(configFileName)) { configFrame = Common.DeserializeConfigurationFrame(configFileName); } return(configFrame); }
// Attempts to cast given frame into a SEL Fast Message configuration frame - theoretically this will // allow the same configuration frame to be used for any protocol implementation internal static ConfigurationFrame CastToDerivedConfigurationFrame(IConfigurationFrame sourceFrame, MessagePeriod messagePeriod) { // See if frame is already a SEL Fast Message frame (if so, we don't need to do any work) ConfigurationFrame derivedFrame = sourceFrame as ConfigurationFrame; if (derivedFrame == null) { // Create a new SEL Fast Message configuration frame converted from equivalent configuration information; SEL Fast Message only supports one device if (sourceFrame.Cells.Count > 0) { IConfigurationCell sourceCell = sourceFrame.Cells[0]; switch (sourceCell.PhasorDefinitions.Count) { case 8: derivedFrame = new ConfigurationFrame(FrameSize.A, messagePeriod, sourceFrame.IDCode); break; case 4: derivedFrame = new ConfigurationFrame(FrameSize.V, messagePeriod, sourceFrame.IDCode); break; default: derivedFrame = new ConfigurationFrame(FrameSize.V1, messagePeriod, sourceFrame.IDCode); break; } // Create new derived configuration cell ConfigurationCell derivedCell = new ConfigurationCell(derivedFrame); IFrequencyDefinition sourceFrequency; // Create equivalent derived phasor definitions foreach (IPhasorDefinition sourcePhasor in sourceCell.PhasorDefinitions) { derivedCell.PhasorDefinitions.Add(new PhasorDefinition(derivedCell, sourcePhasor.Label, sourcePhasor.PhasorType, null)); } // Create equivalent derived frequency definition sourceFrequency = sourceCell.FrequencyDefinition; if (sourceFrequency != null) { derivedCell.FrequencyDefinition = new FrequencyDefinition(derivedCell, sourceFrequency.Label); } // Add cell to frame derivedFrame.Cells.Add(derivedCell); } } return(derivedFrame); }
public ManualConfigurator(IConfigurationFrame configurationFrame) { Thread.CurrentPrincipal = ((App)Application.Current).Principal; InitializeComponent(); ButtonSave.Content = new BitmapImage(new Uri(@"images/Save.png", UriKind.Relative)); ButtonClear.Content = new BitmapImage(new Uri(@"images/Cancel.png", UriKind.Relative)); ButtonClear.Click += new RoutedEventHandler(ButtonClear_Click); ButtonSave.Click += new RoutedEventHandler(ButtonSave_Click); if (configurationFrame != null) UserControlConfiguratorCreator.ConfigurationFrame = configurationFrame; }
/// <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 frame when it's received base.OnReceivedConfigurationFrame(frame); // Cache new configuration frame for parsing subsequent data frames... ConfigurationFrame configurationFrame = frame as ConfigurationFrame; if ((object)configurationFrame != null) { m_configurationFrame = configurationFrame; } }
// Static Methods // Attempts to cast given frame into a BPA PDCstream configuration frame - theoretically this will // allow the same configuration frame to be used for any protocol implementation internal static ConfigurationFrame CastToDerivedConfigurationFrame(IConfigurationFrame sourceFrame, string configurationFileName) { // See if frame is already a BPA PDCstream configuration frame (if so, we don't need to do any work) ConfigurationFrame derivedFrame = sourceFrame as ConfigurationFrame; if (derivedFrame == null) { // Create a new BPA PDCstream configuration frame converted from equivalent configuration information ConfigurationCell derivedCell; IFrequencyDefinition sourceFrequency; derivedFrame = new ConfigurationFrame(sourceFrame.Timestamp, configurationFileName, 1, RevisionNumber.Revision2, StreamType.Compact); foreach (IConfigurationCell sourceCell in sourceFrame.Cells) { // Create new derived configuration cell derivedCell = new ConfigurationCell(derivedFrame, sourceCell.IDCode, sourceCell.NominalFrequency); // 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)); } // Add cell to frame derivedFrame.Cells.Add(derivedCell); } } return(derivedFrame); }
// Attempts to cast given frame into an IEEE 1344 configuration frame - theoretically this will // allow the same configuration frame to be used for any protocol implementation internal static ConfigurationFrame CastToDerivedConfigurationFrame(IConfigurationFrame sourceFrame) { // See if frame is already an IEEE 1344 configuration frame (if so, we don't need to do any work) ConfigurationFrame derivedFrame = sourceFrame as ConfigurationFrame; if (derivedFrame == null) { // Create a new IEEE 1344 configuration frame converted from equivalent configuration information ConfigurationCell derivedCell; IFrequencyDefinition sourceFrequency; derivedFrame = new ConfigurationFrame(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); // 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); } // IEEE 1344 does not define analog values... // Create equivalent derived digital definitions foreach (IDigitalDefinition sourceDigital in sourceCell.DigitalDefinitions) { derivedCell.DigitalDefinitions.Add(new DigitalDefinition(derivedCell, sourceDigital.Label)); } // Add cell to frame derivedFrame.Cells.Add(derivedCell); // IEEE-1344 only supports one cell break; } } return(derivedFrame); }
/// <summary> /// Casts the parsed <see cref="IChannelFrame"/> to its specific implementation (i.e., <see cref="IDataFrame"/>, <see cref="IConfigurationFrame"/>, <see cref="ICommandFrame"/> or <see cref="IHeaderFrame"/>). /// </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 virtual void OnReceivedChannelFrame(IChannelFrame frame) { // Process frame types in order or likely occurrence if ((object)frame != null) { IDataFrame dataFrame = frame as IDataFrame; if ((object)dataFrame != null) { // Frame was a data frame OnReceivedDataFrame(dataFrame); } else { IConfigurationFrame configFrame = frame as IConfigurationFrame; if ((object)configFrame != null) { // Frame was a configuration frame OnReceivedConfigurationFrame(configFrame); } else { IHeaderFrame headerFrame = frame as IHeaderFrame; if ((object)headerFrame != null) { // Frame was a header frame OnReceivedHeaderFrame(headerFrame); } else { ICommandFrame commandFrame = frame as ICommandFrame; if ((object)commandFrame != null) { // Frame was a command frame OnReceivedCommandFrame(commandFrame); } else { // Frame type was undetermined OnReceivedUndeterminedFrame(frame); } } } } } }
public ManualConfigurator(IConfigurationFrame configurationFrame) { Thread.CurrentPrincipal = ((App)Application.Current).Principal; InitializeComponent(); ButtonSave.Content = new BitmapImage(new Uri(@"images/Save.png", UriKind.Relative)); ButtonClear.Content = new BitmapImage(new Uri(@"images/Cancel.png", UriKind.Relative)); ButtonClear.Click += new RoutedEventHandler(ButtonClear_Click); ButtonSave.Click += new RoutedEventHandler(ButtonSave_Click); if (configurationFrame != null) { UserControlConfiguratorCreator.ConfigurationFrame = configurationFrame; } }
/// <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 }
public IEnumerable <AdaptDevice> GetDevices() { if (!m_ConfigFrameSource.Task.IsCompleted && m_ConfigFrameSource.Task.Status != TaskStatus.WaitingForActivation) { return(new List <AdaptDevice>()); } if (m_ConfigFrameSource.Task.Result == null) { return(new List <AdaptDevice>()); } IConfigurationFrame configuration = m_ConfigFrameSource.Task.Result; return(configuration.Cells.Select(cell => new AdaptDevice(cell.IDCode.ToString(), cell.StationName)).ToList()); }
protected override void ClientHelper_ReceivedServiceResponse(object sender, EventArgs <ServiceResponse> e) { List <object> attachments = e.Argument.Attachments; // Handle any special attachments coming in from service if (attachments != null) { foreach (object attachment in attachments) { if (attachment is ConfigurationErrorFrame) { Console.WriteLine("Received configuration error frame, invocation request for device configuration has failed. See common phasor services response for reason.\r\n"); } else if (attachment is IConfigurationFrame) { // Attachment is a configuration frame, serialize it to XML and open it in a browser IConfigurationFrame configurationFrame = attachment as IConfigurationFrame; string fileName = string.Format("{0}\\DownloadedConfiguration-ID[{1}].xml", FilePath.GetAbsolutePath(""), configurationFrame.IDCode); FileStream configFile = File.Create(fileName); SoapFormatter xmlSerializer = new SoapFormatter(); xmlSerializer.AssemblyFormat = FormatterAssemblyStyle.Simple; xmlSerializer.TypeFormat = FormatterTypeStyle.TypesWhenNeeded; try { // Attempt to serialize configuration frame as XML xmlSerializer.Serialize(configFile, configurationFrame); } catch (Exception ex) { byte[] errorMessage = Encoding.UTF8.GetBytes(ex.Message); configFile.Write(errorMessage, 0, errorMessage.Length); Console.Write("Failed to serialize configuration frame: {0}", ex.Message); } configFile.Close(); // Open captured XML sample file in explorer... Process.Start("explorer.exe", fileName); } } } // Allow base class to handle common response base.ClientHelper_ReceivedServiceResponse(sender, e); }
/// <summary> /// Deserializes a configuration frame from an XML stream. /// </summary> /// <param name="configStream"><see cref="Stream"/> that contains an XML serialized configuration frame.</param> /// <returns>Deserialized <see cref="IConfigurationFrame"/>.</returns> public static IConfigurationFrame DeserializeConfigurationFrame(Stream configStream) { IConfigurationFrame configFrame = null; throw new Exception("Needs to be implemented because .NET Core does not support SoapFormatter"); //SoapFormatter xmlSerializer = new SoapFormatter(); //xmlSerializer.AssemblyFormat = FormatterAssemblyStyle.Simple; //xmlSerializer.TypeFormat = FormatterTypeStyle.TypesWhenNeeded; //xmlSerializer.Binder = Serialization.LegacyBinder; //configFrame = xmlSerializer.Deserialize(new MemoryStream(Encoding.Default.GetBytes(xmlFile))) as IConfigurationFrame; //configFrame = xmlSerializer.Deserialize(configStream) as IConfigurationFrame; return(configFrame); }
/// <summary> /// Parses the binary image. /// </summary> /// <param name="buffer">Binary image to parse.</param> /// <param name="startIndex">Start index into <paramref name="buffer"/> to begin parsing.</param> /// <param name="length">Length of valid data within <paramref name="buffer"/>.</param> /// <returns>The length of the data that was parsed.</returns> /// <remarks> /// This method is overridden to ensure assignment of configuration frame. /// </remarks> public override int ParseBinaryImage(byte[] buffer, int startIndex, int length) { // Make sure configuration frame gets assigned before parsing begins... IDataFrameParsingState state = State; IConfigurationFrame configurationFrame = state.ConfigurationFrame; if (configurationFrame != null) { ConfigurationFrame = configurationFrame; // Handle normal parsing return(base.ParseBinaryImage(buffer, startIndex, length)); } // Otherwise we just skip parsing this frame... return(state.ParsedBinaryLength); }
// Attempts to cast given frame into a F-NET configuration frame - theoretically this will // allow the same configuration frame to be used for any protocol implementation internal static ConfigurationFrame CastToDerivedConfigurationFrame(IConfigurationFrame sourceFrame) { // See if frame is already a F-NET frame (if so, we don't need to do any work) ConfigurationFrame derivedFrame = sourceFrame as ConfigurationFrame; if (derivedFrame == null) { // Create a new F-NET configuration frame converted from equivalent configuration information; F-NET only supports one device if (sourceFrame.Cells.Count > 0) { derivedFrame = new ConfigurationFrame(sourceFrame.IDCode, sourceFrame.Timestamp, sourceFrame.FrameRate, sourceFrame.Cells[0].NominalFrequency, Common.DefaultTimeOffset, Common.DefaultStationName); } else { derivedFrame = new ConfigurationFrame(sourceFrame.IDCode, sourceFrame.Timestamp, sourceFrame.FrameRate, LineFrequency.Hz60, Common.DefaultTimeOffset, Common.DefaultStationName); } } return(derivedFrame); }
/// <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) { // IEEE 1344 configuration frames can span multiple frame images, so we don't allow base class to raise this event until all frames have been assembled... ISupportFrameImage <FrameType> frameImage = frame as ISupportFrameImage <FrameType>; if (frameImage != null) { CommonFrameHeader commonHeader = frameImage.CommonHeader as CommonFrameHeader; if (commonHeader != null && commonHeader.IsLastFrame) { base.OnReceivedConfigurationFrame(frame); // Cache new configuration frame for parsing subsequent data frames... ConfigurationFrame configurationFrame = frame as ConfigurationFrame; if (configurationFrame != null) { m_configurationFrame = configurationFrame; } } } }
private void m_frameParser_ReceivedConfigurationFrame(object sender, EventArgs<IConfigurationFrame> e) { // Cache received configuration frame m_configurationFrame = e.Argument; OnStatusMessage("Successfully received configuration frame!"); // Clear wait handle m_configurationWaitHandle.Set(); }
public IConfigurationFrame RequestDeviceConfiguration(string connectionString) { m_cancelConfigurationFrameRequest = false; if (string.IsNullOrEmpty(connectionString)) { OnStatusMessage("ERROR: No connection string was specified, request for configuration canceled."); return new ConfigurationErrorFrame(); } // Define a line of asterisks for emphasis string stars = new string('*', 79); // Only allow configuration request if another request is not already pending... if (Monitor.TryEnter(m_frameParser)) { try { Dictionary<string, string> settings = connectionString.ParseKeyValuePairs(); string setting; ushort accessID; // Get accessID from connection string if (settings.TryGetValue("accessID", out setting)) accessID = ushort.Parse(setting); else accessID = 1; // Most of the parameters in the connection string will be for the data source in the frame parser // so we provide all of them, other parameters will simply be ignored m_frameParser.ConnectionString = connectionString; // Provide access ID to frame parser as this may be necessary to make a phasor connection m_frameParser.DeviceID = accessID; // Clear any existing configuration frame m_configurationFrame = null; // Inform user of temporary loss of command access OnStatusMessage("\r\n{0}\r\n\r\nAttempting to request remote device configuration.\r\n\r\nThis request could take up to sixty seconds to complete.\r\n\r\nOther CPS config requests will not be accepted until request succeeds or fails.\r\n\r\n{0}", stars); // Make sure the wait handle is not set m_configurationWaitHandle.Reset(); // Start the frame parser - this will attempt connection m_frameParser.Start(); // We wait a maximum of 60 seconds to receive the configuration frame - this delay should be the maximum time ever needed // to receive a configuration frame. If the device connection is Active or Hybrid then the configuration frame should be // returned immediately - for purely Passive connections the configuration frame is delivered once per minute. if (!m_configurationWaitHandle.WaitOne(60000)) OnStatusMessage("WARNING: Timed-out waiting to retrieve remote device configuration."); // Terminate connection to device m_frameParser.Stop(); if (m_configurationFrame == null) { m_configurationFrame = new ConfigurationErrorFrame(); if (m_cancelConfigurationFrameRequest) OnStatusMessage("Configuration frame request canceled by user."); else OnStatusMessage("Failed to retrieve remote device configuration."); } return m_configurationFrame; } catch (Exception ex) { OnStatusMessage("ERROR: Failed to request configuration due to exception: {0}", ex.Message); } finally { m_cancelConfigurationFrameRequest = false; // Release the lock Monitor.Exit(m_frameParser); // Inform user of restoration of command access OnStatusMessage("\r\n{0}\r\n\r\nRemote device configuration request completed.\r\n\r\nCPS config requests have been restored.\r\n\r\n{0}", stars); } } else { OnStatusMessage("ERROR: Cannot process simultaneous requests for device configurations, please try again in a few seconds.."); } return new ConfigurationErrorFrame(); }
/// <summary> /// Releases the unmanaged resources used by the <see cref="CommonPhasorServices"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { // Detach from frame parser events and dispose if ((object)m_frameParser != null) { m_frameParser.ConnectionAttempt -= m_frameParser_ConnectionAttempt; m_frameParser.ConnectionEstablished -= m_frameParser_ConnectionEstablished; m_frameParser.ConnectionException -= m_frameParser_ConnectionException; m_frameParser.ConnectionTerminated -= m_frameParser_ConnectionTerminated; m_frameParser.ExceededParsingExceptionThreshold -= m_frameParser_ExceededParsingExceptionThreshold; m_frameParser.ParsingException -= m_frameParser_ParsingException; m_frameParser.ReceivedConfigurationFrame -= m_frameParser_ReceivedConfigurationFrame; m_frameParser.Dispose(); } m_frameParser = null; // Dispose configuration of wait handle if (m_configurationWaitHandle != null) m_configurationWaitHandle.Close(); m_configurationWaitHandle = null; m_configurationFrame = null; } } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); // Call base class Dispose(). } } }
private static void Helper_ReceivedServiceResponse(object sender, EventArgs<ServiceResponse> e) { List<object> attachments = e.Argument.Attachments; // Handle any special attachments coming in from service if (attachments != null) { foreach (object attachment in attachments) { if (attachment is ConfigurationErrorFrame) { Thread.Sleep(1000); s_responseAttachment = attachment as ConfigurationErrorFrame; s_responseWaitHandle.Set(); //Console.WriteLine("Received configuration error frame, invocation request for device configuration has failed. See common phasor services response for reason.\r\n"); } else if (attachment is IConfigurationFrame) // If user requested a configuration frame, send it to parsing function to retrieve devices list. { s_responseAttachment = attachment as IConfigurationFrame; s_responseWaitHandle.Set(); } } } }
/// <summary> /// Stops the <see cref="MultiProtocolFrameParser"/>. /// </summary> public void Stop() { WaitHandle commandWaitHandle; m_enabled = false; m_rateCalcTimer.Enabled = false; m_configurationFrame = null; // Make sure data stream is disabled if (!m_skipDisableRealTimeData) { commandWaitHandle = SendDeviceCommand(DeviceCommand.DisableRealTimeData); if ((object)commandWaitHandle != null) commandWaitHandle.WaitOne(1000); } if ((object)m_dataChannel != null) { try { m_dataChannel.Disconnect(); } catch (Exception ex) { OnParsingException(ex, "Failed to properly disconnect data channel: {0}", ex.Message); } finally { m_dataChannel.ConnectionEstablished -= m_dataChannel_ConnectionEstablished; m_dataChannel.ConnectionAttempt -= m_dataChannel_ConnectionAttempt; m_dataChannel.ConnectionException -= m_dataChannel_ConnectionException; m_dataChannel.ConnectionTerminated -= m_dataChannel_ConnectionTerminated; m_dataChannel.ReceiveData -= m_dataChannel_ReceiveData; m_dataChannel.ReceiveDataException -= m_dataChannel_ReceiveDataException; m_dataChannel.SendDataException -= m_dataChannel_SendDataException; m_dataChannel.UnhandledUserException -= m_dataChannel_UnhandledUserException; m_dataChannel.Dispose(); } m_dataChannel = null; } m_readNextBuffer = null; if ((object)m_serverBasedDataChannel != null) { try { m_serverBasedDataChannel.DisconnectAll(); } catch (Exception ex) { OnParsingException(ex, "Failed to properly disconnect server based data channel: {0}", ex.Message); } finally { m_serverBasedDataChannel.ClientConnected -= m_serverBasedDataChannel_ClientConnected; m_serverBasedDataChannel.ClientDisconnected -= m_serverBasedDataChannel_ClientDisconnected; m_serverBasedDataChannel.ClientConnectingException -= m_serverBasedDataChannel_ClientConnectingException; m_serverBasedDataChannel.ServerStarted -= m_serverBasedDataChannel_ServerStarted; m_serverBasedDataChannel.ServerStopped -= m_serverBasedDataChannel_ServerStopped; m_serverBasedDataChannel.ReceiveClientData -= m_serverBasedDataChannel_ReceiveClientData; m_serverBasedDataChannel.ReceiveClientDataException -= m_serverBasedDataChannel_ReceiveClientDataException; m_serverBasedDataChannel.SendClientDataException -= m_serverBasedDataChannel_SendClientDataException; m_serverBasedDataChannel.UnhandledUserException -= m_serverBasedDataChannel_UnhandledUserException; m_serverBasedDataChannel.Dispose(); } m_serverBasedDataChannel = null; } if ((object)m_commandChannel != null) { try { m_commandChannel.Disconnect(); } catch (Exception ex) { OnParsingException(ex, "Failed to properly disconnect command channel: {0}", ex.Message); } finally { m_commandChannel.ConnectionEstablished -= m_commandChannel_ConnectionEstablished; m_commandChannel.ConnectionAttempt -= m_commandChannel_ConnectionAttempt; m_commandChannel.ConnectionException -= m_commandChannel_ConnectionException; m_commandChannel.ConnectionTerminated -= m_commandChannel_ConnectionTerminated; m_commandChannel.ReceiveData -= m_commandChannel_ReceiveData; m_commandChannel.ReceiveDataException -= m_commandChannel_ReceiveDataException; m_commandChannel.SendDataException -= m_commandChannel_SendDataException; m_commandChannel.UnhandledUserException -= m_commandChannel_UnhandledUserException; m_commandChannel.Dispose(); } m_commandChannel = null; } if ((object)m_frameParser != null) { try { m_frameParser.Stop(); } catch (Exception ex) { OnParsingException(ex, "Failed to properly stop frame parser: {0}", ex.Message); } finally { m_frameParser.ReceivedCommandFrame -= m_frameParser_ReceivedCommandFrame; m_frameParser.ReceivedConfigurationFrame -= m_frameParser_ReceivedConfigurationFrame; m_frameParser.ReceivedDataFrame -= m_frameParser_ReceivedDataFrame; m_frameParser.ReceivedHeaderFrame -= m_frameParser_ReceivedHeaderFrame; m_frameParser.ReceivedUndeterminedFrame -= m_frameParser_ReceivedUndeterminedFrame; m_frameParser.ReceivedFrameImage -= m_frameParser_ReceivedFrameImage; m_frameParser.ConfigurationChanged -= m_frameParser_ConfigurationChanged; m_frameParser.ParsingException -= m_frameParser_ParsingException; m_frameParser.BufferParsed -= m_frameParser_BufferParsed; if ((object)ReceivedFrameBufferImage != null) m_frameParser.ReceivedFrameBufferImage -= m_frameParser_ReceivedFrameBufferImage; m_frameParser.Dispose(); } m_frameParser = null; } }
/// <summary> /// Stops the <see cref="MultiProtocolFrameParser"/>. /// </summary> public virtual void Stop() { m_enabled = false; m_rateCalcTimer.Enabled = false; m_lastFrameReceivedTime = 0; m_configurationFrame = null; // Make sure data stream is disabled SendDeviceCommand(DeviceCommand.DisableRealTimeData); if (m_dataChannel != null) { m_dataChannel.Disconnect(); m_dataChannel.ReceiveDataHandler = null; m_dataChannel.ConnectionEstablished -= m_dataChannel_ConnectionEstablished; m_dataChannel.ConnectionAttempt -= m_dataChannel_ConnectionAttempt; m_dataChannel.ConnectionException -= m_dataChannel_ConnectionException; m_dataChannel.ConnectionTerminated -= m_dataChannel_ConnectionTerminated; m_dataChannel.Dispose(); } m_dataChannel = null; if (m_serverBasedDataChannel != null) { m_serverBasedDataChannel.DisconnectAll(); m_serverBasedDataChannel.ReceiveClientDataHandler = null; m_serverBasedDataChannel.ClientConnected -= m_serverBasedDataChannel_ClientConnected; m_serverBasedDataChannel.ClientDisconnected -= m_serverBasedDataChannel_ClientDisconnected; m_serverBasedDataChannel.ServerStarted -= m_serverBasedDataChannel_ServerStarted; m_serverBasedDataChannel.ServerStopped -= m_serverBasedDataChannel_ServerStopped; m_serverBasedDataChannel.Dispose(); } m_serverBasedDataChannel = null; if (m_commandChannel != null) { m_commandChannel.Disconnect(); m_commandChannel.ReceiveDataHandler = null; m_commandChannel.ConnectionEstablished -= m_commandChannel_ConnectionEstablished; m_commandChannel.ConnectionAttempt -= m_commandChannel_ConnectionAttempt; m_commandChannel.ConnectionException -= m_commandChannel_ConnectionException; m_commandChannel.ConnectionTerminated -= m_commandChannel_ConnectionTerminated; m_commandChannel.Dispose(); } m_commandChannel = null; if (m_frameParser != null) { m_frameParser.Stop(); m_frameParser.ReceivedCommandFrame -= m_frameParser_ReceivedCommandFrame; m_frameParser.ReceivedConfigurationFrame -= m_frameParser_ReceivedConfigurationFrame; m_frameParser.ReceivedDataFrame -= m_frameParser_ReceivedDataFrame; m_frameParser.ReceivedHeaderFrame -= m_frameParser_ReceivedHeaderFrame; m_frameParser.ReceivedUndeterminedFrame -= m_frameParser_ReceivedUndeterminedFrame; m_frameParser.ReceivedFrameBufferImage -= m_frameParser_ReceivedFrameBufferImage; m_frameParser.ConfigurationChanged -= m_frameParser_ConfigurationChanged; m_frameParser.ParsingException -= m_frameParser_ParsingException; m_frameParser.Dispose(); } m_frameParser = null; #if RawDataCapture if (m_rawDataCapture != null) m_rawDataCapture.Close(); m_rawDataCapture = null; #endif }
public ConfigurationFrame LoadConfigurationFrame(string sourceData) { string connectionString = ""; IConfigurationFrame GetConfigurationFrame() { try { ConnectionSettings connectionSettings; SoapFormatter formatter = new SoapFormatter { AssemblyFormat = FormatterAssemblyStyle.Simple, TypeFormat = FormatterTypeStyle.TypesWhenNeeded, Binder = Serialization.LegacyBinder }; using (MemoryStream source = new MemoryStream(Encoding.UTF8.GetBytes(sourceData))) connectionSettings = formatter.Deserialize(source) as ConnectionSettings; if ((object)connectionSettings != null) { connectionString = connectionSettings.ConnectionString; Dictionary <string, string> connectionStringKeyValues = connectionString.ParseKeyValuePairs(); connectionString = "transportProtocol=" + connectionSettings.TransportProtocol + ";" + connectionStringKeyValues.JoinKeyValuePairs(); if ((object)connectionSettings.ConnectionParameters != null) { switch (connectionSettings.PhasorProtocol) { case PhasorProtocol.BPAPDCstream: GSF.PhasorProtocols.BPAPDCstream.ConnectionParameters bpaParameters = connectionSettings.ConnectionParameters as GSF.PhasorProtocols.BPAPDCstream.ConnectionParameters; if ((object)bpaParameters != null) { connectionString += "; iniFileName=" + bpaParameters.ConfigurationFileName + "; refreshConfigFileOnChange=" + bpaParameters.RefreshConfigurationFileOnChange + "; parseWordCountFromByte=" + bpaParameters.ParseWordCountFromByte; } break; case PhasorProtocol.FNET: GSF.PhasorProtocols.FNET.ConnectionParameters fnetParameters = connectionSettings.ConnectionParameters as GSF.PhasorProtocols.FNET.ConnectionParameters; if ((object)fnetParameters != null) { connectionString += "; timeOffset=" + fnetParameters.TimeOffset + "; stationName=" + fnetParameters.StationName + "; frameRate=" + fnetParameters.FrameRate + "; nominalFrequency=" + (int)fnetParameters.NominalFrequency; } break; case PhasorProtocol.SelFastMessage: GSF.PhasorProtocols.SelFastMessage.ConnectionParameters selParameters = connectionSettings.ConnectionParameters as GSF.PhasorProtocols.SelFastMessage.ConnectionParameters; if ((object)selParameters != null) { connectionString += "; messagePeriod=" + selParameters.MessagePeriod; } break; case PhasorProtocol.IEC61850_90_5: GSF.PhasorProtocols.IEC61850_90_5.ConnectionParameters iecParameters = connectionSettings.ConnectionParameters as GSF.PhasorProtocols.IEC61850_90_5.ConnectionParameters; if ((object)iecParameters != null) { connectionString += "; useETRConfiguration=" + iecParameters.UseETRConfiguration + "; guessConfiguration=" + iecParameters.GuessConfiguration + "; parseRedundantASDUs=" + iecParameters.ParseRedundantASDUs + "; ignoreSignatureValidationFailures=" + iecParameters.IgnoreSignatureValidationFailures + "; ignoreSampleSizeValidationFailures=" + iecParameters.IgnoreSampleSizeValidationFailures; } break; case PhasorProtocol.Macrodyne: GSF.PhasorProtocols.Macrodyne.ConnectionParameters macrodyneParameters = connectionSettings.ConnectionParameters as GSF.PhasorProtocols.Macrodyne.ConnectionParameters; if ((object)macrodyneParameters != null) { connectionString += "; protocolVersion=" + macrodyneParameters.ProtocolVersion + "; iniFileName=" + macrodyneParameters.ConfigurationFileName + "; refreshConfigFileOnChange=" + macrodyneParameters.RefreshConfigurationFileOnChange + "; deviceLabel=" + macrodyneParameters.DeviceLabel; } break; } } connectionString += "; accessID=" + connectionSettings.PmuID; connectionString += "; phasorProtocol=" + connectionSettings.PhasorProtocol; using (CommonPhasorServices phasorServices = new CommonPhasorServices()) { phasorServices.StatusMessage += (sender, e) => LogStatusMessage(e.Argument.Replace("**", "")); phasorServices.ProcessException += (sender, e) => LogException(e.Argument); return(phasorServices.RequestDeviceConfiguration(connectionString)); } } using (MemoryStream source = new MemoryStream(Encoding.UTF8.GetBytes(sourceData))) return(formatter.Deserialize(source) as IConfigurationFrame); } catch { return(new ConfigurationErrorFrame()); } } IConfigurationFrame sourceFrame = GetConfigurationFrame(); if (sourceFrame is ConfigurationErrorFrame) { return(new ConfigurationFrame()); } ConfigurationFrame derivedFrame; // Create a new simple concrete configuration frame for JSON serialization converted from equivalent configuration information int protocolID = 0, deviceID = 0, phasorID = -1; // Start phasor ID's at less than -1 since associated voltage == -1 is reserved as unselected if (!string.IsNullOrWhiteSpace(connectionString)) { Dictionary <string, string> settings = connectionString.ParseKeyValuePairs(); protocolID = GetProtocolID(settings["phasorProtocol"]); } derivedFrame = new ConfigurationFrame { IDCode = sourceFrame.IDCode, FrameRate = sourceFrame.FrameRate, ConnectionString = connectionString, ProtocolID = protocolID }; foreach (IConfigurationCell sourceCell in sourceFrame.Cells) { // Create new derived configuration cell ConfigurationCell derivedCell = new ConfigurationCell { ID = --deviceID, // Provide a negative index so any database lookup will return null ParentID = null, IDCode = sourceCell.IDCode, StationName = sourceCell.StationName, IDLabel = sourceCell.IDLabel }; // Create equivalent derived frequency definition IFrequencyDefinition sourceFrequency = sourceCell.FrequencyDefinition; if (sourceFrequency != null) { derivedCell.FrequencyDefinition = new FrequencyDefinition { Label = sourceFrequency.Label } } ; int sourceIndex = 0; // Create equivalent derived phasor definitions foreach (IPhasorDefinition sourcePhasor in sourceCell.PhasorDefinitions) { derivedCell.PhasorDefinitions.Add(new PhasorDefinition { ID = --phasorID, Label = sourcePhasor.Label, PhasorType = sourcePhasor.PhasorType.ToString(), SourceIndex = ++sourceIndex }); } // Create equivalent derived analog definitions (assuming analog type = SinglePointOnWave) foreach (IAnalogDefinition sourceAnalog in sourceCell.AnalogDefinitions) { derivedCell.AnalogDefinitions.Add(new AnalogDefinition { Label = sourceAnalog.Label, AnalogType = sourceAnalog.AnalogType.ToString() }); } // Create equivalent derived digital definitions foreach (IDigitalDefinition sourceDigital in sourceCell.DigitalDefinitions) { derivedCell.DigitalDefinitions.Add(new DigitalDefinition { Label = sourceDigital.Label }); } // Add cell to frame derivedFrame.Cells.Add(derivedCell); } derivedFrame.IsConcentrator = derivedFrame.Cells.Count > 1; return(derivedFrame); }
/// <summary> /// Serialize configuration frame to cache folder for later use (if needed). /// </summary> /// <param name="configurationFrame">New <see cref="IConfigurationFrame"/> to cache.</param> /// <param name="name">Name to use when caching the <paramref name="configurationFrame"/>.</param> /// <remarks> /// Derived concentrators can call this method to manually serialize their protocol specific /// configuration frames. Note that after initial call to <see cref="CreateNewConfigurationFrame"/> /// this method will be call automatically. /// </remarks> protected void CacheConfigurationFrame(IConfigurationFrame configurationFrame, string name) { // Cache configuration frame for reference OnStatusMessage("Caching configuration frame..."); try { // Cache configuration on an independent thread in case this takes some time GSF.PhasorProtocols.Anonymous.ConfigurationFrame.Cache(configurationFrame, OnProcessException, name); } catch (Exception ex) { // Process exception for logging OnProcessException(new InvalidOperationException("Failed to queue caching of config frame due to exception: " + ex.Message, ex)); } }
/// <summary> /// Serialize configuration frame to cache folder for later use (if needed). /// </summary> /// <param name="configurationFrame">New <see cref="IConfigurationFrame"/> to cache.</param> /// <remarks> /// Derived concentrators can call this method to manually serialize their protocol specific /// configuration frames. Note that after initial call to <see cref="CreateNewConfigurationFrame"/> /// this method will be call automatically. /// </remarks> protected void CacheConfigurationFrame(IConfigurationFrame configurationFrame) { // Cache configuration frame for reference OnStatusMessage("Caching configuration frame..."); // Cache configuration on an independent thread in case this takes some time ThreadPool.QueueUserWorkItem(TVA.PhasorProtocols.Anonymous.ConfigurationFrame.Cache, new EventArgs<IConfigurationFrame, Action<Exception>, string>(configurationFrame, OnProcessException, Name)); }
public void UpdateConfiguration() { const int labelLength = 16; Dictionary<string, int> signalCellIndexes = new Dictionary<string, int>(); ConfigurationCell cell; SignalReference signal; SignalReference[] signals; MeasurementKey measurementKey; PhasorType phasorType; AnalogType analogType; char phaseType; string label; int order; uint scale; double offset; // Define a protocol independent configuration frame m_baseConfigurationFrame = new ConfigurationFrame(m_idCode, DateTime.UtcNow.Ticks, (ushort)base.FramesPerSecond); // Define configuration cells (i.e., PMU's that will appear in outgoing data stream) foreach (DataRow deviceRow in DataSource.Tables["OutputStreams"].Select(string.Format("StreamID={0}", ID))) { try { // Create a new configuration cell cell = new ConfigurationCell(m_baseConfigurationFrame, ushort.Parse(deviceRow["ID"].ToString()), deviceRow["IsVirtual"].ToNonNullString("false").ParseBoolean()); // The base class defaults to floating-point, polar values, derived classes can change cell.PhasorDataFormat = DataFormat.FloatingPoint; cell.PhasorCoordinateFormat = CoordinateFormat.Polar; cell.FrequencyDataFormat = DataFormat.FloatingPoint; cell.AnalogDataFormat = DataFormat.FloatingPoint; cell.IDLabel = deviceRow["Acronym"].ToString().Trim(); cell.StationName = deviceRow["Name"].ToString().TruncateRight(cell.MaximumStationNameLength).Trim(); // Define all the phasors configured for this device foreach (DataRow phasorRow in DataSource.Tables["OutputStreamPhasors"].Select(string.Format("DeviceID={0}", cell.IDCode), "Order")) { order = int.Parse(phasorRow["Order"].ToNonNullString("0")); label = phasorRow["Label"].ToNonNullString("Phasor " + order).Trim().RemoveDuplicateWhiteSpace().TruncateRight(labelLength - 4); phasorType = phasorRow["PhasorType"].ToNonNullString("V").Trim().ToUpper().StartsWith("V") ? PhasorType.Voltage : PhasorType.Current; phaseType = phasorRow["PhaseType"].ToNonNullString("+").Trim().ToUpper()[0]; cell.PhasorDefinitions.Add( new PhasorDefinition( cell, GeneratePhasorLabel(label, phaseType, phasorType), phasorType, null)); } // Add frequency definition label = string.Format("{0} Freq", cell.IDLabel.TruncateRight(labelLength - 5)).Trim(); cell.FrequencyDefinition = new FrequencyDefinition(cell, label); // Optionally define all the analogs configured for this device if (DataSource.Tables.Contains("OutputStreamAnalogs")) { foreach (DataRow analogRow in DataSource.Tables["OutputStreamAnalogs"].Select(string.Format("DeviceID={0}", cell.IDCode), "Order")) { order = int.Parse(analogRow["Order"].ToNonNullString("0")); label = analogRow["Label"].ToNonNullString("Analog " + order).Trim().RemoveDuplicateWhiteSpace().TruncateRight(labelLength); scale = uint.Parse(analogRow["Scale"].ToNonNullString("1")); offset = double.Parse(analogRow["Offset"].ToNonNullString("0.0")); analogType = analogRow["AnalogType"].ToNonNullString("SinglePointOnWave").ConvertToType<AnalogType>(); cell.AnalogDefinitions.Add( new AnalogDefinition( cell, label, scale, offset, analogType)); } } // Optionally define all the digitals configured for this device if (DataSource.Tables.Contains("OutputStreamDigitals")) { foreach (DataRow digitalRow in DataSource.Tables["OutputStreamDigitals"].Select(string.Format("DeviceID={0}", cell.IDCode), "Order")) { order = int.Parse(digitalRow["Order"].ToNonNullString("0")); label = digitalRow["Label"].ToNonNullString("Digital " + order).Trim().RemoveDuplicateWhiteSpace().TruncateRight(labelLength); cell.DigitalDefinitions.Add( new DigitalDefinition( cell, label)); } } m_baseConfigurationFrame.Cells.Add(cell); } catch (Exception ex) { OnProcessException(new InvalidOperationException(string.Format("Failed to define output stream device \"{0}\" due to exception: {1}", deviceRow["Acronym"].ToString().Trim(), ex.Message), ex)); } } OnStatusMessage("Defined {0} output stream devices...", m_baseConfigurationFrame.Cells.Count); // Create a new signal reference dictionary indexed on measurement keys m_signalReferences = new Dictionary<MeasurementKey, SignalReference[]>(); // Define measurement to signals cross reference dictionary foreach (DataRow measurementRow in DataSource.Tables["OutputStreamMeasurements"].Select(string.Format("StreamID={0}", ID))) { try { // Create a new signal reference signal = new SignalReference(measurementRow["SignalReference"].ToString()); // Lookup cell index by acronym - doing this work upfront will save a huge amount // of work during primary measurement sorting if (!signalCellIndexes.TryGetValue(signal.Acronym, out signal.CellIndex)) { // We cache these indicies locally to speed up initialization as we'll be // requesting them for the same devices over and over signal.CellIndex = m_configurationFrame.Cells.IndexOfIDLabel(signal.Acronym); signalCellIndexes.Add(signal.Acronym, signal.CellIndex); } // Define measurement key measurementKey = new MeasurementKey(uint.Parse(measurementRow["PointID"].ToString()), measurementRow["Historian"].ToString()); // It is possible, but not as common, that a measurement will have multiple destinations // within an outgoing data stream frame, hence the following if (m_signalReferences.TryGetValue(measurementKey, out signals)) { // Add a new signal to existing collection List<SignalReference> signalList = new List<SignalReference>(signals); signalList.Add(signal); m_signalReferences[measurementKey] = signalList.ToArray(); } else { // Add new signal to new collection signals = new SignalReference[1]; signals[0] = signal; m_signalReferences.Add(measurementKey, signals); } } catch (Exception ex) { OnProcessException(new InvalidOperationException(string.Format("Failed to associate measurement key to signal reference \"{0}\" due to exception: {1}", measurementRow["SignalReference"].ToString().Trim(), ex.Message), ex)); } } // Assign action adapter input measurement keys InputMeasurementKeys = m_signalReferences.Keys.ToArray(); // Create a new protocol specific configuration frame m_configurationFrame = CreateNewConfigurationFrame(m_baseConfigurationFrame); // Cache new protocol specific configuration frame CacheConfigurationFrame(m_configurationFrame); }
/// <summary> /// Creates a new <see cref="DataFrameParsingState"/> from specified parameters. /// </summary> /// <param name="parsedBinaryLength">Binary length of the <see cref="IDataFrame"/> being parsed.</param> /// <param name="configurationFrame">Reference to the <see cref="IConfigurationFrame"/> associated with the <see cref="IDataFrame"/> being parsed.</param> /// <param name="createNewCellFunction">Reference to delegate to create new <see cref="IDataCell"/> instances.</param> public DataFrameParsingState(int parsedBinaryLength, IConfigurationFrame configurationFrame, CreateNewCellFunction<IDataCell> createNewCellFunction) : base(parsedBinaryLength, configurationFrame, createNewCellFunction) { }
// Static Methods /// <summary> /// Serializes configuration frame to cache folder on an independent thread for later use (if needed). /// </summary> /// <param name="configurationFrame">Reference to <see cref="IConfigurationFrame"/>.</param> /// <param name="exceptionHandler"><see cref="Action{T}"/> delegate to handle process exceptions.</param> /// <param name="configurationName"><see cref="string"/> representing the configuration name.</param> public static void Cache(IConfigurationFrame configurationFrame, Action<Exception> exceptionHandler, string configurationName) { Tuple<IConfigurationFrame, Action<Exception>, string> cacheState = new Tuple<IConfigurationFrame, Action<Exception>, string>(configurationFrame, exceptionHandler, configurationName); s_configurationCacheQueue.Add(cacheState); }
private void m_frameParser_ReceivedConfigurationFrame(object sender, EventArgs<IConfigurationFrame> e) { // We automatically request enabling of real-time data upon reception of config frame if requested. Note that SEL Fast Message will // have already been enabled at this point so we don't duplicate request for enabling real-time data stream if ((object)m_configurationFrame == null && m_deviceSupportsCommands && m_autoStartDataParsingSequence && m_phasorProtocol != PhasorProtocol.SelFastMessage && m_phasorProtocol != PhasorProtocol.IEC61850_90_5) SendDeviceCommand(DeviceCommand.EnableRealTimeData); m_configurationFrame = e.Argument; // We don't stop parsing for exceptions thrown in consumer event handlers try { if (m_injectSimulatedTimestamp) e.Argument.Timestamp = DateTime.UtcNow.Ticks; if ((object)ReceivedConfigurationFrame != null) ReceivedConfigurationFrame(this, e); if ((object)m_configurationFrame != null) m_configuredFrameRate = m_configurationFrame.FrameRate; } catch (Exception ex) { OnParsingException(ex, "MultiProtocolFrameParser \"ReceivedConfigurationFrame\" consumer event handler exception: {0}", ex.Message); } // If user has requested to not keep the command channel open, disconnect it once the system has received a configuration frame if (!m_keepCommandChannelOpen && (object)m_commandChannel != null && m_commandChannel.CurrentState == ClientState.Connected) { m_commandChannel.Disconnect(); } }
public static List<WizardDeviceInfo> RetrieveConfigurationFrame(string nodeConnectionString, string deviceConnectionString, int protocolID) { s_responseMessage = string.Empty; s_responseAttachment = null; Dictionary<string, string> settings = nodeConnectionString.ToLower().ParseKeyValuePairs(); WindowsServiceClient windowsServiceClient = new WindowsServiceClient("server=" + settings["server"].Replace("{", "").Replace("}", "")); try { s_responseWaitHandle = new ManualResetEvent(false); windowsServiceClient.Helper.ReceivedServiceResponse += Helper_ReceivedServiceResponse; windowsServiceClient.Helper.ReceivedServiceUpdate += Helper_ReceivedServiceUpdate; windowsServiceClient.Helper.RemotingClient.MaxConnectionAttempts = 10; windowsServiceClient.Helper.Connect(); if (windowsServiceClient.Helper.RemotingClient.Enabled) { if (deviceConnectionString.ToLower().Contains("phasorprotocol")) windowsServiceClient.Helper.SendRequest(string.Format("invoke 0 requestdeviceconfiguration \"{0}\"", deviceConnectionString)); else windowsServiceClient.Helper.SendRequest(string.Format("invoke 0 requestdeviceconfiguration \"{0}\"", deviceConnectionString + "; phasorProtocol=" + GetProtocolAcronymByID(null, protocolID))); if (s_responseWaitHandle.WaitOne(65000)) { if (s_responseAttachment is ConfigurationErrorFrame) throw new ApplicationException("Received configuration error frame, invocation request for device configuration has failed.\r\n"); else if (s_responseAttachment is IConfigurationFrame) return ParseConfigurationFrame(s_responseAttachment as IConfigurationFrame); else throw new ApplicationException("Invalid frame received, invocation for device configuration has failed."); } else throw new ApplicationException("Response timeout occured. Waited 60 seconds for Configuration Frame to arrive."); } else { throw new ApplicationException("Connection timeout occured. Tried 10 times to connect to openPDC windows service."); } } finally { windowsServiceClient.Helper.Disconnect(); //windowsServiceClient.Dispose(); } }
public static List<WizardDeviceInfo> ParseConfigurationFrame(IConfigurationFrame configurationFrame) { //try //{ s_configurationFrame = configurationFrame; List<WizardDeviceInfo> wizardDeviceInfoList = new List<WizardDeviceInfo>(); if (configurationFrame != null) { int parentAccessID = configurationFrame.IDCode; foreach (IConfigurationCell cell in configurationFrame.Cells) { Device tempDevice = GetDeviceByAcronym(null, cell.StationName.Replace(" ", "").ToUpper()); wizardDeviceInfoList.Add(new WizardDeviceInfo() { Acronym = cell.StationName.Replace(" ", "").ToUpper(), Name = CultureInfo.CurrentUICulture.TextInfo.ToTitleCase(cell.StationName.ToLower()), Longitude = tempDevice == null ? -98.6m : tempDevice.Longitude == null ? -98.6m : (decimal)tempDevice.Longitude, Latitude = tempDevice == null ? 37.5m : tempDevice.Latitude == null ? 37.5m : (decimal)tempDevice.Latitude, VendorDeviceID = tempDevice == null ? (int?)null : tempDevice.VendorDeviceID, AccessID = cell.IDCode, ParentAccessID = parentAccessID, Include = true, DigitalCount = cell.DigitalDefinitions.Count(), AnalogCount = cell.AnalogDefinitions.Count(), AddDigitals = false, AddAnalogs = false, IsNew = tempDevice == null ? true : false, PhasorList = new ObservableCollection<PhasorInfo>((from phasor in cell.PhasorDefinitions select new PhasorInfo() { Label = phasor.Label, //CultureInfo.CurrentUICulture.TextInfo.ToTitleCase(phasor.Label.Replace("?", " ").Trim().ToLower()), Type = phasor.PhasorType == PhasorType.Current ? "I" : "V", Phase = "+", DestinationLabel = "", Include = true }).ToList()) }); } } List<string> nondistinctAcronymList = new List<string>(); nondistinctAcronymList = (from item in wizardDeviceInfoList group item by item.Acronym into grouped where grouped.Count() > 1 select grouped.Key).ToList(); if (nondistinctAcronymList.Count > 0) { int i = 0; foreach (WizardDeviceInfo deviceInfo in wizardDeviceInfoList) { if (deviceInfo.IsNew && nondistinctAcronymList.Contains(deviceInfo.Acronym)) { deviceInfo.Acronym = deviceInfo.Acronym.Substring(0, deviceInfo.Acronym.Length - i.ToString().Length) + i.ToString(); i++; } } } return wizardDeviceInfoList; }
public void UpdateConfiguration() { const int LabelLength = 16; PhasorType type; AnalogType analogType; char phase; string label, scale; uint scalingValue; int order; // Define a protocol independent configuration frame m_baseConfigurationFrame = new ConfigurationFrame(m_idCode, DateTime.UtcNow.Ticks, (ushort)base.FramesPerSecond); // Define configuration cells (i.e., PMU's that will appear in outgoing data stream) foreach (DataRow deviceRow in DataSource.Tables["OutputStreamDevices"].Select(string.Format("ParentID={0}", ID), "LoadOrder")) { try { // Get device ID and ID code int deviceID = int.Parse(deviceRow["ID"].ToString()); ushort idCode = ushort.Parse(deviceRow["IDCode"].ToString()); // If number was never assigned or is invalid, we fall back on unique database record ID if (idCode == 0) idCode = unchecked((ushort)deviceID); // Create a new configuration cell ConfigurationCell cell = new ConfigurationCell(m_baseConfigurationFrame, idCode); // Assign user selected data and coordinate formats, derived classes can change string formatString; formatString = deviceRow["PhasorDataFormat"].ToNonNullString(m_dataFormat.ToString()); cell.PhasorDataFormat = (DataFormat)Enum.Parse(typeof(DataFormat), string.IsNullOrEmpty(formatString) ? m_dataFormat.ToString() : formatString, true); formatString = deviceRow["FrequencyDataFormat"].ToNonNullString(m_dataFormat.ToString()); cell.FrequencyDataFormat = (DataFormat)Enum.Parse(typeof(DataFormat), string.IsNullOrEmpty(formatString) ? m_dataFormat.ToString() : formatString, true); formatString = deviceRow["AnalogDataFormat"].ToNonNullString(m_dataFormat.ToString()); cell.AnalogDataFormat = (DataFormat)Enum.Parse(typeof(DataFormat), string.IsNullOrEmpty(formatString) ? m_dataFormat.ToString() : formatString, true); formatString = deviceRow["CoordinateFormat"].ToNonNullString(m_coordinateFormat.ToString()); cell.PhasorCoordinateFormat = (CoordinateFormat)Enum.Parse(typeof(CoordinateFormat), string.IsNullOrEmpty(formatString) ? m_coordinateFormat.ToString() : formatString, true); // Assign device identification labels cell.IDLabel = deviceRow["Name"].ToString().TruncateRight(cell.IDLabelLength).Trim(); label = deviceRow["Acronym"].ToString().TruncateRight(cell.MaximumStationNameLength).Trim(); // Station name is serialized to configuration frame cell.StationName = label; // Define all the phasors configured for this device foreach (DataRow phasorRow in DataSource.Tables["OutputStreamDevicePhasors"].Select(string.Format("OutputStreamDeviceID={0}", deviceID), "LoadOrder")) { order = int.Parse(phasorRow["LoadOrder"].ToNonNullString("0")); label = phasorRow["Label"].ToNonNullString("Phasor " + order).Trim().TruncateRight(LabelLength); type = phasorRow["Type"].ToNonNullString("V").Trim().ToUpper().StartsWith("V") ? PhasorType.Voltage : PhasorType.Current; phase = phasorRow["Phase"].ToNonNullString("+").Trim().ToUpper()[0]; scale = phasorRow["ScalingValue"].ToNonNullString("0"); if (m_replaceWithSpaceChar != Char.MinValue) label = label.Replace(m_replaceWithSpaceChar, ' '); // Scale can be defined as a negative value in database, so check both formatting styles if (!uint.TryParse(scale, out scalingValue)) scalingValue = unchecked((uint)int.Parse(scale)); // Choose stream defined default value if no scaling value was defined if (scalingValue == 0) scalingValue = (type == PhasorType.Voltage ? m_voltageScalingValue : m_currentScalingValue); cell.PhasorDefinitions.Add(new PhasorDefinition( cell, GeneratePhasorLabel(label, phase, type), scalingValue, type, null)); } // Add frequency definition label = string.Format("{0} Freq", cell.IDLabel.TruncateRight(LabelLength - 5)).Trim(); cell.FrequencyDefinition = new FrequencyDefinition(cell, label); // Optionally define all the analogs configured for this device if (DataSource.Tables.Contains("OutputStreamDeviceAnalogs")) { foreach (DataRow analogRow in DataSource.Tables["OutputStreamDeviceAnalogs"].Select(string.Format("OutputStreamDeviceID={0}", deviceID), "LoadOrder")) { order = int.Parse(analogRow["LoadOrder"].ToNonNullString("0")); label = analogRow["Label"].ToNonNullString("Analog " + order).Trim().TruncateRight(LabelLength); analogType = (AnalogType)int.Parse(analogRow["Type"].ToNonNullString("0")); scale = analogRow["ScalingValue"].ToNonNullString("0"); if (m_replaceWithSpaceChar != Char.MinValue) label = label.Replace(m_replaceWithSpaceChar, ' '); // Scale can be defined as a negative value in database, so check both formatting styles if (!uint.TryParse(scale, out scalingValue)) scalingValue = unchecked((uint)int.Parse(scale)); cell.AnalogDefinitions.Add(new AnalogDefinition( cell, label, scalingValue == 0 ? m_analogScalingValue : scalingValue, analogType)); } } // Optionally define all the digitals configured for this device if (DataSource.Tables.Contains("OutputStreamDeviceDigitals")) { foreach (DataRow digitalRow in DataSource.Tables["OutputStreamDeviceDigitals"].Select(string.Format("OutputStreamDeviceID={0}", deviceID), "LoadOrder")) { order = int.Parse(digitalRow["LoadOrder"].ToNonNullString("0")); scale = digitalRow["MaskValue"].ToNonNullString("0"); // IEEE C37.118 digital labels are defined with all 16-labels (one for each bit) in one large formatted string label = digitalRow["Label"].ToNonNullString("Digital " + order).Trim().TruncateRight(LabelLength * 16); if (m_replaceWithSpaceChar != Char.MinValue) label = label.Replace(m_replaceWithSpaceChar, ' '); // Mask can be defined as a negative value in database, so check both formatting styles if (!uint.TryParse(scale, out scalingValue)) scalingValue = unchecked((uint)int.Parse(scale)); cell.DigitalDefinitions.Add(new DigitalDefinition( cell, label, scalingValue == 0 ? m_digitalMaskValue : scalingValue)); } } m_baseConfigurationFrame.Cells.Add(cell); } catch (Exception ex) { OnProcessException(new InvalidOperationException(string.Format("Failed to define output stream device \"{0}\" due to exception: {1}", deviceRow["Acronym"].ToString().Trim(), ex.Message), ex)); } } OnStatusMessage("Defined {0} output stream devices...", m_baseConfigurationFrame.Cells.Count); // Clear any existing signal references m_signalReferences.Clear(); Dictionary<string, int> signalCellIndexes = new Dictionary<string, int>(); SignalReference signal; SignalReference[] signals; MeasurementKey measurementKey; bool foundQualityFlagsMeasurement = false; bool isQualityFlagsMeasurement; // Define measurement to signals cross reference dictionary foreach (DataRow measurementRow in DataSource.Tables["OutputStreamMeasurements"].Select(string.Format("AdapterID={0}", ID))) { isQualityFlagsMeasurement = false; try { // Create a new signal reference signal = new SignalReference(measurementRow["SignalReference"].ToString()); // See if this is the quality flags designation for this output stream if (signal.Kind == SignalKind.Quality) { if (Name.Equals(signal.Acronym, StringComparison.OrdinalIgnoreCase)) { if (foundQualityFlagsMeasurement) throw new Exception("Only one quality flags measurement can be assigned to an output stream - additional quality flags will be ignored."); foundQualityFlagsMeasurement = true; isQualityFlagsMeasurement = true; } else { throw new Exception(string.Format("Unexpected quality flags measurement assignment to \"{0}\". A single quality flags measurement can be assigned to output stream \"{1}\".", signal.Acronym, Name)); } } else { // Lookup cell index by acronym - doing this work upfront will save a huge amount of work during primary measurement sorting if (!signalCellIndexes.TryGetValue(signal.Acronym, out signal.CellIndex)) { // We cache these indices locally to speed up initialization as we'll be // requesting them for the same devices over and over signal.CellIndex = m_baseConfigurationFrame.Cells.IndexOfStationName(signal.Acronym); signalCellIndexes.Add(signal.Acronym, signal.CellIndex); } } // No need to define this measurement for sorting unless it has a destination in the outgoing frame if (signal.CellIndex > -1 || isQualityFlagsMeasurement) { // Get historian field string historian = measurementRow["Historian"].ToNonNullString(); string pointID = measurementRow["PointID"].ToString(); // Define measurement key if (!string.IsNullOrEmpty(historian)) { measurementKey = MeasurementKey.LookUpOrCreate(historian, uint.Parse(pointID)); } else { DataTable activeMeasurements = DataSource.Tables["ActiveMeasurements"]; DataRow[] activeMeasurementRows = new DataRow[0]; object activeMeasurementSignalID = null; object activeMeasurementID = null; // OPTIMIZE: This select query will be slow on very large ActiveMeasurement implementations, consider optimization. if ((object)activeMeasurements != null) activeMeasurementRows = activeMeasurements.Select(string.Format("ID LIKE '*:{0}'", pointID)); if (activeMeasurementRows.Length == 1) { activeMeasurementSignalID = activeMeasurementRows[0]["SignalID"]; activeMeasurementID = activeMeasurementRows[0]["ID"]; } // If we still can't find the measurement key, now is the time to give up if ((object)activeMeasurementSignalID == null && (object)activeMeasurementID == null) throw new Exception(string.Format("Cannot find measurement key for measurement with pointID {0}", pointID)); measurementKey = MeasurementKey.LookUpOrCreate(Guid.Parse(activeMeasurementRows[0]["SignalID"].ToString()), activeMeasurementID.ToString()); } // It is possible, but not as common, that a single measurement will have multiple destinations // within an outgoing data stream frame, hence the following signals = m_signalReferences.GetOrAdd(measurementKey, null as SignalReference[]); if ((object)signals == null) { // Add new signal to new collection signals = new SignalReference[1]; signals[0] = signal; } else { // Add a new signal to existing collection List<SignalReference> signalList = new List<SignalReference>(signals); signalList.Add(signal); signals = signalList.ToArray(); } m_signalReferences[measurementKey] = signals; } } catch (Exception ex) { OnProcessException(new InvalidOperationException(string.Format("Failed to associate measurement key to signal reference \"{0}\" due to exception: {1}", measurementRow["SignalReference"].ToNonNullString(), ex.Message), ex)); } } // Assign action adapter input measurement keys - this assigns the expected measurements per frame needed // by the concentration engine for preemptive publication InputMeasurementKeys = m_signalReferences.Keys.ToArray(); // Allow for spaces in output stream device names if a replacement character has been defined for spaces if (m_replaceWithSpaceChar != Char.MinValue) { foreach (IConfigurationCell cell in m_baseConfigurationFrame.Cells) { cell.StationName = cell.StationName.Replace(m_replaceWithSpaceChar, ' '); } } // Create a new protocol specific configuration frame m_configurationFrame = CreateNewConfigurationFrame(m_baseConfigurationFrame); // Cache new protocol specific configuration frame CacheConfigurationFrame(m_configurationFrame, Name); }
private void m_frameParser_ReceivedConfigurationFrame(object sender, EventArgs<IConfigurationFrame> e) { // We automatically request enabling of real-time data upon reception of config frame if requested. Note that SEL Fast Message will // have already been enabled at this point so we don't duplicate request for enabling real-time data stream if (m_configurationFrame == null && m_deviceSupportsCommands && m_autoStartDataParsingSequence && m_phasorProtocol != PhasorProtocol.SelFastMessage) SendDeviceCommand(DeviceCommand.EnableRealTimeData); m_frameRateTotal++; m_configurationFrame = e.Argument; // We don't stop parsing for exceptions thrown in consumer event handlers try { if (m_injectSimulatedTimestamp) e.Argument.Timestamp = DateTime.UtcNow.Ticks; if (ReceivedConfigurationFrame != null) ReceivedConfigurationFrame(this, e); } catch (Exception ex) { OnParsingException(ex, "MultiProtocolFrameParser \"ReceivedConfigurationFrame\" consumer event handler exception: {0}", ex.Message); } if (m_transportProtocol == TransportProtocol.File) MaintainCapturedFrameReplayTiming(); }
/// <summary> /// Creates a new <see cref="DataFrameBase"/> from specified parameters. /// </summary> /// <param name="cells">The reference to the collection of cells for this <see cref="DataFrameBase"/>.</param> /// <param name="timestamp">The exact timestamp, in <see cref="Ticks"/>, of the data represented by this <see cref="DataFrameBase"/>.</param> /// <param name="configurationFrame">The <see cref="IConfigurationFrame"/> associated with this <see cref="DataFrameBase"/>.</param> protected DataFrameBase(DataCellCollection cells, Ticks timestamp, IConfigurationFrame configurationFrame) : base(0, cells, timestamp) { m_configurationFrame = configurationFrame; }
/// <summary> /// Creates a new <see cref="DataFrameParsingState"/> from specified parameters. /// </summary> /// <param name="parsedBinaryLength">Binary length of the <see cref="IDataFrame"/> being parsed.</param> /// <param name="configurationFrame">Reference to the <see cref="IConfigurationFrame"/> associated with the <see cref="IDataFrame"/> being parsed.</param> /// <param name="createNewCellFunction">Reference to delegate to create new <see cref="IDataCell"/> instances.</param> /// <param name="trustHeaderLength">Determines if header lengths should be trusted over parsed byte count.</param> /// <param name="validateCheckSum">Determines if frame's check-sum should be validated.</param> public DataFrameParsingState(int parsedBinaryLength, IConfigurationFrame configurationFrame, CreateNewCellFunction<IDataCell> createNewCellFunction, bool trustHeaderLength, bool validateCheckSum) : base(parsedBinaryLength, configurationFrame, createNewCellFunction, trustHeaderLength, validateCheckSum) { }
// Compare last configuration to new received configuration frame to see if there have been any changes private bool CheckForConfigurationChanges() { IConfigurationFrame newConfigurationFrame = m_frameParser?.ConfigurationFrame; bool configurationChanged = false; if ((object)newConfigurationFrame == null) return false; if ((object)m_lastConfigurationFrame == null) { m_configurationChanges++; configurationChanged = true; } else { // Check binary image lengths first, if these are different there is already a change if (m_lastConfigurationFrame.BinaryLength != newConfigurationFrame.BinaryLength) { m_configurationChanges++; configurationChanged = true; } else { // Make sure timestamps are identical since this should not count against comparison m_lastConfigurationFrame.Timestamp = newConfigurationFrame.Timestamp; // Generate binary images for the configuration frames byte[] lastConfigFrameBuffer = new byte[m_lastConfigurationFrame.BinaryLength]; byte[] newConfigFrameBuffer = new byte[newConfigurationFrame.BinaryLength]; try { m_lastConfigurationFrame.GenerateBinaryImage(lastConfigFrameBuffer, 0); } catch (Exception ex) { OnStatusMessage(MessageLevel.Info, $"WARNING: Failed to generate a binary image for cached configuration frame - clearing cache. Exception reported: {ex.Message}"); m_lastConfigurationFrame = null; } try { newConfigurationFrame.GenerateBinaryImage(newConfigFrameBuffer, 0); } catch (Exception ex) { OnStatusMessage(MessageLevel.Info, $"WARNING: Failed to generate a binary image for received configuration frame: {ex.Message}"); return false; } // Compare the binary images - if they are different, this counts as a configuration change if ((object)m_lastConfigurationFrame == null || !lastConfigFrameBuffer.SequenceEqual(newConfigFrameBuffer)) { m_configurationChanges++; configurationChanged = true; } } } m_lastConfigurationFrame = newConfigurationFrame; return configurationChanged; }
/// <summary> /// Creates a new <see cref="DataFrameBase"/> from serialization parameters. /// </summary> /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param> /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param> protected DataFrameBase(SerializationInfo info, StreamingContext context) : base(info, context) { // Deserialize data frame m_configurationFrame = (IConfigurationFrame)info.GetValue("configurationFrame", typeof(IConfigurationFrame)); }
public ConfigurationFrame LoadConfigurationFrame(string sourceData) { IConfigurationFrame sourceFrame = GetConfigurationFrame(sourceData, out string connectionString); if (sourceFrame is ConfigurationErrorFrame) { return(new ConfigurationFrame()); } // Create a new simple concrete configuration frame for JSON serialization converted from equivalent configuration information int protocolID = 0, deviceID = 0, phasorID = -1; // Start phasor ID's at less than -1 since associated voltage == -1 is reserved as unselected if (!string.IsNullOrWhiteSpace(connectionString)) { Dictionary <string, string> settings = connectionString.ParseKeyValuePairs(); protocolID = GetProtocolID(settings["phasorProtocol"]); } ConfigurationFrame derivedFrame = new ConfigurationFrame { IDCode = sourceFrame.IDCode, FrameRate = sourceFrame.FrameRate, ConnectionString = connectionString, ProtocolID = protocolID }; foreach (IConfigurationCell sourceCell in sourceFrame.Cells) { // Create new derived configuration cell ConfigurationCell derivedCell = new ConfigurationCell { ID = --deviceID, // Provide a negative index so any database lookup will return null ParentID = null, IDCode = sourceCell.IDCode, StationName = sourceCell.StationName, IDLabel = sourceCell.IDLabel }; // Create equivalent derived frequency definition IFrequencyDefinition sourceFrequency = sourceCell.FrequencyDefinition; if (sourceFrequency != null) { derivedCell.FrequencyDefinition = new FrequencyDefinition { Label = sourceFrequency.Label } } ; int sourceIndex = 0; // Create equivalent derived phasor definitions foreach (IPhasorDefinition sourcePhasor in sourceCell.PhasorDefinitions) { derivedCell.PhasorDefinitions.Add(new PhasorDefinition { ID = --phasorID, Label = sourcePhasor.Label, PhasorType = sourcePhasor.PhasorType.ToString(), SourceIndex = ++sourceIndex }); } // Create equivalent derived analog definitions (assuming analog type = SinglePointOnWave) foreach (IAnalogDefinition sourceAnalog in sourceCell.AnalogDefinitions) { derivedCell.AnalogDefinitions.Add(new AnalogDefinition { Label = sourceAnalog.Label, AnalogType = sourceAnalog.AnalogType.ToString() }); } // Create equivalent derived digital definitions foreach (IDigitalDefinition sourceDigital in sourceCell.DigitalDefinitions) { derivedCell.DigitalDefinitions.Add(new DigitalDefinition { Label = sourceDigital.Label }); } // Add cell to frame derivedFrame.Cells.Add(derivedCell); } derivedFrame.IsConcentrator = derivedFrame.Cells.Count > 1; return(derivedFrame); }
/// <summary> /// Creates a new <see cref="DataFrameParsingState"/> from specified parameters. /// </summary> /// <param name="parsedBinaryLength">Binary length of the <see cref="IDataFrame"/> being parsed.</param> /// <param name="configurationFrame">Reference to the <see cref="IConfigurationFrame"/> associated with the <see cref="IDataFrame"/> being parsed.</param> /// <param name="createNewCellFunction">Reference to delegate to create new <see cref="IDataCell"/> instances.</param> /// <param name="trustHeaderLength">Determines if header lengths should be trusted over parsed byte count.</param> /// <param name="validateCheckSum">Determines if frame's check-sum should be validated.</param> public DataFrameParsingState(int parsedBinaryLength, IConfigurationFrame configurationFrame, CreateNewCellFunction <IDataCell> createNewCellFunction, bool trustHeaderLength, bool validateCheckSum) : base(parsedBinaryLength, configurationFrame, createNewCellFunction, trustHeaderLength, validateCheckSum) { }
// Static Methods /// <summary> /// Gets a generated INI configuration file image. /// </summary> public static string GetIniFileImage(IConfigurationFrame configFrame) { StringBuilder fileImage = new StringBuilder(); fileImage.AppendLine("; BPA PDCstream IniFile for Configuration " + configFrame.IDCode); fileImage.AppendLine("; Auto-generated on " + DateTime.Now); fileImage.AppendLine("; Assembly: " + AssemblyInfo.ExecutingAssembly.Name); fileImage.AppendLine("; Compiled: " + File.GetLastWriteTime(AssemblyInfo.ExecutingAssembly.Location)); fileImage.AppendLine(";"); fileImage.AppendLine(";"); fileImage.AppendLine("; Format:"); fileImage.AppendLine("; Each Column in data file is given a bracketed identifier, numbered in the order it"); fileImage.AppendLine("; appears in the data file, and identified by data type ( PMU, PDC, or other)"); fileImage.AppendLine("; PMU designates column data format from a single PMU"); fileImage.AppendLine("; PDC designates column data format from another PDC which is somewhat different from a single PMU"); fileImage.AppendLine("; Default gives default values for a processing algorithm in case quantities are omitted"); fileImage.AppendLine("; Name= gives the overall station name for print labels"); fileImage.AppendLine("; NumberPhasors= : for PMU data, gives the number of phasors contained in column"); fileImage.AppendLine("; for PDC data, gives the number of PMUs data included in the column"); fileImage.AppendLine("; Note - for PDC data, there will be 2 phasors & 1 freq per PMU"); fileImage.AppendLine("; Quantities within the column are listed by PhasorI=, Frequency=, etc"); fileImage.AppendLine("; Each quantity has 7 comma separated fields followed by an optional comment"); fileImage.AppendLine(";"); fileImage.AppendLine("; Phasor entry format: Type, Ratio, Cal Factor, Offset, Shunt, VoltageRef/Class, Label ;Comments"); fileImage.AppendLine("; Type: Type of measurement, V=voltage, I=current, N=don\'t care, single ASCII character"); fileImage.AppendLine("; Ratio: PT/CT ratio N:1 where N is a floating point number"); fileImage.AppendLine("; Cal Factor: Conversion factor between integer in file and secondary volts, floating point"); fileImage.AppendLine("; Offset: Phase Offset to correct for phase angle measurement errors or differences, floating point"); fileImage.AppendLine("; Shunt: Current- shunt resistence in ohms, or the equivalent ratio for aux CTs, floating point"); fileImage.AppendLine("; Voltage- empty, not used"); fileImage.AppendLine("; VoltageRef: Current- phasor number (1-10) of voltage phasor to use for power calculation, integer"); fileImage.AppendLine("; Voltage- voltage class, standard l-l voltages, 500, 230, 115, etc, integer"); fileImage.AppendLine("; Label: Phasor quantity label for print label, text"); fileImage.AppendLine("; Comments: All text after the semicolon on a line are optional comments not for processing"); fileImage.AppendLine(";"); fileImage.AppendLine("; Voltage Magnitude = MAG(Real,Imaginary) * CalFactor * PTR (line-neutral)"); fileImage.AppendLine("; Current Magnitude = MAG(Real,Imaginary) * CalFactor * CTR / Shunt (phase current)"); fileImage.AppendLine("; Phase Angle = ATAN(Imaginary/Real) + Phase Offset (usually degrees)"); fileImage.AppendLine("; Note: Usually phase Offset is 0, but is sometimes required for comparing measurements"); fileImage.AppendLine("; from different systems or through transformer banks"); fileImage.AppendLine(";"); fileImage.AppendLine("; Frequency entry format: scale, offset, dF/dt scale, dF/dt offset, dummy, label ;Comments"); fileImage.AppendLine("; Frequency = Number / scale + offset"); fileImage.AppendLine("; dF/dt = Number / (dF/dt scale) + (dF/dt offset)"); fileImage.AppendLine(";"); fileImage.AppendLine(";"); fileImage.AppendLine("[DEFAULT]"); fileImage.AppendLine("PhasorV=" + DefaultVoltagePhasorEntry); //PhasorDefinition.ConfigFileFormat(DefaultPhasorV)); fileImage.AppendLine("PhasorI=" + DefaultCurrentPhasorEntry); //PhasorDefinition.ConfigFileFormat(DefaultPhasorI)); fileImage.AppendLine("Frequency=" + DefaultFrequencyEntry); //FrequencyDefinition.ConfigFileFormat(DefaultFrequency)); fileImage.AppendLine(); fileImage.AppendLine("[CONFIG]"); fileImage.AppendLine("SampleRate=" + configFrame.FrameRate); fileImage.AppendLine("NumberOfPMUs=" + configFrame.Cells.Count); fileImage.AppendLine(); for (int x = 0; x < configFrame.Cells.Count; x++) { fileImage.AppendLine("[" + configFrame.Cells[x].IDLabel + "]"); fileImage.AppendLine("Name=" + configFrame.Cells[x].StationName); fileImage.AppendLine("PMU=" + x); fileImage.AppendLine("NumberPhasors=" + configFrame.Cells[x].PhasorDefinitions.Count); for (int y = 0; y < configFrame.Cells[x].PhasorDefinitions.Count; y++) { fileImage.AppendLine("Phasor" + (y + 1) + "=" + PhasorDefinition.ConfigFileFormat(configFrame.Cells[x].PhasorDefinitions[y])); } fileImage.AppendLine("Frequency=" + FrequencyDefinition.ConfigFileFormat(configFrame.Cells[x].FrequencyDefinition)); fileImage.AppendLine(); } return(fileImage.ToString()); }