init
This commit is contained in:
758
Common/DTS.Common.Serialization/TDMS/TDMS.File.Writer.cs
Normal file
758
Common/DTS.Common.Serialization/TDMS/TDMS.File.Writer.cs
Normal file
@@ -0,0 +1,758 @@
|
||||
/*
|
||||
* TDMS.File.Writer.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DTS.Serialization.TDMS
|
||||
{
|
||||
// *** see TDMS.File.cs ***
|
||||
public partial class File
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Utility object for serializing <see cref="DTS.Serialization.Test"/>s to disk
|
||||
/// in the TDMS
|
||||
/// </summary>
|
||||
///
|
||||
public class Writer : Writer<File>, IWriter<Test>
|
||||
{
|
||||
public File WriterParent { get; set; }
|
||||
public Common.ISO.TestPlan TestPlan { get; set; } = null;
|
||||
public string ExtensionPrefix { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Initialize an instance of the TDMS.File.Writer class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="fileType">
|
||||
/// The associated <see cref="DTS.Serialization.TDMS.File"/> object.
|
||||
/// </param>
|
||||
///
|
||||
internal Writer(File fileType, int encoding)
|
||||
: base(fileType, encoding)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the specified test to the specified pathname.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="pathname">
|
||||
/// The <see cref="string"/> pathname to which the specified test should be serialized.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="test">
|
||||
/// The <see cref="DTS.Serialization.Test"/> to be written out.
|
||||
/// </param>
|
||||
///
|
||||
public void Write(string pathname, string id, Test test, bool bFiltering, bool includeGroupNameInISOExport, double minStartTime, int dataCollectionLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
Write(pathname, id, null, test, bFiltering, includeGroupNameInISOExport, null, null, 0, null, null, null, null, null, null, minStartTime, dataCollectionLength);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem non-event notified writing test", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the representation file/files of the specified DTS.Serialization.Test
|
||||
/// at the given pathname.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="targetPathname">
|
||||
/// The <see cref="string"/> pathname of the specified object's resulting file
|
||||
/// representation.
|
||||
/// </param>
|
||||
///
|
||||
public void Write(string pathname,
|
||||
string id,
|
||||
string dataFolder,
|
||||
Test test,
|
||||
bool bFiltering,
|
||||
bool includeGroupNameInISOExport,
|
||||
FilteredData fd,
|
||||
Test.Module.Channel tmChannel,
|
||||
int channelNumber,
|
||||
BeginEventHandler beginEventHandler,
|
||||
CancelEventHandler cancelEventHandler,
|
||||
EndEventHandler endEventHandler,
|
||||
TickEventHandler tickEventHandler,
|
||||
ErrorEventHandler errorEventHandler,
|
||||
CancelRequested cancelRequested,
|
||||
double minStartTime,
|
||||
int dataCollectionLength)
|
||||
{
|
||||
Exception exception = null;
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(pathname))
|
||||
Directory.CreateDirectory(pathname);
|
||||
|
||||
var filename = Path.Combine(pathname, id + (ExtensionPrefix ?? "") + Extension);
|
||||
using (var fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
using (var fileWriter = new BinaryWriter(fs))
|
||||
{
|
||||
beginEventHandler?.Invoke(this, 1);
|
||||
|
||||
//The following is based on http://www.ni.com/white-paper/3727/en/
|
||||
WriteLeadInAndMetaData(fileWriter, test);
|
||||
WriteRawData(fileWriter, test);
|
||||
|
||||
tickEventHandler?.Invoke(this, 100.0);
|
||||
endEventHandler?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
exception = new Exception("encountered problem writing TDMS test files", ex);
|
||||
APILogger.Log("encountered problem writing TDMS test files", ex);
|
||||
}
|
||||
if (null != errorEventHandler && null != exception)
|
||||
{
|
||||
endEventHandler(this);
|
||||
errorEventHandler(this, exception);
|
||||
}
|
||||
else if (null != exception) { throw exception; }
|
||||
}
|
||||
|
||||
public void Initialize(string pathname,
|
||||
string id,
|
||||
string dataFolder,
|
||||
Test test,
|
||||
bool bFiltering,
|
||||
bool includeGroupNameInISOExport,
|
||||
FilteredData fd,
|
||||
Test.Module.Channel tmChannel,
|
||||
int channelNumber,
|
||||
BeginEventHandler beginEventHandler,
|
||||
CancelEventHandler cancelEventHandler,
|
||||
EndEventHandler endEventHandler,
|
||||
TickEventHandler tickEventHandler,
|
||||
ErrorEventHandler errorEventHandler,
|
||||
CancelRequested cancelRequested)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
private readonly string TDSmTag = "TDSm";
|
||||
private readonly int ToCMask = (int)(ToCMaskFields.TocMetaData | ToCMaskFields.TocNewObjList | ToCMaskFields.TocRawData); // 14;
|
||||
private readonly int ToCMaskLength = 4;
|
||||
private enum ToCMaskFields
|
||||
{
|
||||
// = 1 << 0,
|
||||
TocMetaData = 1 << 1,
|
||||
TocNewObjList = 1 << 2,
|
||||
TocRawData = 1 << 3,
|
||||
// = 1 << 4,
|
||||
TocInterleavedData = 1 << 5,
|
||||
TocBigEndian = 1 << 6,
|
||||
TocDAQmxRawData = 1 << 7
|
||||
}
|
||||
private readonly int Version = 4713;
|
||||
private readonly int VersionLength = 4;
|
||||
private readonly int NextSegmentOffsetLength = 8;
|
||||
private readonly int RawDataOffsetLength = 8;
|
||||
private readonly uint NoRawDataAssigned = 0xFFFFFFFF;
|
||||
private enum DataTypes
|
||||
{
|
||||
Void,
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
I64,
|
||||
U8,
|
||||
U16,
|
||||
U32,
|
||||
U64,
|
||||
SingleFloat,
|
||||
DoubleFloat,
|
||||
ExtendedFloat,
|
||||
SingleFloatWithUnit = 0x19,
|
||||
DoubleFloatWithUnit,
|
||||
ExtendedFloatWithUnit,
|
||||
String = 0x20,
|
||||
Boolean = 0x21,
|
||||
TimeStamp = 0x44,
|
||||
FixedPoint = 0x4F,
|
||||
ComplexSingleFloat = 0x08000c,
|
||||
ComplexDoubleFloat = 0x10000d
|
||||
}
|
||||
|
||||
readonly int FloatLength = 4;
|
||||
readonly int DoubleLength = 8;
|
||||
|
||||
private enum GroupProperties
|
||||
{
|
||||
TestId,
|
||||
Description,
|
||||
TestDate,
|
||||
TestTime
|
||||
}
|
||||
|
||||
private enum ChannelProperties
|
||||
{
|
||||
SensorSerialNo,
|
||||
ChannelDescriptionString,
|
||||
ChannelName,
|
||||
ModuleSerialNumber,
|
||||
SampleRate,
|
||||
NumberOfSamples,
|
||||
AAFilterRateHz,
|
||||
BridgeType,
|
||||
BridgeResistanceOhms,
|
||||
DesiredRange,
|
||||
Sensitivity,
|
||||
SensitivityUnits,
|
||||
ScaleFactorMV,
|
||||
ScaleFactorEU,
|
||||
LinearizationFormula,
|
||||
ZeroMethod,
|
||||
ZeroAverageWindowBegin,
|
||||
ZeroAverageWindowEnd,
|
||||
EU,
|
||||
InitialEU,
|
||||
InitialOffset,
|
||||
MeasuredShuntDeflectionMV,
|
||||
FactoryExcitationVoltage,
|
||||
MeasuredExcitationVoltage,
|
||||
SensorCalibrationDate,
|
||||
wf_xName,
|
||||
wf_xunit_string,
|
||||
wf_start_offset,
|
||||
wf_increment,
|
||||
wf_samples
|
||||
}
|
||||
|
||||
private readonly uint ChannelObjectDataType = (uint)DataTypes.I16;
|
||||
private void WriteProperty(BinaryWriter writer, string propertyName, DataTypes dataType, object value)
|
||||
{
|
||||
writer.Write(BitConverter.GetBytes(propertyName.Length), 0, 4);
|
||||
writer.Write(propertyName.ToCharArray());
|
||||
var uDataType = (uint)dataType;
|
||||
writer.Write(BitConverter.GetBytes(uDataType), 0, 4);
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case float:
|
||||
WritePropertyValueFloat(writer, (float)value);
|
||||
break;
|
||||
case ulong:
|
||||
WritePropertyValueUlong(writer, (ulong)value);
|
||||
break;
|
||||
case double:
|
||||
WritePropertyValueDouble(writer, (double)value);
|
||||
break;
|
||||
case string:
|
||||
WritePropertyValueString(writer, (string)value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void WritePropertyValueFloat(BinaryWriter writer, float fValue)
|
||||
{
|
||||
writer.Write(BitConverter.GetBytes(fValue));
|
||||
}
|
||||
private void WritePropertyValueString(BinaryWriter writer, string sValue)
|
||||
{
|
||||
var length = sValue.Length;
|
||||
length += GetSuperScriptBytes(sValue.ToCharArray());
|
||||
writer.Write(BitConverter.GetBytes(length), 0, 4);
|
||||
writer.Write(sValue.ToCharArray());
|
||||
}
|
||||
private void WritePropertyValueUlong(BinaryWriter writer, ulong uValue)
|
||||
{
|
||||
writer.Write(BitConverter.GetBytes(uValue), 0, 8);
|
||||
}
|
||||
private void WritePropertyValueDouble(BinaryWriter writer, double dValue)
|
||||
{
|
||||
writer.Write(BitConverter.GetBytes(dValue), 0, 8);
|
||||
}
|
||||
|
||||
private void GetGroupPropertyLengths(out int numGroupProperties,
|
||||
out int groupPropertyLengths,
|
||||
out GroupProperties[] groupProperties,
|
||||
Test test)
|
||||
{
|
||||
groupProperties = Enum.GetValues(typeof(GroupProperties)).Cast<GroupProperties>().ToArray();
|
||||
numGroupProperties = groupProperties.Length;
|
||||
var groupPropertyNameLengths = groupProperties.Sum(x => x.ToString().Length);
|
||||
var groupPropertyStringLengths = PropertyStringLengthLength * numGroupProperties;
|
||||
var groupPropertyValueLengths = test.Id.Length + test.Description.Length + test.InceptionDate.ToShortDateString().Length
|
||||
+ test.InceptionDate.ToShortTimeString().Length;
|
||||
|
||||
groupPropertyLengths = ((numGroupProperties * PropertyNameLength) +
|
||||
groupPropertyNameLengths +
|
||||
(numGroupProperties * PropertyDataTypeLength) +
|
||||
groupPropertyStringLengths +
|
||||
groupPropertyValueLengths);
|
||||
}
|
||||
private const string TIME = "TIME";
|
||||
private const string SECONDS = "s";
|
||||
private void GetChannelPropertyLengths(Test test,
|
||||
out int channelObjectPathLengths,
|
||||
out int channelObjectIndexLengths,
|
||||
out int channelObjectNumberOfPropertiesLengths,
|
||||
out int channelObjectDataTypeLengths,
|
||||
out int channelObjectDimensionLengths,
|
||||
out int channelObjectDataLengths,
|
||||
out ulong totalNumberRawDataBytes,
|
||||
out ChannelProperties[] channelProperties,
|
||||
out int channelPropertyLengths,
|
||||
int groupObjectPathLength)
|
||||
{
|
||||
channelObjectPathLengths = 0;
|
||||
channelObjectIndexLengths = 0;
|
||||
channelObjectNumberOfPropertiesLengths = 0;
|
||||
channelObjectDataTypeLengths = 0;
|
||||
channelObjectDimensionLengths = 0;
|
||||
channelObjectDataLengths = 0;
|
||||
totalNumberRawDataBytes = 0;
|
||||
channelProperties = Enum.GetValues(typeof(ChannelProperties)).Cast<ChannelProperties>().ToArray();
|
||||
var channelPropertyNameLengths = 0;
|
||||
var channelPropertyStringLengths = 0;
|
||||
var channelPropertyValueLengths = 0;
|
||||
|
||||
foreach (var channel in test.Channels)
|
||||
{
|
||||
foreach (var property in channelProperties)
|
||||
{
|
||||
channelPropertyNameLengths += property.ToString().Length;
|
||||
switch (property)
|
||||
{
|
||||
case ChannelProperties.SampleRate:
|
||||
case ChannelProperties.AAFilterRateHz:
|
||||
channelPropertyValueLengths += FloatLength;
|
||||
break;
|
||||
|
||||
case ChannelProperties.NumberOfSamples:
|
||||
case ChannelProperties.wf_samples:
|
||||
case ChannelProperties.wf_increment:
|
||||
case ChannelProperties.wf_start_offset:
|
||||
case ChannelProperties.BridgeResistanceOhms:
|
||||
case ChannelProperties.DesiredRange:
|
||||
case ChannelProperties.Sensitivity:
|
||||
case ChannelProperties.ScaleFactorMV:
|
||||
case ChannelProperties.ScaleFactorEU:
|
||||
case ChannelProperties.ZeroAverageWindowBegin:
|
||||
case ChannelProperties.ZeroAverageWindowEnd:
|
||||
case ChannelProperties.InitialEU:
|
||||
case ChannelProperties.MeasuredShuntDeflectionMV:
|
||||
case ChannelProperties.FactoryExcitationVoltage:
|
||||
case ChannelProperties.MeasuredExcitationVoltage:
|
||||
channelPropertyValueLengths += DoubleLength;
|
||||
break;
|
||||
case ChannelProperties.wf_xName:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += TIME.Length;
|
||||
break;
|
||||
case ChannelProperties.wf_xunit_string:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += SECONDS.Length;
|
||||
break;
|
||||
case ChannelProperties.SensorSerialNo:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += channel.SensorID.Length;
|
||||
break;
|
||||
case ChannelProperties.ChannelDescriptionString:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += channel.ChannelDescriptionString.Length;
|
||||
break;
|
||||
case ChannelProperties.ChannelName:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += channel.ChannelName2.Length;
|
||||
break;
|
||||
case ChannelProperties.ModuleSerialNumber:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += channel.ParentModule.BaseSerialNumber.Length;
|
||||
break;
|
||||
case ChannelProperties.BridgeType:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += (channel as Test.Module.AnalogInputChannel).Bridge.ToString().Length;
|
||||
break;
|
||||
case ChannelProperties.SensitivityUnits:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += (channel as Test.Module.AnalogInputChannel).SensitivityUnits.ToString().Length;
|
||||
break;
|
||||
case ChannelProperties.LinearizationFormula:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += (channel as Test.Module.AnalogInputChannel).LinearizationFormula.ToDisplayString().ToCharArray().Length;
|
||||
var linearizationFormulaChars = (channel as Test.Module.AnalogInputChannel).LinearizationFormula.ToDisplayString().ToCharArray();
|
||||
channelPropertyValueLengths += GetSuperScriptBytes(linearizationFormulaChars);
|
||||
break;
|
||||
case ChannelProperties.ZeroMethod:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += (channel as Test.Module.AnalogInputChannel).ZeroMethod.ToString().Length;
|
||||
break;
|
||||
case ChannelProperties.EU:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += (channel as Test.Module.AnalogInputChannel).EngineeringUnits.Length;
|
||||
break;
|
||||
case ChannelProperties.InitialOffset:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += (channel as Test.Module.AnalogInputChannel).InitialOffset.Length;
|
||||
break;
|
||||
case ChannelProperties.SensorCalibrationDate:
|
||||
channelPropertyStringLengths += PropertyStringLengthLength;
|
||||
channelPropertyValueLengths += channel.LastCalibrationDate.ToShortDateString().Length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
channelPropertyLengths = (channelProperties.Length * test.Channels.Count * PropertyNameLength) +
|
||||
channelPropertyNameLengths +
|
||||
(test.Channels.Count*channelProperties.Length * PropertyDataTypeLength) +
|
||||
channelPropertyStringLengths +
|
||||
channelPropertyValueLengths;
|
||||
foreach (var channel in test.Channels)
|
||||
{
|
||||
channelObjectPathLengths += (groupObjectPathLength + FORWARD_SLASH.Length + SINGLEQUOTE.Length + channel.ChannelName2.Length + COLON.Length +
|
||||
channel.ChannelDescriptionString.Length + SINGLEQUOTE.Length);
|
||||
channelObjectIndexLengths += ChannelObjectIndexLength;
|
||||
channelObjectDataTypeLengths += ChannelObjectDataTypeLength;
|
||||
channelObjectDimensionLengths += ChannelObjectDimensionLength;
|
||||
channelObjectDataLengths += ChannelObjectDataLength;
|
||||
totalNumberRawDataBytes += (channel as Test.Module.AnalogInputChannel).PersistentChannelInfo.NumberOfSamples * 2;
|
||||
channelObjectNumberOfPropertiesLengths += ChannelObjectNumberOfPropertiesLength;
|
||||
}
|
||||
}
|
||||
private const int ChannelObjectIndexLength = 4;
|
||||
private const int ChannelObjectDataTypeLength = 4;
|
||||
private const int ChannelObjectDimensionLength = 4;
|
||||
private const int ChannelObjectDataLength = 8;
|
||||
private const int ChannelObjectNumberOfPropertiesLength = 4;
|
||||
private const int PropertyNameLength = 4;
|
||||
private const int PropertyDataTypeLength = 4;
|
||||
private const int PropertyStringLengthLength = 4;
|
||||
private const string FORWARD_SLASH = "/";
|
||||
private const string COLON = ":";
|
||||
private const string SINGLEQUOTE = "'";
|
||||
|
||||
private void WriteGroupProperties(BinaryWriter writer, GroupProperties [] groupProperties,
|
||||
Test test, DateTime dateTimeOfTest)
|
||||
{
|
||||
foreach (var property in groupProperties)
|
||||
{
|
||||
switch (property)
|
||||
{
|
||||
case GroupProperties.TestId:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, test.Id);
|
||||
break;
|
||||
case GroupProperties.Description:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, test.Description);
|
||||
break;
|
||||
case GroupProperties.TestDate:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, dateTimeOfTest.ToShortDateString());
|
||||
break;
|
||||
case GroupProperties.TestTime:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, dateTimeOfTest.ToShortTimeString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void WriteLeadInAndMetaData
|
||||
(
|
||||
BinaryWriter fileWriter,
|
||||
Test test
|
||||
)
|
||||
{
|
||||
//Lead In
|
||||
fileWriter.Write(TDSmTag.ToCharArray());
|
||||
fileWriter.Write(BitConverter.GetBytes(ToCMask), 0, ToCMaskLength);
|
||||
fileWriter.Write(BitConverter.GetBytes(Version), 0, VersionLength);
|
||||
|
||||
var NumberOfObjectsField = 4;
|
||||
var FileObject = 1;
|
||||
var GroupObject = 1;
|
||||
var numberOfObjects = FileObject + GroupObject + test.Channels.Count;
|
||||
var ObjectLengthFields = 4 * numberOfObjects;
|
||||
|
||||
var FileObjectPath = FORWARD_SLASH;
|
||||
var FileObjectPathLength = FileObjectPath.Length;
|
||||
var groupObjectPath = FileObjectPath + SINGLEQUOTE + test.Id + SINGLEQUOTE; //Really, test.Id is TestSetupName
|
||||
var GroupObjectPathLength = groupObjectPath.Length;
|
||||
|
||||
GetGroupPropertyLengths(out var numGroupProperties, out var groupPropertyLengths, out var groupProperties, test);
|
||||
|
||||
GetChannelPropertyLengths(test, out var channelObjectPathLengths, out var channelObjectIndexLengths, out var channelObjectNumberOfPropertyLengths,
|
||||
out var channelObjectDataTypeLengths, out var channelObjectDimensionLengths, out var channelObjectDataLengths, out var totalNumberRawDataBytes,
|
||||
out var channelProperties, out var channelPropertyLengths, GroupObjectPathLength);
|
||||
|
||||
var ObjectPathLengths = FileObjectPathLength + GroupObjectPathLength + channelObjectPathLengths;
|
||||
|
||||
var FileObjectRawDataIndexLength = 4; //FF FF FF FF (no data assigned to this object)
|
||||
var GroupObjectRawDataIndexLength = 4; //FF FF FF FF (no data assigned to this object)
|
||||
var DataIndexLengths = FileObjectRawDataIndexLength + GroupObjectRawDataIndexLength + channelObjectIndexLengths;
|
||||
|
||||
var FileObjectNumberOfPropertiesLength = 4;
|
||||
var GroupObjectNumberOfPropertiesLength = 4;
|
||||
var NumberOfPropertiesLengths = FileObjectNumberOfPropertiesLength + GroupObjectNumberOfPropertiesLength + channelObjectNumberOfPropertyLengths;
|
||||
|
||||
var RawDataOffset = (ulong)(NumberOfObjectsField +
|
||||
ObjectLengthFields +
|
||||
ObjectPathLengths +
|
||||
DataIndexLengths +
|
||||
NumberOfPropertiesLengths +
|
||||
groupPropertyLengths +
|
||||
channelObjectDataTypeLengths +
|
||||
channelObjectDimensionLengths +
|
||||
channelObjectDataLengths +
|
||||
channelPropertyLengths);
|
||||
|
||||
var nextSegmentOffset = RawDataOffset + totalNumberRawDataBytes;
|
||||
fileWriter.Write(BitConverter.GetBytes(nextSegmentOffset), 0, NextSegmentOffsetLength);
|
||||
|
||||
fileWriter.Write(BitConverter.GetBytes(RawDataOffset), 0, RawDataOffsetLength);
|
||||
|
||||
//Meta Data
|
||||
fileWriter.Write(BitConverter.GetBytes(numberOfObjects), 0, 4);
|
||||
|
||||
//File Object
|
||||
fileWriter.Write(BitConverter.GetBytes(FileObjectPathLength), 0, 4);
|
||||
fileWriter.Write(FileObjectPath.ToCharArray());
|
||||
|
||||
//File RawData
|
||||
fileWriter.Write(BitConverter.GetBytes(NoRawDataAssigned), 0, 4);
|
||||
|
||||
uint FileObjectNumberOfProperties = 0;
|
||||
fileWriter.Write(BitConverter.GetBytes(FileObjectNumberOfProperties), 0, 4);
|
||||
|
||||
//Group Object
|
||||
fileWriter.Write(BitConverter.GetBytes(GroupObjectPathLength), 0, 4);
|
||||
fileWriter.Write(groupObjectPath.ToCharArray());
|
||||
|
||||
//Group raw data
|
||||
fileWriter.Write(BitConverter.GetBytes(NoRawDataAssigned), 0, 4);
|
||||
|
||||
fileWriter.Write(BitConverter.GetBytes(numGroupProperties), 0, 4);
|
||||
|
||||
var dateTimeOfTest = test.InceptionDate;
|
||||
|
||||
WriteGroupProperties(fileWriter, groupProperties, test, dateTimeOfTest);
|
||||
|
||||
WriteChannelSection(fileWriter, channelProperties, test, groupObjectPath);
|
||||
}
|
||||
private void WriteChannelSection(BinaryWriter writer, ChannelProperties [] channelProperties, Test test,
|
||||
string groupObjectPath)
|
||||
{
|
||||
var channelObjectArrayDimensions = 1;
|
||||
|
||||
//Channel Object(s)
|
||||
foreach (var channel in test.Channels)
|
||||
{
|
||||
var channelObjectPath = groupObjectPath + FORWARD_SLASH + SINGLEQUOTE + channel.ChannelName2 + COLON + channel.ChannelDescriptionString + SINGLEQUOTE;
|
||||
var channelObjectPathLength = channelObjectPath.Length;
|
||||
writer.Write(BitConverter.GetBytes(channelObjectPathLength), 0, 4);
|
||||
writer.Write(channelObjectPath.ToCharArray());
|
||||
|
||||
var lengthOfIndexInformation = (uint)(ChannelObjectDataTypeLength +
|
||||
ChannelObjectDimensionLength +
|
||||
ChannelObjectDataLength +
|
||||
ChannelObjectNumberOfPropertiesLength);
|
||||
|
||||
var channelObjectRawDataIndex = lengthOfIndexInformation;
|
||||
writer.Write(BitConverter.GetBytes(channelObjectRawDataIndex), 0, 4);
|
||||
|
||||
writer.Write(BitConverter.GetBytes(ChannelObjectDataType), 0, 4);
|
||||
writer.Write(BitConverter.GetBytes(channelObjectArrayDimensions), 0, 4);
|
||||
writer.Write(BitConverter.GetBytes((channel as Test.Module.AnalogInputChannel).PersistentChannelInfo.NumberOfSamples), 0, 8);
|
||||
|
||||
writer.Write(BitConverter.GetBytes(channelProperties.Length), 0, 4);
|
||||
var aic = (channel as Test.Module.AnalogInputChannel);
|
||||
foreach (var property in channelProperties)
|
||||
{
|
||||
switch (property)
|
||||
{
|
||||
case ChannelProperties.SensorSerialNo:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, channel.SensorID);
|
||||
break;
|
||||
case ChannelProperties.ChannelDescriptionString:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, channel.ChannelDescriptionString);
|
||||
break;
|
||||
case ChannelProperties.ChannelName:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, channel.ChannelName2);
|
||||
break;
|
||||
case ChannelProperties.ModuleSerialNumber:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, channel.ParentModule.BaseSerialNumber);
|
||||
break;
|
||||
case ChannelProperties.SampleRate:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.SingleFloat, channel.ParentModule.SampleRateHz);
|
||||
break;
|
||||
case ChannelProperties.NumberOfSamples:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.U64, channel.ParentModule.NumberOfSamples);
|
||||
break;
|
||||
case ChannelProperties.AAFilterRateHz:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.SingleFloat, channel.ParentModule.AaFilterRateHz);
|
||||
break;
|
||||
case ChannelProperties.BridgeType:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, (channel as Test.Module.AnalogInputChannel).Bridge.ToString());
|
||||
break;
|
||||
case ChannelProperties.BridgeResistanceOhms:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, (channel as Test.Module.AnalogInputChannel).BridgeResistanceOhms);
|
||||
break;
|
||||
case ChannelProperties.DesiredRange:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, (channel as Test.Module.AnalogInputChannel).DesiredRange);
|
||||
break;
|
||||
case ChannelProperties.Sensitivity:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, (channel as Test.Module.AnalogInputChannel).Sensitivity);
|
||||
break;
|
||||
case ChannelProperties.SensitivityUnits:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, (channel as Test.Module.AnalogInputChannel).SensitivityUnits.ToString());
|
||||
break;
|
||||
case ChannelProperties.ScaleFactorMV:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, (channel as Test.Module.AnalogInputChannel).Data.ScaleFactorMv);
|
||||
break;
|
||||
case ChannelProperties.ScaleFactorEU:
|
||||
var scaleFactorEU = 0D;
|
||||
if ((channel as Test.Module.AnalogInputChannel).ProportionalToExcitation)
|
||||
{
|
||||
scaleFactorEU = aic.Data.ScaleFactorMv / (aic.FactoryExcitationVoltage * aic.Data.MvPerEu);
|
||||
}
|
||||
else
|
||||
{
|
||||
scaleFactorEU = aic.Data.ScaleFactorMv / aic.Data.MvPerEu;
|
||||
}
|
||||
|
||||
if (aic.IsInverted)
|
||||
{
|
||||
scaleFactorEU *= -1D;
|
||||
}
|
||||
scaleFactorEU *= aic.Multiplier;
|
||||
WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, scaleFactorEU);
|
||||
break;
|
||||
case ChannelProperties.LinearizationFormula:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, aic.LinearizationFormula.ToDisplayString());
|
||||
break;
|
||||
case ChannelProperties.ZeroMethod:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, aic.ZeroMethod.ToString());
|
||||
break;
|
||||
case ChannelProperties.ZeroAverageWindowBegin:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, aic.ZeroAverageWindow.Begin);
|
||||
break;
|
||||
case ChannelProperties.ZeroAverageWindowEnd:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, aic.ZeroAverageWindow.End);
|
||||
break;
|
||||
case ChannelProperties.EU:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, aic.EngineeringUnits);
|
||||
break;
|
||||
case ChannelProperties.InitialEU:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, aic.InitialEu + aic.UserOffsetEU);
|
||||
break;
|
||||
case ChannelProperties.InitialOffset:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, aic.InitialOffset);
|
||||
break;
|
||||
case ChannelProperties.MeasuredShuntDeflectionMV:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, aic.MeasureShuntDeflectionMvValid ? aic.MeasuredShuntDeflectionMv : 0D);
|
||||
break;
|
||||
case ChannelProperties.FactoryExcitationVoltage:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, aic.FactoryExcitationVoltageValid ? aic.FactoryExcitationVoltage : 0D);
|
||||
break;
|
||||
case ChannelProperties.MeasuredExcitationVoltage:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, aic.MeasuredExcitationVoltageValid ? aic.MeasuredExcitationVoltage : 0D);
|
||||
break;
|
||||
case ChannelProperties.SensorCalibrationDate:
|
||||
WriteProperty(writer, property.ToString(), DataTypes.String, channel.LastCalibrationDate.ToShortDateString());
|
||||
break;
|
||||
case ChannelProperties.wf_xunit_string: WriteProperty(writer, property.ToString(), DataTypes.String, SECONDS); break;
|
||||
case ChannelProperties.wf_xName: WriteProperty(writer, property.ToString(), DataTypes.String, TIME); break;
|
||||
case ChannelProperties.wf_start_offset: WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, 0D); break;
|
||||
case ChannelProperties.wf_samples: WriteProperty(writer, property.ToString(), DataTypes.U64, aic.ParentModule.NumberOfSamples); break;
|
||||
case ChannelProperties.wf_increment: WriteProperty(writer, property.ToString(), DataTypes.DoubleFloat, 1D / aic.ParentModule.SampleRateHz); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private readonly HashSet<int> _superScriptBytes1 = new HashSet<int>()
|
||||
{
|
||||
112,//20H & 70H or \u2070 (SuperScript '0')
|
||||
116,//20H & 74H or \u2074 (SuperScript '4')
|
||||
117,//20H & 75H or \u2075 (SuperScript '5')
|
||||
118,//20H & 76H or \u2076 (SuperScript '6')
|
||||
119,//20H & 77H or \u2077 (SuperScript '7')
|
||||
120,//20H & 78H or \u2078 (SuperScript '8')
|
||||
121,//20H & 79H or \u2079 (SuperScript '9')
|
||||
123,//20H & 7BH or \u207B (SuperScript '-')
|
||||
127//20H & 7FH or \u207F (SuperScript 'n')
|
||||
};
|
||||
private readonly HashSet<int> _superScriptBytes2 = new HashSet<int>()
|
||||
{
|
||||
178,//00H & B2H or \u00B2 (SuperScript '2')
|
||||
179,//00H & B3H or \u00B3 (SuperScript '3')
|
||||
183,//00H & B7H or \u00B7 (SuperScript '.')
|
||||
185//00H & B9H or \u00B9 (SuperScript '1')
|
||||
};
|
||||
private int GetSuperScriptBytes(char[] linearizationFormulaChars)
|
||||
{
|
||||
var extraBytes = 0;
|
||||
|
||||
foreach (var linearizationFormulaChar in linearizationFormulaChars)
|
||||
{
|
||||
var byteArray = BitConverter.GetBytes(linearizationFormulaChar);
|
||||
if (byteArray[1] == 32 && _superScriptBytes1.Contains(byteArray[0]))
|
||||
{
|
||||
extraBytes++;
|
||||
extraBytes++;
|
||||
}
|
||||
else if (byteArray[1] == 0 && _superScriptBytes2.Contains(byteArray[0]))
|
||||
{
|
||||
extraBytes++;
|
||||
}
|
||||
}
|
||||
return extraBytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the specified test to the specified stream.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="fileWriter">
|
||||
/// The <see cref="System.IO.StreamWriter"/> to which the specified test should be serialized.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="test">
|
||||
/// The <see cref="DTS.Serialization.Test"/> to be serialized.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="writeEvent">
|
||||
/// The <see cref="Diadem.File.Writer.EventHandler"/> that should handle write-progress
|
||||
/// reporting; null if none is to be used.
|
||||
/// </param>
|
||||
///
|
||||
protected void WriteRawData
|
||||
(
|
||||
BinaryWriter fileWriter,
|
||||
Test test
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var channel in test.Channels)
|
||||
{
|
||||
for (ulong i = 0; i < (channel as Test.Module.AnalogInputChannel).PersistentChannelInfo.NumberOfSamples; i++)
|
||||
{
|
||||
fileWriter.Write(BitConverter.GetBytes((channel as Test.Module.AnalogInputChannel).PersistentChannelInfo[i]), 0, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem writing TDMS channel headers", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user