Example #1
0
            public static byte[] GetHeaderBytes(uint unknown, uint lineCount)
            {
                var bytes = new byte[8];

                BitExtensions.ToBytesBigEndian(unknown, bytes);
                BitExtensions.ToBytesBigEndian(lineCount, bytes, 4);
                return(bytes);
            }
Example #2
0
            public static byte[] GetBytes(ushort StartY, ushort EndY, ushort StartX)
            {
                var bytes = new byte[6];

                BitExtensions.ToBytesBigEndian(StartY, bytes);
                BitExtensions.ToBytesBigEndian(EndY, bytes, 2);
                BitExtensions.ToBytesBigEndian(StartX, bytes, 4);
                return(bytes);
            }
Example #3
0
        private void ReadDigitalValues(byte[] buffer, int index)
        {
            int valueIndex = m_schema.AnalogChannels.Length;

            // Parse all digital record values
            for (int i = 0; i < m_schema.DigitalWords; i++)
            {
                // Read next digital word
                ushort digitalWord = LittleEndian.ToUInt16(buffer, index);
                index += 2;

                // Distribute each bit of digital word through next 16 digital values
                for (int j = 0; j < 16 && valueIndex < Values.Length; j++, valueIndex++)
                {
                    Values[valueIndex] = digitalWord.CheckBits(BitExtensions.BitVal(j)) ? 1.0D : 0.0D;
                }
            }
        }
Example #4
0
        internal static IrrigationValveTable Parse(byte[] message)
        {
            var valveTable = new IrrigationValveTable
            {
                TableId = message[2],
                Items   = new List <IrrigationValveTableItem>()
            };
            int i = 3;

            while (message.Length > i)
            {
                var tableItem = new IrrigationValveTableItem
                {
                    ValveId  = message[i],
                    Duration = BitExtensions.FromBigEndianBytes(new[] { message[i + 1], message[i + 2] })
                };
                valveTable.Items.Add(tableItem);
                i += 3;
            }
            return(valveTable);
        }
Example #5
0
        /// <summary>
        /// Writes next COMTRADE record in ASCII format.
        /// </summary>
        /// <param name="output">Destination stream.</param>
        /// <param name="schema">Source schema.</param>
        /// <param name="timestamp">Record timestamp (implicitly castable as <see cref="DateTime"/>).</param>
        /// <param name="values">Values to write - 16-bit digitals should exist as a word in an individual double value, method will write out bits.</param>
        /// <param name="sample">User incremented sample index.</param>
        /// <param name="injectFracSecValue">Determines if FRACSEC value should be automatically injected into stream as first digital - defaults to <c>true</c>.</param>
        /// <param name="fracSecValue">FRACSEC value to inject into output stream - defaults to 0x0000.</param>
        /// <remarks>
        /// This function is primarily intended to write COMTRADE ASCII data records based on synchrophasor data
        /// (see Annex H: Schema for Phasor Data 2150 Using the COMTRADE File Standard in IEEE C37.111-2010),
        /// it may be necessary to manually write records for other COMTRADE needs (e.g., non 16-bit digitals).
        /// </remarks>
        public static void WriteNextRecordAscii(StreamWriter output, Schema schema, Ticks timestamp, double[] values, uint sample, bool injectFracSecValue = true, ushort fracSecValue = 0x0000)
        {
            // Make timestamp relative to beginning of file
            timestamp -= schema.StartTime.Value;

            uint          microseconds   = (uint)(timestamp.ToMicroseconds() / schema.TimeFactor);
            StringBuilder line           = new StringBuilder();
            bool          isFirstDigital = true;

            line.Append(sample);
            line.Append(',');
            line.Append(microseconds);

            for (int i = 0; i < values.Length; i++)
            {
                double value = values[i];

                if (i < schema.AnalogChannels.Length)
                {
                    value -= schema.AnalogChannels[i].Adder;
                    value /= schema.AnalogChannels[i].Multiplier;

                    line.Append(',');
                    line.Append(value.ToString(CultureInfo.InvariantCulture));
                }
                else
                {
                    if (isFirstDigital)
                    {
                        // Handle automatic injection of IEEE C37.118 FRACSEC digital value if requested
                        isFirstDigital = false;

                        if (injectFracSecValue)
                        {
                            for (int j = 0; j < 16; j++)
                            {
                                line.Append(',');
                                line.Append(fracSecValue.CheckBits(BitExtensions.BitVal(j)) ? 1 : 0);
                            }
                        }
                    }

                    ushort digitalWord = (ushort)value;

                    for (int j = 0; j < 16; j++)
                    {
                        line.Append(',');
                        line.Append(digitalWord.CheckBits(BitExtensions.BitVal(j)) ? 1 : 0);
                    }
                }
            }

            // Make sure FRACSEC values are injected
            if (isFirstDigital && injectFracSecValue)
            {
                for (int j = 0; j < 16; j++)
                {
                    line.Append(',');
                    line.Append(fracSecValue.CheckBits(BitExtensions.BitVal(j)) ? 1 : 0);
                }
            }

            output.WriteLine(line.ToString());
        }
