759 lines
40 KiB
C#
759 lines
40 KiB
C#
/*
|
|
* 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|