Protocol independent frame parser.
This class takes all protocol frame parsing implementations and reduces them to a single simple-to-use class exposing all data through abstract interfaces (e.g., IConfigurationFrame, IDataFrame, etc.) - this way new protocol implementations can be added without adversely affecting consuming code. Additionally, this class implements a variety of transport options (e.g., TCP, UDP, Serial, etc.) and hides the complexities of this connectivity and internally pushes all data received from the selected transport protocol to the selected phasor parsing protocol.
Inheritance: IFrameParser
Esempio n. 1
0
        /// <summary>
        /// Creates a new <see cref="CommonPhasorServices"/>.
        /// </summary>
        public CommonPhasorServices()
        {
            // Create wait handle to use to wait for configuration frame
            m_configurationWaitHandle = new ManualResetEvent(false);

            // Create a new phasor protocol frame parser used to dynamically request device configuration frames
            // and return them to remote clients so that the frame can be used in system setup and configuration
            m_frameParser = new MultiProtocolFrameParser();

            // Attach to events on new frame parser reference
            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;

            // We only want to try to connect to device and retrieve configuration as quickly as possible
            m_frameParser.MaximumConnectionAttempts = 1;
            m_frameParser.SourceName = Name;
            m_frameParser.AutoRepeatCapturedPlayback = false;
            m_frameParser.AutoStartDataParsingSequence = false;
            m_frameParser.SkipDisableRealTimeData = true;
        }
