736 lines · 29.0 KB · C#
RawDownload
//******************************************************************************************************//  RealTimeStreams.cs - Gbtc////  Copyright © 2010, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may//  not use this file except in compliance with the License. You may obtain a copy of the License at:////      http://www.opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  08/18/2011 - Mehulbhai P Thakkar//       Generated original version of source code.////****************************************************************************************************** using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.Globalization;using System.Linq;using System.Text;using System.Threading;using System.Windows;using System.Windows.Input;using GSF.Communication;using GSF.Data;using GSF.PhasorProtocols.UI.DataModels;using GSF.ServiceProcess;using GSF.TimeSeries;using GSF.TimeSeries.Statistics;using GSF.TimeSeries.Transport;using GSF.TimeSeries.UI;using GSF.Units.EE; namespace GSF.PhasorProtocols.UI.ViewModels{    /// <summary>    /// Class to hold bindable <see cref="RealTimeStream"/> collection and current selection information for UI.    /// </summary>    internal class RealTimeStreams : PagedViewModelBase<RealTimeStream, int>    {        #region [ Members ]         // Fields        private bool m_expanded;        private bool m_restartConnectionCycle;        private string m_lastRefresh;        private ObservableCollection<StatisticMeasurement> m_statisticMeasurements;        private Dictionary<Guid, RealTimeMeasurement> m_realTimeMeasurements;         private RealTimeStatistics m_statistics;        private readonly int m_statisticRefreshInterval = 5;        private bool m_temporalSupportEnabled;        private string m_startTime = "*-10m";        private string m_stopTime = "*";          // Unsynchronized Subscription Fields.        private DataSubscriber m_unsynchronizedSubscriber;        private bool m_subscribedUnsynchronized;        private string m_allSignalIDs;  // string of GUIDs used for subscription.        private int m_processingUnsynchronizedMeasurements;        private readonly int m_refreshInterval = 5;         #endregion         #region [ Constructors ]         /// <summary>        /// Creates an instance of <see cref="RealTimeStreams"/>.        /// </summary>        /// <param name="itemsPerPage"></param>        /// <param name="refreshInterval">Interval to refresh measurement in a tree.</param>        /// <param name="autoSave"></param>                public RealTimeStreams(int itemsPerPage, int refreshInterval, bool autoSave = false)            : base(itemsPerPage, autoSave)        {            // Perform initialization here.             m_refreshInterval = refreshInterval;            InitializeUnsynchronizedSubscription();            m_restartConnectionCycle = true;            StatisticMeasurements = new ObservableCollection<StatisticMeasurement>();             int.TryParse(IsolatedStorageManager.ReadFromIsolatedStorage("StatisticsDataRefreshInterval").ToString(), out m_statisticRefreshInterval);            Statistics = new RealTimeStatistics(1, m_statisticRefreshInterval);             CheckTemporalSupport();        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets or sets start time for this <see cref="RealTimeStream"/>.        /// </summary>        public string StartTime        {            get            {                return m_startTime;            }            set            {                m_startTime = value;            }        }         /// <summary>        /// Gets or sets stop for this <see cref="RealTimeStream"/>.        /// </summary>        public string StopTime        {            get            {                return m_stopTime;            }            set            {                m_stopTime = value;            }        }         /// <summary>        /// Gets or sets flag that determines if temporal support is enabled.        /// </summary>        public bool TemporalSupportEnabled        {            get            {                return m_temporalSupportEnabled;            }            set            {                m_temporalSupportEnabled = value;                OnPropertyChanged("TemporalSupportEnabled");            }        }         /// <summary>        /// Gets flag that determines if <see cref="PagedViewModelBase{T1, T2}.CurrentItem"/> is a new record.        /// </summary>        public override bool IsNewRecord        {            get            {                return CurrentItem.ID == 0;            }        }         /// <summary>        /// Gets or sets a boolean flag <see cref="RealTimeStreams"/> expanded flag.        /// </summary>        public bool Expanded        {            get            {                return m_expanded;            }            set            {                m_expanded = value;                OnPropertyChanged("Expanded");            }        }         /// <summary>        /// Gets or sets a boolean flag indicating if connection to backend windows service needs to be reestablished upon disconnection.        /// </summary>        public bool RestartConnectionCycle        {            get            {                return m_restartConnectionCycle;            }            set            {                m_restartConnectionCycle = value;            }        }         /// <summary>        /// Gets or sets a last refresh time to display on UI.        /// </summary>        public string LastRefresh        {            get            {                return m_lastRefresh;            }            set            {                m_lastRefresh = value;                OnPropertyChanged("LastRefresh");            }        }         /// <summary>        /// Gets or sets <see cref="RealTimeStreams"/> StatisticMeasurements.        /// </summary>        public ObservableCollection<StatisticMeasurement> StatisticMeasurements        {            get            {                return m_statisticMeasurements;            }            set            {                m_statisticMeasurements = value;                OnPropertyChanged("StatisticMeasurements");            }        }         private RealTimeStatistics Statistics        {            get            {                return m_statistics;            }            set            {                if ((object)m_statistics != null)                    m_statistics.NewMeasurements -= m_statistics_NewMeasurements;                 m_statistics = value;                 if ((object)m_statistics != null)                    m_statistics.NewMeasurements += m_statistics_NewMeasurements;            }        }         #endregion         #region [ Methods ]         /// <summary>        /// Gets the primary key value of the <see cref="PagedViewModelBase{T1, T2}.CurrentItem"/>.        /// </summary>        /// <returns>The primary key value of the <see cref="PagedViewModelBase{T1, T2}.CurrentItem"/>.</returns>        public override int GetCurrentItemKey()        {            return CurrentItem.ID;        }         /// <summary>        /// Gets the string based named identifier of the <see cref="PagedViewModelBase{T1, T2}.CurrentItem"/>.        /// </summary>        /// <returns>The string based named identifier of the <see cref="PagedViewModelBase{T1, T2}.CurrentItem"/>.</returns>        public override string GetCurrentItemName()        {            return CurrentItem.Name;        }         /// <summary>        /// Overrides Load() method from the base class to add aditional functionalities.        /// </summary>        public override void Load()        {            try            {                Mouse.OverrideCursor = Cursors.Wait;                 base.Load();                 // Build a string of measurement GUIDs to pass into subscription request to retrieve data for tree.                StringBuilder sb = new StringBuilder();                 foreach (RealTimeStream stream in ItemsSource)                {                    foreach (RealTimeDevice device in stream.DeviceList)                    {                        foreach (RealTimeMeasurement measurement in device.MeasurementList)                        {                            sb.Append(measurement.SignalID.ToString());                            sb.Append(";");                        }                    }                }                 m_allSignalIDs = sb.ToString();                 if (m_allSignalIDs.Length > 0)                    m_allSignalIDs = m_allSignalIDs.Substring(0, m_allSignalIDs.Length - 1);            }            catch (Exception ex)            {                if (ex.InnerException != null)                {                    Popup(ex.Message + Environment.NewLine + "Inner Exception: " + ex.InnerException.Message, "Load " + DataModelName + " Exception:", MessageBoxImage.Error);                    CommonFunctions.LogException(null, "Load " + DataModelName, ex.InnerException);                }                else                {                    Popup(ex.Message, "Load " + DataModelName + " Exception:", MessageBoxImage.Error);                    CommonFunctions.LogException(null, "Load " + DataModelName, ex);                }            }            finally            {                Mouse.OverrideCursor = null;            }        }         public void GetStatistics(Device device)        {            try            {                StatisticMeasurements.Clear();                 ObservableCollection<StatisticMeasurement> tempMeasurements = new ObservableCollection<StatisticMeasurement>(                    RealTimeStatistic.GetStatisticMeasurements(null).Where(sm => sm.DeviceID == device.ID)                );                 foreach (StatisticMeasurement measurement in tempMeasurements)                {                    StatisticMeasurement tempMeasurement;                     if (RealTimeStatistic.StatisticMeasurements.TryGetValue(measurement.SignalID, out tempMeasurement))                        StatisticMeasurements.Add(tempMeasurement);                }             }            catch (Exception ex)            {                Popup("Failed to retrieve statistics." + Environment.NewLine + ex.Message, "ERROR! Get Statistics", MessageBoxImage.Error);            }        }         private void m_statistics_NewMeasurements(object sender, EventArgs<ICollection<IMeasurement>> e)        {            if (0 == Interlocked.Exchange(ref m_processingUnsynchronizedMeasurements, 1))            {                try                {                    StreamStatistic streamStatistic;                    long now = DateTime.UtcNow.Ticks;                     // Since device health is handled by the data subscription,                    // this subscription will only tell us whether devices have                    // been disconnected -- colors can only turn red                    foreach (RealTimeStream stream in ItemsSource)                    {                        if (stream.ID > 0 && RealTimeStatistic.InputStreamStatistics.TryGetValue(stream.ID, out streamStatistic))                        {                            // Stream has input stream statistics                            // that determine its connectivity state                            if (streamStatistic.StatusColor == "Red")                                stream.StatusColor = "Red";                        }                         foreach (RealTimeDevice device in stream.DeviceList)                        {                            if (device.ID != null && device.ID > 0)                            {                                if (stream.StatusColor == "Red")                                {                                    // If a stream is disconnected,                                    // its devices are also disconnected                                    device.StatusColor = "Red";                                }                                else if (RealTimeStatistic.InputStreamStatistics.TryGetValue((int)device.ID, out streamStatistic))                                {                                    // The device is direct connected, so it has input stream                                    // statistics that determine its connectivity state                                    if (streamStatistic.StatusColor == "Red")                                        device.StatusColor = "Red";                                }                            }                            else                            {                                // This device is not configured, but rather its existence is inferred based on the signal references of its measurements.                                // Its connectivity state is determined by the length of time since its measurements were last received                                if (device.MeasurementList.All(measurement => Ticks.ToSeconds(now - measurement.LastUpdated) > m_refreshInterval * 2))                                    device.StatusColor = "Red";                            }                             if (device.StatusColor == "Red")                            {                                // For devices which are now disconnected, change their measurements to a gray color                                foreach (RealTimeMeasurement measurement in device.MeasurementList)                                    measurement.Quality = "N/A";                            }                        }                    }                }                finally                {                    Interlocked.Exchange(ref m_processingUnsynchronizedMeasurements, 0);                }            }        }         #region [ Unsynchronized Subscription ]         private void m_unsynchronizedSubscriber_ConnectionTerminated(object sender, EventArgs e)        {            m_subscribedUnsynchronized = false;            TerminateSubscription();             if (RestartConnectionCycle)                InitializeUnsynchronizedSubscription();        }         private void m_unsynchronizedSubscriber_NewMeasurements(object sender, EventArgs<ICollection<IMeasurement>> e)        {            if (0 == Interlocked.Exchange(ref m_processingUnsynchronizedMeasurements, 1))            {                try                {                    ObservableCollection<StatisticMeasurement> statisticMeasurements;                    RealTimeMeasurement realTimeMeasurement;                     HashSet<RealTimeStream> updatedStreams = new HashSet<RealTimeStream>();                    HashSet<RealTimeDevice> updatedDevices = new HashSet<RealTimeDevice>();                     // If it doesn't already exist, create lookup table to allow quick                    // lookup of RealTimeMeasurements whose value has changed                    if ((object)m_realTimeMeasurements == null)                    {                        m_realTimeMeasurements = ItemsSource                            .SelectMany(stream => stream.DeviceList)                            .SelectMany(device => device.MeasurementList)                            .GroupBy(measurement => measurement.SignalID)                            .Select(group => group.First())                            .ToDictionary(measurement => measurement.SignalID);                    }                     // Update measurements that have changed                    foreach (IMeasurement newMeasurement in e.Argument)                    {                        if (m_realTimeMeasurements.TryGetValue(newMeasurement.ID, out realTimeMeasurement))                        {                            RealTimeDevice parentDevice = realTimeMeasurement.Parent;                            RealTimeStream parentStream = parentDevice.Parent;                             if (newMeasurement.Timestamp > realTimeMeasurement.LastUpdated)                            {                                realTimeMeasurement.Quality = newMeasurement.ValueQualityIsGood() && newMeasurement.TimestampQualityIsGood() ? "GOOD" : "BAD";                                realTimeMeasurement.LongTimeTag = newMeasurement.Timestamp.ToString("yyyy-MM-dd HH:mm:ss.fff");                                realTimeMeasurement.TimeTag = newMeasurement.Timestamp.ToString("HH:mm:ss.fff");                                realTimeMeasurement.Value = newMeasurement.AdjustedValue.ToString("0.###");                                realTimeMeasurement.LastUpdated = newMeasurement.Timestamp;                                 // Maintain collection of updated devices and streams                                updatedDevices.Add(parentDevice);                                 if ((object)parentStream != null)                                    updatedStreams.Add(parentStream);                            }                        }                    }                     // Update status color of the updated devices                    // NOTE: Color cannot be red since we just received data from the devices                    foreach (RealTimeDevice device in updatedDevices)                    {                        // By default, determine color based on measurement quality                        List<RealTimeMeasurement> measurementList = device.MeasurementList.Where(m => m.Value != "--").ToList();                         if (measurementList.Count > 0)                        {                            if (measurementList.All(m => m.Quality != "BAD"))                                device.StatusColor = "Green";                            else                                device.StatusColor = "Yellow";                        }                         if (device.ID != null && device.ID > 0)                        {                            // Check to see if device has statistic measurements which define the number of errors reported by the device                            if (RealTimeStatistic.DevicesWithStatisticMeasurements.TryGetValue((int)device.ID, out statisticMeasurements))                            {                                // If there are any reported errors, force color to yellow                                foreach (StatisticMeasurement statisticMeasurement in statisticMeasurements)                                {                                    int value;                                     bool yellow =                                        StatisticsEngine.RegexMatch(statisticMeasurement.SignalReference, "PMU") &&                                        statisticMeasurement.StatisticName == "Measurements With Error" &&                                        int.TryParse(statisticMeasurement.Value, NumberStyles.AllowThousands, CultureInfo.CurrentCulture, out value) &&                                        value > 0;                                     if (yellow)                                        device.StatusColor = "Yellow";                                }                            }                        }                    }                     // Update status color of the updated streams                    // NOTE: Color cannot be red since we just received data from the devices                    foreach (RealTimeStream stream in updatedStreams)                    {

Lines 1–500 of 736.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t