//******************************************************************************************************
// ControlFileStructures.cs - Gbtc
//
// Copyright © 2014, 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:
// ----------------------------------------------------------------------------------------------------
// 08/05/2014 - J. Ritchie Carroll
// Generated original version of source code.
//
//******************************************************************************************************
using System;
using System.IO;
using System.Runtime.InteropServices;
// ReSharper disable FieldCanBeMadeReadOnly.Local
// ReSharper disable MemberCanBePrivate.Local
// ReSharper disable NotAccessedField.Local
// ReSharper disable UnusedField.Compiler
namespace GSF.EMAX
{
// All control structures are little-endian encoded
// All control structures only occur once within the control file
public enum DataSize : byte
{
Bits12 = 0xAF,
Bits16 = 0xAB
}
public enum StructureType : ushort
{
EndOfStructures = 0x0000,
SYSTEM_PARAMETERS = 0x0001,
A_E_RSLTS = 0x0003,
ANALOG_GROUP = 0x0004,
EVENT_GROUP = 0x0005,
ANLG_CHNL_NEW = 0x0006,
EVNT_CHNL_NEW = 0x0007,
ANLG_CHNLS = 0x0008,
SYS_SETTINGS = 0x000B,
SHORT_HEADER = 0x000D,
FAULT_HEADER = 0x010D, // (with RMS)
EVENT_DISPLAY = 0x000E,
IDENTSTRING = 0x0010,
A_SELECTION = 0x0040,
E_GROUP_SELECT = 0x0041,
PHASOR_GROUP = 0x0042,
LINE_CONSTANTS = 0x0043,
LINE_NAMES = 0x0044,
FAULT_LOCATION = 0x0045,
SENS_RSLTS = 0x0050,
SEQUENCE_CHANNELS = 0x0051,
TPwrRcd = 0x0052,
BoardAnalogEventChannels = 0x0060,
BREAKER_TRIP_TIMES = 0x0061,
Unknown = 0xFFFF
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CTL_HEADER
{
[MarshalAs(UnmanagedType.U2)]
public ushort id; // System ID
[MarshalAs(UnmanagedType.U4)]
public uint time; // Time of CTL file creation
[MarshalAs(UnmanagedType.U1)]
public byte num_of_structs; // Number of Structures in CTL file
public DateTime Timestamp
{
get
{
return new UnixTimeTag(time).ToDateTime();
}
}
}
public struct CTL_FILE_STRUCT
{
public StructureType type;
public uint offset;
public CTL_FILE_STRUCT(BinaryReader reader)
{
ushort ushortValue = BigEndian.ToUInt16(reader.ReadBytes(2), 0);
if (!Enum.IsDefined(typeof(StructureType), ushortValue))
type = StructureType.Unknown;
else
type = (StructureType)ushortValue;
offset = reader.ReadUInt32() >> 8;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
public struct SYSTEMTIME
{
[MarshalAs(UnmanagedType.U2)]
public ushort Year;
[MarshalAs(UnmanagedType.U2)]
public ushort Month;
[MarshalAs(UnmanagedType.U2)]
public ushort DayOfWeek;
[MarshalAs(UnmanagedType.U2)]
public ushort Day;
[MarshalAs(UnmanagedType.U2)]
public ushort Hour;
[MarshalAs(UnmanagedType.U2)]
public ushort Minute;
[MarshalAs(UnmanagedType.U2)]
public ushort Second;
[MarshalAs(UnmanagedType.U2)]
public ushort Milliseconds;
public SYSTEMTIME(DateTime dt)
{
dt = dt.ToUniversalTime(); // SetSystemTime expects the SYSTEMTIME in UTC
Year = (ushort)dt.Year;
Month = (ushort)dt.Month;
DayOfWeek = (ushort)dt.DayOfWeek;
Day = (ushort)dt.Day;
Hour = (ushort)dt.Hour;
Minute = (ushort)dt.Minute;
Second = (ushort)dt.Second;
Milliseconds = (ushort)dt.Millisecond;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct TIME_ZONE_INFORMATION
{
[MarshalAs(UnmanagedType.I4)]
public Int32 Bias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string StandardName;
public SYSTEMTIME StandardDate;
[MarshalAs(UnmanagedType.I4)]
public Int32 StandardBias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DaylightName;
public SYSTEMTIME DaylightDate;
[MarshalAs(UnmanagedType.I4)]
public Int32 DaylightBias;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct SYSTEM_PARAMETERS
{
[MarshalAs(UnmanagedType.U2)]
public ushort samples_per_second;
[MarshalAs(UnmanagedType.I1)]
public sbyte frequency;
[MarshalAs(UnmanagedType.I1)]
public sbyte vXtndFlt;
[MarshalAs(UnmanagedType.I2)]
public short channel_offset;
[MarshalAs(UnmanagedType.I2)]
public short prefault_samples;
[MarshalAs(UnmanagedType.I2)]
public short prefault_smpls_disp; /* set for the number to be displayed */
[MarshalAs(UnmanagedType.I4)]
public int postfault_samples; /* normal single length record from samples per second times postfault_time */
[MarshalAs(UnmanagedType.I4)]
public int postfault_samples_max; /* maximum length of extended records times postfault_time_max */
[MarshalAs(UnmanagedType.I2)]
public short postfault_time; /* normal minimum record included in 32kword record */
[MarshalAs(UnmanagedType.I2)]
public short postfault_time_max;
[MarshalAs(UnmanagedType.I2)]
public short record_fill; /* 1 = fill 2=double_pixel 4 = dot_join (or for combinations 8 = polarity inversion */
[MarshalAs(UnmanagedType.I2)]
public short event_groups;
[MarshalAs(UnmanagedType.I2)]
public short analog_groups;
[MarshalAs(UnmanagedType.I2)]
public short sequence; /* fault number sequence */
[MarshalAs(UnmanagedType.I2)]
public short time_flag1; /* (determines if irig is set to on) */
[MarshalAs(UnmanagedType.U1)]
public byte board1_scan_multiplier;
[MarshalAs(UnmanagedType.U1)]
public byte board2_scan_multiplier;
[MarshalAs(UnmanagedType.U4)]
public uint time_rtc; /* accumulator for system time in seconds real time clock */
[MarshalAs(UnmanagedType.U4)]
public uint time_fault; /* time in seconds of the triggering fault */
[MarshalAs(UnmanagedType.U4)]
public uint time_sys; /* general timekeeping position */
[MarshalAs(UnmanagedType.I2)]
public short mS_time; /* milliseconds of the triggering fault */
[MarshalAs(UnmanagedType.I2)]
public short flag; /* TRUE if not processed */
[MarshalAs(UnmanagedType.I4)]
public int rcd_sample_count; /* actual count of samples in record(banks * 1024) */
[MarshalAs(UnmanagedType.I2)]
public short start_offset_samples; /* count of samples up to the fault time (500 or 1000) */
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 22)]
public string local_ident;
[MarshalAs(UnmanagedType.U4)]
public uint time_startup; /* time of system startup */
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)]
public string time_zone;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string version_string;
public TIME_ZONE_INFORMATION time_zone_information;
public DateTime FaultTime
{
get
{
return new UnixTimeTag(time_fault).ToDateTime();
}
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct SYS_SETTINGS
{
[MarshalAs(UnmanagedType.I2)]
public short postfault_time;
[MarshalAs(UnmanagedType.I2)]
public short postfault_time_max;
[MarshalAs(UnmanagedType.I2)]
public short prefault_smpls_disp;
[MarshalAs(UnmanagedType.U2)]
public ushort samples_per_second;
[MarshalAs(UnmanagedType.I1)]
public sbyte frequency;
[MarshalAs(UnmanagedType.I1)]
public sbyte vXtndFlt;
[MarshalAs(UnmanagedType.I2)]
public short record_fill;
[MarshalAs(UnmanagedType.I2)]
public short event_groups;
[MarshalAs(UnmanagedType.I2)]
public short analog_groups;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 22)]
public string local_ident;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)]
public string time_zone;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string version_string;
public TIME_ZONE_INFORMATION time_zone_information;
}
[StructLayout(LayoutKind.Sequential)]
public struct A_E_RESULTS
{
[MarshalAs(UnmanagedType.U2)]
public ushort flag_rtn_r;
[MarshalAs(UnmanagedType.U2)]
public ushort flag_fault_r;
[MarshalAs(UnmanagedType.U2)]
public ushort flag_on_r;
[MarshalAs(UnmanagedType.U2)]
public ushort limit_count_r;
[MarshalAs(UnmanagedType.R8)]
public double running_sum;
[MarshalAs(UnmanagedType.U2)]
public ushort rms_counter;
}
// Since this structure includes dynamically sized arrays, we manually parse structure
public struct A_E_RSLTS
{
public short sequence_r;
public ushort flag_r;
public ushort offset_r;
public ushort channel_r;
public ushort mSec_r;
public uint time_fault_r;
public int rcd_sample_count_r; /* length of record in lines */
public A_E_RESULTS[] aer;
public A_E_RSLTS(BinaryReader reader, int channels, int analogGroups)
{
sequence_r = reader.ReadInt16();
flag_r = reader.ReadUInt16();
offset_r = reader.ReadUInt16();
channel_r = reader.ReadUInt16();
mSec_r = reader.ReadUInt16();
time_fault_r = reader.ReadUInt32();
rcd_sample_count_r = reader.ReadInt32();
aer = new A_E_RESULTS[channels * analogGroups];
for (int i = 0; i < aer.Length; i++)
{
aer[i] = reader.ReadStructure<A_E_RESULTS>();
}
}
}
// Since this structure includes dynamically sized arrays, we manually parse structure
public struct ANALOG_GROUP
{
public ushort on; /* if any mask is on */
public ushort flag_high; /* for 1 cycle excess */
public ushort flag_high_end; /* for end of bank test for excess */
public ushort mask_high; /* a 1 indicates the channel is active */
public ushort flag_low; /* for 1 cycle under */
public ushort flag_low_end;
public ushort mask_low;
public ushort flag_slope;
public ushort mask_slope;
public ushort flag_limit;
public ushort mask_limit;
public ushort[] limit_set;
public ushort[] limit_count;
public ushort[] sign_flag;
public short[] high_set;
public ushort[] avg_phasor;
public ushort[] low_set;
public ushort[] triggerdelayunder;
public ushort[] avg_phasor_count;
public short[][] cycle_value;
public short[] cycle_compare;
public short[] slope_rate;
public ANALOG_GROUP(BinaryReader reader, int channels)
{
limit_set = new ushort[channels];
limit_count = new ushort[channels];
sign_flag = new ushort[channels];
high_set = new short[channels];
avg_phasor = new ushort[channels];
low_set = new ushort[channels];
triggerdelayunder = new ushort[channels];
avg_phasor_count = new ushort[channels];
cycle_value = new short[channels][];
cycle_compare = new short[channels];
slope_rate = new short[channels];
for (int i = 0; i < cycle_value.Length; i++)
{
cycle_value[i] = new short[2];
}
on = reader.ReadUInt16();
flag_high = reader.ReadUInt16();
flag_high_end = reader.ReadUInt16();
mask_high = reader.ReadUInt16();
flag_low = reader.ReadUInt16();
flag_low_end = reader.ReadUInt16();
mask_low = reader.ReadUInt16();
flag_slope = reader.ReadUInt16();
mask_slope = reader.ReadUInt16();
flag_limit = reader.ReadUInt16();
mask_limit = reader.ReadUInt16();
for (int i = 0; i < limit_set.Length; i++)
{
limit_set[i] = reader.ReadUInt16();
}
for (int i = 0; i < limit_count.Length; i++)
{
limit_count[i] = reader.ReadUInt16();
}
for (int i = 0; i < sign_flag.Length; i++)
{
sign_flag[i] = reader.ReadUInt16();
}
for (int i = 0; i < high_set.Length; i++)
{
high_set[i] = reader.ReadInt16();
}
for (int i = 0; i < avg_phasor.Length; i++)
{
avg_phasor[i] = reader.ReadUInt16();
}
for (int i = 0; i < low_set.Length; i++)
{
low_set[i] = reader.ReadUInt16();
}
for (int i = 0; i < triggerdelayunder.Length; i++)
{
triggerdelayunder[i] = reader.ReadUInt16();
}
for (int i = 0; i < avg_phasor_count.Length; i++)
{
avg_phasor_count[i] = reader.ReadUInt16();
}
for (int i = 0; i < cycle_value.Length; i++)
{
for (int j = 0; j < cycle_value[i].Length; j++)
{
cycle_value[i][j] = reader.ReadInt16();
}
}
for (int i = 0; i < cycle_compare.Length; i++)
{
cycle_compare[i] = reader.ReadInt16();
}
for (int i = 0; i < slope_rate.Length; i++)
{
slope_rate[i] = reader.ReadInt16();
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct EVENT_GROUP
{
[MarshalAs(UnmanagedType.U2)]
public ushort on; /* the or of mask_rtn and mask_fault */
[MarshalAs(UnmanagedType.U2)]
public ushort flag_rtn; /* set when in fault at end of time */
[MarshalAs(UnmanagedType.U2)]
public ushort mask_rtn;
[MarshalAs(UnmanagedType.U2)]
public ushort flag_fault;
[MarshalAs(UnmanagedType.U2)]
public ushort mask_fault;
[MarshalAs(UnmanagedType.U2)]
public ushort previous;
[MarshalAs(UnmanagedType.U2)]
public ushort dir_change;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IDENTSTRING
{
[MarshalAs(UnmanagedType.I2)]
public short length;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 163)]
public string value;
}
// Since this structure includes dynamically sized arrays, we manually parse structure
public struct BREAKER_TRIP_TIMES
{
public float[] breaker_trip_time;
public float[] accumulated_breaker_trip_time;
public float[] zero_trip_percent;
public float[] zero_trip_time;
public BREAKER_TRIP_TIMES(BinaryReader reader, int channels, int analogGroups)
{
breaker_trip_time = ReadArray(reader, channels, analogGroups);
accumulated_breaker_trip_time = ReadArray(reader, channels, analogGroups);
zero_trip_percent = ReadArray(reader, channels, analogGroups);
zero_trip_time = ReadArray(reader, channels, analogGroups);
}
private static float[] ReadArray(BinaryReader reader, int channels, int analogGroups)
{
float[] floats = new float[channels * analogGroups];
for (int i = 0; i < floats.Length; i++)
{
floats[i] = reader.ReadSingle();
}
return floats;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ANLG_CHNL_NEW
{
private const int TYPE_LEN = 1;
private const int TITLE_LEN = 20;
private const int CHANLNUM_LEN = 2;
private const int PRIMARY_LEN = 6;
private const int SECONDARY_LEN = 4;
private const int CT_RATIO_LEN = 4;
private const int SHUNT_LEN = 4;
private const int LIMIT_SET_LEN = 3;
private const int SET_LEN = 3;
private const int ON_OFF_LEN = 3;
private const int SCALE_FACTOR_LEN = 2;
private const int ZERO_LINE_LEN = 4;
private const int MULT_FACT_LEN = 8;
private const int CAL_LEN = 4;
private const int PEAK_CAL_LEN = 4;
Lines 1–500 of 1013. Load more
//****************************************************************************************************** // ControlFileStructures.cs - Gbtc // // Copyright © 2014, 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: // ---------------------------------------------------------------------------------------------------- // 08/05/2014 - J. Ritchie Carroll // Generated original version of source code. // //****************************************************************************************************** using System; using System.IO; using System.Runtime.InteropServices; // ReSharper disable FieldCanBeMadeReadOnly.Local // ReSharper disable MemberCanBePrivate.Local // ReSharper disable NotAccessedField.Local // ReSharper disable UnusedField.Compiler namespace GSF.EMAX { // All control structures are little-endian encoded // All control structures only occur once within the control file public enum DataSize : byte { Bits12 = 0xAF, Bits16 = 0xAB } public enum StructureType : ushort { EndOfStructures = 0x0000, SYSTEM_PARAMETERS = 0x0001, A_E_RSLTS = 0x0003, ANALOG_GROUP = 0x0004, EVENT_GROUP = 0x0005, ANLG_CHNL_NEW = 0x0006, EVNT_CHNL_NEW = 0x0007, ANLG_CHNLS = 0x0008, SYS_SETTINGS = 0x000B, SHORT_HEADER = 0x000D, FAULT_HEADER = 0x010D, // (with RMS) EVENT_DISPLAY = 0x000E, IDENTSTRING = 0x0010, A_SELECTION = 0x0040, E_GROUP_SELECT = 0x0041, PHASOR_GROUP = 0x0042, LINE_CONSTANTS = 0x0043, LINE_NAMES = 0x0044, FAULT_LOCATION = 0x0045, SENS_RSLTS = 0x0050, SEQUENCE_CHANNELS = 0x0051, TPwrRcd = 0x0052, BoardAnalogEventChannels = 0x0060, BREAKER_TRIP_TIMES = 0x0061, Unknown = 0xFFFF } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct CTL_HEADER { [MarshalAs(UnmanagedType.U2)] public ushort id; // System ID [MarshalAs(UnmanagedType.U4)] public uint time; // Time of CTL file creation [MarshalAs(UnmanagedType.U1)] public byte num_of_structs; // Number of Structures in CTL file public DateTime Timestamp { get { return new UnixTimeTag(time).ToDateTime(); } } } public struct CTL_FILE_STRUCT { public StructureType type; public uint offset; public CTL_FILE_STRUCT(BinaryReader reader) { ushort ushortValue = BigEndian.ToUInt16(reader.ReadBytes(2), 0); if (!Enum.IsDefined(typeof(StructureType), ushortValue)) type = StructureType.Unknown; else type = (StructureType)ushortValue; offset = reader.ReadUInt32() >> 8; } } [StructLayout(LayoutKind.Sequential, Pack = 2)] public struct SYSTEMTIME { [MarshalAs(UnmanagedType.U2)] public ushort Year; [MarshalAs(UnmanagedType.U2)] public ushort Month; [MarshalAs(UnmanagedType.U2)] public ushort DayOfWeek; [MarshalAs(UnmanagedType.U2)] public ushort Day; [MarshalAs(UnmanagedType.U2)] public ushort Hour; [MarshalAs(UnmanagedType.U2)] public ushort Minute; [MarshalAs(UnmanagedType.U2)] public ushort Second; [MarshalAs(UnmanagedType.U2)] public ushort Milliseconds; public SYSTEMTIME(DateTime dt) { dt = dt.ToUniversalTime(); // SetSystemTime expects the SYSTEMTIME in UTC Year = (ushort)dt.Year; Month = (ushort)dt.Month; DayOfWeek = (ushort)dt.DayOfWeek; Day = (ushort)dt.Day; Hour = (ushort)dt.Hour; Minute = (ushort)dt.Minute; Second = (ushort)dt.Second; Milliseconds = (ushort)dt.Millisecond; } } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct TIME_ZONE_INFORMATION { [MarshalAs(UnmanagedType.I4)] public Int32 Bias; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string StandardName; public SYSTEMTIME StandardDate; [MarshalAs(UnmanagedType.I4)] public Int32 StandardBias; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string DaylightName; public SYSTEMTIME DaylightDate; [MarshalAs(UnmanagedType.I4)] public Int32 DaylightBias; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct SYSTEM_PARAMETERS { [MarshalAs(UnmanagedType.U2)] public ushort samples_per_second; [MarshalAs(UnmanagedType.I1)] public sbyte frequency; [MarshalAs(UnmanagedType.I1)] public sbyte vXtndFlt; [MarshalAs(UnmanagedType.I2)] public short channel_offset; [MarshalAs(UnmanagedType.I2)] public short prefault_samples; [MarshalAs(UnmanagedType.I2)] public short prefault_smpls_disp; /* set for the number to be displayed */ [MarshalAs(UnmanagedType.I4)] public int postfault_samples; /* normal single length record from samples per second times postfault_time */ [MarshalAs(UnmanagedType.I4)] public int postfault_samples_max; /* maximum length of extended records times postfault_time_max */ [MarshalAs(UnmanagedType.I2)] public short postfault_time; /* normal minimum record included in 32kword record */ [MarshalAs(UnmanagedType.I2)] public short postfault_time_max; [MarshalAs(UnmanagedType.I2)] public short record_fill; /* 1 = fill 2=double_pixel 4 = dot_join (or for combinations 8 = polarity inversion */ [MarshalAs(UnmanagedType.I2)] public short event_groups; [MarshalAs(UnmanagedType.I2)] public short analog_groups; [MarshalAs(UnmanagedType.I2)] public short sequence; /* fault number sequence */ [MarshalAs(UnmanagedType.I2)] public short time_flag1; /* (determines if irig is set to on) */ [MarshalAs(UnmanagedType.U1)] public byte board1_scan_multiplier; [MarshalAs(UnmanagedType.U1)] public byte board2_scan_multiplier; [MarshalAs(UnmanagedType.U4)] public uint time_rtc; /* accumulator for system time in seconds real time clock */ [MarshalAs(UnmanagedType.U4)] public uint time_fault; /* time in seconds of the triggering fault */ [MarshalAs(UnmanagedType.U4)] public uint time_sys; /* general timekeeping position */ [MarshalAs(UnmanagedType.I2)] public short mS_time; /* milliseconds of the triggering fault */ [MarshalAs(UnmanagedType.I2)] public short flag; /* TRUE if not processed */ [MarshalAs(UnmanagedType.I4)] public int rcd_sample_count; /* actual count of samples in record(banks * 1024) */ [MarshalAs(UnmanagedType.I2)] public short start_offset_samples; /* count of samples up to the fault time (500 or 1000) */ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 22)] public string local_ident; [MarshalAs(UnmanagedType.U4)] public uint time_startup; /* time of system startup */ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)] public string time_zone; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string version_string; public TIME_ZONE_INFORMATION time_zone_information; public DateTime FaultTime { get { return new UnixTimeTag(time_fault).ToDateTime(); } } } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct SYS_SETTINGS { [MarshalAs(UnmanagedType.I2)] public short postfault_time; [MarshalAs(UnmanagedType.I2)] public short postfault_time_max; [MarshalAs(UnmanagedType.I2)] public short prefault_smpls_disp; [MarshalAs(UnmanagedType.U2)] public ushort samples_per_second; [MarshalAs(UnmanagedType.I1)] public sbyte frequency; [MarshalAs(UnmanagedType.I1)] public sbyte vXtndFlt; [MarshalAs(UnmanagedType.I2)] public short record_fill; [MarshalAs(UnmanagedType.I2)] public short event_groups; [MarshalAs(UnmanagedType.I2)] public short analog_groups; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 22)] public string local_ident; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)] public string time_zone; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string version_string; public TIME_ZONE_INFORMATION time_zone_information; } [StructLayout(LayoutKind.Sequential)] public struct A_E_RESULTS { [MarshalAs(UnmanagedType.U2)] public ushort flag_rtn_r; [MarshalAs(UnmanagedType.U2)] public ushort flag_fault_r; [MarshalAs(UnmanagedType.U2)] public ushort flag_on_r; [MarshalAs(UnmanagedType.U2)] public ushort limit_count_r; [MarshalAs(UnmanagedType.R8)] public double running_sum; [MarshalAs(UnmanagedType.U2)] public ushort rms_counter; } // Since this structure includes dynamically sized arrays, we manually parse structure public struct A_E_RSLTS { public short sequence_r; public ushort flag_r; public ushort offset_r; public ushort channel_r; public ushort mSec_r; public uint time_fault_r; public int rcd_sample_count_r; /* length of record in lines */ public A_E_RESULTS[] aer; public A_E_RSLTS(BinaryReader reader, int channels, int analogGroups) { sequence_r = reader.ReadInt16(); flag_r = reader.ReadUInt16(); offset_r = reader.ReadUInt16(); channel_r = reader.ReadUInt16(); mSec_r = reader.ReadUInt16(); time_fault_r = reader.ReadUInt32(); rcd_sample_count_r = reader.ReadInt32(); aer = new A_E_RESULTS[channels * analogGroups]; for (int i = 0; i < aer.Length; i++) { aer[i] = reader.ReadStructure<A_E_RESULTS>(); } } } // Since this structure includes dynamically sized arrays, we manually parse structure public struct ANALOG_GROUP { public ushort on; /* if any mask is on */ public ushort flag_high; /* for 1 cycle excess */ public ushort flag_high_end; /* for end of bank test for excess */ public ushort mask_high; /* a 1 indicates the channel is active */ public ushort flag_low; /* for 1 cycle under */ public ushort flag_low_end; public ushort mask_low; public ushort flag_slope; public ushort mask_slope; public ushort flag_limit; public ushort mask_limit; public ushort[] limit_set; public ushort[] limit_count; public ushort[] sign_flag; public short[] high_set; public ushort[] avg_phasor; public ushort[] low_set; public ushort[] triggerdelayunder; public ushort[] avg_phasor_count; public short[][] cycle_value; public short[] cycle_compare; public short[] slope_rate; public ANALOG_GROUP(BinaryReader reader, int channels) { limit_set = new ushort[channels]; limit_count = new ushort[channels]; sign_flag = new ushort[channels]; high_set = new short[channels]; avg_phasor = new ushort[channels]; low_set = new ushort[channels]; triggerdelayunder = new ushort[channels]; avg_phasor_count = new ushort[channels]; cycle_value = new short[channels][]; cycle_compare = new short[channels]; slope_rate = new short[channels]; for (int i = 0; i < cycle_value.Length; i++) { cycle_value[i] = new short[2]; } on = reader.ReadUInt16(); flag_high = reader.ReadUInt16(); flag_high_end = reader.ReadUInt16(); mask_high = reader.ReadUInt16(); flag_low = reader.ReadUInt16(); flag_low_end = reader.ReadUInt16(); mask_low = reader.ReadUInt16(); flag_slope = reader.ReadUInt16(); mask_slope = reader.ReadUInt16(); flag_limit = reader.ReadUInt16(); mask_limit = reader.ReadUInt16(); for (int i = 0; i < limit_set.Length; i++) { limit_set[i] = reader.ReadUInt16(); } for (int i = 0; i < limit_count.Length; i++) { limit_count[i] = reader.ReadUInt16(); } for (int i = 0; i < sign_flag.Length; i++) { sign_flag[i] = reader.ReadUInt16(); } for (int i = 0; i < high_set.Length; i++) { high_set[i] = reader.ReadInt16(); } for (int i = 0; i < avg_phasor.Length; i++) { avg_phasor[i] = reader.ReadUInt16(); } for (int i = 0; i < low_set.Length; i++) { low_set[i] = reader.ReadUInt16(); } for (int i = 0; i < triggerdelayunder.Length; i++) { triggerdelayunder[i] = reader.ReadUInt16(); } for (int i = 0; i < avg_phasor_count.Length; i++) { avg_phasor_count[i] = reader.ReadUInt16(); } for (int i = 0; i < cycle_value.Length; i++) { for (int j = 0; j < cycle_value[i].Length; j++) { cycle_value[i][j] = reader.ReadInt16(); } } for (int i = 0; i < cycle_compare.Length; i++) { cycle_compare[i] = reader.ReadInt16(); } for (int i = 0; i < slope_rate.Length; i++) { slope_rate[i] = reader.ReadInt16(); } } } [StructLayout(LayoutKind.Sequential)] public struct EVENT_GROUP { [MarshalAs(UnmanagedType.U2)] public ushort on; /* the or of mask_rtn and mask_fault */ [MarshalAs(UnmanagedType.U2)] public ushort flag_rtn; /* set when in fault at end of time */ [MarshalAs(UnmanagedType.U2)] public ushort mask_rtn; [MarshalAs(UnmanagedType.U2)] public ushort flag_fault; [MarshalAs(UnmanagedType.U2)] public ushort mask_fault; [MarshalAs(UnmanagedType.U2)] public ushort previous; [MarshalAs(UnmanagedType.U2)] public ushort dir_change; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct IDENTSTRING { [MarshalAs(UnmanagedType.I2)] public short length; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 163)] public string value; } // Since this structure includes dynamically sized arrays, we manually parse structure public struct BREAKER_TRIP_TIMES { public float[] breaker_trip_time; public float[] accumulated_breaker_trip_time; public float[] zero_trip_percent; public float[] zero_trip_time; public BREAKER_TRIP_TIMES(BinaryReader reader, int channels, int analogGroups) { breaker_trip_time = ReadArray(reader, channels, analogGroups); accumulated_breaker_trip_time = ReadArray(reader, channels, analogGroups); zero_trip_percent = ReadArray(reader, channels, analogGroups); zero_trip_time = ReadArray(reader, channels, analogGroups); } private static float[] ReadArray(BinaryReader reader, int channels, int analogGroups) { float[] floats = new float[channels * analogGroups]; for (int i = 0; i < floats.Length; i++) { floats[i] = reader.ReadSingle(); } return floats; } } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct ANLG_CHNL_NEW { private const int TYPE_LEN = 1; private const int TITLE_LEN = 20; private const int CHANLNUM_LEN = 2; private const int PRIMARY_LEN = 6; private const int SECONDARY_LEN = 4; private const int CT_RATIO_LEN = 4; private const int SHUNT_LEN = 4; private const int LIMIT_SET_LEN = 3; private const int SET_LEN = 3; private const int ON_OFF_LEN = 3; private const int SCALE_FACTOR_LEN = 2; private const int ZERO_LINE_LEN = 4; private const int MULT_FACT_LEN = 8; private const int CAL_LEN = 4; private const int PEAK_CAL_LEN = 4;