Esempio n. 2
0
File: Program.cs Progetto: rmc00/gsf
        public static void Main(string[] args)
        {
            m_definedMeasurements = new ConcurrentDictionary<string, IMeasurement>();
            m_definedDevices = new ConcurrentDictionary<ushort, ConfigurationCell>();

            if (WriteLogs)
                m_exportFile = new StreamWriter(FilePath.GetAbsolutePath("InputTimestamps.csv"));

            if (TestConcentrator)
            {
                // Create a new concentrator
                concentrator = new Concentrator(WriteLogs, FilePath.GetAbsolutePath("OutputTimestamps.csv"));
                concentrator.TimeResolution = 333000;
                concentrator.FramesPerSecond = 30;
                concentrator.LagTime = 3.0D;
                concentrator.LeadTime = 9.0D;
                concentrator.PerformTimestampReasonabilityCheck = false;
                concentrator.ProcessByReceivedTimestamp = true;
                concentrator.Start();
            }

            // Create a new protocol parser
            parser = new MultiProtocolFrameParser();
            parser.AllowedParsingExceptions = 500;
            parser.ParsingExceptionWindow = 5;

            // Attach to desired events
            parser.ConnectionAttempt += parser_ConnectionAttempt;
            parser.ConnectionEstablished += parser_ConnectionEstablished;
            parser.ConnectionException += parser_ConnectionException;
            parser.ParsingException += parser_ParsingException;
            parser.ReceivedConfigurationFrame += parser_ReceivedConfigurationFrame;
            parser.ReceivedDataFrame += parser_ReceivedDataFrame;
            parser.ReceivedFrameBufferImage += parser_ReceivedFrameBufferImage;
            parser.ConnectionTerminated += parser_ConnectionTerminated;

            // Define the connection string
            //parser.ConnectionString = @"phasorProtocol=IeeeC37_118V1; transportProtocol=UDP; localport=5000; server=233.123.123.123:5000; interface=0.0.0.0";
            //parser.ConnectionString = @"phasorProtocol=Ieee1344; transportProtocol=File; file=D:\Projects\Applications\openPDC\Synchrophasor\Current Version\Build\Output\Debug\Applications\openPDC\Sample1344.PmuCapture";
            //parser.ConnectionString = @"phasorProtocol=Macrodyne; accessID=1; transportProtocol=File; skipDisableRealTimeData = true; file=C:\Users\Ritchie\Desktop\Development\Macrodyne\ING.out; iniFileName=C:\Users\Ritchie\Desktop\Development\Macrodyne\BCH18Aug2011.ini; deviceLabel=ING1; protocolVersion=G";
            //parser.ConnectionString = @"phasorProtocol=Iec61850_90_5; accessID=1; transportProtocol=UDP; skipDisableRealTimeData = true; localPort=102; interface=0.0.0.0; commandChannel={transportProtocol=TCP; server=172.21.1.201:4712; interface=0.0.0.0}";
            //parser.ConnectionString = @"phasorProtocol=FNET; transportProtocol=TCP; server=172.21.4.100:4001; interface=0.0.0.0; isListener=false";
            //parser.ConnectionString = @"phasorProtocol=Macrodyne; transportProtocol=Serial; port=COM6; baudrate=38400; parity=None; stopbits=One; databits=8; dtrenable=False; rtsenable=False;";
            //parser.ConnectionString = @"phasorProtocol=SelFastMessage; transportProtocol=Serial; port=COM5; baudrate=57600; parity=None; stopbits=One; databits=8; dtrenable=False; rtsenable=False;";            
            //parser.ConnectionString = @"phasorProtocol=IEEEC37_118v1; transportProtocol=File; file=C:\Users\Ritchie\Desktop\MTI_Test_3phase.PmuCapture; checkSumValidationFrameTypes=DataFrame,HeaderFrame,CommandFrame";
            parser.ConnectionString = @"phasorProtocol=IEEEC37_118V1; transportProtocol=tcp; accessID=105; server=172.31.105.135:4712; interface=0.0.0.0; isListener=false";

            Dictionary<string, string> settings = parser.ConnectionString.ParseKeyValuePairs();
            string setting;

            // TODO: These should be optional picked up from connection string inside of MPFP
            // Apply other settings as needed
            if (settings.TryGetValue("accessID", out setting))
                parser.DeviceID = ushort.Parse(setting);

            if (settings.TryGetValue("simulateTimestamp", out setting))
                parser.InjectSimulatedTimestamp = setting.ParseBoolean();

            if (settings.TryGetValue("allowedParsingExceptions", out setting))
                parser.AllowedParsingExceptions = int.Parse(setting);

            if (settings.TryGetValue("parsingExceptionWindow", out setting))
                parser.ParsingExceptionWindow = Ticks.FromSeconds(double.Parse(setting));

            if (settings.TryGetValue("autoStartDataParsingSequence", out setting))
                parser.AutoStartDataParsingSequence = setting.ParseBoolean();

            if (settings.TryGetValue("skipDisableRealTimeData", out setting))
                parser.SkipDisableRealTimeData = setting.ParseBoolean();

            // When connecting to a file based resource you may want to loop the data
            parser.AutoRepeatCapturedPlayback = true;

            // Start frame parser
            parser.AutoStartDataParsingSequence = true;

            Console.WriteLine("ConnectionString: {0}", parser.ConnectionString);

            parser.Start();

            // To keep the console open while receiving live data with AutoRepeatCapturedPlayback = false, uncomment the following line of code:

            Console.WriteLine("Press <enter> to terminate application...");

            Console.ReadLine();

            parser.Stop();

            // Stop concentrator
            if (TestConcentrator)
                concentrator.Stop();

            if (WriteLogs)
                m_exportFile.Close();
        }
