//******************************************************************************************************
// CalculatedMeasurementBase.cs - Gbtc
//
// Copyright © 2012, 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:
// ----------------------------------------------------------------------------------------------------
// 10/19/2009 - J. Ritchie Carroll
// Generated original version of source code.
// 04/21/2010 - J. Ritchie Carroll
// Added signal type summary to the calculated measurement status.
// 12/04/2012 - J. Ritchie Carroll
// Migrated to PhasorProtocolAdapters project.
// 12/13/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using GSF;
using GSF.TimeSeries;
using GSF.TimeSeries.Adapters;
using GSF.TimeSeries.Data;
using GSF.Units.EE;
namespace PhasorProtocolAdapters
{
///
/// Represents the base class for calculated measurements that use phasor data.
///
///
/// This base class extends by automatically looking up the
/// for each of the input and output measurements.
///
public abstract class CalculatedMeasurementBase : ActionAdapterBase
{
#region [ Members ]
// Fields
private string m_configurationSection;
private bool m_supportsTemporalProcessing;
#endregion
#region [ Properties ]
///
/// Gets or sets primary keys of input measurements the calculated measurement expects.
///
[ConnectionStringParameter]
[DefaultValue(null)]
[Description("Defines primary keys of input measurements the action adapter expects; can be one of a filter expression, measurement key, point tag or Guid.")]
[CustomConfigurationEditor("GSF.TimeSeries.UI.WPF.dll", "GSF.TimeSeries.UI.Editors.MeasurementEditor")]
public override MeasurementKey[] InputMeasurementKeys
{
get => base.InputMeasurementKeys;
set
{
base.InputMeasurementKeys = value;
InputMeasurementKeyTypes = DataSource.GetSignalTypes(value);
}
}
///
/// Gets or sets output measurements that the calculated measurement will produce, if any.
///
[ConnectionStringParameter]
[DefaultValue(null)]
[Description("Defines primary keys of output measurements the action adapter expects; can be one of a filter expression, measurement key, point tag or Guid.")]
[CustomConfigurationEditor("GSF.TimeSeries.UI.WPF.dll", "GSF.TimeSeries.UI.Editors.MeasurementEditor")]
public override IMeasurement[] OutputMeasurements
{
get => base.OutputMeasurements;
set
{
base.OutputMeasurements = value;
OutputMeasurementTypes = DataSource.GetSignalTypes(value);
}
}
///
/// Gets or sets input measurement 's for each of the , if any.
///
public virtual SignalType[] InputMeasurementKeyTypes { get; private set; }
///
/// Gets or sets output measurement 's for each of the , if any.
///
public virtual SignalType[] OutputMeasurementTypes { get; private set; }
///
/// Gets or sets the configuration section to use for this .
///
public virtual string ConfigurationSection
{
get => m_configurationSection;
set => m_configurationSection = value;
}
///
/// Gets the flag indicating if this adapter supports temporal processing.
///
public override bool SupportsTemporalProcessing => m_supportsTemporalProcessing;
///
/// Returns the detailed status of the calculated measurement.
///
///
/// Derived classes should extend status with implementation specific information.
///
public override string Status
{
get
{
StringBuilder status = new StringBuilder();
int count;
status.AppendFormat(" Configuration section: {0}", ConfigurationSection);
status.AppendLine();
status.Append(base.Status);
if (OutputMeasurements != null && OutputMeasurements.Length > 0)
{
status.AppendLine();
status.AppendLine("Output measurements signal type summary:");
status.AppendLine();
foreach (SignalType signalType in Enum.GetValues(typeof(SignalType)))
{
count = OutputMeasurements.Where((key, index) => OutputMeasurementTypes[index] == signalType).Count();
if (count <= 0)
continue;
status.AppendFormat("{0} {1} signal{2}", count.ToString().PadLeft(15), signalType.GetFormattedName(), count > 1 ? "s" : "");
status.AppendLine();
}
}
if (InputMeasurementKeys != null && InputMeasurementKeys.Length > 0)
{
status.AppendLine();
status.AppendLine("Input measurement keys signal type summary:");
status.AppendLine();
foreach (SignalType signalType in Enum.GetValues(typeof(SignalType)))
{
count = InputMeasurementKeys.Where((key, index) => InputMeasurementKeyTypes[index] == signalType).Count();
if (count <= 0)
continue;
status.AppendFormat("{0} {1} signal{2}", count.ToString().PadLeft(15), signalType.GetFormattedName(), count > 1 ? "s" : "");
status.AppendLine();
}
}
return status.ToString();
}
}
#endregion
#region [ Methods ]
///
/// Initializes .
///
public override void Initialize()
{
base.Initialize();
Dictionary settings = Settings;
// Load optional parameters
if (!settings.TryGetValue("configurationSection", out m_configurationSection))
m_configurationSection = Name;
if (string.IsNullOrEmpty(m_configurationSection))
m_configurationSection = Name;
m_supportsTemporalProcessing = settings.TryGetValue("supportsTemporalProcessing", out string setting) && setting.ParseBoolean();
}
#endregion
}
}