//****************************************************************************************************** // RealTimeStatistic.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: // ---------------------------------------------------------------------------------------------------- // 09/28/2011 - Mehulbhai P Thakkar // Generated original version of source code. // //****************************************************************************************************** using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Diagnostics; using System.Linq; using System.Windows.Media; using GSF.Data; using GSF.TimeSeries.Statistics; using GSF.TimeSeries.UI; namespace GSF.PhasorProtocols.UI.DataModels { /// /// Represents collection of statistics for the configured devices. /// public class RealTimeStatistic : DataModelBase { #region [ Members ] // Fields private string m_sourceType; private bool m_expanded; private ObservableCollection m_streamStatisticList; #endregion #region [ Properties ] /// /// Gets or sets 's SourceType. /// public string SourceType { get { return m_sourceType; } set { m_sourceType = value; OnPropertyChanged("SourceType"); } } /// /// Gets or sets 's SourceType. /// public bool Expanded { get { return m_expanded; } set { m_expanded = value; OnPropertyChanged("Expanded"); } } /// /// Gets or sets 's SourceType. /// public ObservableCollection StreamStatisticList { get { return m_streamStatisticList; } set { m_streamStatisticList = value; OnPropertyChanged("StreamStatisticList"); } } #endregion #region [ Methods ] // Static /// /// Creates type collection of . /// /// to connection to database. /// Collection of . public static ObservableCollection Load(AdoDataConnection database) { bool createdConnection = false; try { createdConnection = CreateConnection(ref database); ObservableCollection realTimeStatisticList = new(); DataSet resultSet = new(); resultSet.EnforceConstraints = false; // Get PDCs and directly connected devices. resultSet.Tables.Add(database.Connection.RetrieveData(database.AdapterType, database.ParameterizedQueryString("SELECT ID, Acronym, Name FROM DeviceDetail " + "WHERE NodeID = {0} AND (IsConcentrator = {1} OR ParentAcronym = {2} OR ParentAcronym IS NULL) AND Enabled = {3} ORDER BY Acronym", "nodeID", "isConcentrator", "parentAcronym", "enabled"), DefaultTimeout, database.CurrentNodeID(), database.Bool(true), string.Empty, database.Bool(true)).Copy()); resultSet.Tables[0].TableName = "DirectDevices"; // Get all the devices connected via PDC. resultSet.Tables.Add(database.Connection.RetrieveData(database.AdapterType, database.ParameterizedQueryString("SELECT ID, Acronym, Name, ParentID, " + "ParentAcronym FROM DeviceDetail WHERE NodeID = {0} AND IsConcentrator = {1} AND Enabled = {2} AND ParentID > 0 ORDER BY Acronym", "nodeID", "isConcentrator", "enabled"), DefaultTimeout, database.CurrentNodeID(), database.Bool(false), database.Bool(true)).Copy()); resultSet.Tables[1].TableName = "PdcDevices"; // Get output stream information. resultSet.Tables.Add(database.Connection.RetrieveData(database.AdapterType, database.ParameterizedQueryString("SELECT ID, Acronym, Name FROM OutputStream WHERE " + "NodeID = {0} AND Enabled = {1} ORDER BY Acronym", "nodeID", "enabled"), DefaultTimeout, database.CurrentNodeID(), database.Bool(true)).Copy()); resultSet.Tables[2].TableName = "OutputStreams"; resultSet.Tables.Add(database.Connection.RetrieveData(database.AdapterType, database.ParameterizedQueryString("SELECT ID, AdapterName FROM CustomActionAdapter WHERE " + "NodeID = {0} AND TypeName = {1} AND Enabled = {2} ORDER BY AdapterName", "nodeID", "typeName", "enabled"), DefaultTimeout, database.CurrentNodeID(), "GSF.TimeSeries.Transport.DataPublisher", database.Bool(true)).Copy()); resultSet.Tables[3].TableName = "DataPublishers"; // Get list of statistic measurements detail. ObservableCollection statisticMeasurements = GetStatisticMeasurements(database); bool expanded = (statisticMeasurements.Count < 100); // We do this for later use in refreshing data. StatisticMeasurements = new Dictionary(); foreach (StatisticMeasurement statisticMeasurement in statisticMeasurements) StatisticMeasurements.Add(statisticMeasurement.SignalID, statisticMeasurement); // Create a system statistics list. ObservableCollection systemStatistics = new(); systemStatistics.Add(new StreamStatistic() { ID = 0, Acronym = "SYSTEM", Name = "System", StatusColor = "Green", Expanded = expanded, StatisticMeasurementList = new ObservableCollection(statisticMeasurements.Where(sm => sm.SignalReference.Contains("!SYSTEM"))), DeviceStatisticList = new ObservableCollection() }); SystemStatistics = new Dictionary(); foreach (StreamStatistic streamStatistic in systemStatistics) { // We do this to associate statistic measurement to parent output stream easily. foreach (StatisticMeasurement measurement in streamStatistic.StatisticMeasurementList) measurement.DeviceID = streamStatistic.ID; streamStatistic.DeviceStatisticList.Insert(0, new PdcDeviceStatistic() { DeviceID = 0, DeviceAcronym = "Run-time Statistics", DeviceName = "", Expanded = expanded, StatisticMeasurementList = streamStatistic.StatisticMeasurementList }); streamStatistic.StatisticMeasurementList = null; // We do this for later use in refreshing data. SystemStatistics.Add(streamStatistic.ID, streamStatistic); } // Create an input stream statistics list. ObservableCollection inputStreamStatistics = new ( from stream in resultSet.Tables["DirectDevices"].AsEnumerable() select new StreamStatistic { ID = Convert.ToInt32(stream.Field("ID")), Acronym = stream.Field("Acronym"), Name = stream.Field("Name"), StatusColor = "Gray", Expanded = expanded, StatisticMeasurementList = new ObservableCollection ( ( from statisticMeasurement in statisticMeasurements where statisticMeasurement.DeviceID == Convert.ToInt32(stream.Field("ID")) select statisticMeasurement ).OrderBy(sm => sm.Source).ThenBy(sm => sm.LoadOrder) ), DeviceStatisticList = new ObservableCollection ( from pdcdevice in resultSet.Tables["PdcDevices"].AsEnumerable() where Convert.ToInt32(pdcdevice.Field("ParentID")) == Convert.ToInt32(stream.Field("ID")) select new PdcDeviceStatistic() { DeviceID = Convert.ToInt32(pdcdevice.Field("ID")), ParentID = Convert.ToInt32(pdcdevice.Field("ParentID")), DeviceAcronym = pdcdevice.Field("Acronym"), DeviceName = pdcdevice.Field("Name"), Expanded = expanded, StatisticMeasurementList = new ObservableCollection ( ( from statisticMeasurement in statisticMeasurements where statisticMeasurement.DeviceID == Convert.ToInt32(pdcdevice.Field("ID")) select statisticMeasurement ).OrderBy(sm => sm.LoadOrder) ) } ) } ); InputStreamStatistics = new Dictionary(); DevicesWithStatisticMeasurements = new Dictionary>(); foreach (StreamStatistic streamStatistic in inputStreamStatistics) { streamStatistic.DeviceStatisticList.Insert(0, new PdcDeviceStatistic() { DeviceID = 0, DeviceAcronym = "Run-time Statistics", DeviceName = "", Expanded = expanded, StatisticMeasurementList = new ObservableCollection(streamStatistic.StatisticMeasurementList) }); // We do this for later use in refreshing data. InputStreamStatistics.Add(streamStatistic.ID, streamStatistic); // We do this for use in Input Status & Monitoring screen to set proper status color. if (streamStatistic.ID > 0) { DevicesWithStatisticMeasurements.Add(streamStatistic.ID, streamStatistic.StatisticMeasurementList); foreach (PdcDeviceStatistic device in streamStatistic.DeviceStatisticList) { if (device.DeviceID > 0) DevicesWithStatisticMeasurements.Add(device.DeviceID, device.StatisticMeasurementList); } } streamStatistic.StatisticMeasurementList = null; } // Create an output stream statistics list. ObservableCollection outputStreamStatistics = new ( from outputStream in resultSet.Tables["OutputStreams"].AsEnumerable() select new StreamStatistic() { ID = Convert.ToInt32(outputStream.Field("ID")), Acronym = outputStream.Field("Acronym"), Name = outputStream.Field("Name"), StatusColor = "Gray", DeviceStatisticList = new ObservableCollection(), Expanded = expanded, StatisticMeasurementList = new ObservableCollection ( ( from statisticMeasurement in statisticMeasurements where statisticMeasurement.SignalReference.StartsWith(outputStream.Field("Acronym") + "!OS-") select statisticMeasurement ).OrderBy(sm => sm.Source).ThenBy(sm => sm.LoadOrder) ) } ); OutputStreamStatistics = new Dictionary(); foreach (StreamStatistic streamStatistic in outputStreamStatistics) { // We do this to associate statistic measurement to parent output stream easily. foreach (StatisticMeasurement measurement in streamStatistic.StatisticMeasurementList) measurement.DeviceID = streamStatistic.ID; streamStatistic.DeviceStatisticList.Insert(0, new PdcDeviceStatistic { DeviceID = 0, DeviceAcronym = "Run-time Statistics", DeviceName = "", Expanded = expanded, StatisticMeasurementList = streamStatistic.StatisticMeasurementList }); streamStatistic.StatisticMeasurementList = null; // We do this for later use in refreshing data. OutputStreamStatistics.Add(streamStatistic.ID, streamStatistic); } // Create a data publisher statistics list ObservableCollection dataPublisherStatistics = new ( from publisher in resultSet.Tables["DataPublishers"].AsEnumerable() select new StreamStatistic() { ID = Convert.ToInt32(publisher.Field("ID")), Acronym = publisher.Field("AdapterName"), Name = "", StatusColor = "Gray", DeviceStatisticList = new ObservableCollection(), Expanded = expanded, StatisticMeasurementList = new ObservableCollection ( ( from statisticMeasurement in statisticMeasurements where statisticMeasurement.SignalReference.StartsWith(publisher.Field("AdapterName") + "!PUB-") select statisticMeasurement ).OrderBy(sm => sm.Source).ThenBy(sm => sm.LoadOrder) ) } ); DataPublisherStatistics = new Dictionary(); foreach (StreamStatistic streamStatistic in dataPublisherStatistics) { // We do this to associate statistic measurement to parent output stream easily. foreach (StatisticMeasurement measurement in streamStatistic.StatisticMeasurementList) measurement.DeviceID = streamStatistic.ID; streamStatistic.DeviceStatisticList.Insert(0, new PdcDeviceStatistic() { DeviceID = 0, DeviceAcronym = "Run-time Statistics", DeviceName = "", Expanded = expanded, StatisticMeasurementList = streamStatistic.StatisticMeasurementList }); streamStatistic.StatisticMeasurementList = null; // We do this for later use in refreshing data. DataPublisherStatistics.Add(streamStatistic.ID, streamStatistic); } // Merge system, input and output stream statistics to create a realtime statistics list. realTimeStatisticList.Add(new RealTimeStatistic() { SourceType = "System", Expanded = false, StreamStatisticList = systemStatistics }); realTimeStatisticList.Add(new RealTimeStatistic() { SourceType = "Input Streams", Expanded = false, StreamStatisticList = inputStreamStatistics }); realTimeStatisticList.Add(new RealTimeStatistic() { SourceType = "Output Streams", Expanded = false, StreamStatisticList = outputStreamStatistics }); realTimeStatisticList.Add(new RealTimeStatistic() { SourceType = "Data Publisher", Expanded = false, StreamStatisticList = dataPublisherStatistics }); return realTimeStatisticList; } finally { if (createdConnection && database != null) database.Dispose(); } } /// /// Gets statistic measurements from the database for current node. /// /// to connection to database. /// Collection of . public static ObservableCollection GetStatisticMeasurements(AdoDataConnection database) { bool createdConnection = false; try { createdConnection = CreateConnection(ref database); // Get Statistic Definitions ObservableCollection statisticDefinitions = Statistic.Load(database); // Get statistics measurements. DataTable statisticMeasurements = database.Connection.RetrieveData(database.AdapterType, database.ParameterizedQueryString("SELECT SignalID, ID, DeviceID, PointID, PointTag, SignalReference, Description " + "FROM StatisticMeasurement WHERE NodeID = {0}", "nodeID"), DefaultTimeout, database.CurrentNodeID()); // Assign min and max point IDs as we will need them to request data from web service. MinPointID = int.MaxValue; MaxPointID = int.MinValue; foreach (DataRow row in statisticMeasurements.Rows) { int pointID = Convert.ToInt32(row.Field("PointID")); MinPointID = Math.Min(MinPointID, pointID); MaxPointID = Math.Max(MaxPointID, pointID); } // Takes datarow from statisticMeasurements data table, and associates each row to their statistic source and returns KeyValuePair. Func> mapFunction = measurement => { string signalReference = measurement.Field("SignalReference"); string measurementSource; if (StatisticsEngine.RegexMatch(signalReference, "SYSTEM")) measurementSource = "System"; else if (StatisticsEngine.RegexMatch(signalReference, "PMU")) measurementSource = "Device"; else if (StatisticsEngine.RegexMatch(signalReference, "OS")) measurementSource = "OutputStream"; else if (StatisticsEngine.RegexMatch(signalReference, "IS")) measurementSource = "InputStream"; else if (StatisticsEngine.RegexMatch(signalReference, "SUB")) measurementSource = "Subscriber"; else if (StatisticsEngine.RegexMatch(signalReference, "PUB")) measurementSource = "Publisher"; else measurementSource = "???"; return new KeyValuePair(measurement, measurementSource); }; // Takes KeyValuePair and generates StatisticMeasurement record by maping statistic measurements with statistic definitions. Func, StatisticMeasurement> selectFunction = keyvaluepair => { DataRow measurement = keyvaluepair.Key; string measurementSource = keyvaluepair.Value; Debug.WriteLine(measurementSource); string signalReference = measurement.Field("SignalReference"); int signalReferenceIndex = signalReference.LastIndexOf("-ST"); int measurementIndex = (signalReferenceIndex != -1) ? Convert.ToInt32(signalReference.Substring(signalReference.LastIndexOf("-ST") + 3)) : -1; Statistic statisticDefinition = null; foreach (Statistic statistic in statisticDefinitions) { if (statistic.Source == measurementSource && statistic.SignalIndex == measurementIndex) { statisticDefinition = statistic; break; } } return new StatisticMeasurement() { SignalID = database.Guid(measurement, "SignalID"), ID = measurement.Field("ID"), DeviceID = Convert.ToInt32(measurement.Field("DeviceID") ?? -1), PointID = Convert.ToInt32(measurement.Field("PointID")), PointTag = measurement.Field("PointTag"), SignalReference = signalReference, Source = measurementSource, StatisticName = statisticDefinition?.Name ?? measurement.Field("Description"), StatisticDescription = statisticDefinition?.Description ?? measurement.Field("Description"), DataType = statisticDefinition?.DataType ?? "System.Double", DisplayFormat = statisticDefinition?.DisplayFormat ?? "{0}", ConnectedState = statisticDefinition?.IsConnectedState ?? false, LoadOrder = statisticDefinition?.LoadOrder ?? 0, TimeTag = "n/a", Quality = "n/a", Value = "--" }; }; return new ObservableCollection(statisticMeasurements.Rows.Cast().Select(mapFunction).OrderBy(pair => pair.Value).Select(selectFunction).OrderBy(s => s.LoadOrder)); } finally { if (createdConnection && database != null) database.Dispose(); } } /// /// Defines maximum value of statistic measurement's point id defined in the database. /// public static int MaxPointID; /// /// Defines minimum value of statistic measurement's point id defined in the database. /// public static int MinPointID; /// /// Defines a collection of s defined in the database. /// public static Dictionary StatisticMeasurements; /// /// Defines a collection of defined in the database. /// public static Dictionary SystemStatistics; /// /// Defines a collection of defined in the database. /// public static Dictionary InputStreamStatistics; /// /// Defines a collection of defined in the database. /// public static Dictionary OutputStreamStatistics; /// /// Defines a collection of defined in the database. /// public static Dictionary DataPublisherStatistics; /// /// Defines collection of device ids with associated statistical measurements. /// public static Dictionary> DevicesWithStatisticMeasurements; #endregion } /// /// Represents a connection (either to a PDC or a device) with a list of associated devices and statistical measurements. /// public class StreamStatistic : DataModelBase { #region [ Members ] // Fields private int m_id; private string m_acronym; private string m_name; private string m_statusColor; private bool m_expanded; private ObservableCollection m_deviceStatisticList; private ObservableCollection m_statisticMeasurementList; #endregion #region [ Properties ] /// /// Gets or sets 's ID. /// public int ID { get { return m_id; } set { m_id = value; OnPropertyChanged("ID"); } } /// /// Gets or sets 's Acronym. /// public string Acronym { get { return m_acronym; } set { m_acronym = value; OnPropertyChanged("Acronym"); } } /// /// Gets or sets 's Name. /// public string Name { get { return m_name; } set { m_name = value; OnPropertyChanged("Name"); } } /// /// Gets or set 's Foreground. /// public string StatusColor { get { return m_statusColor; } set { m_statusColor = value; OnPropertyChanged("StatusColor"); } } /// /// Gets or sets 's DeviceStatisticList. /// public ObservableCollection DeviceStatisticList { get { return m_deviceStatisticList; } set { m_deviceStatisticList = value; OnPropertyChanged("DeviceStatisticList"); } } /// /// Gets or sets 's StatisticMeasurementList. /// public ObservableCollection StatisticMeasurementList { get { return m_statisticMeasurementList; } set { m_statisticMeasurementList = value; OnPropertyChanged("StatisticMeasurementList"); } } /// /// Gets or sets 's Expanded flag. /// public bool Expanded { get { return m_expanded; } set { m_expanded = value; OnPropertyChanged("Expanded"); } } #endregion } /// /// Represents a device with a list of statistical measurement associated with it. /// public class PdcDeviceStatistic : DataModelBase { #region [ Members ] // Fields private int m_id; private int m_parentId; private string m_acronym; private string m_name; private ObservableCollection m_statisticMeasurementList; private bool m_expanded; #endregion #region [ Properties ] /// /// Gets or sets 's ID. /// public int DeviceID { get { return m_id; } set { m_id = value; OnPropertyChanged("DeviceID"); } } /// /// Gets or sets 's ParentID. /// public int ParentID { get { return m_parentId; } set { m_parentId = value; OnPropertyChanged("ParentID"); } } /// /// Gets or sets 's Acronym. /// public string DeviceAcronym { get { return m_acronym; } set { m_acronym = value; OnPropertyChanged("DeviceAcronym"); } } /// /// Gets or sets 's Name. /// public string DeviceName { get { return m_name; } set { m_name = value; OnPropertyChanged("DeviceName"); } } /// /// Gets or sets 's StatisticMeasurementList. /// public ObservableCollection StatisticMeasurementList { get { return m_statisticMeasurementList; } set { m_statisticMeasurementList = value; OnPropertyChanged("StatisticMeasurementList"); } } /// /// Gets or sets 's Expanded flag. /// public bool Expanded { get { return m_expanded; } set { m_expanded = value; OnPropertyChanged("Expanded"); } } #endregion } /// /// Represents a measurement record with all related statistic information. /// public class StatisticMeasurement : DataModelBase { #region [ Members ] // Fields private Guid m_signalID; private int m_deviceID; private int m_pointID; private string m_id; private string m_pointTag; private string m_signalReference; private string m_source; private string m_statisticName; private string m_statisticDescription; private string m_dataType; private string m_displayFormat; private bool m_connectedState; private int m_loadOrder; private string m_timeTag; private string m_value; private string m_quality; private SolidColorBrush m_foreground; private bool m_expanded; #endregion #region [ Properties ] /// /// Gets or sets 's SignalID. /// public Guid SignalID { get { return m_signalID; } set { m_signalID = value; OnPropertyChanged("SignalID"); } } /// /// Gets or set 's DeviceID. /// public int DeviceID { get { return m_deviceID; } set { m_deviceID = value; OnPropertyChanged("DeviceID"); } } /// /// Gets or set 's PointID. /// public int PointID { get { return m_pointID; } set { m_pointID = value; OnPropertyChanged("PointID"); } } /// /// Gets or set 's ID. /// public string ID { get { return m_id; } set { m_id = value; OnPropertyChanged("ID"); } } /// /// Gets or set 's PointTag. /// public string PointTag { get { return m_pointTag; } set { m_pointTag = value; OnPropertyChanged("PointTag"); } } /// /// Gets or set 's SignalReference. /// public string SignalReference { get { return m_signalReference; } set { m_signalReference = value; OnPropertyChanged("SignalReference"); } } /// /// Gets or set 's Source. /// public string Source { get { return m_source; } set { m_source = value; OnPropertyChanged("Source"); } } /// /// Gets or set 's StatisticName. /// public string StatisticName { get { return m_statisticName; } set { m_statisticName = value; OnPropertyChanged("StatisticName"); } } /// /// Gets or set 's StatisticDescription. /// public string StatisticDescription { get { return m_statisticDescription; } set { m_statisticDescription = value; OnPropertyChanged("StatisticDescription"); } } /// /// Gets or set 's DataType. /// public string DataType { get { return m_dataType; } set { m_dataType = value; OnPropertyChanged("DataType"); } } /// /// Gets or set 's DisplayFormat. /// public string DisplayFormat { get { return m_displayFormat; } set { m_displayFormat = value; OnPropertyChanged("DisplayFormat"); } } /// /// Gets or set 's ConnectedState. /// public bool ConnectedState { get { return m_connectedState; } set { m_connectedState = value; OnPropertyChanged("ConnectedState"); } } /// /// Gets or set 's LoadOrder. /// public int LoadOrder { get { return m_loadOrder; } set { m_loadOrder = value; OnPropertyChanged("LoadOrder"); } } /// /// Gets or set 's TimeTag. /// public string TimeTag { get { return m_timeTag; } set { m_timeTag = value; OnPropertyChanged("TimeTag"); } } /// /// Gets or set 's Value. /// public string Value { get { return m_value; } set { m_value = value; OnPropertyChanged("Value"); } } /// /// Gets or set 's Quality. /// public string Quality { get { return m_quality; } set { m_quality = value; OnPropertyChanged("Quality"); } } /// /// Gets or set 's Foreground. /// public SolidColorBrush Foreground { get { return m_foreground; } set { m_foreground = value; OnPropertyChanged("Foreground"); } } /// /// Gets or set 's Expanded flag. /// public bool Expanded { get { return m_expanded; } set { m_expanded = value; OnPropertyChanged("Expanded"); } } #endregion } }