//******************************************************************************************************
// MetadataRecordComposedFields.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:
// ----------------------------------------------------------------------------------------------------
// 02/21/2007 - Pinal C. Patel
// Generated original version of code based on DatAWare system specifications by Brian B. Fox, GSF.
// 04/20/2009 - Pinal C. Patel
// Converted to C#.
// 09/15/2009 - Stephen C. Wills
// Added new header and license agreement.
// 10/11/2010 - Mihir Brahmbhatt
// Updated header and license agreement.
// 11/30/2011 - J. Ritchie Carroll
// Modified to support buffer optimized ISupportBinaryImage.
// 12/14/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using GSF.Parsing;
namespace GSF.Historian.Files
{
///
/// Defines specific fields for s that are of type .
///
///
public class MetadataRecordComposedFields : ISupportBinaryImage
{
// **************************************************************************************************
// * Binary Structure *
// **************************************************************************************************
// * # Of Bytes Byte Index Data Type Property Name *
// * ---------- ---------- ---------- --------------------------------------------------------------*
// * 4 0-3 Single HighAlarm *
// * 4 4-7 Single LowAlarm *
// * 4 8-11 Single HighRange *
// * 4 12-15 Single LowRange *
// * 4 16-19 Single LowWarning *
// * 4 20-23 Single HighWarning *
// * 4 24-27 Int32 DisplayDigits *
// * 48 28-75 Int32(12) InputPointers *
// * 24 76-99 Char(24) EngineeringUnits *
// * 256 100-355 Char(256) Equation *
// * 4 356-359 Single CompressionLimit *
// **************************************************************************************************
#region [ Members ]
// Constants
///
/// Specifies the number of bytes in the binary image of .
///
public const int FixedLength = 360;
// Fields
private float m_highAlarm;
private float m_lowAlarm;
private float m_highRange;
private float m_lowRange;
private float m_lowWarning;
private float m_highWarning;
private int m_displayDigits;
private readonly List m_inputPointers;
private string m_engineeringUnits;
private string m_equation;
private float m_compressionLimit;
private readonly MetadataFileLegacyMode m_legacyMode;
#endregion
#region [ Constructors ]
///
/// Initializes a new instance of the class.
///
/// Legacy mode of .
internal MetadataRecordComposedFields(MetadataFileLegacyMode legacyMode)
{
m_engineeringUnits = string.Empty;
m_equation = string.Empty;
m_inputPointers = new List();
for (int i = 0; i < 12; i++)
{
m_inputPointers.Add(default(int));
}
m_legacyMode = legacyMode;
}
internal MetadataRecordComposedFields(BinaryReader reader)
{
m_legacyMode = MetadataFileLegacyMode.Disabled;
m_highAlarm = reader.ReadSingle();
m_lowAlarm = reader.ReadSingle();
m_highRange = reader.ReadSingle();
m_lowRange = reader.ReadSingle();
m_lowWarning = reader.ReadSingle();
m_highWarning = reader.ReadSingle();
m_displayDigits = reader.ReadInt32();
m_inputPointers = new List();
int count = reader.ReadInt32();
for (int i = 0; i < count; i++)
{
m_inputPointers.Add(reader.ReadInt32());
}
m_engineeringUnits = reader.ReadString();
m_equation = reader.ReadString();
m_compressionLimit = reader.ReadSingle();
}
#endregion
#region [ Properties ]
///
/// Gets or sets the value above which archived data for the is assigned a quality of .
///
public float HighAlarm
{
get
{
return m_highAlarm;
}
set
{
m_highAlarm = value;
}
}
///
/// Gets or sets the value above which archived data for the is assigned a quality of .
///
public float LowAlarm
{
get
{
return m_lowAlarm;
}
set
{
m_lowAlarm = value;
}
}
///
/// Gets or sets the value above which archived data for the is assigned a quality of .
///
public float HighRange
{
get
{
return m_highRange;
}
set
{
m_highRange = value;
}
}
///
/// Gets or sets the value above which archived data for the is assigned a quality of .
///
public float LowRange
{
get
{
return m_lowRange;
}
set
{
m_lowRange = value;
}
}
///
/// Gets or sets the value above which archived data for the is assigned a quality of .
///
public float LowWarning
{
get
{
return m_lowWarning;
}
set
{
m_lowWarning = value;
}
}
///
/// Gets or sets the value above which archived data for the is assigned a quality of .
///
public float HighWarning
{
get
{
return m_highWarning;
}
set
{
m_highWarning = value;
}
}
///
/// Gets or sets the number of digits after the decimal point to be displayed for the .
///
public int DisplayDigits
{
get
{
return m_displayDigits;
}
set
{
m_displayDigits = value;
}
}
///
/// Gets or sets the historian identifiers being used in the .
///
public IList InputPointers
{
get
{
return m_inputPointers.AsReadOnly();
}
}
///
/// Gets or sets the engineering units of archived data values for the .
///
/// The value being assigned is null.
public string EngineeringUnits
{
get
{
return m_engineeringUnits;
}
set
{
if ((object)value == null)
throw new ArgumentNullException(nameof(value));
if (m_legacyMode == MetadataFileLegacyMode.Enabled)
m_engineeringUnits = value.TruncateRight(24);
else
m_engineeringUnits = value;
}
}
///
/// Gets or sets the mathematical equation used for calculating the data value for the .
///
/// The value being assigned is null.
public string Equation
{
get
{
return m_equation;
}
set
{
if ((object)value == null)
throw new ArgumentNullException(nameof(value));
if (m_legacyMode == MetadataFileLegacyMode.Enabled)
m_equation = value.TruncateRight(256);
else
m_equation = value;
}
}
///
/// Gets or sets the amount, expressed in , by which data values for the must changed before being archived.
///
public float CompressionLimit
{
get
{
return m_compressionLimit;
}
set
{
m_compressionLimit = value;
}
}
///
/// Gets the length of the .
///
public int BinaryLength
{
get
{
return FixedLength;
}
}
#endregion
#region [ Methods ]
///
/// Initializes from the specified .
///
/// Binary image to be used for initializing .
/// 0-based starting index of initialization data in the .
/// Valid number of bytes in from .
/// Number of bytes used from the for initializing .
public int ParseBinaryImage(byte[] buffer, int startIndex, int length)
{
if (length >= FixedLength)
{
// Binary image has sufficient data.
HighAlarm = LittleEndian.ToSingle(buffer, startIndex);
LowAlarm = LittleEndian.ToSingle(buffer, startIndex + 4);
HighRange = LittleEndian.ToSingle(buffer, startIndex + 8);
LowRange = LittleEndian.ToSingle(buffer, startIndex + 12);
LowWarning = LittleEndian.ToSingle(buffer, startIndex + 16);
HighWarning = LittleEndian.ToSingle(buffer, startIndex + 20);
DisplayDigits = LittleEndian.ToInt32(buffer, startIndex + 24);
for (int i = 0; i < m_inputPointers.Count; i++)
{
m_inputPointers[i] = LittleEndian.ToInt32(buffer, startIndex + 28 + (i * 4));
}
EngineeringUnits = Encoding.ASCII.GetString(buffer, startIndex + 76, 24).Trim();
Equation = Encoding.ASCII.GetString(buffer, startIndex + 100, 256).Trim();
CompressionLimit = LittleEndian.ToSingle(buffer, startIndex + 356);
return FixedLength;
}
// Binary image does not have sufficient data.
return 0;
}
///
/// Generates binary image of the and copies it into the given buffer, for bytes.
///
/// Buffer used to hold generated binary image of the source object.
/// 0-based starting index in the to start writing.
/// The number of bytes written to the .
/// is null.
///
/// or is less than 0 -or-
/// and will exceed length.
///
public virtual int GenerateBinaryImage(byte[] buffer, int startIndex)
{
int length = BinaryLength;
buffer.ValidateParameters(startIndex, length);
Buffer.BlockCopy(LittleEndian.GetBytes(m_highAlarm), 0, buffer, startIndex, 4);
Buffer.BlockCopy(LittleEndian.GetBytes(m_lowAlarm), 0, buffer, startIndex + 4, 4);
Buffer.BlockCopy(LittleEndian.GetBytes(m_highRange), 0, buffer, startIndex + 8, 4);
Buffer.BlockCopy(LittleEndian.GetBytes(m_lowRange), 0, buffer, startIndex + 12, 4);
Buffer.BlockCopy(LittleEndian.GetBytes(m_lowWarning), 0, buffer, startIndex + 16, 4);
Buffer.BlockCopy(LittleEndian.GetBytes(m_highWarning), 0, buffer, startIndex + 20, 4);
Buffer.BlockCopy(LittleEndian.GetBytes(m_displayDigits), 0, buffer, startIndex + 24, 4);
for (int i = 0; i < m_inputPointers.Count; i++)
{
Buffer.BlockCopy(LittleEndian.GetBytes(m_inputPointers[i]), 0, buffer, startIndex + 28 + (i * 4), 4);
}
Buffer.BlockCopy(Encoding.ASCII.GetBytes(m_engineeringUnits.PadRight(24).TruncateRight(24)), 0, buffer, startIndex + 76, 24);
Buffer.BlockCopy(Encoding.ASCII.GetBytes(m_equation.PadRight(256).TruncateRight(256)), 0, buffer, startIndex + 100, 256);
Buffer.BlockCopy(LittleEndian.GetBytes(m_compressionLimit), 0, buffer, startIndex + 356, 4);
return length;
}
internal void WriteImage(BinaryWriter writer)
{
writer.Write(m_highAlarm);
writer.Write(m_lowAlarm);
writer.Write(m_highRange);
writer.Write(m_lowRange);
writer.Write(m_lowWarning);
writer.Write(m_highWarning);
writer.Write(m_displayDigits);
writer.Write(m_inputPointers.Count);
foreach (int inputPointer in m_inputPointers)
{
writer.Write(inputPointer);
}
writer.Write(m_engineeringUnits);
writer.Write(m_equation);
writer.Write(m_compressionLimit);
}
#endregion
}
}