948 lines · 34.2 KB · C#
RawDownload
//******************************************************************************************************
//  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 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:
//  ----------------------------------------------------------------------------------------------------
//  08/05/2014 - J. Ritchie Carroll
//       Generated original version of source code.
//
//******************************************************************************************************

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

// ReSharper disable FieldCanBeMadeReadOnly.Local
// ReSharper disable MemberCanBePrivate.Local
// ReSharper disable NotAccessedField.Local
// ReSharper disable UnusedField.Compiler
namespace GSF.EMAX
{
    // TODO: Have to know if these control structures are big-endian or little-endian encoded... Cannot use marshaling functions if big-endian...
    // TODO: Need to know which structures will be for multiple entries in the definition and which ones will be singletons

    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
    }

    public struct CTL_HEADER
    {
        public UInt24 id;               // System ID
        public uint time;               // Time of CTL file creation
        public ushort sp_offset;        // System parameters offset

        public CTL_HEADER(BinaryReader reader)
        {
            id = BigEndian.ToUInt24(reader.ReadBytes(3), 0);
            time = BigEndian.ToUInt32(reader.ReadBytes(4), 0);
            sp_offset = BigEndian.ToUInt16(reader.ReadBytes(2), 0);

            // Skip padding
            reader.ReadBytes(2);
        }

        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;

            //throw new InvalidOperationException("Invalid EMAX control file structure type encountered: 0x" + ushortValue.ToString("X").PadLeft(4, '0'));

            offset = reader.ReadUInt32() >> 8;

            //Debug.WriteLine("{0} [0x{1}] => Offset = 0x{2}",
            //    type,
            //    ushortValue.ToString("X").PadLeft(4, '0'),
            //    offset.ToString("X").PadLeft(8, '0'));
        }
    }

    [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;
    }

    [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();            // BigEndian.ToInt16(reader.ReadBytes(2), 0);
            flag_r = reader.ReadUInt16();               // BigEndian.ToUInt16(reader.ReadBytes(2), 0);
            offset_r = reader.ReadUInt16();             // BigEndian.ToUInt16(reader.ReadBytes(2), 0);
            channel_r = reader.ReadUInt16();            // BigEndian.ToUInt16(reader.ReadBytes(2), 0);
            mSec_r = reader.ReadUInt16();               // BigEndian.ToUInt16(reader.ReadBytes(2), 0);
            time_fault_r = reader.ReadUInt32();         // BigEndian.ToUInt32(reader.ReadBytes(4), 0);
            rcd_sample_count_r = reader.ReadInt32();    // BigEndian.ToInt32(reader.ReadBytes(4), 0);

            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;

Lines 1–500 of 948.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t