//******************************************************************************************************
// MetaDataTag.cs - Gbtc
//
// Copyright © 2020, 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 Eclipse Public License -v 1.0 (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/eclipse-1.0.php
//
// 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:
// ----------------------------------------------------------------------------------------------------
// 03/06/2020 - Christoph Lackner
// Generated original version of source code.
//
//******************************************************************************************************
using System;
using System.Collections.Generic;
namespace GSF.PQDS
{
///
/// PQDS metadata tag Datatypes according to PQDS spec.
///
public enum PQDSMetaDataType
{
///
/// Enumeration data type
///
Enumeration = 0,
///
/// Numeric data type
///
Numeric = 1,
///
/// AlphaNumeric data type
///
AlphaNumeric = 2,
///
/// Text data type
///
Text = 3,
///
/// Binary data type
///
Binary = 4
}
///
/// Abstract Class of MetaData Tags for a .
///
public abstract class MetaDataTag
{
#region[Properties]
///
/// Meta data key value of row
///
protected string m_key;
///
/// Meta data unit value of row
///
protected string m_unit;
///
/// Meta data raw value of row
///
protected string m_rawValue;
///
/// Meta data expected data type of row
///
protected PQDSMetaDataType m_expectedDataType;
///
/// Meta data note value of row
///
protected string m_note;
#endregion[Properties]
#region[Methods]
///
/// the Metadata Tag key.
///
public string Key { get { return (m_key); } }
///
/// the Metadata Tag unit.
///
public string Unit { get { return (m_unit); } }
///
/// the Metadata Tag raw value without typing.
///
public string RawValue { get { return (m_rawValue); } }
///
/// Converst the Metadata tag into a line of a PQDS file
///
/// The metadataTag as a String
public abstract String Write();
///
/// Returns the PQDS datatype
///
/// The PQDS Datatype
public abstract PQDSMetaDataType Type();
#endregion[Methods]
}
///
/// Class of MetaData Tags for a .
///
public class MetaDataTag : MetaDataTag
{
#region[Properties]
private DataType m_value;
///
/// Value of the MetadataTag.
///
public DataType Value { get { return m_value; } }
#endregion[Properties]
#region[Constructor]
///
/// Creates a .
///
/// key of the MetadataTag
/// Value of the MetadataTag
public MetaDataTag(String key, DataType value)
{
m_value = value;
m_rawValue = value?.ToString() ?? "";
m_key = key;
if (!keyToDataTypeLookup.TryGetValue(key, out m_expectedDataType))
m_expectedDataType = PQDSMetaDataType.Text;
if (!keyToUnitLookup.TryGetValue(key, out m_unit))
m_unit = null;
if (!keyToNoteLookup.TryGetValue(key, out m_note))
m_note = null;
//Check to ensure a string does not end up being a number etc...
if (m_expectedDataType == PQDSMetaDataType.AlphaNumeric)
{
if (!((value is string) | (value is Guid)))
{ throw new InvalidCastException("Can not cast object to Alphanumeric Type"); }
}
else if (m_expectedDataType == PQDSMetaDataType.Numeric)
{
if (!((value is int) | (value is double)))
{ throw new InvalidCastException("Can not cast object to Numeric Type"); }
}
else if (m_expectedDataType == PQDSMetaDataType.Enumeration)
{
if (!((value is int)))
{ throw new InvalidCastException("Can not cast object to Numeric Type"); }
}
else if (m_expectedDataType == PQDSMetaDataType.Binary)
{
if (!((value is int) | (value is Boolean)))
{ throw new InvalidCastException("Can not cast object to Numeric Type"); }
}
}
///
/// Creates a custom .
///
/// key of the MetadataTag
/// Value of the MetadataTag
/// The of the metadata tag
/// The unit of the metadata tag
/// a describtion of the metadata tag
public MetaDataTag(String key, DataType value, PQDSMetaDataType valueType, String unit, String description)
{
m_value = value;
m_rawValue = value?.ToString() ?? "";
m_key = key;
m_expectedDataType = valueType;
if (unit.Trim('"') == "") { m_unit = null; }
else { m_unit = unit.Trim('"'); }
if (description.Trim('"') == "") { m_note = null; }
else { m_note = description.Trim('"'); }
}
#endregion[Constructor]
#region[Methods]
///
/// Converst the Metadata tag into a line of a PQDS file
///
/// The metadataTag as a String
public override string Write()
{
string result = String.Format("{0},\"{1}\",{2},{3},\"{4}\"",
m_key, m_value, m_unit, DataTypeToCSV(m_expectedDataType), m_note);
return result;
}
///
/// Returns the PQDS datatype
///
/// The PQDS Datatype
public override PQDSMetaDataType Type()
{
return m_expectedDataType;
}
#endregion[Methods]
#region[Statics]
private static readonly Dictionary keyToDataTypeLookup = new Dictionary()
{
{"DeviceName", PQDSMetaDataType.Text },
{"DeviceAlias", PQDSMetaDataType.Text },
{"DeviceLocation", PQDSMetaDataType.Text },
{"DeviceLocationAlias", PQDSMetaDataType.Text },
{"DeviceLatitude", PQDSMetaDataType.Text },
{"DeviceLongitude", PQDSMetaDataType.Text },
{"Accountname", PQDSMetaDataType.Text },
{"AccountNameAlias", PQDSMetaDataType.Text },
{"DeviceDistanceToXFMR", PQDSMetaDataType.Numeric },
{"DeviceConnectionTypeCode", PQDSMetaDataType.Enumeration },
{"DeviceOwner", PQDSMetaDataType.Text },
{"NominalVoltage-LG", PQDSMetaDataType.Numeric },
{"NominalFrequency", PQDSMetaDataType.Numeric },
{"UpstreamXFMR-kVA", PQDSMetaDataType.Numeric },
{"LineLength", PQDSMetaDataType.Numeric },
{"AssetName", PQDSMetaDataType.Text },
{"EventGUID", PQDSMetaDataType.AlphaNumeric },
{"EventID", PQDSMetaDataType.Text },
{"EventYear", PQDSMetaDataType.Enumeration },
{"EventMonth", PQDSMetaDataType.Enumeration },
{"EventDay", PQDSMetaDataType.Enumeration },
{"EventHour", PQDSMetaDataType.Enumeration },
{"EventMinute", PQDSMetaDataType.Enumeration },
{"EventSecond", PQDSMetaDataType.Enumeration },
{"EventNanoSecond", PQDSMetaDataType.Numeric },
{"EventDate", PQDSMetaDataType.Text },
{"EventTime", PQDSMetaDataType.Text },
{"EventTypeCode", PQDSMetaDataType.Enumeration },
{"EventFaultTypeCode", PQDSMetaDataType.Enumeration },
{"EventPeakCurrent", PQDSMetaDataType.Numeric },
{"EventPeakVoltage", PQDSMetaDataType.Numeric },
{"EventMaxVA", PQDSMetaDataType.Numeric },
{"EventMaxVB", PQDSMetaDataType.Numeric },
{"EventMaxVC", PQDSMetaDataType.Numeric },
{"EventMinVA", PQDSMetaDataType.Numeric },
{"EventMinVB", PQDSMetaDataType.Numeric },
{"EventMinVC", PQDSMetaDataType.Numeric },
{"EventMaxIA", PQDSMetaDataType.Numeric },
{"EventMaxIB", PQDSMetaDataType.Numeric },
{"EventMaxIC", PQDSMetaDataType.Numeric },
{"EventPreEventCurrent", PQDSMetaDataType.Numeric },
{"EventPreEventVoltage", PQDSMetaDataType.Numeric },
{"EventDuration", PQDSMetaDataType.Numeric },
{"EventFaultI2T", PQDSMetaDataType.Numeric },
{"DistanceToFault", PQDSMetaDataType.Numeric },
{"EventCauseCode", PQDSMetaDataType.Enumeration },
{"WaveformDataType", PQDSMetaDataType.Enumeration },
{"WaveFormSensitivityCode", PQDSMetaDataType.Enumeration },
{"WaveFormSensitivityNote", PQDSMetaDataType.Text },
{"Utility", PQDSMetaDataType.Text },
{"ContactEmail", PQDSMetaDataType.Text }
};
private static readonly Dictionary keyToUnitLookup = new Dictionary()
{
{"DeviceName", null },
{"DeviceAlias", null },
{"DeviceLocation", null },
{"DeviceLocationAlias", null },
{"DeviceLatitude", null },
{"DeviceLongitude", null },
{"Accountname", null },
{"AccountNameAlias", null },
{"DeviceDistanceToXFMR", "feet" },
{"DeviceConnectionTypeCode", null },
{"DeviceOwner", null },
{"NominalVoltage-LG", "Volts" },
{"NominalFrequency", "Hz" },
{"UpstreamXFMR-kVA", "kVA" },
{"LineLength", "miles" },
{"AssetName", null },
{"EventGUID", null },
{"EventID", null },
{"EventYear", null },
{"EventMonth", null },
{"EventDay", null },
{"EventHour", null },
{"EventMinute", null },
{"EventSecond", null },
{"EventNanoSecond", null },
{"EventDate", null },
{"EventTime", null },
{"EventTypeCode", null },
{"EventFaultTypeCode", null },
{"EventPeakCurrent", "Amps" },
{"EventPeakVoltage", "Volts" },
{"EventMaxVA", "Volts" },
{"EventMaxVB", "Volts" },
{"EventMaxVC", "Volts" },
{"EventMinVA", "Volts" },
{"EventMinVB", "Volts" },
{"EventMinVC", "Volts" },
{"EventMaxIA", "Amps" },
{"EventMaxIB", "Amps" },
{"EventMaxIC", "Amps" },
{"EventPreEventCurrent", "Amps" },
{"EventPreEventVoltage", "Volts" },
{"EventDuration", "ms" },
{"EventFaultI2T", "A2s" },
{"DistanceToFault", "miles" },
{"EventCauseCode", null },
{"WaveformDataType", null },
{"WaveFormSensitivityCode", null },
{"WaveFormSensitivityNote", null },
{"Utility", null },
{"ContactEmail", null }
};
private static readonly Dictionary keyToNoteLookup = new Dictionary()
{
{"DeviceName", "Meter or measurement device name" },
{"DeviceAlias", "Alternate meter or measurement device name" },
{"DeviceLocation", "Meter or measurment device location name" },
{"DeviceLocationAlias", "Alternate meter or device location name" },
{"DeviceLatitude", "Latitude" },
{"DeviceLongitude", "Longtitude" },
{"Accountname", "Name of customer or account" },
{"AccountNameAlias", "Alternate name of customer or account" },
{"DeviceDistanceToXFMR", "Distance to the upstream transformer" },
{"DeviceConnectionTypeCode", "PQDS code for meter connection type" },
{"DeviceOwner", "Utility name" },
{"NominalVoltage-LG", "Nominal Line to Ground Voltage" },
{"NominalFrequency", "Nominal System frequency" },
{"UpstreamXFMR-kVA", "Upstream Transformer size" },
{"LineLength", "Length of the Line" },
{"AssetName", "Asset name" },
{"EventGUID", "Globally Unique Event Identifier" },
{"EventID", "A user defined Event Name" },
{"EventYear", "Year" },
{"EventMonth", "Month" },
{"EventDay", "Day" },
{"EventHour", "Hour" },
{"EventMinute", "Minute" },
{"EventSecond", "Second" },
{"EventNanoSecond", "Nanosconds" },
{"EventDate", "Event Date" },
{"EventTime", "Event Time" },
{"EventTypeCode", "PQDS Event Type Code" },
{"EventFaultTypeCode", "PQDS Fault Type Code" },
{"EventPeakCurrent", "Peak Current"},
{"EventPeakVoltage", "Peak Voltage" },
{"EventMaxVA", "RMS Maximum A Phase Voltage" },
{"EventMaxVB", "RMS Maximum B Phase Voltage" },
{"EventMaxVC", "RMS Maximum C Phase Voltage" },
{"EventMinVA", "RMS Minimum A Phase Voltage" },
{"EventMinVB", "RMS Minimum B Phase Voltage" },
{"EventMinVC", "RMS Minimum C Phase Voltage" },
{"EventMaxIA", "RMS Maximum A Phase Current" },
{"EventMaxIB", "RMS Maximum B Phase Current" },
{"EventMaxIC", "RMS Maximum C Phase Current" },
{"EventPreEventCurrent", "Pre Event Current" },
{"EventPreEventVoltage", "pre Event Voltage" },
{"EventDuration", "Event Duration" },
{"EventFaultI2T", "I2(t) during Fault duration" },
{"DistanceToFault", "Distance to Fault" },
{"EventCauseCode", "PQDS Event Cause Code" },
{ "WaveformDataType", "PQDS Data Type Code"},
{"WaveFormSensitivityCode", "PQDS Data Sensitivity Code" },
{"WaveFormSensitivityNote", "Notes on the PQDS Data Sensitivity Code" },
{"Utility", "Utility that Generated this Dataset" },
{"ContactEmail", "Contact for Utility that Created this Dataset" }
};
private static string DataTypeToCSV(PQDSMetaDataType dataType)
{
switch (dataType)
{
case (PQDSMetaDataType.Text):
return "T";
case (PQDSMetaDataType.Numeric):
return "N";
case (PQDSMetaDataType.Enumeration):
return "E";
case (PQDSMetaDataType.AlphaNumeric):
return "A";
case (PQDSMetaDataType.Binary):
return "B";
default:
return "T";
}
}
#endregion[Statics]
}
}