public static byte[] GetHeaderBytes(uint unknown, uint lineCount) { var bytes = new byte[8]; BitExtensions.ToBytesBigEndian(unknown, bytes); BitExtensions.ToBytesBigEndian(lineCount, bytes, 4); return(bytes); }
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); }
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; } } }
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); }
/// <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()); }
// 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); }
/// <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); }