private DateTime ParseTimestamp(ushort[] clockWords) { if ((object)clockWords == null) { throw new NullReferenceException("Clock words array was null - cannot parse timestamp"); } if (clockWords.Length != 4) { throw new InvalidOperationException("Clock words array must have four values - cannot parse timestamp"); } int days, hours, minutes, seconds, milliseconds, microseconds; byte highByte, lowByte; highByte = clockWords[0].HighByte(); lowByte = clockWords[0].LowByte(); days = highByte.HighNibble() * 100 + highByte.LowNibble() * 10 + lowByte.HighNibble(); hours = lowByte.LowNibble() * 10; highByte = clockWords[1].HighByte(); lowByte = clockWords[1].LowByte(); hours += highByte.HighNibble(); minutes = highByte.LowNibble() * 10 + lowByte.HighNibble(); seconds = lowByte.LowNibble() * 10; highByte = clockWords[2].HighByte(); lowByte = clockWords[2].LowByte(); seconds += highByte.HighNibble(); milliseconds = highByte.LowNibble() * 100 + lowByte.HighNibble() * 10 + lowByte.LowNibble(); if (milliseconds > 999) { milliseconds = 0; } highByte = clockWords[3].HighByte(); lowByte = clockWords[3].LowByte(); microseconds = highByte.HighNibble() * 100 + highByte.LowNibble() * 10 + lowByte.HighNibble(); if (microseconds > 999) { microseconds = 0; } return(m_baseTime .AddDays(days - 1) // Base time starts at day one, so we subtract one for target day .AddHours(hours) .AddMinutes(minutes) .AddSeconds(seconds) .AddMilliseconds(milliseconds) .AddTicks(Ticks.FromMicroseconds(microseconds))); }
private int ReadTimestamp(byte[] buffer) { int index = 0; // Read sample index uint sample = LittleEndian.ToUInt32(buffer, index); index += 4; // Get timestamp of this record Timestamp = DateTime.MinValue; // If sample rates are defined, this is the preferred method for timestamp resolution if (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) { 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 (Timestamp == DateTime.MinValue) { Timestamp = new DateTime(Ticks.FromMicroseconds(microseconds * m_schema.TimeFactor) + m_schema.StartTime.Value); } // Apply timestamp offset to restore UTC timezone if (AdjustToUTC) { TimeOffset offset = Schema.TimeCode ?? new TimeOffset(); Timestamp = new DateTime(Timestamp.Ticks + offset.TickOffset, DateTimeKind.Utc); } return(index); }
// 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); }
// Handle ASCII file read private bool ReadNextAscii() { if ((object)m_fileReaders == null) { m_fileReaders = new StreamReader[m_fileStreams.Length]; for (int i = 0; i < m_fileStreams.Length; i++) { m_fileReaders[i] = new StreamReader(m_fileStreams[i]); } } // Read next line of record values StreamReader reader = m_fileReaders[m_streamIndex]; string line = reader.ReadLine(); string[] elems = ((object)line != null) ? line.Split(',') : null; // See if we have reached the end of this file if ((object)elems == null || elems.Length != m_values.Length + 2) { if (reader.EndOfStream) { m_streamIndex++; // There is more to read if there is another file return(m_streamIndex < m_fileStreams.Length && ReadNext()); } throw new InvalidOperationException("COMTRADE schema does not match number of elements found in ASCII data file."); } // Parse row of data uint sample = uint.Parse(elems[0]); // 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); } } // Fall back on specified microsecond time if (m_timestamp == DateTime.MinValue) { m_timestamp = new DateTime(Ticks.FromMicroseconds(uint.Parse(elems[1]) * m_schema.TimeFactor) + m_schema.StartTime.Value); } // Parse all record values for (int i = 0; i < m_values.Length; i++) { m_values[i] = double.Parse(elems[i + 2]); if (i < m_schema.AnalogChannels.Length) { m_values[i] *= m_schema.AnalogChannels[i].Multiplier; m_values[i] += m_schema.AnalogChannels[i].Adder; } } return(true); }
// Handle ASCII file read private bool ReadNextAscii() { // For ASCII files, we wrap file streams with file readers if ((object)m_fileReaders == null) { m_fileReaders = new StreamReader[m_fileStreams.Length]; for (int i = 0; i < m_fileStreams.Length; i++) { m_fileReaders[i] = new StreamReader(m_fileStreams[i]); } } // Read next line of record values StreamReader reader = m_fileReaders[m_streamIndex]; string line = reader.ReadLine(); string[] elems = ((object)line != null) ? line.Split(',') : null; // See if we have reached the end of this file if ((object)elems == null || elems.Length != Values.Length + 2) { if (reader.EndOfStream) { return(ReadNextFile()); } throw new InvalidOperationException("COMTRADE schema does not match number of elements found in ASCII data file."); } // Parse row of data uint sample = uint.Parse(elems[0]); // Get timestamp of this record Timestamp = DateTime.MinValue; // If sample rates are defined, this is the preferred method for timestamp resolution if (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) { Timestamp = new DateTime(Ticks.FromSeconds(1.0D / sampleRate.Rate * sample) + m_schema.StartTime.Value); } } // Fall back on specified microsecond time if (Timestamp == DateTime.MinValue) { Timestamp = new DateTime(Ticks.FromMicroseconds(uint.Parse(elems[1]) * m_schema.TimeFactor) + m_schema.StartTime.Value); } // Apply timestamp offset to restore UTC timezone if (AdjustToUTC) { TimeOffset offset = Schema.TimeCode ?? new TimeOffset(); Timestamp = new DateTime(Timestamp.Ticks + offset.TickOffset, DateTimeKind.Utc); } // Parse all record values for (int i = 0; i < Values.Length; i++) { Values[i] = double.Parse(elems[i + 2]); if (i < m_schema.AnalogChannels.Length) { Values[i] = AdjustValue(Values[i], i); } } return(true); }