예제 #1
0
 /// <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);
            }
        }
예제 #3
0
 /// <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);
 }
예제 #4
0
 /// <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();
        }
예제 #6
0
        // 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);
        }
예제 #7
0
 /// <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);
 }
예제 #8
0
 /// <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);
        }
예제 #11
0
        /// <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));
        }
예제 #13
0
        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));
        }
예제 #14
0
        /// <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);
        }
예제 #15
0
        // 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);
        }
예제 #16
0
        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;
        }
예제 #17
0
        /// <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;
            }
        }
예제 #18
0
        // 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);
        }
예제 #19
0
        // 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);
        }
예제 #20
0
        /// <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);
                            }
                        }
                    }
                }
            }
        }
예제 #21
0
        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;
            }
        }
예제 #22
0
파일: FrameParser.cs 프로젝트: kobi2187/gsf
        /// <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
        }
예제 #23
0
        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());
        }
예제 #24
0
        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);
        }
예제 #25
0
        /// <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);
        }
예제 #26
0
        /// <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);
        }
예제 #27
0
        // 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);
        }
예제 #28
0
        /// <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;
                    }
                }
            }
        }
예제 #29
0
        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();
        }
예제 #30
0
        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();
        }
예제 #31
0
        /// <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().
                }
            }
        }
예제 #32
0
        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();
                    }
                }
            }
        }
예제 #33
0
        /// <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;
            }
        }
예제 #34
0
        /// <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
        }
예제 #35
0
        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);
        }
예제 #36
0
        /// <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));
            }
        }
예제 #37
0
        /// <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));
        }
예제 #38
0
        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);
        }
예제 #39
0
 /// <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)
 {
 }
예제 #40
0
        // 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);
        }
예제 #41
0
        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();
            }
        }
예제 #42
0
        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();
            }
        }
예제 #43
0
        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;
        }
예제 #44
0
        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);
        }
예제 #45
0
        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();
        }
예제 #46
0
 /// <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;
 }
예제 #47
0
 /// <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;
        }
예제 #49
0
 /// <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));
 }
예제 #50
0
        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);
        }
예제 #51
0
 /// <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)
 {
 }
예제 #52
0
        // 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());
        }