Esempio n. 3
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().
                }
            }
        }
        /// <summary>
        /// Initializes <see cref="PhasorMeasurementMapper"/>.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            Dictionary<string, string> settings = Settings;
            string setting;

            // Load optional mapper specific connection parameters
            if (settings.TryGetValue("isConcentrator", out setting))
                m_isConcentrator = setting.ParseBoolean();
            else
                m_isConcentrator = false;

            if (settings.TryGetValue("accessID", out setting))
                m_accessID = ushort.Parse(setting);
            else
                m_accessID = 1;

            if (settings.TryGetValue("forceLabelMapping", out setting))
                m_forceLabelMapping = setting.ParseBoolean();
            else
                m_forceLabelMapping = false;

            // Commented out for security purposes related to Parent collection --
            // Replace with secure notification mechanism

            //if (settings.TryGetValue("primaryDataSource", out setting))
            //{
            //    uint primaryDataSourceID = 0;

            //    // Lookup adapter runtime ID of specified primary data source
            //    if (!string.IsNullOrWhiteSpace(setting))
            //    {
            //        try
            //        {
            //            DataRow[] filteredRows = DataSource.Tables["InputAdapters"].Select(string.Format("AdapterName = '{0}'", setting));

            //            if (filteredRows.Length > 0)
            //                primaryDataSourceID = uint.Parse(filteredRows[0]["ID"].ToString());
            //            else
            //                OnProcessException(new InvalidOperationException(string.Format("Failed to find input adapter ID for primary data source \"{0}\", data source was not established.", setting)));
            //        }
            //        catch (Exception ex)
            //        {
            //            OnProcessException(new InvalidOperationException(string.Format("Failed to find input adapter ID for primary data source \"{0}\" due to exception: {1} Data source was not established.", setting, ex.Message), ex));
            //        }
            //    }

            //    if (primaryDataSourceID > 0)
            //    {
            //        // Get matching data subscriber
            //        m_primaryDataSource = Parent.FirstOrDefault(adapter => adapter.ID == primaryDataSourceID && adapter is DataSubscriber) as DataSubscriber;

            //        if ((object)m_primaryDataSource == null)
            //        {
            //            OnProcessException(new InvalidOperationException(string.Format("Input adapter \"{0}\" specified to be the primary data source was not a DataSubscriber adapter, data source was not established.", setting)));
            //        }
            //        else
            //        {
            //            // Attach to connection events of primary source adapter since these will be used to control when back connection is established...
            //            m_primaryDataSource.ConnectionEstablished += m_primaryDataSource_ConnectionEstablished;
            //            m_primaryDataSource.ConnectionTerminated += m_primaryDataSource_ConnectionTerminated;
            //        }
            //    }
            //}

            if (settings.TryGetValue("sharedMapping", out setting))
                SharedMapping = setting.Trim();
            else
                SharedMapping = null;

            if (settings.TryGetValue("timeZone", out setting) && !string.IsNullOrWhiteSpace(setting) && !setting.Trim().Equals("UTC", StringComparison.OrdinalIgnoreCase) && !setting.Trim().Equals("Coordinated Universal Time", StringComparison.OrdinalIgnoreCase))
            {
                try
                {
                    m_timezone = TimeZoneInfo.FindSystemTimeZoneById(setting);
                }
                catch (Exception ex)
                {
                    OnProcessException(MessageLevel.Info, new InvalidOperationException($"Defaulting to UTC. Failed to find system time zone for ID \"{setting}\": {ex.Message}", ex));
                    m_timezone = TimeZoneInfo.Utc;
                }
            }
            else
            {
                m_timezone = TimeZoneInfo.Utc;
            }

            if (settings.TryGetValue("timeAdjustmentTicks", out setting))
                m_timeAdjustmentTicks = long.Parse(setting);
            else
                m_timeAdjustmentTicks = 0;

            if (settings.TryGetValue("dataLossInterval", out setting))
                m_dataStreamMonitor.Interval = (int)(double.Parse(setting) * 1000.0D);
            else
                m_dataStreamMonitor.Interval = 5000;

            if (settings.TryGetValue("delayedConnectionInterval", out setting))
            {
                double interval = double.Parse(setting) * 1000.0D;

                // Minimum delay is one millisecond
                if (interval < 1.0D)
                    interval = 1.0D;

                ConnectionAttemptInterval = interval;
            }
            else
            {
                ConnectionAttemptInterval = 1500.0D;
            }

            if (settings.TryGetValue("allowUseOfCachedConfiguration", out setting))
                m_allowUseOfCachedConfiguration = setting.ParseBoolean();
            else
                m_allowUseOfCachedConfiguration = true;

            if (settings.TryGetValue("countOnlyMappedMeasurements", out setting))
                m_countOnlyMappedMeasurements = setting.ParseBoolean();
            else
                m_countOnlyMappedMeasurements = false;

            // Create a new phasor protocol frame parser for non-virtual connections
            MultiProtocolFrameParser frameParser = new MultiProtocolFrameParser();

            // 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
            frameParser.ConnectionString = ConnectionString;

            // Since input adapter will automatically reconnect on connection exceptions, we need only to specify
            // that the frame parser try to connect once per connection attempt
            frameParser.MaximumConnectionAttempts = 1;

            // For captured data simulations we will inject a simulated timestamp and auto-repeat file stream...
            if (frameParser.TransportProtocol == TransportProtocol.File)
            {
                if (settings.TryGetValue("definedFrameRate", out setting))
                    frameParser.DefinedFrameRate = int.Parse(setting);
                else
                    frameParser.DefinedFrameRate = 30;

                if (settings.TryGetValue("autoRepeatFile", out setting))
                    frameParser.AutoRepeatCapturedPlayback = setting.ParseBoolean();
                else
                    frameParser.AutoRepeatCapturedPlayback = true;

                if (settings.TryGetValue("useHighResolutionInputTimer", out setting))
                    frameParser.UseHighResolutionInputTimer = setting.ParseBoolean();
                else
                    frameParser.UseHighResolutionInputTimer = false;
            }

            // Apply other settings as needed
            if (settings.TryGetValue("simulateTimestamp", out setting))
                frameParser.InjectSimulatedTimestamp = setting.ParseBoolean();
            else
                frameParser.InjectSimulatedTimestamp = (frameParser.TransportProtocol == TransportProtocol.File);

            if (settings.TryGetValue("allowedParsingExceptions", out setting))
                frameParser.AllowedParsingExceptions = int.Parse(setting);

            if (settings.TryGetValue("parsingExceptionWindow", out setting))
                frameParser.ParsingExceptionWindow = Ticks.FromSeconds(double.Parse(setting));

            if (settings.TryGetValue("autoStartDataParsingSequence", out setting))
                frameParser.AutoStartDataParsingSequence = setting.ParseBoolean();

            if (settings.TryGetValue("skipDisableRealTimeData", out setting))
                frameParser.SkipDisableRealTimeData = setting.ParseBoolean();

            if (!(settings.TryGetValue("lagTime", out setting) && double.TryParse(setting, out m_lagTime)))
                m_lagTime = 10.0D;

            if (!(settings.TryGetValue("leadTime", out setting) && double.TryParse(setting, out m_leadTime)))
                m_leadTime = 3.0D;

            if (!(settings.TryGetValue("timeResolution", out setting) && long.TryParse(setting, out m_timeResolution)))
                m_timeResolution = 10000L;

            if (settings.TryGetValue("enableConnectionErrors", out setting))
                EnableConnectionErrors = setting.ParseBoolean();

            // Provide access ID to frame parser as this may be necessary to make a phasor connection
            frameParser.DeviceID = m_accessID;
            frameParser.SourceName = Name;

            // Assign reference to frame parser for this connection and attach to needed events
            FrameParser = frameParser;

            // Load input devices associated with this connection
            LoadInputDevices();

            // Load active device measurements associated with this connection
            LoadDeviceMeasurements();

            // Load specific configuration file if one was specified
            if (settings.TryGetValue("configurationFile", out setting))
                LoadConfiguration(setting);

            // Register with the statistics engine
            StatisticsEngine.Register(this, "InputStream", "IS");
            StatisticsEngine.Calculated += (sender, args) => ResetLatencyCounters();
            StatisticsEngine.Calculated += (sender, args) => ResetMeasurementsPerSecondCounters();
        }