Esempio n. 1
0
        // Tests the given measurement to determine whether
        // its value indicates that the signal has been in
        // the alarming range for the configured delay time.
        private bool CheckRange(IMeasurement signal)
        {
            bool  result = GetTestResult(signal);
            Ticks dist;

            if (!result)
            {
                // Keep track of the last time
                // the signal was in range
                m_lastNegative = signal.Timestamp;
            }
            else
            {
                // Get the amount of time since the
                // last time the value was in range
                dist = signal.Timestamp - m_lastNegative;

                // If the amount of time is larger than
                // the delay threshold, raise the alarm
                if (dist >= Ticks.FromSeconds(Delay.Value))
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 2
0
File: Alarm.cs Progetto: xj0229/gsf
        // Keeps track of the signal's timestamps to determine whether a given
        // measurement is eligible to raise the alarm based on the delay.
        private bool CheckDelay(IMeasurement measurement, bool raiseCondition)
        {
            Ticks dist;

            if (!raiseCondition)
            {
                // Keep track of the last time
                // the signal failed the raise test
                m_lastNegative = measurement.Timestamp;
            }
            else
            {
                // Get the amount of time since the last
                // time the signal failed the raise test
                dist = measurement.Timestamp - m_lastNegative;

                // If the amount of time is larger than
                // the delay threshold, raise the alarm
                if (dist >= Ticks.FromSeconds(m_delay.GetValueOrDefault()))
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TimestampTest"/> class.
 /// </summary>
 public TimestampTest()
 {
     m_badTimestampMeasurements = new Dictionary <Ticks, LinkedList <IMeasurement> >();
     m_timeToPurge  = Ticks.FromSeconds(1.0);
     m_warnInterval = Ticks.FromSeconds(4.0);
     m_purgeTimer   = new Timer();
     m_warningTimer = new Timer();
 }
Esempio n. 4
0
 /// <summary>
 /// Creates a new instance of the <see cref="RangeTest"/> class.
 /// </summary>
 public RangeTest()
 {
     m_outOfRangeMeasurements = new Dictionary <MeasurementKey, LinkedList <IMeasurement> >();
     m_timeToPurge            = Ticks.FromSeconds(1.0);
     m_warnInterval           = Ticks.FromSeconds(4.0);
     m_warningTimer           = new Timer();
     m_purgeTimer             = new Timer();
 }
Esempio n. 5
0
        /// <summary>
        /// Gets a short one-line status of this <see cref="AdapterBase"/>.
        /// </summary>
        /// <param name="maxLength">Maximum number of available characters for display.</param>
        /// <returns>A short one-line summary of the current status of this <see cref="AdapterBase"/>.</returns>
        public override string GetShortStatus(int maxLength)
        {
            if (!Enabled || !IsConnected)
            {
                return($"Streaming for \"{Path.GetFileName(WavFileName)}\" is paused...".CenterText(maxLength));
            }

            TimeSpan time = Ticks.FromSeconds(m_dataIndex / (double)m_sampleRate);

            return($"Streaming \"{Path.GetFileName(WavFileName)}\" at time {time.ToString(@"m\:ss")} / {m_audioLength.ToString(@"m\:ss")} - {time.TotalSeconds / m_audioLength.TotalSeconds:0.00%}.".CenterText(maxLength));
        }
Esempio n. 6
0
        /// <summary>
        /// Creates a new instance of the <see cref="FlatlineTest"/> class.
        /// </summary>
        public FlatlineTest()
        {
            m_minFlatline   = Ticks.FromSeconds(4);
            m_warnInterval  = Ticks.FromSeconds(4);
            m_emailInterval = Ticks.FromSeconds(3600);
            m_smtpServer    = Mail.DefaultSmtpServer;

            m_lastChange   = new Dictionary <MeasurementKey, IMeasurement>();
            m_lastNotified = new Dictionary <MeasurementKey, Ticks>();
            m_warningTimer = new Timer();
        }
Esempio n. 7
0
        /// <summary>
        /// Initializes this <see cref="RangeTest"/>.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            string errorMessage = "{0} is missing from Settings - Example: lowRange=59.95; highRange=60.05";
            bool   rangeSet     = false;

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

            if (settings.TryGetValue("signalType", out m_signalType))
            {
                rangeSet = TrySetRange(m_signalType);
            }

            if (!rangeSet)
            {
                // Load required parameters
                if (!settings.TryGetValue("lowRange", out setting))
                {
                    throw new ArgumentException(string.Format(errorMessage, "lowRange"));
                }

                m_lowRange = double.Parse(setting);

                if (!settings.TryGetValue("highRange", out setting))
                {
                    throw new ArgumentException(string.Format(errorMessage, "highRange"));
                }

                m_highRange = double.Parse(setting);

                rangeSet = true;
            }

            // Load optional parameters
            if (settings.TryGetValue("timeToPurge", out setting))
            {
                m_timeToPurge = Ticks.FromSeconds(double.Parse(setting));
            }

            if (settings.TryGetValue("warnInterval", out setting))
            {
                m_warnInterval = Ticks.FromSeconds(double.Parse(setting));
            }

            m_warningTimer.Interval = m_warnInterval.ToMilliseconds();
            m_warningTimer.Elapsed += m_warningTimer_Elapsed;

            m_purgeTimer.Interval = m_timeToPurge.ToMilliseconds();
            m_purgeTimer.Elapsed += m_purgeTimer_Elapsed;
        }
Esempio n. 8
0
        static GlobalDeviceStatistics()
        {
            CategorizedSettingsElementCollection settings = ConfigurationFile.Current.Settings["systemSettings"];

            settings.Add("MedianTimestampDeviation", DefaultMedianTimestampDeviation, "Maximum allowed deviation from median timestamp, in seconds, for consideration in average timestamp calculation.");

            s_medianTimestampDeviation = new BigInteger(Ticks.FromSeconds(settings["MedianTimestampDeviation"].ValueAs(DefaultMedianTimestampDeviation)).Value);
            s_latestDeviceTimes        = new ConcurrentDictionary <IDevice, LatestDeviceTime>();
            s_bigTwo     = new BigInteger(2);
            s_bigMaxLong = new BigInteger(long.MaxValue);

            StatisticsEngine.SourceRegistered   += StatisticsEngine_SourceRegistered;
            StatisticsEngine.SourceUnregistered += StatisticsEngine_SourceUnregistered;
            StatisticsEngine.BeforeCalculate    += StatisticsEngine_BeforeCalculate;
        }
Esempio n. 9
0
File: Alarm.cs Progetto: xj0229/gsf
        // Indicates whether the given measurement has maintained the same
        // value for at least a number of seconds defined by the delay.
        private bool RaiseIfFlatline(IMeasurement measurement)
        {
            long dist, diff;

            if (measurement.Value != m_lastValue)
            {
                m_lastChanged = measurement.Timestamp;
                m_lastValue   = measurement.Value;
            }

            dist = Ticks.FromSeconds(Delay.GetValueOrDefault());
            diff = measurement.Timestamp - m_lastChanged;

            return(diff >= dist);
        }
Esempio n. 10
0
        // Determines whether the given value has
        // flatlined over the configured delay interval.
        private bool CheckFlatline(IMeasurement signal)
        {
            long dist, diff;

            if (signal.Value != m_lastValue)
            {
                m_lastChanged = signal.Timestamp;
                m_lastValue   = signal.Value;
            }

            dist = Ticks.FromSeconds(Delay.Value);
            diff = signal.Timestamp - m_lastChanged;

            return(diff >= dist);
        }
Esempio n. 11
0
        private void m_activityMonitor_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (DateTime.UtcNow.Ticks - m_lastFileChangedTime > Ticks.FromSeconds(60.0D))
            {
                m_activityMonitor.Enabled = false;

                try
                {
                    m_process?.Kill();
                }
                catch (Exception ex)
                {
                    Program.Log("Error while trying to kill no responsive downloader: " + ex.Message);
                    throw;
                }
            }
        }
Esempio n. 12
0
        private int ReadTimestamp(byte[] buffer)
        {
            int index = 0;

            // Read sample index
            uint sample = LittleEndian.ToUInt32(buffer, index);

            index += 4;

            // Get timestamp of this record
            Timestamp = DateTime.MinValue;

            // If sample rates are defined, this is the preferred method for timestamp resolution
            if (InferTimeFromSampleRates && m_schema.SampleRates.Length > 0)
            {
                // Find rate for given sample
                SampleRate sampleRate = m_schema.SampleRates.LastOrDefault(sr => sample <= sr.EndSample);

                if (sampleRate.Rate > 0.0D)
                {
                    Timestamp = new DateTime(Ticks.FromSeconds(1.0D / sampleRate.Rate * sample) + m_schema.StartTime.Value);
                }
            }

            // Read microsecond timestamp
            uint microseconds = LittleEndian.ToUInt32(buffer, index);

            index += 4;

            // Fall back on specified microsecond time
            if (Timestamp == DateTime.MinValue)
            {
                Timestamp = new DateTime(Ticks.FromMicroseconds(microseconds * m_schema.TimeFactor) + m_schema.StartTime.Value);
            }

            // Apply timestamp offset to restore UTC timezone
            if (AdjustToUTC)
            {
                TimeOffset offset = Schema.TimeCode ?? new TimeOffset();
                Timestamp = new DateTime(Timestamp.Ticks + offset.TickOffset, DateTimeKind.Utc);
            }

            return(index);
        }
Esempio n. 13
0
        /// <summary>
        /// Initializes <see cref="FlatlineTest"/>.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

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

            if (settings.TryGetValue("minFlatline", out setting))
            {
                m_minFlatline = Ticks.FromSeconds(double.Parse(setting));
            }

            if (settings.TryGetValue("warnInterval", out setting))
            {
                m_warnInterval = Ticks.FromSeconds(double.Parse(setting));
            }

            if (settings.TryGetValue("adminEmailAddress", out m_adminEmailAddress))
            {
                // emailInterval is entered in minutes.
                if (settings.TryGetValue("emailInterval", out setting))
                {
                    m_emailInterval = Ticks.FromSeconds(long.Parse(setting) * 60L);
                }
            }

            if (settings.TryGetValue("smtpServer", out setting))
            {
                m_smtpServer = setting;
            }

            m_warningTimer.Interval = m_warnInterval.ToMilliseconds();
            m_warningTimer.Elapsed += m_warningTimer_Elapsed;

            m_flatlineService = new FlatlineService(this);
            m_flatlineService.SettingsCategory         = base.Name + m_flatlineService.SettingsCategory;
            m_flatlineService.ServiceProcessException += m_flatlineService_ServiceProcessException;
            m_flatlineService.Initialize();

            InitializeLastChange();
        }
Esempio n. 14
0
        // Static Methods

        /// <summary>
        /// Gets proper NTP offset based on <paramref name="seconds"/> value, see RFC-2030.
        /// </summary>
        /// <param name="seconds">Seconds value.</param>
        /// <returns>Proper NTP offset.</returns>
        protected static long GetBaseDateOffsetTicks(double seconds)
        {
            return(GetBaseDateOffsetTicks(Ticks.FromSeconds(seconds)));
        }
Esempio n. 15
0
        // Internal Functions

        private void ReadArchive(object state)
        {
            try
            {
                double    timeRange           = (m_settings.EndTime - m_settings.StartTime).TotalSeconds;
                long      receivedPoints      = 0;
                long      processedDataBlocks = 0;
                long      duplicatePoints     = 0;
                Ticks     operationTime;
                Ticks     operationStartTime;
                DataPoint point          = new DataPoint();
                DateTime  firstTimestamp = new DateTime(0L);
                DateTime  lastTimestamp  = new DateTime(0L);

                using (Algorithm algorithm = new Algorithm())
                {
                    algorithm.ShowMessage     = ShowUpdateMessage;
                    algorithm.MessageInterval = m_settings.MessageInterval;
                    algorithm.StartTime       = m_settings.StartTime;
                    algorithm.EndTime         = m_settings.EndTime;
                    algorithm.FrameRate       = m_settings.FrameRate;
                    algorithm.TimeRange       = timeRange;
                    algorithm.Log             = m_log;

                    // Load historian meta-data
                    ShowUpdateMessage(">>> Loading source connection metadata...");

                    operationStartTime = DateTime.UtcNow.Ticks;
                    algorithm.Metadata = MetadataRecord.Query(m_settings.HostAddress, m_settings.MetadataPort, m_settings.MetadataTimeout);
                    operationTime      = DateTime.UtcNow.Ticks - operationStartTime;

                    ShowUpdateMessage("*** Metadata Load Complete ***");
                    ShowUpdateMessage($"Total metadata load time {operationTime.ToElapsedTimeString(3)}...");

                    ShowUpdateMessage(">>> Processing filter expression for metadata...");

                    operationStartTime = DateTime.UtcNow.Ticks;
                    MeasurementKey[] inputKeys   = AdapterBase.ParseInputMeasurementKeys(MetadataRecord.Metadata, false, textBoxPointList.Text, "MeasurementDetail");
                    List <ulong>     pointIDList = inputKeys.Select(key => (ulong)key.ID).ToList();
                    operationTime = DateTime.UtcNow.Ticks - operationStartTime;

                    // Allow algorithm to augment (or even replace) point ID list as provided by user
                    algorithm.AugmentPointIDList(pointIDList);

                    ShowUpdateMessage($">>> Historian read will be for {pointIDList.Count:N0} points based on provided meta-data expression and algorithm augmentation.");

                    // Reduce metadata to filtered point list
                    ShowUpdateMessage($">>> Reducing metadata to the {pointIDList.Count:N0} defined points...");

                    List <MetadataRecord> records = new List <MetadataRecord>();

                    foreach (ulong pointID in pointIDList)
                    {
                        MetadataRecord record = algorithm.Metadata.FirstOrDefault(metadata => metadata.PointID == pointID);

                        if ((object)record != null)
                        {
                            records.Add(record);
                        }
                    }

                    algorithm.Metadata = records;

                    ShowUpdateMessage("*** Filter Expression Processing Complete ***");
                    ShowUpdateMessage($"Total filter expression processing time {operationTime.ToElapsedTimeString(3)}...");

                    ShowUpdateMessage(">>> Initializing algorithm...");
                    algorithm.Initialize();

                    ShowUpdateMessage(">>> Starting archive read...");

                    // Start historian data read
                    operationStartTime = DateTime.UtcNow.Ticks;

                    using (SnapDBClient historianClient = new SnapDBClient(m_settings.HostAddress, m_settings.DataPort, m_settings.InstanceName, m_settings.StartTime, m_settings.EndTime, m_settings.FrameRate, pointIDList))
                    {
                        // Scan to first record
                        if (!historianClient.ReadNext(point))
                        {
                            throw new InvalidOperationException("No data for specified time range in openHistorian connection!");
                        }

                        ulong currentTimestamp;
                        receivedPoints++;

                        while (!m_formClosing)
                        {
                            int  timeComparison;
                            bool readSuccess = true;

                            // Create a new data block for current timestamp and load first/prior point
                            Dictionary <ulong, DataPoint> dataBlock = new Dictionary <ulong, DataPoint>
                            {
                                [point.PointID] = point.Clone()
                            };

                            currentTimestamp = point.Timestamp;

                            // Load remaining data for current timestamp
                            do
                            {
                                // Scan to next record
                                if (!historianClient.ReadNext(point))
                                {
                                    readSuccess = false;
                                    break;
                                }

                                receivedPoints++;
                                timeComparison = DataPoint.CompareTimestamps(point.Timestamp, currentTimestamp, m_settings.FrameRate);

                                if (timeComparison == 0)
                                {
                                    // Timestamps are compared based on configured frame rate - if archived data rate is
                                    // higher than configured frame rate, then data block will contain only latest values
                                    if (dataBlock.ContainsKey(point.PointID))
                                    {
                                        duplicatePoints++;
                                    }

                                    dataBlock[point.PointID] = point.Clone();
                                }
                            }while (timeComparison == 0);

                            // Finished with data read
                            if (!readSuccess)
                            {
                                ShowUpdateMessage(">>> End of data in range encountered...");
                                break;
                            }

                            if (++processedDataBlocks % m_settings.MessageInterval == 0)
                            {
                                ShowUpdateMessage($"{Environment.NewLine}{receivedPoints:N0} points{(duplicatePoints > 0 ? $", which included {duplicatePoints:N0} duplicates," : "")} read so far averaging {receivedPoints / (DateTime.UtcNow.Ticks - operationStartTime).ToSeconds():N0} points per second.");
                                UpdateProgressBar((int)((1.0D - new Ticks(m_settings.EndTime.Ticks - (long)point.Timestamp).ToSeconds() / timeRange) * 100.0D));
                            }

                            try
                            {
                                lastTimestamp = new DateTime((long)currentTimestamp);

                                if (firstTimestamp.Ticks == 0L)
                                {
                                    firstTimestamp = lastTimestamp;
                                }

                                // Analyze data block
                                algorithm.Execute(lastTimestamp, dataBlock.Values.ToArray());
                            }
                            catch (Exception ex)
                            {
                                ShowUpdateMessage($"ERROR: Algorithm exception: {ex.Message}");
                                m_log.Publish(MessageLevel.Error, "AlgorithmError", "Failed while processing data from the historian", exception: ex);
                            }
                        }

                        operationTime = DateTime.UtcNow.Ticks - operationStartTime;

                        if (m_formClosing)
                        {
                            ShowUpdateMessage("*** Historian Read Canceled ***");
                            UpdateProgressBar(0);
                        }
                        else
                        {
                            ShowUpdateMessage("*** Historian Read Complete ***");
                            UpdateProgressBar(100);
                        }

                        algorithm.Complete();

                        // Show some operational statistics
                        long   expectedPoints   = (long)(timeRange * m_settings.FrameRate * algorithm.Metadata.Count);
                        double dataCompleteness = Math.Round(receivedPoints / (double)expectedPoints * 100000.0D) / 1000.0D;

                        string overallSummary =
                            $"Total processing time {operationTime.ToElapsedTimeString(3)} at {receivedPoints / operationTime.ToSeconds():N0} points per second.{Environment.NewLine}" +
                            $"{Environment.NewLine}" +
                            $"           Meta-data points: {algorithm.Metadata.Count}{Environment.NewLine}" +
                            $"          Time-span covered: {timeRange:N0} seconds: {Ticks.FromSeconds(timeRange).ToElapsedTimeString(2)}{Environment.NewLine}" +
                            $"       Processed timestamps: {processedDataBlocks:N0}{Environment.NewLine}" +
                            $"            Expected points: {expectedPoints:N0} @ {m_settings.FrameRate:N0} samples per second{Environment.NewLine}" +
                            $"            Received points: {receivedPoints:N0}{Environment.NewLine}" +
                            $"           Duplicate points: {duplicatePoints:N0}{Environment.NewLine}" +
                            $"          Data completeness: {dataCompleteness:N3}%{Environment.NewLine}" +
                            $"  First timestamp with data: {firstTimestamp:yyyy-MM-dd HH:mm:ss.fff}{Environment.NewLine}" +
                            $"   Last timestamp with data: {lastTimestamp:yyyy-MM-dd HH:mm:ss.fff}{Environment.NewLine}";

                        ShowUpdateMessage(overallSummary);
                    }
                }
            }
            catch (Exception ex)
            {
                ShowUpdateMessage($"!!! Failure during historian read: {ex.Message}");
                m_log.Publish(MessageLevel.Error, "HistorianDataRead", "Failed while reading data from the historian", exception: ex);
            }
            finally
            {
                SetGoButtonEnabledState(true);
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Gets a short one-line status of this <see cref="AdapterBase"/>.
        /// </summary>
        /// <param name="maxLength">Maximum number of available characters for display.</param>
        /// <returns>A short one-line summary of the current status of this <see cref="AdapterBase"/>.</returns>
        public override string GetShortStatus(int maxLength)
        {
            TimeSpan time = Ticks.FromSeconds(m_dataIndex / (double)m_sampleRate);

            return(string.Format("Streaming {0} at time {1} / {2} - {3:0.00%}.", Path.GetFileName(WavFileName), time.ToString(@"m\:ss"), m_audioLength.ToString(@"m\:ss"), time.TotalSeconds / m_audioLength.TotalSeconds));
        }
Esempio n. 17
0
        // Handle binary file read
        private bool ReadNextBinary()
        {
            FileStream currentFile  = m_fileStreams[m_streamIndex];
            int        recordLength = m_schema.BinaryRecordLength;

            byte[] buffer = new byte[recordLength];

            // Read next record from file
            int bytesRead = currentFile.Read(buffer, 0, recordLength);

            // See if we have reached the end of this file
            if (bytesRead == 0)
            {
                m_streamIndex++;

                // There is more to read if there is another file
                return(m_streamIndex < m_fileStreams.Length && ReadNext());
            }

            if (bytesRead == recordLength)
            {
                int index = 0;

                // Read sample index
                uint sample = LittleEndian.ToUInt32(buffer, index);
                index += 4;

                // Get timestamp of this record
                m_timestamp = DateTime.MinValue;

                // If sample rates are defined, this is the preferred method for timestamp resolution
                if (m_inferTimeFromSampleRates && m_schema.SampleRates.Length > 0)
                {
                    // Find rate for given sample
                    SampleRate sampleRate = m_schema.SampleRates.LastOrDefault(sr => sample <= sr.EndSample);

                    if (sampleRate.Rate > 0.0D)
                    {
                        m_timestamp = new DateTime(Ticks.FromSeconds(1.0D / sampleRate.Rate * sample) + m_schema.StartTime.Value);
                    }
                }

                // Read microsecond timestamp
                uint microseconds = LittleEndian.ToUInt32(buffer, index);
                index += 4;

                // Fall back on specified microsecond time
                if (m_timestamp == DateTime.MinValue)
                {
                    m_timestamp = new DateTime(Ticks.FromMicroseconds(microseconds * m_schema.TimeFactor) + m_schema.StartTime.Value);
                }

                // Parse all analog record values
                for (int i = 0; i < m_schema.AnalogChannels.Length; i++)
                {
                    // Read next value
                    m_values[i] = LittleEndian.ToInt16(buffer, index) * m_schema.AnalogChannels[i].Multiplier + m_schema.AnalogChannels[i].Adder;
                    index      += 2;
                }

                int    valueIndex   = m_schema.AnalogChannels.Length;
                int    digitalWords = m_schema.DigitalWords;
                ushort digitalWord;

                for (int i = 0; i < digitalWords; i++)
                {
                    // Read next digital word
                    digitalWord = LittleEndian.ToUInt16(buffer, index);
                    index      += 2;

                    // Distribute each bit of digital word through next 16 digital values
                    for (int j = 0; j < 16 && valueIndex < m_values.Length; j++, valueIndex++)
                    {
                        m_values[valueIndex] = digitalWord.CheckBits(BitExtensions.BitVal(j)) ? 1.0D : 0.0D;
                    }
                }
            }
            else
            {
                throw new InvalidOperationException("Failed to read enough bytes from COMTRADE file for a record as defined by schema - possible schema/data file mismatch or file corruption.");
            }

            return(true);
        }
Esempio n. 18
0
        // Handle ASCII file read
        private bool ReadNextAscii()
        {
            if ((object)m_fileReaders == null)
            {
                m_fileReaders = new StreamReader[m_fileStreams.Length];

                for (int i = 0; i < m_fileStreams.Length; i++)
                {
                    m_fileReaders[i] = new StreamReader(m_fileStreams[i]);
                }
            }

            // Read next line of record values
            StreamReader reader = m_fileReaders[m_streamIndex];
            string       line   = reader.ReadLine();

            string[] elems = ((object)line != null) ? line.Split(',') : null;

            // See if we have reached the end of this file
            if ((object)elems == null || elems.Length != m_values.Length + 2)
            {
                if (reader.EndOfStream)
                {
                    m_streamIndex++;

                    // There is more to read if there is another file
                    return(m_streamIndex < m_fileStreams.Length && ReadNext());
                }

                throw new InvalidOperationException("COMTRADE schema does not match number of elements found in ASCII data file.");
            }

            // Parse row of data
            uint sample = uint.Parse(elems[0]);

            // Get timestamp of this record
            m_timestamp = DateTime.MinValue;

            // If sample rates are defined, this is the preferred method for timestamp resolution
            if (m_inferTimeFromSampleRates && m_schema.SampleRates.Length > 0)
            {
                // Find rate for given sample
                SampleRate sampleRate = m_schema.SampleRates.LastOrDefault(sr => sample <= sr.EndSample);

                if (sampleRate.Rate > 0.0D)
                {
                    m_timestamp = new DateTime(Ticks.FromSeconds(1.0D / sampleRate.Rate * sample) + m_schema.StartTime.Value);
                }
            }

            // Fall back on specified microsecond time
            if (m_timestamp == DateTime.MinValue)
            {
                m_timestamp = new DateTime(Ticks.FromMicroseconds(uint.Parse(elems[1]) * m_schema.TimeFactor) + m_schema.StartTime.Value);
            }

            // Parse all record values
            for (int i = 0; i < m_values.Length; i++)
            {
                m_values[i] = double.Parse(elems[i + 2]);

                if (i < m_schema.AnalogChannels.Length)
                {
                    m_values[i] *= m_schema.AnalogChannels[i].Multiplier;
                    m_values[i] += m_schema.AnalogChannels[i].Adder;
                }
            }

            return(true);
        }
Esempio n. 19
0
        public void Ages()
        {
            UT_INIT();

            Log.SetVerbosity(new ConsoleLogger(), Verbosity.Verbose, "/");
            Log.MapThreadName("UnitTest");
            Log.SetDomain("TickWatch", Scope.Method);

            TickWatch tt = new TickWatch();
            // minimum time measuring
            {
                tt.Start();
                tt.Sample();
                tt.Reset(); // we need to do this once before, otherwise C# might be
                // very slow. Obviously the optimizer...
                tt.Start();
                tt.Sample();

                long ttAverageInNanos  = tt.GetAverage().InNanos();
                long ttAverageInMicros = tt.GetAverage().InMicros();
                long ttAverageInMillis = tt.GetAverage().InMillis();

                Log.Info("TickWatch minimum measurement nanos:    " + ttAverageInNanos);
                Log.Info("TickWatch minimum measurement micros:   " + ttAverageInMicros);
                Log.Info("TickWatch minimum measurement millis:   " + ttAverageInMillis);
                UT_TRUE(ttAverageInNanos < 5000);
                UT_TRUE(ttAverageInMicros <= 5);
                UT_TRUE(ttAverageInMillis == 0);
            }

            // minimum sleep time measuring
            {
                tt.Reset();
                for (int i = 0; i < 100; i++)
                {
                    ALIB.SleepNanos(1);
                    tt.Sample();
                }
                Ticks avg = tt.GetAverage();
                Log.Info("100 probes of 1 ns of sleep leads to average sleep time of " + avg.InNanos() + " ns");
            }


            // sleep two times 20 ms and probe it to an average
            {
                tt.Reset();
                tt.Start();
                ALIB.SleepMillis(20);
                tt.Sample();


                ALIB.SleepMillis(80);

                tt.Start();
                ALIB.SleepMillis(20);
                tt.Sample();

                long   cnt   = tt.GetSampleCnt();
                long   avg   = tt.GetAverage().InMillis();
                double hertz = tt.GetAverage().InHertz(1);
                Log.Info("TickWatch sum is " + tt.GetCumulated().InMillis() + " after " + cnt + " times 20 ms sleep");
                Log.Info("  average is: " + avg + " ms");
                Log.Info("  in Hertz:   " + hertz);
                UT_TRUE(hertz < 53);
                UT_TRUE(hertz > 30);   // should work even on heavily loaded machines
                UT_EQ(2, cnt);
                UT_TRUE(avg >= 18);
                UT_TRUE(avg < 45);   // should work even on heavily loaded machines
            }

            // Ticks Since
            {
                Ticks tt1 = new Ticks(); tt1.FromSeconds(1000);
                Ticks tt2 = new Ticks(); tt2.FromSeconds(1001);

                UT_TRUE(tt2.Since(tt1).InMillis() == 1000L);
                UT_TRUE(tt2.Since(tt1).InMicros() == 1000L * 1000L);
                UT_TRUE(tt2.Since(tt1).InNanos() == 1000L * 1000L * 1000L);
            }
        }
Esempio n. 20
0
        private void ProcessMeasurements()
        {
            List <IMeasurement> measurements = new List <IMeasurement>((int)(Ticks.ToSeconds(GapThreshold) * m_sampleRate * m_channels * 1.1D));

            LittleBinaryValue[] sample;

            while (Enabled)
            {
                try
                {
                    SpinWait spinner = new SpinWait();

                    // Determine what time it is now
                    long now = DateTime.UtcNow.Ticks;

                    // Assign a timestamp to the next sample based on its location
                    // in the file relative to the other samples in the file
                    long timestamp = m_startTime + (m_dataIndex * Ticks.PerSecond / m_sampleRate);

                    if (now - timestamp > GapThreshold)
                    {
                        // Reset the start time and delay next transmission in an attempt to catch up
                        m_startTime = now - (m_dataIndex * Ticks.PerSecond / m_sampleRate) + Ticks.FromSeconds(RecoveryDelay);
                        timestamp   = now;
                        OnStatusMessage(MessageLevel.Info, "Start time reset.");
                    }

                    // Keep generating measurements until
                    // we catch up to the current time.
                    while (timestamp < now)
                    {
                        sample = m_dataReader.GetNextSample();

                        // If the sample is null, we've reached the end of the file - close and reopen,
                        // resetting the data index and start time
                        if (sample == null)
                        {
                            m_dataReader.Close();
                            m_dataReader.Dispose();

                            m_dataReader = OpenWaveDataReader();
                            m_dataIndex  = 0;

                            m_startTime = timestamp;
                            sample      = m_dataReader.GetNextSample();
                        }

                        // Create new measurements, one for each channel, and add them to the measurements list
                        for (int i = 0; i < m_channels; i++)
                        {
                            measurements.Add(Measurement.Clone(OutputMeasurements[i], sample[i].ConvertToType(TypeCode.Double), timestamp));
                        }

                        // Update the data index and recalculate the assigned timestamp for the next sample
                        m_dataIndex++;
                        timestamp = m_startTime + (m_dataIndex * Ticks.PerSecond / m_sampleRate);
                    }

                    OnNewMeasurements(measurements);
                    measurements.Clear();

                    while (DateTime.UtcNow.Ticks - timestamp <= GapThreshold / 100)
                    {
                        // Ahead of schedule -- pause for a moment
                        spinner.SpinOnce();
                    }
                }
                catch (Exception ex)
                {
                    OnProcessException(MessageLevel.Warning, ex);
                }
            }
        }
Esempio n. 21
0
        /// <summary>
        /// Queues a collection of measurements for processing.
        /// </summary>
        /// <param name="measurements">Collection of measurements to queue for processing.</param>
        /// <remarks>
        /// Measurements are filtered against the defined <see cref="InputMeasurementKeys"/> so we override method
        /// so that dynamic updates to keys will be synchronized with filtering to prevent interference.
        /// </remarks>
        public override void QueueMeasurementsForProcessing(IEnumerable <IMeasurement> measurements)
        {
            if ((object)measurements == null)
            {
                return;
            }

            if (!m_startTimeSent && measurements.Any())
            {
                m_startTimeSent = true;

                IMeasurement measurement = measurements.FirstOrDefault(m => (object)m != null);
                Ticks        timestamp   = 0;

                if ((object)measurement != null)
                {
                    timestamp = measurement.Timestamp;
                }

                m_parent.SendDataStartTime(m_clientID, timestamp);
            }

            if (m_isNaNFiltered)
            {
                measurements = measurements.Where(measurement => !double.IsNaN(measurement.Value));
            }

            if (!measurements.Any() || !Enabled)
            {
                return;
            }

            if (TrackLatestMeasurements)
            {
                double publishInterval;

                // Keep track of latest measurements
                base.QueueMeasurementsForProcessing(measurements);
                publishInterval = (m_publishInterval > 0) ? m_publishInterval : LagTime;

                if (DateTime.UtcNow.Ticks > m_lastPublishTime + Ticks.FromSeconds(publishInterval))
                {
                    List <IMeasurement> currentMeasurements = new List <IMeasurement>();
                    Measurement         newMeasurement;

                    // Create a new set of measurements that represent the latest known values setting value to NaN if it is old
                    foreach (TemporalMeasurement measurement in LatestMeasurements)
                    {
                        newMeasurement = new Measurement
                        {
                            Key        = measurement.Key,
                            Value      = measurement.GetValue(RealTime),
                            Adder      = measurement.Adder,
                            Multiplier = measurement.Multiplier,
                            Timestamp  = measurement.Timestamp,
                            StateFlags = measurement.StateFlags
                        };

                        currentMeasurements.Add(newMeasurement);
                    }

                    // Order measurements by signal type for better compression when enabled
                    if (m_usePayloadCompression)
                    {
                        ProcessMeasurements(currentMeasurements.OrderBy(measurement => measurement.GetSignalType(DataSource)));
                    }
                    else
                    {
                        ProcessMeasurements(currentMeasurements);
                    }
                }
            }
            else
            {
                // Order measurements by signal type for better compression when enabled
                if (m_usePayloadCompression)
                {
                    ProcessMeasurements(measurements.OrderBy(measurement => measurement.GetSignalType(DataSource)));
                }
                else
                {
                    ProcessMeasurements(measurements);
                }
            }
        }
Esempio n. 22
0
        /// <summary>
        /// Creates a new <see cref="CommonFrameHeader"/> from given <paramref name="buffer"/>.
        /// </summary>
        /// <param name="parseWordCountFromByte">Defines flag that interprets word count in packet header from a byte instead of a word.</param>
        /// <param name="usePhasorDataFileFormat">Defines flag that determines if source data is in the Phasor Data File Format (i.e., a DST file).</param>
        /// <param name="configFrame">Previously parsed configuration frame, if available.</param>
        /// <param name="buffer">Buffer that contains data to parse.</param>
        /// <param name="startIndex">Start index into buffer where valid data begins.</param>
        /// <param name="length">Maximum length of valid data from start index.</param>
        public CommonFrameHeader(bool parseWordCountFromByte, bool usePhasorDataFileFormat, ConfigurationFrame configFrame, byte[] buffer, int startIndex, int length)
        {
            uint secondOfCentury;

            // Determines if format is for DST file or streaming data
            m_usePhasorDataFileFormat = usePhasorDataFileFormat;

            if (m_usePhasorDataFileFormat)
            {
                // Handle phasor file format data protocol steps
                if (buffer[startIndex] == PhasorProtocols.Common.SyncByte && buffer[startIndex + 1] == Common.PhasorFileFormatFlag)
                {
                    // Bail out and leave frame length zero if there's not enough buffer to parse complete fixed portion of header
                    if (length >= DstHeaderFixedLength)
                    {
                        // Read full DST header
                        m_packetNumber = (byte)BPAPDCstream.FrameType.ConfigurationFrame;
                        m_fileType     = (FileType)buffer[startIndex + 2];
                        m_fileVersion  = (FileVersion)buffer[startIndex + 3];
                        m_sourceID     = Encoding.ASCII.GetString(buffer, startIndex + 4, 4);
                        uint headerLength = BigEndian.ToUInt32(buffer, startIndex + 8);
                        secondOfCentury = BigEndian.ToUInt32(buffer, startIndex + 12);

                        switch (m_fileType)
                        {
                        case FileType.PdcNtp:
                            RoughTimestamp = new NtpTimeTag(secondOfCentury, 0).ToDateTime().Ticks;
                            break;

                        case FileType.PdcUnix:
                            RoughTimestamp = new UnixTimeTag(secondOfCentury).ToDateTime().Ticks;
                            break;

                        default:
                            RoughTimestamp = 0;
                            break;
                        }

                        m_startSample    = BigEndian.ToUInt32(buffer, startIndex + 16);
                        m_sampleInterval = BigEndian.ToUInt16(buffer, startIndex + 20);
                        m_sampleRate     = BigEndian.ToUInt16(buffer, startIndex + 22);
                        m_rowLength      = BigEndian.ToUInt32(buffer, startIndex + 24);
                        m_totalRows      = BigEndian.ToUInt32(buffer, startIndex + 28);
                        secondOfCentury  = BigEndian.ToUInt32(buffer, startIndex + 32);

                        switch (m_fileType)
                        {
                        case FileType.PdcNtp:
                            m_triggerTime = new NtpTimeTag(secondOfCentury, 0).ToDateTime().Ticks;
                            break;

                        case FileType.PdcUnix:
                            m_triggerTime = new UnixTimeTag(secondOfCentury).ToDateTime().Ticks;
                            break;

                        default:
                            m_triggerTime = 0;
                            break;
                        }

                        m_triggerSample   = BigEndian.ToUInt32(buffer, startIndex + 36);
                        m_preTriggerRows  = BigEndian.ToUInt32(buffer, startIndex + 40);
                        m_triggerPMU      = BigEndian.ToUInt16(buffer, startIndex + 44);
                        m_triggerType     = BigEndian.ToUInt16(buffer, startIndex + 46);
                        m_userInformation = Encoding.ASCII.GetString(buffer, startIndex + 48, 80).Trim();
                        m_pmuCount        = BigEndian.ToUInt32(buffer, startIndex + 128);
                        FrameLength       = unchecked ((ushort)headerLength);
                    }
                }
                else
                {
                    // Must assume this is a data row if there are no sync bytes
                    m_packetNumber = (byte)BPAPDCstream.FrameType.DataFrame;
                    m_rowFlags     = BigEndian.ToUInt32(buffer, startIndex);

                    if (configFrame is null)
                    {
                        FrameLength = FixedLength;
                    }
                    else
                    {
                        uint sampleIndex = configFrame.SampleIndex;
                        CommonFrameHeader configFrameHeader = configFrame.CommonHeader;

                        if (configFrameHeader is null)
                        {
                            FrameLength = FixedLength;
                        }
                        else
                        {
                            // Assign row length to make sure parser knows how much data it needs
                            FrameLength = unchecked ((ushort)configFrameHeader.RowLength);

                            // Calculate timestamp as offset plus sample index * frame rate
                            RoughTimestamp = configFrameHeader.RoughTimestamp + Ticks.FromSeconds(sampleIndex * (1.0D / configFrameHeader.FrameRate));
                        }

                        // Increment sample index for next row
                        configFrame.SampleIndex = sampleIndex + 1;
                    }
                }
            }
            else
            {
                // Handle streaming data protocol steps
                if (buffer[startIndex] != PhasorProtocols.Common.SyncByte)
                {
                    throw new InvalidOperationException($"Bad data stream, expected sync byte 0xAA as first byte in BPA PDCstream frame, got 0x{buffer[startIndex].ToString("X").PadLeft(2, '0')}");
                }

                // Get packet number
                m_packetNumber = buffer[startIndex + 1];

                // Some older streams have a bad word count (e.g., some data streams have a 0x01 as the third byte
                // in the stream - this should be a 0x00 to make the word count come out correctly).  The following
                // compensates for this erratic behavior
                m_wordCount = parseWordCountFromByte ? buffer[startIndex + 3] : BigEndian.ToUInt16(buffer, startIndex + 2);

                // If this is a data frame get a rough timestamp down to the second (full parse will get accurate timestamp), this way
                // data frames that don't get fully parsed because configuration hasn't been received will still show a timestamp
                if (m_packetNumber > 0 && length > 8)
                {
                    secondOfCentury = BigEndian.ToUInt32(buffer, startIndex + 4);

                    // Until configuration is available, we make a guess at time tag type - this will just be
                    // used for display purposes until a configuration frame arrives.  If second of century
                    // is greater than 3155673600 (SOC value for NTP timestamp 1/1/2007), then this is likely
                    // an NTP time stamp (else this is a Unix time tag for the year 2069 - not likely).
                    RoughTimestamp = secondOfCentury > 3155673600 ?
                                     new NtpTimeTag(secondOfCentury, 0).ToDateTime().Ticks :
                                     new UnixTimeTag(secondOfCentury).ToDateTime().Ticks;
                }
            }
        }
Esempio n. 23
0
        // Handle ASCII file read
        private bool ReadNextAscii()
        {
            // For ASCII files, we wrap file streams with file readers
            if ((object)m_fileReaders == null)
            {
                m_fileReaders = new StreamReader[m_fileStreams.Length];

                for (int i = 0; i < m_fileStreams.Length; i++)
                {
                    m_fileReaders[i] = new StreamReader(m_fileStreams[i]);
                }
            }

            // Read next line of record values
            StreamReader reader = m_fileReaders[m_streamIndex];
            string       line   = reader.ReadLine();

            string[] elems = ((object)line != null) ? line.Split(',') : null;

            // See if we have reached the end of this file
            if ((object)elems == null || elems.Length != Values.Length + 2)
            {
                if (reader.EndOfStream)
                {
                    return(ReadNextFile());
                }

                throw new InvalidOperationException("COMTRADE schema does not match number of elements found in ASCII data file.");
            }

            // Parse row of data
            uint sample = uint.Parse(elems[0]);

            // Get timestamp of this record
            Timestamp = DateTime.MinValue;

            // If sample rates are defined, this is the preferred method for timestamp resolution
            if (InferTimeFromSampleRates && m_schema.SampleRates.Length > 0)
            {
                // Find rate for given sample
                SampleRate sampleRate = m_schema.SampleRates.LastOrDefault(sr => sample <= sr.EndSample);

                if (sampleRate.Rate > 0.0D)
                {
                    Timestamp = new DateTime(Ticks.FromSeconds(1.0D / sampleRate.Rate * sample) + m_schema.StartTime.Value);
                }
            }

            // Fall back on specified microsecond time
            if (Timestamp == DateTime.MinValue)
            {
                Timestamp = new DateTime(Ticks.FromMicroseconds(uint.Parse(elems[1]) * m_schema.TimeFactor) + m_schema.StartTime.Value);
            }

            // Apply timestamp offset to restore UTC timezone
            if (AdjustToUTC)
            {
                TimeOffset offset = Schema.TimeCode ?? new TimeOffset();
                Timestamp = new DateTime(Timestamp.Ticks + offset.TickOffset, DateTimeKind.Utc);
            }

            // Parse all record values
            for (int i = 0; i < Values.Length; i++)
            {
                Values[i] = double.Parse(elems[i + 2]);

                if (i < m_schema.AnalogChannels.Length)
                {
                    Values[i] = AdjustValue(Values[i], i);
                }
            }

            return(true);
        }
Esempio n. 24
0
        /// <summary>
        /// Queues a collection of measurements for processing.
        /// </summary>
        /// <param name="measurements">Collection of measurements to queue for processing.</param>
        /// <remarks>
        /// Measurements are filtered against the defined <see cref="InputMeasurementKeys"/> so we override method
        /// so that dyanmic updates to keys will be synchronized with filtering to prevent interference.
        /// </remarks>
        public override void QueueMeasurementsForProcessing(IEnumerable <IMeasurement> measurements)
        {
            if (!m_startTimeSent && (object)measurements != null && measurements.Any())
            {
                m_startTimeSent = true;

                IMeasurement measurement = measurements.FirstOrDefault(m => m != null);
                Ticks        timestamp   = 0;

                if (measurement != null)
                {
                    timestamp = measurement.Timestamp;
                }

                m_parent.SendDataStartTime(m_clientID, timestamp);
            }

            if (ProcessMeasurementFilter)
            {
                List <IMeasurement> filteredMeasurements = new List <IMeasurement>();

                lock (this)
                {
                    foreach (IMeasurement measurement in measurements)
                    {
                        if (IsInputMeasurement(measurement.Key))
                        {
                            filteredMeasurements.Add(measurement);
                        }
                    }
                }

                measurements = filteredMeasurements;
            }

            if (measurements.Any() && Enabled)
            {
                if (TrackLatestMeasurements)
                {
                    double publishInterval;

                    // Keep track of latest measurements
                    base.QueueMeasurementsForProcessing(measurements);
                    publishInterval = (m_publishInterval > 0) ? m_publishInterval : LagTime;

                    if (DateTime.UtcNow.Ticks > m_lastPublishTime + Ticks.FromSeconds(publishInterval))
                    {
                        List <IMeasurement> currentMeasurements = new List <IMeasurement>();
                        Measurement         newMeasurement;

                        // Create a new set of measurements that represent the latest known values setting value to NaN if it is old
                        foreach (TemporalMeasurement measurement in LatestMeasurements)
                        {
                            newMeasurement = new Measurement()
                            {
                                ID         = measurement.ID,
                                Key        = measurement.Key,
                                Value      = measurement.GetValue(RealTime),
                                Adder      = measurement.Adder,
                                Multiplier = measurement.Multiplier,
                                Timestamp  = measurement.Timestamp,
                                StateFlags = measurement.StateFlags
                            };

                            currentMeasurements.Add(newMeasurement);
                        }

                        // Publish latest data values...
                        if ((object)m_processQueue != null)
                        {
                            m_processQueue.Enqueue(currentMeasurements);
                        }
                    }
                }
                else
                {
                    // Publish unsynchronized on data receipt otherwise...
                    m_processQueue.Enqueue(measurements);
                }
            }
        }
Esempio n. 25
0
        public void Basics()
        {
            UT_INIT();

            Log.SetVerbosity(new ConsoleLogger(), Verbosity.Verbose, "/");
            Log.MapThreadName("UnitTest");
            Log.SetDomain("TickWatch", Scope.Method);

            Log.Info("\n### TicksBasics ###");

            // check times
            {
                Ticks t = new Ticks();
                t.FromNanos(42);      // beyond resolution in C#:  UT_EQ( t.InNanos(),        42L);
                UT_EQ(t.InMicros(), 0L);
                UT_EQ(t.InMillis(), 0L);
                UT_EQ(t.InSeconds(), 0L);
                t.FromMicros(42);    UT_EQ(t.InNanos(), 42000L);
                UT_EQ(t.InMicros(), 42L);
                UT_EQ(t.InMillis(), 0L);
                UT_EQ(t.InSeconds(), 0L);
                t.FromMillis(42);    UT_EQ(t.InNanos(), 42000000L);
                UT_EQ(t.InMicros(), 42000L);
                UT_EQ(t.InMillis(), 42L);
                UT_EQ(t.InSeconds(), 0L);
                t.FromSeconds(42);    UT_EQ(t.InNanos(), 42000000000L);
                UT_EQ(t.InMicros(), 42000000L);
                UT_EQ(t.InMillis(), 42000L);
                UT_EQ(t.InSeconds(), 42L);
                Ticks diff = new Ticks();
                diff.FromMillis(100);
                t.Add(diff);            UT_EQ(t.InNanos(), 42100000000L);
                UT_EQ(t.InMicros(), 42100000L);
                UT_EQ(t.InMillis(), 42100L);
                UT_EQ(t.InSeconds(), 42L);
                t.Sub(diff);            UT_EQ(t.InNanos(), 42000000000L);
                UT_EQ(t.InMicros(), 42000000L);
                UT_EQ(t.InMillis(), 42000L);
                UT_EQ(t.InSeconds(), 42L);

                t.FromMillis(100); UT_EQ(t.InHertz(), 10.0);
                t.FromMillis(300); UT_EQ(t.InHertz(0), 3.0);
                UT_EQ(t.InHertz(1), 3.3);
                UT_EQ(t.InHertz(2), 3.33);
                UT_EQ(t.InHertz(5), 3.33333);
            }

            // check internal frequency
            {
                double freq = Ticks.InternalFrequency;
                Log.Info("TickWatch InternalFrequency:   " + freq);
                UT_TRUE(freq >= 1000000.0);
            }

            // check TickWatch creation time
            {
                Ticks creationTimeDiff = new Ticks();
                creationTimeDiff.Sub(Ticks.CreationTime);
                Log.Info("TickWatch library creation was: " + creationTimeDiff.InNanos() + "ns ago");
                Log.Info("TickWatch library creation was: " + creationTimeDiff.InMicros() + "µs ago");
                Log.Info("TickWatch library creation was: " + creationTimeDiff.InMillis() + "ms ago");
                Log.Info("TickWatch library creation was: " + creationTimeDiff.InSeconds() + "s ago");
                UT_TRUE(creationTimeDiff.InNanos() > 100);       // It should really take 100 nanoseconds to get here!
                UT_TRUE(creationTimeDiff.InSeconds() < 3600);    // these test will probably not last an hour
            }

            // check if we could sleep for 100ms
            {
                Ticks start = new Ticks();
                ALIB.SleepMillis(30);
                Ticks sleepTime = new Ticks();
                sleepTime.Sub(start);
                Log.Info("TickWatch diff after 100ms sleep: " + sleepTime.InMillis() + " ms");
                UT_TRUE(sleepTime.InMillis() > 28);
                UT_TRUE(sleepTime.InMillis() < 150);    // should work even on heavily loaded machines
            }
        }
Esempio n. 26
0
        // Per partition consumer read handler
        private void ProcessPartitionMessages(object state)
        {
            int partition = (int)state;

            try
            {
                Dictionary <uint, MeasurementKey> idTable         = new Dictionary <uint, MeasurementKey>();
                ConsumerOptions           options                 = new ConsumerOptions(Topic, m_router);
                LongSynchronizedOperation cacheLastConsumerOffset = null;
                OffsetPosition            consumerCursor          = new OffsetPosition {
                    PartitionId = partition, Offset = 0
                };
                long lastUpdateTime          = 0;
                long lastMetadataUpdateCount = 0;
                long lastMeasurementTime     = 0;

                options.PartitionWhitelist.Add(partition);
                options.Log = new TimeSeriesLogger((message, parameters) => OnStatusMessage($"P[{partition}]: " + message, parameters), OnProcessException);

                // Handle consumer offset tracking, i.e., adapter will start reading messages where it left off from last run
                if (TrackConsumerOffset)
                {
                    // Parse path/filename.ext into constituent parts
                    string[] fileParts = new string[3];

                    fileParts[0] = FilePath.GetDirectoryName(ConsumerOffsetFileName);               // 0: path/
                    fileParts[1] = FilePath.GetFileNameWithoutExtension(ConsumerOffsetFileName);    // 1: filename
                    fileParts[2] = FilePath.GetExtension(ConsumerOffsetFileName);                   // 2: .ext

                    // Include partition index as part of consumer offset cache file name
                    string fileName = $"{fileParts[0]}{fileParts[1]}-P{partition}{fileParts[2]}";

                    if (File.Exists(fileName))
                    {
                        try
                        {
                            // Read last consumer offset
                            consumerCursor.Offset = long.Parse(File.ReadAllText(fileName));
                        }
                        catch (Exception ex)
                        {
                            OnProcessException(new InvalidOperationException($"Failed to read last consumer offset from \"{fileName}\": {ex.Message}", ex));
                        }
                    }

                    cacheLastConsumerOffset = new LongSynchronizedOperation(() =>
                    {
                        // Do not write file any more often than defined consumer offset cache interval
                        int restTime = (int)(Ticks.FromSeconds(ConsumerOffsetCacheInterval) - (DateTime.UtcNow.Ticks - lastUpdateTime)).ToMilliseconds();

                        if (restTime > 0)
                        {
                            Thread.Sleep(restTime);
                        }

                        lastUpdateTime = DateTime.UtcNow.Ticks;

                        // Write current consumer offset
                        File.WriteAllText(fileName, consumerCursor.Offset.ToString());
                    },
                                                                            ex => OnProcessException(new InvalidOperationException($"Failed to cache current consumer offset to \"{fileName}\": {ex.Message}", ex)))
                    {
                        IsBackground = true
                    };
                }

                using (Consumer consumer = new Consumer(options, new OffsetPosition(partition, consumerCursor.Offset)))
                {
                    lock (m_consumers)
                        m_consumers.Add(new WeakReference <Consumer>(consumer));

                    foreach (Message message in consumer.Consume())
                    {
                        if ((object)m_metadata == null)
                        {
                            continue;
                        }

                        uint         id;
                        byte         metadataVersion;
                        IMeasurement measurement = message.KafkaDeserialize(out id, out metadataVersion);

                        // Kick-off a refresh for new metadata if message version numbers change
                        if (m_lastMetadataVersion != metadataVersion)
                        {
                            m_lastMetadataVersion = metadataVersion;
                            m_updateMetadata.RunOnceAsync();
                        }

                        // Clear all undefined items in dictionary when metadata gets updated
                        if (lastMetadataUpdateCount < m_metadataUpdateCount)
                        {
                            lastMetadataUpdateCount = m_metadataUpdateCount;
                            foreach (uint undefinedID in idTable.Where(item => item.Value.SignalID == Guid.Empty).Select(item => item.Key).ToArray())
                            {
                                idTable.Remove(undefinedID);
                            }
                        }

                        // Get associated measurement key, or look it up in metadata table
                        measurement.Key = idTable.GetOrAdd(id, lookupID => MeasurementKey.LookUpBySignalID(m_metadata?.Records?.FirstOrDefault(record => record.ID == lookupID)?.ParseSignalID() ?? Guid.Empty));

                        // Only publish measurements with associated metadata and are assigned to this adapter
                        if (measurement.Key != MeasurementKey.Undefined && ((object)m_outputMeasurementKeys == null || m_outputMeasurementKeys.Contains(measurement.Key)))
                        {
                            OnNewMeasurements(new[] { measurement });
                        }

                        // Cache last consumer offset
                        consumerCursor.Offset = message.Offset;

                        if ((object)cacheLastConsumerOffset != null)
                        {
                            cacheLastConsumerOffset.RunOnceAsync();
                        }

                        if (ReadDelay > -1)
                        {
                            // As a group of measurements transition from timestamp to another, inject configured read delay
                            if (lastMeasurementTime != measurement.Timestamp)
                            {
                                Thread.Sleep(ReadDelay);
                            }

                            lastMeasurementTime = measurement.Timestamp;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                OnProcessException(new InvalidOperationException($"Exception while reading Kafka messages for topic \"{Topic}\" P[{partition}]: {ex.Message}", ex));
            }
        }
Esempio n. 27
0
        public static void Main(string[] args)
        {
            m_definedMeasurements = new ConcurrentDictionary <string, MeasurementMetadata>();
            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";
            parser.ConnectionString = @"phasorProtocol=IEEEC37_118V1; transportProtocol=Serial; port=COM6; baudRate=115200; dataBits=8; stopBits=One; parity=None; dtrEnable=false; rtsEnable=false; autoStartDataParsingSequence=false; disableRealTimeDataOnStop=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();
            }

            if (settings.TryGetValue("disableRealTimeDataOnStop", out setting))
            {
                parser.DisableRealTimeDataOnStop = setting.ParseBoolean();
            }

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

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

            parser.Start();

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

            parser.Stop();

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

            if (WriteLogs)
            {
                m_exportFile.Close();
            }
        }
        /// <summary>
        /// Queues a collection of measurements for processing.
        /// </summary>
        /// <param name="measurements">Collection of measurements to queue for processing.</param>
        /// <remarks>
        /// Measurements are filtered against the defined <see cref="InputMeasurementKeys"/> so we override method
        /// so that dynamic updates to keys will be synchronized with filtering to prevent interference.
        /// </remarks>
        // IMPORTANT: TSSC is sensitive to order - always make sure this function gets called sequentially, concurrent
        // calls to this function can cause TSSC parsing to get out of sequence and fail
        public override void QueueMeasurementsForProcessing(IEnumerable <IMeasurement> measurements)
        {
            if ((object)measurements == null)
            {
                return;
            }

            if (!m_startTimeSent && measurements.Any())
            {
                m_startTimeSent = true;

                IMeasurement measurement = measurements.FirstOrDefault(m => (object)m != null);
                Ticks        timestamp   = 0;

                if ((object)measurement != null)
                {
                    timestamp = measurement.Timestamp;
                }

                m_parent.SendDataStartTime(m_clientID, timestamp);
            }

            if (m_isNaNFiltered)
            {
                measurements = measurements.Where(measurement => !double.IsNaN(measurement.Value));
            }

            if (!measurements.Any() || !Enabled)
            {
                return;
            }

            if (TrackLatestMeasurements)
            {
                double publishInterval;

                // Keep track of latest measurements
                base.QueueMeasurementsForProcessing(measurements);
                publishInterval = m_publishInterval > 0 ? m_publishInterval : LagTime;

                if (DateTime.UtcNow.Ticks > m_lastPublishTime + Ticks.FromSeconds(publishInterval))
                {
                    List <IMeasurement> currentMeasurements = new List <IMeasurement>();
                    Measurement         newMeasurement;

                    // Create a new set of measurements that represent the latest known values setting value to NaN if it is old
                    foreach (TemporalMeasurement measurement in LatestMeasurements)
                    {
                        MeasurementStateFlags timeQuality = measurement.Timestamp.TimeIsValid(RealTime, measurement.LagTime, measurement.LeadTime)
                            ? MeasurementStateFlags.Normal
                            : MeasurementStateFlags.BadTime;

                        newMeasurement = new Measurement
                        {
                            Metadata   = measurement.Metadata,
                            Value      = measurement.Value,
                            Timestamp  = measurement.Timestamp,
                            StateFlags = measurement.StateFlags | timeQuality
                        };

                        currentMeasurements.Add(newMeasurement);
                    }

                    ProcessMeasurements(currentMeasurements);
                }
            }
            else
            {
                ProcessMeasurements(measurements);
            }
        }
Esempio n. 29
0
 private void DataInserter_BulkInsertCompleted(object sender, EventArgs <string, int, int> e) //string TableName, int TotalRows, int TotalSeconds
 {
     AddMessage("Bulk insert of " + e.Argument2 + " rows into table " + e.Argument1 + " completed in " + Ticks.FromSeconds(e.Argument3).ToElapsedTimeString(2).ToLower());
 }
Esempio n. 30
0
        /// <summary>
        /// Initializes <see cref="TimestampTest"/>.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            string errorMessage = "{0} is missing from Settings - Example: concentratorName=TESTSTREAM";
            Dictionary <string, string> settings = Settings;
            string setting;

            // Load optional parameters
            if (settings.TryGetValue("timeToPurge", out setting))
            {
                m_timeToPurge = Ticks.FromSeconds(double.Parse(setting));
            }

            if (settings.TryGetValue("warnInterval", out setting))
            {
                m_warnInterval = Ticks.FromSeconds(double.Parse(setting));
            }

            // Load required parameters
            string concentratorName;

            if (!settings.TryGetValue("concentratorName", out concentratorName))
            {
                throw new ArgumentException(string.Format(errorMessage, "concentratorName"));
            }

            m_discardingAdapter = null;

            // Find the adapter whose name matches the specified concentratorName
            foreach (IAdapter adapter in Parent)
            {
                IActionAdapter concentrator = adapter as IActionAdapter;

                if (concentrator != null && string.Compare(adapter.Name, concentratorName, true) == 0)
                {
                    m_discardingAdapter = concentrator;
                    break;
                }
            }

            if (m_discardingAdapter == null)
            {
                throw new ArgumentException(string.Format("Concentrator {0} not found.", concentratorName));
            }

            // Wait for associated adapter to initialize
            int timeout = m_discardingAdapter.InitializationTimeout;

            m_discardingAdapter.WaitForInitialize(timeout);

            if (!m_discardingAdapter.Initialized)
            {
                throw new TimeoutException(string.Format("Timeout waiting for concentrator {0} to initialize.", concentratorName));
            }

            // Attach to adapter's discarding measurements and disposed events
            m_discardingAdapter.DiscardingMeasurements += m_discardingAdapter_DiscardingMeasurements;
            m_discardingAdapter.Disposed += m_discardingAdapter_Disposed;

            m_purgeTimer.Interval = m_timeToPurge.ToMilliseconds();
            m_purgeTimer.Elapsed += m_purgeTimer_Elapsed;

            m_warningTimer.Interval = m_warnInterval.ToMilliseconds();
            m_warningTimer.Elapsed += m_warningTimer_Elapsed;

            m_timestampService = new TimestampService(this);
            m_timestampService.ServiceProcessException += m_timestampService_ServiceProcessException;
            m_timestampService.SettingsCategory         = base.Name + m_timestampService.SettingsCategory;
            m_timestampService.Initialize();
        }