Example #6
0
        // Handle binary file read
        private bool ReadNextBinary()
        {
            FileStream currentFile  = m_fileStreams[m_streamIndex];
            int        recordLength = m_schema.BinaryRecordLength;

            byte[] buffer = new byte[recordLength];

            // Read next record from file
            int bytesRead = currentFile.Read(buffer, 0, recordLength);

            // See if we have reached the end of this file
            if (bytesRead == 0)
            {
                m_streamIndex++;

                // There is more to read if there is another file
                return(m_streamIndex < m_fileStreams.Length && ReadNext());
            }

            if (bytesRead == recordLength)
            {
                int index = 0;

                // Read sample index
                uint sample = LittleEndian.ToUInt32(buffer, index);
                index += 4;

                // Get timestamp of this record
                m_timestamp = DateTime.MinValue;

                // If sample rates are defined, this is the preferred method for timestamp resolution
                if (m_inferTimeFromSampleRates && m_schema.SampleRates.Length > 0)
                {
                    // Find rate for given sample
                    SampleRate sampleRate = m_schema.SampleRates.LastOrDefault(sr => sample <= sr.EndSample);

                    if (sampleRate.Rate > 0.0D)
                    {
                        m_timestamp = new DateTime(Ticks.FromSeconds(1.0D / sampleRate.Rate * sample) + m_schema.StartTime.Value);
                    }
                }

                // Read microsecond timestamp
                uint microseconds = LittleEndian.ToUInt32(buffer, index);
                index += 4;

                // Fall back on specified microsecond time
                if (m_timestamp == DateTime.MinValue)
                {
                    m_timestamp = new DateTime(Ticks.FromMicroseconds(microseconds * m_schema.TimeFactor) + m_schema.StartTime.Value);
                }

                // Parse all analog record values
                for (int i = 0; i < m_schema.AnalogChannels.Length; i++)
                {
                    // Read next value
                    m_values[i] = LittleEndian.ToInt16(buffer, index) * m_schema.AnalogChannels[i].Multiplier + m_schema.AnalogChannels[i].Adder;
                    index      += 2;
                }

                int    valueIndex   = m_schema.AnalogChannels.Length;
                int    digitalWords = m_schema.DigitalWords;
                ushort digitalWord;

                for (int i = 0; i < digitalWords; i++)
                {
                    // Read next digital word
                    digitalWord = LittleEndian.ToUInt16(buffer, index);
                    index      += 2;

                    // Distribute each bit of digital word through next 16 digital values
                    for (int j = 0; j < 16 && valueIndex < m_values.Length; j++, valueIndex++)
                    {
                        m_values[valueIndex] = digitalWord.CheckBits(BitExtensions.BitVal(j)) ? 1.0D : 0.0D;
                    }
                }
            }
            else
            {
                throw new InvalidOperationException("Failed to read enough bytes from COMTRADE file for a record as defined by schema - possible schema/data file mismatch or file corruption.");
            }

            return(true);
        }
Example #7
0
        /// <summary>
        /// Get an object from a byte array
        /// </summary>
        /// <param name="type">The type of the object</param>
        /// <param name="array">The byte array to decode from</param>
        /// <param name="shift">The shift to apply to the array</param>
        /// <returns>A decoded object</returns>
        /// <exception cref="ArgumentOutOfRangeException">If the type of the object is not managed</exception>
        protected static object FromBytes(Type type, byte[] array, ref int shift)
        {
            switch (Type.GetTypeCode(type))
            {
            case TypeCode.Boolean:
                return(BitExtensions.ToBool(array, ref shift));

            case TypeCode.Byte:
                return(BitExtensions.ToByte(array, ref shift));

            case TypeCode.Char:
                return(BitExtensions.ToChar(array, ref shift));

            case TypeCode.Double:
                return(BitExtensions.ToDouble(array, ref shift));

            case TypeCode.Int16:
                return(BitExtensions.ToShort(array, ref shift));

            case TypeCode.Int32:
                return(BitExtensions.ToInt(array, ref shift));

            case TypeCode.Int64:
                return(BitExtensions.ToLong(array, ref shift));

            case TypeCode.Single:
                return(BitExtensions.ToFloat(array, ref shift));

            case TypeCode.UInt16:
                return(BitExtensions.ToUShort(array, ref shift));

            case TypeCode.UInt32:
                return(BitExtensions.ToUInt(array, ref shift));

            case TypeCode.UInt64:
                return(BitExtensions.ToULong(array, ref shift));

            case TypeCode.DateTime:
                break;

            case TypeCode.DBNull:
                break;

            case TypeCode.Decimal:
                break;

            case TypeCode.Empty:
                break;

            case TypeCode.Object:
                break;

            case TypeCode.SByte:
                break;

            case TypeCode.String:
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            return(null);
        }