//******************************************************************************************************
// RealTimeData.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:
// ----------------------------------------------------------------------------------------------------
// 07/21/2011 - Mehulbhai P Thakkar
// Generated original version of source code.
// 03/06/2012 - J. Ritchie Carroll
// Added virtual device for subscribed measurements when two nodes share a single database.
//
//******************************************************************************************************
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using GSF.Data;
using GSF.TimeSeries.UI;
namespace GSF.PhasorProtocols.UI.DataModels
{
///
/// Represents a real-time stream of subscribed data.
///
public class RealTimeStream : DataModelBase
{
#region [ Members ]
// Fields
private int m_id;
private string m_acronym;
private string m_name;
private string m_companyName;
private bool m_enabled;
private bool m_expanded;
private string m_statusColor;
private ObservableCollection m_deviceList;
#endregion
#region [ Constructors ]
///
/// Creates a new instance of the class.
///
public RealTimeStream()
: base(false, false)
{
}
#endregion
#region [ Properties ]
///
/// Gets or sets the ID of the .
///
public int ID
{
get
{
return m_id;
}
set
{
m_id = value;
OnPropertyChanged(nameof(ID));
}
}
///
/// Gets or sets the acronym of the current .
///
public string Acronym
{
get
{
return m_acronym;
}
set
{
m_acronym = value;
OnPropertyChanged(nameof(Acronym));
}
}
///
/// Gets or sets the name of the current .
///
public string Name
{
get
{
return m_name;
}
set
{
m_name = value;
OnPropertyChanged(nameof(Name));
}
}
///
/// Gets or sets the company name of the current .
///
public string CompanyName
{
get
{
return m_companyName;
}
set
{
m_companyName = value;
OnPropertyChanged(nameof(CompanyName));
}
}
///
/// Gets or sets the Expanded flag for the current .
///
public bool Expanded
{
get
{
return m_expanded;
}
set
{
m_expanded = value;
OnPropertyChanged(nameof(Expanded));
}
}
///
/// Gets or sets the status color of the current .
///
public string StatusColor
{
get
{
return m_statusColor;
}
set
{
m_statusColor = value;
OnPropertyChanged(nameof(StatusColor));
}
}
///
/// Gets or sets whether the current is enabled.
///
public bool Enabled
{
get
{
return m_enabled;
}
set
{
m_enabled = value;
OnPropertyChanged(nameof(Enabled));
}
}
///
/// Gets or sets collection of s for the current .
///
public ObservableCollection DeviceList
{
get
{
return m_deviceList;
}
set
{
m_deviceList = value;
OnPropertyChanged(nameof(DeviceList));
}
}
#endregion
#region [ Static ]
private const int GroupAccessID = -99999;
// Static Methods
///
/// Loads information as an style list.
///
/// to connection to database.
/// Collection of .
public static ObservableCollection Load(AdoDataConnection database)
{
bool createdConnection = false;
try
{
ObservableCollection realTimeStreamList = null;
createdConnection = CreateConnection(ref database);
DataSet resultSet = new();
resultSet.EnforceConstraints = false;
// Get PDCs list.
resultSet.Tables.Add(database.Connection.RetrieveData(database.AdapterType, database.ParameterizedQueryString("SELECT ID, Acronym, Name, ConnectionString, CompanyName, Enabled FROM DeviceDetail " +
"WHERE NodeID = {0} AND IsConcentrator = {1} AND Enabled = {2} ORDER BY Acronym", "nodeID", "isConcentrator", "enabled"), DefaultTimeout, database.CurrentNodeID(), database.Bool(true), database.Bool(true)).Copy());
resultSet.Tables[0].TableName = "PdcTable";
// Add a dummy device row in PDC table to associate PMUs which are not PDC and connected directly.
DataRow row = resultSet.Tables["PdcTable"].NewRow();
row["ID"] = 0;
row["Acronym"] = string.Empty;
row["Name"] = "Devices Connected Directly";
row["CompanyName"] = string.Empty;
row["Enabled"] = false;
resultSet.Tables["PdcTable"].Rows.Add(row);
// Get Non-PDC device list.
resultSet.Tables.Add(database.Connection.RetrieveData(database.AdapterType, database.ParameterizedQueryString("SELECT ID, Acronym, Name, AccessID, CompanyName, ProtocolName, VendorDeviceName, " +
"ParentAcronym, Enabled FROM DeviceDetail WHERE NodeID = {0} AND IsConcentrator = {1} AND Enabled = {2} ORDER BY Acronym", "nodeID", "isConcentrator", "enabled"),
DefaultTimeout, database.CurrentNodeID(), database.Bool(false), database.Bool(true)).Copy());
resultSet.Tables[1].TableName = "DeviceTable";
// Get non-statistical measurement list
resultSet.Tables.Add(database.Connection.RetrieveData(database.AdapterType, database.ParameterizedQueryString("SELECT ID, DeviceID, SignalID, PointID, PointTag, SignalReference, " +
"SignalAcronym, Description, SignalName, EngineeringUnits, HistorianAcronym, Subscribed, Internal FROM MeasurementDetail WHERE NodeID = {0} AND " +
"SignalAcronym <> {1} ORDER BY SignalReference", "nodeID", "signalAcronym"), DefaultTimeout, database.CurrentNodeID(), "STAT").Copy());
resultSet.Tables[2].TableName = "MeasurementTable";
// Query for any non-statistical measurements that are subscribed via GEP, but are a part of another node in the same database
// IMPORTANT: Make sure columns in this external node query exactly match those of the previous primary measurement query
DataTable otherMeasurements = database.Connection.RetrieveData(database.AdapterType, database.ParameterizedQueryString("SELECT ID, 0 AS DeviceID, SignalID, PointID, PointTag, SignalReference, " +
"SignalAcronym, Description, SignalName, EngineeringUnits, HistorianAcronym, Subscribed, Internal FROM MeasurementDetail WHERE NodeID <> {0} AND " +
"SignalAcronym <> {1} AND Subscribed <> 0 ORDER BY SignalReference", "nodeID", "signalAcronym"), DefaultTimeout, database.CurrentNodeID(), "STAT");
realTimeStreamList = new ObservableCollection(
from pdc in resultSet.Tables["PdcTable"].AsEnumerable()
let settings = pdc.Field("ConnectionString").ToNonNullString().ParseKeyValuePairs()
select new RealTimeStream
{
ID = pdc.ConvertField("ID"),
Acronym = string.IsNullOrEmpty(pdc.Field("Acronym")) ? "DIRECT CONNECTED" : pdc.Field("Acronym"),
Name = pdc.Field("Name"),
CompanyName = pdc.Field("CompanyName"),
StatusColor = string.IsNullOrEmpty(pdc.Field("Acronym")) ? "Transparent" : "Gray",
Enabled = Convert.ToBoolean(pdc.Field