//******************************************************************************************************
// AnalogChannel.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:
// ----------------------------------------------------------------------------------------------------
// 05/19/2011 - J. Ritchie Carroll
// Generated original version of source code.
// 12/13/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
using System.Collections.Generic;
using GSF.Collections;
using GSF.PhasorProtocols;
using GSF.Units.EE;
namespace GSF.COMTRADE
{
///
/// Represents an analog channel definition of the .
///
public class AnalogChannel
{
#region [ Members ]
// Fields
private int m_index;
private string m_stationName;
private string m_channelName;
private char m_phaseDesignation;
private SignalKind m_signalKind;
private PhasorType m_phasorType;
private double m_nominalFrequency;
private CoordinateFormat m_coordinateFormat;
private string m_circuitComponent;
private string m_units;
private double m_multipler;
private double m_adder;
private double m_skew;
private int m_minValue;
private int m_maxValue;
private double m_primaryRatio;
private double m_secondaryRatio;
private char m_scalingIdentifier;
#endregion
#region [ Constructors ]
///
/// Creates a new instance of the .
///
public AnalogChannel()
{
m_phaseDesignation = char.MinValue;
m_signalKind = SignalKind.Analog;
m_coordinateFormat = CoordinateFormat.Polar;
m_multipler = 0.04;
m_adder = 0.0;
m_nominalFrequency = 60.0D;
m_minValue = -99999;
m_maxValue = 99998;
m_primaryRatio = 1.0;
m_secondaryRatio = 1.0;
m_scalingIdentifier = 'P';
}
///
/// Creates a new instance of the from an existing line image.
///
/// Line image to parse.
public AnalogChannel(string lineImage)
{
// An,ch_id,ph,ccbm,uu,a,b,skew,min,max,primary,secondary,PS
string[] parts = lineImage.Split(',');
if (parts.Length != 13)
throw new InvalidOperationException(string.Format("Unexpected number of line image elements for analog channel definition: {0} - expected 13\r\nImage = {1}", parts.Length, lineImage));
Index = int.Parse(parts[0].Trim());
Name = parts[1];
PhaseID = parts[2];
CircuitComponent = parts[3];
Units = parts[4];
Multiplier = double.Parse(parts[5].Trim());
Adder = double.Parse(parts[6].Trim());
Skew = double.Parse(parts[7].Trim());
MinValue = int.Parse(parts[8].Trim());
MaxValue = int.Parse(parts[9].Trim());
PrimaryRatio = double.Parse(parts[10].Trim());
SecondaryRatio = double.Parse(parts[11].Trim());
ScalingIdentifier = parts[12].Trim()[0];
}
#endregion
#region [ Properties ]
///
/// Gets or sets index of this .
///
public int Index
{
get
{
return m_index;
}
set
{
m_index = value;
}
}
///
/// Gets or sets name of this formatted as station_name:channel_name.
///
/// Name must be formatted as station_name:channel_name.
public string Name
{
get
{
if (string.IsNullOrEmpty(m_stationName))
return null;
if (!string.IsNullOrEmpty(m_channelName))
return string.Format("{0}:{1}", m_stationName, m_channelName);
return m_stationName;
}
set
{
string[] parts = value.Split(':');
if (parts.Length == 2)
{
m_stationName = parts[0].Trim();
m_channelName = parts[1].Trim();
}
else
{
m_stationName = value;
}
}
}
///
/// Gets or sets station name component of this .
///
public string StationName
{
get
{
return m_stationName;
}
set
{
m_stationName = value.Replace(":", "_").Trim();
}
}
///
/// Gets or sets channel name component of this .
///
public string ChannelName
{
get
{
return m_channelName;
}
set
{
m_channelName = value.Replace(":", "_").Trim();
}
}
///
/// Gets or sets the 2-character phase identifier for this .
///
public string PhaseID
{
get
{
switch (m_signalKind)
{
case SignalKind.Magnitude:
if (m_phaseDesignation != char.MinValue)
{
if (m_coordinateFormat == CoordinateFormat.Rectangular)
return m_phaseDesignation + "r";
return m_phaseDesignation + "m";
}
break;
case SignalKind.Angle:
if (m_phaseDesignation != char.MinValue)
{
if (m_coordinateFormat == CoordinateFormat.Rectangular)
return m_phaseDesignation + "i";
return m_phaseDesignation + "a";
}
break;
case SignalKind.Frequency:
return "F";
case SignalKind.DfDt:
return "df";
}
return PhaseDesignation;
}
set
{
value = value.Trim();
if (string.IsNullOrEmpty(value))
{
m_phaseDesignation = char.MinValue;
this.SignalKind = SignalKind.Analog;
m_coordinateFormat = CoordinateFormat.Polar;
}
else
{
if (string.Compare(value, "F", true) == 0)
{
m_phaseDesignation = char.MinValue;
this.SignalKind = SignalKind.Frequency;
m_coordinateFormat = CoordinateFormat.Polar;
}
else if (string.Compare(value, "df", true) == 0)
{
m_phaseDesignation = char.MinValue;
this.SignalKind = SignalKind.DfDt;
m_coordinateFormat = CoordinateFormat.Polar;
}
else if (value.Length > 1)
{
this.PhaseDesignation = value[0].ToString();
char component = char.ToLower(value[1]);
switch (component)
{
case 'r':
this.SignalKind = SignalKind.Magnitude;
m_coordinateFormat = CoordinateFormat.Rectangular;
break;
case 'i':
this.SignalKind = SignalKind.Angle;
m_coordinateFormat = CoordinateFormat.Rectangular;
break;
case 'm':
this.SignalKind = SignalKind.Magnitude;
m_coordinateFormat = CoordinateFormat.Polar;
break;
case 'a':
this.SignalKind = SignalKind.Angle;
m_coordinateFormat = CoordinateFormat.Polar;
break;
}
}
else
{
this.PhaseDesignation = value[0].ToString();
this.SignalKind = SignalKind.Analog;
m_coordinateFormat = CoordinateFormat.Polar;
}
}
}
}
///
/// Gets or sets phase designation of this .
///
/// Value is not a valid phase designation.
public string PhaseDesignation
{
get
{
return m_phaseDesignation.ToString().RemoveNull();
}
set
{
value = value.Trim();
if (string.IsNullOrEmpty(value))
{
m_phaseDesignation = char.MinValue;
}
else
{
char phaseDesignation = char.ToUpper(value[0]);
switch (phaseDesignation)
{
case 'A':
case 'R':
case '1':
m_phaseDesignation = 'A';
break;
case 'B':
case 'S':
case '2':
m_phaseDesignation = 'B';
break;
case 'C':
case 'T':
case '3':
m_phaseDesignation = 'C';
break;
case 'P':
case '+':
m_phaseDesignation = 'P';
break;
case 'N':
case '-':
m_phaseDesignation = '-';
break;
case 'Z':
case '0':
m_phaseDesignation = '0';
break;
default:
m_phaseDesignation = char.MinValue;
break;
}
}
}
}
///
/// Gets or sets phasor type of this , if applicable.
///
public PhasorType PhasorType
{
get
{
return m_phasorType;
}
set
{
m_phasorType = value;
}
}
///
/// Gets or sets nominal frequency of this .
///
public double NominalFrequency
{
get
{
return m_nominalFrequency;
}
set
{
m_nominalFrequency = value;
if (m_signalKind == SignalKind.Frequency)
m_adder = (double)m_nominalFrequency;
}
}
///
/// Gets or sets signal kind of this .
///
/// Value is not a valid analog signal kind.
public SignalKind SignalKind
{
get
{
return m_signalKind;
}
set
{
if (s_validAnalogSignalKinds.BinarySearch(value) < 0)
throw new ArgumentException(value + " is not a valid analog signal kind.");
m_signalKind = value;
switch (m_signalKind)
{
case SignalKind.Angle:
m_multipler = 0.006;
m_adder = 0.0;
break;
case SignalKind.Magnitude:
if (m_phasorType == PhasorType.Current)
m_multipler = 0.4;
else
m_multipler = 0.04;
m_adder = 0.0;
break;
case SignalKind.Frequency:
m_multipler = 0.001;
m_adder = (double)m_nominalFrequency;
break;
case SignalKind.DfDt:
m_multipler = 0.01;
m_adder = 0.0;
break;
default:
m_multipler = 0.04;
m_adder = 0.0;
break;
}
}
}
///
/// Gets or sets coordinate format of this .
///
public CoordinateFormat CoordinateFormat
{
get
{
return m_coordinateFormat;
}
set
{
m_coordinateFormat = value;
}
}
///
/// Gets or sets circuit component of this .
///
public string CircuitComponent
{
get
{
return m_circuitComponent;
}
set
{
if (!string.IsNullOrWhiteSpace(value))
m_circuitComponent = value.Trim();
else
m_circuitComponent = "";
if (m_circuitComponent.Length > 64)
m_circuitComponent = m_circuitComponent.Substring(0, 64);
}
}
///
/// Gets or sets units of this .
///
public string Units
{
get
{
return m_units;
}
set
{
if (!string.IsNullOrWhiteSpace(value))
m_units = value.Trim();
else
m_units = "";
if (m_units.Length > 32)
m_units = m_units.Substring(0, 32);
}
}
///
/// Gets or sets value multipler of this .
///
public double Multiplier
{
get
{
return m_multipler;
}
set
{
m_multipler = value;
}
}
///
/// Gets or sets adder of this .
///
public double Adder
{
get
{
return m_adder;
}
set
{
m_adder = value;
}
}
///
/// Gets or sets time skew between channels of this .
///
public double Skew
{
get
{
return m_skew;
}
set
{
m_skew = value;
}
}
///
/// Gets or sets minimum unscaled value of this .
///
public int MinValue
{
get
{
return m_minValue;
}
set
{
m_minValue = value;
}
}
///
/// Gets or sets maximum unscaled value of this .
///
public int MaxValue
{
get
{
return m_maxValue;
}
set
{
m_maxValue = value;
}
}
///
/// Gets or sets the channel voltage or current transformer ratio primary factor of this .
///
public double PrimaryRatio
{
get
{
return m_primaryRatio;
}
set
{
m_primaryRatio = value;
}
}
///
/// Gets or sets the channel voltage or current transformer ratio secondary factor of this .
///
public double SecondaryRatio
{
get
{
return m_secondaryRatio;
}
set
{
m_secondaryRatio = value;
}
}
///
/// Gets or sets the the primary or secondary data scaling identifer of this .
///
public char ScalingIdentifier
{
get
{
return m_scalingIdentifier;
}
set
{
value = char.ToUpper(value);
if (value != 'P' && value != 'S')
throw new ArgumentException(value + " is not a valid primary or secondary data scaling identifer - must be either \'P\' or \'S\'.");
m_scalingIdentifier = value;
}
}
#endregion
#region [ Methods ]
///
/// Converts to its string format.
///
public override string ToString()
{
string[] values = new string[13];
// An,ch_id,ph,ccbm,uu,a,b,skew,min,max,primary,secondary,PS
values[0] = Index.ToString();
values[1] = Name;
values[2] = PhaseID;
values[3] = CircuitComponent;
values[4] = Units;
values[5] = Multiplier.ToString();
values[6] = Adder.ToString();
values[7] = Skew.ToString();
values[8] = MinValue.ToString();
values[9] = MaxValue.ToString();
values[10] = PrimaryRatio.ToString();
values[11] = SecondaryRatio.ToString();
values[12] = ScalingIdentifier.ToString();
return values.ToDelimitedString(',');
}
#endregion
#region [ Static ]
// Static Fields
private static readonly List s_validAnalogSignalKinds;
// Static Constructor
static AnalogChannel()
{
s_validAnalogSignalKinds = new List(new[] { SignalKind.Analog, SignalKind.Angle, SignalKind.Calculation, SignalKind.DfDt, SignalKind.Frequency, SignalKind.Magnitude, SignalKind.Statistic });
s_validAnalogSignalKinds.Sort();
}
#endregion
}
}