init
This commit is contained in:
1
Common/DTS.Common.Serialization/.svn/entries
Normal file
1
Common/DTS.Common.Serialization/.svn/entries
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
1
Common/DTS.Common.Serialization/.svn/format
Normal file
1
Common/DTS.Common.Serialization/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
SliceRaw.File.Writer.cs
|
||||
|
||||
Copyright © 2009
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.Serialization.SliceRaw
|
||||
{
|
||||
// *** see SliceRaw.File.cs ***
|
||||
public partial class File
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Utility object for serializing <see cref="DTS.Serialization.Test"/>s to disk
|
||||
/// in the SliceRaw format.
|
||||
/// </summary>
|
||||
///
|
||||
public class Writer : Writer<File>, IWriter<Test>
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the SliceRaw.File.Writer class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="fileType">
|
||||
/// The <see cref="DTS.Serialization.SliceRaw.File"/>-type this serializer is associated with.
|
||||
/// </param>
|
||||
///
|
||||
public Writer(File fileType, int encoding)
|
||||
: base(fileType, encoding)
|
||||
{
|
||||
}
|
||||
|
||||
public delegate void SetProgressDelegate(double d);
|
||||
/// <summary>
|
||||
/// if present will be used to notify of progress
|
||||
/// used to provide "finishing download" progrses
|
||||
/// 17587 Add Finishing download feedback
|
||||
/// </summary>
|
||||
public SetProgressDelegate SetProgress { get; set; }
|
||||
/// <summary>
|
||||
/// Perform disk serialization now.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="directory">
|
||||
/// The <see cref="string"/> path of the directory to contain the written test.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="test">
|
||||
/// The <see cref="DTS.Serialization.Test"/> to be written out.
|
||||
/// </param>
|
||||
///
|
||||
public void Write(string directory, string id, Test test, bool bFiltering, bool includeGroupNameInISOExport, double minStartTime, int dataCollectionLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
Write(directory, 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 doing non-event reporting write", ex);
|
||||
}
|
||||
}
|
||||
private void ChannelException(string problem, string channel, System.Exception ex)
|
||||
{
|
||||
APILogger.Log("Exception writing channel: ", channel, " field: ", problem, " exception: ", ex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform disk serialization now.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="directory">
|
||||
/// The <see cref="string"/> path of the directory to contin the written test.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="test">
|
||||
/// The <see cref="DTS.Serialization.Test"/> to be written out.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="onEvent">
|
||||
/// The <see cref="DTS.Serialization.File.Writer.EventHandler"/> to be notified whenever
|
||||
/// the writer does something noteworthy.
|
||||
/// </param>
|
||||
///
|
||||
public void Write(string directory,
|
||||
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)
|
||||
{
|
||||
System.Exception exception = null;
|
||||
//int line = 0;
|
||||
try
|
||||
{
|
||||
if (null == test)
|
||||
{
|
||||
throw new ArgumentNullException("cannot write null test reference");
|
||||
}
|
||||
//ConfigurationManager.AppSettings
|
||||
|
||||
test.Software = System.Reflection.Assembly.GetEntryAssembly().GetName().Name;
|
||||
test.SoftwareVersion = System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString(4);
|
||||
//line = 1;
|
||||
var numberOfFiles = 1; // There will always be the main test file.
|
||||
var numberOfTicksSent = 0;
|
||||
foreach (var module in test.Modules)
|
||||
numberOfFiles += module.Channels.Count;
|
||||
beginEventHandler?.Invoke(this, (uint)numberOfFiles);
|
||||
|
||||
//line = 2;
|
||||
var encoder = Encoding.Default;
|
||||
try
|
||||
{
|
||||
//force UTF-16 for the dts file, it contains "UTF-16" in the xml by default and isn't consumed by anything that requires
|
||||
//codepage exports (CSV/excel)
|
||||
encoder = Common.Utils.FileUtils.GetEncoding(DefaultEncoding);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("Problem getting encoder", ex);
|
||||
encoder = Encoding.Default;
|
||||
}
|
||||
//line = 3;
|
||||
using (StringWriter writer = new StringWriterWithEncoding(encoder))
|
||||
{
|
||||
new XmlSerializer(typeof(Test)).Serialize(writer, test);
|
||||
|
||||
//FB14854 Add option to move ROI Download folders into the main test folder
|
||||
// Cleaned up folder get/set to accomodate ROI both within the main test folder and without
|
||||
var testIdNode = id;// new DirectoryInfo(Path.GetDirectoryName(subPath)).Name;
|
||||
using (var fileWriter = new StreamWriter((directory.EndsWith("\\") ? directory : directory + "\\") + testIdNode + TestFileExtension, false, encoder))
|
||||
fileWriter.Write(writer.ToString());
|
||||
tickEventHandler?.Invoke(this, (uint)(++numberOfTicksSent) / numberOfFiles * 100);
|
||||
}
|
||||
|
||||
var file = 0;
|
||||
if (true == bFiltering)
|
||||
{
|
||||
//line = 4;
|
||||
foreach (var module in test.Modules)
|
||||
{
|
||||
//line = 5;
|
||||
foreach (var channel in module.Channels)
|
||||
{
|
||||
file++;
|
||||
if (null != cancelRequested && cancelRequested()) { break; }
|
||||
|
||||
CreatePersistentChannel(channel, module.NumberOfSamples, module.SampleRateHz, tickEventHandler, cancelRequested, numberOfFiles, numberOfTicksSent);
|
||||
SetProgress?.Invoke(100D * file / numberOfFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
exception = new Exception("encountered problem doing test file write", ex);
|
||||
}
|
||||
|
||||
finally
|
||||
{
|
||||
endEventHandler?.Invoke(this);
|
||||
if (null != exception && null != errorEventHandler)
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
public void CreatePersistentChannel(Test.Module.Channel channel,
|
||||
ulong numberOfSamples,
|
||||
float sampleRateHz,
|
||||
TickEventHandler tickEventHandler,
|
||||
CancelRequested cancelRequested,
|
||||
int numberOfFiles,
|
||||
int numberOfTicksSent)
|
||||
{
|
||||
try
|
||||
{
|
||||
//line = 6;
|
||||
channel.ExpressDataInlineOnXmlSerialization = false;
|
||||
const string DefaultIsoCode = "????????????????";
|
||||
|
||||
var fields = Enum.GetValues(typeof(PersistentChannel.Field)).Cast<PersistentChannel.Field>().ToArray();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
try
|
||||
{
|
||||
//line = 7;
|
||||
if (null != cancelRequested && cancelRequested()) { break; }
|
||||
switch (field)
|
||||
{
|
||||
case PersistentChannel.Field.AreSamplesSigned:
|
||||
channel.PersistentChannelInfo.AreSamplesSigned = 1;
|
||||
break;
|
||||
case PersistentChannel.Field.BeginningOfData:
|
||||
break;
|
||||
case PersistentChannel.Field.BeginningOfFile:
|
||||
break;
|
||||
case PersistentChannel.Field.Crc32:
|
||||
break;
|
||||
case PersistentChannel.Field.DataZeroLevelCounts:
|
||||
try { channel.PersistentChannelInfo.DataZeroLevelCounts = channel.DataZeroLevelAdc; }// xxx This needs to be calculated on the fly during download.
|
||||
catch (System.Exception myException) { ChannelException("DataZeroLevelCounts", channel.ChannelDescriptionString, myException); }
|
||||
break;
|
||||
case PersistentChannel.Field.EngineeringUnit:
|
||||
break;
|
||||
case PersistentChannel.Field.EuFieldLengthWithTerminator:
|
||||
break;
|
||||
case PersistentChannel.Field.Excitation:
|
||||
try { channel.PersistentChannelInfo.Excitation = channel.Excitation; }
|
||||
catch (System.Exception) { }
|
||||
break;
|
||||
case PersistentChannel.Field.HeaderVersionNumber:
|
||||
break;
|
||||
case PersistentChannel.Field.IsoCode:
|
||||
try
|
||||
{
|
||||
channel.PersistentChannelInfo.IsoCode = (channel is Common.DAS.Concepts.DAS.Channel.IIsoCodeAware)
|
||||
? (channel as Common.DAS.Concepts.DAS.Channel.IIsoCodeAware).IsoCode.PadRight(DefaultIsoCode.Length, '?').ToCharArray(0, DefaultIsoCode.Length)
|
||||
: DefaultIsoCode.ToCharArray();
|
||||
}
|
||||
catch (System.Exception myException)
|
||||
{
|
||||
ChannelException("IsoCode", channel.ChannelDescriptionString, myException);
|
||||
}
|
||||
break;
|
||||
case PersistentChannel.Field.MagicKey:
|
||||
break;
|
||||
case PersistentChannel.Field.MvPerEu:
|
||||
try { channel.PersistentChannelInfo.MvPerEu = channel.Data.MvPerEu; }
|
||||
catch (System.Exception myException) { ChannelException("MvPerEu", channel.ChannelDescriptionString, myException); }
|
||||
break;
|
||||
case PersistentChannel.Field.NumberOfBitsPerSample:
|
||||
channel.PersistentChannelInfo.NumberOfBitsPerSample = 16;
|
||||
break;
|
||||
case PersistentChannel.Field.NumberOfSamples:
|
||||
try
|
||||
{
|
||||
var numSamples = (0 != numberOfSamples ? numberOfSamples : (ulong)channel.Data.Values.Length);
|
||||
channel.PersistentChannelInfo.NumberOfSamples = numSamples;
|
||||
}
|
||||
catch (System.Exception myException) { ChannelException("NumberOfSamples", channel.ChannelDescriptionString, myException); }
|
||||
break;
|
||||
case PersistentChannel.Field.NumberOfTriggers:
|
||||
break;
|
||||
case PersistentChannel.Field.OffsetOfSampleDataStart:
|
||||
try { channel.PersistentChannelInfo.OffsetOfSampleDataStart = (ulong)(channel.PersistentChannelInfo.GetFileOffsetOf(PersistentChannel.Field.BeginningOfData)); }
|
||||
catch (System.Exception myException) { ChannelException("OffsetOfSampleDataStart", channel.ChannelDescriptionString, myException); }
|
||||
break;
|
||||
case PersistentChannel.Field.OriginalOffsetADC:
|
||||
try { channel.PersistentChannelInfo.OriginalOffsetADC = channel.OriginalOffsetADC; }
|
||||
catch (System.Exception) { }
|
||||
break;
|
||||
case PersistentChannel.Field.PostTestDiagnosticsLevelCounts:
|
||||
try { channel.PersistentChannelInfo.PostTestDiagnosticsLevelCounts = 0; }
|
||||
catch (System.Exception myException) { ChannelException("PostTestDiagnosticsLevelCounts", channel.ChannelDescriptionString, myException); }
|
||||
break;
|
||||
case PersistentChannel.Field.PostTestZeroLevelCounts:
|
||||
try { channel.PersistentChannelInfo.PostTestZeroLevelCounts = channel.PreTestZeroLevelAdc; }
|
||||
catch (System.Exception myException) { ChannelException("PostTestZeroLevelCounts", channel.ChannelDescriptionString, myException); }
|
||||
break;
|
||||
case PersistentChannel.Field.PreTestDiagnosticsLevelCounts:
|
||||
channel.PersistentChannelInfo.PreTestDiagnosticsLevelCounts = 0;
|
||||
break;
|
||||
case PersistentChannel.Field.PreTestNoisePercentageOfFullScale:
|
||||
try { channel.PersistentChannelInfo.PreTestNoisePercentageOfFullScale = channel.NoiseAsPercentageOfFullScale; }
|
||||
catch (System.Exception myException) { ChannelException("PreTestNoisePercentageOfFullScale", channel.ChannelDescriptionString, myException); }
|
||||
break;
|
||||
case PersistentChannel.Field.PreTestZeroLevelCounts:
|
||||
try { channel.PersistentChannelInfo.PreTestZeroLevelCounts = channel.PreTestZeroLevelAdc; }
|
||||
catch (System.Exception myException) { ChannelException("PreTestZeroLevelCounts", channel.ChannelDescriptionString, myException); }
|
||||
break;
|
||||
case PersistentChannel.Field.RemovedADC:
|
||||
try { channel.PersistentChannelInfo.RemovedADC = channel.RemovedADC; }
|
||||
catch (System.Exception) { }
|
||||
break;
|
||||
case PersistentChannel.Field.SampleRate:
|
||||
try { channel.PersistentChannelInfo.SampleRate = sampleRateHz; }
|
||||
catch (System.Exception myException) { ChannelException("SampleRate", channel.ChannelDescriptionString, myException); }
|
||||
break;
|
||||
case PersistentChannel.Field.ScaleFactorMv:
|
||||
try { channel.PersistentChannelInfo.ScaleFactorMv = channel.Data.ScaleFactorMv; }
|
||||
catch (System.Exception myException) { ChannelException("ScaleFactorMv", channel.ChannelDescriptionString, myException); }
|
||||
break;
|
||||
case PersistentChannel.Field.TriggerAdjustmentSamples:
|
||||
try { channel.PersistentChannelInfo.TriggerAdjustmentSamples = channel.TriggerAdjustmentSamples; }
|
||||
catch (System.Exception) { }
|
||||
break;
|
||||
case PersistentChannel.Field.TriggerSampleNumbers:
|
||||
break;
|
||||
case PersistentChannel.Field.ZeroMvInADC:
|
||||
try { channel.PersistentChannelInfo.ZeroMvInADC = channel.ZeroMvInADC; }
|
||||
catch (System.Exception) { }
|
||||
break;
|
||||
case PersistentChannel.Field.WindowAverageADC:
|
||||
try { channel.PersistentChannelInfo.WindowAverageADC = channel.WindowAverageADC; }
|
||||
catch (System.Exception) { }
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("exception writing serializing channel header, field: " + field.ToString());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
channel.PersistentChannelInfo.StampCrc();
|
||||
// force file handle release
|
||||
try
|
||||
{
|
||||
channel.PersistentChannelInfo.Dispose();
|
||||
channel.PersistentChannelInfo = null;
|
||||
}
|
||||
catch (System.Exception) { }
|
||||
|
||||
tickEventHandler?.Invoke(this, (uint)(++numberOfTicksSent) / numberOfFiles * 100);
|
||||
}
|
||||
catch (System.Exception channelException)
|
||||
{
|
||||
APILogger.Log("Exception writing serializing channel header, Channel: ", channel.ChannelDescriptionString, " Exception: ", channelException);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* IReadable.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.Serialization
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Defines "readability" for DTS.Serialization objects.
|
||||
/// </summary>
|
||||
///
|
||||
public interface IReadable
|
||||
{ //
|
||||
// It's not that it doesn't take much to be readable, just that all non-trivial readable
|
||||
// definitions involve a specific type of object that the file is to be deserialized
|
||||
// into (see non-trivial IReadable interface below). But one may want to reflect against
|
||||
// a general "IReadable" type for various reasons, i.e., to check to see if file-type object
|
||||
// is readable in general before presenting the user with read options on the UI (that will
|
||||
// perform polymorphic read functions on the object, natch).
|
||||
} //
|
||||
|
||||
/// <summary>
|
||||
/// Defines "readability" for DTS.Serialization objects.
|
||||
/// </summary>
|
||||
///
|
||||
/// <typeparam name="T">
|
||||
/// The type of object to be deserialized to.
|
||||
/// </typeparam>
|
||||
///
|
||||
public interface IReadable<T> : IReadable
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Get a deserializer to "read" an instance of this file format into the specified object type.
|
||||
/// </summary>
|
||||
///
|
||||
IReader<T> Importer { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the general requirements of a DTS.Serialization file reader object.
|
||||
/// </summary>
|
||||
public interface IReader
|
||||
{ //
|
||||
// It's not that it doesn't take much to be a reader, just that all non-trivial reader
|
||||
// definitions involve a specific type of object that the file is to be deserialized
|
||||
// into (see non-trivial IReader interface below). But one may want to reflect against
|
||||
// a general "IReader" type for various reasons, i.e., to check to see if file-type object
|
||||
// is readable in general before presenting the user with read options on the UI (that will
|
||||
// perform polymorphic read functions on the object, natch).
|
||||
} //
|
||||
|
||||
/// <summary>
|
||||
/// Defines the non-trivial requirements of a DTS.Serialization file reader object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <typeparam name="T">
|
||||
/// The type of object the file is to be deserialized into.
|
||||
/// </typeparam>
|
||||
///
|
||||
public interface IReader<T> : IReader
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Deserialize the path-specified serialization into the given object reference.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="pathname">
|
||||
/// The <see cref="string"/> pathname at which the serialization can be found.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="target">
|
||||
/// The object to be initialized by the specified serialization.
|
||||
/// </param>
|
||||
///
|
||||
void Read(string pathname, out T target);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,468 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
[Serializable]
|
||||
public partial class TestSetup : Exceptional
|
||||
{
|
||||
public TestSetup()
|
||||
{
|
||||
_dateOfTheTest.Value = null;
|
||||
_description.Value = null;
|
||||
_calibrationBehavior.Value = CalibrationBehaviors.NonLinearIfAvailable;
|
||||
_exportFolder.Value = null;
|
||||
_exportTypes.Value = 0;
|
||||
|
||||
_labName.Value = null;
|
||||
_laboratoryName.Value = null;
|
||||
_laboratoryContactName.Value = null;
|
||||
_laboratoryContactPhone.Value = null;
|
||||
_laboratoryContactFax.Value = null;
|
||||
_laboratoryContactEmail.Value = null;
|
||||
_laboratoryTestReferenceNumber.Value = null;
|
||||
|
||||
_custName.Value = null;
|
||||
_customerName.Value = null;
|
||||
_customerTestReferenceNumber.Value = null;
|
||||
_customerProjectReferenceNumber.Value = null;
|
||||
_customerOrderNumber.Value = null;
|
||||
_customerCostUnit.Value = null;
|
||||
_testEngineerName.Value = null;
|
||||
_testEngineerPhone.Value = null;
|
||||
_testEngineerFax.Value = null;
|
||||
_testEngineerEmail.Value = null;
|
||||
|
||||
_name.Value = null;
|
||||
_numberOfMedia.Value = null;
|
||||
_numberOfTestObjects.Value = null;
|
||||
_testComment.Value = null;
|
||||
_typeOfTheTest.Value = null;
|
||||
_referenceTemperature.Value = null;
|
||||
_relativeAirHumidity.Value = null;
|
||||
_regulation.Value = null;
|
||||
_subtype.Value = null;
|
||||
_dateOfTheTest.Value = null;
|
||||
_timestamp.Value = null;
|
||||
//version 2.0 - 2019-05-17 added Upload/UploadFolder/UploadExportsOnly
|
||||
_version.Value = "2.0.0.0";
|
||||
_upload.Value = false;
|
||||
_uploadExportsOnly.Value = false;
|
||||
_uploadFolder.Value = "";
|
||||
}
|
||||
|
||||
private readonly Property<bool> _upload =
|
||||
new Property<bool>(typeof(TestSetup).Namespace + ".TestSetup.Upload", false, true);
|
||||
/// <summary>
|
||||
/// indicates whether the test setup was configured to upload when it was run
|
||||
/// 12874 export button, upload feature not displaying information
|
||||
/// </summary>
|
||||
public bool Upload
|
||||
{
|
||||
get => _upload.Value;
|
||||
set => _upload.Value = value;
|
||||
}
|
||||
|
||||
private readonly Property<string> _uploadFolder =
|
||||
new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.UploadFolder", "", true);
|
||||
/// <summary>
|
||||
/// stores the simple upload folder value set in edit test setup
|
||||
/// 12874 export button, upload feature not displaying information
|
||||
/// this is where the test setup was configured to upload when it was run
|
||||
/// this is overridden by an INI file if one is set
|
||||
/// </summary>
|
||||
public string UploadFolder
|
||||
{
|
||||
get => _uploadFolder.Value;
|
||||
set => _uploadFolder.Value = value;
|
||||
}
|
||||
|
||||
private readonly Property<bool> _uploadExportsOnly =
|
||||
new Property<bool>(typeof(TestSetup).Namespace + ".TestSetup.UploadExportsOnly", false, true);
|
||||
/// <summary>
|
||||
/// stores the simple upload folder value set in edit test setup
|
||||
/// 12874 export button, upload feature not displaying information
|
||||
/// this is where the test setup was configured to upload when it was run
|
||||
/// this is overridden by an INI file if one is set
|
||||
/// </summary>
|
||||
public bool UploadExportsOnly
|
||||
{
|
||||
get => _uploadExportsOnly.Value;
|
||||
set => _uploadExportsOnly.Value = value;
|
||||
}
|
||||
|
||||
|
||||
private readonly Property<string> _isfFile
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.ISFFile", "", true);
|
||||
public string ISFFile
|
||||
{
|
||||
get => _isfFile.Value;
|
||||
set => _isfFile.Value = value;
|
||||
}
|
||||
|
||||
public string DateOfTheTest
|
||||
{
|
||||
get => _dateOfTheTest.Value;
|
||||
set => _dateOfTheTest.Value = value;
|
||||
}
|
||||
private readonly Property<string> _dateOfTheTest
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.DateOfTheTest", "", false);
|
||||
|
||||
public string Description
|
||||
{
|
||||
get => _description.Value;
|
||||
set => _description.Value = value;
|
||||
}
|
||||
private readonly Property<string> _description
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.Description", "", false);
|
||||
|
||||
public CalibrationBehaviors CalibrationBehavior
|
||||
{
|
||||
get => _calibrationBehavior.Value;
|
||||
set => _calibrationBehavior.Value = value;
|
||||
}
|
||||
private readonly Property<CalibrationBehaviors> _calibrationBehavior
|
||||
= new Property<CalibrationBehaviors>(typeof(TestSetup).Namespace + ".TestSetup.CalibrationBehavior", CalibrationBehaviors.NonLinearIfAvailable, false);
|
||||
|
||||
public string ExportFolder
|
||||
{
|
||||
get => _exportFolder.Value;
|
||||
set => _exportFolder.Value = value;
|
||||
}
|
||||
private readonly Property<string> _exportFolder
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.ExportFolder", "", false);
|
||||
|
||||
public Int32 ExportTypes
|
||||
{
|
||||
get => _exportTypes.Value;
|
||||
set => _exportTypes.Value = value;
|
||||
}
|
||||
private readonly Property<Int32> _exportTypes
|
||||
= new Property<Int32>(typeof(TestSetup).Namespace + ".TestSetup.ExportFormats", new Int32(), false);
|
||||
|
||||
public List<Graph> Graphs
|
||||
{
|
||||
get => _graphs.Value;
|
||||
set => _graphs.Value = value;
|
||||
}
|
||||
private readonly Property<List<Graph>> _graphs
|
||||
= new Property<List<Graph>>(typeof(TestSetup).Namespace + ".TestSetup.Graphs", new List<Graph>(), true);
|
||||
|
||||
public List<Sensor> Sensors
|
||||
{
|
||||
get => _sensors.Value;
|
||||
set => _sensors.Value = value;
|
||||
}
|
||||
private readonly Property<List<Sensor>> _sensors
|
||||
= new Property<List<Sensor>>(typeof(TestSetup).Namespace + ".TestSetup.Sensors", new List<Sensor>(), true);
|
||||
|
||||
public string LabName
|
||||
{
|
||||
get => _labName.Value;
|
||||
set => _labName.Value = value;
|
||||
}
|
||||
private readonly Property<string> _labName
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.LabName", "", false);
|
||||
|
||||
public string LaboratoryName
|
||||
{
|
||||
get => _laboratoryName.Value;
|
||||
set => _laboratoryName.Value = value;
|
||||
}
|
||||
private readonly Property<string> _laboratoryName
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.LaboratoryName", "", false);
|
||||
|
||||
public string LaboratoryContactName
|
||||
{
|
||||
get => _laboratoryContactName.Value;
|
||||
set => _laboratoryContactName.Value = value;
|
||||
}
|
||||
private readonly Property<string> _laboratoryContactName
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.LaboratoryContactName", "", false);
|
||||
|
||||
public string LaboratoryContactPhone
|
||||
{
|
||||
get => _laboratoryContactPhone.Value;
|
||||
set => _laboratoryContactPhone.Value = value;
|
||||
}
|
||||
private readonly Property<string> _laboratoryContactPhone
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.LaboratoryContactPhone", "", false);
|
||||
|
||||
public string LaboratoryContactFax
|
||||
{
|
||||
get => _laboratoryContactFax.Value;
|
||||
set => _laboratoryContactFax.Value = value;
|
||||
}
|
||||
private readonly Property<string> _laboratoryContactFax
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.LaboratoryContactFax", "", false);
|
||||
|
||||
public string LaboratoryContactEmail
|
||||
{
|
||||
get => _laboratoryContactEmail.Value;
|
||||
set => _laboratoryContactEmail.Value = value;
|
||||
}
|
||||
private readonly Property<string> _laboratoryContactEmail
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.LaboratoryContactEmail", "", false);
|
||||
|
||||
public string LaboratoryTestReferenceNumber
|
||||
{
|
||||
get => _laboratoryTestReferenceNumber.Value;
|
||||
set => _laboratoryTestReferenceNumber.Value = value;
|
||||
}
|
||||
private readonly Property<string> _laboratoryTestReferenceNumber
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.LaboratoryTestReferenceNumber", "", false);
|
||||
|
||||
public string LaboratoryProjectReferenceNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_laboratoryProjectReferenceNumber.IsValueInitialized) { return _laboratoryProjectReferenceNumber.Value; }
|
||||
return "";
|
||||
}
|
||||
set => _laboratoryProjectReferenceNumber.Value = value;
|
||||
}
|
||||
private readonly Property<string> _laboratoryProjectReferenceNumber
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.LaboratoryProjectReferenceNumber", "", false);
|
||||
|
||||
public string CustName
|
||||
{
|
||||
get => _custName.Value;
|
||||
set => _custName.Value = value;
|
||||
}
|
||||
private readonly Property<string> _custName
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.CustName", "", false);
|
||||
|
||||
public string CustomerName
|
||||
{
|
||||
get => _customerName.Value;
|
||||
set => _customerName.Value = value;
|
||||
}
|
||||
private readonly Property<string> _customerName
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.CustomerName", "", false);
|
||||
|
||||
public string CustomerTestReferenceNumber
|
||||
{
|
||||
get => _customerTestReferenceNumber.Value;
|
||||
set => _customerTestReferenceNumber.Value = value;
|
||||
}
|
||||
private readonly Property<string> _customerTestReferenceNumber
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.CustomerTestReferenceNumber", "", false);
|
||||
|
||||
public string CustomerProjectReferenceNumber
|
||||
{
|
||||
get => _customerProjectReferenceNumber.Value;
|
||||
set => _customerProjectReferenceNumber.Value = value;
|
||||
}
|
||||
private readonly Property<string> _customerProjectReferenceNumber
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.CustomerProjectReferenceNumber", "", false);
|
||||
|
||||
public string CustomerOrderNumber
|
||||
{
|
||||
get => _customerOrderNumber.Value;
|
||||
set => _customerOrderNumber.Value = value;
|
||||
}
|
||||
private readonly Property<string> _customerOrderNumber
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.CustomerOrderNumber", "", false);
|
||||
|
||||
public string CustomerCostUnit
|
||||
{
|
||||
get => _customerCostUnit.Value;
|
||||
set => _customerCostUnit.Value = value;
|
||||
}
|
||||
private readonly Property<string> _customerCostUnit
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.CustomerCostUnit", "", false);
|
||||
|
||||
public string TEName
|
||||
{
|
||||
get => _teName.IsValueInitialized ? _teName.Value : "";
|
||||
set => _teName.Value = value;
|
||||
}
|
||||
private readonly Property<string> _teName
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.TEName", "", false);
|
||||
|
||||
public string TestEngineerName
|
||||
{
|
||||
get => _testEngineerName.Value;
|
||||
set => _testEngineerName.Value = value;
|
||||
}
|
||||
private readonly Property<string> _testEngineerName
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.TestEngineerName", "", false);
|
||||
|
||||
public string TestEngineerPhone
|
||||
{
|
||||
get => _testEngineerPhone.Value;
|
||||
set => _testEngineerPhone.Value = value;
|
||||
}
|
||||
private readonly Property<string> _testEngineerPhone
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.TestEngineerPhone", "", false);
|
||||
|
||||
public string TestEngineerFax
|
||||
{
|
||||
get => _testEngineerFax.Value;
|
||||
set => _testEngineerFax.Value = value;
|
||||
}
|
||||
private readonly Property<string> _testEngineerFax
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.TestEngineerFax", "", false);
|
||||
|
||||
public string TestEngineerEmail
|
||||
{
|
||||
get => _testEngineerEmail.Value;
|
||||
set => _testEngineerEmail.Value = value;
|
||||
}
|
||||
private readonly Property<string> _testEngineerEmail
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.TestEngineerEmail", "", false);
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name.Value;
|
||||
set => _name.Value = value;
|
||||
}
|
||||
private readonly Property<string> _name
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.Name", "", false);
|
||||
|
||||
public string NumberOfTestObjects
|
||||
{
|
||||
get => _numberOfTestObjects.Value;
|
||||
set => _numberOfTestObjects.Value = value;
|
||||
}
|
||||
private readonly Property<string> _numberOfTestObjects
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.NumberOfTestObjects", "", false);
|
||||
|
||||
public string NumberOfMedia
|
||||
{
|
||||
get => _numberOfMedia.Value;
|
||||
set => _numberOfMedia.Value = value;
|
||||
}
|
||||
private readonly Property<string> _numberOfMedia
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.NumberOfMedia", "", false);
|
||||
|
||||
public string ReferenceTemperature
|
||||
{
|
||||
get => _referenceTemperature.Value;
|
||||
set => _referenceTemperature.Value = value;
|
||||
}
|
||||
private readonly Property<string> _referenceTemperature
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.ReferenceTemperature", "", false);
|
||||
|
||||
public string Regulation
|
||||
{
|
||||
get => _regulation.Value;
|
||||
set => _regulation.Value = value;
|
||||
}
|
||||
private readonly Property<string> _regulation
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.Regulation", "", false);
|
||||
|
||||
public string RelativeAirHumidity
|
||||
{
|
||||
get => _relativeAirHumidity.Value;
|
||||
set => _relativeAirHumidity.Value = value;
|
||||
}
|
||||
private readonly Property<string> _relativeAirHumidity
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.RelativeAirHumidity", "", false);
|
||||
|
||||
public string Subtype
|
||||
{
|
||||
get => _subtype.Value;
|
||||
set => _subtype.Value = value;
|
||||
}
|
||||
private readonly Property<string> _subtype
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.Subtype", "", false);
|
||||
|
||||
public string TestComment
|
||||
{
|
||||
get => _testComment.Value;
|
||||
set => _testComment.Value = value;
|
||||
}
|
||||
private readonly Property<string> _testComment
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.TestComment", "", false);
|
||||
|
||||
public List<ExtraProperty> ExtraProperties
|
||||
{
|
||||
get => _extraProperties.Value;
|
||||
set => _extraProperties.Value = value;
|
||||
}
|
||||
private readonly Property<List<ExtraProperty>> _extraProperties
|
||||
= new Property<List<ExtraProperty>>(typeof(TestSetup).Namespace + ".TestSetup.ExtraProperties", new List<ExtraProperty>(), true);
|
||||
|
||||
public List<TestObject> TestObjects
|
||||
{
|
||||
get => _testObjects.Value;
|
||||
set => _testObjects.Value = value;
|
||||
}
|
||||
private readonly Property<List<TestObject>> _testObjects
|
||||
= new Property<List<TestObject>>(typeof(TestSetup).Namespace + ".TestSetup.TestObjects", new List<TestObject>(), true);
|
||||
|
||||
public string Timestamp
|
||||
{
|
||||
get => _timestamp.Value;
|
||||
set => _timestamp.Value = value;
|
||||
}
|
||||
private readonly Property<string> _timestamp
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.Timestamp", "", false);
|
||||
|
||||
public string TypeOfTheTest
|
||||
{
|
||||
get => _typeOfTheTest.Value;
|
||||
set => _typeOfTheTest.Value = value;
|
||||
}
|
||||
private readonly Property<string> _typeOfTheTest
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.TypeOfTheTest", "", false);
|
||||
|
||||
public virtual string Version
|
||||
{
|
||||
get => _version.Value;
|
||||
set => _version.Value = value;
|
||||
}
|
||||
private readonly Property<string> _version
|
||||
= new Property<string>(typeof(TestSetup).Namespace + ".TestSetup.Version", "", false);
|
||||
|
||||
//Placeholder for all graph channels
|
||||
[System.Xml.Serialization.XmlIgnore]
|
||||
public List<Graph.Channel> Channels = new List<Graph.Channel>();
|
||||
|
||||
//Placeholder for Single Channel Graphs
|
||||
[System.Xml.Serialization.XmlIgnore]
|
||||
public List<Graph> SingleChannelGraphs = new List<Graph>();
|
||||
|
||||
[System.Xml.Serialization.XmlIgnore]
|
||||
public IDictionary<Guid, Graph> SortedGraphs = new Dictionary<Guid, Graph>();
|
||||
|
||||
/*
|
||||
* Display listing of graphs is a little funny:
|
||||
* First come defined multi-channel graphs in the order that they are listed in the .dts file.
|
||||
* Next come the single channel files that are created when a dts file is read in sorted by display order
|
||||
* Finally come all the calculated channels, sorted in display order.
|
||||
*/
|
||||
|
||||
public void SortGraphs()
|
||||
{
|
||||
SortedGraphs.Clear();
|
||||
|
||||
foreach (var g in Graphs)
|
||||
{
|
||||
SortedGraphs.Add(g.Identifier, g);
|
||||
}
|
||||
|
||||
//All of the multi channel graphs are in the dictionary in the correct order, now sort the single channel graphs.
|
||||
SingleChannelGraphs.Sort(GraphDisplayOrderComparer);
|
||||
|
||||
//Add them to the dictionary
|
||||
foreach (var g in SingleChannelGraphs)
|
||||
{
|
||||
SortedGraphs.Add(g.Identifier, g);
|
||||
}
|
||||
}
|
||||
|
||||
private int GraphDisplayOrderComparer(Graph a, Graph b)
|
||||
{
|
||||
if (a == b) { return 0; }
|
||||
if (null == a) { return -1; }
|
||||
if (null == b) { return 1; }
|
||||
|
||||
return a.FirstTestChannel.AbsoluteDisplayOrder.CompareTo(b.FirstTestChannel.AbsoluteDisplayOrder);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,72 @@
|
||||
using IRIGCh10;
|
||||
using System;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10
|
||||
{
|
||||
//public class WriteTest
|
||||
//{
|
||||
// public static void Write()
|
||||
// {
|
||||
// var ch10File = new Chapter10File();
|
||||
|
||||
// ch10File.AddPacket(CreateTMATSPacket());
|
||||
// ch10File.AddPacket(CreateTimePacket());
|
||||
// ch10File.AddPacket(CreateUserDefinedPacket());
|
||||
// ch10File.AddPacket(CreatePCMPacket());
|
||||
// }
|
||||
|
||||
// private const long REFERENCE_RTC = 141989612500056;
|
||||
// private const long SECOND_RTC = 141989612612992;
|
||||
// private const long THIRD_RTC = 141989612606736;
|
||||
// private static IDataPacket CreateTMATSPacket()
|
||||
// {
|
||||
// var tmats = new TMATSPacket();
|
||||
// tmats.SetRTC(REFERENCE_RTC);
|
||||
// var s = TMATSCreationTest.CreateTMATS();
|
||||
// tmats.SetTMATSDocument(s);
|
||||
// return tmats;
|
||||
// }
|
||||
|
||||
// private static IDataPacket CreatePCMPacket()
|
||||
// {
|
||||
// var pcmPacket = new PCMPacket();
|
||||
// pcmPacket.SetRTC(THIRD_RTC);
|
||||
// pcmPacket.SetChannelID(BitConverter.ToUInt16(new byte[] { 0x00, 0x0A}, 0));
|
||||
// pcmPacket.SetDataVersion(Enums.DataTypeVersion.TG78);
|
||||
// pcmPacket.SetSequenceNumber(0);
|
||||
// pcmPacket.SetPacketFlags(false, false, false, false, Enums.SecondaryHeaderTimeFormat.IRIG106Chapter4,
|
||||
// Enums.DataCheckSumType.ThirtyTwoBit);
|
||||
// var data = new ushort[625];
|
||||
|
||||
// var amplitude = .25 * short.MaxValue;
|
||||
// var frequency = 1000;
|
||||
// for (var i = 0; i < data.Length; i++)
|
||||
// {
|
||||
// var val = (ushort)(0x8000 + amplitude * Math.Sin(2 * Math.PI * i * frequency) / 625);
|
||||
// }
|
||||
// //pcmPacket.SetThroughputData(data);
|
||||
// return pcmPacket;
|
||||
// }
|
||||
// private static IDataPacket CreateTimePacket()
|
||||
// {
|
||||
// var timePacket = new TimeDataPacket();
|
||||
// timePacket.SetRTC(SECOND_RTC);
|
||||
// timePacket.SetTime(new DateTime(2018, 11, 20, 22, 51, 11, 320));
|
||||
// timePacket.SetTimeFormat(Enums.TimeFormats.IRIGB);
|
||||
// timePacket.SetTimeSource(0x03);
|
||||
// timePacket.SetChannelID(BitConverter.ToUInt16(new byte[] {0xFF, 0xFF}, 0));
|
||||
// timePacket.SetDataVersion(Enums.DataTypeVersion.TG78);
|
||||
// timePacket.SetPacketFlags(false, false, false, false, Enums.SecondaryHeaderTimeFormat.IRIG106Chapter4,
|
||||
// Enums.DataCheckSumType.ThirtyTwoBit);
|
||||
// timePacket.SetSequenceNumber(1);
|
||||
// var bytes = timePacket.GetBytes();
|
||||
// return timePacket;
|
||||
// }
|
||||
|
||||
// private static IDataPacket CreateUserDefinedPacket()
|
||||
// {
|
||||
// var userPacket = new UserDefinedPacket();
|
||||
// return userPacket;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* SoMat.File.Writer.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DTS.Serialization.DDAS
|
||||
{
|
||||
// *** see DDAS.File.Writer.cs ***
|
||||
public partial class File
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Utility object for serializing <see cref="DTS.Serialization.Test"/>s to disk
|
||||
/// in the Diadem
|
||||
/// </summary>
|
||||
///
|
||||
public class Writer : Writer<File>, IWriter<Test>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize an instance of the SoMat.File.Writer class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="fileType">
|
||||
/// The associated <see cref="DTS.SErialization.Diadem.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)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of data samples that need to be written for a "tick" to be dispatched.
|
||||
/// </summary>
|
||||
private int DataSamplesPerTick => 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Return the number of data to be written per "tick".
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
/// <returns></returns>
|
||||
private uint GetChannelTicks(Test.Module.Channel channel)
|
||||
{
|
||||
try
|
||||
{ //
|
||||
// Most of our wait time will be spent writing data, so we need to give
|
||||
// the process a little finer granularity.
|
||||
//
|
||||
return (uint)(channel.PersistentChannelInfo.Length / DataSamplesPerTick);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem determining number of status ticks for channel " + (null != channel ? "\"" + channel.Number.ToString() + "\"" : "<NULL>"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public string ExtensionPrefix { get; set; } = string.Empty;
|
||||
public DDASTest MyTVTTest { get; set; }
|
||||
/// <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)
|
||||
{
|
||||
System.Exception exception = null;
|
||||
uint totalWriteTicksNeeded = 0;
|
||||
if (test.Channels.Count > 0)
|
||||
totalWriteTicksNeeded = GetChannelTicks(test.Channels[0]);
|
||||
try
|
||||
{
|
||||
beginEventHandler?.Invoke(this, totalWriteTicksNeeded); foreach (var channel in MyTVTTest.Channels) { channel.Serialize(tickEventHandler); }
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
}
|
||||
tickEventHandler?.Invoke(this, 100D);
|
||||
if (null != errorEventHandler && null != exception)
|
||||
{
|
||||
endEventHandler(this);
|
||||
errorEventHandler(this, exception);
|
||||
}
|
||||
else if (null != exception) { throw exception; }
|
||||
else
|
||||
{
|
||||
tickEventHandler?.Invoke(this, 100.0);
|
||||
endEventHandler?.Invoke(this);
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<section name="DTS.Serialization.Properties.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
|
||||
<section name="DTS.Serialization.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
|
||||
</sectionGroup>
|
||||
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<section name="DTS.Serialization.Properties.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<userSettings>
|
||||
<DTS.Serialization.Properties.Settings1>
|
||||
<setting name="TDMFolder" serializeAs="String">
|
||||
<value>.\Data\TDM CFC1000</value>
|
||||
</setting>
|
||||
<setting name="DefaultStart" serializeAs="String">
|
||||
<value>-500</value>
|
||||
</setting>
|
||||
<setting name="DefaultStop" serializeAs="String">
|
||||
<value>500</value>
|
||||
</setting>
|
||||
<setting name="TSVPOCNameLastUsed" serializeAs="String">
|
||||
<value>#NOVALUE</value>
|
||||
</setting>
|
||||
<setting name="TSVPOCPhoneAndEmailLastUsed" serializeAs="String">
|
||||
<value>#NOVALUE</value>
|
||||
</setting>
|
||||
<setting name="TSVDataTypeLastUsed" serializeAs="String">
|
||||
<value>Converted</value>
|
||||
</setting>
|
||||
<setting name="TSVLabNameLastUsed" serializeAs="String">
|
||||
<value>#NOVALUE</value>
|
||||
</setting>
|
||||
<setting name="TSVTestObjectLastUsed" serializeAs="String">
|
||||
<value>#NOVALUE</value>
|
||||
</setting>
|
||||
<setting name="TSVTestTypeLastUsed" serializeAs="String">
|
||||
<value>#NOVALUE</value>
|
||||
</setting>
|
||||
<setting name="AlternatingRow" serializeAs="String">
|
||||
<value>238, 242, 255</value>
|
||||
</setting>
|
||||
</DTS.Serialization.Properties.Settings1>
|
||||
<DTS.Serialization.Settings1>
|
||||
<setting name="TDMFolder" serializeAs="String">
|
||||
<value>.\Data\TDM CFC1000</value>
|
||||
</setting>
|
||||
</DTS.Serialization.Settings1>
|
||||
</userSettings>
|
||||
<applicationSettings>
|
||||
<DTS.Serialization.Properties.Settings1>
|
||||
<setting name="TableHeader" serializeAs="String">
|
||||
<value>215, 225, 255</value>
|
||||
</setting>
|
||||
</DTS.Serialization.Properties.Settings1>
|
||||
</applicationSettings>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Iso.File.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
using DTS.Serialization.Iso.Report;
|
||||
|
||||
// ISO implementation items:
|
||||
// ------------------------
|
||||
// * Do properly dynamically-presented/not-there-at-all comments.
|
||||
// * Comments.txt file.
|
||||
// * Progress reporting.
|
||||
|
||||
namespace DTS.Serialization.Iso
|
||||
{
|
||||
public partial class File
|
||||
: Serialization.File,
|
||||
IWritable<Test>
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether to export a summary report with the iso export
|
||||
/// http://manuscript.dts.local/f/cases/43833/SW-Test-Summary-Report-for-data-collection-THF
|
||||
/// </summary>
|
||||
public bool ExportSummaryReport { get; set; } = false;
|
||||
|
||||
private readonly Common.ISO.TestPlan _testPlan = null;
|
||||
public Common.ISO.TestPlan GetTestPlan() { return _testPlan; }
|
||||
///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the Iso.File class.
|
||||
/// </summary>
|
||||
///
|
||||
public File(Common.ISO.TestPlan testplan)
|
||||
: base("ISO")
|
||||
{
|
||||
_testPlan = testplan;
|
||||
}
|
||||
public bool UseZeroForUnfiltered { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// when true forces the isocode for filter to by determined by the software filter for the channel
|
||||
/// </summary>
|
||||
public bool UseIsoCodeFilterMapping { get; set; }
|
||||
public bool FilteredExport { get; set; } = false;
|
||||
public bool ExportISOChannelName { get; set; } = false;
|
||||
|
||||
public void AddChannel(string dasserial, int moduleNumber, int number, string description, FilteredData data)
|
||||
{
|
||||
(Exporter as Writer).AddChannel(dasserial, moduleNumber, number, description, data);
|
||||
}
|
||||
|
||||
public void ApplyTestPlan(Serialization.Test test)
|
||||
{
|
||||
foreach (Common.ISO.TestPlan.IsoFields field in Enum.GetValues(typeof(Common.ISO.TestPlan.IsoFields)))
|
||||
{
|
||||
var value = GetTestPlan().GetField(field);
|
||||
switch (field)
|
||||
{
|
||||
case Common.ISO.TestPlan.IsoFields.CustName:
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.CustomerCostUnit:
|
||||
TestInstance.CustomerCostUnit = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.CustomerName:
|
||||
TestInstance.CustomerName = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.CustomerOrderNumber:
|
||||
TestInstance.CustomerOrderNumber = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.CustomerProjectReferenceNumber:
|
||||
TestInstance.CustomerProjectReferenceNumber = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TEName:
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TestEngineerEmail:
|
||||
TestInstance.TestEngineerEmail = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TestEngineerFax:
|
||||
TestInstance.TestEngineerFax = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TestEngineerName:
|
||||
TestInstance.TestEngineerName = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TestEngineerPhone:
|
||||
TestInstance.TestEngineerPhone = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.CustomerTestReferenceNumber:
|
||||
TestInstance.CustomerTestReferenceNumber = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.Date:
|
||||
if (DateTime.TryParse(value, out var temp))
|
||||
{
|
||||
TestInstance.Date = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
TestInstance.Date = test.InceptionDate;
|
||||
}
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.ExtraProperties:
|
||||
TestInstance.ExtraProperties = GetTestPlan().ExtraProperties.Select(kvp => new Test.ExtraProperty(kvp.Key, kvp.Value)).ToList();
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LabName:
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryContactEmail:
|
||||
TestInstance.LaboratoryContactEmail = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryContactFax:
|
||||
TestInstance.LaboratoryContactFax = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryContactName:
|
||||
TestInstance.LaboratoryContactName = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryContactPhone:
|
||||
TestInstance.LaboratoryContactPhone = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryName:
|
||||
TestInstance.LaboratoryName = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryTestReferenceNumber:
|
||||
TestInstance.LaboratoryTestReferenceNumber = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryProjectReferenceNumber:
|
||||
TestInstance.LaboratoryProjectReferenceNumber = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.NumberOfMedia:
|
||||
TestInstance.NumberOfMedia = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.NumberOfTestObjects:
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.ReferenceTemperature:
|
||||
TestInstance.ReferenceTemperature = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.Regulation:
|
||||
TestInstance.Regulation = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.RelativeAirHumidity:
|
||||
TestInstance.RelativeAirHumidity = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.Subtype:
|
||||
TestInstance.Subtype = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TestComment:
|
||||
TestInstance.TestComment = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.Title:
|
||||
TestInstance.Title = value == NoValue ? test.Id : value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.Type:
|
||||
TestInstance.Type = value;
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("unsupported iso field");
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Get the file writer for this file type.
|
||||
/// </summary>
|
||||
public IWriter<Serialization.Test> Exporter
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_Exporter == null)
|
||||
{
|
||||
var writer = new Writer(this, DefaultEncoding, this);
|
||||
writer.UseZeroForUnfiltered = UseZeroForUnfiltered;
|
||||
writer.UseIsoCodeFilterMapping = UseIsoCodeFilterMapping;
|
||||
writer.FilteredExport = FilteredExport;
|
||||
writer.ExportISOChannelName = ExportISOChannelName;
|
||||
writer.ExportSummaryReport = ExportSummaryReport;
|
||||
_Exporter = writer;
|
||||
}
|
||||
return _Exporter;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting exporter", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private IWriter<Serialization.Test> _Exporter = null;
|
||||
|
||||
/// <summary>
|
||||
/// File extension for the disk entity that contains the serialized test information.
|
||||
/// </summary>
|
||||
public static string TestFileExtension
|
||||
{
|
||||
get => _TestFileExtension.Value;
|
||||
private set => _TestFileExtension.Value = value;
|
||||
}
|
||||
private static readonly Property<string> _TestFileExtension = new Property<string>("TestFileExtension", ".mme", true);
|
||||
|
||||
/// <summary>
|
||||
/// File extension for the disk entity that contains serialized channel information.
|
||||
/// </summary>
|
||||
public static string ChannelFileExtension
|
||||
{
|
||||
get => _ChannelFileExtension.Value;
|
||||
private set => _ChannelFileExtension.Value = value;
|
||||
}
|
||||
private static readonly Property<string> _ChannelFileExtension = new Property<string>("ChannelFileExtension", ".chn", true);
|
||||
|
||||
/// <summary>
|
||||
/// String representation of a value-less field.
|
||||
/// </summary>
|
||||
private const string NoValue = "NOVALUE";
|
||||
|
||||
/// <summary>
|
||||
/// Line terminator to use when printing out files.
|
||||
/// </summary>
|
||||
private static readonly string Eol = Environment.NewLine;
|
||||
|
||||
/// <summary>
|
||||
/// Attribute/value seperator to use when printing out files.
|
||||
/// </summary>
|
||||
private const string Separator = ":";
|
||||
|
||||
/// <summary>
|
||||
/// Offset to use for attribute/value seperator when printing out files.
|
||||
/// </summary>
|
||||
private const int SeparatorOffset = 28;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for extracting the value of a field in a controllable context e.g., in
|
||||
/// a try/catch block.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="string"/> representation of the field.
|
||||
/// </returns>
|
||||
///
|
||||
private delegate string FieldValueStringExtractor();
|
||||
|
||||
/// <summary>
|
||||
/// Get a string representation of the field wrapped within the extractor delegate.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="extractor">
|
||||
/// The <see cref="DTS.Serialization.File.Iso.File.FieldValueStringExtractor"/> wrapping the
|
||||
/// field to be stringified.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// A <see cref="string"/> version of the field; "NOVALUE" if the field has not been initialized.
|
||||
/// </returns>
|
||||
///
|
||||
private static string GetFieldString(FieldValueStringExtractor extractor)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{ //
|
||||
// Empty string is no value.
|
||||
//
|
||||
|
||||
var fieldString = extractor();
|
||||
return (!string.IsNullOrEmpty(fieldString) ? fieldString : NoValue);
|
||||
}
|
||||
|
||||
catch (System.Exception)
|
||||
{
|
||||
return NoValue;
|
||||
}
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting field string from field extractor", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the <see cref="Iso.File.Test"/> associated with this file.
|
||||
/// </summary>
|
||||
public Test TestInstance => _TestInstance.Value;
|
||||
|
||||
private readonly Property<Test> _TestInstance
|
||||
= new Property<Test>(
|
||||
typeof(Test).Namespace + ".Iso.File.TestInstance",
|
||||
new Test(),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using DTS.Utilities;
|
||||
using DTS.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
public partial class TestSetup : Exceptional
|
||||
{
|
||||
public partial class TestObject : Exceptional
|
||||
{
|
||||
public partial class DASHardware : Exceptional
|
||||
{
|
||||
public partial class DASChannel : Exceptional
|
||||
{
|
||||
public DASChannel()
|
||||
{
|
||||
_Location.Value = null;
|
||||
_MeasurementUnits.Value = null;
|
||||
_Name.Value = null;
|
||||
_NumberOfSamples.Value = null;
|
||||
_SerialNumber.Value = null;
|
||||
_Version.Value = "1.0.0.0";
|
||||
}
|
||||
|
||||
public string Location
|
||||
{
|
||||
get { return _Location.Value; }
|
||||
set { _Location.Value = value; }
|
||||
}
|
||||
private Property<string> _Location
|
||||
= new Property<string>(typeof(DASHardware).Namespace + ".DASChannel.Location", "", false);
|
||||
|
||||
public string MeasurementUnits
|
||||
{
|
||||
get { return _MeasurementUnits.Value; }
|
||||
set { _MeasurementUnits.Value = value; }
|
||||
}
|
||||
private Property<string> _MeasurementUnits
|
||||
= new Property<string>(typeof(DASHardware).Namespace + ".DASChannel.MeasurementUnits", "", false);
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _Name.Value; }
|
||||
set { _Name.Value = value; }
|
||||
}
|
||||
private Property<string> _Name
|
||||
= new Property<string>(typeof(DASHardware).Namespace + ".DASChannel.Name", "", false);
|
||||
|
||||
public string NumberOfSamples
|
||||
{
|
||||
get { return _NumberOfSamples.Value; }
|
||||
set { _NumberOfSamples.Value = value; }
|
||||
}
|
||||
private Property<string> _NumberOfSamples
|
||||
= new Property<string>(typeof(DASHardware).Namespace + ".DASChannel.NumberOfSamples", "", false);
|
||||
|
||||
public string SensorName
|
||||
{
|
||||
get { return _SensorName.Value; }
|
||||
set { _SensorName.Value = value; }
|
||||
}
|
||||
private Property<string> _SensorName
|
||||
= new Property<string>(typeof(DASHardware).Namespace + ".DASChannel.SensorName", "", false);
|
||||
|
||||
public string SerialNumber
|
||||
{
|
||||
get { return _SerialNumber.Value; }
|
||||
set { _SerialNumber.Value = value; }
|
||||
}
|
||||
private Property<string> _SerialNumber
|
||||
= new Property<string>(typeof(DASHardware).Namespace + ".DASChannel.SerialNumber", "", false);
|
||||
|
||||
public string Version
|
||||
{
|
||||
get { return _Version.Value; }
|
||||
set { _Version.Value = value; }
|
||||
}
|
||||
private Property<string> _Version
|
||||
= new Property<string>(typeof(DASHardware).Namespace + ".DASChannel.Version", "", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Test.Module.Channel.IConvertable.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
// *** see Test.Module.cs ***
|
||||
public partial class Module
|
||||
{
|
||||
// *** see Test.Module.Channel.cs ***
|
||||
public partial class Channel
|
||||
{
|
||||
/// <summary>
|
||||
/// An object that expresses this interface can convert itself to and from a
|
||||
/// <see cref="DTS.Serialization.Test.Module.Channel"/> object.
|
||||
/// </summary>
|
||||
///
|
||||
public interface IConvertable
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert this object to a <see cref="DTS.Serialization.Test.Module.Channel"/>.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="DTS.Serialization.Test.Module.Channel"/> equivalent of this object.
|
||||
/// </returns>
|
||||
///
|
||||
Channel ToDtsSerializationTestModuleChannel();
|
||||
|
||||
/// <summary>
|
||||
/// Initialize this object using the specified <see cref="DTS.Serialization.Test.Module.Channel"/>.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="channel">
|
||||
/// The <see cref="DTS.Serialization.Test.Module.Channel"/> with which this object will be
|
||||
/// initialized from.
|
||||
/// </param>
|
||||
///
|
||||
void FromDtsSerializationTestModuleChannel(Channel channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.Serialization.IRIGCh10.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// allows annotating an enum with a value,
|
||||
/// see TABLE 10-7. DATA TYPE NAMES AND DESCRIPTIONS in Chapter 10 pdf
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class PacketHeaderValueAttribute : Attribute
|
||||
{
|
||||
/// <summary>Specifies the default value for the <see cref="PacketHeaderValueAttribute" />, which is 0x00. This <see langword="static" /> field is read-only.</summary>
|
||||
public static readonly PacketHeaderValueAttribute Default = new PacketHeaderValueAttribute();
|
||||
private byte _packetHeader;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="PacketHeaderValueAttribute" /> class with no parameters.</summary>
|
||||
public PacketHeaderValueAttribute()
|
||||
: this(0x00)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="PacketHeaderValueAttribute" /> class with a PacketHeader.</summary>
|
||||
/// <param name="packetHeader">packet header value. </param>
|
||||
public PacketHeaderValueAttribute(byte packetHeader)
|
||||
{
|
||||
_packetHeader = packetHeader;
|
||||
}
|
||||
|
||||
/// <summary>Gets the packet header value stored in this attribute.</summary>
|
||||
/// <returns>The packet header value stored in this attribute.</returns>
|
||||
public virtual byte PacketHeader => PacketHeaderValue;
|
||||
|
||||
/// <summary>Gets or sets the byte stored as the packet header value.</summary>
|
||||
/// <returns>The byte stored as the packet header version value. The default value is 0x00.</returns>
|
||||
protected byte PacketHeaderValue
|
||||
{
|
||||
get => _packetHeader;
|
||||
set => _packetHeader = value;
|
||||
}
|
||||
|
||||
/// <summary>Returns whether the value of the given object is equal to the current <see cref="PacketHeaderValueAttribute" />.</summary>
|
||||
/// <param name="obj">The object to test the value equality of. </param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if the value of the given object is equal to that of the current; otherwise, <see langword="false" />.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == this)
|
||||
return true;
|
||||
if (obj is PacketHeaderValueAttribute packetHeaderAttribute)
|
||||
return packetHeaderAttribute.PacketHeader == PacketHeader;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Returns the hash code for this instance.</summary>
|
||||
/// <returns>A 32-bit signed integer hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return PacketHeader.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>Returns a value indicating whether this is the default <see cref="PacketHeaderValueAttribute" /> instance.</summary>
|
||||
/// <returns>
|
||||
/// <see langword="true" />, if this is the default <see cref="PacketHeaderValueAttribute" /> instance; otherwise, <see langword="false" />.</returns>
|
||||
public override bool IsDefaultAttribute()
|
||||
{
|
||||
return Equals(Default);
|
||||
}
|
||||
|
||||
public static byte GetPacketHeaderValue(Enum value)
|
||||
{
|
||||
var fi = value.GetType().GetField(value.ToString());
|
||||
var attributes = (PacketHeaderValueAttribute[])fi.GetCustomAttributes(
|
||||
typeof(PacketHeaderValueAttribute), false);
|
||||
if (attributes.Any())
|
||||
{
|
||||
return attributes.First().PacketHeaderValue;
|
||||
}
|
||||
return Default.PacketHeaderValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
Test.Module.AnalogInputChannel.cs
|
||||
|
||||
Copyright © 2008
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
using System.ComponentModel;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.Utilities.Xml;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
// *** see Test.Module.cs ***
|
||||
public partial class Module
|
||||
{
|
||||
/// <summary>
|
||||
/// Representation of a calculated channel.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("CalculatedChannel")]
|
||||
public class CalculatedChannel : AnalogInputChannel
|
||||
{
|
||||
public CalculatedChannel(Module parentModule)
|
||||
: base(parentModule)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the Source Channel for this channel.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("SourceChannelNumber")]
|
||||
public int[] SourceChannelNumber
|
||||
{
|
||||
get => _SourceChannelNumber.Value;
|
||||
set => _SourceChannelNumber.Value = value;
|
||||
}
|
||||
private readonly Property<int[]> _SourceChannelNumber
|
||||
= new Property<int[]>(
|
||||
typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.SourceChannelNumber",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the Source Channel for this channel.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("SourceModuleNumber")]
|
||||
public int[] SourceModuleNumber
|
||||
{
|
||||
get => _SourceModuleNumber.Value;
|
||||
set => _SourceModuleNumber.Value = value;
|
||||
}
|
||||
private readonly Property<int[]> _SourceModuleNumber
|
||||
= new Property<int[]>(
|
||||
typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.SourceModuleNumber",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the Source Channel for this channel.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("SourceModuleSerialNumber")]
|
||||
public string[] SourceModuleSerialNumber
|
||||
{
|
||||
get => _SourceModuleSerialNumber.Value;
|
||||
set => _SourceModuleSerialNumber.Value = value;
|
||||
}
|
||||
private readonly Property<string[]> _SourceModuleSerialNumber
|
||||
= new Property<string[]>(
|
||||
typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.SourceModuleSerialNumber",
|
||||
null,
|
||||
false
|
||||
);
|
||||
/// <summary>
|
||||
/// the calculation for the channel(s) involved
|
||||
/// </summary>
|
||||
[XmlSerializationTag("Calculation")]
|
||||
public string Calculation
|
||||
{
|
||||
get => _Calculation.Value;
|
||||
set => _Calculation.Value = value;
|
||||
}
|
||||
private readonly Property<string> _Calculation
|
||||
= new Property<string>(
|
||||
typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.Calculation",
|
||||
"NONE",
|
||||
false
|
||||
);
|
||||
|
||||
[XmlSerializationTag("T1")]
|
||||
public ulong T1
|
||||
{
|
||||
get => _T1.Value;
|
||||
set => _T1.Value = value;
|
||||
}
|
||||
private readonly Property<ulong> _T1
|
||||
= new Property<ulong>(
|
||||
typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.T1",
|
||||
0,
|
||||
false);
|
||||
|
||||
[XmlSerializationTag("T2")]
|
||||
public ulong T2
|
||||
{
|
||||
get => _T2.Value;
|
||||
set => _T2.Value = value;
|
||||
}
|
||||
private readonly Property<ulong> _T2
|
||||
= new Property<ulong>(
|
||||
typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.T2",
|
||||
0,
|
||||
false);
|
||||
|
||||
[XmlSerializationTag("HIC")]
|
||||
public double HIC
|
||||
{
|
||||
get => _HIC.Value;
|
||||
set => _HIC.Value = value;
|
||||
}
|
||||
private readonly Property<double> _HIC
|
||||
= new Property<double>(
|
||||
typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.HIC",
|
||||
0D,
|
||||
false);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the sample rate for this test module.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("SampleRateHz")]
|
||||
public double SampleRateHz
|
||||
{
|
||||
get => _SampleRateHz.Value;
|
||||
set => _SampleRateHz.Value = value;
|
||||
}
|
||||
private readonly Property<double> _SampleRateHz
|
||||
= new Property<double>(
|
||||
typeof(CalculatedChannel).Namespace + ".Test.Module.CalculatedChannel.SampleRateHz",
|
||||
0,
|
||||
false
|
||||
);
|
||||
|
||||
private const string BeginTagModifier = "Begin";
|
||||
private const string EndTagModifier = "End";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Write XML serialization for this object to the specified writer.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="writer">
|
||||
/// The <see cref="XmlWriter"/> to which this object's XML serialization
|
||||
/// will be written.
|
||||
/// </param>
|
||||
///
|
||||
public override void WriteXml(XmlWriter writer)
|
||||
{
|
||||
try
|
||||
{
|
||||
APILogger.Log("writing CalculatedChannel::WriteXML");
|
||||
var cult = new System.Globalization.CultureInfo("");
|
||||
var attributeExtractor = new AttributeExtractor<XmlSerializationTagAttribute>();
|
||||
|
||||
writer.WriteStartElement(attributeExtractor.ExtractAttachedAttributeFromObject(this).Value);
|
||||
|
||||
writeXmlAttributes(writer);
|
||||
|
||||
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this,
|
||||
"SourceChannelNumber").Value, IntArrayToString(SourceChannelNumber));
|
||||
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this,
|
||||
"SourceModuleNumber").Value, IntArrayToString(SourceModuleNumber));
|
||||
writer.WriteAttributeString(
|
||||
attributeExtractor.ExtractAttachedAttributeFromProperty(this, "SourceModuleSerialNumber")
|
||||
.Value, StringArrayToString(SourceModuleSerialNumber));
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this,
|
||||
"Calculation").Value, Calculation.ToString(cult));
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this,
|
||||
"SampleRateHz").Value, SampleRateHz.ToString(cult));
|
||||
|
||||
|
||||
if (_HIC.IsValueInitialized)
|
||||
{
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this,
|
||||
"HIC").Value, HIC.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this,
|
||||
"T1").Value, T1.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this,
|
||||
"T2").Value, T2.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem converting " + GetType().FullName + " object to XML: ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read XML serialization for this object from the specified reader.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="reader">
|
||||
/// The <see cref="XmlReader"/> from which this object's XML serialization
|
||||
/// will be read.
|
||||
/// </param>
|
||||
///
|
||||
public override void ReadXml(XmlReader reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cult = new System.Globalization.CultureInfo("");
|
||||
var attributeExtractor = new AttributeExtractor<XmlSerializationTagAttribute>();
|
||||
|
||||
var xmlAttributeDecoder
|
||||
= new PropertyAttributeDecoder<CalculatedChannel>(this);
|
||||
|
||||
base.ReadXml(reader);
|
||||
|
||||
SourceChannelNumber =
|
||||
StringToIntArray(xmlAttributeDecoder.ExtractStringProperty("SourceChannelNumber", reader));
|
||||
|
||||
SourceModuleNumber =
|
||||
StringToIntArray(xmlAttributeDecoder.ExtractStringProperty("SourceModuleNumber", reader));
|
||||
|
||||
SourceModuleSerialNumber =
|
||||
StringToStringArray(xmlAttributeDecoder.ExtractStringProperty("SourceModuleSerialNumber",
|
||||
reader));
|
||||
|
||||
Calculation = xmlAttributeDecoder.ExtractStringProperty("Calculation", reader);
|
||||
SampleRateHz = xmlAttributeDecoder.ExtractDoubleProperty("SampleRateHz", reader);
|
||||
|
||||
var s = reader.GetAttribute("HIC");
|
||||
if (!string.IsNullOrWhiteSpace(s))
|
||||
{
|
||||
HIC = Convert.ToDouble(s);
|
||||
T1 = Convert.ToUInt64(reader.GetAttribute("T1"));
|
||||
T2 = Convert.ToUInt64(reader.GetAttribute("T2"));
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem converting XML to " + GetType().FullName + " object", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private int[] StringToIntArray(string s)
|
||||
{
|
||||
var ints = new List<int>();
|
||||
var tokens = s.Split(new char[] { ',' });
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
if (int.TryParse(token, System.Globalization.NumberStyles.Any,
|
||||
System.Globalization.CultureInfo.InvariantCulture, out int i))
|
||||
{
|
||||
ints.Add(i);
|
||||
}
|
||||
}
|
||||
return ints.ToArray();
|
||||
}
|
||||
|
||||
private string[] StringToStringArray(string s)
|
||||
{
|
||||
var tokens = s.Split(new string[] { "_.-._" }, StringSplitOptions.None);
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private string IntArrayToString(int[] array)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var i in array)
|
||||
{
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
sb.Append(",");
|
||||
}
|
||||
sb.Append(i.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private string StringArrayToString(string[] array)
|
||||
{
|
||||
return string.Join("_.-._", array);
|
||||
}
|
||||
/// <summary>
|
||||
/// Test the specified object for equality with this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="obj">
|
||||
/// The <see cref="object"/> to be tested for equality.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if the specified object has memeberwise equality with
|
||||
/// this object; false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
var that = obj as CalculatedChannel;
|
||||
return (null != obj)
|
||||
|
||||
// Must-be-initialized properties.
|
||||
&& ChannelId.Equals(that.ChannelId)
|
||||
&& SourceChannelNumber.Equals(that.SourceChannelNumber)
|
||||
&& ChannelDescriptionString.Equals(that.ChannelDescriptionString)
|
||||
&& EngineeringUnits.Equals(that.EngineeringUnits, StringComparison.OrdinalIgnoreCase)
|
||||
&& Calculation.Equals(that.Calculation)
|
||||
&& IsoCode.Equals(that.IsoCode);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem equality-testing the object " + (null != obj ? "\"" + obj.ToString() + "\"" : "<<NULL>>"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the hash code for this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="int"/> hash code for this object.
|
||||
/// </returns>
|
||||
///
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ChannelDescriptionString;
|
||||
}
|
||||
/// <summary>
|
||||
/// creates a new calculated channel, with the modulenumbers, channelnumbers, and moduleserialnumbers composed of all the inputs
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="channels"></param>
|
||||
/// <returns></returns>
|
||||
public static CalculatedChannel CreateInstance(Channel[] channels)
|
||||
{
|
||||
var cc = new CalculatedChannel(channels.First().ParentModule);
|
||||
|
||||
var maxSampleRAte = channels.Select(ch => ch.ParentModule.SampleRateHz).Max();
|
||||
//CC only values
|
||||
var channelNumbers = new List<int>();
|
||||
var moduleNumbers = new List<int>();
|
||||
var moduleSerialNumbers = new List<string>();
|
||||
var sps = channels.First().ParentModule.SampleRateHz;
|
||||
foreach (var ch in channels)
|
||||
{
|
||||
channelNumbers.Add(ch.Number);
|
||||
moduleSerialNumbers.Add(ch.ParentModule.SerialNumber);
|
||||
if (0 != maxSampleRAte % ch.ParentModule.SampleRateHz)
|
||||
{
|
||||
throw new InvalidOperationException($"sample rate: {maxSampleRAte} is not a multiple of sample rate: {ch.ParentModule.SampleRateHz}");
|
||||
}
|
||||
}
|
||||
cc.SourceChannelNumber = channelNumbers.ToArray();
|
||||
cc.SourceModuleNumber = moduleNumbers.ToArray();
|
||||
cc.SourceModuleSerialNumber = moduleSerialNumbers.ToArray();
|
||||
cc.SampleRateHz = sps;
|
||||
|
||||
//Rip a copy. Can't use cloning
|
||||
foreach (
|
||||
PropertyDescriptor item in
|
||||
TypeDescriptor.GetProperties(
|
||||
channels.First() as AnalogInputChannel))
|
||||
{
|
||||
try
|
||||
{
|
||||
item.SetValue(cc, item.GetValue(channels.First()));
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
//need a copy not the original for linearization formula...
|
||||
cc.LinearizationFormula =
|
||||
new DTS.Common.Classes.Sensors.LinearizationFormula(
|
||||
(channels.First() as AnalogInputChannel).LinearizationFormula);
|
||||
return cc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// creates a calculated channel using a single source channel
|
||||
/// </summary>
|
||||
/// <param name="sourceChannel"></param>
|
||||
/// <returns></returns>
|
||||
public static CalculatedChannel CreateInstance(Channel sourceChannel)
|
||||
{
|
||||
//Dammit, need to manually clone properties from souce channel
|
||||
var cc = new CalculatedChannel(sourceChannel.ParentModule);
|
||||
|
||||
//CC only values
|
||||
cc.SourceChannelNumber = new int[] { sourceChannel.Number };
|
||||
cc.SourceModuleNumber = new int[] { sourceChannel.ParentModule.Number };
|
||||
cc.SourceModuleSerialNumber = new string[] { sourceChannel.ParentModule.SerialNumber };
|
||||
cc.SampleRateHz = sourceChannel.ParentModule.SampleRateHz;
|
||||
|
||||
//Rip a copy. Can't use cloning
|
||||
foreach (PropertyDescriptor item in TypeDescriptor.GetProperties(sourceChannel as AnalogInputChannel))
|
||||
{
|
||||
try
|
||||
{
|
||||
item.SetValue(cc, item.GetValue(sourceChannel));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* DTS.Slice.Control.Event.DasModuleChannelAccessor.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using DTS.Common.Utilities;
|
||||
|
||||
namespace DTS.Slice.Control
|
||||
{
|
||||
// *** see DTS.Slice.Control.Event.cs ***
|
||||
public partial class Event
|
||||
{
|
||||
/// <summary>
|
||||
/// An object returned during Event creation that allows access to the event's channel information
|
||||
/// by DAS ID/DAS module number/module channel number triplet.
|
||||
/// </summary>
|
||||
public class DasModuleChannelAccessor : ExceptionalDictionary<Common.DAS.Concepts.DAS.Id, ModuleChannelAccessor>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Slice.Control.Event.DasModuleChannelAccessor class.
|
||||
/// </summary>
|
||||
public DasModuleChannelAccessor() { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,886 @@
|
||||
/*
|
||||
* DTS.Slice.Control.Event.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using DTS.DASLib.Service;
|
||||
using DTS.Serialization;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Serialization.StringResources;
|
||||
|
||||
namespace DTS.Slice.Control
|
||||
{
|
||||
/// <summary>
|
||||
/// Slice control representation of all information related to a slice event.
|
||||
/// </summary>
|
||||
public partial class Event
|
||||
: Exceptional,
|
||||
Test.IConvertable
|
||||
{
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="string"/> Id for this event.
|
||||
/// </summary>
|
||||
public string Id
|
||||
{
|
||||
get => _Id.Value;
|
||||
set => _Id.Value = value;
|
||||
}
|
||||
private readonly Property<string> _Id = new Property<string>("DTS.Slice.Control.Event.Id", null, false);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the description <see cref="string"/> for this event.
|
||||
/// </summary>
|
||||
public string Description
|
||||
{
|
||||
get => _Description.Value;
|
||||
set => _Description.Value = value;
|
||||
}
|
||||
private readonly Property<string> _Description = new Property<string>("DTS.Slice.Control.Event.Description", null, false);
|
||||
|
||||
/// <summary>
|
||||
/// The globally unique identification string for this event.
|
||||
/// </summary>
|
||||
public Guid Guid
|
||||
{
|
||||
get => _Guid.Value;
|
||||
set => _Guid.Value = value;
|
||||
}
|
||||
private readonly Property<Guid> _Guid
|
||||
= new Property<Guid>(typeof(Event).Namespace + ".Event.Guid", new Guid("00000000-0000-0000-0000-000000000000"), true);
|
||||
|
||||
/// <summary>
|
||||
/// The global Fault Flags for this event.
|
||||
/// </summary>
|
||||
public UInt16 FaultFlags
|
||||
{
|
||||
get => _FaultFlags.Value;
|
||||
set => _FaultFlags.Value = value;
|
||||
}
|
||||
private readonly Property<UInt16> _FaultFlags
|
||||
= new Property<UInt16>(typeof(Event).Namespace + ".Event.FaultFlags", 0, true);
|
||||
|
||||
/// <summary>
|
||||
/// Get the date of this object's creation. Expected to be populated with the creation
|
||||
/// date of the serialization from which this object has been generated.
|
||||
/// </summary>
|
||||
public DateTime InceptionDate
|
||||
{
|
||||
get => _InceptionDate.Value;
|
||||
private set => _InceptionDate.Value = value;
|
||||
}
|
||||
private readonly Property<DateTime> _InceptionDate
|
||||
= new Property<DateTime>(
|
||||
typeof(Event).Namespace + ".Event.InceptionDate",
|
||||
DateTime.Now,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set this event's list of <see cref="DTS.Slice.Control.Event.Module"/>s.
|
||||
/// </summary>
|
||||
public List<Module> Modules
|
||||
{
|
||||
get => _Modules.Value;
|
||||
set => _Modules.Value = value;
|
||||
}
|
||||
private readonly Property<List<Module>> _Modules = new Property<List<Module>>("DTS.Slice.Control.Event.Modules", null, false);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set this event's list of <see cref="DTS.Slice.Control.Event.CalculatedChannelsModule"/>s.
|
||||
/// </summary>
|
||||
public List<Module.Channel> CalculatedChannels
|
||||
{
|
||||
get => _CalculatedChannels.Value;
|
||||
set => _CalculatedChannels.Value = value;
|
||||
}
|
||||
private readonly Property<List<Module.Channel>> _CalculatedChannels = new Property<List<Module.Channel>>("DTS.Slice.Control.Event.CalculatedChannels", null, false);
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Slice.Control.Event class.
|
||||
/// </summary>
|
||||
public Event()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Slice.Control.Event class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="id">
|
||||
/// The <see cref="string"/> ID of this event.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="description">
|
||||
/// The <see cref="string"/> description of this event.
|
||||
/// </param>
|
||||
///
|
||||
public Event(string id, string description)
|
||||
{
|
||||
try
|
||||
{
|
||||
Id = id;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
Strings.DTS_Slice_Control_Event_ConstructionFailedString, GetType().FullName),
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Slice.Control.Event class.
|
||||
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="test">
|
||||
/// The <see cref="DTS.Serialization.Test"/> to initialize this object with.
|
||||
/// </param>
|
||||
///
|
||||
public Event(Test test, Test.ReportErrors reportErrors)
|
||||
{
|
||||
try
|
||||
{
|
||||
FromDtsSerializationTest(test, reportErrors);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
/*throw new Exception(
|
||||
string.Format(
|
||||
DataPROWin7.Properties.Resources.DTS_Slice_Control_Event_ConstructionFailedString, this.GetType().FullName),
|
||||
ex);*/
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Slice.Control.Event class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="id">
|
||||
/// The <see cref="string"/> ID of this event.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="description">
|
||||
/// The <see cref="string"/> description of this event.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="modules">
|
||||
/// The list of <see cref="DTS.Slice.Control.Event.Module"/>s associated with this event.
|
||||
/// </param>
|
||||
///
|
||||
public Event(string id, string description, List<Module> modules)
|
||||
{
|
||||
try
|
||||
{
|
||||
Id = id;
|
||||
Description = description;
|
||||
Modules = modules;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
Strings.DTS_Slice_Control_Event_ConstructionFailedString, GetType().FullName),
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
// xxx Event ID, start sample, stop sample,
|
||||
|
||||
// xxx Keep a double hash of DAS->Channel... looks like it would probably bypass the
|
||||
// module concept since the API just returns based on
|
||||
// Also need to add thread protection.
|
||||
|
||||
// xxx Can we set locks in the property accessors for this stuff? At least for the
|
||||
// data methods... should the constructor need just an enclosure, or a lambda that
|
||||
// takes a dictionary lookup...
|
||||
|
||||
/// <summary>
|
||||
/// Get a named-DAS/numbered-module accessor to this Event's modules.
|
||||
/// </summary>
|
||||
public DasModuleAccessor DasModules
|
||||
{
|
||||
get => _DasModules.Value;
|
||||
private set => _DasModules.Value = value;
|
||||
}
|
||||
private readonly Property<DasModuleAccessor> _DasModules
|
||||
= new Property<DasModuleAccessor>(
|
||||
typeof(Event).Namespace + ".Event.DasModules",
|
||||
new DasModuleAccessor(),
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get a named-DAS/numbered-channel accessor to this Event's channels.
|
||||
/// </summary>
|
||||
public DasChannelAccessor DasChannels
|
||||
{
|
||||
get => _DasChannels.Value;
|
||||
private set => _DasChannels.Value = value;
|
||||
}
|
||||
private readonly Property<DasChannelAccessor> _DasChannels
|
||||
= new Property<DasChannelAccessor>(
|
||||
typeof(Event).Namespace + ".Event.DasChannels",
|
||||
new DasChannelAccessor(),
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get a named-DAS/numbered-module/numbered-channel accessor to this Event's channels.
|
||||
/// </summary>
|
||||
public DasModuleChannelAccessor DasModuleChannels
|
||||
{
|
||||
get => _DasModuleChannels.Value;
|
||||
private set => _DasModuleChannels.Value = value;
|
||||
}
|
||||
private readonly Property<DasModuleChannelAccessor> _DasModuleChannels
|
||||
= new Property<DasModuleChannelAccessor>(
|
||||
typeof(Event).Namespace + ".Event.DasModules",
|
||||
new DasModuleChannelAccessor(),
|
||||
true
|
||||
);
|
||||
public static bool IsG5(IDASCommunication idas)
|
||||
{
|
||||
return idas.SerialNumber.StartsWith("5M");
|
||||
}
|
||||
|
||||
const string Slice6DBModule = "slice6db module";
|
||||
public static bool IsSlice6DBModule(Module module)
|
||||
{
|
||||
if (null != module && null != module.Description && module.Description.ToLower() == Slice6DBModule)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Slice.Control.Event class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="dases">
|
||||
/// A <see cref="List"/> of <see cref="IConnectedDevice"/>s that will be used
|
||||
/// to determine the dimensions of the Event's internal structures.
|
||||
/// </param>
|
||||
///
|
||||
public Event(List<IDASCommunication> dases, EventInfoAggregate info)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (null == dases)
|
||||
throw new ArgumentNullException(Strings.DTS_Slice_Control_Event_Event_NullDasListString);
|
||||
if (0 >= dases.Count)
|
||||
throw new Exception(Strings.DTS_Slice_Control_Event_Event_EmptyDasListString);
|
||||
Modules = new List<Module>();
|
||||
var dasTestInformations = new Dictionary<string, TestInformation>();
|
||||
var absoluteChannelNumber = 0;
|
||||
|
||||
foreach (var das in dases)
|
||||
{
|
||||
var eventIndex = info.GetEventIndex(das);
|
||||
if (null == das.SerialNumber)
|
||||
throw new UserException("Slice API returned no serial number for passed DAS"); // (connect string: " + ( null != das.DASInfo. das.ConnectString ? das.ConnectString : "<NULL>" ) + ")" );
|
||||
if (null == das.EventInfo)
|
||||
throw new UserException("Slice API returned no EventInfo for passed DAS");
|
||||
if (null == das.EventInfo.Events[eventIndex])
|
||||
throw new UserException("Slice API returned no configuration data for passed DAS"); // \"" + ( null != das.Comm.SensorSerialNumber ? das.Comm.SensorSerialNumber : "<NULL>" ) + "\"" );
|
||||
var eventInfo = das.EventInfo.Events[eventIndex];
|
||||
|
||||
dasTestInformations.Add(das.SerialNumber, new TestInformation(eventInfo.TestID, eventInfo.Description == null ? "" : eventInfo.Description));
|
||||
DasModules.Add(das.SerialNumber, new List<Module>());
|
||||
DasChannels.Add(das.SerialNumber, new List<Module.Channel>());
|
||||
DasModuleChannels.Add(das.SerialNumber, new ModuleChannelAccessor());
|
||||
|
||||
if (null != eventInfo.Modules)
|
||||
{
|
||||
foreach (var dasModule in new List<DASModule>(eventInfo.Modules))
|
||||
{
|
||||
//Add entries for empty slots in a TDAS rack
|
||||
while (dasModule.ModuleArrayIndex > DasModules[das.SerialNumber].Count)
|
||||
{
|
||||
Module emptyModule;
|
||||
Modules.Add(emptyModule = new Module(this));
|
||||
|
||||
DasModules[das.SerialNumber].Add(emptyModule);
|
||||
}
|
||||
|
||||
Module nextModule;
|
||||
Modules.Add(nextModule = new Module(this));
|
||||
|
||||
DasModules[das.SerialNumber].Add(nextModule);
|
||||
DasModuleChannels[das.SerialNumber].Add(dasModule.ModuleArrayIndex, new ChannelAccessor());
|
||||
|
||||
// I think this can be done for everyone (and is the right thing), but for now make it TDAS PRO Rack specific
|
||||
if (das is EthernetTDAS)
|
||||
{
|
||||
// We want module to be the actual SIM or TOM serial number, not the rack serial number
|
||||
nextModule.DasSerialNumber = das.DASInfo.Modules[dasModule.ModuleArrayIndex].SerialNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextModule.DasSerialNumber = das.SerialNumber;
|
||||
}
|
||||
// This is an important condition if they module property population that occurs after
|
||||
// this constructor using the dasModules object is going to line thing up right.
|
||||
Debug.Assert(DasModules[das.SerialNumber].Count - 1 == dasModule.ModuleArrayIndex);
|
||||
|
||||
// Maybe these should be getting populated later on using the SetPropertiesFrom(x) after
|
||||
// the query download successfully returns...?
|
||||
nextModule.Description = dasModule.Description;
|
||||
nextModule.AaFilterRateHz = dasModule.AAFilterRateHz;
|
||||
nextModule.Number = dasModule.ModuleArrayIndex;
|
||||
nextModule.NumberOfSamples = dasModule.NumberOfSamples;
|
||||
nextModule.RequestedPostTriggerSeconds = dasModule.RequestedPostTriggerSeconds;
|
||||
nextModule.RequestedPreTriggerSeconds = dasModule.RequestedPreTriggerSeconds;
|
||||
nextModule.PostTriggerSeconds = dasModule.PostTriggerSeconds;
|
||||
nextModule.PreTriggerSeconds = dasModule.PreTriggerSeconds;
|
||||
nextModule.RecordingMode = dasModule.RecordingMode;
|
||||
nextModule.SampleRateHz = dasModule.SampleRateHz;
|
||||
nextModule.StartRecordSampleNumber = dasModule.StartRecordSampleNumber;
|
||||
nextModule.BaseSerialNumber = dasModule.OwningDAS.SerialNumber;
|
||||
nextModule.StartRecordTimestampSec = dasModule.StartRecordTimestampSec;
|
||||
nextModule.StartRecordTimestampNanoSec = dasModule.StartRecordTimestampNanoSec;
|
||||
nextModule.TriggerTimestampSec = dasModule.TriggerTimestampSec;
|
||||
nextModule.TriggerTimestampNanoSec = dasModule.StartRecordTimestampNanoSec;
|
||||
nextModule.PTPMasterSync = dasModule.PTPMasterSync;
|
||||
nextModule.TiltSensorAxisXDegreesPre = dasModule.TiltSensorAxisXDegreesPre;
|
||||
nextModule.TiltSensorAxisYDegreesPre = dasModule.TiltSensorAxisYDegreesPre;
|
||||
nextModule.TiltSensorAxisZDegreesPre = dasModule.TiltSensorAxisZDegreesPre;
|
||||
nextModule.TiltSensorAxisXDegreesPost = dasModule.TiltSensorAxisXDegreesPost;
|
||||
nextModule.TiltSensorAxisYDegreesPost = dasModule.TiltSensorAxisYDegreesPost;
|
||||
nextModule.TiltSensorAxisZDegreesPost = dasModule.TiltSensorAxisZDegreesPost;
|
||||
nextModule.TemperatureLocation1Pre = dasModule.TemperatureLocation1Pre;
|
||||
nextModule.TemperatureLocation2Pre = dasModule.TemperatureLocation2Pre;
|
||||
nextModule.TemperatureLocation3Pre = dasModule.TemperatureLocation3Pre;
|
||||
nextModule.TemperatureLocation4Pre = dasModule.TemperatureLocation4Pre;
|
||||
nextModule.TemperatureLocation1Post = dasModule.TemperatureLocation1Post;
|
||||
nextModule.TemperatureLocation2Post = dasModule.TemperatureLocation2Post;
|
||||
nextModule.TemperatureLocation3Post = dasModule.TemperatureLocation3Post;
|
||||
nextModule.TemperatureLocation4Post = dasModule.TemperatureLocation4Post;
|
||||
|
||||
nextModule.Channels = new List<Module.Channel>();
|
||||
|
||||
var moduleType = dasModule.GetType();
|
||||
if ((null != dasModule.Channels) && (dasModule.Channels.Length > 0) &&
|
||||
((dasModule.Channels[0].ConfigurationMode != DASChannel.ConfigMode.DummyArm)|| IsG5(das))
|
||||
)
|
||||
{
|
||||
foreach (var dasChannel in new List<DASChannel>(dasModule.Channels))
|
||||
{
|
||||
Module.Channel nextChannel;
|
||||
nextModule.Channels.Add(nextChannel = Module.Channel.CreateChannel(dasChannel, nextModule, absoluteChannelNumber++));
|
||||
|
||||
DasModuleChannels[das.SerialNumber][dasModule.ModuleArrayIndex].Add(dasChannel.ModuleChannelNumber, nextChannel);
|
||||
|
||||
nextChannel.Number = dasChannel.ModuleChannelNumber;
|
||||
nextChannel.Start = dasChannel.EventStartTime;
|
||||
|
||||
//Debug.Assert( das.SensorSerialNumber.Equals( dasModule.OwningDAS.SensorSerialNumber, StringComparison.OrdinalIgnoreCase ) );
|
||||
|
||||
//if ( null == das.Comm.ChannelDiagnosticsResults )
|
||||
// throw new DTS.Slice.Control.Event.Exception( "no diagnostics results were received from the API for module " + nextModule.Number.ToString( ) + ", channel " + nextChannel.Number.ToString( ) );
|
||||
//else
|
||||
{
|
||||
nextChannel.UnfilteredData = new List<short>();
|
||||
DasChannels[das.SerialNumber].Add(nextChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string testId = null;
|
||||
string testDescription = null;
|
||||
foreach (var dasId in dasTestInformations.Keys)
|
||||
{ //
|
||||
// Walk through the list and verify that all of the test ID and description
|
||||
// strings are the same.
|
||||
//
|
||||
var newTestId = dasTestInformations[dasId].Id;
|
||||
if (null != testId && !testId.Equals(newTestId, StringComparison.OrdinalIgnoreCase))
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
Strings.DTS_Slice_Control_Event_Event_DASTestIdMismatchString, testId, dasId, newTestId));
|
||||
testId = newTestId;
|
||||
|
||||
var newTestDescription = dasTestInformations[dasId].Description;
|
||||
|
||||
if (null != testDescription
|
||||
&& !testDescription.Equals(newTestDescription, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
/*throw new Exception(
|
||||
string.Format(
|
||||
Properties.Resources.DTS_Slice_Control_Event_Event_DASTestDescriptionMismatchString, testDescription, dasId, newTestDescription));*/
|
||||
}
|
||||
else { testDescription = newTestDescription; }
|
||||
}
|
||||
|
||||
if (null == testId) { testId = "Empty"; }
|
||||
if (null == testDescription) { testDescription = ""; }
|
||||
|
||||
if (null == testId || null == testDescription)
|
||||
throw new Exception(Strings.DTS_Slice_Control_Event_Event_FailedToDetermineIdOrDescriptionFromConfigurationString);
|
||||
Id = testId;
|
||||
Description = testDescription;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
Strings.DTS_Slice_Control_Event_ConstructionFailedString, GetType().FullName),
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsTom(DASModule module)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (module.SerialNumber().ToLower().Contains("tom"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (null != module.Channels && module.Channels.Length > 0)
|
||||
{
|
||||
if (module.Channels[0] is OutputSquibChannel) { return true; }
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex) { APILogger.Log("problem getting serial number", ex); }
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the highest <see cref="int"/> absolute channel number currently in this event.
|
||||
/// </summary>
|
||||
public int LastAbsoluteChannelNumberInEvent
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
var highestAbsoluteChannelNumberFound = -1;
|
||||
foreach (var module in Modules)
|
||||
foreach (var channel in module.Channels)
|
||||
if (channel.AbsoluteNumber > highestAbsoluteChannelNumberFound)
|
||||
highestAbsoluteChannelNumberFound = channel.AbsoluteNumber;
|
||||
//if ( highestAbsoluteChannelNumberFound < 0 )
|
||||
// throw new Event.Exception( "no absolute channel numbers exist within this event" );
|
||||
return highestAbsoluteChannelNumberFound;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting last absolute channel number in event", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the <see cref="double"/> per-sample threshold that when exceeded by the total basic data
|
||||
/// volume of this event results in Event.IsTooLargeFor32BitVisualization to return true.
|
||||
/// </summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// Justification for the current default value:
|
||||
/// With filter caching disabled, the memory usage is AT LEAST 76.4 bytes/sample, broken down thus:
|
||||
///
|
||||
/// Event structure:
|
||||
/// 1 sample needs 2 bytes ADC representation,
|
||||
/// 8 bytes mV representation,
|
||||
/// 8 bytes EU representation. Total: 18 bytes
|
||||
/// +
|
||||
/// Filtering procedure: 1 sample needs 8 bytes for initial double-sized "ToArray",
|
||||
/// and 1.1 * ( 8 * 3 ) bytes for the three 5% padded front & end processing arrays
|
||||
/// inside the algorithm. Total: 34.4 bytes
|
||||
/// +
|
||||
/// Viewer memory: 1 sample needs 8 bytes for the internal viewer representation
|
||||
/// (at a minimum) + ( 2 * 8 ) bytes for the two arrays required to feed the viewer
|
||||
/// interface. Total: 24 bytes
|
||||
///
|
||||
/// = 76.5 bytes/sample.
|
||||
///
|
||||
/// Not sure how much memory the rest of SliceWARE takes when up and running, but using this number
|
||||
/// we seem to be okay if we stay below 1GB, but run into trouble when we go over if we first do other
|
||||
/// things that might leave things around in memory, i.e., download. The three sections above pretty
|
||||
/// much stack while loading a test into the viewer.
|
||||
/// </remarks>
|
||||
///
|
||||
private static readonly double MaximumVisualizationBytesPerSample = 2D;
|
||||
public double TooLargeFor32BitVisualizationBytesPerSampleThreshold
|
||||
{
|
||||
get => _TooLargeFor32BitVisualizationBytesPerSampleThreshold.Value;
|
||||
private set => _TooLargeFor32BitVisualizationBytesPerSampleThreshold.Value = value;
|
||||
}
|
||||
private readonly Property<double> _TooLargeFor32BitVisualizationBytesPerSampleThreshold
|
||||
= new Property<double>(
|
||||
typeof(Event).FullName + ".TooLargeFor32BitVisualizationBytesPerSampleThreshold",
|
||||
MaximumVisualizationBytesPerSample,
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get <see cref="bool"/> value indicating whether or not this event has more combined data than a 32 bit
|
||||
/// system could handle all at once.
|
||||
/// </summary>
|
||||
public bool IsTooLargeFor32BitVisualization
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
ulong totalChannelDataCount = 0;
|
||||
foreach (var module in Modules)
|
||||
foreach (var channel in module.Channels)
|
||||
{
|
||||
if (channel.UnfilteredData is Serialization.TDAS.File.PersistentChannel)
|
||||
{
|
||||
totalChannelDataCount += (channel.UnfilteredData as Serialization.TDAS.File.PersistentChannel).NumberOfSamples;
|
||||
}
|
||||
else
|
||||
{
|
||||
totalChannelDataCount += (channel.UnfilteredData as Serialization.SliceRaw.File.PersistentChannel).NumberOfSamples;
|
||||
}
|
||||
}
|
||||
return (totalChannelDataCount * TooLargeFor32BitVisualizationBytesPerSampleThreshold) > 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem determining whether or not this event's combined data is too big for 32-bit visualization", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get <see cref="bool"/> value indicating whether or not this event contains channels with average over
|
||||
/// time zero methods, but have specified an invalid averaging window.
|
||||
/// </summary>
|
||||
public bool ContainsChannelsActiveInvalidZeroingWindows => ChannelsWithActiveInvalidZeroingWindows.Count > 0;
|
||||
|
||||
/// <summary>
|
||||
/// we initialize the window average to short min value, which is a valid data value but probably means bad things
|
||||
/// if your window average is legitimately short min value ...
|
||||
/// </summary>
|
||||
private const short InvalidWindowAverage = short.MinValue;
|
||||
/// <summary>
|
||||
/// Get the list of all <see cref="DTS.Slice.Control.Event.Module.Channel"/>s that with average over time
|
||||
/// zero method set, but have specified an invalid averaging window.
|
||||
/// </summary>
|
||||
public List<Module.Channel> ChannelsWithActiveInvalidZeroingWindows
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
var invalidZeroWindowChannels = new List<Module.Channel>();
|
||||
foreach (var module in Modules)
|
||||
foreach (var channel in module.Channels)
|
||||
if (channel is Module.AnalogInputChannel)
|
||||
{
|
||||
var analogChannel = channel as Module.AnalogInputChannel;
|
||||
if (Common.DAS.Concepts.Test.Module.Channel.Sensor.ZeroMethodType.AverageOverTime == analogChannel.ZeroMethod)
|
||||
{
|
||||
//if we have a stored window average for the channel, well then it's definitely not an invalid window average ...
|
||||
if (analogChannel.WindowAverageADC != InvalidWindowAverage) { continue; }
|
||||
//otherwise check to see if we have an invalid window average
|
||||
var windowStart = ((analogChannel.ParentModule.TriggerSampleNumbers.Count > 0) ? (double)analogChannel.ParentModule.TriggerSampleNumbers[0] : 0) + (analogChannel.ZeroAverageWindow.Begin * (double)analogChannel.ParentModule.SampleRateHz);
|
||||
var windowEnd = ((analogChannel.ParentModule.TriggerSampleNumbers.Count > 0) ? (double)analogChannel.ParentModule.TriggerSampleNumbers[0] : 0) + (analogChannel.ZeroAverageWindow.End * (double)analogChannel.ParentModule.SampleRateHz);
|
||||
if (0 > windowStart || 0 > windowEnd) { invalidZeroWindowChannels.Add(analogChannel); }
|
||||
else
|
||||
{
|
||||
var dataStart = analogChannel.ParentModule.StartRecordSampleNumber;
|
||||
var dataEnd = dataStart + analogChannel.ParentModule.NumberOfSamples;
|
||||
if (dataStart > windowStart || windowStart > dataEnd) { invalidZeroWindowChannels.Add(analogChannel); }
|
||||
else if (dataEnd < windowEnd || windowEnd < dataStart) { invalidZeroWindowChannels.Add(analogChannel); }
|
||||
}
|
||||
}
|
||||
}
|
||||
return invalidZeroWindowChannels;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem building list of event channels with active invalid zeroing windows", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private bool IsEmptyModule(Module module)
|
||||
{
|
||||
foreach (var channel in module.Channels)
|
||||
{
|
||||
if (channel.IsConfigured || !IsDummyChannel(channel)) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void PurgeUnconfiguredChannels()
|
||||
{
|
||||
foreach (var module in Modules)
|
||||
{
|
||||
module.Channels.RemoveAll(channel => !channel.IsConfigured || IsDummyChannel(channel));
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Convert this object to a DTS.Serialization.Test.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// A <see cref="DTS.Serialization.Test"/> equivalent to this object.
|
||||
/// </returns>
|
||||
///
|
||||
public Test ToDtsSerializationTest()
|
||||
{
|
||||
try
|
||||
{ //
|
||||
// Create a test to embody the conversion and copy over all relevant
|
||||
// test data members.
|
||||
//
|
||||
var that = new Test();
|
||||
|
||||
PurgeUnconfiguredChannels();
|
||||
|
||||
that.Id = Id;
|
||||
that.Description = Description;
|
||||
that.Guid = Guid;
|
||||
that.FaultFlags = FaultFlags;
|
||||
that.Modules = new List<Test.Module>();
|
||||
|
||||
foreach (var thisModule in Modules)
|
||||
{
|
||||
//Normally, we don't care about empty modules (no data channels), but if it's
|
||||
//a SLICE6 Distributor (a null ParentEvent), we want to output a module element to the .dts file.
|
||||
if (IsEmptyModule(thisModule) && !IsSlice6DBModule(thisModule)) { continue; }
|
||||
//
|
||||
// Create a test module to embody each module conversion, and then copy
|
||||
// over all relevant module data members.
|
||||
//
|
||||
that.Modules.Add(thisModule.ToDtsSerializationTestModule(that));
|
||||
}
|
||||
return that;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem converting " + GetType().FullName + " to " + typeof(Test).FullName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize this object from a DTS.Serialization.Test.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="that">
|
||||
/// A <see cref="DTS.Serialization.Test"/> from which to initialize this object.
|
||||
/// </param>
|
||||
///
|
||||
public void FromDtsSerializationTest(Test that, Test.ReportErrors reportErrors)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (null == that)
|
||||
throw new ArgumentNullException("cannot set this object's properties from null serialization test reference");
|
||||
//
|
||||
// Create the Slice Control test that will be equivalent to the specified serialization
|
||||
// test and populate its relevant properties.
|
||||
//
|
||||
Id = that.Id;
|
||||
Description = that.Description;
|
||||
FaultFlags = that.FaultFlags;
|
||||
Guid = that.Guid;
|
||||
InceptionDate = that.InceptionDate;
|
||||
|
||||
Modules = new List<Module>();
|
||||
foreach (var thatModule in that.Modules)
|
||||
{ //
|
||||
// Create a Slice Control module corresponding to the specified serialization module
|
||||
// and populate its relevant properties.
|
||||
//
|
||||
Modules.Add(new Module(thatModule, this, reportErrors));
|
||||
}
|
||||
}
|
||||
catch (System.IO.InvalidDataException) { throw; }
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem initializing " + GetType().FullName + " using " + typeof(Test).FullName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method to convert a DTS.Slice.Control.Event object to an equivalent DTS.Serialization.Test object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="sliceControlEvent">
|
||||
/// The <see cref="DTS.Slice.Control.Event"/> to be converted.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// A <see cref="DTS.Serialization.Test"/> that is equivalent to the specified Slice Control event.
|
||||
/// </returns>
|
||||
///
|
||||
public static implicit operator Test(Event sliceControlEvent)
|
||||
{
|
||||
try
|
||||
{
|
||||
return sliceControlEvent.ToDtsSerializationTest();
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem implicitly converting " + typeof(Event).FullName + " to " + typeof(Test).FullName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// this really belongs in the channel object, but for now just abstract the function out of
|
||||
/// where the logic is needed
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
/// <returns></returns>
|
||||
private bool IsDummyChannel(Module.Channel channel)
|
||||
{
|
||||
if (null != channel && channel.ChannelDescriptionString.ToLower() == "dummy arm channel")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the base serialization directory path <see cref="string"/> for events.
|
||||
/// </summary>
|
||||
public static string BaseSerializationDirectory
|
||||
{
|
||||
get => _BaseSerializationDirectory.Value;
|
||||
set => _BaseSerializationDirectory.Value = value;
|
||||
}
|
||||
private static readonly Property<string> _BaseSerializationDirectory
|
||||
= new Property<string>(
|
||||
typeof(Event).Namespace + ".BaseSerializationDirectory",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Construct the serialization path for the specified event ID.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="eventId">
|
||||
/// The <see cref="string"/> ID of the event whose serialization path is sought.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="string"/> path for the specified event's serialization.
|
||||
/// </returns>
|
||||
///
|
||||
public static string GetEventSerializationDirectory(string eventId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return System.IO.Path.Combine(BaseSerializationDirectory, eventId);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
//throw new ReviewForm.Exception("encountered problem getting target directory for test " + (null != eventId ? "\"" + eventId + "\"" : "<NULL>"), ex);
|
||||
throw new Exception("encountered problem getting target directory for test " + (null != eventId ? "\"" + eventId + "\"" : "<NULL>"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the specified object for equality with this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="obj">
|
||||
/// The <see cref="object"/> to be tested for equality.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if the specified object has memberwise equality with
|
||||
/// this object; false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
var that = obj as Event;
|
||||
return null != that
|
||||
&& Id.Equals(that.Id)
|
||||
&& Description.Equals(that.Description)
|
||||
&& Guid.Equals(that.Guid)
|
||||
&& ModulesEquals(that.Modules)
|
||||
&& FaultFlags.Equals(that.FaultFlags);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
Strings.DTS_Slice_Control_Equals_ComparisonFailedString, null != obj ? "\"" + obj.ToString() + "\"" : Strings.DTS_Slice_Control_NullIndicatorString),
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the specified object's module list for equality with this object's
|
||||
/// module list.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="thoseModules">
|
||||
/// The <see cref="List"/> of <see cref="DTS.Slice.Control.Event.Module"/> objects to be
|
||||
/// compared for equality with this test's equivalent.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if the two lists contain equivalent-valued members;
|
||||
/// false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
private bool ModulesEquals(List<Module> thoseModules)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Modules.Count != thoseModules.Count)
|
||||
return false;
|
||||
for (var i = 0; i < thoseModules.Count; i++)
|
||||
if (!Modules[i].Equals(thoseModules[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception(Strings.DTS_Slice_Control_Event_ModuleEquals_ComparisonFailedString, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the hash code for this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="int"/> hash code for this object.
|
||||
/// </returns>
|
||||
///
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using DTS.Utilities;
|
||||
using DTS.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
//[Serializable]
|
||||
public partial class TestSetup : Exceptional
|
||||
{
|
||||
public partial class Graph : Exceptional
|
||||
{
|
||||
public Graph()
|
||||
{
|
||||
_Name.Value = null;
|
||||
_Version.Value = "1.0.0.0";
|
||||
Identifier = Guid.NewGuid();
|
||||
}
|
||||
|
||||
public void UnSet()
|
||||
{
|
||||
}
|
||||
public List<Channel> Channels
|
||||
{
|
||||
get { return _Channels.Value; }
|
||||
set { _Channels.Value = value; }
|
||||
}
|
||||
private Property<List<Channel>> _Channels
|
||||
= new Property<List<Channel>>(typeof(Graph).Namespace + "Graph.Channels", new List<Channel>(), true);
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _Name.Value; }
|
||||
set { _Name.Value = value; }
|
||||
}
|
||||
private Property<string> _Name
|
||||
= new Property<string>(typeof(Graph).Namespace + ".Graph.Name", "", false);
|
||||
|
||||
public string HardwareChannelName
|
||||
{
|
||||
get { return _HardwareChannelName.Value; }
|
||||
set { _HardwareChannelName.Value = value; }
|
||||
}
|
||||
private Property<string> _HardwareChannelName
|
||||
= new Property<string>(typeof(Graph).Namespace + ".Graph.HardwareChannelName", "", true);
|
||||
|
||||
public string DisplayName
|
||||
{
|
||||
get { return _Name.Value + "_" + _HardwareChannelName.Value; }
|
||||
}
|
||||
|
||||
public string Version
|
||||
{
|
||||
get { return _Version.Value; }
|
||||
set { _Version.Value = value; }
|
||||
}
|
||||
private Property<string> _Version
|
||||
= new Property<string>(typeof(Graph).Namespace + ".Graph.Version", "", false);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
[System.Xml.Serialization.XmlIgnoreAttribute]
|
||||
public bool IsSingleChannelGraph
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((null != Channels) && (1 == Channels.Count));
|
||||
}
|
||||
}
|
||||
|
||||
[System.Xml.Serialization.XmlIgnoreAttribute]
|
||||
public Channel FirstChannel
|
||||
{
|
||||
get
|
||||
{
|
||||
return Channels[0];
|
||||
}
|
||||
}
|
||||
|
||||
[System.Xml.Serialization.XmlIgnoreAttribute]
|
||||
public DTS.Serialization.Test.Module.Channel FirstTestChannel
|
||||
{
|
||||
get
|
||||
{
|
||||
return Channels[0].TestChannel;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Xml.Serialization.XmlIgnoreAttribute]
|
||||
public Guid Identifier
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.Serialization.TDM
|
||||
{
|
||||
public class ChannelHeader
|
||||
{
|
||||
internal const int MAX_HEADER_LINES = 15;
|
||||
internal const int DAS_LINE = 0;
|
||||
internal const int CAPACITY_LINE = 1;
|
||||
internal const int EU_LINE = 2;
|
||||
internal const int SENSOR_SN_LINE = 3;
|
||||
internal const int SENSITIVITY_LINE = 4;
|
||||
internal const int EXCITATION_LINE = 5;
|
||||
internal const int MIN_LINE = 6;
|
||||
internal const int MAX_LINE = 7;
|
||||
internal const int TOYOTA_CALC1_LINE = 8;
|
||||
internal const int TOYOTA_CALC2_LINE = 9;
|
||||
internal const int TOYOTA_CALC3_LINE = 10;
|
||||
internal const int KNEE_POINT_LINE = 11;
|
||||
internal const int STRANGE_DATA_FLAG_LINE = 12;
|
||||
internal const int CHANNEL_CODE_LINE = 13;
|
||||
internal const int CHANNEL_JCODE_LINE = 14;
|
||||
|
||||
public void WriteChannelHeaderToString(Writer writer, System.IO.TextWriter tw, bool bFiltered, double start, double end)
|
||||
{
|
||||
var test = writer.Test;
|
||||
writer.IncrementDone(2);
|
||||
|
||||
var HeaderLines = new string[MAX_HEADER_LINES];
|
||||
for (var i = 0; i < MAX_HEADER_LINES; i++) { HeaderLines[i] = ""; }
|
||||
var testChannels = new List<Test.Module.Channel>(test.Channels);
|
||||
|
||||
for (var i = 0; i < testChannels.Count; i++)
|
||||
{
|
||||
if (testChannels[i] is Test.Module.AnalogInputChannel)
|
||||
{
|
||||
var channel = testChannels[i] as Test.Module.AnalogInputChannel;
|
||||
|
||||
if (channel.IsSquibVoltage())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var startSampleNumber = start * channel.ParentModule.SampleRateHz + channel.ParentModule.TriggerSampleNumbers[0];
|
||||
var endSampleNumber = end * channel.ParentModule.SampleRateHz + channel.ParentModule.TriggerSampleNumbers[0];
|
||||
|
||||
if (startSampleNumber < channel.ParentModule.StartRecordSampleNumber) { startSampleNumber = channel.ParentModule.StartRecordSampleNumber; }
|
||||
if (endSampleNumber > channel.ParentModule.NumberOfSamples + (double)channel.ParentModule.StartRecordSampleNumber)
|
||||
{
|
||||
endSampleNumber = channel.ParentModule.StartRecordSampleNumber + (double)channel.ParentModule.NumberOfSamples;
|
||||
}
|
||||
|
||||
var startSample = Convert.ToInt32(startSampleNumber - channel.ParentModule.StartRecordSampleNumber);
|
||||
var endSample = Convert.ToInt32(endSampleNumber - channel.ParentModule.StartRecordSampleNumber - 1);
|
||||
|
||||
if (channel.IsDigital())
|
||||
{
|
||||
HeaderLines[DAS_LINE] = string.Format("{0},{1}", HeaderLines[DAS_LINE],
|
||||
channel.HardwareChannelName);
|
||||
HeaderLines[CAPACITY_LINE] = string.Format("{0},{1}", HeaderLines[CAPACITY_LINE], 1);
|
||||
HeaderLines[EU_LINE] = string.Format("{0},{1}", HeaderLines[EU_LINE], "Digital");
|
||||
HeaderLines[SENSOR_SN_LINE] = string.Format("{0},{1}", HeaderLines[SENSOR_SN_LINE], channel.HardwareChannelName);
|
||||
}
|
||||
else if (channel.IsSquib())
|
||||
{
|
||||
HeaderLines[DAS_LINE] = string.Format("{0},{1}", HeaderLines[DAS_LINE], channel.HardwareChannelName);
|
||||
HeaderLines[CAPACITY_LINE] = string.Format("{0},{1}", HeaderLines[CAPACITY_LINE], 10); //hardcoded per TDM cpp file
|
||||
HeaderLines[EU_LINE] = string.Format("{0},{1}", HeaderLines[EU_LINE], channel.EngineeringUnits.TrimEnd());
|
||||
HeaderLines[SENSOR_SN_LINE] = string.Format("{0},{1}", HeaderLines[SENSOR_SN_LINE], channel.HardwareChannelName);
|
||||
}
|
||||
else
|
||||
{
|
||||
HeaderLines[DAS_LINE] = string.Format("{0},{1}", HeaderLines[DAS_LINE], channel.HardwareChannelName);
|
||||
if (channel.ProportionalToExcitation || (channel.SensorCapacity == 0))
|
||||
{
|
||||
HeaderLines[CAPACITY_LINE] = string.Format("{0},{1}", HeaderLines[CAPACITY_LINE], channel.DesiredRange);
|
||||
}
|
||||
else
|
||||
{
|
||||
HeaderLines[CAPACITY_LINE] = string.Format("{0},{1}", HeaderLines[CAPACITY_LINE], channel.SensorCapacity);
|
||||
}
|
||||
HeaderLines[EU_LINE] = string.Format("{0},{1}", HeaderLines[EU_LINE], channel.EngineeringUnits.TrimEnd());
|
||||
HeaderLines[SENSOR_SN_LINE] = string.Format("{0},{1}", HeaderLines[SENSOR_SN_LINE], channel.SerialNumber);
|
||||
}
|
||||
|
||||
|
||||
if (channel.IsSquib()) { HeaderLines[SENSITIVITY_LINE] = string.Format("{0},{1:0.000000000000}", HeaderLines[SENSITIVITY_LINE], 1D); }
|
||||
else { HeaderLines[SENSITIVITY_LINE] = string.Format("{0},{1:0.000000000000}", HeaderLines[SENSITIVITY_LINE], channel.Sensitivity); }
|
||||
|
||||
if (channel.IsSquib())
|
||||
{
|
||||
HeaderLines[EXCITATION_LINE] = string.Format("{0},{1}", HeaderLines[EXCITATION_LINE], (5D).ToString("e4", CultureInfo.InvariantCulture));
|
||||
}
|
||||
else if (channel.IsDigital())
|
||||
{
|
||||
HeaderLines[EXCITATION_LINE] = string.Format("{0},{1}", HeaderLines[EXCITATION_LINE], (1D).ToString("e4", CultureInfo.InvariantCulture));
|
||||
}
|
||||
else
|
||||
{
|
||||
HeaderLines[EXCITATION_LINE] = string.Format("{0},{1}", HeaderLines[EXCITATION_LINE], channel.MeasuredExcitationVoltageValid ? channel.MeasuredExcitationVoltage.ToString("e4", CultureInfo.InvariantCulture)
|
||||
: channel.FactoryExcitationVoltageValid ? channel.FactoryExcitationVoltage.ToString("e4", CultureInfo.InvariantCulture) : (5D).ToString("e4", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
var dMin = double.MaxValue;
|
||||
var dMax = double.MinValue;
|
||||
|
||||
var scaler = new DataScaler();
|
||||
scaler.IsInverted = channel.IsInverted;//channel is DTS.Common.DAS.Concepts.DAS.Channel.IInversionAware ? (channel as DTS.Common.DAS.Concepts.DAS.Channel.IInversionAware).IsInverted : false;
|
||||
scaler.SetLinearizationFormula(channel.LinearizationFormula);
|
||||
|
||||
scaler.SetScaleFactorMv(channel.Data.ScaleFactorMv);
|
||||
scaler.SetScaleFactorEU(channel.Data.ScaleFactorEU);
|
||||
scaler.SetUseEUScaleFactors(channel.Data.UseEUScaleFactors);
|
||||
scaler.UnitConversion = channel.UnitConversion;
|
||||
scaler.BasedOnOutputAtCapacity = channel.AtCapacity;
|
||||
scaler.CapacityOutputIsBasedOn = channel.CapacityOutputIsBasedOn;
|
||||
scaler.SensitivityUnits = channel.SensitivityUnits;
|
||||
scaler.IEPE = channel.Bridge == SensorConstants.BridgeType.IEPE;
|
||||
scaler.Digital = channel.Bridge == SensorConstants.BridgeType.DigitalInput;
|
||||
scaler.SetLinearizationFormula(channel.LinearizationFormula);
|
||||
scaler.SetDigitalMultiplier(channel.DigitalMultiplier);
|
||||
scaler.Digital = channel.IsDigital();
|
||||
scaler.DigitalMode = channel.DigitalMode;
|
||||
scaler.SetMvPerEu(channel.Data.MvPerEu);
|
||||
var analogChannel = channel;
|
||||
|
||||
try
|
||||
{
|
||||
scaler.SetInitialOffset(analogChannel.InitialOffset);
|
||||
scaler.ZeroMethodType = analogChannel.ZeroMethod;
|
||||
if (analogChannel.RemoveOffset) { scaler.SetRemovedADC(channel.RemovedADC); scaler.SetRemovedInternalADC(channel.RemovedInternalADC); }
|
||||
else { scaler.SetRemovedADC(0); scaler.SetRemovedInternalADC(0); }
|
||||
|
||||
scaler.SetDataZeroLevelADC(channel.DataZeroLevelAdc);
|
||||
scaler.SetZeroMvInADC(channel.ZeroMvInADC);
|
||||
try { scaler.SetWindowAverageADC(channel.WindowAverageADC); }
|
||||
catch (Exception) { }
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
scaler.NominalExcitationVoltage = analogChannel.ExcitationVoltage;
|
||||
if (analogChannel.MeasuredExcitationVoltageValid)
|
||||
{
|
||||
try { scaler.MeasuredExcitationVoltage = analogChannel.MeasuredExcitationVoltage; }
|
||||
catch { };
|
||||
}
|
||||
if (analogChannel.FactoryExcitationVoltageValid)
|
||||
{
|
||||
try { scaler.FactoryExcitationVoltage = analogChannel.FactoryExcitationVoltage; }
|
||||
catch { };
|
||||
}
|
||||
scaler.ProportionalToExcitation = channel.ProportionalToExcitation;
|
||||
|
||||
if (bFiltered)
|
||||
{
|
||||
for (var curSample = startSample; curSample <= endSample; curSample++)
|
||||
{
|
||||
var d = channel.Sensitivity * scaler.GetEU(writer.FilteredData[i].Data[Convert.ToUInt64(curSample)]);
|
||||
dMin = Math.Min(dMin, d);
|
||||
dMax = Math.Max(dMax, d);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var curSample = startSample; curSample <= endSample; curSample++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var d = channel.Sensitivity * scaler.GetEU(channel.PersistentChannelInfo.Data[Convert.ToUInt64(curSample)]);
|
||||
|
||||
dMin = Math.Min(dMin, d);
|
||||
dMax = Math.Max(dMax, d);
|
||||
}
|
||||
catch (IndexOutOfRangeException ex)
|
||||
{
|
||||
APILogger.Log("unexpected end in TDM export looking for min/max, ", ex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HeaderLines[MIN_LINE] = string.Format("{0},{1}", HeaderLines[MIN_LINE], dMin.ToString("e4", CultureInfo.InvariantCulture));
|
||||
HeaderLines[MAX_LINE] = string.Format("{0},{1}", HeaderLines[MAX_LINE], dMax.ToString("e4", CultureInfo.InvariantCulture));
|
||||
|
||||
|
||||
|
||||
//11344 The function of Cable Multiplier on Analog Channels in TTS import is not ready yet
|
||||
//var cableMultipler = "0"; //default in the old code
|
||||
//if (!string.IsNullOrWhiteSpace(channel.UserValue2))
|
||||
//{
|
||||
// if (double.TryParse(channel.UserValue2, NumberStyles.Any, CultureInfo.InvariantCulture,
|
||||
// out var dTemp))
|
||||
// {
|
||||
// cableMultipler = dTemp.ToString(CultureInfo.InvariantCulture);
|
||||
// }
|
||||
//}
|
||||
//22284 Use a hardcoded value of 1 for cable multiplier for TTS export
|
||||
HeaderLines[TOYOTA_CALC1_LINE] += $",1";
|
||||
|
||||
HeaderLines[TOYOTA_CALC2_LINE] += $",0";
|
||||
|
||||
HeaderLines[TOYOTA_CALC3_LINE] += ",0";
|
||||
double softwareFrequency = 0;
|
||||
|
||||
if (channel.IsSquib())
|
||||
{
|
||||
softwareFrequency = 2000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(channel.SoftwareFilter))
|
||||
{
|
||||
if (channel.SoftwareFilter.Contains("Hz"))
|
||||
{
|
||||
double d;
|
||||
if (double.TryParse(channel.SoftwareFilter.Replace("Hz", ""), out d))
|
||||
{
|
||||
softwareFrequency = d;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var coder = new DescriptionAttributeCoder<ChannelFilter>();
|
||||
foreach (ChannelFilter filterType in Enum.GetValues(typeof(ChannelFilter)))
|
||||
{
|
||||
if (coder.DecodeAttributeValue(filterType).Equals(channel.SoftwareFilter, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
softwareFrequency = (double)filterType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// This used to have manipulation logic, but no more. See http://fogbugz/fogbugz/default.asp?4594
|
||||
HeaderLines[KNEE_POINT_LINE] = string.Format("{0},{1}", HeaderLines[KNEE_POINT_LINE], softwareFrequency);
|
||||
HeaderLines[STRANGE_DATA_FLAG_LINE] = string.Format("{0},{1}", HeaderLines[STRANGE_DATA_FLAG_LINE], channel.DataFlag);
|
||||
|
||||
//7714 Remove " (Current)" from AIC channel name/description in TTS export.
|
||||
var chName = channel.UserCode;
|
||||
if (channel.IsSquibChannel)
|
||||
{
|
||||
chName = channel.ChannelName2;
|
||||
var index = chName.IndexOf(" (Current)");
|
||||
if (index >= 0)
|
||||
{
|
||||
chName = chName.Substring(0, index);
|
||||
}
|
||||
}
|
||||
HeaderLines[CHANNEL_CODE_LINE] = string.Format("{0},{1}", HeaderLines[CHANNEL_CODE_LINE], chName);
|
||||
|
||||
var description = channel.UserChannelName;
|
||||
if (channel.IsSquib())
|
||||
{
|
||||
description = channel.ChannelDescriptionString;
|
||||
var index = description.IndexOf(" (Current)");
|
||||
if (index >= 0) { description = description.Remove(index, 10); }
|
||||
}
|
||||
HeaderLines[CHANNEL_JCODE_LINE] = string.Format("{0},{1}", HeaderLines[CHANNEL_JCODE_LINE], description);
|
||||
}
|
||||
}
|
||||
foreach (var line in HeaderLines)
|
||||
{
|
||||
tw.WriteLine("{0},", line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* FtssTsv.File.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.Serialization.FtssTsv
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Basic representation of a FTSS TSV file.
|
||||
/// </summary>
|
||||
///
|
||||
public partial class File
|
||||
: Serialization.File, IWritable<Test>
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the FtssTsv.File class.
|
||||
/// </summary>
|
||||
///
|
||||
public File()
|
||||
: base("TSV")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get this file format's extension.
|
||||
/// </summary>
|
||||
public static string Extension => ".tsv";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the file writer for this file type.
|
||||
/// </summary>
|
||||
public IWriter<Test> Exporter
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_Exporter == null)
|
||||
{
|
||||
_Exporter = new Writer(this, DefaultEncoding);
|
||||
}
|
||||
return _Exporter;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting exporter", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private IWriter<Test> _Exporter = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
//[Serializable]
|
||||
public partial class TestSetup : Exceptional
|
||||
{
|
||||
public partial class Graph : Exceptional
|
||||
{
|
||||
public Graph()
|
||||
{
|
||||
_Name.Value = null;
|
||||
_Version.Value = "1.0.0.0";
|
||||
Identifier = Guid.NewGuid();
|
||||
}
|
||||
|
||||
public void UnSet()
|
||||
{
|
||||
}
|
||||
public List<Channel> Channels
|
||||
{
|
||||
get => _Channels.Value;
|
||||
set => _Channels.Value = value;
|
||||
}
|
||||
private readonly Property<List<Channel>> _Channels
|
||||
= new Property<List<Channel>>(typeof(Graph).Namespace + "Graph.Channels", new List<Channel>(), true);
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _Name.Value;
|
||||
set => _Name.Value = value;
|
||||
}
|
||||
private readonly Property<string> _Name
|
||||
= new Property<string>(typeof(Graph).Namespace + ".Graph.Name", "", false);
|
||||
|
||||
public string HardwareChannelName
|
||||
{
|
||||
get => _HardwareChannelName.Value;
|
||||
set => _HardwareChannelName.Value = value;
|
||||
}
|
||||
private readonly Property<string> _HardwareChannelName
|
||||
= new Property<string>(typeof(Graph).Namespace + ".Graph.HardwareChannelName", "", true);
|
||||
|
||||
public string DisplayName => _Name.Value + "_" + _HardwareChannelName.Value;
|
||||
|
||||
public string Version
|
||||
{
|
||||
get => _Version.Value;
|
||||
set => _Version.Value = value;
|
||||
}
|
||||
private readonly Property<string> _Version
|
||||
= new Property<string>(typeof(Graph).Namespace + ".Graph.Version", "", false);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
[System.Xml.Serialization.XmlIgnoreAttribute]
|
||||
public bool IsSingleChannelGraph => ((null != Channels) && (1 == Channels.Count));
|
||||
|
||||
[System.Xml.Serialization.XmlIgnoreAttribute]
|
||||
public Channel FirstChannel => Channels[0];
|
||||
|
||||
[System.Xml.Serialization.XmlIgnoreAttribute]
|
||||
public Test.Module.Channel FirstTestChannel => Channels[0].TestChannel;
|
||||
|
||||
[System.Xml.Serialization.XmlIgnoreAttribute]
|
||||
public Guid Identifier
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Excel.File.cs
|
||||
*
|
||||
* Copyright © 2017
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.Serialization.XLSX
|
||||
{
|
||||
/// <summary>
|
||||
/// implementation of the Serialization.File class for XLSX
|
||||
/// http://fogbugz/fogbugz/default.asp?9920'
|
||||
/// right now this will only export EU, (filtered or unfiltered)
|
||||
/// but we'll likely want to control whether to export mV/ADC in future
|
||||
/// </summary>
|
||||
public partial class File
|
||||
: Serialization.File, IWritable<Test>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// constructor
|
||||
/// </summary>
|
||||
public File()
|
||||
: base( "XLSX" )
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the file writer for this file type.
|
||||
/// </summary>
|
||||
public IWriter<Test> Exporter
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_exporter == null)
|
||||
{
|
||||
var writer = new Writer(this, DefaultEncoding);
|
||||
|
||||
_exporter = writer;
|
||||
}
|
||||
return _exporter;
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem getting exporter", ex );
|
||||
}
|
||||
}
|
||||
}
|
||||
private IWriter<Test> _exporter;
|
||||
|
||||
/// <summary>
|
||||
/// Controls whether to export ADC or not
|
||||
/// </summary>
|
||||
public bool ExportADC
|
||||
{
|
||||
set => ((Writer) Exporter).ExportADC = value;
|
||||
}
|
||||
/// <summary>
|
||||
/// Controls whether to export EU or not
|
||||
/// </summary>
|
||||
public bool ExportEU
|
||||
{
|
||||
set => ((Writer) Exporter).ExportEU = value;
|
||||
}
|
||||
/// <summary>
|
||||
/// Controls whether to export mV or not
|
||||
/// </summary>
|
||||
public bool ExportMV
|
||||
{
|
||||
set => ((Writer) Exporter).ExportMv = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10.Packets
|
||||
{
|
||||
public class AnalogDataFormat1Packet : AbstractDataPacket, IDataPacket
|
||||
{
|
||||
|
||||
public DateTime LocalTimeOfFirstSample
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
//bit 28
|
||||
public bool Same
|
||||
{
|
||||
get
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var bits = new BitArray(channelSpecificDataWord);
|
||||
return bits[28];
|
||||
}
|
||||
set
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var b = new BitArray(channelSpecificDataWord);
|
||||
b[28] = value;
|
||||
var ret = new byte[sizeof(uint)];
|
||||
b.CopyTo(ret, 0);
|
||||
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||||
}
|
||||
}
|
||||
//bits 27-24
|
||||
public int Factor
|
||||
{
|
||||
get
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var bits = new BitArray(channelSpecificDataWord);
|
||||
return Utils.Utils.BitArrayToInt32(bits, 24, 27);
|
||||
}
|
||||
set
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var b = new BitArray(channelSpecificDataWord);
|
||||
Utils.Utils.SetBits(b, (uint)value, 24, 27);
|
||||
var ret = new byte[sizeof(uint)];
|
||||
b.CopyTo(ret, 0);
|
||||
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||||
}
|
||||
}
|
||||
//bits 23-16
|
||||
public int TotChan
|
||||
{
|
||||
get
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var bits = new BitArray(channelSpecificDataWord);
|
||||
return Utils.Utils.BitArrayToInt32(bits, 16, 23);
|
||||
}
|
||||
set
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var b = new BitArray(channelSpecificDataWord);
|
||||
Utils.Utils.SetBits(b, (uint)value, 16, 23);
|
||||
var ret = new byte[sizeof(uint)];
|
||||
b.CopyTo(ret, 0);
|
||||
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||||
}
|
||||
}
|
||||
//bits 15-8
|
||||
public long Subchan
|
||||
{
|
||||
get
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var bits = new BitArray(channelSpecificDataWord);
|
||||
return Utils.Utils.BitArrayToInt32(bits, 8, 15);
|
||||
}
|
||||
set
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var b = new BitArray(channelSpecificDataWord);
|
||||
Utils.Utils.SetBits(b, (uint)value, 8, 15);
|
||||
var ret = new byte[sizeof(uint)];
|
||||
b.CopyTo(ret, 0);
|
||||
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||||
}
|
||||
}
|
||||
//bits 7-2
|
||||
public long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var bits = new BitArray(channelSpecificDataWord);
|
||||
return Utils.Utils.BitArrayToInt32(bits, 2, 7);
|
||||
}
|
||||
set
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var b = new BitArray(channelSpecificDataWord);
|
||||
Utils.Utils.SetBits(b, (uint)value, 2, 7);
|
||||
var ret = new byte[sizeof(uint)];
|
||||
b.CopyTo(ret, 0);
|
||||
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||||
}
|
||||
}
|
||||
public enum Modes
|
||||
{
|
||||
DataIsPacked,
|
||||
DataIsUnpackedLSBPadded,
|
||||
Reserved,
|
||||
DataIsUnpackedMSBPadded
|
||||
}
|
||||
//bits 1-0
|
||||
public Modes Mode
|
||||
{
|
||||
get
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var bits = new BitArray(channelSpecificDataWord);
|
||||
var mode = Utils.Utils.BitArrayToInt32(bits, 0, 1);
|
||||
switch (mode)
|
||||
{
|
||||
case 0: return Modes.DataIsPacked;
|
||||
case 1: return Modes.DataIsUnpackedLSBPadded;
|
||||
case 3: return Modes.DataIsUnpackedMSBPadded;
|
||||
case 2:
|
||||
default: return Modes.Reserved;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var b = new BitArray(channelSpecificDataWord);
|
||||
Utils.Utils.SetBits(b, (uint)value, 0, 1);
|
||||
var ret = new byte[sizeof(uint)];
|
||||
b.CopyTo(ret, 0);
|
||||
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||||
}
|
||||
}
|
||||
public SampleData[] Samples = new SampleData[0];
|
||||
public class SampleData
|
||||
{
|
||||
public short[] ChannelData { private set; get; }
|
||||
protected SampleData() { }
|
||||
public SampleData(short[] channels)
|
||||
{
|
||||
ChannelData = channels;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// it seems the EMC ch10 validation tool only supports CH10 106v5, so use this header value for the analog packet when in this mode
|
||||
/// whether to include secondary time header or not
|
||||
/// 33199 Add Time format 1 as an export option for CH 10 export
|
||||
/// </summary>
|
||||
private const byte DATA_VERSION_V105 = 0x01;
|
||||
|
||||
|
||||
private const byte DATA_VERSION_DASSAULT = 0x06;
|
||||
public AnalogDataFormat1Packet(int nanoseconds, int seconds,
|
||||
Chapter10File.GetNextSampleDelegate getNextSample, int totalChannels, long channelLength, long rtc, long numSamples, long currentSample, byte sequenceNumber,
|
||||
ushort channelId, bool includeSecondaryHeader) : base(Enums.DataFileDataTypes.AnalogDataFormat1, includeSecondaryHeader)
|
||||
{
|
||||
TotChan = totalChannels;
|
||||
Subchan = 0;
|
||||
Same = true;
|
||||
Factor = 0;
|
||||
Length = 16;
|
||||
Mode = Modes.DataIsUnpackedMSBPadded;
|
||||
|
||||
var dataLength = Convert.ToUInt32(4 + sizeof(ushort) * totalChannels * numSamples); ;
|
||||
var offset = CommonHeaderWork(channelId, includeSecondaryHeader ? DATA_VERSION_DASSAULT : DATA_VERSION_V105, sequenceNumber, rtc, dataLength, nanoseconds, seconds);
|
||||
|
||||
for (var sampleIdx = 0; sampleIdx < numSamples; sampleIdx++)
|
||||
{
|
||||
for (var chIdx = 0; chIdx < totalChannels; chIdx++)
|
||||
{
|
||||
var signed = getNextSample(chIdx);
|
||||
var unsigned = (ushort)(((signed - 0x8000 & 0x00FF) << 8) | ((signed - 0x8000 >> 8) & 0x00FF));
|
||||
var bytes = BitConverter.GetBytes(unsigned).Reverse().ToArray();
|
||||
Buffer.BlockCopy(bytes, 0, _dataBytes, offset, 2);
|
||||
offset += 2;
|
||||
}
|
||||
currentSample++;
|
||||
}
|
||||
}
|
||||
public AnalogDataFormat1Packet() : base(Enums.DataFileDataTypes.AnalogDataFormat1, true)
|
||||
{
|
||||
}
|
||||
public AnalogDataFormat1Packet(byte[] bytes) : base(bytes)
|
||||
{
|
||||
var offset = IRIGCH10.PacketHeader.PACKET_HEADER_LENGTH;
|
||||
|
||||
if (PacketHeader.SecondaryHeaderPresent)
|
||||
{
|
||||
var secondaryHeaderBytes = new byte[SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH];
|
||||
Buffer.BlockCopy(bytes, offset,
|
||||
secondaryHeaderBytes, 0, SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH);
|
||||
var secondaryHeader = new SecondaryTimeFormatHeader(secondaryHeaderBytes);
|
||||
LocalTimeOfFirstSample = secondaryHeader.LocalTime;
|
||||
offset += SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH;
|
||||
}
|
||||
|
||||
ChannelSpecificDataWord = BitConverter.ToUInt32(bytes, offset);
|
||||
offset += sizeof(uint);
|
||||
var numChannels = TotChan;
|
||||
var sizeOf1SampleForAllChannels = sizeof(ushort) * numChannels;
|
||||
//There's a CSDW in the data section, then all ADC data. CSDW is uint, 4 bytes
|
||||
var numSamples = (PacketHeader.DataLength - 4) / sizeOf1SampleForAllChannels;
|
||||
|
||||
Samples = new SampleData[numSamples];
|
||||
for (var i = 0; i < Samples.Length; i++)
|
||||
{
|
||||
var channels = GetChannels(bytes, offset, numChannels);
|
||||
Samples[i] = new SampleData(channels);
|
||||
offset += sizeOf1SampleForAllChannels;
|
||||
}
|
||||
}
|
||||
|
||||
private short[] GetChannels(byte[] bytes, int sampleStart, int numChannels)
|
||||
{
|
||||
var ret = new short[numChannels];
|
||||
for (var i = 0; i < numChannels; i++)
|
||||
{
|
||||
var unsignedBytes = new byte[2];
|
||||
Buffer.BlockCopy(bytes, sampleStart + i * 2, unsignedBytes, 0, 2);
|
||||
//we have to change the byte order here
|
||||
var unsigned = BitConverter.ToUInt16(new[] { unsignedBytes[1], unsignedBytes[0] }, 0);
|
||||
//go from unsigned to signed
|
||||
var adc = (short)((((unsigned & 0x00FF) << 8) | ((unsigned >> 8) & 0x00FF)) + 0x8000);
|
||||
ret[i] = adc;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// ChannelDefinition.h
|
||||
// --------------------
|
||||
// Defines a data channel (based on DDAS testplan.h)
|
||||
//
|
||||
//
|
||||
// AUTHOR: A. J. Owski
|
||||
// LOC: 1250
|
||||
// DEPT: 5260 Tool Development
|
||||
// (formerly Instrument Systems)
|
||||
//
|
||||
// COPYRIGHT: (c) 2002 DaimlerChrysler Corp.
|
||||
//
|
||||
// REVISIONS: (most-recent at top of list).
|
||||
//
|
||||
// Date Init Description of Change
|
||||
// ---- ---- ---------------------
|
||||
// 11/08/04 wjp Remove redundant CalDate from Channel definition and label the
|
||||
// field as spare bytes. Use the date in the transducer structure,
|
||||
// which is part of the channel definition.
|
||||
//
|
||||
|
||||
#if !defined( CHANNEL_H )
|
||||
#define CHANNEL_H
|
||||
|
||||
#include "TransducerDefinition.h"
|
||||
|
||||
enum ChannelFlags{CHANFLAG_ACTIVE};
|
||||
|
||||
|
||||
// Channel State Macro's
|
||||
|
||||
#define ISCHANACTIVE(pChan)(pChan->Flags&(1<<CHANFLAG_ACTIVE)?1:0)
|
||||
#define SETCHANACTIVE(pChan)(pChan->Flags|=(1<<CHANFLAG_ACTIVE))
|
||||
#define CLRCHANACTIVE(pChan)(pChan->Flags&=(~(1<<CHANFLAG_ACTIVE)))
|
||||
|
||||
|
||||
// Channel Data Structure
|
||||
|
||||
typedef struct tagCHANNEL
|
||||
{
|
||||
short Size; // Size of this object
|
||||
short Flags; // Channel Flags
|
||||
char Name[64]; // Channel Name
|
||||
char Sign[8]; // Sign +, -, or blank
|
||||
char Axis[8]; // X,Y,Z,FX,MX,AX,...
|
||||
float FilterFreq; // Channel Filter Class (in Hz)
|
||||
float SetGain; // Gain setting (1 - n)
|
||||
float ActGain; // Actual (measured?) gain setting.
|
||||
float Rcal; // Shunt cal resistance
|
||||
float Excitation; // Excitation Voltage (when programable)
|
||||
// time_t CalDate; // Calibration date (Remove - redundant)
|
||||
byte byteSpares[4]; // Spare bytes (was Cal Date)
|
||||
TRANSDUCER Transducer; // "Snapshot" of transducer values
|
||||
} CHANNEL;
|
||||
|
||||
typedef CHANNEL *PCHANNEL; // Pointer to a channel
|
||||
typedef CHANNEL *PCHAN; // Even shorter version of above
|
||||
|
||||
#endif // !defined( CHANNEL_H )
|
||||
@@ -0,0 +1,279 @@
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
using DTS.Common.Utilities.Xml;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
public partial class Test
|
||||
{
|
||||
/// <summary>
|
||||
/// Representation of serializable das timestamp information.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("DasTimestamp")]
|
||||
public partial class DasTimestamp : Exceptional
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="DTS.Serialization.Test"/> that contains this module.
|
||||
/// </summary>
|
||||
public Test ParentTest
|
||||
{
|
||||
get => _ParentTest.Value;
|
||||
private set => _ParentTest.Value = value;
|
||||
}
|
||||
private readonly Property<Test> _ParentTest
|
||||
= new Property<Test>(
|
||||
typeof(DasTimestamp).Namespace + ".Test.DasTimestamp.ParentTest",
|
||||
null,
|
||||
false
|
||||
);
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Serialization.Test.DasTimestamp class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="parentTest">
|
||||
/// The <see cref="DTS.Serialization.Test"/> containing this object.
|
||||
/// </param>
|
||||
///
|
||||
public DasTimestamp(Test parentTest)
|
||||
{
|
||||
try
|
||||
{
|
||||
ParentTest = parentTest;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem constructing " + GetType().Name, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the base serial number <see cref="string"/> for this DAS.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("BaseSerialNumber")]
|
||||
public string BaseSerialNumber
|
||||
{
|
||||
get => _BaseSerialNumber.Value;
|
||||
set => _BaseSerialNumber.Value = value;
|
||||
}
|
||||
private readonly Property<string> _BaseSerialNumber
|
||||
= new Property<string>(
|
||||
typeof(DasTimestamp).Namespace + ".Test.DasTimestamp.BaseSerialNumber",
|
||||
"",
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the number of samples in this test das.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("NumberOfSamples")]
|
||||
public UInt64 NumberOfSamples
|
||||
{
|
||||
get => _NumberOfSamples.Value;
|
||||
set => _NumberOfSamples.Value = value;
|
||||
}
|
||||
private readonly Property<UInt64> _NumberOfSamples
|
||||
= new Property<UInt64>(
|
||||
typeof(DasTimestamp).Namespace + ".Test.DasTimestamp.NumberOfSamples",
|
||||
0,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the number of bits per sample timestamp in this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("NumberOfBitsPerSample")]
|
||||
public UInt32 NumberOfBitsPerSample
|
||||
{
|
||||
get => _NumberOfBitsPerSample.Value;
|
||||
set => _NumberOfBitsPerSample.Value = value;
|
||||
}
|
||||
private readonly Property<UInt32> _NumberOfBitsPerSample
|
||||
= new Property<UInt32>(
|
||||
typeof(DasTimestamp).Namespace + ".Test.DasTimestamp.NumberOfBitsPerSample",
|
||||
0,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// The name of the .bin file in the Binary folder that corresponds to this set of timestamps.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("FileName")]
|
||||
public string FileName
|
||||
{
|
||||
get => _fileName.Value;
|
||||
set => _fileName.Value = value;
|
||||
}
|
||||
private readonly Property<string> _fileName
|
||||
= new Property<string>(
|
||||
typeof(DasTimestamp).Namespace + ".Test.DasTimestamp.FileName",
|
||||
"",
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Write XML serialization for this object to the specified writer.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="writer">
|
||||
/// The <see cref="XmlWriter"/> to which this object's XML serialization
|
||||
/// will be written.
|
||||
/// </param>
|
||||
///
|
||||
public void WriteXml(XmlWriter writer)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cult = new CultureInfo("");
|
||||
var attributeExtractor = new AttributeExtractor<XmlSerializationTagAttribute>();
|
||||
|
||||
//
|
||||
// Write simple das timestamp properties.
|
||||
//
|
||||
// NOTE: The way this really should be done is to examine this object using reflection and just automatically
|
||||
// assemble the list of properties that have been tagged with the serialization attribute. That way, when I
|
||||
// add in a property after the fact, I don't have to worry about any of this crap below. It would just automatically
|
||||
// get de/serialized. The equality check should also pick it's comparison properties that way. I'd do the conversion
|
||||
// now, but we're under pressure for a release so it'll have to wait.
|
||||
//
|
||||
writer.WriteStartElement(attributeExtractor.ExtractAttachedAttributeFromObject(this).Value);
|
||||
|
||||
try
|
||||
{
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "BaseSerialNumber").Value, BaseSerialNumber.ToString(cult));
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "BaseSerialNumber").Value, "NA");
|
||||
}
|
||||
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "NumberOfSamples").Value, NumberOfSamples.ToString(cult));
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem converting DTS.Serialization.Test.DasTimestamp object to XML", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read XML serialization for this object from the specified reader.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="reader">
|
||||
/// The <see cref="XmlReader"/> from which this object's XML serialization
|
||||
/// will be read.
|
||||
/// </param>
|
||||
///
|
||||
public void ReadXml(XmlReader reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cult = new CultureInfo("");
|
||||
var attributeExtractor = new AttributeExtractor<XmlSerializationTagAttribute>();
|
||||
reader.MoveToContent();
|
||||
|
||||
//
|
||||
// Read simple attributes.
|
||||
//
|
||||
try
|
||||
{
|
||||
BaseSerialNumber = reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "BaseSerialNumber").Value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new Exception("error reading BaseSerialNumber");
|
||||
}
|
||||
|
||||
if (
|
||||
ulong.TryParse(
|
||||
reader.GetAttribute(
|
||||
attributeExtractor.ExtractAttachedAttributeFromProperty(this, "NumberOfSamples").Value),
|
||||
NumberStyles.Any, cult, out ulong numberOfSamples))
|
||||
{
|
||||
NumberOfSamples = numberOfSamples;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("error reading NumberOfSamples");
|
||||
}
|
||||
|
||||
if (
|
||||
uint.TryParse(
|
||||
reader.GetAttribute(
|
||||
attributeExtractor.ExtractAttachedAttributeFromProperty(this, "NumberOfBitsPerSample").Value),
|
||||
NumberStyles.Any, cult, out uint numberOfBitsPerSample))
|
||||
{
|
||||
NumberOfBitsPerSample = numberOfBitsPerSample;
|
||||
}
|
||||
else
|
||||
{
|
||||
//not written, set to standard size
|
||||
NumberOfBitsPerSample = 8 * sizeof(ulong);
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem converting XML to DTS.Serialization.Test.DasTimestamp object", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should normally return a schema representing the form of the XML
|
||||
/// generated/consumed by WriteXml/ReadXml, but it never called during
|
||||
/// the serialization process so ours just returns null.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// Null <see cref="XmlSchema"/> reference, always.
|
||||
/// </returns>
|
||||
///
|
||||
public XmlSchema GetSchema()
|
||||
{
|
||||
// This method is never invoked during XML object serialization.
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the specified object for equality with this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="obj">
|
||||
/// The <see cref="object"/> to be tested for equality.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if the specified object has memeberwise equality with
|
||||
/// this object; false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
return obj is DasTimestamp that
|
||||
&& FileName.Equals(that.FileName)
|
||||
&& NumberOfSamples.Equals(that.NumberOfSamples)
|
||||
&& NumberOfBitsPerSample.Equals(that.NumberOfBitsPerSample)
|
||||
&& BaseSerialNumber.Equals(that.BaseSerialNumber);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem equality-testing object " + (null != obj ? "\"" + obj.ToString() + "\"" : "<<NULL>>"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using DTS.Utilities;
|
||||
using DTS.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
public partial class TestSetup : Exceptional
|
||||
{
|
||||
public partial class TestObject : Exceptional
|
||||
{
|
||||
public partial class DASHardware : Exceptional
|
||||
{
|
||||
public DASHardware()
|
||||
{
|
||||
_SampleRate.Value = null;
|
||||
_SerialNumber.Value = null;
|
||||
_Version.Value = "1.0.0.0";
|
||||
}
|
||||
|
||||
public List<DASChannel> DASChannels
|
||||
{
|
||||
get { return _DASChannels.Value; }
|
||||
set { _DASChannels.Value = value; }
|
||||
}
|
||||
private Property<List<DASChannel>> _DASChannels
|
||||
= new Property<List<DASChannel>>(typeof(TestObject).Namespace + "DASHardware.DASChannels", new List<DASChannel>(), true);
|
||||
|
||||
public string SampleRate
|
||||
{
|
||||
get { return _SampleRate.Value; }
|
||||
set { _SampleRate.Value = value; }
|
||||
}
|
||||
private Property<string> _SampleRate
|
||||
= new Property<string>(typeof(TestObject).Namespace + ".DASHardware.SampleRate", "", false);
|
||||
|
||||
public string SerialNumber
|
||||
{
|
||||
get { return _SerialNumber.Value; }
|
||||
set { _SerialNumber.Value = value; }
|
||||
}
|
||||
private Property<string> _SerialNumber
|
||||
= new Property<string>(typeof(TestObject).Namespace + ".DASHardware.SerialNumber", "", false);
|
||||
|
||||
public string Version
|
||||
{
|
||||
get { return _Version.Value; }
|
||||
set { _Version.Value = value; }
|
||||
}
|
||||
private Property<string> _Version
|
||||
= new Property<string>(typeof(TestObject).Namespace + ".DASHardware.Version", "", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,613 @@
|
||||
/*
|
||||
* Chapter10.File.Writer.cs
|
||||
*
|
||||
* Copyright © 2020
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Text;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using DTS.Common;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.Utils;
|
||||
using static DTS.Serialization.Test.Module;
|
||||
// ReSharper disable PossiblyMistakenUseOfParamsMethod
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10
|
||||
{
|
||||
public partial class File
|
||||
{
|
||||
/// <summary>
|
||||
/// implementation of the Serialization.File.Writer class for Chapter10
|
||||
/// </summary>
|
||||
public class Writer : Writer<File>, IWriter<Test>
|
||||
{
|
||||
#region properties
|
||||
/// <summary>
|
||||
/// the owning file that controls this writer
|
||||
/// </summary>
|
||||
internal File WriterParent { get; }
|
||||
|
||||
public double Start { get; set; }
|
||||
public double Stop { get; set; }
|
||||
public bool Filtered { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region methods
|
||||
/// <summary>
|
||||
/// writes out test to given path
|
||||
/// </summary>
|
||||
/// <param name="pathname"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="test"></param>
|
||||
/// <param name="bFiltering"></param>
|
||||
/// <param name="includeGroupNameInISOExport"></param>
|
||||
/// <param name="dataCollectionLength"></param>
|
||||
/// <param name="minStartTime"></param>
|
||||
public void Write(string pathname, string id, Test test, bool bFiltering, bool includeGroupNameInISOExport, double minStartTime, int dataCollectionLength)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// updates the progress if possible
|
||||
/// </summary>
|
||||
/// <param name="dValue"></param>
|
||||
/// <param name="tickEventHandler"></param>
|
||||
private void UpdateProgress(double dValue, TickEventHandler tickEventHandler)
|
||||
{
|
||||
tickEventHandler?.Invoke(this, dValue);
|
||||
}
|
||||
/// <summary>
|
||||
/// returns a name for the given channel
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
/// <returns></returns>
|
||||
private static string GetChannelName(Channel channel)
|
||||
{
|
||||
|
||||
if (!(channel is AnalogInputChannel aic))
|
||||
{
|
||||
return channel.ChannelName2;
|
||||
}
|
||||
|
||||
switch (IsoViewModeStatic.ViewMode)
|
||||
{
|
||||
case IsoViewMode.ISOOnly:
|
||||
return $"{aic.IsoChannelName}";
|
||||
case IsoViewMode.ISOAndUserCode:
|
||||
return $"{aic.IsoChannelName}\\{aic.UserChannelName}";
|
||||
case IsoViewMode.UserCodeOnly:
|
||||
return $"{aic.UserCode}";
|
||||
case IsoViewMode.ChannelNameOnly:
|
||||
return $"{aic.UserChannelName}";
|
||||
}
|
||||
return aic.HardwareChannelName;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// we don't really have an RTC, so we make up one
|
||||
/// with an arbitrary value, this is actually a 6byte value,
|
||||
/// we're just using a long for convenience
|
||||
/// </summary>
|
||||
public const long BASE_RTC = 141989612500056L;
|
||||
private void GetTimeStamp(Test test, out int nanoseconds, out int seconds)
|
||||
{
|
||||
nanoseconds = 0;
|
||||
seconds = 0;
|
||||
var basemodules = test.Modules.GroupBy(module => module.BaseSerialNumber).Select(group => group.First());
|
||||
|
||||
var testModuleTimeStamps = GetModuleTimeStamps(basemodules, out var testModuleStartTimestamps);
|
||||
|
||||
Tuple<double, double> minUnixTime = null;
|
||||
|
||||
if (testModuleTimeStamps.Any())
|
||||
{
|
||||
minUnixTime = TestUtils.MinUnixTime(testModuleTimeStamps);
|
||||
}
|
||||
else if (testModuleStartTimestamps.Any())
|
||||
{
|
||||
minUnixTime = TestUtils.MinUnixTime(testModuleStartTimestamps);
|
||||
}
|
||||
|
||||
if (null == minUnixTime)
|
||||
{
|
||||
var ticks = test.InceptionDate.ToUniversalTime().Ticks;
|
||||
var s = Math.Truncate((decimal)ticks / TimeSpan.TicksPerSecond);
|
||||
ticks -= Convert.ToInt64(s * TimeSpan.TicksPerSecond);
|
||||
var n = Math.Truncate(ticks * Common.Constants.NANOS_PER_SECOND / TimeSpan.TicksPerSecond);
|
||||
minUnixTime = new Tuple<double, double>(Convert.ToDouble(n), Convert.ToDouble(s));
|
||||
}
|
||||
|
||||
var minStartTime = double.MinValue;
|
||||
foreach (var module in test.Modules)
|
||||
{
|
||||
var dStartTime = (double)module.StartRecordSampleNumber / module.SampleRateHz;
|
||||
if (module.TriggerSampleNumbers.Count > 0)
|
||||
{
|
||||
dStartTime -= (double)module.TriggerSampleNumbers[0] / module.SampleRateHz;
|
||||
}
|
||||
minStartTime = Math.Max(minStartTime, dStartTime);
|
||||
}
|
||||
var nanos = ((decimal)(minStartTime) * Common.Constants.NANOS_PER_SECOND) + (decimal)minUnixTime.Item2 + (decimal)minUnixTime.Item1 * Common.Constants.NANOS_PER_SECOND;
|
||||
seconds = Convert.ToInt32(Math.Truncate(nanos / Common.Constants.NANOS_PER_SECOND));
|
||||
nanos -= seconds * Common.Constants.NANOS_PER_SECOND;
|
||||
nanoseconds = Convert.ToInt32(nanos);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// whether to include secondary time header or not
|
||||
/// 33199 Add Time format 1 as an export option for CH 10 export
|
||||
/// </summary>
|
||||
public bool IncludeSecondaryHeader { get; set; } = true;
|
||||
/// <summary>
|
||||
/// Whether to use analog format or not during export
|
||||
/// </summary>
|
||||
public bool UseAnalogFormat { get; set; } = true;
|
||||
/// <summary>
|
||||
/// Whether to use PCM format or not during export
|
||||
/// </summary>
|
||||
public bool UsePCMFormat { get; set; } = false;
|
||||
/// <summary>
|
||||
/// returns a list of binary readers given a test that all point at the start of data
|
||||
/// </summary>
|
||||
/// <param name="test"></param>
|
||||
/// <returns></returns>
|
||||
private List<BinaryReader> GetBinaryReaders(Test test, IReadOnlyDictionary<Channel, ChannelInformation> lookup)
|
||||
{
|
||||
var binaryReaders = new List<BinaryReader>();
|
||||
for (var i = 0; i < test.Channels.Count; i++)
|
||||
{
|
||||
var channel = test.Channels[i];
|
||||
//get the filename and the start of data before we go and nuke the persistantchannelinfo object ...
|
||||
var fileName = lookup[channel].ChannelFileName;
|
||||
var offset = lookup[channel].OffsetDataStart;
|
||||
//get the reader and advance it to the start of data
|
||||
var br = new BinaryReader(new FileStream(fileName, FileMode.Open));
|
||||
br.ReadBytes(Convert.ToInt32(offset));
|
||||
lookup[channel].Reader = br;
|
||||
binaryReaders.Add(br);
|
||||
}
|
||||
return binaryReaders;
|
||||
}
|
||||
/// <summary>
|
||||
/// internal class for encapsulating some of the information from analoginputdaschannels without keeping any files open
|
||||
/// </summary>
|
||||
internal class ChannelInformation
|
||||
{
|
||||
public string ChannelFileName;
|
||||
public ulong OffsetDataStart;
|
||||
public ulong NumberOfSamples;
|
||||
public short MinADC { get; set; } = short.MaxValue;
|
||||
public short MaxADC { get; set; } = short.MinValue;
|
||||
public BinaryReader Reader;
|
||||
public ChannelInformation(AnalogInputChannel channel)
|
||||
{
|
||||
ChannelFileName = channel.PersistentChannelInfo.Filename;
|
||||
OffsetDataStart = channel.PersistentChannelInfo.OffsetOfSampleDataStart;
|
||||
NumberOfSamples = channel.PersistentChannelInfo.NumberOfSamples;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// retrieves channel summary information for channels in a test
|
||||
/// </summary>
|
||||
/// <param name="test"></param>
|
||||
/// <returns></returns>
|
||||
private IReadOnlyDictionary<Channel, ChannelInformation> GetChannelSummaries(Test test)
|
||||
{
|
||||
var lookup = new Dictionary<Channel, ChannelInformation>();
|
||||
|
||||
foreach (var channel in test.Channels)
|
||||
{
|
||||
if (channel is AnalogInputChannel aic)
|
||||
{
|
||||
lookup[channel] = new ChannelInformation(aic);
|
||||
}
|
||||
}
|
||||
|
||||
return lookup;
|
||||
}
|
||||
/// <summary>
|
||||
/// closes and disposes of all readers in list, then clears the list
|
||||
/// </summary>
|
||||
/// <param name="readers"></param>
|
||||
private void CloseAndDisposeReaders(List<BinaryReader> readers)
|
||||
{
|
||||
for (var i = 0; i < readers.Count; i++)
|
||||
{
|
||||
readers[i].Close();
|
||||
readers[i].Dispose();
|
||||
}
|
||||
readers.Clear();
|
||||
}
|
||||
/// <summary>
|
||||
/// go throughs all binary readers and determines the min and max ADC from files
|
||||
/// </summary>
|
||||
/// <param name="test"></param>
|
||||
/// <param name="lookup"></param>
|
||||
/// <param name="tickEventHandler"></param>
|
||||
private void GetMinAndMax(Test test, IReadOnlyDictionary<Channel, ChannelInformation> lookup,
|
||||
TickEventHandler tickEventHandler)
|
||||
{
|
||||
var index = 0;
|
||||
foreach (var channel in test.Channels)
|
||||
{
|
||||
if (!lookup.ContainsKey(channel)) { return; }
|
||||
var info = lookup[channel];
|
||||
try
|
||||
{
|
||||
for (var i = 0UL; i < info.NumberOfSamples; i++)
|
||||
{
|
||||
var adc = ReadShort(info.Reader);
|
||||
if (adc < info.MinADC) { info.MinADC = adc; }
|
||||
else if (adc > info.MaxADC) { info.MaxADC = adc; }
|
||||
}
|
||||
index++;
|
||||
tickEventHandler?.Invoke(this, (50D * index) / (double)test.Channels.Count);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log($"Failed to get Min/Max for file {info.ChannelFileName} - ", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Readers a single signed short from file
|
||||
/// </summary>
|
||||
/// <param name="reader"></param>
|
||||
/// <returns></returns>
|
||||
private short ReadShort(BinaryReader reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bytes = reader.ReadBytes(2);
|
||||
//to get the next sample from the file we just read two bytes and make a short out of it
|
||||
//I'm not sure why to use this version rather than alternatives, but the existing code
|
||||
//used this method, so I just preserved it here ...
|
||||
return (short)((bytes[0] & 0xFFFF) + ((bytes[1] & 0xFFFF) << 8));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log($"Failed to read from file", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// writes out test to given path
|
||||
/// </summary>
|
||||
/// <param name="pathname"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="dataFolder"></param>
|
||||
/// <param name="test"></param>
|
||||
/// <param name="bFiltering"></param>
|
||||
/// <param name="includeGroupNameInISOExport"></param>
|
||||
/// <param name="fd"></param>
|
||||
/// <param name="tmChannel"></param>
|
||||
/// <param name="channelNumber"></param>
|
||||
/// <param name="beginEventHandler"></param>
|
||||
/// <param name="cancelEventHandler"></param>
|
||||
/// <param name="endEventHandler"></param>
|
||||
/// <param name="tickEventHandler"></param>
|
||||
/// <param name="errorEventHandler"></param>
|
||||
/// <param name="cancelRequested"></param>
|
||||
/// <param name="minStartTime"></param>
|
||||
/// <param name="dataCollectionLength"></param>
|
||||
public void Write(string pathname,
|
||||
string id,
|
||||
string dataFolder,
|
||||
Test test,
|
||||
bool bFiltering,
|
||||
bool includeGroupNameInISOExport,
|
||||
FilteredData fd,
|
||||
Channel tmChannel,
|
||||
int channelNumber,
|
||||
BeginEventHandler beginEventHandler,
|
||||
CancelEventHandler cancelEventHandler,
|
||||
EndEventHandler endEventHandler,
|
||||
TickEventHandler tickEventHandler,
|
||||
ErrorEventHandler errorEventHandler,
|
||||
CancelRequested cancelRequested,
|
||||
double minStartTime,
|
||||
int dataCollectionLength)
|
||||
{
|
||||
System.Exception caughtException = null;
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(Path.GetDirectoryName(pathname)))
|
||||
{
|
||||
_ = Directory.CreateDirectory(Path.GetDirectoryName(pathname));
|
||||
}
|
||||
var summaryLookup = GetChannelSummaries(test);
|
||||
var binaryReaders = GetBinaryReaders(test, summaryLookup);
|
||||
GetMinAndMax(test, summaryLookup, tickEventHandler);
|
||||
tickEventHandler?.Invoke(this, 50D);
|
||||
CloseAndDisposeReaders(binaryReaders);
|
||||
string tmatsDoc = UseAnalogFormat ? GetTMATSAnalog(test, summaryLookup) : GetTMATSPCM(test, summaryLookup);
|
||||
GetTimeStamp(test, out var nanoseconds, out var seconds);
|
||||
var channelsCount = test.Channels.Count;
|
||||
|
||||
binaryReaders = GetBinaryReaders(test, summaryLookup);
|
||||
|
||||
if (UseAnalogFormat)
|
||||
{
|
||||
Chapter10File.WriteFileAnalog(tmatsDoc,
|
||||
(int chIdx) =>
|
||||
{
|
||||
return ReadShort(binaryReaders[chIdx]);
|
||||
},
|
||||
(int chIdx) => (long)summaryLookup[test.Channels[chIdx]].NumberOfSamples,
|
||||
channelsCount, nanoseconds, seconds, test.Modules[0].SampleRateHz,
|
||||
IncludeSecondaryHeader, pathname, tickEventHandler, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Chapter10File.WriteFilePCM(tmatsDoc,
|
||||
(int chIdx) => { return ReadShort(binaryReaders[chIdx]); },
|
||||
(int chIdx) => (long)summaryLookup[test.Channels[chIdx]].NumberOfSamples,
|
||||
channelsCount, nanoseconds, seconds, test.Modules[0].SampleRateHz,
|
||||
IncludeSecondaryHeader, pathname, tickEventHandler, this);
|
||||
}
|
||||
|
||||
CloseAndDisposeReaders(binaryReaders);
|
||||
tickEventHandler?.Invoke(this, 100D);
|
||||
}
|
||||
catch (IOException ioException)
|
||||
{
|
||||
if (ioException.HResult == -2147024816)
|
||||
{
|
||||
var msg = $"failed to create file, check that file isn't currently open: {pathname}";
|
||||
APILogger.Log(msg, ioException);
|
||||
caughtException = new IOException(msg, ioException);
|
||||
}
|
||||
else
|
||||
{
|
||||
APILogger.Log("encountered problem writing Ch10 file", pathname, ioException);
|
||||
caughtException = ioException;
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("encountered problem writing Ch10 file", pathname, ex);
|
||||
caughtException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
tickEventHandler?.Invoke(this, 100D);
|
||||
endEventHandler?.Invoke(this);
|
||||
if (null != caughtException)
|
||||
{
|
||||
errorEventHandler?.Invoke(this, caughtException);
|
||||
}
|
||||
}
|
||||
}
|
||||
private const int DATA_CHANNEL_ID = 3;
|
||||
/// <summary>
|
||||
/// returns a string with multiple lines for a single channel for a PCM TMATS file
|
||||
/// </summary>
|
||||
private static string GetTMATSChannelPCM(Test test, IReadOnlyDictionary<Channel, ChannelInformation> summaryLookup)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var baseText = System.IO.File.ReadAllText(@"TMTTemplates\S6ATMTTemplate_PCM_ExportChannel.tmt");
|
||||
for ( var i = 0; i< test.Channels.Count; i++)
|
||||
{
|
||||
sb.AppendLine(GetTMATSChannelPCM(test, summaryLookup, i, baseText));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns a string with multiple lines for a single channel for a PCM TMATS file
|
||||
/// <summary>
|
||||
private static string GetTMATSChannelPCM(Test test, IReadOnlyDictionary<Channel, ChannelInformation> summaryLookup, int channelIdx,
|
||||
string unmodifiedText)
|
||||
{
|
||||
//we'll return the basetext, but just make it clear the original string isn't modified, strings are immutable and we
|
||||
//are creating new strings and we're holding onto the old string
|
||||
var baseText = unmodifiedText;
|
||||
var channel = test.Channels[channelIdx];
|
||||
try
|
||||
{
|
||||
var summary = summaryLookup[channel];
|
||||
if (channel is AnalogInputChannel aic)
|
||||
{
|
||||
var ds = SliceRaw.File.Reader.GetDataScaler(aic);
|
||||
var eu = aic.EngineeringUnits?.Trim() ?? "";
|
||||
var scaler = ds.GetAdcToEuScalingFactor();
|
||||
//we want 0 * ds = ds.GetEU(0), but the way to do that is to add in ds.GetEU(0)
|
||||
//so that's the offset to add back in ... I'm not sure why analog is using a different formula
|
||||
var offset = ds.GetEU(0);
|
||||
var minEU = ds.GetEU(summary.MinADC);
|
||||
var maxEU = ds.GetEU(summary.MaxADC);
|
||||
var channelName = GetChannelName(channel);
|
||||
baseText = baseText.Replace("{CHANNEL NUMBER}", $"{1 + channelIdx}");
|
||||
baseText = baseText.Replace("{CHANNEL NAME}", channelName);
|
||||
baseText = baseText.Replace("{CHANNEL OFFSET EU}", $"{offset:0.0000}");
|
||||
baseText = baseText.Replace("{CHANNEL SCALEFACTOR EU}", $"{scaler:0.0000}");
|
||||
baseText = baseText.Replace("{CHANNEL EU}", PrepareOutput(eu));
|
||||
baseText = baseText.Replace("{CHANNEL MAX RANGE EU}", $"{maxEU:0.0000}");
|
||||
baseText = baseText.Replace("{CHANNEL MIN RANGE EU}", $"{minEU:0.0000}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log($"Failed to get TMATS for channel: {channelIdx} - {channel.ChannelName2}", ex);
|
||||
}
|
||||
return baseText;
|
||||
}
|
||||
private static string GetTMATSChannelsAnalog(Test test, IReadOnlyDictionary<Channel, ChannelInformation> summaryLookup)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine(@"R-1\COM:--------------------- Start of channels ---------------------;");
|
||||
|
||||
for (var i = 0; i < test.Channels.Count; i++)
|
||||
{
|
||||
var channel = test.Channels[i];
|
||||
try
|
||||
{
|
||||
var summary = summaryLookup[channel];
|
||||
var ds = new DataScaler();
|
||||
var eu = "EU";
|
||||
if (channel is AnalogInputChannel aic)
|
||||
{
|
||||
ds = SliceRaw.File.Reader.GetDataScaler(aic);
|
||||
eu = aic.EngineeringUnits?.Trim() ?? "";
|
||||
}
|
||||
var channelName = PrepareOutput(GetChannelName(channel));
|
||||
sb.Append(GetTMATSChannel(channelName, summary.MinADC, summary.MaxADC, 1 + i, ds, eu));
|
||||
sb.AppendLine();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log($"Failed to get TMATS for channel: {i} - {channel.ChannelName2}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine(@"R-1\COM:--------------------- End of channels ---------------------;");
|
||||
sb.AppendLine(@"R-1\COM:--------------------- End of TMATS ---------------------;");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
private static string GetTMATSChannel(string channelName, short ADCMin, short ADCMax, int channelNumber, DataScaler ds,
|
||||
string eu)
|
||||
{
|
||||
var baseText = System.IO.File.ReadAllText(@"TMTTemplates\S6ATMTTemplate_ANALOG_ExportChannel.tmt");
|
||||
|
||||
baseText = baseText.Replace("{CHANNEL_NUMBER}", $"{channelNumber}");
|
||||
baseText = baseText.Replace("{CHANNEL_NAME}", channelName);
|
||||
|
||||
var scaler = ds.GetAdcToEuScalingFactor();
|
||||
var adcToEU = ds.GetAdcToEuScalingFactor();
|
||||
var midPointRemoval = adcToEU * Constants.ADC_MIDPOINT;
|
||||
|
||||
//the scaler is already aware of datazerolevelADC, so just get 0 and datazerolevel is applied, as is
|
||||
//initial eu or user offset
|
||||
var offset = ds.GetEU(0) - midPointRemoval;
|
||||
var minEU = ds.GetEU(ADCMin);
|
||||
var maxEU = ds.GetEU(ADCMax);
|
||||
|
||||
baseText = baseText.Replace("{CHANNEL_OFFSETEU}", $"{offset}");
|
||||
baseText = baseText.Replace("{CHANNEL_SCALEFACTOREU}", $"{scaler}");
|
||||
baseText = baseText.Replace("{CHANNEL_EU}", PrepareOutput(eu));
|
||||
baseText = baseText.Replace("{CHANNEL_MAXRANGEEU}", $"{maxEU}");
|
||||
baseText = baseText.Replace("{CHANNEL_MINRANGEEU}", $"{minEU}");
|
||||
|
||||
return baseText;
|
||||
}
|
||||
private static string PrepareOutput(string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s)) { return string.Empty; }
|
||||
return s.Replace(' ', '_');
|
||||
}
|
||||
/// <summary>
|
||||
/// returns the entire TMATS document as a string for a PCM export
|
||||
/// <summary>
|
||||
private static string GetTMATSPCM(Test test, IReadOnlyDictionary<Channel, ChannelInformation> summaryLookup)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var baseText = System.IO.File.ReadAllText(@"TMTTemplates\S6ATMTTemplate_PCM_ExportBase.tmt");
|
||||
|
||||
baseText = baseText.Replace("{NAME OF PROGRAM}", "DataPRO");
|
||||
baseText = baseText.Replace("{TEST ID}", test.Modules[0].SerialNumber);
|
||||
baseText = baseText.Replace("{STREAM TIME FORMAT}", "2");
|
||||
baseText = baseText.Replace("{DAS SERIAL NUMBER}", test.Modules[0].SerialNumber);
|
||||
int channelCount = test.Modules.Sum(m => m.Channels.Count);
|
||||
var bitsPerFrame = 32 + 16 * channelCount;
|
||||
baseText = baseText.Replace("{DAS BIT RATE}", $"{bitsPerFrame * test.Modules[0].SampleRateHz:0}");
|
||||
var now = DateTime.UtcNow;
|
||||
baseText = baseText.Replace("{CREATE DATE}", $"{now.Year:0000}-{now.Month:00}-{now.Day:00} {now.Hour:00}:{now.Minute:00}:{now.Second:00}");
|
||||
baseText = baseText.Replace("{DAS SAMPLE RATE}", $"{test.Modules[0].SampleRateHz}");
|
||||
baseText = baseText.Replace("{NUMBER OF CHANNELS}", $"{channelCount}");
|
||||
baseText = baseText.Replace("{NUMBER OF WORDS}", $"{1 + channelCount}");
|
||||
baseText = baseText.Replace("{NUMBER OF BITS}", $"{32 + 16*channelCount}");
|
||||
sb.Append(baseText);
|
||||
sb.Append(GetTMATSChannelPCM(test, summaryLookup));
|
||||
return sb.ToString();
|
||||
}
|
||||
private string GetTMATSAnalog(Test test, IReadOnlyDictionary<Channel, ChannelInformation> summaryLookup)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var baseText = System.IO.File.ReadAllText(@"TMTTemplates\S6ATMTTemplate_ANALOG_ExportBase.tmt");
|
||||
|
||||
baseText = baseText.Replace("{NAME OF PROGRAM}", PrepareOutput(GetApplicationVersion()));
|
||||
baseText = baseText.Replace("{TEST ID}", PrepareOutput(test.Id));
|
||||
var now = DateTime.UtcNow;
|
||||
baseText = baseText.Replace("{CREATE DATE}", $"{now.Year:0000}-{now.Month:00}-{now.Day:00} {now.Hour:00}:{now.Minute:00}:{now.Second:00}");
|
||||
baseText = baseText.Replace("{UDP STREAM DATA CHANNEL ID}", $"{DATA_CHANNEL_ID}");
|
||||
baseText = baseText.Replace("{DAS SAMPLE RATE}", $"{test.Modules[0].SampleRateHz}");
|
||||
baseText = baseText.Replace("{NUMBER_OF_CHANNELS}", $"{test.Modules.Sum(m => m.Channels.Count)}");
|
||||
sb.Append(baseText);
|
||||
sb.AppendLine();
|
||||
sb.Append(GetTMATSChannelsAnalog(test, summaryLookup));
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static string GetApplicationVersion()
|
||||
{
|
||||
var v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||
return string.Format("DataPRO {0}.{1:00}.{2:00000}", v.Major, v.Minor, v.Build);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// constructs the writer with a given file and encoding
|
||||
/// </summary>
|
||||
/// <param name="fileType"></param>
|
||||
/// <param name="encoding"></param>
|
||||
internal Writer(File fileType, int encoding)
|
||||
: base(fileType, encoding)
|
||||
{
|
||||
WriterParent = fileType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initializes the writer
|
||||
/// </summary>
|
||||
/// <param name="pathname"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="dataFolder"></param>
|
||||
/// <param name="test"></param>
|
||||
/// <param name="bFiltering"></param>
|
||||
/// <param name="includeGroupNameInISOExport"></param>
|
||||
/// <param name="fd"></param>
|
||||
/// <param name="tmChannel"></param>
|
||||
/// <param name="channelNumber"></param>
|
||||
/// <param name="beginEventHandler"></param>
|
||||
/// <param name="cancelEventHandler"></param>
|
||||
/// <param name="endEventHandler"></param>
|
||||
/// <param name="tickEventHandler"></param>
|
||||
/// <param name="errorEventHandler"></param>
|
||||
/// <param name="cancelRequested"></param>
|
||||
public void Initialize(string pathname,
|
||||
string id,
|
||||
string dataFolder,
|
||||
Test test,
|
||||
bool bFiltering,
|
||||
bool includeGroupNameInISOExport,
|
||||
FilteredData fd,
|
||||
Channel tmChannel,
|
||||
int channelNumber,
|
||||
BeginEventHandler beginEventHandler,
|
||||
CancelEventHandler cancelEventHandler,
|
||||
EndEventHandler endEventHandler,
|
||||
TickEventHandler tickEventHandler,
|
||||
ErrorEventHandler errorEventHandler,
|
||||
CancelRequested cancelRequested)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
using DTS.Serialization.IRIGCH10.Enums;
|
||||
using DTS.Serialization.IRIGCH10.Packets;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10
|
||||
{
|
||||
/// <summary>
|
||||
/// this is the interface that all datapackets implement, it defines how packets can be interacted with in general
|
||||
/// </summary>
|
||||
public interface IDataPacket
|
||||
{
|
||||
/// <summary>
|
||||
/// all chapter 10 packets have a packet header
|
||||
/// </summary>
|
||||
IPacketHeader PacketHeader { get; }
|
||||
/// <summary>
|
||||
/// computes the checksum for the datapacket data
|
||||
/// </summary>
|
||||
uint ComputeCheckSum();
|
||||
/// <summary>
|
||||
/// returns all bytes for the packet
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
byte[] GetBytes();
|
||||
/// <summary>
|
||||
/// sets the Realtime Counter (10 MHZ) for the packet
|
||||
/// </summary>
|
||||
/// <param name="rtc"></param>
|
||||
void SetRTC(long rtc);
|
||||
/// <summary>
|
||||
/// sets the DataVersion of the packet
|
||||
/// (part of the packet header)
|
||||
/// </summary>
|
||||
/// <param name="version"></param>
|
||||
void SetDataVersion(DataTypeVersion version);
|
||||
|
||||
/// <summary>
|
||||
/// sets the packet flags for the packet (part of packet header)
|
||||
/// </summary>
|
||||
/// <param name="SecondaryHeaderPresent"></param>
|
||||
/// <param name="SecondaryHeaderTime"></param>
|
||||
/// <param name="RTCSyncerror"></param>
|
||||
/// <param name="DataOverflow"></param>
|
||||
/// <param name="fmt"></param>
|
||||
/// <param name="checkSum"></param>
|
||||
//void SetPacketFlags(bool SecondaryHeaderPresent,
|
||||
// bool SecondaryHeaderTime,
|
||||
// bool RTCSyncerror,
|
||||
// bool DataOverflow,
|
||||
// SecondaryHeaderTimeFormat fmt,
|
||||
// DataCheckSumType checkSum
|
||||
//);
|
||||
/// <summary>
|
||||
/// sets the channel id for the packet (part of packet header)
|
||||
/// </summary>
|
||||
/// <param name="channelID"></param>
|
||||
void SetChannelID(ushort channelID);
|
||||
/// <summary>
|
||||
/// sets the sequence number for the packet,
|
||||
/// in general should be increasing and flip back to 0
|
||||
/// after max value
|
||||
/// </summary>
|
||||
/// <param name="seq"></param>
|
||||
void SetSequenceNumber(ushort seq);
|
||||
}
|
||||
/// <summary>
|
||||
/// this is the general base class all packets extend, it
|
||||
/// has common features like computing the checksum, setting the
|
||||
/// packet specific Channel Data Word, etc
|
||||
/// </summary>
|
||||
public abstract class AbstractDataPacket
|
||||
{
|
||||
protected int CommonHeaderWork(ushort channelId, byte dataVersion,
|
||||
byte sequenceNumber, long rtc, uint dataLength, int nanoseconds, int seconds)
|
||||
{
|
||||
PacketHeader.ChannelId = channelId;
|
||||
PacketHeader.DataVersion = dataVersion;
|
||||
PacketHeader.SequenceNum = sequenceNumber;
|
||||
PacketHeader.IPTSTimeSource = PacketHeader.SecondaryHeaderPresent;
|
||||
PacketHeader.RTCSyncError = false;
|
||||
PacketHeader.SecondaryHeaderTimeFormat = IRIGCH10.PacketHeader.SecondaryHeaderTimeFormats.IEEE1588;
|
||||
PacketHeader.DataOverflowError = false;
|
||||
PacketHeader.CheckSumPresence = IRIGCH10.PacketHeader.DataCheckSumPresences.NotPresent;
|
||||
PacketHeader.SetRTC(rtc);
|
||||
PacketHeader.DataLength = dataLength;
|
||||
|
||||
PacketHeader.PacketLength = PacketHeader.DataLength + IRIGCH10.PacketHeader.PACKET_HEADER_LENGTH;
|
||||
if (PacketHeader.SecondaryHeaderPresent)
|
||||
{
|
||||
PacketHeader.PacketLength += SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH;
|
||||
}
|
||||
if (0 != PacketHeader.PacketLength % 4)
|
||||
{
|
||||
var pad = 4 - PacketHeader.PacketLength % 4;
|
||||
//pad out packet length to a multiple of 4 ...
|
||||
PacketHeader.PacketLength += pad;
|
||||
//_dataBytes = new byte[_dataBytes.Length + pad];
|
||||
}
|
||||
_dataBytes = new byte[PacketHeader.PacketLength - IRIGCH10.PacketHeader.PACKET_HEADER_LENGTH];
|
||||
|
||||
var offset = 0;
|
||||
|
||||
if (PacketHeader.SecondaryHeaderPresent)
|
||||
{
|
||||
var secondaryHeader = SecondaryTimeFormatHeader.GetBytes(nanoseconds, seconds);
|
||||
|
||||
Buffer.BlockCopy(secondaryHeader, 0, _dataBytes, offset, secondaryHeader.Length);
|
||||
offset += secondaryHeader.Length;
|
||||
}
|
||||
|
||||
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
Buffer.BlockCopy(channelSpecificDataWord, 0, _dataBytes, offset, channelSpecificDataWord.Length);
|
||||
offset += channelSpecificDataWord.Length;
|
||||
return offset;
|
||||
}
|
||||
private uint _ChannelSpecificDataWork = 0;
|
||||
[Browsable(false)]
|
||||
public uint ChannelSpecificDataWord
|
||||
{
|
||||
get => _ChannelSpecificDataWork;
|
||||
protected set => _ChannelSpecificDataWork = value;
|
||||
}
|
||||
[Browsable(false)]
|
||||
public IPacketHeader PacketHeader { get; protected set; }
|
||||
public uint ComputeCheckSum()
|
||||
{
|
||||
return Utils.Utils.GetCheckSum32(_dataBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sets the sequence number for the packet
|
||||
/// </summary>
|
||||
/// <param name="seq"></param>
|
||||
public void SetSequenceNumber(ushort seq)
|
||||
{
|
||||
PacketHeader.SequenceNum = BitConverter.GetBytes(seq)[0];
|
||||
}
|
||||
|
||||
private long _rtc;
|
||||
/// <summary>
|
||||
/// returns the Realtime Counter (10Mhz) value for the packet
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public long GetRTC() { return _rtc; }
|
||||
/// <summary>
|
||||
/// sets the Realtime Counter (10Mhz) value for the packet
|
||||
/// </summary>
|
||||
/// <param name="rtc"></param>
|
||||
public void SetRTC(long rtc)
|
||||
{
|
||||
_rtc = rtc;
|
||||
PacketHeader.SetRTC(rtc);
|
||||
|
||||
}
|
||||
|
||||
public const long BASE_RTC = 141989612500056L;
|
||||
/// <summary>
|
||||
/// returns all bytes for the packet
|
||||
/// is virtual so extending classes can define their own behavior as needed
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual byte[] GetBytes()
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write(PacketHeader.GetBytes());
|
||||
bw.Write(_dataBytes);
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public AbstractDataPacket(DataFileDataTypes dataType, bool secondaryHeaderPresent)
|
||||
{
|
||||
PacketHeader = new PacketHeader(dataType);
|
||||
PacketHeader.SecondaryHeaderPresent = secondaryHeaderPresent;
|
||||
}
|
||||
public AbstractDataPacket(byte[] bytes)
|
||||
{
|
||||
var header = new byte[24];
|
||||
Buffer.BlockCopy(bytes, 0, header, 0, 24);
|
||||
PacketHeader = new PacketHeader(header);
|
||||
FromBytes(bytes);
|
||||
}
|
||||
|
||||
protected virtual void FromBytes(byte[] bytes)
|
||||
{
|
||||
_dataBytes = new byte[PacketHeader.DataLength];
|
||||
Buffer.BlockCopy(bytes, 24, _dataBytes, 0, _dataBytes.Length);
|
||||
}
|
||||
protected byte[] _dataBytes;
|
||||
public void SetDataVersion(DataTypeVersion version)
|
||||
{
|
||||
PacketHeader.SetDataVersion(version);
|
||||
}
|
||||
|
||||
public void SetChannelID(ushort channelID)
|
||||
{
|
||||
PacketHeader.ChannelId = channelID;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Test.IConvertable.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
public delegate void ReportErrors(List<string> errors);
|
||||
/// <summary>
|
||||
/// An object that expresses this interface can convert itself to and from a
|
||||
/// <see cref="DTS.Serialization.Test"/> object.
|
||||
/// </summary>
|
||||
///
|
||||
public interface IConvertable
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert this object to a <see cref="DTS.Serialization.Test"/>.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="DTS.Serialization.Test"/> equivalent of this object.
|
||||
/// </returns>
|
||||
///
|
||||
Test ToDtsSerializationTest();
|
||||
|
||||
/// <summary>
|
||||
/// Initialize this object using the specified <see cref="DTS.Serialization.Test"/>.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="test">
|
||||
/// The <see cref="DTS.Serialization.Test"/> with which this object will be initialized from.
|
||||
/// </param>
|
||||
///
|
||||
void FromDtsSerializationTest(Test test, ReportErrors reportErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,850 @@
|
||||
/*
|
||||
* Iso.File.Writer.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using DTS.Common.Classes.Sensors;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.DAS.Concepts.DAS.Channel;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.Utils;
|
||||
|
||||
namespace DTS.Serialization.Iso
|
||||
{
|
||||
|
||||
// *** see Iso.File.cs ***
|
||||
public partial class File
|
||||
{
|
||||
|
||||
///
|
||||
/// <summary>
|
||||
/// Utility object for serializing <see cref="Serialization.Test"/>s to disk
|
||||
/// in the ISO format.
|
||||
/// </summary>
|
||||
///
|
||||
public class Writer : Writer<File>, IWriter<Serialization.Test>, IProgressAware
|
||||
{
|
||||
private const string VARIABLE_NAME_HEADER = "[";
|
||||
private const string VARIABLE_NAME_FOOTER = "]";
|
||||
/// <summary>
|
||||
/// used in mme file, this is the number of channels that will be exported
|
||||
/// 14226 Exports not using test obj/pos set by the group in a test when using a nonlinear sensor with a linear CAL
|
||||
/// (issue #2)
|
||||
/// </summary>
|
||||
public int NumberOfChannels { get; set; }
|
||||
private File _file = null;
|
||||
public File GetFile() { return _file; }
|
||||
public void SetFile(File f) { _file = f; }
|
||||
///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the Iso.File.Writer class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="fileType">
|
||||
/// The associated <see cref="File"/> object.
|
||||
/// </param>
|
||||
///
|
||||
internal Writer(File fileType, int encoding, File f)
|
||||
: base(fileType, encoding)
|
||||
{
|
||||
SetFile(f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notify <see cref="BeginEventHandler"/> subscribers that the write
|
||||
/// is starting.
|
||||
/// </summary>
|
||||
public event BeginEventHandler OnBegin;
|
||||
|
||||
/// <summary>
|
||||
/// Notify <see cref="EndEventHandler"/> subscribers that the write
|
||||
/// is finished.
|
||||
/// </summary>
|
||||
public event EndEventHandler OnEnd;
|
||||
|
||||
/// <summary>
|
||||
/// Notify <see cref="TickEventHandler"/> subscribers that we are one
|
||||
/// tick closer to write completion.
|
||||
/// </summary>
|
||||
public event TickEventHandler OnTick;
|
||||
|
||||
/// <summary>
|
||||
/// notify that the writer is cancelling
|
||||
/// </summary>
|
||||
public event CancelEventHandler OnCancel;
|
||||
|
||||
/// <summary>
|
||||
/// notify that the writer encountered fatal error
|
||||
/// </summary>
|
||||
public event ErrorEventHandler OnError;
|
||||
/// <summary>
|
||||
/// The number of data samples that need to be written for a "tick" to be dispatched.
|
||||
/// </summary>
|
||||
private int DataSamplesPerTick => 1000;
|
||||
|
||||
public bool UseZeroForUnfiltered { get; set; }
|
||||
public bool FilteredExport { get; set; }
|
||||
public bool ExportISOChannelName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Return the number of data to be written per "tick".
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
/// <returns></returns>
|
||||
private uint GetChannelTicks(Serialization.Test.Module.Channel channel)
|
||||
{
|
||||
try
|
||||
{ //
|
||||
// Most of our wait time will be spent writing data, so we need to give
|
||||
// the process a little finer granularity.
|
||||
//
|
||||
return (uint)(channel.PersistentChannelInfo.Length / DataSamplesPerTick);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem determining number of status ticks for channel " + (null != channel ? "\"" + channel.Number.ToString() + "\"" : "<NULL>"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly object ChannelLookupLock = new object();
|
||||
private readonly Dictionary<string, FilteredData> _channelDictionary = new Dictionary<string, FilteredData>();
|
||||
public FilteredData GetChannel(Serialization.Test.Module.Channel channel)
|
||||
{
|
||||
lock (ChannelLookupLock)
|
||||
{
|
||||
return _channelDictionary[$"{channel.ParentModule.SerialNumber}_{channel.ParentModule.Number}_{channel.Number}_{channel.ChannelDescriptionString}"];
|
||||
}
|
||||
}
|
||||
public void AddChannel(string dasserial, int moduleNumber, int number, string description, FilteredData data)
|
||||
{
|
||||
lock (ChannelLookupLock)
|
||||
{
|
||||
_channelDictionary.Add($"{dasserial}_{moduleNumber}_{number}_{description}", data);
|
||||
}
|
||||
}
|
||||
|
||||
// xxx May be able to do the check here?
|
||||
private void VerifyExportedFileWillFitOnDisk(
|
||||
string testname,
|
||||
string saveLocation,
|
||||
CancelRequested cancelRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
ulong predictedExportSize = 0;
|
||||
foreach (var sizedTestObject in FileType.TestInstance.Objects)
|
||||
predictedExportSize += (ulong)sizedTestObject.ToString().Length;
|
||||
|
||||
var sizedChannelNumber = 1;
|
||||
predictedExportSize += (ulong)("Instrumentation standard".PadRight(SeparatorOffset) + Separator + "ISO 6487 (1987) / SAE J211 (MAR95)").Length;
|
||||
predictedExportSize += (ulong)("Number of channels".PadRight(SeparatorOffset) + Separator + FileType.TestInstance.Channels.Count.ToString()).Length;
|
||||
|
||||
int thisChannelNumber;
|
||||
foreach (var channel in FileType.TestInstance.Channels)
|
||||
{
|
||||
if (null != cancelRequested && cancelRequested()) { break; }
|
||||
if (channel.Samples != null)
|
||||
{
|
||||
thisChannelNumber = sizedChannelNumber++;
|
||||
predictedExportSize += (ulong)channel.ToString().Length;
|
||||
long numSamples = channel.Samples.Data.Length;
|
||||
//this lets us do a little subsampling when predicting the export file size
|
||||
var segmentLength = numSamples / 20000;
|
||||
if (segmentLength < 1) { segmentLength = 1; }
|
||||
|
||||
for (long i = 0; i < channel.Samples.Data.Length; i += segmentLength)
|
||||
{
|
||||
if (null != cancelRequested && cancelRequested()) { break; }
|
||||
var segmentSize = (ulong)(channel.Samples.Data[i] - channel.DataZeroOffsetEu).ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat).Length;
|
||||
var nextJump = i + segmentLength > numSamples ? numSamples - i : segmentLength;
|
||||
//sanity check - if numSamples is 0 for some reason we don't want a negative nextJump, we still need to count space
|
||||
if (nextJump < 0) { nextJump = segmentLength; }
|
||||
predictedExportSize += (ulong)nextJump * segmentSize;
|
||||
}
|
||||
var channelName = channel.IsSquib ? channel.Name.ReplaceStrings(Common.Constants.ExportNameFilters, StringReplacementMode.Last) : channel.Name ?? ""; //17650: sanitize name output for certain exports
|
||||
predictedExportSize += (ulong)(("Name of channel " + thisChannelNumber.ToString("D3")).PadRight(SeparatorOffset) + Separator + channel.Code + " /" + channelName).Length;
|
||||
}
|
||||
}
|
||||
|
||||
predictedExportSize *= sizeof(char);
|
||||
|
||||
// Get the stats on available disk space.
|
||||
DiskUtility.GetDiskFreeSpaceEx(saveLocation, out ulong freeBytesAvailable, out ulong totalNumberOfBytes, out ulong totalNumberOfFreeBytes);
|
||||
|
||||
// Do the comparison.
|
||||
if (freeBytesAvailable < predictedExportSize)
|
||||
{
|
||||
var bytesNeeded = DiskUtility.GetHumanReadableBytes(predictedExportSize);
|
||||
var bytesAvailable = DiskUtility.GetHumanReadableBytes(freeBytesAvailable);
|
||||
throw new UserException("Export requires " + bytesNeeded + " but there are only " + bytesAvailable + " available on \"" + saveLocation + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem trying to determing if ISO export of test " + (testname ?? "<NULL>") + " will fit at location " + (saveLocation ?? "<NULL>"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <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="Serialization.Test"/> to be written out.
|
||||
/// </param>
|
||||
///
|
||||
public void Write(string pathname, string id, Serialization.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);
|
||||
}
|
||||
}
|
||||
private void AssignTestObject(ref Test.Object o, Common.ISO.MMETestObjectWrapper tow)
|
||||
{
|
||||
o.Class = tow.ClassOfTestObject;
|
||||
o.Code = tow.CodeOfTestObject;
|
||||
o.Comments = tow.Comments; // string.Join("\n", tow.Comments);
|
||||
o.Mass = tow.MassOfTestObject;
|
||||
//o.Name = tow.Name;
|
||||
o.Position = tow.DriverPosition;
|
||||
o.TestObjectImpactSide = tow.ImpactSide;
|
||||
o.Velocity = tow.VelocityMeterPerSecond;
|
||||
}
|
||||
private void ApplyISOTestChannel(ref Serialization.Test.Module.AnalogInputChannel channel, Common.ISO.TestObjectChannel toc)
|
||||
{
|
||||
//toc.CustomerChannelCode;
|
||||
}
|
||||
|
||||
private uint totalWriteTicksDispatched = 0;
|
||||
private uint totalWriteTicksNeeded = 0;
|
||||
/// <summary>
|
||||
/// populates a test object with meta data information
|
||||
/// this code already existed, I just abstracted it out for easier reading
|
||||
/// http://manuscript.dts.local/f/cases/13735/Need-the-ability-to-add-ISO-metadata-without-an-associated-Group
|
||||
/// </summary>
|
||||
/// <param name="testObject"></param>
|
||||
/// <param name="testObjects"></param>
|
||||
/// <param name="testObjectNumber"></param>
|
||||
/// <param name="ISOTestObjectType"></param>
|
||||
private void PopulateTestObject(Test.Object testObject, Common.ISO.MMETestObjectWrapper[] testObjects,
|
||||
int testObjectNumber, string ISOTestObjectType)
|
||||
{
|
||||
testObject.Comments = testObjects[testObjectNumber].Comments;
|
||||
testObject.Name = testObjects[testObjectNumber].Name;
|
||||
testObject.Velocity = testObjects[testObjectNumber].VelocityMeterPerSecond;
|
||||
testObject.Mass = testObjects[testObjectNumber].MassOfTestObject;
|
||||
testObject.Position = testObjects[testObjectNumber].DriverPosition;
|
||||
testObject.TestObjectImpactSide = testObjects[testObjectNumber].ImpactSide;
|
||||
testObject.Type = ISOTestObjectType;
|
||||
testObject.Class = testObjects[testObjectNumber].ClassOfTestObject;
|
||||
testObject.Code = testObjects[testObjectNumber].CodeOfTestObject;
|
||||
testObject.Number = testObjects[testObjectNumber].ReferenceNumberOfTestObject;
|
||||
testObject.Offset = testObjects[testObjectNumber].OffsetOfTestObject;
|
||||
testObject.BarrierWidth = testObjects[testObjectNumber].BarrierWidthOfTestObject;
|
||||
testObject.BarrierHeight = testObjects[testObjectNumber].BarrierHeightOfTestObject;
|
||||
testObject.YawAngle = testObjects[testObjectNumber].YawAngleOfTestObject;
|
||||
testObject.ReferenceSystem = testObjects[testObjectNumber].ReferenceSystemOfTestObject;
|
||||
testObject.OriginX = testObjects[testObjectNumber].OriginXOfTestObject;
|
||||
testObject.OriginY = testObjects[testObjectNumber].OriginYOfTestObject;
|
||||
testObject.OriginZ = testObjects[testObjectNumber].OriginZOfTestObject;
|
||||
testObject.NumberOfLoadcells = testObjects[testObjectNumber].NumberOfLoadcellsOfTestObject;
|
||||
testObject.ExtraProperties = testObjects[testObjectNumber].ExtraProperties.Select(kvp => new Test.ExtraProperty(kvp.Key, kvp.Value)).ToList();
|
||||
// Assign our object number.
|
||||
}
|
||||
/// <summary>
|
||||
/// Write the representation file/files of the specified DTS.Serialization.Test
|
||||
/// at the given pathname.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="pathname">
|
||||
/// The <see cref="string"/> pathname of the specified object's resulting file
|
||||
/// representation.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="test">
|
||||
/// The <see cref="Serialization.Test"/> to be written out.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="beginEvent">
|
||||
/// <see cref="Serialization.BeginWriteEventHandler"/> delegate to be notified
|
||||
/// when this object begins writing.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="endEvent">
|
||||
/// <see cref="Serialization.EndWriteEventHandler"/> delegate to be notified
|
||||
/// when this object ends writing.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="tickEvent">
|
||||
/// <see cref="TickEventHandler"/> delegate to be notified
|
||||
/// when this object completes a write "tick".
|
||||
/// </param>
|
||||
///
|
||||
public void Write(string pathname,
|
||||
string id,
|
||||
string dataFolder,
|
||||
Serialization.Test test,
|
||||
bool bFiltering,
|
||||
bool includeGroupNameInISOExport,
|
||||
FilteredData fd,
|
||||
Serialization.Test.Module.Channel tmChannel,
|
||||
int channelNumber,
|
||||
BeginEventHandler beginEventHandler,
|
||||
CancelEventHandler cancelEventHandler,
|
||||
EndEventHandler endEventHandler,
|
||||
TickEventHandler tickEventHandler,
|
||||
ErrorEventHandler errorEventHandler,
|
||||
CancelRequested cancelRequested,
|
||||
double minStartTime,
|
||||
int dataCollectionLength)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
var mmeDirectory = pathname + "\\";
|
||||
|
||||
var testSampleRate = test.Channels.Select(ch => ch.ParentModule.SampleRateHz).Max();
|
||||
|
||||
ISOChannelScale(totalWriteTicksDispatched, totalWriteTicksNeeded, tmChannel, bFiltering, fd, test.Id, includeGroupNameInISOExport, false, testSampleRate);
|
||||
|
||||
var testObjectNumber = 0;
|
||||
var testObjects = GetFile().GetTestPlan().ISOTestObjects;
|
||||
foreach (var ISOTestObjectType in testObjectChannels.Keys)
|
||||
{
|
||||
if (ISOTestObjectType != (tmChannel as IIsoCodeAware).IsoCode.Substring(0, 1))
|
||||
{
|
||||
testObjectNumber++;
|
||||
continue;
|
||||
}
|
||||
|
||||
var thisObjectChannels = testObjectChannels[ISOTestObjectType];
|
||||
|
||||
Test.Object testObject;
|
||||
FileType.TestInstance.Objects.Add(testObject = new Test.Object());
|
||||
PopulateTestObject(testObject, testObjects, testObjectNumber, ISOTestObjectType);
|
||||
testObject.MmeNumber = ++testObjectNumber;
|
||||
FileType.TestInstance.Channels[0].TestObjectNumber = testObject.MmeNumber;
|
||||
|
||||
FileType.TestInstance.Channels[0].ExtraProperties = testObject.ExtraProperties;
|
||||
//FB14276: If a Iso.File.Test.Channel's Extra Property's value contains "[Test.Module.Channel Property Name]", substitute in the tmc property's value
|
||||
IList<PropertyInfo> props = new List<PropertyInfo>(tmChannel.GetType().GetProperties());
|
||||
var propVals = props.Select(prop => new KeyValuePair<string, string>(prop.Name, prop.GetValue(tmChannel)?.ToString())).ToList();
|
||||
foreach (var exp in FileType.TestInstance.Channels[0].ExtraProperties)
|
||||
{
|
||||
foreach (var kvp in propVals)
|
||||
{
|
||||
exp.Value = exp.Value.Replace(VARIABLE_NAME_HEADER + kvp.Key + VARIABLE_NAME_FOOTER, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
testObject.TestObject = ISOTestObjectType; //not needed?
|
||||
|
||||
break; //We found what we were looking for, so no need to keep looping.
|
||||
}
|
||||
|
||||
//add any iso test objects from groups without channels ...
|
||||
foreach (var testObjectType in testObjects.Select(x => x.TypeOfTestObject))
|
||||
{
|
||||
var exists = FileType.TestInstance.Objects.Exists(o => o.Type == testObjectType);
|
||||
if (!exists)
|
||||
{
|
||||
var newObject = new Test.Object();
|
||||
PopulateTestObject(newObject, testObjects, testObjectNumber, testObjectType);
|
||||
newObject.MmeNumber = ++testObjectNumber;
|
||||
FileType.TestInstance.Objects.Add(newObject);
|
||||
}
|
||||
}
|
||||
|
||||
var channelLookup = new Dictionary<string, Common.ISO.TestObjectChannel>();
|
||||
var testObjectLookkup = new Dictionary<string, Common.ISO.MMETestObjectWrapper>();
|
||||
|
||||
ApplyAnalogChannel(tmChannel, channelLookup);
|
||||
for (var i = 0; i < FileType.TestInstance.Objects.Count; i++)
|
||||
{
|
||||
var o = FileType.TestInstance.Objects[i];
|
||||
if (testObjectLookkup.ContainsKey(o.TestObject))
|
||||
{
|
||||
AssignTestObject(ref o, testObjectLookkup[o.TestObject]);
|
||||
}
|
||||
}
|
||||
|
||||
var channelDirectory = mmeDirectory + "Channel\\";
|
||||
|
||||
var filename = channelDirectory + id + ".chn";
|
||||
APILogger.Log("writing 1 ", filename);
|
||||
Encoding encoder;
|
||||
|
||||
try
|
||||
{
|
||||
encoder = FileUtils.GetEncoding(DefaultEncoding);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("Problem getting encoder", ex);
|
||||
encoder = Encoding.Default;
|
||||
}
|
||||
using (var channelsFileWriter = new StreamWriter(filename, true, encoder))
|
||||
{
|
||||
foreach (var channel in FileType.TestInstance.Channels)
|
||||
{
|
||||
using (var channelFileWriter = new StreamWriter(channelDirectory + id + "." + channelNumber.ToString("D3"), false, encoder))
|
||||
{
|
||||
if (null != cancelRequested && cancelRequested()) { break; }
|
||||
channelFileWriter.Write(channel.ToString());
|
||||
if (channel.Samples != null)
|
||||
{
|
||||
for (long i = 0; i < channel.Samples.Data.Length; i++) // xxx change this back!!!
|
||||
{
|
||||
if (null != cancelRequested && cancelRequested()) { break; }
|
||||
channelFileWriter.WriteLine((channel.Samples.Data[i] - channel.DataZeroOffsetEu).ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat));
|
||||
if (0 == i % DataSamplesPerTick)
|
||||
{
|
||||
OnTick?.Invoke(this, (double)totalWriteTicksDispatched++ / totalWriteTicksNeeded * 100);
|
||||
System.Windows.Forms.Application.DoEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
channelFileWriter.Close();
|
||||
var channelName = channel.IsSquib ? channel.Name.ReplaceStrings(Common.Constants.ExportNameFilters, StringReplacementMode.Last) : channel.Name ?? ""; //17650: sanitize name output for certain exports
|
||||
channelsFileWriter.WriteLine(("Name of channel " + channelNumber.ToString("D3")).PadRight(SeparatorOffset) + Separator + channel.Code + " /" + channelName);
|
||||
}
|
||||
}
|
||||
channelsFileWriter.Close();
|
||||
FileType.TestInstance.Channels.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize(string pathname,
|
||||
string id,
|
||||
string dataFolder,
|
||||
Serialization.Test test,
|
||||
bool bFiltering,
|
||||
bool includeGroupNameInISOExport,
|
||||
FilteredData fd,
|
||||
Serialization.Test.Module.Channel tmChannel,
|
||||
int channelNumber,
|
||||
BeginEventHandler beginEventHandler,
|
||||
CancelEventHandler cancelEventHandler,
|
||||
EndEventHandler endEventHandler,
|
||||
TickEventHandler tickEventHandler,
|
||||
ErrorEventHandler errorEventHandler,
|
||||
CancelRequested cancelRequested)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
var mmeDirectory = pathname + "\\";
|
||||
|
||||
OnBegin += beginEventHandler;
|
||||
OnTick += tickEventHandler;
|
||||
OnCancel += cancelEventHandler;
|
||||
OnError += errorEventHandler;
|
||||
|
||||
foreach (var module in test.Modules)
|
||||
{
|
||||
foreach (var calculatedChannel in module.CalculatedChannels)
|
||||
{
|
||||
totalWriteTicksNeeded++;
|
||||
}
|
||||
}
|
||||
|
||||
uint totalWriteTicksDispatched = 0;
|
||||
foreach (var channel in test.Channels)
|
||||
totalWriteTicksNeeded += GetChannelTicks(channel);
|
||||
foreach (var module in test.Modules)
|
||||
{
|
||||
foreach (var calculatedChannel in module.CalculatedChannels)
|
||||
{
|
||||
totalWriteTicksNeeded += GetChannelTicks(calculatedChannel);
|
||||
}
|
||||
}
|
||||
OnBegin?.Invoke(this, totalWriteTicksNeeded);
|
||||
|
||||
var testSampleRate = test.Channels.Select(ch => ch.ParentModule.SampleRateHz).Max();
|
||||
|
||||
|
||||
foreach (var channel in test.Channels)
|
||||
{
|
||||
ISOChannelScale(totalWriteTicksDispatched, totalWriteTicksNeeded, channel, bFiltering, fd, test.Id, includeGroupNameInISOExport, true, testSampleRate);
|
||||
}
|
||||
|
||||
foreach (var module in test.Modules)
|
||||
{
|
||||
foreach (var calculatedChannel in module.CalculatedChannels)
|
||||
{
|
||||
ISOChannelScale(totalWriteTicksDispatched, totalWriteTicksNeeded, calculatedChannel, bFiltering, fd, test.Id, includeGroupNameInISOExport, true, testSampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
var testObjectNumber = 0;
|
||||
var testObjects = GetFile().GetTestPlan().ISOTestObjects;
|
||||
foreach (var ISOTestObjectType in testObjectChannels.Keys)
|
||||
{
|
||||
var thisObjectChannels = testObjectChannels[ISOTestObjectType];
|
||||
|
||||
Test.Object testObject;
|
||||
FileType.TestInstance.Objects.Add(testObject = new Test.Object());
|
||||
PopulateTestObject(testObject, testObjects, testObjectNumber, ISOTestObjectType);
|
||||
// Assign our object number.
|
||||
testObject.MmeNumber = ++testObjectNumber;
|
||||
|
||||
// Reference the associated ISO channels back to this object.
|
||||
foreach (var channel in thisObjectChannels)
|
||||
{
|
||||
channel.TestObjectNumber = testObject.MmeNumber;
|
||||
var code = new Common.ISO.IsoCode(channel.Code);
|
||||
channel.ChannelFrequencyClass = code.FilterClass;
|
||||
channel.Dimension = code.PhysicalDimension;
|
||||
channel.Direction = code.Direction;
|
||||
channel.ExtraProperties = testObject.ExtraProperties.ToList();
|
||||
}
|
||||
testObject.TestObject = ISOTestObjectType; //not needed?
|
||||
}
|
||||
|
||||
//add any iso test objects from groups without channels ...
|
||||
foreach (var testObjectType in testObjects.Select(x => x.TypeOfTestObject))
|
||||
{
|
||||
var exists = FileType.TestInstance.Objects.Exists(o => o.Type == testObjectType);
|
||||
if (!exists)
|
||||
{
|
||||
var newObject = new Test.Object();
|
||||
PopulateTestObject(newObject, testObjects, testObjectNumber, testObjectType);
|
||||
newObject.MmeNumber = ++testObjectNumber;
|
||||
FileType.TestInstance.Objects.Add(newObject);
|
||||
}
|
||||
}
|
||||
|
||||
var channelLookup = new Dictionary<string, Common.ISO.TestObjectChannel>();
|
||||
var testObjectLookkup = new Dictionary<string, Common.ISO.MMETestObjectWrapper>();
|
||||
|
||||
for (var i = 0; i < test.Channels.Count; i++)
|
||||
{
|
||||
ApplyAnalogChannel(test.Channels[i], channelLookup);
|
||||
}
|
||||
foreach (var module in test.Modules)
|
||||
{
|
||||
foreach (var calculatedChannel in module.CalculatedChannels)
|
||||
{
|
||||
ApplyAnalogChannel(calculatedChannel, channelLookup);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < FileType.TestInstance.Objects.Count; i++)
|
||||
{
|
||||
var o = FileType.TestInstance.Objects[i];
|
||||
if (testObjectLookkup.ContainsKey(o.TestObject))
|
||||
{
|
||||
AssignTestObject(ref o, testObjectLookkup[o.TestObject]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Directory.Exists(mmeDirectory))
|
||||
Directory.CreateDirectory(mmeDirectory);
|
||||
VerifyExportedFileWillFitOnDisk(test.Id, mmeDirectory, cancelRequested);
|
||||
Encoding encoder;
|
||||
|
||||
try
|
||||
{
|
||||
encoder = Common.Utils.FileUtils.GetEncoding(DefaultEncoding);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("Problem getting encoder", ex);
|
||||
encoder = Encoding.Default;
|
||||
}
|
||||
using (var fileWriter = new StreamWriter(mmeDirectory + id + TestFileExtension, false, encoder))
|
||||
{
|
||||
var enc = fileWriter.Encoding;
|
||||
fileWriter.Write(FileType.TestInstance.ToString());
|
||||
foreach (var testObject in FileType.TestInstance.Objects)
|
||||
{
|
||||
fileWriter.Write(testObject.ToString());
|
||||
}
|
||||
fileWriter.Close();
|
||||
}
|
||||
FileType.TestInstance.Objects.Clear();
|
||||
|
||||
var channelDirectory = mmeDirectory + "Channel\\";
|
||||
|
||||
if (!Directory.Exists(channelDirectory))
|
||||
Directory.CreateDirectory(channelDirectory);
|
||||
VerifyExportedFileWillFitOnDisk(test.Id, channelDirectory, cancelRequested);
|
||||
|
||||
var filename = channelDirectory + id + ".chn";
|
||||
APILogger.Log("writing 1 ", filename);
|
||||
using (var channelsFileWriter = new StreamWriter(filename, false, encoder))
|
||||
{
|
||||
channelsFileWriter.WriteLine("Instrumentation standard".PadRight(SeparatorOffset) + Separator + "ISO 6487 (1987) / SAE J211 (MAR95)");
|
||||
channelsFileWriter.WriteLine("Number of channels".PadRight(SeparatorOffset) + Separator + NumberOfChannels.ToString());
|
||||
FileType.TestInstance.Channels.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log($"encountered problem writing ISO test files", ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// controls whether to use desired range or actual range
|
||||
/// Channel amplitude class
|
||||
/// 15392 Exported CAC in the MME file is the requested CAC not the actual CAC
|
||||
/// </summary>
|
||||
public bool ExportActualRange { get; set; } = false;
|
||||
private readonly IDictionary<string, List<Test.Channel>> testObjectChannels = new Dictionary<string, List<Test.Channel>>();
|
||||
public bool UseIsoCodeFilterMapping { get; set; } = true;
|
||||
|
||||
private void ISOChannelScale(uint totalWriteTicksDispatched, uint totalWriteTicksNeeded, Serialization.Test.Module.Channel channel,
|
||||
bool bFiltering, FilteredData fd, string testId, bool includeGroupNameInISOExport, bool initializing, double testSampleRate)
|
||||
{
|
||||
Test.Channel isoChannel;
|
||||
FileType.TestInstance.Channels.Add(isoChannel = new Test.Channel());
|
||||
|
||||
isoChannel.BitResolution = 16;
|
||||
isoChannel.Code = channel is IIsoCodeAware ? (channel as IIsoCodeAware).IsoCode : NoValue;
|
||||
var code = new Common.ISO.IsoCode(isoChannel.Code);
|
||||
isoChannel.ChannelFrequencyClass = code.FilterClass;
|
||||
isoChannel.Dimension = code.PhysicalDimension;
|
||||
isoChannel.Direction = code.Direction;
|
||||
isoChannel.Location = code.MainLocation;
|
||||
|
||||
if (initializing)
|
||||
{
|
||||
if (!isoChannel.Code.Equals(NoValue, StringComparison.OrdinalIgnoreCase))
|
||||
{ //
|
||||
// Push each channel into our dictionary of ISO-object-indexable ISO channels.
|
||||
//
|
||||
var objectCode = isoChannel.Code.Substring(0, 1);
|
||||
if (!testObjectChannels.Keys.Contains(objectCode))
|
||||
testObjectChannels.Add(objectCode, new List<Test.Channel>());
|
||||
testObjectChannels[objectCode].Add(isoChannel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
isoChannel.PrefilterType = "Butterworth, 5 pole"; // This will need to change for SlicePRO
|
||||
|
||||
if (channel is Serialization.Test.Module.AnalogInputChannel)
|
||||
{
|
||||
isoChannel.IsDigitalInput = (channel as Serialization.Test.Module.AnalogInputChannel).Bridge == SensorConstants.BridgeType.DigitalInput;
|
||||
isoChannel.IsSquib = (channel as Serialization.Test.Module.AnalogInputChannel).Bridge == SensorConstants.BridgeType.SQUIB;
|
||||
}
|
||||
|
||||
isoChannel.CutOffFrequency = channel.ParentModule.AaFilterRateHz;
|
||||
if (ExportISOChannelName)
|
||||
{
|
||||
if (includeGroupNameInISOExport)
|
||||
{
|
||||
isoChannel.Name = channel.ChannelGroupName + ":" + channel.ChannelName2;
|
||||
}
|
||||
else
|
||||
{
|
||||
isoChannel.Name = channel.ChannelName2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (includeGroupNameInISOExport)
|
||||
{
|
||||
isoChannel.Name = channel.ChannelGroupName + ":" + channel.ChannelDescriptionString;
|
||||
}
|
||||
else
|
||||
{
|
||||
isoChannel.Name = channel.ChannelDescriptionString;
|
||||
}
|
||||
}
|
||||
isoChannel.SamplingInterval = 1.0 / channel.ParentModule.SampleRateHz;
|
||||
isoChannel.SamplingIntervalTest = 1D / testSampleRate;
|
||||
var aic = channel as Serialization.Test.Module.AnalogInputChannel;
|
||||
if (null != aic)
|
||||
{
|
||||
isoChannel.TransducerId = string.IsNullOrWhiteSpace(aic.SerialNumber) ? aic.ToString() : aic.SerialNumber;
|
||||
}
|
||||
if (null != channel.ParentModule.TriggerSampleNumbers && 1 >= channel.ParentModule.TriggerSampleNumbers.Count)
|
||||
{
|
||||
isoChannel.TimeOfFirstSample = (channel.ParentModule.StartRecordSampleNumber - (double)channel.ParentModule.TriggerSampleNumbers[0])
|
||||
/ channel.ParentModule.SampleRateHz;
|
||||
}
|
||||
else { isoChannel.TimeOfFirstSample = 0; }
|
||||
isoChannel.StartOffsetInterval = (channel as Serialization.Test.Module.AnalogInputChannel).ZeroAverageWindow.Begin;
|
||||
isoChannel.EndOffsetInterval = (channel as Serialization.Test.Module.AnalogInputChannel).ZeroAverageWindow.End;
|
||||
|
||||
if (channel is IEngineeringUnitAware)
|
||||
{
|
||||
isoChannel.Unit = (channel as IEngineeringUnitAware).EngineeringUnits.TrimEnd();
|
||||
if (isoChannel.Unit == "G")
|
||||
{
|
||||
isoChannel.Unit = "g"; //X-Crash doesn't like "G"
|
||||
}
|
||||
}
|
||||
|
||||
var scaler = new DataScaler();
|
||||
scaler.IsInverted = channel is IInversionAware ? (channel as IInversionAware).IsInverted : false;
|
||||
|
||||
if ((channel as ILinearized).LinearizationFormula.IsValid())
|
||||
{
|
||||
scaler.SetLinearizationFormula((channel as ILinearized).LinearizationFormula);
|
||||
}
|
||||
else
|
||||
{
|
||||
scaler.SetLinearizationFormula(null);
|
||||
}
|
||||
|
||||
scaler.Digital = (channel as Serialization.Test.Module.AnalogInputChannel).IsDigital();
|
||||
|
||||
scaler.SetDigitalMultiplier((channel as Serialization.Test.Module.AnalogInputChannel).DigitalMultiplier);
|
||||
scaler.DigitalMode = (channel as Serialization.Test.Module.AnalogInputChannel).DigitalMode;
|
||||
|
||||
|
||||
scaler.SetScaleFactorMv(channel.Data.ScaleFactorMv);
|
||||
scaler.SetScaleFactorEU(channel.Data.ScaleFactorEU);
|
||||
scaler.SetUseEUScaleFactors(channel.Data.UseEUScaleFactors);
|
||||
scaler.UnitConversion = (channel as Serialization.Test.Module.AnalogInputChannel).UnitConversion;
|
||||
|
||||
scaler.BasedOnOutputAtCapacity = (channel as Serialization.Test.Module.AnalogInputChannel).AtCapacity;
|
||||
scaler.CapacityOutputIsBasedOn = (channel as Serialization.Test.Module.AnalogInputChannel).CapacityOutputIsBasedOn;
|
||||
scaler.SensitivityUnits = (channel as Serialization.Test.Module.AnalogInputChannel).SensitivityUnits;
|
||||
scaler.Multiplier = (channel as Serialization.Test.Module.AnalogInputChannel).Multiplier;
|
||||
scaler.UserOffsetEU = (channel as Serialization.Test.Module.AnalogInputChannel).UserOffsetEU;
|
||||
|
||||
if (channel is Serialization.Test.Module.AnalogInputChannel)
|
||||
{
|
||||
scaler.IEPE = (channel as Serialization.Test.Module.AnalogInputChannel).Bridge == SensorConstants.BridgeType.IEPE;
|
||||
scaler.Digital = (channel as Serialization.Test.Module.AnalogInputChannel).Bridge == SensorConstants.BridgeType.DigitalInput;
|
||||
}
|
||||
scaler.SetMvPerEu(channel.Data.MvPerEu);
|
||||
scaler.SetDataZeroLevelADC(channel.DataZeroLevelAdc);
|
||||
scaler.SetRemovedADC(channel.RemovedADC);
|
||||
scaler.SetRemovedInternalADC(channel.RemovedInternalADC);
|
||||
|
||||
scaler.SetZeroMvInADC(channel.ZeroMvInADC);
|
||||
try { scaler.SetWindowAverageADC(channel.WindowAverageADC); }
|
||||
catch (System.Exception) { }
|
||||
|
||||
if (channel is Serialization.Test.Module.AnalogInputChannel)
|
||||
{
|
||||
//
|
||||
// Maybe these should be replaced by DTS.DAS.Concepts versions for casting? Would need to
|
||||
// add excitation voltage as a concept, and proportional to excitation.
|
||||
//
|
||||
var analogChannel = channel as Serialization.Test.Module.AnalogInputChannel;
|
||||
|
||||
try { scaler.SetInitialOffset(analogChannel.InitialOffset); }
|
||||
catch (System.Exception) { }
|
||||
scaler.ZeroMethodType = analogChannel.ZeroMethod;
|
||||
scaler.NominalExcitationVoltage = analogChannel.ExcitationVoltage;
|
||||
if (analogChannel.MeasuredExcitationVoltageValid)
|
||||
{
|
||||
try { scaler.MeasuredExcitationVoltage = analogChannel.MeasuredExcitationVoltage; }
|
||||
catch { };
|
||||
}
|
||||
if (analogChannel.FactoryExcitationVoltageValid)
|
||||
{
|
||||
try { scaler.FactoryExcitationVoltage = analogChannel.FactoryExcitationVoltage; }
|
||||
catch { };
|
||||
}
|
||||
scaler.ProportionalToExcitation = analogChannel.ProportionalToExcitation;
|
||||
isoChannel.StartOffsetInterval = analogChannel.ZeroAverageWindow.Begin;
|
||||
isoChannel.EndOffsetInterval = analogChannel.ZeroAverageWindow.End;
|
||||
}
|
||||
|
||||
|
||||
// xxx Probably need to create an object for isoChannel.Samples that wraps the memory mapped data
|
||||
// object and just converts the samples as they're accessed. And maybe for the data viewer, we can
|
||||
// do an "is a" test on the data object and do the right thing accordingly...?
|
||||
// xxx Or is there any reason why we can't just keep it short and cast it each time?
|
||||
if ((channel as ILinearized).LinearizationFormula.IsValid())
|
||||
{
|
||||
isoChannel.DataZeroOffsetEu = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//19038 Export data in ISO not respecting initial offset EU at mV settings.
|
||||
//DataZeroOffsetEU in linear sensors should be a constant, but we can't
|
||||
//just subtract GetEU(DataZeroLevelADC), normally EU= GetEU(ADC-ZeroLevelADC) but
|
||||
//this overlooks and overapplies things like InitialOffsetEU, so
|
||||
//EU = GetEU(ADC)-GetEU(ZeroLevelADC) is applying InitialOffset twice while
|
||||
//EU = GetEU(ADC-ZeroLevelADC) only applies it once ... so don't apply any initial offset to DataZeroOfsetEU
|
||||
var scaler2 = new DataScaler(scaler);
|
||||
scaler2.SetInitialOffset(new InitialOffset() { Form = InitialOffsetTypes.None, EU = 0, MV = 0 });
|
||||
//also close out useroffset or it will be double counted ...
|
||||
//29678 ISO export does not match CSV/ Viewer output
|
||||
scaler2.UserOffsetEU = 0;
|
||||
isoChannel.DataZeroOffsetEu = scaler2.GetEU(channel.DataZeroLevelAdc);
|
||||
}
|
||||
|
||||
isoChannel.Samples = fd;
|
||||
isoChannel.OffsetPostTest = scaler.GetEU(channel.PreTestZeroLevelAdc); //Change this when we have post-test diagnostics
|
||||
|
||||
// 15392 Exported CAC in the MME file is the requested CAC not the actual CAC
|
||||
if (ExportActualRange)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (scaler.GetLinearizationFormula().IsValid())
|
||||
{
|
||||
isoChannel.AmplitudeClass = aic?.DesiredRange ?? 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
var a = scaler.GetEU(short.MinValue);
|
||||
var b = scaler.GetEU(short.MaxValue);
|
||||
isoChannel.AmplitudeClass = Math.Abs((b - a) / 2);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("Actual range unavailable for channel export", ex);
|
||||
isoChannel.AmplitudeClass = aic.DesiredRange;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isoChannel.AmplitudeClass = aic.DesiredRange;
|
||||
}
|
||||
|
||||
channel.PersistentChannelInfo.Dispose();
|
||||
}
|
||||
|
||||
private void ApplyAnalogChannel(Serialization.Test.Module.Channel channel, Dictionary<string, Common.ISO.TestObjectChannel> channelLookup)
|
||||
{
|
||||
if (!(channel is Serialization.Test.Module.AnalogInputChannel analogChannel)) { return; }
|
||||
if (channelLookup.ContainsKey(analogChannel.SerialNumber))
|
||||
{
|
||||
ApplyISOTestChannel(ref analogChannel, channelLookup[analogChannel.SerialNumber]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DTS.Serialization.TSV
|
||||
{
|
||||
public partial class TSVSettingsWindow : Form
|
||||
{
|
||||
protected TSVSettingsWindow() { InitializeComponent(); }
|
||||
|
||||
private volatile bool _bPopulating = false;
|
||||
private TSVTest _test;
|
||||
public TSVSettingsWindow(TSVTest test)
|
||||
{
|
||||
InitializeComponent();
|
||||
_test = test;
|
||||
_bPopulating = true;
|
||||
try
|
||||
{
|
||||
c1GridGlobal.AutoGenerateColumns = false;
|
||||
c1GridGlobal.Styles.Alternate.BackColor = Properties.Settings1.Default.AlternatingRow;
|
||||
c1GridGlobal.Styles.Fixed.BackColor = Properties.Settings1.Default.TableHeader;
|
||||
|
||||
TSVTest.Fields[] fields = Enum.GetValues(typeof(TSVTest.Fields)).Cast<TSVTest.Fields>().ToArray();
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case TSVTest.Fields.AAFilterCutoffDescription:
|
||||
case TSVTest.Fields.BitResolution:
|
||||
case TSVTest.Fields.ChannelErrors:
|
||||
case TSVTest.Fields.DataType:
|
||||
case TSVTest.Fields.DigitalFilterType:
|
||||
case TSVTest.Fields.EngineeringUnits:
|
||||
case TSVTest.Fields.SensorAxis:
|
||||
case TSVTest.Fields.SensorLocation:
|
||||
case TSVTest.Fields.SensorMakeModelSerial:
|
||||
case TSVTest.Fields.SensorMountType:
|
||||
//do not display
|
||||
break;
|
||||
default:
|
||||
var row = c1GridGlobal.Rows.Add();
|
||||
row["colField"] = TSVStrings.ResourceManager.GetString(string.Format("{0}_Title", field.ToString()));
|
||||
row["colDescription"] = TSVStrings.ResourceManager.GetString(string.Format("{0}_Description", field.ToString()));
|
||||
row["colValue"] = test.GetValue(field);
|
||||
row.UserData = field;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
c1GridChannels.Styles.Fixed.BackColor = Properties.Settings1.Default.TableHeader;
|
||||
c1GridChannels.Styles.Alternate.BackColor = Properties.Settings1.Default.AlternatingRow;
|
||||
|
||||
var c = c1GridChannels.Cols.Add();
|
||||
c.Caption = "Channel Number";
|
||||
c.AllowEditing = false;
|
||||
c.DataType = typeof(int);
|
||||
c.Name = "colNumber";
|
||||
c.UserData = null;
|
||||
|
||||
c = c1GridChannels.Cols.Add();
|
||||
c.Caption = "File Name";
|
||||
c.AllowEditing = true;
|
||||
c.DataType = typeof(string);
|
||||
c.Name = "colFileName";
|
||||
c.UserData = null;
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
c = c1GridChannels.Cols.Add();
|
||||
c.Caption = TSVStrings.ResourceManager.GetString(string.Format("{0}_Title", field.ToString()));
|
||||
c.DataType = typeof(string);
|
||||
c.AllowEditing = true;
|
||||
c.Name = "col" + field.ToString();
|
||||
c.UserData = field;
|
||||
}
|
||||
|
||||
foreach (var channel in test.Channels)
|
||||
{
|
||||
var r = c1GridChannels.Rows.Add();
|
||||
r["colNumber"] = channel.ChannelNumber;
|
||||
r["colFileName"] = channel.FileName;
|
||||
foreach (var field in fields) { r["col" + field.ToString()] = channel.GetValue(field); }
|
||||
r.UserData = channel;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_bPopulating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void button1_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void c1GridGlobal_CellChanged(object sender, C1.Win.C1FlexGrid.RowColEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void gridChannels_CellChanged(object sender, C1.Win.C1FlexGrid.RowColEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void c1GridChannels_AfterEdit(object sender, C1.Win.C1FlexGrid.RowColEventArgs e)
|
||||
{
|
||||
if (_bPopulating) { return; }
|
||||
try
|
||||
{
|
||||
_bPopulating = true;
|
||||
if (null != c1GridChannels.Rows[e.Row].UserData)
|
||||
{
|
||||
TSVChannel channel = c1GridChannels.Rows[e.Row].UserData as TSVChannel;
|
||||
if (null == channel) { return; }
|
||||
|
||||
if (null != c1GridChannels.Cols[e.Col].UserData)
|
||||
{
|
||||
TSVTest.Fields field = (TSVTest.Fields)c1GridChannels.Cols[e.Col].UserData;
|
||||
channel.SetValue(field, c1GridChannels.Rows[e.Row][e.Col] as string);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_bPopulating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void c1GridGlobal_AfterEdit(object sender, C1.Win.C1FlexGrid.RowColEventArgs e)
|
||||
{
|
||||
if (_bPopulating) { return; }
|
||||
try
|
||||
{
|
||||
if (null != c1GridGlobal.Rows[e.Row].UserData)
|
||||
{
|
||||
TSVTest.Fields field = (TSVTest.Fields)c1GridGlobal.Rows[e.Row].UserData;
|
||||
_test.SetValue(field, c1GridGlobal.Rows[e.Row]["colValue"] as string);
|
||||
|
||||
for (int i = 0; i < c1GridChannels.Rows.Count; i++)
|
||||
{
|
||||
if (null != c1GridChannels.Rows[i].UserData)
|
||||
{
|
||||
TSVChannel channel = c1GridChannels.Rows[i].UserData as TSVChannel;
|
||||
if (null != channel)
|
||||
{
|
||||
c1GridChannels.Rows[i]["col" + field.ToString()] = channel.GetValue(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally { _bPopulating = false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using IRIGCh10;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10.TMATS.DataConversion
|
||||
{
|
||||
public enum TelemetryAttributes
|
||||
{
|
||||
[Description("BFM")]
|
||||
[MaxLength(3)]
|
||||
BinaryFormat
|
||||
}
|
||||
|
||||
public enum BinaryFormats
|
||||
{
|
||||
[Description("INT")]
|
||||
Integer,
|
||||
[Description("UNS")]
|
||||
UnsignedBinary,
|
||||
[Description("SIG")]
|
||||
SignAndMagnitudeSig,
|
||||
[Description("SIM")]
|
||||
SignAndMagnitudeSim,
|
||||
[Description("ONE")]
|
||||
OnesCompliment,
|
||||
[Description("TWO")]
|
||||
TwosCompliment,
|
||||
[Description("OFF")]
|
||||
OffsetBinary,
|
||||
[Description("FPT")]
|
||||
FloatingPoint,
|
||||
[Description("BCD")]
|
||||
BinaryCodedDecimal,
|
||||
[Description("BWT")]
|
||||
BitWeight,
|
||||
[Description("OTH")]
|
||||
Other
|
||||
}
|
||||
/// <summary>
|
||||
/// implements part of the telemetry section of the TMATS packet (see chapter 9)
|
||||
/// </summary>
|
||||
public class TelemetrySection : TMATSSection<TelemetryAttributes>
|
||||
{
|
||||
public TelemetrySection(int number) : base(AttributeIdentifiers.DataConversionAttributes, number)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetBinaryFormat(BinaryFormats format)
|
||||
{
|
||||
SetValueWithLength(TelemetryAttributes.BinaryFormat,
|
||||
DescriptionDecoder.GetDescription(format));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
namespace DTS.Serialization.TSV
|
||||
{
|
||||
partial class TSVSettingsWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TSVSettingsWindow));
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.c1GridGlobal = new C1.Win.C1FlexGrid.C1FlexGrid();
|
||||
this.c1GridChannels = new C1.Win.C1FlexGrid.C1FlexGrid();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.c1GridGlobal)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.c1GridChannels)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.ColumnCount = 1;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel1.Controls.Add(this.button1, 0, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.tabControl1, 0, 1);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 3;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 494F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(731, 570);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Location = new System.Drawing.Point(3, 544);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(75, 23);
|
||||
this.button1.TabIndex = 0;
|
||||
this.button1.Text = "Export";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Font = new System.Drawing.Font("Segoe UI", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label1.Location = new System.Drawing.Point(3, 0);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(656, 20);
|
||||
this.label1.TabIndex = 1;
|
||||
this.label1.Text = "Use Global tab to set values across all channels. Use Channels tab to set indivi" +
|
||||
"dual channel values.";
|
||||
//
|
||||
// tabControl1
|
||||
//
|
||||
this.tabControl1.Controls.Add(this.tabPage1);
|
||||
this.tabControl1.Controls.Add(this.tabPage2);
|
||||
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tabControl1.Location = new System.Drawing.Point(3, 50);
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(725, 488);
|
||||
this.tabControl1.TabIndex = 2;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.Controls.Add(this.c1GridGlobal);
|
||||
this.tabPage1.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage1.Name = "tabPage1";
|
||||
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage1.Size = new System.Drawing.Size(717, 462);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Global Settings";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Controls.Add(this.c1GridChannels);
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage2.Name = "tabPage2";
|
||||
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage2.Size = new System.Drawing.Size(717, 462);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Channel Settings";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// c1GridGlobal
|
||||
//
|
||||
this.c1GridGlobal.ColumnInfo = resources.GetString("c1GridGlobal.ColumnInfo");
|
||||
this.c1GridGlobal.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.c1GridGlobal.ExtendLastCol = true;
|
||||
this.c1GridGlobal.Location = new System.Drawing.Point(3, 3);
|
||||
this.c1GridGlobal.Name = "c1GridGlobal";
|
||||
this.c1GridGlobal.Rows.Count = 1;
|
||||
this.c1GridGlobal.Rows.DefaultSize = 19;
|
||||
this.c1GridGlobal.Size = new System.Drawing.Size(711, 456);
|
||||
this.c1GridGlobal.TabIndex = 0;
|
||||
this.c1GridGlobal.CellChanged += new C1.Win.C1FlexGrid.RowColEventHandler(this.c1GridGlobal_CellChanged);
|
||||
this.c1GridGlobal.AfterEdit += new C1.Win.C1FlexGrid.RowColEventHandler(this.c1GridGlobal_AfterEdit);
|
||||
//
|
||||
// c1GridChannels
|
||||
//
|
||||
this.c1GridChannels.AutoGenerateColumns = false;
|
||||
this.c1GridChannels.ColumnInfo = "1,1,0,0,0,95,Columns:";
|
||||
this.c1GridChannels.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.c1GridChannels.Location = new System.Drawing.Point(3, 3);
|
||||
this.c1GridChannels.Name = "c1GridChannels";
|
||||
this.c1GridChannels.Rows.Count = 1;
|
||||
this.c1GridChannels.Rows.DefaultSize = 19;
|
||||
this.c1GridChannels.Size = new System.Drawing.Size(711, 456);
|
||||
this.c1GridChannels.TabIndex = 0;
|
||||
this.c1GridChannels.CellChanged += new C1.Win.C1FlexGrid.RowColEventHandler(this.gridChannels_CellChanged);
|
||||
this.c1GridChannels.AfterEdit += new C1.Win.C1FlexGrid.RowColEventHandler(this.c1GridChannels_AfterEdit);
|
||||
//
|
||||
// TSVSettingsWindow
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(239)))), ((int)(((byte)(246)))), ((int)(((byte)(253)))));
|
||||
this.ClientSize = new System.Drawing.Size(731, 570);
|
||||
this.Controls.Add(this.tableLayoutPanel1);
|
||||
this.Name = "TSVSettingsWindow";
|
||||
this.Text = "TSV Options";
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.c1GridGlobal)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.c1GridChannels)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.Button button1;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.TabControl tabControl1;
|
||||
private System.Windows.Forms.TabPage tabPage1;
|
||||
private System.Windows.Forms.TabPage tabPage2;
|
||||
private C1.Win.C1FlexGrid.C1FlexGrid c1GridGlobal;
|
||||
private C1.Win.C1FlexGrid.C1FlexGrid c1GridChannels;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* TDAS.File.cs
|
||||
*
|
||||
* Copyright © 2010
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Serialization.TDAS
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// TDAS File
|
||||
/// </summary>
|
||||
///
|
||||
public partial class File
|
||||
: Serialization.File, IWritable<Test>
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the FtssCsv.File class.
|
||||
/// </summary>
|
||||
///
|
||||
public File()
|
||||
: base("TDAS")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get this file format's extension.
|
||||
/// </summary>
|
||||
public static string Extension => ".tlf";
|
||||
|
||||
/// <summary>
|
||||
/// Get the file writer for this file type.
|
||||
/// </summary>
|
||||
public IWriter<Test> Exporter
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_Exporter == null)
|
||||
_Exporter = new Writer(this, DefaultEncoding);
|
||||
return _Exporter;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting exporter", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private IWriter<Test> _Exporter = null;
|
||||
|
||||
/// <summary>
|
||||
/// Get the file reader for this file type.
|
||||
/// </summary>
|
||||
public IReader<Test> Importer
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_Importer == null)
|
||||
_Importer = new Reader(this);
|
||||
return _Importer;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting importer", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private IReader<Test> _Importer = null;
|
||||
|
||||
/// <summary>
|
||||
/// File extension for the disk entity that contains the serialized test information.
|
||||
/// </summary>
|
||||
public static string TestFileExtension
|
||||
{
|
||||
get => _TestFileExtension.Value;
|
||||
private set => _TestFileExtension.Value = value;
|
||||
}
|
||||
private static readonly Property<string> _TestFileExtension = new Property<string>("TestFileExtension", ".tlf", true);
|
||||
|
||||
/// <summary>
|
||||
/// File extension for the disk entity that contains serialized channel information.
|
||||
/// </summary>
|
||||
public static string ChannelFileExtension
|
||||
{
|
||||
get => _ChannelFileExtension.Value;
|
||||
private set => _ChannelFileExtension.Value = value;
|
||||
}
|
||||
private static readonly Property<string> _ChannelFileExtension = new Property<string>("ChannelFileExtension", ".BIN", true);
|
||||
|
||||
/// <summary>
|
||||
/// File extension for the disk entity that contains serialized channel information.
|
||||
/// </summary>
|
||||
public static string CalculatedChannelFileExtension
|
||||
{
|
||||
get => _CalculatedChannelFileExtension.Value;
|
||||
private set => _CalculatedChannelFileExtension.Value = value;
|
||||
}
|
||||
private static readonly Property<string> _CalculatedChannelFileExtension = new Property<string>("CalculatedChannelFileExtension", ".cchn", true);
|
||||
|
||||
/// <summary>
|
||||
/// The string that separates the channel numbers from the riffraff.
|
||||
/// </summary>
|
||||
private const string ChannelNumberDelimiter = ".";
|
||||
|
||||
/// <summary>
|
||||
/// Extract the channel number from the specified channel filename.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="channelFileName">
|
||||
/// The channel filename <see cref="string"/> to be converted into a channel number.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="int"/> channel number represented by the specified file.
|
||||
/// </returns>
|
||||
///
|
||||
public override int GetChannelNumberFromChannelFileName(string channelFileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var indexOfExtension = channelFileName.LastIndexOf(ChannelFileExtension);
|
||||
if (indexOfExtension == -1)
|
||||
{
|
||||
indexOfExtension = channelFileName.LastIndexOf(ChannelFileExtension.ToLower());
|
||||
}
|
||||
var indexOfFirstChannelNumberCharacter = indexOfExtension - 3; //901, 001, etc. but could be _C001 (not a problem)
|
||||
var intResult = -1;
|
||||
int.TryParse(channelFileName.Substring(indexOfFirstChannelNumberCharacter, 3), out intResult);
|
||||
return intResult;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting channel number from channel file name", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* File.Reader.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
// *** see File.cs ***
|
||||
public abstract partial class File
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// A class for reading files of this type. There can be several reader types in a
|
||||
/// File-based class -- one for each "type" that the reader target is to be read/converted
|
||||
/// into.
|
||||
/// </summary>
|
||||
///
|
||||
/// <typeparam name="T">
|
||||
/// The file type that this reader belongs to.
|
||||
/// </typeparam>
|
||||
///
|
||||
public abstract class Reader<T> : Exceptional, IReader
|
||||
where T : File
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Constructor for the DTS.Export.File.Reader class. Note that access restrictions require that
|
||||
/// readers be constructed by the hosting DTS.Export.File class only. Use a File-level property or
|
||||
/// factory function to create/pass reader objects to outside parties.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="fileType">
|
||||
/// The associated DTS.Serialization.File-based class.
|
||||
/// </param>
|
||||
///
|
||||
protected Reader(T fileType)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileType = fileType;
|
||||
ChFileCompare = new ChannelFilenameComparer(fileType);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem constructing " + GetType().FullName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the <see cref="DTS.Serialization.File"/>-type associated with this reader.
|
||||
/// </summary>
|
||||
protected T FileType
|
||||
{
|
||||
get => _FileType.Value;
|
||||
private set => _FileType.Value = value;
|
||||
}
|
||||
private readonly Property<T> _FileType
|
||||
= new Property<T>(
|
||||
typeof(Reader<T>).Namespace + ".File.Reader.FileType",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Channel Filename comparer used by some file types.
|
||||
/// </summary>
|
||||
protected ChannelFilenameComparer ChFileCompare
|
||||
{
|
||||
get => _ChFileCompare.Value;
|
||||
private set => _ChFileCompare.Value = value;
|
||||
}
|
||||
private readonly Property<ChannelFilenameComparer> _ChFileCompare
|
||||
= new Property<ChannelFilenameComparer>(
|
||||
typeof(ChannelFilenameComparer).Namespace + ".File.Reader.ChFileCompare",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
protected class ChannelFilenameComparer : IComparer<string>
|
||||
{
|
||||
public File file { get; private set; }
|
||||
public int Compare(string left, string right)
|
||||
{
|
||||
return file.GetChannelNumberFromChannelFileName(left) != file.GetChannelNumberFromChannelFileName(right) ?
|
||||
file.GetChannelNumberFromChannelFileName(left) - file.GetChannelNumberFromChannelFileName(right) :
|
||||
string.Compare(left, right); // 19044 only dual-cal sensors will have repeat channel numbers (nonlinear then linear),
|
||||
// so do a straight compare to put nonlinear .chn before linear .lin.chn
|
||||
// if a non-SLICE or TDAS file type uses this, will be a regular string compare as GetChannelNumber... returns -1 always
|
||||
}
|
||||
public ChannelFilenameComparer(T fileType)
|
||||
{
|
||||
if (fileType is File f)
|
||||
{
|
||||
file = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace DTS.Serialization.DDAS
|
||||
{
|
||||
public class DDASChannel
|
||||
{
|
||||
private readonly DDASTest _parentTest;
|
||||
|
||||
private readonly Dictionary<DDASTest.Fields, string> _values = new Dictionary<DDASTest.Fields, string>();
|
||||
|
||||
public string GetValue(DDASTest.Fields field)
|
||||
{
|
||||
if (!_values.ContainsKey(field)) _values.Add(field, "#NOVALUE");
|
||||
return _values[field];
|
||||
}
|
||||
|
||||
public void SetValue(DDASTest.Fields field, string value)
|
||||
{
|
||||
_values[field] = value;
|
||||
switch (field)
|
||||
{
|
||||
case DDASTest.Fields.DataType:
|
||||
if (value == "Raw")
|
||||
{
|
||||
SetValue(DDASTest.Fields.EngineeringUnits, "ADC");
|
||||
SetValue(DDASTest.Fields.DigitalFilterType, "");
|
||||
var actualRange = _parentTest.ActualRangesADC[_channelIndex];
|
||||
|
||||
SetValue(DDASTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
|
||||
|
||||
FileName = Path.Combine(Path.Combine(_path, "DDAS"), "Raw");
|
||||
FileName = Path.Combine(FileName, $"{_parentTest.Test.Id}_{ChannelNumber}.DDAS");
|
||||
}
|
||||
else if (value == "Processed")
|
||||
{
|
||||
SetValue(DDASTest.Fields.EngineeringUnits, _engineeringUnits);
|
||||
SetValue(DDASTest.Fields.DigitalFilterType,
|
||||
$"CFC {_parentTest.DataUnfilteredEU[_channelIndex].FilterDescription}/{_parentTest.DataUnfilteredEU[_channelIndex].FilterFrequencyHz}");
|
||||
var actualRange = _parentTest.ActualRangesEUFiltered[_channelIndex];
|
||||
|
||||
SetValue(DDASTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
|
||||
FileName = Path.Combine(Path.Combine(_path, "DDAS"), "Processed");
|
||||
FileName = Path.Combine(FileName, $"{_parentTest.Test.Id}_{ChannelNumber}.DDAS");
|
||||
}
|
||||
else if (value == "Converted")
|
||||
{
|
||||
SetValue(DDASTest.Fields.EngineeringUnits, _engineeringUnits);
|
||||
SetValue(DDASTest.Fields.DigitalFilterType, "");
|
||||
var actualRange = _parentTest.ActualRangesEUUnfiltered[_channelIndex];
|
||||
|
||||
SetValue(DDASTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
|
||||
FileName = Path.Combine(Path.Combine(_path, "DDAS"), "Converted");
|
||||
FileName = Path.Combine(FileName, $"{_parentTest.Test.Id}_{ChannelNumber}.DDAS");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly string _engineeringUnits = "";
|
||||
|
||||
public string FileName { get; set; }
|
||||
|
||||
public void Serialize(TickEventHandler tickHandler)
|
||||
{
|
||||
if (!Directory.Exists(new FileInfo(FileName).Directory.FullName))
|
||||
Directory.CreateDirectory(new FileInfo(FileName).Directory.FullName);
|
||||
using (var bw = new BinaryWriter(System.IO.File.Open(FileName, FileMode.Create)))
|
||||
{
|
||||
// First write the "fileinfoblock"
|
||||
//typedef struct tagFILEINFOBLOCK
|
||||
//{
|
||||
// UINT Size; // Block Size (including nSize)
|
||||
// char FileTypeName[12]; // Software Type Name
|
||||
// char FileTypeVers[12]; // File Version Name
|
||||
// UINT FileTypeFlags; // File Type Flags
|
||||
// // - Hardware Type in upper 16 bits
|
||||
// // - File Type in lower 16 bits
|
||||
// char CreatedByName[16]; // Created by T-number
|
||||
// char UpdatedByName[16]; // Updated by T-number
|
||||
//}FILEINFOBLOCK;
|
||||
|
||||
bw.Write((uint)0x40);
|
||||
var fileType = "DDAS FlPt";
|
||||
bw.Write(Encoding.ASCII.GetBytes(fileType.PadRight(12, '\0')));
|
||||
var fileTypeVersion = "Ver 500";
|
||||
bw.Write(Encoding.ASCII.GetBytes(fileTypeVersion.PadRight(12, '\0')));
|
||||
bw.Write((uint)0);
|
||||
bw.Write(
|
||||
Encoding.ASCII.GetBytes(
|
||||
_parentTest.Test.Id.Substring(0, Math.Min(16, _parentTest.Test.Id.Length)).PadRight(16, '\0')));
|
||||
bw.Write(
|
||||
Encoding.ASCII.GetBytes(
|
||||
_parentTest.Test.Id.Substring(0, Math.Min(16, _parentTest.Test.Id.Length)).PadRight(16, '\0')));
|
||||
|
||||
// Now the test info
|
||||
// typedef struct tagTESTINFO
|
||||
// {
|
||||
// unsigned long Size; // Block Size (including Size)
|
||||
// unsigned long DeviceID; // DAQ device ID
|
||||
// long ChannelNo; // Channel number (1-32)
|
||||
// long SampleRate; // Samples per second
|
||||
// long TotalSamples; // Total samples in data record
|
||||
// long PreEventSamples; // Samples before event
|
||||
// short ChanNumInSys; // Channel Number (1-128) in system (many devices)
|
||||
// short NumPreCalPts; // Number of preCal points included with data
|
||||
// short NumPostCalPts; // Number of preCal points included with data
|
||||
// char TestCreation[TESTPATHSIZE]; // Test path and date
|
||||
// char TimeAxisTitle[32]; // Time axis title
|
||||
// byte SpareBytes[2]; // 2 bytes of spare (for 4 byte alignment)
|
||||
//
|
||||
// } TESTINFO;
|
||||
|
||||
var channel = _parentTest.Test.Channels[_channelIndex] as Test.Module.AnalogInputChannel;
|
||||
|
||||
bw.Write((uint)0xC0);
|
||||
bw.Write((uint)(1 + channel.ParentModule.Number));
|
||||
bw.Write((uint)(1 + _channelIndex));
|
||||
bw.Write((uint)channel.ParentModule.SampleRateHz);
|
||||
bw.Write((uint)channel.ParentModule.NumberOfSamples);
|
||||
bw.Write((uint)(channel.ParentModule.PreTriggerSeconds * channel.ParentModule.SampleRateHz));
|
||||
bw.Write((ushort)channel.Number);
|
||||
bw.Write((ushort)0);
|
||||
bw.Write((ushort)0);
|
||||
var testPathAndDate = FileName + " " + channel.ParentModule.ParentTest.InceptionDate.ToLongDateString();
|
||||
bw.Write(
|
||||
Encoding.ASCII.GetBytes(
|
||||
testPathAndDate.Substring(0, Math.Min(128, testPathAndDate.Length)).PadRight(128, '\0')));
|
||||
var TimeLabel = "Time (msec)";
|
||||
bw.Write(Encoding.ASCII.GetBytes(TimeLabel.PadRight(32, '\0')));
|
||||
bw.Write((byte)0x00);
|
||||
bw.Write((byte)0x00);
|
||||
|
||||
// Channel
|
||||
//typedef struct tagCHANNEL
|
||||
// {
|
||||
// short Size; // Size of this object
|
||||
// short Flags; // Channel Flags
|
||||
// char Name[64]; // Channel Name
|
||||
// char Sign[8]; // Sign +, -, or blank
|
||||
// char Axis[8]; // X,Y,Z,FX,MX,AX,...
|
||||
// float FilterFreq; // Channel Filter Class (in Hz)
|
||||
// float SetGain; // Gain setting (1 - n)
|
||||
// float ActGain; // Actual (measured?) gain setting.
|
||||
// float Rcal; // Shunt cal resistance
|
||||
// float Excitation; // Excitation Voltage (when programable)
|
||||
// byte byteSpares[4]; // Spare bytes (was Cal Date)
|
||||
// TRANSDUCER Transducer; // "Snapshot" of transducer values
|
||||
// } CHANNEL;
|
||||
|
||||
bw.Write((ushort)0x1001);
|
||||
bw.Write((ushort)0x0100);
|
||||
var description =
|
||||
Encoding.ASCII.GetBytes(
|
||||
channel.Description.Substring(0, Math.Min(64, channel.Description.Length)).PadRight(64, '\0'));
|
||||
bw.Write(description);
|
||||
|
||||
var polarity = "+";
|
||||
if (channel.IsInverted)
|
||||
polarity = "-";
|
||||
bw.Write(Encoding.ASCII.GetBytes(polarity.PadRight(8, (char)0x00)));
|
||||
|
||||
const string empty = "";
|
||||
bw.Write(Encoding.ASCII.GetBytes(empty.PadRight(8, (char)0x00)));
|
||||
|
||||
//ChannelFilter[] filterClasses = Enum.GetValues(typeof(ChannelFilter)).Cast<ChannelFilter>().ToArray();
|
||||
//float effectiveCFCFrequency = 0;
|
||||
//foreach(var f in filterClasses)
|
||||
//{
|
||||
// if((int)f == (int)_parentTest.DataUnfilteredEU[_channelIndex].FilterFrequencyHz)
|
||||
// {
|
||||
// var type = typeof(ChannelFilter);
|
||||
// var memInfo = type.GetMember(f.ToString());
|
||||
// var attributes = memInfo[0].GetCustomAttributes(typeof(CFCValueAttribute),
|
||||
// false);
|
||||
// effectiveCFCFrequency = (float)((CFCValueAttribute)attributes[0]).CFCValue;
|
||||
// }
|
||||
//}
|
||||
//if (0 == effectiveCFCFrequency) { effectiveCFCFrequency = (float)_parentTest.DataUnfilteredEU[_channelIndex].FilterFrequencyHz; }
|
||||
bw.Write(channel.ParentModule.AaFilterRateHz);
|
||||
|
||||
if (channel.ExpectedGainValid)
|
||||
bw.Write((float)channel.ExpectedGain);
|
||||
else
|
||||
bw.Write((float)(2500.0 / channel.DesiredRange));
|
||||
if (channel.MeasuredGainValid)
|
||||
bw.Write((float)channel.MeasuredGain);
|
||||
else if (channel.ExpectedGainValid)
|
||||
bw.Write((float)channel.ExpectedGain);
|
||||
else
|
||||
bw.Write((float)1.0);
|
||||
|
||||
bw.Write((float)channel.BridgeResistanceOhms);
|
||||
|
||||
if (channel.MeasuredExcitationVoltageValid)
|
||||
bw.Write((float)channel.MeasuredExcitationVoltage);
|
||||
else
|
||||
bw.Write((float)channel.ExcitationVoltage);
|
||||
bw.Write((byte)0x00);
|
||||
bw.Write((byte)0x00);
|
||||
bw.Write((byte)0x00);
|
||||
bw.Write((byte)0x00);
|
||||
|
||||
//typedef struct tagTRANSDUCER
|
||||
//{
|
||||
//char Mfr[32]; // Manufacturer
|
||||
//char Model[32]; // Model
|
||||
//char SN[32]; // Transducer Serial No
|
||||
//char Type[16]; // Transducer Type (load cell, accel, etc)
|
||||
//char EngUnits[16]; // Engineering Units (applies to Capacity,
|
||||
// // Sensitivity, and EUCalValue
|
||||
//float Capacity; // Max applied accel, force, displacement, etc
|
||||
//float XdcrRactive; // Bridge arm resistance of active half
|
||||
//float XdcrRinactive; // Bridge arm resistance of inactive half
|
||||
//float Sensitivity; // Sensitivity in V/EU
|
||||
//float EUCalValue; // Engineering unit cal value with Rcal
|
||||
//float Rcal; // Cal Resistor in Ohms
|
||||
//float Excitation; // Excitation Voltage (when specified)
|
||||
//long CalDate; // Cal date as time_t (seconds since 1970)
|
||||
// // (Good til 2038...shouldn't be an issue
|
||||
// // for this developer).
|
||||
// long Spare; // Spare long
|
||||
//} TRANSDUCER;
|
||||
|
||||
|
||||
var Manufacturer = "CHRYSLER";
|
||||
bw.Write(
|
||||
Encoding.ASCII.GetBytes(Manufacturer.Substring(0, Math.Min(32, Manufacturer.Length))
|
||||
.PadRight(32, '\0')));
|
||||
bw.Write(Encoding.ASCII.GetBytes(empty.PadRight(32, (char)0x00)));
|
||||
bw.Write(
|
||||
Encoding.ASCII.GetBytes(
|
||||
channel.SerialNumber.Substring(0, Math.Min(32, channel.SerialNumber.Length)).PadRight(32, '\0')));
|
||||
var SensorType = "UNKNOWN";
|
||||
bw.Write(
|
||||
Encoding.ASCII.GetBytes(SensorType.Substring(0, Math.Min(16, SensorType.Length)).PadRight(16, '\0')));
|
||||
bw.Write(
|
||||
Encoding.ASCII.GetBytes(
|
||||
channel.EngineeringUnits.Substring(0, Math.Min(16, channel.EngineeringUnits.Length))
|
||||
.PadRight(16, '\0')));
|
||||
|
||||
bw.Write((float)channel.DesiredRange);
|
||||
bw.Write((float)0);
|
||||
bw.Write((float)0);
|
||||
bw.Write((float)(1000 * channel.Sensitivity));
|
||||
bw.Write((float)0);
|
||||
bw.Write((float)channel.BridgeResistanceOhms);
|
||||
bw.Write((float)channel.ExcitationVoltage);
|
||||
|
||||
var Epoch = new DateTime(1971, 1, 1, 0, 0, 0);
|
||||
bw.Write((int)(channel.LastCalibrationDate - Epoch).TotalSeconds);
|
||||
var TransducerSpare = 0;
|
||||
bw.Write(TransducerSpare);
|
||||
|
||||
var Spare = new byte[0x0230 - 0x0210];
|
||||
bw.Write(Spare);
|
||||
|
||||
double percentageComplete = (float)_channelIndex / _parentTest.Channels.Length;
|
||||
var weight = 1D / _parentTest.Channels.Length;
|
||||
|
||||
for (var i = 0; i < _parentTest.DataUnfilteredEU[_channelIndex].Data.Length; i++)
|
||||
{
|
||||
bw.Write((float)_parentTest.DataUnfilteredEU[_channelIndex].Data[i]);
|
||||
if (0 == i % 1000)
|
||||
{
|
||||
var percent = 100D * (percentageComplete + i * weight / channel.ParentModule.NumberOfSamples);
|
||||
tickHandler(this, percent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly int _channelIndex;
|
||||
|
||||
public int ChannelNumber => 1 + _channelIndex;
|
||||
|
||||
private readonly string _path;
|
||||
|
||||
public DDASChannel(DDASTest parentTest, int channelIndex, string path)
|
||||
{
|
||||
_path = path;
|
||||
_parentTest = parentTest;
|
||||
_channelIndex = channelIndex;
|
||||
var aic = parentTest.Test.Channels[channelIndex] as Test.Module.AnalogInputChannel;
|
||||
|
||||
_engineeringUnits = aic.EngineeringUnits;
|
||||
|
||||
SetValue(DDASTest.Fields.EngineeringUnits, aic.EngineeringUnits);
|
||||
SetValue(DDASTest.Fields.SensorMakeModelSerial, aic.SerialNumber);
|
||||
SetValue(DDASTest.Fields.SensorLocation, aic.Description);
|
||||
|
||||
// double actualRange = _parentTest.ActualRangesEUFiltered[_channelIndex];
|
||||
double actualRange = 0;
|
||||
|
||||
SetValue(DDASTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
|
||||
//FB14282: Option to Flatten Export Folders
|
||||
FileName = path;
|
||||
|
||||
var channel = _parentTest.Test.Channels[_channelIndex] as Test.Module.AnalogInputChannel;
|
||||
|
||||
// We need a list of bases in order to properly formulate the file name.
|
||||
var moduleSerialNumbers = new List<string>();
|
||||
foreach (var currentChannel in _parentTest.Test.Channels)
|
||||
if (!moduleSerialNumbers.Contains(currentChannel.ParentModule.SerialNumber))
|
||||
moduleSerialNumbers.Add(currentChannel.ParentModule.SerialNumber);
|
||||
|
||||
var baseIndex = moduleSerialNumbers.IndexOf(channel.ParentModule.SerialNumber);
|
||||
// Another SLICE Specific short cut. To properly number the channels, we need to know how many channels per module. However, in the case
|
||||
// of SLICE where a bridge only has one channel _assigned_, channel.ParentModule.NumberOfChannels is 1. AFAIK, in this context, there is
|
||||
// no way other than assumption to know a bridge has three channels.
|
||||
var numberOfChannelsPerModule = (channel.ParentModule.NumberOfChannels + 2) / 3 * 3;
|
||||
FileName = Path.Combine(FileName, $"ch{1 + baseIndex:D2}{1 + channel.Number + numberOfChannelsPerModule * channel.ParentModule.Number:D2}.fpd");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
using DTS.Serialization.IRIGCH10.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10
|
||||
{
|
||||
/// <summary>
|
||||
/// this packet just points to specific time data packets as part of an indexing system
|
||||
/// </summary>
|
||||
public class RecorderIndexPacket : AbstractDataPacket, IDataPacket
|
||||
{
|
||||
//not confident on breaking out the individual properties of this dataword yet
|
||||
//(root index, file size, presence of data header, etc, so just use a
|
||||
//prefilled one for now ...
|
||||
private readonly byte [] ChannelSpecificDataWord = new byte[] {0x8D, 0x02, 0x00, 0xE0};
|
||||
private readonly byte [] RootPacketAddress = new byte [8];
|
||||
public void SetRootPacketAddress(long address)
|
||||
{
|
||||
var bits = BitConverter.GetBytes(address);
|
||||
Buffer.BlockCopy(bits, 0, RootPacketAddress, 0, bits.Length);
|
||||
}
|
||||
|
||||
private List<RecordingIndex> _indices = new List<RecordingIndex>();
|
||||
|
||||
public DateTime GetDateTime()
|
||||
{
|
||||
return _indices.First().GetDateTime();
|
||||
}
|
||||
public int NumberOfEntries => _indices.Count;
|
||||
public void AddRecordingIndex(RecordingIndex index)
|
||||
{
|
||||
_indices.Add(index);
|
||||
}
|
||||
|
||||
public RecorderIndexPacket()
|
||||
: base(DataFileDataTypes.ComputerGeneratedDataFormat3)
|
||||
{
|
||||
_CheckSum = new byte[4];
|
||||
}
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
//we just need to make sure data bytes is populated then we can let the base class do it's thing
|
||||
_dataBytes = new byte[_indices.Count * RecordingIndex.SIZE + RootPacketAddress.Length +
|
||||
ChannelSpecificDataWord.Length];
|
||||
Buffer.BlockCopy(ChannelSpecificDataWord, 0, _dataBytes, 0, ChannelSpecificDataWord.Length);
|
||||
Buffer.BlockCopy(RootPacketAddress, 0, _dataBytes, ChannelSpecificDataWord.Length, RootPacketAddress.Length);
|
||||
var offset = ChannelSpecificDataWord.Length + RootPacketAddress.Length;
|
||||
foreach (var index in _indices)
|
||||
{
|
||||
var bytes = index.GetBytes();
|
||||
Buffer.BlockCopy(bytes, 0, _dataBytes, offset, bytes.Length);
|
||||
offset += bytes.Length;
|
||||
}
|
||||
return base.GetBytes();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// here's a structure for the recording indicies in the recording index packet
|
||||
/// </summary>
|
||||
public class RecordingIndex
|
||||
{
|
||||
public const int SIZE = 8+8+2+1+1+8;
|
||||
private byte [] RTC = new byte [8];
|
||||
private byte [] TimeDate = new byte[8];
|
||||
private DateTime _dt;
|
||||
private readonly ushort ChannelId = ushort.MaxValue;
|
||||
private readonly byte DataType = 0x11;
|
||||
private readonly byte Reserved = 0x00;
|
||||
private byte[] DataPacketOffset = new byte[8];
|
||||
|
||||
private void SetRTC(long rtc)
|
||||
{
|
||||
var bits = BitConverter.GetBytes(rtc);
|
||||
Buffer.BlockCopy(bits, 0, RTC, 0, bits.Length);
|
||||
}
|
||||
|
||||
private void SetDataPacketOffset(long offset)
|
||||
{
|
||||
var bits = BitConverter.GetBytes(offset);
|
||||
Buffer.BlockCopy(bits, 0, DataPacketOffset, 0, bits.Length);
|
||||
}
|
||||
public DateTime GetDateTime(){ return _dt; }
|
||||
private void SetDateTime(DateTime dt)
|
||||
{
|
||||
_dt = dt;
|
||||
TimeDate[0] = Utils.Utils.GetBCDBytes(dt.Millisecond/10)[0];
|
||||
TimeDate[1] = Utils.Utils.GetBCDBytes(dt.Second)[0];
|
||||
TimeDate[2] = Utils.Utils.GetBCDBytes(dt.Minute)[0];
|
||||
TimeDate[3] = Utils.Utils.GetBCDBytes(dt.Hour)[0];
|
||||
TimeDate[4] = Utils.Utils.GetBCDBytes(dt.Day)[0];
|
||||
TimeDate[5] = Utils.Utils.GetBCDBytes(dt.Month)[0];
|
||||
TimeDate[6] = Utils.Utils.GetBCDBytes(dt.Year)[0];
|
||||
TimeDate[7] = Utils.Utils.GetBCDBytes(dt.Year)[1];
|
||||
}
|
||||
|
||||
public RecordingIndex(long rtc, long offset, DateTime dt)
|
||||
{
|
||||
SetDataPacketOffset(offset);
|
||||
SetRTC(rtc);
|
||||
SetDateTime(dt);
|
||||
}
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
var data = new byte[8 + 8 + 2 + 1 + 1 + 8];
|
||||
var curOffset = 0;
|
||||
Buffer.BlockCopy(RTC, 0, data, 0, RTC.Length);
|
||||
curOffset += RTC.Length;
|
||||
Buffer.BlockCopy(TimeDate, 0, data, curOffset, TimeDate.Length);
|
||||
curOffset += TimeDate.Length;
|
||||
var bytes = BitConverter.GetBytes(ChannelId);
|
||||
Buffer.BlockCopy(bytes, 0, data, curOffset, 2);
|
||||
curOffset += 2;
|
||||
data[curOffset++] = DataType;
|
||||
data[curOffset++] = Reserved;
|
||||
Buffer.BlockCopy(DataPacketOffset, 0, data, curOffset, DataPacketOffset.Length);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* DTS.Slice.Control.Event.ChannelAccessor.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using DTS.Common.Utilities;
|
||||
|
||||
namespace DTS.Slice.Control
|
||||
{
|
||||
// *** see DTS.Slice.Control.Event.cs ***
|
||||
public partial class Event
|
||||
{
|
||||
/// <summary>
|
||||
/// A component object of the Event.DasModuleChannelAccessor.
|
||||
/// </summary>
|
||||
public class ChannelAccessor : ExceptionalDictionary<int, Module.Channel> // xxx change this int to DAS.(Module?).Channel.Id?
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Slice.Control.Event.ChannelAccessor class.
|
||||
/// </summary>
|
||||
public ChannelAccessor() { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10.Packets
|
||||
{
|
||||
/// <summary>
|
||||
/// this class helps encapsulate a secondary time format header, but it's really
|
||||
/// only designed for one type of format currently
|
||||
/// </summary>
|
||||
public class SecondaryTimeFormatHeader : ISecondaryTimeFormatHeader
|
||||
{
|
||||
private byte[] _bytes = new byte[SECONDARY_TIME_HEADER_LENGTH];
|
||||
public int NanoSeconds { get; }
|
||||
public int Seconds { get; }
|
||||
public ushort Reserved { get; }
|
||||
public ushort CheckSum { get; }
|
||||
|
||||
public DateTime LocalTime
|
||||
{
|
||||
get => (new DateTime(1970, 1, 1)).AddSeconds(Seconds).AddTicks(NanoSeconds / 100).ToLocalTime();
|
||||
}
|
||||
public SecondaryTimeFormatHeader(byte[] input)
|
||||
{
|
||||
Array.Copy(input, 0, _bytes, 0, SECONDARY_TIME_HEADER_LENGTH);
|
||||
NanoSeconds = BitConverter.ToInt32(_bytes, 0);
|
||||
Seconds = BitConverter.ToInt32(_bytes, 4);
|
||||
Reserved = BitConverter.ToUInt16(_bytes, 8);
|
||||
CheckSum = BitConverter.ToUInt16(_bytes, 10);
|
||||
byte[] bytesToCompute;
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write(BitConverter.GetBytes(NanoSeconds));
|
||||
bw.Write(BitConverter.GetBytes(Seconds));
|
||||
bw.Write(Reserved);
|
||||
}
|
||||
bytesToCompute = ms.ToArray();
|
||||
}
|
||||
var computedChecksum = Utils.Utils.GetCheckSum8(bytesToCompute);
|
||||
if (computedChecksum != CheckSum)
|
||||
{
|
||||
System.Diagnostics.Trace.WriteLine("Secondary time header CRC does not match expectations");
|
||||
}
|
||||
}
|
||||
public static byte[] GetBytes(int nanoseconds, int seconds)
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write(BitConverter.GetBytes(nanoseconds));
|
||||
bw.Write(BitConverter.GetBytes(seconds));
|
||||
bw.Write((ushort)0);
|
||||
|
||||
bw.Write(Utils.Utils.GetCheckSum8(ms.ToArray()));
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
public const int SECONDARY_TIME_HEADER_LENGTH = 12;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* DTS.Slice.Control.DAS.Channel.IFilterable.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DTS.Slice.Control.DAS.Channel
|
||||
{
|
||||
/// <summary>
|
||||
/// Methodical definition of a filterable slice control event module channle.
|
||||
/// </summary>
|
||||
public interface IFilterable
|
||||
//: DTS.Common.DAS.ConceptsIFilterable<Event.Module.Channel, short[]>
|
||||
{
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="bool"/> switch to (de)activate filter caching.
|
||||
/// </summary>
|
||||
bool UseFilterCaching
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the list of available filters for this object.
|
||||
/// </summary>
|
||||
List<IFilter> AvailableFilters
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The currently applied filter.
|
||||
/// </summary>
|
||||
IFilter CurrentFilter
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the specified filtering for this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="filter">
|
||||
/// The <see cref="DTS.Slice.Control.CAS.Channel.IFilter"/> to be applied to this object.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="displayUnits">
|
||||
/// Choose the output <see cref="DTS.Slice.Control.DAS.Channel.Data.DisplayUnits"/>.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// An array of <see cref="double"/> data reflecting the specified parameters.
|
||||
/// </returns>
|
||||
///
|
||||
double[] GetDataFilteredBy(IFilter filter, Event.Module.Channel.DataDisplayUnits displayUnits);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DTS.Serialization.TDM
|
||||
{
|
||||
public partial class TDMParameterDlg : Form
|
||||
{
|
||||
private readonly double _min;
|
||||
private readonly double _max;
|
||||
protected TDMParameterDlg()
|
||||
{
|
||||
}
|
||||
public TDMParameterDlg(string testName, double testStart, double testEnd)
|
||||
{
|
||||
InitializeComponent();
|
||||
DialogResult = DialogResult.Cancel;
|
||||
var di = new System.IO.DirectoryInfo(Properties.Settings1.Default.TDMFolder);
|
||||
if (!di.Exists)
|
||||
{
|
||||
di.Create();
|
||||
}
|
||||
var path = System.IO.Path.Combine(di.FullName, string.Format("{0}.csv", testName));
|
||||
tbLocation.Text = path;
|
||||
//tbStart.Text = (testStart*1000D).ToString();
|
||||
//tbStop.Text = (testEnd*1000D).ToString();
|
||||
var start = testStart * 1000D;
|
||||
var stop = testEnd * 1000D;
|
||||
_min = start;
|
||||
_max = stop;
|
||||
if (Properties.Settings1.Default.DefaultStart < start) { tbStart.Text = start.ToString(); }
|
||||
else { tbStart.Text = Properties.Settings1.Default.DefaultStart.ToString(); }
|
||||
|
||||
if (Properties.Settings1.Default.DefaultStop > stop) { tbStop.Text = stop.ToString(); }
|
||||
else { tbStop.Text = Properties.Settings1.Default.DefaultStop.ToString(); }
|
||||
}
|
||||
|
||||
private void btnBrowse_Click(object sender, EventArgs e)
|
||||
{
|
||||
using (var dlg = new SaveFileDialog())
|
||||
{
|
||||
dlg.Filter = "TDM CSV (*.csv)|*.csv";
|
||||
dlg.FilterIndex = 0;
|
||||
dlg.RestoreDirectory = true;
|
||||
dlg.OverwritePrompt = true;
|
||||
|
||||
var fi = new System.IO.FileInfo(tbLocation.Text);
|
||||
dlg.InitialDirectory = fi.Directory.FullName;
|
||||
dlg.FileName = tbLocation.Text;
|
||||
|
||||
if (DialogResult.OK == dlg.ShowDialog(this))
|
||||
{
|
||||
tbLocation.Text = dlg.FileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void btnOK_Click(object sender, EventArgs e)
|
||||
{
|
||||
errorProvider1.SetError(tbStart, null);
|
||||
errorProvider1.SetError(tbStop, null);
|
||||
var fi = new System.IO.FileInfo(tbLocation.Text);
|
||||
Properties.Settings1.Default.TDMFolder = fi.Directory.FullName;
|
||||
|
||||
var dstart = double.MinValue;
|
||||
if (double.TryParse(tbStart.Text, out dstart))
|
||||
{
|
||||
Properties.Settings1.Default.DefaultStart = dstart;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorProvider1.SetError(tbStart, "Could not parse");
|
||||
return;
|
||||
}
|
||||
var dend = double.MinValue;
|
||||
if (double.TryParse(tbStop.Text, out dend))
|
||||
{
|
||||
Properties.Settings1.Default.DefaultStop = dend;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorProvider1.SetError(tbStop, "Could not parse");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dend < dstart) { errorProvider1.SetError(tbStart, "Start must be before end"); return; }
|
||||
if (dend > _max) { errorProvider1.SetError(tbStop, string.Format("exceeds max data in test ({0} ms)", _max)); return; }
|
||||
if (dstart < _min) { errorProvider1.SetError(tbStart, string.Format("test does not contain requested region, min start is ({0} ms)", _min)); return; }
|
||||
|
||||
Properties.Settings1.Default.Save();
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
|
||||
public string FileName => tbLocation.Text;
|
||||
|
||||
public double Start => double.Parse(tbStart.Text) / 1000D;
|
||||
public double Stop => double.Parse(tbStop.Text) / 1000D;
|
||||
|
||||
private void btnCancel_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
using DTS.Serialization.IRIGCH10.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10
|
||||
{
|
||||
/// <summary>
|
||||
/// this class handles the root recorder index packet,
|
||||
/// it points to recorder index packets, it's the last packet in a ch10 file
|
||||
/// (but can be broken over multiple packets)
|
||||
/// </summary>
|
||||
public class RootRecorderIndexPacket : AbstractDataPacket, IDataPacket
|
||||
{
|
||||
//not confident on breaking out the individual properties of this dataword yet
|
||||
//(root index, file size, presence of data header, etc, so just use a
|
||||
//prefilled one for now ...
|
||||
private readonly byte [] ChannelSpecificDataWord = new byte[] {0x8D, 0x00, 0x00, 0x60};
|
||||
private long _rootPacketAddressLong;
|
||||
private readonly byte [] RootPacketAddress = new byte [8];
|
||||
public void SetRootPacketAddress(long address)
|
||||
{
|
||||
_rootPacketAddressLong = address;
|
||||
var bits = BitConverter.GetBytes(address);
|
||||
Buffer.BlockCopy(bits, 0, RootPacketAddress, 0, bits.Length);
|
||||
}
|
||||
|
||||
private List<RecordingIndexIndex> _indices = new List<RecordingIndexIndex>();
|
||||
|
||||
public void AddRecordingIndex(RecordingIndexIndex index)
|
||||
{
|
||||
_indices.Add(index);
|
||||
}
|
||||
private readonly DateTime _dt;
|
||||
public RootRecorderIndexPacket(DateTime dt)
|
||||
: base(DataFileDataTypes.ComputerGeneratedDataFormat3)
|
||||
{
|
||||
_dt = dt;
|
||||
_CheckSum = new byte[4];
|
||||
}
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
//the last index should apparently point back to this entry...
|
||||
_indices.Add(new RecordingIndexIndex(GetRTC(), _rootPacketAddressLong, _dt));
|
||||
//we just need to make sure data bytes is populated then we can let the base class do it's thing
|
||||
_dataBytes = new byte[_indices.Count * RecordingIndexIndex.SIZE + RootPacketAddress.Length +
|
||||
ChannelSpecificDataWord.Length];
|
||||
|
||||
Buffer.BlockCopy(ChannelSpecificDataWord, 0, _dataBytes, 0, ChannelSpecificDataWord.Length);
|
||||
Buffer.BlockCopy(RootPacketAddress, 0, _dataBytes, ChannelSpecificDataWord.Length, RootPacketAddress.Length);
|
||||
var offset = ChannelSpecificDataWord.Length + RootPacketAddress.Length;
|
||||
foreach (var index in _indices)
|
||||
{
|
||||
var bytes = index.GetBytes();
|
||||
Buffer.BlockCopy(bytes, 0, _dataBytes, offset, bytes.Length);
|
||||
offset += bytes.Length;
|
||||
}
|
||||
return base.GetBytes();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// here is a root recording index entry, it points at other recording indicies
|
||||
/// </summary>
|
||||
public class RecordingIndexIndex
|
||||
{
|
||||
public const int SIZE = 8+8+8;
|
||||
private byte [] RTC = new byte [8];
|
||||
private byte [] TimeDate = new byte[8];
|
||||
private byte[] DataPacketOffset = new byte[8];
|
||||
|
||||
private void SetRTC(long rtc)
|
||||
{
|
||||
var bits = BitConverter.GetBytes(rtc);
|
||||
Buffer.BlockCopy(bits, 0, RTC, 0, bits.Length);
|
||||
}
|
||||
|
||||
private void SetDataPacketOffset(long offset)
|
||||
{
|
||||
var bits = BitConverter.GetBytes(offset);
|
||||
Buffer.BlockCopy(bits, 0, DataPacketOffset, 0, bits.Length);
|
||||
}
|
||||
|
||||
private void SetDateTime(DateTime dt)
|
||||
{
|
||||
TimeDate[0] = Utils.Utils.GetBCDBytes(dt.Millisecond/10)[0];
|
||||
TimeDate[1] = Utils.Utils.GetBCDBytes(dt.Second)[0];
|
||||
TimeDate[2] = Utils.Utils.GetBCDBytes(dt.Minute)[0];
|
||||
TimeDate[3] = Utils.Utils.GetBCDBytes(dt.Hour)[0];
|
||||
TimeDate[4] = Utils.Utils.GetBCDBytes(dt.Day)[0];
|
||||
TimeDate[5] = Utils.Utils.GetBCDBytes(dt.Month)[0];
|
||||
TimeDate[6] = Utils.Utils.GetBCDBytes(dt.Year)[0];
|
||||
TimeDate[7] = Utils.Utils.GetBCDBytes(dt.Year)[1];
|
||||
}
|
||||
|
||||
public RecordingIndexIndex(long rtc, long offset, DateTime dt)
|
||||
{
|
||||
SetDataPacketOffset(offset);
|
||||
SetRTC(rtc);
|
||||
SetDateTime(dt);
|
||||
}
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
var data = new byte[SIZE];
|
||||
var curOffset = 0;
|
||||
Buffer.BlockCopy(RTC, 0, data, 0, RTC.Length);
|
||||
curOffset += RTC.Length;
|
||||
Buffer.BlockCopy(TimeDate, 0, data, curOffset, TimeDate.Length);
|
||||
curOffset += TimeDate.Length;
|
||||
Buffer.BlockCopy(DataPacketOffset, 0, data, curOffset, DataPacketOffset.Length);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10.Packets
|
||||
{
|
||||
public interface ISecondaryTimeFormatHeader
|
||||
{
|
||||
int NanoSeconds { get; }
|
||||
int Seconds { get; }
|
||||
ushort Reserved { get; }
|
||||
ushort CheckSum { get; }
|
||||
DateTime LocalTime { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DTS.Serialization.SoMat
|
||||
{
|
||||
public class SoMatTestHeader
|
||||
{
|
||||
public string TestTitle { get; set; } = "";
|
||||
public string Operator { get; set; } = "";
|
||||
public string RunDateTime { get; set; } = "";
|
||||
|
||||
private readonly List<SoMatChannel> _channels = new List<SoMatChannel>();
|
||||
public int NumLogChannels => _channels.Count;
|
||||
public SoMatChannel[] Channels => _channels.ToArray();
|
||||
public int NumDataModes { get; set; } = 1;
|
||||
|
||||
public void Serialize(System.IO.StreamWriter sw)
|
||||
{
|
||||
sw.Write("DM_TestTitle=");
|
||||
sw.WriteLine(TestTitle);
|
||||
|
||||
sw.Write("DM_Operator=");
|
||||
sw.WriteLine(Operator);
|
||||
|
||||
sw.Write("RUNDATETIME=");
|
||||
sw.WriteLine(RunDateTime);
|
||||
|
||||
sw.Write("DM_NumLogChans=");
|
||||
sw.WriteLine(NumLogChannels.ToString());
|
||||
|
||||
sw.Write("DM_NumDataModes=");
|
||||
sw.WriteLine(NumDataModes.ToString());
|
||||
|
||||
sw.WriteLine();
|
||||
}
|
||||
public SoMatTestHeader(Test test, FilteredData[] filteredData)
|
||||
{
|
||||
TestTitle = test.Id;
|
||||
RunDateTime = string.Format("{0} {1}", test.InceptionDate.ToShortDateString(), test.InceptionDate.ToShortTimeString());
|
||||
try
|
||||
{
|
||||
Operator = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
|
||||
}
|
||||
catch (System.Exception) { }
|
||||
|
||||
for (var i = 0; i < test.Channels.Count && i < filteredData.Length; i++)
|
||||
{
|
||||
var moduleArrayIndex = 0;
|
||||
for (moduleArrayIndex = 0; moduleArrayIndex < test.Modules.Count; moduleArrayIndex++)
|
||||
{
|
||||
if (test.Channels[i].ParentModule.SerialNumber ==
|
||||
test.Modules[moduleArrayIndex].SerialNumber) { break; }
|
||||
}
|
||||
_channels.Add(new SoMatChannel(test.Channels[i], 1 + i, filteredData[i], moduleArrayIndex, 3, test.InceptionDate));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,906 @@
|
||||
/*
|
||||
* Diadem.File.Writer.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.ISO;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
|
||||
namespace DTS.Serialization.RDF
|
||||
{
|
||||
// *** see Diadem.File.cs ***
|
||||
public partial class File
|
||||
{
|
||||
///
|
||||
/// <summary>
|
||||
/// Utility object for serializing <see cref="DTS.Serialization.Test"/>s to disk
|
||||
/// in the Diadem
|
||||
/// </summary>
|
||||
///
|
||||
public class Writer : Writer<File>, IWriter<Test>
|
||||
{
|
||||
public File WriterParent { get; set; }
|
||||
|
||||
public TestPlan TestPlan { get; set; }
|
||||
public string ExtensionPrefix { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Initialize an instance of the Diadem.File.Writer class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="fileType">
|
||||
/// The associated <see cref="DTS.Serialization.Diadem.File"/> object.
|
||||
/// </param>
|
||||
/// <param name="encoding"></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="id"></param>
|
||||
/// <param name="test">
|
||||
/// The <see cref="DTS.Serialization.Test"/> to be written out.
|
||||
/// </param>
|
||||
/// <param name="bFiltering"></param>
|
||||
/// <param name="includeGroupNameInISOExport"></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="pathname"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="dataFolder"></param>
|
||||
/// <param name="test"></param>
|
||||
/// <param name="bFiltering"></param>
|
||||
/// <param name="includeGroupNameInISOExport"></param>
|
||||
/// <param name="fd"></param>
|
||||
/// <param name="tmChannel"></param>
|
||||
/// <param name="channelNumber"></param>
|
||||
/// <param name="beginEventHandler"></param>
|
||||
/// <param name="cancelEventHandler"></param>
|
||||
/// <param name="endEventHandler"></param>
|
||||
/// <param name="tickEventHandler"></param>
|
||||
/// <param name="errorEventHandler"></param>
|
||||
/// <param name="cancelRequested"></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 idBad = !id.ToLower().Contains(SUFFIX_CHECKOUT.ToLower()) &&
|
||||
!id.ToLower().Contains(SUFFIX_RUNTEST.ToLower());
|
||||
if (null != test && !string.IsNullOrEmpty(test.Id) && idBad)
|
||||
{
|
||||
//don't use that id, use the one in test
|
||||
//http://manuscript.dts.local/f/cases/36769/RDF-Export-is-not-named-correctly
|
||||
id = test.Id;
|
||||
}
|
||||
//FB8419 - RDF files must contain an 8char test name without "runtest" or "checkout"
|
||||
if (id.ToLower().EndsWith(SUFFIX_CHECKOUT.ToLower()))
|
||||
{
|
||||
id = id.Substring(0, id.Length - SUFFIX_CHECKOUT.Length);
|
||||
}
|
||||
else if (id.ToLower().EndsWith(SUFFIX_RUNTEST.ToLower()))
|
||||
{
|
||||
id = id.Substring(0, id.Length - SUFFIX_RUNTEST.Length);
|
||||
}
|
||||
//id = id.PadRight(MAX_TEST_NAME_LENGTH); //FB8418 - JCL file names must be 8 characters long. No longer/shorter
|
||||
|
||||
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);
|
||||
|
||||
WriteTestInfo(fileWriter, test, id, tickEventHandler, dataFolder);
|
||||
WriteChannelInfo(fileWriter, test, id, tickEventHandler, dataFolder, cancelRequested,
|
||||
pathname, TestPlan);
|
||||
|
||||
tickEventHandler?.Invoke(this, 100.0);
|
||||
endEventHandler?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
exception = new Exception("encountered problem writing RDF test files", ex);
|
||||
APILogger.Log("encountered problem writing RDF test files", ex);
|
||||
}
|
||||
if (null != errorEventHandler && null != exception && null != endEventHandler)
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
public bool UseIsoCodeForDiadem200 { get; set; }
|
||||
public bool UseZeroForUnfiltered { get; set; }
|
||||
public bool FilteredExport { get; set; }
|
||||
|
||||
// ReSharper disable once UnusedParameter.Local
|
||||
private void CreateLinearizedData(Test.Module.Channel currentChannel, string dataFolder, long startSample, long endSample)
|
||||
{
|
||||
var sChnName = currentChannel.PersistentChannelInfo.Filename;
|
||||
|
||||
var sNewFileName = sChnName.Replace(".chn", ".lin");
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
var data = GetEUData(currentChannel);
|
||||
if (endSample >= data.Length)
|
||||
{
|
||||
endSample = data.Length - 1;
|
||||
}
|
||||
for (var i = startSample; i <= endSample; i++)
|
||||
{
|
||||
sb.Append(data[i].ToString(CultureInfo.InvariantCulture));
|
||||
if (i < endSample)
|
||||
{
|
||||
sb.Append(CultureInfo.InvariantCulture.TextInfo.ListSeparator);
|
||||
}
|
||||
sb.AppendLine();
|
||||
}
|
||||
System.IO.File.WriteAllText(sNewFileName, sb.ToString(), Encoding.ASCII);
|
||||
}
|
||||
|
||||
//this commented out function was used during testing for 3D ir-tracc, it creates CSV files for all channels in the test with
|
||||
//several key values, which makes it useful for debugging data set issues.
|
||||
/*private void Create3DIRTraccDataCSV(Test.Module.Channel CurrentChannel,
|
||||
string dataFolder,
|
||||
DataScaler scaler)
|
||||
{
|
||||
// renable code to produce a nice CSV with ADC and the variables needed to calculate EU
|
||||
string sChnName = CurrentChannel.PersistentChannelInfo.Filename;
|
||||
string newFileName2 = sChnName.Replace(".chn", ".csv").Replace(".cchn", ".csv");
|
||||
|
||||
if (System.IO.File.Exists(newFileName2))
|
||||
{
|
||||
System.IO.File.Delete(newFileName2);
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendFormat("{0},{1}", CurrentChannel.ChannelDescriptionString, CurrentChannel.ChannelName2);
|
||||
|
||||
sb.AppendLine();
|
||||
sb.AppendFormat("Sensitivity,Excitation,LinearizationExponent,ZeroPosition,Intercept");
|
||||
sb.AppendLine();
|
||||
if (CurrentChannel is Test.Module.AnalogInputChannel)
|
||||
{
|
||||
var aic = CurrentChannel as Test.Module.AnalogInputChannel;
|
||||
if (aic.LinearizationFormula.IsValid() &&
|
||||
aic.LinearizationFormula.NonLinearStyle == Common.DAS.Concepts.NonLinearStyles.IRTraccCalFactor)
|
||||
{
|
||||
sb.Append(aic.LinearizationFormula.CalibrationFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(aic.Sensitivity);
|
||||
}
|
||||
sb.Append(",");
|
||||
|
||||
sb.Append(aic.FactoryExcitationVoltage);
|
||||
sb.Append(",");
|
||||
if (aic.LinearizationFormula.IsValid())
|
||||
{
|
||||
sb.Append(aic.LinearizationFormula.LinearizationExponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append("0");
|
||||
}
|
||||
sb.Append(",");
|
||||
|
||||
sb.Append(aic.ZeroPoint);
|
||||
sb.Append(",");
|
||||
|
||||
if (aic.LinearizationFormula.IsValid() &&
|
||||
aic.LinearizationFormula.NonLinearStyle == Common.DAS.Concepts.NonLinearStyles.IRTraccCalFactor)
|
||||
{
|
||||
sb.Append(aic.LinearizationFormula.Intercept);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append("0");
|
||||
}
|
||||
|
||||
sb.AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
sb.AppendLine("ADC, mV, EU");
|
||||
|
||||
for (int i = 0; i < CurrentChannel.PersistentChannelInfo.Data.Length; i++)
|
||||
{
|
||||
if (0 == i % 10)
|
||||
{
|
||||
sb.AppendFormat("{0},{1},{2}", CurrentChannel.PersistentChannelInfo.Data[i],
|
||||
scaler.GetMv(CurrentChannel.PersistentChannelInfo.Data[i]),
|
||||
scaler.GetEU(CurrentChannel.PersistentChannelInfo.Data[i]));
|
||||
sb.AppendLine();
|
||||
}
|
||||
}
|
||||
System.IO.File.AppendAllText(newFileName2, sb.ToString());
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// this is a function to output CSV data for non linear channels
|
||||
/// it's used for debugging non linear output.
|
||||
/// </summary>
|
||||
/// <param name="currentChannel"></param>
|
||||
/// <param name="dataFolder"></param>
|
||||
/// <param name="scaler"></param>
|
||||
// ReSharper disable once UnusedParameter.Local
|
||||
private static void CreateLinearizedDataCSV(Test.Module.Channel currentChannel, string dataFolder,
|
||||
DataScaler scaler, long startSample, long endSample)
|
||||
{
|
||||
try
|
||||
{
|
||||
/* re-enable code to produce a nice CSV with ADC and the variables needed to calculate EU*/
|
||||
var sChnName = currentChannel.PersistentChannelInfo.Filename;
|
||||
var newFileName2 = sChnName.Replace(".chn", ".csv");
|
||||
|
||||
if (System.IO.File.Exists(newFileName2))
|
||||
{
|
||||
System.IO.File.Delete(newFileName2);
|
||||
}
|
||||
//for comparison reasons it can be useful to normalize your mV using a specific target
|
||||
//this code arranges for the first mV to match your target.
|
||||
var oldzeroMvinADC = scaler.ZeroMvInADC;
|
||||
var oldmV = scaler.GetMv(currentChannel.PersistentChannelInfo.Data[0]);
|
||||
var deltamV = 61.5D - oldmV;
|
||||
var deltamVinADC = deltamV / scaler.GetScaleFactorMv();
|
||||
var newzeromvinADC = scaler.ZeroMvInADC - deltamVinADC;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine(
|
||||
"ScaleFactorMV,Excitation,ZeromVInADCOriginal,ZeromVInADCAdjusted,DeltaInADC,DeltaInmV");
|
||||
sb.AppendFormat("{0},{1},{2},{3},{4},{5}", scaler.GetAdcToMvScalingFactor(),
|
||||
scaler.FactoryExcitationVoltage,
|
||||
oldzeroMvinADC,
|
||||
newzeromvinADC,
|
||||
deltamVinADC,
|
||||
deltamV);
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("ADC, mV, EU");
|
||||
|
||||
if (endSample >= currentChannel.PersistentChannelInfo.Data.Length)
|
||||
{
|
||||
endSample = currentChannel.PersistentChannelInfo.Data.Length - 1;
|
||||
}
|
||||
for (var i = startSample; i <= endSample; i++)
|
||||
{
|
||||
if (0 != i % 10) continue;
|
||||
sb.AppendFormat("{0},{1},{2}", currentChannel.PersistentChannelInfo.Data[i],
|
||||
scaler.GetMv(currentChannel.PersistentChannelInfo.Data[i]),
|
||||
scaler.GetEU(currentChannel.PersistentChannelInfo.Data[i]));
|
||||
sb.AppendLine();
|
||||
}
|
||||
System.IO.File.AppendAllText(newFileName2, sb.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// ReSharper disable once UnusedParameter.Local
|
||||
private void CreateDigitizedData(Test.Module.Channel currentChannel, string dataFolder, long startSample,
|
||||
long endSample)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sChnName = currentChannel.PersistentChannelInfo.Filename;
|
||||
|
||||
var sNewFileName = sChnName.Replace(".chn", ".dig");
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
var data = GetEUData(currentChannel);
|
||||
if (endSample >= data.Length)
|
||||
{
|
||||
endSample = data.Length - 1;
|
||||
}
|
||||
|
||||
for (var i = startSample; i <= endSample; i++)
|
||||
{
|
||||
sb.Append(data[i].ToString(CultureInfo.InvariantCulture));
|
||||
if (i < endSample - 1L)
|
||||
{
|
||||
sb.Append(CultureInfo.InvariantCulture.TextInfo.ListSeparator);
|
||||
}
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
System.IO.File.WriteAllText(sNewFileName, sb.ToString(), Encoding.ASCII);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private double[] GetEUData(Test.Module.Channel channel)
|
||||
{
|
||||
return WriterParent.GetEUData(channel.ChannelId).Data;
|
||||
}
|
||||
|
||||
|
||||
protected void WriteTestInfo(
|
||||
BinaryWriter fileWriter,
|
||||
Test test,
|
||||
string testId,
|
||||
TickEventHandler tickEventHandler,
|
||||
string dataFolder)
|
||||
{
|
||||
var emptyBuffer = Enumerable.Repeat(' ', 80).ToArray();
|
||||
|
||||
fileWriter.Write(
|
||||
testId.PadRight(MAX_TEST_NAME_LENGTH, ' ').Substring(0, MAX_TEST_NAME_LENGTH).ToCharArray());
|
||||
fileWriter.Write("1".PadLeft(3, ' ').ToCharArray()); // Number of files
|
||||
fileWriter.Write(" 1".ToCharArray()); // File number always 1
|
||||
fileWriter.Write(test.Channels.Count.ToString().PadLeft(3, ' ').ToCharArray()); // Number of channels
|
||||
fileWriter.Write(test.InceptionDate.Month.ToString("00").ToCharArray());
|
||||
fileWriter.Write(test.InceptionDate.Day.ToString("00").ToCharArray());
|
||||
fileWriter.Write(test.InceptionDate.Year.ToString().Substring(2, 2).ToCharArray());
|
||||
fileWriter.Write(test.InceptionDate.Hour.ToString("00").ToCharArray());
|
||||
fileWriter.Write(test.InceptionDate.Minute.ToString("00").ToCharArray());
|
||||
fileWriter.Write(emptyBuffer, 0, 53); // Complete the 80 byte record
|
||||
}
|
||||
|
||||
private static int DisplayOrderComparer(object x, object y)
|
||||
{
|
||||
var channelX = (Test.Module.Channel)x;
|
||||
var channelY = (Test.Module.Channel)y;
|
||||
|
||||
if (channelX.AbsoluteDisplayOrder > channelY.AbsoluteDisplayOrder)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (channelX.AbsoluteDisplayOrder < channelY.AbsoluteDisplayOrder)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return channelX.ToString().CompareTo(channelY.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns a gm formatted 5 character string for a rack serial number
|
||||
/// for now it takes the last 5 characters and pads as necessary
|
||||
///
|
||||
/// 2019-09-16
|
||||
/// 14823 DP vs TDC TDAS PRO Rack Naming Consistency
|
||||
/// modified to accept baseserialnumber as well as function was outputting module serial numbers with TDAS
|
||||
/// </summary>
|
||||
/// <param name="serialNumber"></param>
|
||||
/// <param name="baseSerialNumber"></param>
|
||||
/// <returns></returns>
|
||||
private static string GetRackSerialNumber(string serialNumber, string baseSerialNumber)
|
||||
{
|
||||
var sn = string.IsNullOrWhiteSpace(baseSerialNumber) ? serialNumber : baseSerialNumber;
|
||||
if (string.IsNullOrWhiteSpace(sn))
|
||||
{
|
||||
return "EMPTY";
|
||||
}
|
||||
return sn.Length >= 4 ? sn.Substring(sn.Length - 4, 4).PadLeft(5) : sn.PadLeft(5, ' ');
|
||||
}
|
||||
|
||||
private static readonly double MidpointDeflection = Math.Floor(0.7D * Common.Constants.ADC_MIDPOINT);
|
||||
|
||||
private static bool IsSlice(string sn)
|
||||
{
|
||||
return sn.StartsWith("SPS") || sn.StartsWith("SPT") || sn.StartsWith("SPD") || sn.StartsWith("BA") ||
|
||||
sn.StartsWith("SLT") || sn.StartsWith("SLS") || sn.StartsWith("SLD");
|
||||
}
|
||||
|
||||
private bool HasNaturallyInvertedScaleFactor(Test.Module.Channel channel)
|
||||
{
|
||||
var serialNumberStart = channel.ParentModule.SerialNumber.Substring(0, 3);
|
||||
serialNumberStart = serialNumberStart.ToUpper();
|
||||
if (serialNumberStart != "SPS" && serialNumberStart != "SLS") return false;
|
||||
|
||||
if (!(channel is Test.Module.AnalogInputChannel)) return false;
|
||||
var aic = channel as Test.Module.AnalogInputChannel;
|
||||
if (aic.LinearizationFormula.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !aic.IsDigital();
|
||||
}
|
||||
|
||||
/// <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="testId"></param>
|
||||
/// <param name="tickEventHandler"></param>
|
||||
/// <param name="dataFolder"></param>
|
||||
/// <param name="cancelRequested"></param>
|
||||
/// <param name="pathName"></param>
|
||||
/// <param name="testPlan"></param>
|
||||
///
|
||||
protected void WriteChannelInfo(
|
||||
BinaryWriter fileWriter,
|
||||
Test test,
|
||||
string testId,
|
||||
TickEventHandler tickEventHandler,
|
||||
string dataFolder,
|
||||
CancelRequested cancelRequested,
|
||||
string pathName,
|
||||
TestPlan testPlan)
|
||||
{
|
||||
try
|
||||
{
|
||||
var emptyBuffer = Enumerable.Repeat(' ', 160).ToArray();
|
||||
var channels = test.Channels;
|
||||
channels.Sort(DisplayOrderComparer);
|
||||
|
||||
var dMaxStart = double.MinValue;
|
||||
var dMinEnd = double.MaxValue;
|
||||
|
||||
//find the subset of time from all channels, this is the max time data starts between all channels and the min time the data ends between all channels
|
||||
//10132 [Zendesk] Trim RDF exports so all channels from all DAS have same totalsample and triggersample
|
||||
//there is a hack here, in the above case I noticed TotalSamplesRecorded = 40k, but TriggerSampleNumber = 1,xxx,xxx meaning you would have
|
||||
//never have seen a trigger in the first point ... I don't think this is expected ... I hacked around this case to since the RDF export is very contained
|
||||
//and only used by one customer, while changing the totalsamplesrecorded might not be
|
||||
foreach (var channel in channels)
|
||||
{
|
||||
var dStart = (channel.ParentModule.StartRecordSampleNumber -
|
||||
(double)channel.ParentModule.TriggerSampleNumbers[0]) /
|
||||
channel.ParentModule.SampleRateHz;
|
||||
dMaxStart = Math.Max(dMaxStart, dStart);
|
||||
|
||||
var dEnd = ((double)channel.ParentModule.NumberOfSamples -
|
||||
channel.ParentModule.TriggerSampleNumbers[0] +
|
||||
channel.ParentModule.StartRecordSampleNumber - 1D) / channel.ParentModule.SampleRateHz;
|
||||
|
||||
if (channel.ParentModule.NumberOfSamples > channel.ParentModule.TriggerSampleNumbers[0])
|
||||
{
|
||||
dEnd = (channel.ParentModule.NumberOfSamples -
|
||||
(double)channel.ParentModule.TriggerSampleNumbers[0]) /
|
||||
channel.ParentModule.SampleRateHz;
|
||||
}
|
||||
dMinEnd = Math.Min(dMinEnd, dEnd);
|
||||
}
|
||||
for (var iChannelIdx = 0; iChannelIdx < channels.Count; iChannelIdx++)
|
||||
{
|
||||
var currentChannel = channels[iChannelIdx];
|
||||
var dStart = (currentChannel.ParentModule.StartRecordSampleNumber -
|
||||
(double)currentChannel.ParentModule.TriggerSampleNumbers[0]) /
|
||||
currentChannel.ParentModule.SampleRateHz;
|
||||
var dEnd = ((double)currentChannel.ParentModule.NumberOfSamples -
|
||||
currentChannel.ParentModule.TriggerSampleNumbers[0] +
|
||||
currentChannel.ParentModule.StartRecordSampleNumber - 1D) / currentChannel.ParentModule.SampleRateHz;
|
||||
|
||||
if (currentChannel.ParentModule.NumberOfSamples > currentChannel.ParentModule.TriggerSampleNumbers[0])
|
||||
{
|
||||
dEnd = (currentChannel.ParentModule.NumberOfSamples -
|
||||
(double)currentChannel.ParentModule.TriggerSampleNumbers[0]) /
|
||||
currentChannel.ParentModule.SampleRateHz;
|
||||
}
|
||||
|
||||
var startSample = Convert.ToInt64((dMaxStart - dStart) * currentChannel.ParentModule.SampleRateHz);
|
||||
var endSample = startSample + Convert.ToInt64((dMinEnd - dMaxStart) * currentChannel.ParentModule.SampleRateHz);
|
||||
|
||||
var bHasNaturallyInvertedScaleFactor = HasNaturallyInvertedScaleFactor(currentChannel);
|
||||
// Channel #
|
||||
fileWriter.Write((1 + iChannelIdx).ToString().PadLeft(5).ToCharArray());
|
||||
|
||||
// DAS Channel #.
|
||||
// This entry is simply the integer number representing the channel on the Sensor Input Module (SIM).
|
||||
// As with the .ISF file format, the Timed Output Module (TOM) has two channels associated with it.
|
||||
// One channel is the TOM Indication, which is the measure of the signal of TOM command to deploy an SIR.
|
||||
// The other channel is TOM Current, which measures the output current while deploying the SIR.
|
||||
// The channel number for a TOM begins with the channel number on the TOM. The channel number
|
||||
// is then followed by an ‘I’ or ‘C’. The ‘I’ represents channel indication and the ‘C’ indicates
|
||||
// current. G5 and TDAS Pro systems have a DAS Channel Number from 1-8 for the channel number field.
|
||||
// The DAS Rack Number and the DAS Module Number are required for DTS systems to setup. Barrier,
|
||||
// Hydraulic Sled, and Rollover are examples of sites that use this format. Slice systems have a DAS
|
||||
// Channel Number from 1-18.
|
||||
|
||||
var supposedChannelNumber = 1 + currentChannel.Number;
|
||||
var channel = currentChannel as Test.Module.AnalogInputChannel;
|
||||
if (channel != null && channel.IsSquib())
|
||||
{
|
||||
//0 = init, 1 = current
|
||||
var decorator = "I";
|
||||
if (0 == supposedChannelNumber % 2)
|
||||
{
|
||||
decorator = "C";
|
||||
supposedChannelNumber--;
|
||||
}
|
||||
var text = string.Format(" {0}{1}", supposedChannelNumber.ToString()[0], decorator);
|
||||
fileWriter.Write(text.ToCharArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsSlice(currentChannel.ParentModule.SerialNumber))
|
||||
{
|
||||
//slice are in the dts file by module, so SPS00041 0,1,2 SPS00041 0,1,2
|
||||
//but we want it in DAS order (1-18), so we hack and convert for SLICE.
|
||||
supposedChannelNumber += currentChannel.ParentModule.Number * 3;
|
||||
}
|
||||
fileWriter.Write(supposedChannelNumber.ToString()
|
||||
.PadLeft(2, '0')
|
||||
.PadLeft(4, ' ')
|
||||
.ToCharArray());
|
||||
}
|
||||
|
||||
fileWriter.Write(" ".ToCharArray()); // DAS Sub channel, not used
|
||||
fileWriter.Write(" 0".ToCharArray());
|
||||
// Number of scaling samples in data. 0, scaling is explicit
|
||||
var totalSamplesHomogenized =
|
||||
Convert.ToInt64((dMinEnd - dMaxStart) * channel.ParentModule.SampleRateHz);
|
||||
|
||||
fileWriter.Write((1L - 2L + totalSamplesHomogenized).ToString().PadLeft(10).ToCharArray());
|
||||
// Pre trigger samples.
|
||||
var preTrigger = Convert.ToInt64(Math.Abs(dMaxStart) *
|
||||
currentChannel.ParentModule.SampleRateHz);
|
||||
fileWriter.Write(preTrigger.ToString().PadLeft(10).ToCharArray());
|
||||
fileWriter.Write(currentChannel.ParentModule.SampleRateHz.ToString("+0.000E+000").ToCharArray());
|
||||
|
||||
// All ADC values are 0-65,536. Several uses of +32767 to center the value.
|
||||
// Data zero
|
||||
var dataZeroLevelADC = currentChannel.DataZeroLevelAdc;
|
||||
var currentAnalogChannel = currentChannel as Test.Module.AnalogInputChannel;
|
||||
|
||||
if (bHasNaturallyInvertedScaleFactor)
|
||||
{
|
||||
dataZeroLevelADC *= -1;
|
||||
}
|
||||
if (null != currentAnalogChannel && currentAnalogChannel.Bridge ==
|
||||
SensorConstants.BridgeType.DigitalInput)
|
||||
{
|
||||
//18142 digital input, just set ADC zero level
|
||||
fileWriter.Write(dataZeroLevelADC.ToString(CultureInfo.InvariantCulture).PadLeft(6, ' ').ToCharArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
fileWriter.Write((dataZeroLevelADC + DTS.Common.Constants.ADC_MIDPOINT).ToString(CultureInfo.InvariantCulture).PadLeft(6, ' ').ToCharArray());
|
||||
}
|
||||
//Cal point 1 is always 0
|
||||
fileWriter.Write("+0.000E+000".ToCharArray());
|
||||
|
||||
if (currentChannel is Test.Module.AnalogInputChannel && (currentChannel as Test.Module.AnalogInputChannel).LinearizationFormula.IsValid())
|
||||
{
|
||||
CreateLinearizedData(currentChannel, dataFolder, startSample, endSample); //Temp place holder to output lin files
|
||||
}
|
||||
else if (currentChannel is Test.Module.AnalogInputChannel && (currentChannel as Test.Module.AnalogInputChannel).IsDigital())
|
||||
{
|
||||
CreateDigitizedData(currentChannel, dataFolder, startSample, endSample);
|
||||
}
|
||||
|
||||
//Cal point 2 is the voltage insertion deflection, or 70% of the range in ADC
|
||||
if (null != currentAnalogChannel && currentAnalogChannel.Bridge ==
|
||||
SensorConstants.BridgeType.DigitalInput)
|
||||
{
|
||||
//18142 except for digital input, where cal point 2 is one louder
|
||||
// see note in digital input loop below regarding on/off routine
|
||||
fileWriter.Write((dataZeroLevelADC + 1).ToString(CultureInfo.InvariantCulture).PadLeft(6, ' ').ToCharArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
fileWriter.Write(
|
||||
(DTS.Common.Constants.ADC_MIDPOINT + MidpointDeflection).ToString(CultureInfo.InvariantCulture)
|
||||
.PadLeft(6, ' ')
|
||||
.ToCharArray());
|
||||
}
|
||||
|
||||
var scaler = new DataScaler
|
||||
{
|
||||
IsInverted = currentAnalogChannel.IsInverted,
|
||||
UnitConversion = currentAnalogChannel.UnitConversion,
|
||||
BasedOnOutputAtCapacity = currentAnalogChannel.AtCapacity,
|
||||
CapacityOutputIsBasedOn = currentAnalogChannel.CapacityOutputIsBasedOn,
|
||||
SensitivityUnits = currentAnalogChannel.SensitivityUnits,
|
||||
Multiplier = currentAnalogChannel.Multiplier
|
||||
};
|
||||
scaler.SetLinearizationFormula(currentAnalogChannel.LinearizationFormula);
|
||||
scaler.SetScaleFactorMv(currentChannel.Data.ScaleFactorMv);
|
||||
scaler.SetScaleFactorEU(currentChannel.Data.ScaleFactorEU);
|
||||
scaler.SetUseEUScaleFactors(currentChannel.Data.UseEUScaleFactors);
|
||||
if (currentChannel is Test.Module.AnalogInputChannel)
|
||||
{
|
||||
scaler.IEPE = (currentChannel as Test.Module.AnalogInputChannel).Bridge ==
|
||||
SensorConstants.BridgeType.IEPE;
|
||||
}
|
||||
scaler.SetMvPerEu(currentChannel.Data.MvPerEu);
|
||||
try
|
||||
{
|
||||
scaler.SetInitialOffset(currentAnalogChannel.InitialOffset);
|
||||
scaler.ZeroMethodType = currentAnalogChannel.ZeroMethod;
|
||||
scaler.SetRemovedADC(currentAnalogChannel.RemovedADC);
|
||||
scaler.SetRemovedInternalADC(currentAnalogChannel.RemovedInternalADC);
|
||||
scaler.SetDataZeroLevelADC(currentAnalogChannel.DataZeroLevelAdc);
|
||||
scaler.SetZeroMvInADC(currentAnalogChannel.ZeroMvInADC);
|
||||
try
|
||||
{
|
||||
scaler.SetWindowAverageADC(currentAnalogChannel.WindowAverageADC);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
|
||||
scaler.NominalExcitationVoltage = currentAnalogChannel.ExcitationVoltage;
|
||||
if (currentAnalogChannel.MeasuredExcitationVoltageValid)
|
||||
{
|
||||
try
|
||||
{
|
||||
scaler.MeasuredExcitationVoltage = currentAnalogChannel.MeasuredExcitationVoltage;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
if (currentAnalogChannel.FactoryExcitationVoltageValid)
|
||||
{
|
||||
try
|
||||
{
|
||||
scaler.FactoryExcitationVoltage = currentAnalogChannel.FactoryExcitationVoltage;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
scaler.ProportionalToExcitation = currentAnalogChannel.ProportionalToExcitation;
|
||||
|
||||
double[] nonLinearEUData = null;
|
||||
var nonLinearScaleFactor = 1D;
|
||||
//Cal point 2 in EU
|
||||
if (null != currentAnalogChannel && currentAnalogChannel.IsSquib())
|
||||
{
|
||||
var d = Math.Abs((MidpointDeflection - scaler.GetDataZeroLevelADC()) *
|
||||
scaler.GetAdcToEuScalingFactor());
|
||||
var dStr = d.ToString("+0.00000E+0;-0.00000E+0");
|
||||
fileWriter.Write(dStr.ToCharArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (null != currentAnalogChannel && currentAnalogChannel.Bridge ==
|
||||
SensorConstants.BridgeType.DigitalInput)
|
||||
{
|
||||
//digital input, use 1ADC = 5EU?
|
||||
fileWriter.Write(5D.ToString("+0.000E+000;-0.000E+000").ToCharArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (null != currentAnalogChannel && currentAnalogChannel.LinearizationFormula.IsValid())
|
||||
{
|
||||
nonLinearEUData = GetEUData(currentChannel);
|
||||
var max = nonLinearEUData.Max();
|
||||
var min = nonLinearEUData.Min();
|
||||
|
||||
max = Math.Max(Math.Abs(max), Math.Abs(min));
|
||||
var biPolar = min < 0 && max > 0;
|
||||
if (biPolar)
|
||||
{
|
||||
max = max * 2;
|
||||
}
|
||||
//we need twice the space to handle both the negative and positive values
|
||||
nonLinearScaleFactor = max / Common.Constants.ADC_MIDPOINT;
|
||||
fileWriter.Write(
|
||||
(MidpointDeflection * nonLinearScaleFactor).ToString(
|
||||
"+0.000E+000;-0.000E+000").ToCharArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
var dScaleFactor = scaler.GetAdcToEuScalingFactor() * scaler.Multiplier;
|
||||
if (bHasNaturallyInvertedScaleFactor)
|
||||
{
|
||||
dScaleFactor *= -1;
|
||||
}
|
||||
fileWriter.Write(
|
||||
(MidpointDeflection * dScaleFactor).ToString(
|
||||
"+0.000E+000;-0.000E+000").ToCharArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resolution
|
||||
fileWriter.Write(" 16".ToCharArray());
|
||||
// "rack" serial number
|
||||
fileWriter.Write(GetRackSerialNumber(currentChannel.ParentModule.SerialNumber, currentChannel.ParentModule.BaseSerialNumber).ToCharArray());
|
||||
|
||||
// "module" number
|
||||
fileWriter.Write(
|
||||
(1 + currentChannel.ParentModule.Number).ToString().PadLeft(2, ' ').ToCharArray());
|
||||
// Padding
|
||||
fileWriter.Write(emptyBuffer, 0, 63);
|
||||
|
||||
|
||||
// Write ADC data centered at 32767
|
||||
if (!(currentChannel is Test.Module.AnalogInputChannel)) continue;
|
||||
//ADC DIM data is -/+ rail, convert it to 0,1, then center around 32767
|
||||
if ((currentChannel as Test.Module.AnalogInputChannel).Bridge ==
|
||||
SensorConstants.BridgeType.DigitalInput)
|
||||
{
|
||||
scaler.SetDigitalMultiplier(
|
||||
(currentChannel as Test.Module.AnalogInputChannel)
|
||||
.DigitalMultiplier);
|
||||
scaler.Digital = true;
|
||||
scaler.DigitalMode =
|
||||
(currentChannel as Test.Module.AnalogInputChannel).DigitalMode;
|
||||
|
||||
// adjusted to remove 2 samples to be consistent with TDC RDF exports
|
||||
// TDC appears to be miscounting by 1 sample, developing 1 sample too few
|
||||
// DataPRO download appears to download 1 extra sample, so to be consistent with TDC, remove 2 samples...
|
||||
for (var iPt = startSample; iPt <= endSample - 2; iPt++)
|
||||
{
|
||||
var dataPoint = currentChannel.PersistentChannelInfo.Data[iPt];
|
||||
//note that this is an arbitrary over the threshold = on, below = off
|
||||
//more than likely we need to actually look at the input mode to make sense of
|
||||
//the information we are reading (CCNO/CCNC/LowToHigh/HighToLow)
|
||||
//the mode is accessible via (CurrentChannel as Test.Module.AnalogInputChannel).DigitalMode
|
||||
var value = dataZeroLevelADC;
|
||||
var eu = scaler.GetEU(dataPoint);
|
||||
|
||||
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
||||
if (eu != 0)
|
||||
{
|
||||
value += 1;
|
||||
}
|
||||
var byte2 = (byte)(value >> 8);
|
||||
var byte1 = (byte)(value & 0xFF);
|
||||
fileWriter.Write(byte1);
|
||||
fileWriter.Write(byte2);
|
||||
}
|
||||
}
|
||||
else if (null != currentAnalogChannel && currentAnalogChannel.LinearizationFormula.IsValid())
|
||||
{
|
||||
CreateLinearizedDataCSV(currentChannel, dataFolder, scaler, startSample, endSample);
|
||||
// adjusted to remove 2 samples to be consistent with TDC RDF exports
|
||||
// TDC appears to be miscounting by 1 sample, developing 1 sample too few
|
||||
// DataPRO download appears to download 1 extra sample, so to be consistent with TDC, remove 2 samples...
|
||||
for (var iPt = startSample; iPt <= endSample - 2; iPt++)
|
||||
{
|
||||
var dValue = nonLinearEUData[iPt];
|
||||
var adc = double.IsNaN(dValue / nonLinearScaleFactor) ? 0 : dValue / nonLinearScaleFactor;
|
||||
|
||||
var value = (ushort)(Convert.ToInt16(adc) + DTS.Common.Constants.ADC_MIDPOINT);
|
||||
var byte2 = (byte)(value >> 8);
|
||||
var byte1 = (byte)(value & 0xFF);
|
||||
fileWriter.Write(byte1);
|
||||
fileWriter.Write(byte2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bHasNaturallyInvertedScaleFactor && currentChannel.ZeroMvInADC != 0)
|
||||
{
|
||||
currentChannel.ZeroMvInADC *= -1;
|
||||
scaler.SetZeroMvInADC(currentChannel.ZeroMvInADC);
|
||||
}
|
||||
// adjusted to remove 2 samples to be consistent with TDC RDF exports
|
||||
// TDC appears to be miscounting by 1 sample, developing 1 sample too few
|
||||
// DataPRO download appears to download 1 extra sample, so to be consistent with TDC, remove 2 samples...
|
||||
for (var pt = startSample; pt <= endSample - 2; pt++)
|
||||
{
|
||||
var dataPoint = currentChannel.PersistentChannelInfo.Data[pt];
|
||||
if (bHasNaturallyInvertedScaleFactor)
|
||||
{
|
||||
dataPoint *= -1;
|
||||
}
|
||||
var value = (ushort)(dataPoint + DTS.Common.Constants.ADC_MIDPOINT);
|
||||
var byte2 = (byte)(value >> 8);
|
||||
var byte1 = (byte)(value & 0xFF);
|
||||
fileWriter.Write(byte1);
|
||||
fileWriter.Write(byte2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem writing RDF channel headers", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetTestObjectNumber(string isocode, TestPlan plan)
|
||||
{
|
||||
var ic = new IsoCode(isocode);
|
||||
var testobjectcharacter = ic.TestObject;
|
||||
|
||||
var objectNumber = 1;
|
||||
foreach (var to in plan.ISOTestObjects)
|
||||
{
|
||||
if (to.TypeOfTestObject == testobjectcharacter)
|
||||
{
|
||||
return objectNumber.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
objectNumber++;
|
||||
}
|
||||
return objectNumber.ToString("1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace DTS.Serialization.StringResources {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Strings {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Strings() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
var temp = new global::System.Resources.ResourceManager("DTS.Serialization.StringResources.Strings", typeof(Strings).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DTS_Slice_Control_Equals_ComparisonFailedString.
|
||||
/// </summary>
|
||||
internal static string DTS_Slice_Control_Equals_ComparisonFailedString {
|
||||
get {
|
||||
return ResourceManager.GetString("DTS_Slice_Control_Equals_ComparisonFailedString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DTS_Slice_Control_Event_ConstructionFailedString.
|
||||
/// </summary>
|
||||
internal static string DTS_Slice_Control_Event_ConstructionFailedString {
|
||||
get {
|
||||
return ResourceManager.GetString("DTS_Slice_Control_Event_ConstructionFailedString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DTS_Slice_Control_Event_Event_DASTestIdMismatchString.
|
||||
/// </summary>
|
||||
internal static string DTS_Slice_Control_Event_Event_DASTestIdMismatchString {
|
||||
get {
|
||||
return ResourceManager.GetString("DTS_Slice_Control_Event_Event_DASTestIdMismatchString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DTS_Slice_Control_Event_Event_EmptyDasListString.
|
||||
/// </summary>
|
||||
internal static string DTS_Slice_Control_Event_Event_EmptyDasListString {
|
||||
get {
|
||||
return ResourceManager.GetString("DTS_Slice_Control_Event_Event_EmptyDasListString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DTS_Slice_Control_Event_Event_FailedToDetermineIdOrDescriptionFromConfigurationString.
|
||||
/// </summary>
|
||||
internal static string DTS_Slice_Control_Event_Event_FailedToDetermineIdOrDescriptionFromConfigurationString {
|
||||
get {
|
||||
return ResourceManager.GetString("DTS_Slice_Control_Event_Event_FailedToDetermineIdOrDescriptionFromConfigurationSt" +
|
||||
"ring", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DTS_Slice_Control_Event_Event_NullDasListString.
|
||||
/// </summary>
|
||||
internal static string DTS_Slice_Control_Event_Event_NullDasListString {
|
||||
get {
|
||||
return ResourceManager.GetString("DTS_Slice_Control_Event_Event_NullDasListString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DTS_Slice_Control_Event_Module_Channel_DataEquals_ComparisonFailedString.
|
||||
/// </summary>
|
||||
internal static string DTS_Slice_Control_Event_Module_Channel_DataEquals_ComparisonFailedString {
|
||||
get {
|
||||
return ResourceManager.GetString("DTS_Slice_Control_Event_Module_Channel_DataEquals_ComparisonFailedString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DTS_Slice_Control_Event_Module_ChannelsEquals_ComparisonFailedString.
|
||||
/// </summary>
|
||||
internal static string DTS_Slice_Control_Event_Module_ChannelsEquals_ComparisonFailedString {
|
||||
get {
|
||||
return ResourceManager.GetString("DTS_Slice_Control_Event_Module_ChannelsEquals_ComparisonFailedString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DTS_Slice_Control_Event_Module_TriggerSampleNumbersEquals_ComparisonFailedString.
|
||||
/// </summary>
|
||||
internal static string DTS_Slice_Control_Event_Module_TriggerSampleNumbersEquals_ComparisonFailedString {
|
||||
get {
|
||||
return ResourceManager.GetString("DTS_Slice_Control_Event_Module_TriggerSampleNumbersEquals_ComparisonFailedString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DTS_Slice_Control_Event_ModuleEquals_ComparisonFailedString.
|
||||
/// </summary>
|
||||
internal static string DTS_Slice_Control_Event_ModuleEquals_ComparisonFailedString {
|
||||
get {
|
||||
return ResourceManager.GetString("DTS_Slice_Control_Event_ModuleEquals_ComparisonFailedString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DTS_Slice_Control_NullIndicatorString.
|
||||
/// </summary>
|
||||
internal static string DTS_Slice_Control_NullIndicatorString {
|
||||
get {
|
||||
return ResourceManager.GetString("DTS_Slice_Control_NullIndicatorString", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,857 @@
|
||||
/*
|
||||
* Iso.File.Test.Channel.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
using DTS.Common.Utils;
|
||||
|
||||
namespace DTS.Serialization.Iso
|
||||
{
|
||||
// *** Iso.File.cs ***
|
||||
public partial class File
|
||||
{
|
||||
// *** Iso.File.Test.cs ***
|
||||
public partial class Test
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// ISO-style representation of a test channel.
|
||||
/// </summary>
|
||||
///
|
||||
public class Channel : Exceptional
|
||||
{
|
||||
/// <summary>
|
||||
/// Get/set the data zero offset of the data (in EU).
|
||||
/// </summary>
|
||||
public double DataZeroOffsetEu
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_DataZeroOffsetEu.IsValueInitialized) { return 0; }
|
||||
return _DataZeroOffsetEu.Value;
|
||||
}
|
||||
set => _DataZeroOffsetEu.Value = value;
|
||||
}
|
||||
private readonly Property<double> _DataZeroOffsetEu
|
||||
= new Property<double>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.DataZeroOffsetEu",
|
||||
0,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="int"/> number associated with this test object.
|
||||
/// </summary>
|
||||
public int TestObjectNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_TestObjectNumber.IsValueInitialized) { return 0; }
|
||||
return _TestObjectNumber.Value;
|
||||
}
|
||||
set => _TestObjectNumber.Value = value;
|
||||
}
|
||||
private const string TestObjectNumberLabel = "Test object number";
|
||||
private readonly Property<int> _TestObjectNumber
|
||||
= new Property<int>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.TestObjectNumber",
|
||||
0,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="bool"/> indicating whether or not errors occurred in
|
||||
/// the capture of this channel data.
|
||||
/// </summary>
|
||||
public bool ErrorsOccurred
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_ErrorsOccurred.IsValueInitialized) { return false; }
|
||||
return _ErrorsOccurred.Value;
|
||||
}
|
||||
set => _ErrorsOccurred.Value = value;
|
||||
}
|
||||
private readonly Property<bool> _ErrorsOccurred
|
||||
= new Property<bool>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.ErrorsOccurred",
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="string"/> name of the channel.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_Name.IsValueInitialized) { return null; }
|
||||
return _Name.Value;
|
||||
}
|
||||
set => _Name.Value = value;
|
||||
}
|
||||
private const string NameLabel = "Name of the channel";
|
||||
private readonly Property<string> _Name
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.Name",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the laboratory code <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string LaboratoryCode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_LaboratoryCode.IsValueInitialized) { return null; }
|
||||
return _LaboratoryCode.Value;
|
||||
}
|
||||
set => _LaboratoryCode.Value = value;
|
||||
}
|
||||
private const string LaboratoryCodeLabel = "Laboratory channel code";
|
||||
private readonly Property<string> _LaboratoryCode
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.LaboratoryCode",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the customer code <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string CustomerCode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_CustomerCode.IsValueInitialized) { return null; }
|
||||
return _CustomerCode.Value;
|
||||
}
|
||||
set => _CustomerCode.Value = value;
|
||||
}
|
||||
private const string CustomerCodeLabel = "Customer channel code";
|
||||
private readonly Property<string> _CustomerCode
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.CustomerCode",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the code <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string Code
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_Code.IsValueInitialized) { return null; }
|
||||
return _Code.Value;
|
||||
}
|
||||
set => _Code.Value = value;
|
||||
}
|
||||
private const string CodeLabel = "Channel code";
|
||||
private readonly Property<string> _Code
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.Code",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the location <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string Location
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_Location.IsValueInitialized) { return "????"; }
|
||||
return _Location.Value;
|
||||
}
|
||||
set => _Location.Value = value;
|
||||
}
|
||||
private const string LocationLabel = "Location";
|
||||
private readonly Property<string> _Location
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.Location",
|
||||
"????",
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the location <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string Dimension
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_Dimension.IsValueInitialized) { return null; }
|
||||
return _Dimension.Value;
|
||||
}
|
||||
set => _Dimension.Value = value;
|
||||
}
|
||||
private const string DimensionLabel = "Dimension";
|
||||
private readonly Property<string> _Dimension
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.Dimension",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the direction <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string Direction
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_Direction.IsValueInitialized) { return null; }
|
||||
return _Direction.Value;
|
||||
}
|
||||
set => _Direction.Value = value;
|
||||
}
|
||||
private const string DirectionLabel = "Direction";
|
||||
private readonly Property<string> _Direction
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.Direction",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the list of <see cref="ExtraProperty"/>s for this test.
|
||||
/// </summary>
|
||||
public List<ExtraProperty> ExtraProperties
|
||||
{
|
||||
get => _ExtraProperties.Value;
|
||||
set => _ExtraProperties.Value = value;
|
||||
}
|
||||
private readonly Property<List<ExtraProperty>> _ExtraProperties
|
||||
= new Property<List<ExtraProperty>>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.ExtraProperties",
|
||||
new List<ExtraProperty>(),
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="ChannelFilter"/> for the channel.
|
||||
/// </summary>
|
||||
public ChannelFilter FilterClass
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_FilterClass.IsValueInitialized) { return ChannelFilter.Unfiltered; }
|
||||
return _FilterClass.Value;
|
||||
}
|
||||
set => _FilterClass.Value = value;
|
||||
}
|
||||
private readonly Property<ChannelFilter> _FilterClass
|
||||
= new Property<ChannelFilter>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.FilterClass",
|
||||
ChannelFilter.Unfiltered,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string ChannelFrequencyClass
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_ChannelFrequencyClass.IsValueInitialized) { return null; }
|
||||
return _ChannelFrequencyClass.Value;
|
||||
}
|
||||
set => _ChannelFrequencyClass.Value = value;
|
||||
}
|
||||
private const string FrequencyClassLabel = "Channel frequency class";
|
||||
private readonly Property<string> _ChannelFrequencyClass
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.ChannelFrequencyClass",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the unit <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string Unit
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_Unit.IsValueInitialized) { return null; }
|
||||
return _Unit.Value;
|
||||
}
|
||||
set => _Unit.Value = value;
|
||||
}
|
||||
private const string UnitLabel = "Unit";
|
||||
private readonly Property<string> _Unit
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.Unit",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the reference system <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string ReferenceSystem
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_ReferenceSystem.IsValueInitialized) { return null; }
|
||||
return _ReferenceSystem.Value;
|
||||
}
|
||||
set => _ReferenceSystem.Value = value;
|
||||
}
|
||||
private const string ReferenceSystemLabel = "Reference system";
|
||||
private readonly Property<string> _ReferenceSystem
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.ReferenceSystem",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the transducer type <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string TransducerType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_TransducerType.IsValueInitialized) { return null; }
|
||||
return _TransducerType.Value;
|
||||
}
|
||||
set => _TransducerType.Value = value;
|
||||
}
|
||||
private const string TransducerTypeLabel = "Transducer type";
|
||||
private readonly Property<string> _TransducerType
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.TransducerType",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the transducer id (sensor serial number) <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string TransducerId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_TransducerId.IsValueInitialized) { return null; }
|
||||
return _TransducerId.Value;
|
||||
}
|
||||
set => _TransducerId.Value = value;
|
||||
}
|
||||
private const string TransducerIdLabel = "Transducer id";
|
||||
private readonly Property<string> _TransducerId
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.TransducerId",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the pre-filter type <see cref="string"/> for the channel.
|
||||
/// </summary>
|
||||
public string PrefilterType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_PrefilterType.IsValueInitialized) { return null; }
|
||||
return _PrefilterType.Value;
|
||||
}
|
||||
set => _PrefilterType.Value = value;
|
||||
}
|
||||
private const string PrefilterTypeLabel = "Pre-filter type";
|
||||
private readonly Property<string> _PrefilterType
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.PrefilterType",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> cut-off frequency value for the channel.
|
||||
/// </summary>
|
||||
public double CutOffFrequency
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_CutOffFrequency.IsValueInitialized) { return 0D; }
|
||||
return _CutOffFrequency.Value;
|
||||
}
|
||||
set => _CutOffFrequency.Value = value;
|
||||
}
|
||||
private const string CutOffFrequencyLabel = "Cut off frequency";
|
||||
private readonly Property<double> _CutOffFrequency
|
||||
= new Property<double>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.CutOffFrequency",
|
||||
0.0,
|
||||
false
|
||||
);
|
||||
|
||||
public bool IsDigitalInput { get; set; }
|
||||
public bool IsSquib { get; set; }
|
||||
public double AmplitudeClass { get; set; }
|
||||
private const string AmplitudeClassLabel = "Channel amplitude class";
|
||||
private const string ReferenceChannelLabel = "Reference channel";
|
||||
private const string ReferenceChannelNameLabel = "Reference channel name";
|
||||
private const string DataSourceLabel = "Data source";
|
||||
private const string DataStatusLabel = "Data status";
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> sampling interval for the Test.
|
||||
/// this is the max sample rate between all channels
|
||||
/// </summary>
|
||||
public double SamplingIntervalTest
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_SamplingIntervalTest.IsValueInitialized) { return 0D; }
|
||||
return _SamplingIntervalTest.Value;
|
||||
}
|
||||
set => _SamplingIntervalTest.Value = value;
|
||||
}
|
||||
|
||||
private readonly Property<double> _SamplingIntervalTest
|
||||
= new Property<double>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.SamplingIntervalTest",
|
||||
0.0,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> sampling interval for the channel.
|
||||
/// </summary>
|
||||
public double SamplingInterval
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_SamplingInterval.IsValueInitialized) { return 0D; }
|
||||
return _SamplingInterval.Value;
|
||||
}
|
||||
set => _SamplingInterval.Value = value;
|
||||
}
|
||||
private const string SamplingIntervalLabel = "Sampling interval";
|
||||
private readonly Property<double> _SamplingInterval
|
||||
= new Property<double>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.SamplingInterval",
|
||||
0.0,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="int"/> bit resolution for the channel.
|
||||
/// </summary>
|
||||
public int BitResolution
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_BitResolution.IsValueInitialized) { return 0; }
|
||||
return _BitResolution.Value;
|
||||
}
|
||||
set => _BitResolution.Value = value;
|
||||
}
|
||||
private const string BitResolutionLabel = "Bit resolution";
|
||||
private readonly Property<int> _BitResolution
|
||||
= new Property<int>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.BitResolution",
|
||||
0,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set this channel's comment <see cref="string"/>.
|
||||
/// </summary>
|
||||
public string Comments
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_Comments.IsValueInitialized) { return null; }
|
||||
return _Comments.Value;
|
||||
}
|
||||
set => _Comments.Value = value;
|
||||
}
|
||||
private readonly Property<string> _Comments
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.Comments",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> time of first sample for the channel.
|
||||
/// </summary>
|
||||
public double TimeOfFirstSample
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_TimeOfFirstSample.IsValueInitialized) { return 0D; }
|
||||
return _TimeOfFirstSample.Value;
|
||||
}
|
||||
set => _TimeOfFirstSample.Value = value;
|
||||
}
|
||||
private const string TimeOfFirstSampleLabel = "Time of first sample";
|
||||
private readonly Property<double> _TimeOfFirstSample
|
||||
= new Property<double>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.TimeOfFirstSample",
|
||||
0.0,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="int"/> number of samples on the channel.
|
||||
/// </summary>
|
||||
public ulong NumberOfSamples
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToUInt64(Samples.Data.Length);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting number of samples for channel " + (_Name.IsInitialized && null != Name ? "\"" + Name + "\"" : "<NULL>"), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private const string NumberOfSamplesLabel = "Number of samples";
|
||||
|
||||
/// <summary>
|
||||
/// Get/set this channel's offset post test <see cref="string"/>.
|
||||
/// </summary>
|
||||
public double OffsetPostTest
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_OffsetPostTest.IsValueInitialized) { return 0D; }
|
||||
return _OffsetPostTest.Value;
|
||||
}
|
||||
set => _OffsetPostTest.Value = value;
|
||||
}
|
||||
private const string OffsetPostTestLabel = "Offset post test";
|
||||
private readonly Property<double> _OffsetPostTest
|
||||
= new Property<double>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.OffsetPostTest",
|
||||
0.0,
|
||||
false
|
||||
);
|
||||
|
||||
private const string TransducerNatFreqLabel = "Transducer natural frequency";
|
||||
private const string TransducerDampRatioLabel = "Transducer damping ratio";
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> first global maximum for the channel.
|
||||
/// </summary>
|
||||
public double FirstGlobalMaximum
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_IsFirstGlobalMaximumValueInitialized)
|
||||
return _FirstGlobalMaximumValue;
|
||||
long firstMaxIndex = 0;
|
||||
long maxIndex = 0;
|
||||
var firstMax = double.NaN;
|
||||
if (Samples != null)
|
||||
{
|
||||
firstMaxIndex = (Samples.Data.Length > 0) ? Samples.Data.Length - 1 : 0;
|
||||
maxIndex = Samples.Data.Length;
|
||||
firstMax = Samples.Data[firstMaxIndex - 1];
|
||||
}
|
||||
|
||||
// xxx For some reason the memory mapped class is painfully slow when
|
||||
// traversed in reverse, so we're going from the front. Also, indexing
|
||||
// the last item causes problems, so for the moment we're stopping
|
||||
// one item short.
|
||||
for (long i = 0; i < maxIndex - 1; i++)
|
||||
{
|
||||
if (firstMax < Samples.Data[i])
|
||||
{
|
||||
firstMax = Samples.Data[i];
|
||||
firstMaxIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
_FirstGlobalMaximumValue = firstMax - DataZeroOffsetEu;
|
||||
_FirstGlobalMaximumValueIndex = firstMaxIndex;
|
||||
_IsFirstGlobalMaximumValueInitialized = true;
|
||||
|
||||
return _FirstGlobalMaximumValue;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting first global maximum on channel " + (_Name.IsInitialized && null != Name ? "\"" + Name + "\"" : "<NULL>"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_FirstGlobalMaximumValue = value;
|
||||
_IsFirstGlobalMaximumValueInitialized = true;
|
||||
}
|
||||
}
|
||||
private const string FirstGlobalMaximumLabel = "First global maximum";
|
||||
private double _FirstGlobalMaximumValue = 0.0;
|
||||
private long _FirstGlobalMaximumValueIndex = 0;
|
||||
private bool _IsFirstGlobalMaximumValueInitialized = false;
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> time of maximum value for the channel.
|
||||
/// </summary>
|
||||
public double TimeOfMaximumValue
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_IsTimeOfMaximumValueInitialized)
|
||||
{
|
||||
_TimeOfMaximumValue = TimeOfFirstSample + SamplingInterval * _FirstGlobalMaximumValueIndex;
|
||||
_IsTimeOfMaximumValueInitialized = true;
|
||||
}
|
||||
return _TimeOfMaximumValue;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting time of maximum value", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private const string TimeOfMaximumValueLabel = "Time of maximum value";
|
||||
private double _TimeOfMaximumValue = 0.0;
|
||||
private bool _IsTimeOfMaximumValueInitialized = false;
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> first global minimum for the channel.
|
||||
/// </summary>
|
||||
public double FirstGlobalMinimum
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_IsFirstGlobalMinimumValueInitialized)
|
||||
return _FirstGlobalMinimumValue;
|
||||
long firstMinIndex = 0;
|
||||
var firstMin = double.NaN;
|
||||
|
||||
if (Samples != null)
|
||||
{
|
||||
firstMinIndex = Samples.Data.Length > 0 ? Samples.Data.Length - 1 : 0;
|
||||
firstMin = Samples.Data[firstMinIndex - 1];
|
||||
}
|
||||
|
||||
// xxx correct these indicies. Have to go from front to back, also --
|
||||
// for some reason the memory mapping is painfully slow when the array
|
||||
// is traversed in reverse.
|
||||
for (var i = firstMinIndex - 1; i >= 0; i--)
|
||||
{
|
||||
if (firstMin > Samples.Data[i])
|
||||
{
|
||||
firstMin = Samples.Data[i];
|
||||
firstMinIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
_FirstGlobalMinimumValue = firstMin - DataZeroOffsetEu;
|
||||
_FirstGlobalMinimumValueIndex = firstMinIndex;
|
||||
_IsFirstGlobalMinimumValueInitialized = true;
|
||||
|
||||
return _FirstGlobalMinimumValue;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting first global minimum on channel " + (_Name.IsInitialized && null != Name ? "\"" + Name + "\"" : "<NULL>"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_FirstGlobalMinimumValue = value;
|
||||
_IsFirstGlobalMinimumValueInitialized = true;
|
||||
}
|
||||
}
|
||||
private const string FirstGlobalMinimumLabel = "First global minimum";
|
||||
private double _FirstGlobalMinimumValue = 0.0;
|
||||
private long _FirstGlobalMinimumValueIndex = 0;
|
||||
private bool _IsFirstGlobalMinimumValueInitialized = false;
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> time of minimum value for the channel.
|
||||
/// </summary>
|
||||
public double TimeOfMinimumValue
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_IsTimeOfMinimumValueInitialized)
|
||||
{
|
||||
_TimeOfMinimumValue = TimeOfFirstSample + SamplingInterval * _FirstGlobalMinimumValueIndex;
|
||||
_IsTimeOfMinimumValueInitialized = true;
|
||||
}
|
||||
return _TimeOfMinimumValue;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting time of minimum value", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private const string TimeOfMinimumValueLabel = "Time of minimum value";
|
||||
private double _TimeOfMinimumValue = 0.0;
|
||||
private bool _IsTimeOfMinimumValueInitialized = false;
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> time of minimum value for the channel.
|
||||
/// </summary>
|
||||
public double StartOffsetInterval
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return _StartOffsetInterval;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting start offset interval", ex);
|
||||
}
|
||||
}
|
||||
|
||||
set => _StartOffsetInterval = value;
|
||||
}
|
||||
private const string StartOffsetIntervalLabel = "Start offset interval";
|
||||
private double _StartOffsetInterval = 0.0;
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> time of minimum value for the channel.
|
||||
/// </summary>
|
||||
public double EndOffsetInterval
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return _EndOffsetInterval;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting start offset interval", ex);
|
||||
}
|
||||
}
|
||||
|
||||
set => _EndOffsetInterval = value;
|
||||
}
|
||||
private const string EndOffsetIntervalLabel = "End offset interval";
|
||||
private double _EndOffsetInterval = 0.0;
|
||||
|
||||
|
||||
public FilteredData Samples
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_Samples.IsValueInitialized) { return null; }
|
||||
return _Samples.Value;
|
||||
}
|
||||
set => _Samples.Value = value;
|
||||
}
|
||||
private readonly Property<FilteredData> _Samples
|
||||
= new Property<FilteredData>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Channel.Samples",
|
||||
null,
|
||||
false
|
||||
);
|
||||
/// <summary>
|
||||
/// Generate a string representation for this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// A <see cref="string"/> representation of this object.
|
||||
/// </returns>
|
||||
///
|
||||
public override string ToString()
|
||||
{
|
||||
try
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
string line = null;
|
||||
|
||||
builder.Append(TestObjectNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestObjectNumber.ToString())) + (null != line ? Eol : ""));
|
||||
builder.Append(NameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => IsSquib ? Name.ReplaceStrings(Common.Constants.ExportNameFilters, StringReplacementMode.Last) : Name)) + (null != line ? Eol : "")); //17650: sanitize name output for certain exports
|
||||
builder.Append(LaboratoryCodeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryCode)) + (null != line ? Eol : ""));
|
||||
builder.Append(CustomerCodeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerCode)) + (null != line ? Eol : ""));
|
||||
builder.Append(CodeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Code)) + (null != line ? Eol : ""));
|
||||
builder.Append(LocationLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Location)) + (null != line ? Eol : ""));
|
||||
builder.Append(DimensionLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Dimension)) + (null != line ? Eol : ""));
|
||||
builder.Append(DirectionLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Direction)) + (null != line ? Eol : ""));
|
||||
builder.Append(FrequencyClassLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => ChannelFrequencyClass)) + (null != line ? Eol : ""));
|
||||
builder.Append(UnitLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Unit)) + (null != line ? Eol : ""));
|
||||
builder.Append(ReferenceSystemLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => ReferenceSystem)) + (null != line ? Eol : ""));
|
||||
builder.Append(TransducerTypeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TransducerType)) + (null != line ? Eol : ""));
|
||||
builder.Append(TransducerIdLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => IsSquib ? TransducerId.ReplaceStrings(Common.Constants.ExportNameFilters, StringReplacementMode.Last) : TransducerId)) + (null != line ? Eol : "")); //17650: sanitize name/id output for certain exports
|
||||
builder.Append(PrefilterTypeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => IsDigitalInput ? "NOVALUE" : PrefilterType)) + (null != line ? Eol : ""));
|
||||
builder.Append(CutOffFrequencyLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => IsDigitalInput ? "NOVALUE" : CutOffFrequency.ToString())) + (null != line ? Eol : ""));
|
||||
builder.Append(AmplitudeClassLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => AmplitudeClass.ToString())) + (null != line ? Eol : ""));
|
||||
builder.Append(ReferenceChannelLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "implicit")) + (null != line ? Eol : ""));
|
||||
builder.Append(ReferenceChannelNameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "NOVALUE")) + (null != line ? Eol : ""));
|
||||
builder.Append(DataSourceLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "transducer")) + (null != line ? Eol : ""));
|
||||
builder.Append(DataStatusLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "ok")) + (null != line ? Eol : ""));
|
||||
|
||||
//14247 Data resampled using linear interpolation to the highest sample rate in the test looks incorrect?
|
||||
//we put in the test sample interval rather than the channel, since we will not be exporting at the channel's rate
|
||||
builder.Append(SamplingIntervalLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => SamplingIntervalTest.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
|
||||
|
||||
builder.Append(BitResolutionLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => BitResolution.ToString())) + (null != line ? Eol : ""));
|
||||
builder.Append(CommentsLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Comments)) + (null != line ? Eol : ""));
|
||||
builder.Append(TimeOfFirstSampleLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TimeOfFirstSample.ToString())) + (null != line ? Eol : ""));
|
||||
builder.Append(NumberOfSamplesLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => NumberOfSamples.ToString())) + (null != line ? Eol : ""));
|
||||
builder.Append(OffsetPostTestLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => OffsetPostTest.ToString())) + (null != line ? Eol : ""));
|
||||
builder.Append(TransducerNatFreqLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "NOVALUE")) + (null != line ? Eol : ""));
|
||||
builder.Append(TransducerDampRatioLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "NOVALUE")) + (null != line ? Eol : ""));
|
||||
builder.Append(FirstGlobalMaximumLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => FirstGlobalMaximum.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
|
||||
builder.Append(TimeOfMaximumValueLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TimeOfMaximumValue.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
|
||||
builder.Append(FirstGlobalMinimumLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => FirstGlobalMinimum.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
|
||||
builder.Append(TimeOfMinimumValueLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TimeOfMinimumValue.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
|
||||
builder.Append(StartOffsetIntervalLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => StartOffsetInterval.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
|
||||
builder.Append(EndOffsetIntervalLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => EndOffsetInterval.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
|
||||
|
||||
foreach (var exp in ExtraProperties)
|
||||
{
|
||||
builder.Append(exp.Key.PadRight(SeparatorOffset) + Separator + (line = exp.Value) + (null != line ? Eol : ""));
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem generating string representation for " + GetType().FullName, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="DTS_Slice_Control_Equals_ComparisonFailedString" xml:space="preserve">
|
||||
<value>DTS_Slice_Control_Equals_ComparisonFailedString</value>
|
||||
</data>
|
||||
<data name="DTS_Slice_Control_Event_ConstructionFailedString" xml:space="preserve">
|
||||
<value>DTS_Slice_Control_Event_ConstructionFailedString</value>
|
||||
</data>
|
||||
<data name="DTS_Slice_Control_Event_Event_DASTestIdMismatchString" xml:space="preserve">
|
||||
<value>DTS_Slice_Control_Event_Event_DASTestIdMismatchString</value>
|
||||
</data>
|
||||
<data name="DTS_Slice_Control_Event_Event_EmptyDasListString" xml:space="preserve">
|
||||
<value>DTS_Slice_Control_Event_Event_EmptyDasListString</value>
|
||||
</data>
|
||||
<data name="DTS_Slice_Control_Event_Event_FailedToDetermineIdOrDescriptionFromConfigurationString" xml:space="preserve">
|
||||
<value>DTS_Slice_Control_Event_Event_FailedToDetermineIdOrDescriptionFromConfigurationString</value>
|
||||
</data>
|
||||
<data name="DTS_Slice_Control_Event_Event_NullDasListString" xml:space="preserve">
|
||||
<value>DTS_Slice_Control_Event_Event_NullDasListString</value>
|
||||
</data>
|
||||
<data name="DTS_Slice_Control_Event_ModuleEquals_ComparisonFailedString" xml:space="preserve">
|
||||
<value>DTS_Slice_Control_Event_ModuleEquals_ComparisonFailedString</value>
|
||||
</data>
|
||||
<data name="DTS_Slice_Control_Event_Module_ChannelsEquals_ComparisonFailedString" xml:space="preserve">
|
||||
<value>DTS_Slice_Control_Event_Module_ChannelsEquals_ComparisonFailedString</value>
|
||||
</data>
|
||||
<data name="DTS_Slice_Control_Event_Module_Channel_DataEquals_ComparisonFailedString" xml:space="preserve">
|
||||
<value>DTS_Slice_Control_Event_Module_Channel_DataEquals_ComparisonFailedString</value>
|
||||
</data>
|
||||
<data name="DTS_Slice_Control_Event_Module_TriggerSampleNumbersEquals_ComparisonFailedString" xml:space="preserve">
|
||||
<value>DTS_Slice_Control_Event_Module_TriggerSampleNumbersEquals_ComparisonFailedString</value>
|
||||
</data>
|
||||
<data name="DTS_Slice_Control_NullIndicatorString" xml:space="preserve">
|
||||
<value>DTS_Slice_Control_NullIndicatorString</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* DTS.Slice.Control.Event.TestInformation.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Slice.Control
|
||||
{
|
||||
// *** see DTS.Slice.Control.DAS.Event.cs ***
|
||||
public partial class Event
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal representation of DAS event test information.
|
||||
/// </summary>
|
||||
private class TestInformation : Exceptional
|
||||
{
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="string"/> ID of the test associated with this DAS event.
|
||||
/// </summary>
|
||||
public string Id
|
||||
{
|
||||
get => _Id.Value;
|
||||
set => _Id.Value = value;
|
||||
}
|
||||
private readonly Property<string> _Id = new Property<string>("DTS.Slice.Control.Event.TestInformation.Id", null, false);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="string"/> description of the test associated with this DAS event.
|
||||
/// </summary>
|
||||
public string Description
|
||||
{
|
||||
get => _Description.Value;
|
||||
set => _Description.Value = value;
|
||||
}
|
||||
private readonly Property<string> _Description = new Property<string>("DTS.Slice.Control.Event.TestInformation.Description", null, false);
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Slice.Control.Event.TestInformation class.
|
||||
/// </summary>
|
||||
public TestInformation()
|
||||
{ //
|
||||
// NOTE that the invocation of this constructor will leave this class'
|
||||
// properties uninitialized.
|
||||
} //
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Slice.Control.Event.TestInformation class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="id">
|
||||
/// The <see cref="string"/> ID of the test associated with this DAS event.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="description">
|
||||
/// The <see cref="string"/> description of the test associated with this DAS event.
|
||||
/// </param>
|
||||
///
|
||||
public TestInformation(string id, string description)
|
||||
{
|
||||
try
|
||||
{
|
||||
Id = id;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
Serialization.StringResources.Strings.DTS_Slice_Control_Event_ConstructionFailedString, GetType().FullName),
|
||||
ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.Serialization.TDM
|
||||
{
|
||||
public class TestHeader
|
||||
{
|
||||
internal const int MAX_TESTDEVICES = 1000;
|
||||
internal const int MAX_DUMMY_DISPLAY = 16;
|
||||
internal const int MAX_BARRIER_DISPLAY = 3;
|
||||
internal const int MAX_GROUP_DISPLAY = 20;
|
||||
internal const int MAX_DEVICE_DISPLAY = MAX_DUMMY_DISPLAY + MAX_BARRIER_DISPLAY + MAX_GROUP_DISPLAY + 1;
|
||||
internal const char DEV_TYPE_DUMMY = 'D';
|
||||
internal const char DEV_TYPE_BARRIER = 'B';
|
||||
internal const char DEV_TYPE_GROUP = 'G';
|
||||
internal const char DEV_TYPE_UNDEFINED = 'U';
|
||||
internal const int MAX_DEVICE_LINES = 23;
|
||||
internal const int MAX_OLD_GROUP_LINES = 4;
|
||||
|
||||
public void WriteTestHeader(Writer writer, System.IO.TextWriter tw, bool bFiltered, UInt16 subSampleInterval, ulong numSamples, int preTriggerSamples)
|
||||
{
|
||||
var test = writer.Test;
|
||||
|
||||
writer.IncrementDone(1);
|
||||
|
||||
tw.WriteLine("{0},", test.Id);//test id
|
||||
tw.WriteLine("{0},", 0);//impact speed 1
|
||||
tw.WriteLine("{0},", 0);//impact weight 1
|
||||
tw.WriteLine("{0},", 0);//impact speed 2
|
||||
tw.WriteLine("{0},", 0);//impact weight 2
|
||||
tw.WriteLine("{0},", "km/h");//unit (m/s or km/h)
|
||||
//test start date
|
||||
tw.WriteLine("'{0:00}-{1:00}-{2:00},", test.InceptionDate.Year - 2000, test.InceptionDate.Month, test.InceptionDate.Day);
|
||||
//test start time
|
||||
tw.WriteLine("{0:00}:{1:00}:{2:00},", test.InceptionDate.Hour, test.InceptionDate.Minute, test.InceptionDate.Second);
|
||||
var testCompleteTime = (test.InceptionDate.AddSeconds(test.Modules[0].PreTriggerSeconds).AddSeconds(test.Modules[0].PostTriggerSeconds));
|
||||
//test complete time
|
||||
tw.WriteLine("{0:00}:{1:00}:{2:00},", testCompleteTime.Hour, testCompleteTime.Minute, testCompleteTime.Second);
|
||||
|
||||
|
||||
// Note this section is not completely implemented equivalent to TDM. Specifically, the dummy list passed in
|
||||
// the test description works, but the notion of barriers and groups and written with blank lines. TBD if THF or TEMA really need this and
|
||||
// how we would propigate that information.
|
||||
var userValue3 = test.Channels.FirstOrDefault().UserValue3;
|
||||
string[] dummyList;
|
||||
|
||||
if (!string.IsNullOrEmpty(userValue3))
|
||||
{
|
||||
dummyList = test.Channels.FirstOrDefault().UserValue3.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
else
|
||||
{
|
||||
dummyList = new string[0];
|
||||
}
|
||||
|
||||
var barrierCount = 0;
|
||||
var groupCount = 0;
|
||||
var dummyCount = dummyList.Count();
|
||||
|
||||
// this is only of importance if we have more than 4 groups
|
||||
// and if the others are full we're stuck
|
||||
if (groupCount > MAX_OLD_GROUP_LINES && !(dummyCount == MAX_DUMMY_DISPLAY && barrierCount == MAX_BARRIER_DISPLAY))
|
||||
{
|
||||
// we must prioritize dummies and barriers
|
||||
if (MAX_DEVICE_LINES - dummyCount - barrierCount >= groupCount)
|
||||
{
|
||||
// this will be a full house
|
||||
groupCount = MAX_DEVICE_LINES - dummyCount - barrierCount;
|
||||
WriteDeviceSection(test, DEV_TYPE_DUMMY, dummyCount, dummyCount, tw, dummyList);
|
||||
WriteDeviceSection(test, DEV_TYPE_BARRIER, barrierCount, barrierCount, tw, null);
|
||||
WriteDeviceSection(test, DEV_TYPE_GROUP, groupCount, groupCount, tw, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the only thing we know now is that groupCount > MAX_OLD_GROUP_LINES
|
||||
if (dummyCount == 0)
|
||||
{
|
||||
if (barrierCount == 0)
|
||||
{
|
||||
// we only have groups, easy
|
||||
WriteDeviceSection(test, DEV_TYPE_GROUP, MAX_DEVICE_LINES, groupCount, tw, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have barriers and groups
|
||||
var spaceAvail = MAX_DEVICE_LINES - barrierCount - groupCount;
|
||||
WriteDeviceSection(test, DEV_TYPE_BARRIER, barrierCount + spaceAvail, barrierCount, tw, null);
|
||||
WriteDeviceSection(test, DEV_TYPE_GROUP, groupCount, groupCount, tw, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (barrierCount == 0)
|
||||
{
|
||||
// we have dummies and groups
|
||||
var spaceAvail = MAX_DEVICE_LINES - dummyCount - groupCount;
|
||||
WriteDeviceSection(test, DEV_TYPE_DUMMY, dummyCount + spaceAvail, dummyCount, tw, null);
|
||||
WriteDeviceSection(test, DEV_TYPE_GROUP, groupCount, groupCount, tw, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have all three types
|
||||
var spaceAvail = MAX_DEVICE_LINES - dummyCount - barrierCount - groupCount;
|
||||
var firstSpace = spaceAvail / 2;
|
||||
WriteDeviceSection(test, DEV_TYPE_DUMMY, dummyCount + firstSpace, dummyCount, tw, dummyList);
|
||||
WriteDeviceSection(test, DEV_TYPE_BARRIER, barrierCount + spaceAvail - firstSpace, barrierCount, tw, null);
|
||||
WriteDeviceSection(test, DEV_TYPE_GROUP, groupCount, groupCount, tw, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is the normal case with less than 5 groups
|
||||
WriteDeviceSection(test, DEV_TYPE_DUMMY, MAX_DUMMY_DISPLAY, MAX_DUMMY_DISPLAY, tw, dummyList);
|
||||
WriteDeviceSection(test, DEV_TYPE_BARRIER, MAX_BARRIER_DISPLAY, MAX_BARRIER_DISPLAY, tw, null);
|
||||
WriteDeviceSection(test, DEV_TYPE_GROUP, MAX_OLD_GROUP_LINES, MAX_OLD_GROUP_LINES, tw, null);
|
||||
}
|
||||
|
||||
var TotalSamples = ulong.MaxValue;
|
||||
|
||||
//the lowest common start in samples from t0 that all modules have
|
||||
var minStart = double.MinValue;
|
||||
//the highest common end in samples from t0 that all modules have
|
||||
var maxEnd = double.MaxValue;
|
||||
|
||||
foreach (var module in test.Modules)
|
||||
{
|
||||
//Don't process Slice6DB modules that were created to store Temperature values from Arm checklist
|
||||
if (module.Channels.Count <= 0) continue;
|
||||
//TriggerSampleNumber = Math.Min(TriggerSampleNumber, module.TriggerSampleNumbers[0]);
|
||||
TotalSamples = Math.Min(TotalSamples, module.NumberOfSamples);
|
||||
//System.Diagnostics.Trace.Assert(module.TriggerSampleNumbers[0] >= module.StartRecordSampleNumber);
|
||||
double mStart = module.TriggerSampleNumbers[0] - module.StartRecordSampleNumber;
|
||||
minStart = Math.Max(minStart, mStart);
|
||||
var mEnd = module.NumberOfSamples - mStart;
|
||||
maxEnd = Math.Min(maxEnd, mEnd);
|
||||
}
|
||||
|
||||
if (preTriggerSamples < 0)
|
||||
{
|
||||
preTriggerSamples = 0;
|
||||
}
|
||||
else if (preTriggerSamples > (int)numSamples)
|
||||
{
|
||||
//All of the ROI is pre-trigger
|
||||
preTriggerSamples = (int)numSamples;
|
||||
}
|
||||
tw.WriteLine("{0},", preTriggerSamples);
|
||||
tw.WriteLine("{0},", (int)numSamples - preTriggerSamples);
|
||||
tw.WriteLine("{0},", numSamples);
|
||||
tw.WriteLine("{0},", subSampleInterval);
|
||||
tw.WriteLine("{0},", Math.Truncate(test.Modules[0].SampleRateHz / subSampleInterval));
|
||||
|
||||
var tomVoltageCount = 0;
|
||||
foreach (var currentChannel in test.Channels)
|
||||
{
|
||||
if (currentChannel is Test.Module.AnalogInputChannel analogChannel && analogChannel.IsSquibVoltage())
|
||||
{
|
||||
tomVoltageCount++;
|
||||
}
|
||||
}
|
||||
|
||||
tw.WriteLine("{0},", test.Channels.Count - tomVoltageCount);
|
||||
tw.WriteLine("{0},", test.Description);
|
||||
|
||||
}
|
||||
|
||||
private void WriteDeviceSection(Test test, char devType, int totalSize, int maxDevices, System.IO.TextWriter tw, string[] DeviceList)
|
||||
{
|
||||
var DeviceCount = 0;
|
||||
var channelCount = test.Channels.Count;
|
||||
|
||||
for (var Index = 0; Index < MAX_DEVICE_DISPLAY && Index < channelCount; Index++)
|
||||
{
|
||||
if (devType == DEV_TYPE_DUMMY)//if (TestPtr->DeviceList[Index].DeviceType == devType)
|
||||
{
|
||||
if (Index < DeviceList.Count() && !String.IsNullOrEmpty(DeviceList[Index]))
|
||||
{
|
||||
tw.Write(DeviceList[Index]);
|
||||
}
|
||||
|
||||
tw.WriteLine(",");
|
||||
DeviceCount++;
|
||||
}
|
||||
// make sure we don't do more than
|
||||
if (DeviceCount == maxDevices)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// pad until MAX_DUMMY_DISPLAY lines
|
||||
for (/*NOOP*/; DeviceCount < totalSize; DeviceCount++)
|
||||
{
|
||||
tw.WriteLine(",");
|
||||
//fprintf(fp, ",\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,434 @@
|
||||
using DTS.Common;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.Utils;
|
||||
using DTS.Serialization.IRIGCH10.Packets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10
|
||||
{
|
||||
/// <summary>
|
||||
/// this class is used to simplify parsing out CH10 data from a binary stream
|
||||
/// </summary>
|
||||
public class Chapter10File
|
||||
{
|
||||
/// <summary>
|
||||
/// used to hold transport stream headers as they are read
|
||||
/// </summary>
|
||||
private readonly List<ITransportStreamHeader> _transportHeaders = new List<ITransportStreamHeader>();
|
||||
/// <summary>
|
||||
/// returns all transport headers that were read, in order they were read
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ITransportStreamHeader[] GetTransportHeaders() { return _transportHeaders.ToArray(); }
|
||||
/// <summary>
|
||||
/// holds a list of packet headers as they are read
|
||||
/// </summary>
|
||||
private readonly List<IPacketHeader> _packets = new List<IPacketHeader>();
|
||||
/// <summary>
|
||||
/// returns all packet headers that were read, in the order they were read in
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IPacketHeader[] GetPacketHeaders() { return _packets.ToArray(); }
|
||||
/// <summary>
|
||||
/// holds any secondary time packets that were read
|
||||
/// </summary>
|
||||
private readonly List<ISecondaryTimeFormatHeader> _secondaryTimePackets = new List<ISecondaryTimeFormatHeader>();
|
||||
/// <summary>
|
||||
/// returns all secondary time headers in the order they were read in
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ISecondaryTimeFormatHeader[] GetSecondaryTimeHeaders() { return _secondaryTimePackets.ToArray(); }
|
||||
|
||||
/// <summary>
|
||||
/// lookup of a packet header that was read in as well as the start of that packet and end of that packet amongst
|
||||
/// all bytes in the file
|
||||
/// </summary>
|
||||
private readonly Dictionary<IPacketHeader, Tuple<long, long>> _packetToByteStartStop = new Dictionary<IPacketHeader, Tuple<long, long>>();
|
||||
|
||||
private readonly byte[] _bytes = null;
|
||||
/// <summary>
|
||||
/// returns all bytes for a packet (as apposed to just the bytes for the packet header)
|
||||
/// all bytes returned are in their own buffer, independent of bytes read in
|
||||
/// </summary>
|
||||
/// <param name="packet"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetBytesForPacket(IPacketHeader packet)
|
||||
{
|
||||
if (!_packetToByteStartStop.ContainsKey(packet)) { return null; }
|
||||
var tuple = _packetToByteStartStop[packet];
|
||||
var length = tuple.Item2 - tuple.Item1;
|
||||
var bytes = new byte[length];
|
||||
Buffer.BlockCopy(_bytes, (int)tuple.Item1, bytes, 0, (int)length);
|
||||
return bytes;
|
||||
}
|
||||
public int GoodPackets { get; private set; } = 0;
|
||||
public int RejectedPackets { get; private set; } = 0;
|
||||
/// <summary>
|
||||
/// adds a time packet 1 packet to the byte stream
|
||||
/// </summary>
|
||||
private static void InsertTimePacket1(BinaryWriter bw, int seconds, int nanoseconds, ref byte timeSequenceNumber,
|
||||
int startSeconds, int startNanoSeconds)
|
||||
{
|
||||
//time packet 1 must always start on a second boundary, so we need to calulate the nearest start second to our
|
||||
//actual start time, and all further packets also need to be on that boundary
|
||||
var time = PTP1588Timestamps.UnitTimeStampToDateTimeLocal((decimal)startSeconds, (decimal)startNanoSeconds).ToUniversalTime();
|
||||
var currentTime = PTP1588Timestamps.UnitTimeStampToDateTimeLocal((decimal)seconds, (decimal)nanoseconds).ToUniversalTime();
|
||||
|
||||
var newTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, currentTime.Hour, currentTime.Minute, currentTime.Second);
|
||||
var tickDelta = time.Ticks - newTime.Ticks;
|
||||
var newRTC = GetRTC(tickDelta);
|
||||
|
||||
var timePacket = new TimePacketFormat1(timeSequenceNumber, newTime, newRTC, nanoseconds, seconds);
|
||||
timeSequenceNumber++;
|
||||
bw.Write(timePacket.GetBytes());
|
||||
}
|
||||
/// <summary>
|
||||
/// describes a function to get the next Int16 ADC sample from a binary file
|
||||
/// </summary>
|
||||
/// <param name="channelIdx">the index of the channel among channels in the test</param>
|
||||
/// <returns></returns>
|
||||
public delegate short GetNextSampleDelegate(int channelIdx);
|
||||
/// <summary>
|
||||
/// returns the number of samples for the channel
|
||||
/// </summary>
|
||||
/// <param name="channelIndex">the index of the channel among channels in the test</param>
|
||||
/// <returns></returns>
|
||||
public delegate long GetChannelLengthDelegate(int channelIndex);
|
||||
|
||||
/// <summary>
|
||||
/// writes an output PCM export file
|
||||
/// </summary>
|
||||
public static void WriteFilePCM(string tmats, GetNextSampleDelegate getNextSample,
|
||||
GetChannelLengthDelegate getChannelLength,
|
||||
int totalChannels,
|
||||
int nanoseconds, int seconds, double sampleRate,
|
||||
bool includeSecondaryHeader,
|
||||
string fileName,
|
||||
TickEventHandler tickEventHandler,
|
||||
object tickObject)
|
||||
{
|
||||
var startNanoSeconds = nanoseconds;
|
||||
var startSeconds = seconds;
|
||||
if (System.IO.File.Exists(fileName))
|
||||
{
|
||||
FileUtils.DeleteFileOrMove(fileName, APILogger.Log);
|
||||
}
|
||||
using (var ms = new FileStream(fileName, FileMode.OpenOrCreate))
|
||||
{
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
//simulate writing the transport bytes ... not needed for ch10 file though ...
|
||||
//first packet should be tmats
|
||||
var tmatsPacket = new TMATSPacket(nanoseconds, seconds, tmats, includeSecondaryHeader);
|
||||
bw.Write(tmatsPacket.GetBytes());
|
||||
var currentSample = 0L;
|
||||
byte sequenceNumber = 0x01;
|
||||
byte timeSequenceNumber = 0x01;
|
||||
var lastSecondTransmitted = 0;
|
||||
if (!includeSecondaryHeader)
|
||||
{
|
||||
//insert first time packet at time second 1
|
||||
InsertTimePacket1(bw, seconds, nanoseconds, ref timeSequenceNumber, startSeconds, startNanoSeconds);
|
||||
lastSecondTransmitted = seconds;
|
||||
}
|
||||
|
||||
var channel0Length = getChannelLength(0);
|
||||
while (currentSample < channel0Length)
|
||||
{
|
||||
var newRTC = GetRTC(currentSample, sampleRate);
|
||||
if (includeSecondaryHeader)
|
||||
{
|
||||
var timePacket = new TimePacketFormat2(timeSequenceNumber, false, nanoseconds, seconds, newRTC,
|
||||
includeSecondaryHeader);
|
||||
|
||||
var time = PTP1588Timestamps.UnitTimeStampToDateTimeLocal((decimal)seconds, (decimal)nanoseconds).ToUniversalTime();
|
||||
|
||||
timeSequenceNumber++;
|
||||
bw.Write(timePacket.GetBytes());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seconds > lastSecondTransmitted)
|
||||
{
|
||||
lastSecondTransmitted = seconds;
|
||||
InsertTimePacket1(bw, seconds, nanoseconds, ref timeSequenceNumber, startSeconds, startNanoSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
var pcmPacket = GetPcmPacket(currentSample, getNextSample, channel0Length, totalChannels, nanoseconds, seconds, sampleRate, out var samplesProcessed,
|
||||
sequenceNumber, includeSecondaryHeader);
|
||||
bw.Write(pcmPacket.GetBytes());
|
||||
currentSample += samplesProcessed;
|
||||
sequenceNumber++;
|
||||
var elapsedNanoSeconds = samplesProcessed / (decimal)sampleRate * Constants.NANOS_PER_SECOND;
|
||||
|
||||
var newNanos = nanoseconds + elapsedNanoSeconds;
|
||||
if (newNanos > Constants.NANOS_PER_SECOND)
|
||||
{
|
||||
while (newNanos >= Constants.NANOS_PER_SECOND)
|
||||
{
|
||||
seconds++;
|
||||
newNanos -= Constants.NANOS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
nanoseconds = Convert.ToInt32(Math.Truncate(newNanos));
|
||||
tickEventHandler?.Invoke(tickObject, 50D + 50D * currentSample / channel0Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteFileAnalog(string tmats, GetNextSampleDelegate getNextSample,
|
||||
GetChannelLengthDelegate getChannelLength,
|
||||
int totalChannels,
|
||||
int nanoseconds, int seconds, double sampleRate,
|
||||
bool includeSecondaryHeader,
|
||||
string fileName,
|
||||
TickEventHandler tickEventHandler,
|
||||
object tickObject)
|
||||
{
|
||||
var startNanoSeconds = nanoseconds;
|
||||
var startSeconds = seconds;
|
||||
if (System.IO.File.Exists(fileName))
|
||||
{
|
||||
FileUtils.DeleteFileOrMove(fileName, APILogger.Log);
|
||||
}
|
||||
using (var ms = new FileStream(fileName, FileMode.OpenOrCreate))
|
||||
{
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
//simulate writing the transport bytes ... not needed for ch10 file though ...
|
||||
//first packet should be tmats
|
||||
var tmatsPacket = new TMATSPacket(nanoseconds, seconds, tmats, includeSecondaryHeader);
|
||||
bw.Write(tmatsPacket.GetBytes());
|
||||
var currentSample = 0L;
|
||||
byte sequenceNumber = 0x01;
|
||||
byte timeSequenceNumber = 0x01;
|
||||
var lastSecondTransmitted = 0;
|
||||
if (!includeSecondaryHeader)
|
||||
{
|
||||
//insert first time packet at time second 1
|
||||
InsertTimePacket1(bw, seconds, nanoseconds, ref timeSequenceNumber, startSeconds, startNanoSeconds);
|
||||
lastSecondTransmitted = seconds;
|
||||
}
|
||||
|
||||
var channel0Length = getChannelLength(0);
|
||||
while (currentSample < channel0Length)
|
||||
{
|
||||
var newRTC = GetRTC(currentSample, sampleRate);
|
||||
if (includeSecondaryHeader)
|
||||
{
|
||||
var timePacket = new TimePacketFormat2(timeSequenceNumber, false, nanoseconds, seconds, newRTC,
|
||||
includeSecondaryHeader);
|
||||
|
||||
var time = PTP1588Timestamps.UnitTimeStampToDateTimeLocal((decimal)seconds, (decimal)nanoseconds).ToUniversalTime();
|
||||
var newTime = new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second);
|
||||
|
||||
timeSequenceNumber++;
|
||||
bw.Write(timePacket.GetBytes());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seconds > lastSecondTransmitted)
|
||||
{
|
||||
lastSecondTransmitted = seconds;
|
||||
InsertTimePacket1(bw, seconds, nanoseconds, ref timeSequenceNumber, startSeconds, startNanoSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
var analogPacket = GetAnalogPacket(currentSample, getNextSample, channel0Length, totalChannels, nanoseconds, seconds, sampleRate, out var samplesProcessed,
|
||||
sequenceNumber, includeSecondaryHeader);
|
||||
bw.Write(analogPacket.GetBytes());
|
||||
currentSample += samplesProcessed;
|
||||
sequenceNumber++;
|
||||
var elapsedNanoSeconds = samplesProcessed / (decimal)sampleRate * Constants.NANOS_PER_SECOND;
|
||||
|
||||
var newNanos = nanoseconds + elapsedNanoSeconds;
|
||||
if (newNanos > Constants.NANOS_PER_SECOND)
|
||||
{
|
||||
while (newNanos >= Constants.NANOS_PER_SECOND)
|
||||
{
|
||||
seconds++;
|
||||
newNanos -= Constants.NANOS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
nanoseconds = Convert.ToInt32(Math.Truncate(newNanos));
|
||||
tickEventHandler?.Invoke(tickObject, 50D + 50D * currentSample / channel0Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// returns a PCM data packet with the next samples (targetting 100ms of data)
|
||||
/// </summary>
|
||||
private static PCMDataPacket GetPcmPacket(long currentSample, GetNextSampleDelegate getNextSample,
|
||||
long channelLength, int totalChannels, int nanoseconds,
|
||||
int seconds, double sampleRate, out long samplesProcessed, byte sequenceNumber, bool includeSecondaryHeader)
|
||||
{
|
||||
var newRTC = GetRTC(currentSample, sampleRate);
|
||||
|
||||
var numSamples = channelLength;
|
||||
numSamples -= currentSample;
|
||||
|
||||
//we should target 100ms of data per packet, sample rate is in seconds
|
||||
//so divide by 10 to get number of samples per 100ms
|
||||
var numSamplesPerPacket = sampleRate / 10;
|
||||
//if we want more samples than are available, just truncate down to max available
|
||||
if (numSamples > numSamplesPerPacket)
|
||||
{
|
||||
numSamples = Convert.ToInt64(numSamplesPerPacket);
|
||||
}
|
||||
var pcmPacket = new PCMDataPacket(nanoseconds, seconds,
|
||||
getNextSample, totalChannels, channelLength, newRTC, numSamples, currentSample, sequenceNumber, 3,
|
||||
includeSecondaryHeader);
|
||||
|
||||
samplesProcessed = numSamples;
|
||||
return pcmPacket;
|
||||
}
|
||||
private static AnalogDataFormat1Packet GetAnalogPacket(long currentSample, GetNextSampleDelegate getNextSample,
|
||||
long channelLength, int totalChannels, int nanoseconds,
|
||||
int seconds, double sampleRate, out long samplesProcessed, byte sequenceNumber, bool includeSecondaryHeader)
|
||||
{
|
||||
var newRTC = GetRTC(currentSample, sampleRate);
|
||||
|
||||
var numSamples = channelLength;
|
||||
numSamples -= currentSample;
|
||||
|
||||
//we should target 100ms of data per packet
|
||||
var numSamplesPerPacket = Math.Floor(sampleRate / 10);
|
||||
|
||||
if (numSamples > numSamplesPerPacket)
|
||||
{
|
||||
numSamples = Convert.ToInt64(numSamplesPerPacket);
|
||||
}
|
||||
|
||||
var analogPacket = new AnalogDataFormat1Packet(nanoseconds, seconds,
|
||||
getNextSample, totalChannels, channelLength, newRTC, numSamples, currentSample, sequenceNumber, 3,
|
||||
includeSecondaryHeader);
|
||||
|
||||
samplesProcessed = numSamples;
|
||||
return analogPacket;
|
||||
}
|
||||
|
||||
//for convenience just store relative time counter 10MHZ conversion factor
|
||||
private const int RTC_PER_SECOND = 10000000;
|
||||
private static long GetRTC(long currentSample, double sampleRate)
|
||||
{
|
||||
var secondsPassed = currentSample / sampleRate;
|
||||
return AbstractDataPacket.BASE_RTC + Convert.ToInt64(secondsPassed * RTC_PER_SECOND);
|
||||
}
|
||||
|
||||
private static long GetRTC(long tickDelta)
|
||||
{
|
||||
var seconds = (double)tickDelta / TimeSpan.TicksPerSecond;
|
||||
return AbstractDataPacket.BASE_RTC - Convert.ToInt64(seconds * RTC_PER_SECOND);
|
||||
}
|
||||
/// <summary>
|
||||
/// parses out all packets from array of bytes
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
public Chapter10File(byte[] bytes)
|
||||
{
|
||||
_bytes = new byte[bytes.Length];
|
||||
Buffer.BlockCopy(bytes, 0, _bytes, 0, bytes.Length);
|
||||
var currentByteIndex = 0L;
|
||||
var badPackets = 0;
|
||||
var goodPackets = 0;
|
||||
while (currentByteIndex < (bytes.Length - PacketHeader.PACKET_HEADER_LENGTH))
|
||||
{
|
||||
try
|
||||
{
|
||||
currentByteIndex = ReadTransportHeader(bytes, currentByteIndex, out var transportHeader);
|
||||
var startOfChapter10Packet = currentByteIndex;
|
||||
currentByteIndex = ReadChapter10PacketHeader(bytes, currentByteIndex, out var packetHeader);
|
||||
if (packetHeader.PacketSyncPattern != PacketHeader.EXPECTED_SYNC_PATTERN || packetHeader.CheckSum != packetHeader.ComputeCheckSum())
|
||||
{
|
||||
badPackets++;
|
||||
//this packet is invalid, so we need to skip ahead
|
||||
//skip until we see the next sync pattern, then backstep to the start of the transport bytes, then continue on
|
||||
currentByteIndex = GetIndexOfNextPacket(bytes, startOfChapter10Packet);
|
||||
continue;
|
||||
}
|
||||
_transportHeaders.Add(transportHeader);
|
||||
if (packetHeader.SecondaryHeaderPresent)
|
||||
{
|
||||
ReadChapter10SecondHeaderTimeFormat(bytes, startOfChapter10Packet + PacketHeader.PACKET_HEADER_LENGTH, out var secondaryTimeHeader);
|
||||
_secondaryTimePackets.Add(secondaryTimeHeader);
|
||||
}
|
||||
_packets.Add(packetHeader);
|
||||
|
||||
_packetToByteStartStop[packetHeader] = new Tuple<long, long>(startOfChapter10Packet, currentByteIndex);
|
||||
goodPackets++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Hit exception processing file at byte: {currentByteIndex}, {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
GoodPackets = goodPackets;
|
||||
RejectedPackets = badPackets;
|
||||
}
|
||||
/// <summary>
|
||||
/// determines the next valid packet starting location after the provided starting spot
|
||||
/// this is used to skip over bad data to the next good packet
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <returns></returns>
|
||||
public static long GetIndexOfNextPacket(byte[] bytes, long startIndex)
|
||||
{
|
||||
for (var i = startIndex; i < bytes.Length - 1; i++)
|
||||
{
|
||||
if (BitConverter.ToUInt16(bytes, (int)i) == PacketHeader.EXPECTED_SYNC_PATTERN)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
//if we got here there are no more valid packets, you are done.
|
||||
return bytes.Length;
|
||||
}
|
||||
/// <summary>
|
||||
/// reads a secondary time header from provided bytes and starting spot
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="secondaryTimeFormat"></param>
|
||||
private void ReadChapter10SecondHeaderTimeFormat(byte[] bytes, long start, out ISecondaryTimeFormatHeader secondaryTimeFormat)
|
||||
{
|
||||
var headerBytes = new byte[SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH];
|
||||
Array.Copy(bytes, start, headerBytes, 0, SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH);
|
||||
secondaryTimeFormat = new SecondaryTimeFormatHeader(headerBytes);
|
||||
}
|
||||
/// <summary>
|
||||
/// reads a transport header from provided bytes and starting spot
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <param name="transportHeader"></param>
|
||||
/// <returns></returns>
|
||||
private long ReadTransportHeader(byte[] bytes, long startIndex, out TransportStreamHeader transportHeader)
|
||||
{
|
||||
var transportHeaderBytes = new byte[4];
|
||||
Array.Copy(bytes, startIndex, transportHeaderBytes, 0, 4);
|
||||
transportHeader = new TransportStreamHeader(transportHeaderBytes);
|
||||
return startIndex + 4L;
|
||||
}
|
||||
/// <summary>
|
||||
/// reads a Packet from stream of bytes at given starting spot
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <param name="packetHeader"></param>
|
||||
/// <returns></returns>
|
||||
public static long ReadChapter10PacketHeader(byte[] bytes, long startIndex, out IPacketHeader packetHeader)
|
||||
{
|
||||
var headerBytes = new byte[PacketHeader.PACKET_HEADER_LENGTH];
|
||||
Array.Copy(bytes, startIndex, headerBytes, 0, PacketHeader.PACKET_HEADER_LENGTH);
|
||||
packetHeader = new PacketHeader(headerBytes);
|
||||
return startIndex + packetHeader.PacketLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Test.Module.IConvertable.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
// *** see Test.Module.cs ***
|
||||
public partial class Module
|
||||
{
|
||||
/// <summary>
|
||||
/// An object that expresses this interface can convert itself to and from a
|
||||
/// <see cref="DTS.Serialization.Test.Module"/> object.
|
||||
/// </summary>
|
||||
///
|
||||
public interface IConvertable
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert this object to a <see cref="DTS.Serialization.Test.Module"/>.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="parentTest">
|
||||
/// The <see cref="DTS.Serialization.ParentTest"/> that contains the afixed object.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="DTS.Serialization.Test.Module"/> equivalent of this object.
|
||||
/// </returns>
|
||||
///
|
||||
Module ToDtsSerializationTestModule(Test parentTest);
|
||||
|
||||
/// <summary>
|
||||
/// Initialize this object using the specified <see cref="DTS.Serialization.Test.Module"/>.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="test">
|
||||
/// The <see cref="DTS.Serialization.Test.Module"/> with which this object will be initialized from.
|
||||
/// </param>
|
||||
///
|
||||
void FromDtsSerializationTestModule(Module testModule, ReportErrors reportErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AAFilterCutoffDescription_Description" xml:space="preserve">
|
||||
<value>What freuqncy content the user can expect; Include notes of AAfilters applied and any applicable reasoning</value>
|
||||
</data>
|
||||
<data name="AAFilterCutoffDescription_Title" xml:space="preserve">
|
||||
<value>AA Filter Cutoff description</value>
|
||||
</data>
|
||||
<data name="BitResolution_Description" xml:space="preserve">
|
||||
<value>The resolution settings for the test in engineering units per bit</value>
|
||||
</data>
|
||||
<data name="BitResolution_Title" xml:space="preserve">
|
||||
<value>Bit Resolution(Units per bit)</value>
|
||||
</data>
|
||||
<data name="ChannelErrors_Description" xml:space="preserve">
|
||||
<value>Yes or No depending if channel errors are noted in the data</value>
|
||||
</data>
|
||||
<data name="ChannelErrors_Title" xml:space="preserve">
|
||||
<value>Channel Errors (Y or N)</value>
|
||||
</data>
|
||||
<data name="DataType_Description" xml:space="preserve">
|
||||
<value>The type of data milestone this file supports</value>
|
||||
</data>
|
||||
<data name="DataType_Title" xml:space="preserve">
|
||||
<value>Data Type (Raw, Converted, or Processed)</value>
|
||||
</data>
|
||||
<data name="DigitalFilterType_Description" xml:space="preserve">
|
||||
<value>The digital filter applied and the cutoff in Hz</value>
|
||||
</data>
|
||||
<data name="DigitalFilterType_Title" xml:space="preserve">
|
||||
<value>Digital Filter Type/Cutoff (Hz)</value>
|
||||
</data>
|
||||
<data name="EngineeringUnits_Description" xml:space="preserve">
|
||||
<value>Engineering units depicted in Converted and Processed Data sets; Voltages for Raw data</value>
|
||||
</data>
|
||||
<data name="EngineeringUnits_Title" xml:space="preserve">
|
||||
<value>Engineering Units</value>
|
||||
</data>
|
||||
<data name="LabName_Description" xml:space="preserve">
|
||||
<value>Include the name of the University, Institution, and/or Lab that conducted the test</value>
|
||||
</data>
|
||||
<data name="LabName_Title" xml:space="preserve">
|
||||
<value>Lab Name</value>
|
||||
</data>
|
||||
<data name="Notes_Description" xml:space="preserve">
|
||||
<value>Any notes or descriptions useful in supporting data file analysis</value>
|
||||
</data>
|
||||
<data name="Notes_Title" xml:space="preserve">
|
||||
<value>Notes</value>
|
||||
</data>
|
||||
<data name="POCName_Description" xml:space="preserve">
|
||||
<value>Include the name of the test Point of Contact</value>
|
||||
</data>
|
||||
<data name="POCName_Title" xml:space="preserve">
|
||||
<value>POC Name</value>
|
||||
</data>
|
||||
<data name="POCPhoneAndEmail_Description" xml:space="preserve">
|
||||
<value>Include applicable lab phone number, email, etc. for contacting the POC</value>
|
||||
</data>
|
||||
<data name="POCPhoneAndEmail_Title" xml:space="preserve">
|
||||
<value>POC phone and email</value>
|
||||
</data>
|
||||
<data name="SamplingRate_Description" xml:space="preserve">
|
||||
<value>The data sampling rate in Hz</value>
|
||||
</data>
|
||||
<data name="SamplingRate_Title" xml:space="preserve">
|
||||
<value>Sampling Rate (Hz)</value>
|
||||
</data>
|
||||
<data name="SensorAxis_Description" xml:space="preserve">
|
||||
<value>The direction of the sensor axis; include whether direction is global or local</value>
|
||||
</data>
|
||||
<data name="SensorAxis_Title" xml:space="preserve">
|
||||
<value>Sensor Axis (direction)</value>
|
||||
</data>
|
||||
<data name="SensorLocation_Description" xml:space="preserve">
|
||||
<value>Location of the sensor, using body region codes</value>
|
||||
</data>
|
||||
<data name="SensorLocation_Title" xml:space="preserve">
|
||||
<value>Sensor Location</value>
|
||||
</data>
|
||||
<data name="SensorMakeModelSerial_Description" xml:space="preserve">
|
||||
<value>The brand name of the sensor used with the model name and serial number</value>
|
||||
</data>
|
||||
<data name="SensorMakeModelSerial_Title" xml:space="preserve">
|
||||
<value>Sensor Make Model Serial</value>
|
||||
</data>
|
||||
<data name="SensorMountType_Description" xml:space="preserve">
|
||||
<value>If Applicable include the type of sensor mount: LOFFI, BOBKAT, glued, fixed, other</value>
|
||||
</data>
|
||||
<data name="SensorMountType_Title" xml:space="preserve">
|
||||
<value>Sensor Mount Type</value>
|
||||
</data>
|
||||
<data name="TestDate_Description" xml:space="preserve">
|
||||
<value>Date the test was conducted</value>
|
||||
</data>
|
||||
<data name="TestDate_Title" xml:space="preserve">
|
||||
<value>Test Date</value>
|
||||
</data>
|
||||
<data name="TestNumber_Description" xml:space="preserve">
|
||||
<value>Test Number that correlates with filename and README file test numbers. This is a lab generated test number that sequences the series of tests for a specific surrogate (PHMS or HIII)</value>
|
||||
</data>
|
||||
<data name="TestNumber_Title" xml:space="preserve">
|
||||
<value>Test Number</value>
|
||||
</data>
|
||||
<data name="TestObject_Description" xml:space="preserve">
|
||||
<value>Description of the objects being tested. PHMS with specimen ID, type of HIII, combination, or other</value>
|
||||
</data>
|
||||
<data name="TestObject_Title" xml:space="preserve">
|
||||
<value>Test Object (HIII, PMHS, combo, etc.)</value>
|
||||
</data>
|
||||
<data name="TestTime_Description" xml:space="preserve">
|
||||
<value>Local lab time when the test was conducted</value>
|
||||
</data>
|
||||
<data name="TestTime_Title" xml:space="preserve">
|
||||
<value>Test Time</value>
|
||||
</data>
|
||||
<data name="TestType_Description" xml:space="preserve">
|
||||
<value>Short text description of the type of test conducted</value>
|
||||
</data>
|
||||
<data name="TestType_Title" xml:space="preserve">
|
||||
<value>Test Type (sled, blast, drop, etc.)</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,260 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10.Packets
|
||||
{
|
||||
public class PCMDataPacket : AbstractDataPacket, IDataPacket
|
||||
{
|
||||
//Bit 30 Intra packet headers
|
||||
public bool HasIntraPacketHeader
|
||||
{
|
||||
get => GetCSDWBit(30);
|
||||
set => SetCSDWBit(30, value);
|
||||
}
|
||||
//Bit29 Major Frame Indicator
|
||||
//not applicable in throughput mode
|
||||
public bool IsMajorFrame
|
||||
{
|
||||
get => GetCSDWBit(29);
|
||||
set => SetCSDWBit(29, value);
|
||||
}
|
||||
//Bit28 IsMinorFrame
|
||||
//not applicable in throughput mode
|
||||
public bool IsMinorFrame
|
||||
{
|
||||
get => GetCSDWBit(28);
|
||||
set => SetCSDWBit(28, value);
|
||||
}
|
||||
public enum MinorFrameStatus
|
||||
{
|
||||
Reserved0 = 0, //00
|
||||
Reserved1 = 1, //01
|
||||
MinorFrameCheck = 2, //10
|
||||
MinorFrameLock = 3 //11
|
||||
}
|
||||
public enum MajorFrameStatus
|
||||
{
|
||||
MajorFrameNotLocked = 0, //00
|
||||
Reserved1 = 1, //01
|
||||
MajorFrameCheck = 2, //10
|
||||
MajorFrameLock = 3 //11
|
||||
}
|
||||
//bits 27-24
|
||||
//not applicable for throughput mode
|
||||
public MinorFrameStatus LockStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
var csdw = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var bits = new BitArray(csdw);
|
||||
return (MinorFrameStatus)Utils.Utils.BitArrayToInt32(bits, 24, 27);
|
||||
}
|
||||
set
|
||||
{
|
||||
var iValue = (int)value;
|
||||
var csdw = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||||
var bits = new BitArray(csdw);
|
||||
Utils.Utils.SetBits(bits, (uint)iValue, 24, 27);
|
||||
var ret = new Byte[sizeof(uint)];
|
||||
bits.CopyTo(ret, 0);
|
||||
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||||
}
|
||||
}
|
||||
//bit 21
|
||||
public bool Is32BitAligned
|
||||
{
|
||||
get => GetCSDWBit(21);
|
||||
set => SetCSDWBit(21, value);
|
||||
}
|
||||
//bit 20
|
||||
public bool IsThroughputMode
|
||||
{
|
||||
get => GetCSDWBit(20);
|
||||
set => SetCSDWBit(20, value);
|
||||
}
|
||||
|
||||
//bit 19 packed mode
|
||||
public bool IsPackedMode
|
||||
{
|
||||
get => GetCSDWBit(19);
|
||||
set => SetCSDWBit(19, value);
|
||||
}
|
||||
//bit 18 unpacked mode
|
||||
public bool IsUnpackedMode
|
||||
{
|
||||
get => GetCSDWBit(18);
|
||||
set => SetCSDWBit(18, value);
|
||||
}
|
||||
/// <summary>
|
||||
/// it seems the EMC ch10 validation tool only supports CH10 106v5, so use this header value for the analog packet when in this mode
|
||||
/// whether to include secondary time header or not
|
||||
/// 33199 Add Time format 1 as an export option for CH 10 export
|
||||
/// </summary>
|
||||
private const byte DATA_VERSION = 0x06;
|
||||
public PCMDataPacket(int nanoseconds, int seconds,
|
||||
Chapter10File.GetNextSampleDelegate getNextSample, int totalChannels, long channelLength, long rtc, long numSamples, long currentSample, byte sequenceNumber,
|
||||
ushort channelId, bool includeSecondaryHeader) : base(Enums.DataFileDataTypes.PCMDataFormat1, includeSecondaryHeader)
|
||||
{
|
||||
HasIntraPacketHeader = includeSecondaryHeader;
|
||||
IsMajorFrame = false;
|
||||
IsMinorFrame = false;
|
||||
LockStatus = MinorFrameStatus.Reserved0;
|
||||
IsThroughputMode = true;
|
||||
Is32BitAligned = false;
|
||||
IsPackedMode = false;
|
||||
IsUnpackedMode = false;
|
||||
|
||||
//4 bytes for CSDW, then 4 bytes for a PCM FRAMESYNC??? this isn't in the spec but f/w is using it
|
||||
var dataLength = Convert.ToUInt32(4 + 2 * totalChannels * numSamples + 4*numSamples);
|
||||
|
||||
var offset = CommonHeaderWork(channelId, DATA_VERSION, sequenceNumber, rtc, dataLength, nanoseconds, seconds);
|
||||
for (var sampleIdx = 0; sampleIdx < numSamples; sampleIdx++)
|
||||
{
|
||||
Buffer.BlockCopy(new byte[] { 0x6B, 0xFE, 0x40, 0x28 }, 0, _dataBytes, offset, 4);
|
||||
offset += 4;
|
||||
for (var chIdx = 0; chIdx < totalChannels; chIdx++)
|
||||
{
|
||||
var signed = getNextSample(chIdx);
|
||||
var unsigned = (ushort)(((signed - 0x8000 & 0x00FF) << 8) | ((signed - 0x8000 >> 8) & 0x00FF));
|
||||
var bytes = BitConverter.GetBytes(unsigned).Reverse().ToArray();
|
||||
Buffer.BlockCopy(bytes, 0, _dataBytes, offset, 2);
|
||||
offset += 2;
|
||||
}
|
||||
currentSample++;
|
||||
}
|
||||
}
|
||||
public PCMDataPacket() : base(Enums.DataFileDataTypes.PCMDataFormat1, true)
|
||||
{
|
||||
}
|
||||
public PCMDataPacket(byte[] bytes) : base (bytes)
|
||||
{
|
||||
|
||||
}
|
||||
public PCMDataPacket(bool _) : base(UDP_DATA)
|
||||
{
|
||||
}
|
||||
|
||||
private static readonly byte[] UDP_DATA = { 0x25, 0xeb, 0x03, 0x00, 0x98, 0x05, 0x00, 0x00, 0x74, 0x05, 0x00, 0x00,
|
||||
0x06, 0x65, 0xc4, 0x09, 0x21, 0xe5, 0x5d, 0xed, 0x07, 0x00, 0x83, 0x37, 0x42, 0x89, 0x77, 0x2a,
|
||||
0x4c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00, 0x10, 0x00, 0x6b, 0xfe, 0x40, 0x28,
|
||||
0x04, 0x80, 0xe3, 0x7f, 0xcf, 0x7f, 0xe1, 0x7f, 0xee, 0x7f, 0xea, 0x7f, 0x6b, 0xfe, 0x40, 0x28,
|
||||
0x07, 0x80, 0xe7, 0x7f, 0xcf, 0x7f, 0xe7, 0x7f, 0xf3, 0x7f, 0xee, 0x7f, 0x6b, 0xfe, 0x40, 0x28,
|
||||
0x04, 0x80, 0xe5, 0x7f, 0xcd, 0x7f, 0xe2, 0x7f, 0xf1, 0x7f, 0xed, 0x7f, 0x6b, 0xfe, 0x40, 0x28,
|
||||
0x05, 0x80, 0xe9, 0x7f, 0xcd, 0x7f, 0xe2, 0x7f, 0xf1, 0x7f, 0xeb, 0x7f, 0x6b, 0xfe, 0x40, 0x28,
|
||||
0x07, 0x80, 0xe9, 0x7f, 0xcd, 0x7f, 0xec, 0x7f, 0xf3, 0x7f, 0xf1, 0x7f, 0x6b, 0xfe, 0x40, 0x28,
|
||||
0x06, 0x80, 0xe3, 0x7f, 0xce, 0x7f, 0xe6, 0x7f, 0xee, 0x7f, 0xee, 0x7f, 0x6b, 0xfe, 0x40, 0x28,
|
||||
0x02, 0x80, 0xe1, 0x7f, 0xc9, 0x7f, 0xdc, 0x7f, 0xec, 0x7f, 0xea, 0x7f, 0x6b, 0xfe, 0x40, 0x28,
|
||||
0x04, 0x80, 0xe7, 0x7f, 0xc5, 0x7f, 0xe7, 0x7f, 0xef, 0x7f, 0xed, 0x7f, 0x6b, 0xfe, 0x40, 0x28,
|
||||
0x05, 0x80, 0xed, 0x7f, 0xca, 0x7f, 0xe3, 0x7f, 0xf0, 0x7f, 0xf2, 0x7f, 0x6b, 0xfe, 0x40, 0x28,
|
||||
0x04, 0x80, 0xe5, 0x7f, 0xca, 0x7f, 0xe2, 0x7f, 0xec, 0x7f, 0xec, 0x7f, 0x6b, 0xfe, 0x40, 0x28,
|
||||
0x04, 0x80, 0xe6, 0x7f, 0xcc, 0x7f, 0xe5, 0x7f, 0xec, 0x7f, 0xed, 0x7f, 0x6b, 0xfe, 0x40, 0x28 };/*,
|
||||
0x06, 80, e7, 7f, cc, 7f, e6, 7f, f0, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, e7, 7f, d2, 7f, e4, 7f, f0, 7f, f2, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, eb, 7f, cc, 7f, e7, 7f, e9, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x03, 80, e7, 7f, d1, 7f, ed, 7f, ef, 7f, f1, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, ec, 7f, d7, 7f, e9, 7f, f2, 7f, ee, 7f, 6b, fe, 40, 28,
|
||||
0x07, 80, ed, 7f, cf, 7f, e7, 7f, f1, 7f, f0, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, e7, 7f, d0, 7f, e6, 7f, f0, 7f, f0, 7f, 6b, fe, 40, 28,
|
||||
0x03, 80, e7, 7f, cf, 7f, e2, 7f, f0, 7f, ee, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, e6, 7f, c8, 7f, dc, 7f, ef, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, ec, 7f, cc, 7f, e4, 7f, f2, 7f, f0, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, eb, 7f, c9, 7f, e8, 7f, f1, 7f, ec, 7f, 6b, fe, 40, 28,
|
||||
0x02, 80, e9, 7f, c6, 7f, e6, 7f, ed, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x03, 80, e1, 7f, c9, 7f, e2, 7f, e9, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0xff, 7f, e2, 7f, c8, 7f, de, 7f, ea, 7f, eb, 7f, 6b, fe, 40, 28,
|
||||
0x03, 80, e6, 7f, ca, 7f, df, 7f, f0, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x00, 80, e7, 7f, cb, 7f, e2, 7f, f0, 7f, ec, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, e7, 7f, d1, 7f, df, 7f, ef, 7f, f0, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, eb, 7f, d0, 7f, e5, 7f, ed, 7f, f0, 7f, 6b, fe, 40, 28,
|
||||
0x07, 80, e9, 7f, d3, 7f, ee, 7f, ef, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, eb, 7f, ca, 7f, e1, 7f, ef, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, e9, 7f, d0, 7f, e6, 7f, f2, 7f, f3, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, e3, 7f, d2, 7f, e6, 7f, f2, 7f, f1, 7f, 6b, fe, 40, 28,
|
||||
0x05, 80, ed, 7f, cf, 7f, e9, 7f, ed, 7f, f5, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, ed, 7f, d0, 7f, e6, 7f, ed, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, e8, 7f, cf, 7f, ec, 7f, ed, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, ea, 7f, cc, 7f, e8, 7f, ec, 7f, ec, 7f, 6b, fe, 40, 28,
|
||||
0x00, 80, eb, 7f, c9, 7f, e5, 7f, ef, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x03, 80, de, 7f, ce, 7f, e7, 7f, eb, 7f, f1, 7f, 6b, fe, 40, 28,
|
||||
0x05, 80, e1, 7f, c6, 7f, e0, 7f, f0, 7f, ec, 7f, 6b, fe, 40, 28,
|
||||
0x01, 80, df, 7f, c7, 7f, df, 7f, e9, 7f, e9, 7f, 6b, fe, 40, 28,
|
||||
0x05, 80, e4, 7f, cd, 7f, e0, 7f, ea, 7f, eb, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, ea, 7f, ca, 7f, de, 7f, ed, 7f, ee, 7f, 6b, fe, 40, 28,
|
||||
0x03, 80, e7, 7f, c9, 7f, de, 7f, ef, 7f, ec, 7f, 6b, fe, 40, 28,
|
||||
0x05, 80, e5, 7f, c9, 7f, df, 7f, ed, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, e3, 7f, d0, 7f, e2, 7f, ed, 7f, f0, 7f, 6b, fe, 40, 28,
|
||||
0x02, 80, e3, 7f, ce, 7f, e0, 7f, ed, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, f0, 7f, cc, 7f, e3, 7f, ee, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, ed, 7f, d0, 7f, e4, 7f, f3, 7f, ea, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, eb, 7f, c8, 7f, e6, 7f, ec, 7f, ea, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, e9, 7f, ce, 7f, e3, 7f, ee, 7f, f0, 7f, 6b, fe, 40, 28,
|
||||
0x09, 80, e9, 7f, d1, 7f, e5, 7f, ea, 7f, eb, 7f, 6b, fe, 40, 28,
|
||||
0x07, 80, eb, 7f, ce, 7f, e6, 7f, f0, 7f, ec, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, ea, 7f, ce, 7f, e4, 7f, eb, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x08, 80, ed, 7f, ce, 7f, e8, 7f, ef, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x08, 80, ee, 7f, ce, 7f, e7, 7f, ef, 7f, ee, 7f, 6b, fe, 40, 28,
|
||||
0x05, 80, e3, 7f, cb, 7f, e0, 7f, ed, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x02, 80, e4, 7f, d0, 7f, e0, 7f, ed, 7f, ee, 7f, 6b, fe, 40, 28,
|
||||
0x00, 80, e7, 7f, cb, 7f, e5, 7f, e9, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x02, 80, df, 7f, cb, 7f, e3, 7f, ed, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0xff, 7f, e3, 7f, cf, 7f, ea, 7f, f0, 7f, eb, 7f, 6b, fe, 40, 28,
|
||||
0x02, 80, e3, 7f, cc, 7f, e2, 7f, ef, 7f, f0, 7f, 6b, fe, 40, 28,
|
||||
0x03, 80, e5, 7f, d3, 7f, e4, 7f, f1, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x07, 80, e9, 7f, ce, 7f, e6, 7f, f2, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, ed, 7f, cf, 7f, e6, 7f, ec, 7f, f1, 7f, 6b, fe, 40, 28,
|
||||
0x05, 80, ef, 7f, d5, 7f, e6, 7f, ec, 7f, f1, 7f, 6b, fe, 40, 28,
|
||||
0x07, 80, e7, 7f, d1, 7f, e8, 7f, f1, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, e7, 7f, cc, 7f, e1, 7f, ed, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x02, 80, e6, 7f, cb, 7f, e7, 7f, f1, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, e5, 7f, ce, 7f, e9, 7f, ed, 7f, ee, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, e3, 7f, cd, 7f, e6, 7f, ec, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x00, 80, ea, 7f, cd, 7f, e8, 7f, ed, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x03, 80, e7, 7f, c8, 7f, e9, 7f, f3, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x03, 80, e5, 7f, cb, 7f, e3, 7f, f1, 7f, f0, 7f, 6b, fe, 40, 28,
|
||||
0x02, 80, e3, 7f, ce, 7f, df, 7f, f0, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, e7, 7f, ca, 7f, e0, 7f, ef, 7f, ee, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, e7, 7f, d3, 7f, e5, 7f, f0, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x01, 80, e9, 7f, c9, 7f, e2, 7f, ef, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x02, 80, df, 7f, c8, 7f, e1, 7f, ed, 7f, eb, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, e7, 7f, ca, 7f, e4, 7f, ee, 7f, ea, 7f, 6b, fe, 40, 28,
|
||||
0x04, 80, e7, 7f, d1, 7f, e6, 7f, f0, 7f, ec, 7f, 6b, fe, 40, 28,
|
||||
0x02, 80, df, 7f, cc, 7f, e6, 7f, eb, 7f, ef, 7f, 6b, fe, 40, 28,
|
||||
0x05, 80, e7, 7f, d1, 7f, e4, 7f, ee, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x07, 80, e9, 7f, cf, 7f, e9, 7f, ec, 7f, ec, 7f, 6b, fe, 40, 28,
|
||||
0x03, 80, e7, 7f, cb, 7f, e7, 7f, ed, 7f, ed, 7f, 6b, fe, 40, 28,
|
||||
0x06, 80, e3, 7f, cf, 7f, e4, 7f, f1, 7f, ec, 7f, 6b, fe, 40, 28,
|
||||
0x07, 80, e8, 7f, cc, 7f, e9, 7f, f2, 7f, ed, 7f
|
||||
}*/
|
||||
//public AnalogDataFormat1Packet(byte[] bytes) : base(bytes)
|
||||
//{
|
||||
// var offset = IRIGCH10.PacketHeader.PACKET_HEADER_LENGTH;
|
||||
|
||||
// if (PacketHeader.SecondaryHeaderPresent)
|
||||
// {
|
||||
// var secondaryHeaderBytes = new byte[SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH];
|
||||
// Buffer.BlockCopy(bytes, offset,
|
||||
// secondaryHeaderBytes, 0, SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH);
|
||||
// var secondaryHeader = new SecondaryTimeFormatHeader(secondaryHeaderBytes);
|
||||
// LocalTimeOfFirstSample = secondaryHeader.LocalTime;
|
||||
// offset += SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH;
|
||||
// }
|
||||
|
||||
// ChannelSpecificDataWord = BitConverter.ToUInt32(bytes, offset);
|
||||
// offset += sizeof(uint);
|
||||
// var numChannels = TotChan;
|
||||
// var sizeOf1SampleForAllChannels = sizeof(ushort) * numChannels;
|
||||
// //There's a CSDW in the data section, then all ADC data. CSDW is uint, 4 bytes
|
||||
// var numSamples = (PacketHeader.DataLength - 4) / sizeOf1SampleForAllChannels;
|
||||
|
||||
// Samples = new SampleData[numSamples];
|
||||
// for (var i = 0; i < Samples.Length; i++)
|
||||
// {
|
||||
// var channels = GetChannels(bytes, offset, numChannels);
|
||||
// Samples[i] = new SampleData(channels);
|
||||
// offset += sizeOf1SampleForAllChannels;
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
public partial class TestSetup : Exceptional
|
||||
{
|
||||
public partial class ExtraProperty : Exceptional
|
||||
{
|
||||
public ExtraProperty()
|
||||
{
|
||||
_key.Value = null;
|
||||
_value.Value = null;
|
||||
_version.Value = "1.0.0.0";
|
||||
}
|
||||
|
||||
public ExtraProperty(string key, string value)
|
||||
: this()
|
||||
{
|
||||
_key.Value = key;
|
||||
_value.Value = value;
|
||||
}
|
||||
|
||||
public string Key
|
||||
{
|
||||
get => _key.Value;
|
||||
set => _key.Value = value;
|
||||
}
|
||||
private readonly Property<string> _key
|
||||
= new Property<string>(typeof(Graph).Namespace + ".ExtraProperty.Key", "", false);
|
||||
|
||||
public string Value
|
||||
{
|
||||
get => _value.Value;
|
||||
set => _value.Value = value;
|
||||
}
|
||||
private readonly Property<string> _value
|
||||
= new Property<string>(typeof(Graph).Namespace + ".ExtraProperty.Value", "", false);
|
||||
|
||||
public string Version
|
||||
{
|
||||
get => _version.Value;
|
||||
set => _version.Value = value;
|
||||
}
|
||||
private readonly Property<string> _version
|
||||
= new Property<string>(typeof(Graph).Namespace + ".ExtraProperty.Version", "", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace DTS.Serialization.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")]
|
||||
internal sealed partial class Settings1 : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings1 defaultInstance = ((Settings1)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings1())));
|
||||
|
||||
public static Settings1 Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute(".\\Data\\TDM CFC1000")]
|
||||
public string TDMFolder {
|
||||
get {
|
||||
return ((string)(this["TDMFolder"]));
|
||||
}
|
||||
set {
|
||||
this["TDMFolder"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("-500")]
|
||||
public double DefaultStart {
|
||||
get {
|
||||
return ((double)(this["DefaultStart"]));
|
||||
}
|
||||
set {
|
||||
this["DefaultStart"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("500")]
|
||||
public double DefaultStop {
|
||||
get {
|
||||
return ((double)(this["DefaultStop"]));
|
||||
}
|
||||
set {
|
||||
this["DefaultStop"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("#NOVALUE")]
|
||||
public string TSVPOCNameLastUsed {
|
||||
get {
|
||||
return ((string)(this["TSVPOCNameLastUsed"]));
|
||||
}
|
||||
set {
|
||||
this["TSVPOCNameLastUsed"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("#NOVALUE")]
|
||||
public string TSVPOCPhoneAndEmailLastUsed {
|
||||
get {
|
||||
return ((string)(this["TSVPOCPhoneAndEmailLastUsed"]));
|
||||
}
|
||||
set {
|
||||
this["TSVPOCPhoneAndEmailLastUsed"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("Converted")]
|
||||
public string TSVDataTypeLastUsed {
|
||||
get {
|
||||
return ((string)(this["TSVDataTypeLastUsed"]));
|
||||
}
|
||||
set {
|
||||
this["TSVDataTypeLastUsed"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("#NOVALUE")]
|
||||
public string TSVLabNameLastUsed {
|
||||
get {
|
||||
return ((string)(this["TSVLabNameLastUsed"]));
|
||||
}
|
||||
set {
|
||||
this["TSVLabNameLastUsed"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("#NOVALUE")]
|
||||
public string TSVTestObjectLastUsed {
|
||||
get {
|
||||
return ((string)(this["TSVTestObjectLastUsed"]));
|
||||
}
|
||||
set {
|
||||
this["TSVTestObjectLastUsed"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("#NOVALUE")]
|
||||
public string TSVTestTypeLastUsed {
|
||||
get {
|
||||
return ((string)(this["TSVTestTypeLastUsed"]));
|
||||
}
|
||||
set {
|
||||
this["TSVTestTypeLastUsed"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("215, 225, 255")]
|
||||
public global::System.Drawing.Color TableHeader {
|
||||
get {
|
||||
return ((global::System.Drawing.Color)(this["TableHeader"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("238, 242, 255")]
|
||||
public global::System.Drawing.Color AlternatingRow {
|
||||
get {
|
||||
return ((global::System.Drawing.Color)(this["AlternatingRow"]));
|
||||
}
|
||||
set {
|
||||
this["AlternatingRow"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* DTS.Slice.Control.Event.Module.Channel.ReviewableAttribute.NotApplicableException.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace DTS.Slice.Control
|
||||
{
|
||||
// *** see DTS.Slice.Control.Event.cs ***
|
||||
public partial class Event
|
||||
{
|
||||
|
||||
// *** see DTS.Slice.Control.Event.Module.cs ***
|
||||
public partial class Module
|
||||
{
|
||||
|
||||
// *** see DTS.Slice.Control.Event.Module.Channel.cs ***
|
||||
public partial class Channel
|
||||
{
|
||||
|
||||
// *** see DTS.Slice.Control.Event.Module.Channel.ReviewableAttribute.cs ***
|
||||
public partial class ReviewableAttribute
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Representation of an attempt to use a channel attribute that is not
|
||||
/// applicable to the associated channel.
|
||||
/// </summary>
|
||||
public class NotApplicableException : ApplicationException
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the NotApplicableException class.
|
||||
/// </summary>
|
||||
///
|
||||
public NotApplicableException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the NotApplicableException class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="msg">
|
||||
/// The <see cref="string"/> message to be associated with this exception.
|
||||
/// </param>
|
||||
///
|
||||
public NotApplicableException(string msg)
|
||||
: base(msg)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the NotApplicableException class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="msg">
|
||||
/// The <see cref="string"/> message to be associated with this exception.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="innerEx">
|
||||
/// The <see cref="System.Exception"/> responsible for this exception inception.
|
||||
/// </param>
|
||||
///
|
||||
public NotApplicableException(string msg, System.Exception innerEx)
|
||||
: base(msg, innerEx)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
} // *** end ReviewableAttribute ***
|
||||
} // *** end Channel ***
|
||||
} // *** end Module ***
|
||||
} // *** end Event ***
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* SliceRaw.File.PersistentChannel.IsInitializingException.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DTS.Serialization.SliceRaw
|
||||
{
|
||||
// *** see SliceRaw.File.cs ***
|
||||
public partial class File
|
||||
{
|
||||
|
||||
// *** see SliceRaw.File.PersistentChannel.cs ***
|
||||
public partial class PersistentChannel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Representation of an attempt to get a property of a persistent channel still
|
||||
/// being initialized.
|
||||
/// </summary>
|
||||
public class IsInitializingException : ApplicationException
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the IsInitializingException class.
|
||||
/// </summary>
|
||||
///
|
||||
public IsInitializingException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the IsInitializingException class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="msg">
|
||||
/// The <see cref="string"/> message to be associated with this exception.
|
||||
/// </param>
|
||||
///
|
||||
public IsInitializingException(string msg)
|
||||
: base(msg)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the IsInitializingException class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="msg">
|
||||
/// The <see cref="string"/> message to be associated with this exception.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="innerEx">
|
||||
/// The <see cref="System.Exception"/> responsible for this exception exception.
|
||||
/// </param>
|
||||
///
|
||||
public IsInitializingException(string msg, System.Exception innerEx)
|
||||
: base(msg, innerEx)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
} // *** end PersistentChannel ***
|
||||
} // *** end File ***
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="errorProvider1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* ToyotaCsv.File.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.Serialization.ToyotaCsv
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Basic representation of a Toyota CSV file.
|
||||
/// </summary>
|
||||
///
|
||||
public partial class File
|
||||
: Serialization.File, IWritable<Test>
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the ToyotaCsv.File class.
|
||||
/// </summary>
|
||||
///
|
||||
public File()
|
||||
: base("Toyota CSV")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get this file format's extension.
|
||||
/// </summary>
|
||||
public static string Extension => ".csv";
|
||||
|
||||
/// <summary>
|
||||
/// Get the file writer for this file type.
|
||||
/// </summary>
|
||||
public IWriter<Test> Exporter
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_Exporter == null)
|
||||
_Exporter = new Writer(this, DefaultEncoding);
|
||||
return _Exporter;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting exporter", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private IWriter<Test> _Exporter = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// DDASTestDefinition.h
|
||||
// --------------------
|
||||
// Defines the data acquisition system configuration and channels for a test.
|
||||
//
|
||||
//
|
||||
// AUTHOR: A. J. Owski
|
||||
// LOC: 1250
|
||||
// DEPT: 5260 Tool Development
|
||||
// (formerly Instrument Systems)
|
||||
//
|
||||
// COPYRIGHT: (c) 2002-2004 DaimlerChrysler Corp.
|
||||
//
|
||||
// REVISIONS: (most-recent at top of list).
|
||||
//
|
||||
// Date Init Description of Change
|
||||
// -------- --- ---------------------
|
||||
// 06/22/05 WJP Add support for MemoryOptionFlags bits MEMOPT_PREEVENT and
|
||||
// MEMOPT_PREEVENTXXX, Programmable Pre-Event blocks up to 99 and
|
||||
// 511 introduced in Memory Units versions 2.40 and 3.10,
|
||||
// respectively.
|
||||
// 10/19/04 WJP Add support for channel (analog) triggers.
|
||||
// 04/02/04 WJP General clean up
|
||||
// 07/22/03 WJP Added HardwareType
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef DDASTYPENAME // If these def's aren't def'd,
|
||||
|
||||
#define TESTDEFEXT ".tdf"
|
||||
#define DDASTYPENAME "DDAS V5"
|
||||
#define DDASFILEVERS "Ver 500"
|
||||
|
||||
enum FileTypeFlags
|
||||
{
|
||||
FILETYPE_IMPORTED4X // Test was imported from 4x
|
||||
};
|
||||
|
||||
enum HardwareType // Hardware type values
|
||||
{ // in upper 16 bits of FileTypeFlags
|
||||
HWTYPE_UNKNOWN, // None specified - old DDAS
|
||||
HWTYPE_DDAS3, // DDAS III hardware
|
||||
HWTYPE_KAYSERTHREDE, // Kayser-Threde hardware (future)
|
||||
HWTYPE_COUNT
|
||||
};
|
||||
|
||||
typedef struct tagFILEINFOBLOCK
|
||||
{
|
||||
UINT Size; // Block Size (including nSize)
|
||||
char FileTypeName[12]; // Software Type Name
|
||||
char FileTypeVers[12]; // File Version Name
|
||||
UINT FileTypeFlags; // File Type Flags
|
||||
// - Hardware Type in upper 16 bits
|
||||
// - File Type in lower 16 bits
|
||||
char CreatedByName[16]; // Created by T-number
|
||||
char UpdatedByName[16]; // Updated by T-number
|
||||
}FILEINFOBLOCK;
|
||||
|
||||
|
||||
typedef struct tagDATASYSTEMBLOCK
|
||||
{
|
||||
UINT Size; // Block Size (including nSize)
|
||||
UINT NumberOfSystems; // No of systems in this definition
|
||||
UINT ChannelsPerSystem; // Chan per system in this definition
|
||||
UINT MaxSampleRate; // Max (or default) sample rate
|
||||
UINT SizeOfConfig; // Size of 1 DDASCONFIGBLOCK
|
||||
}DATASYSTEMBLOCK;
|
||||
|
||||
|
||||
typedef struct tagDDASCONFIGBLOCK // One config block per system
|
||||
{
|
||||
UINT Size; // Block Size (including nSize)
|
||||
short AnalogUnitNo; // DDAS analog unit for this test
|
||||
short AnalogOptions; // DDAS analog unit options
|
||||
short MemoryUnitNo; // DDAS memory unit for this test
|
||||
short MemoryOptions; // DDAS memory unit options
|
||||
long MemorySize; // DDAS memory unit RAM (bytes)
|
||||
}DDASCONFIGBLOCK;
|
||||
|
||||
enum AnalogOptionFlags
|
||||
{
|
||||
ANAOPT_CHANTRIGGERS // Analog unit has channel triggers
|
||||
};
|
||||
|
||||
enum MemoryOptionFlags
|
||||
{
|
||||
MEMOPT_TAPEMODE, // Memory unit has tape mode
|
||||
MEMOPT_PREEVENT, // Memory unit can sel pre-event to 99
|
||||
MEMOPT_PREEVENTXXX // Memory unit can sel pre-event to 511
|
||||
};
|
||||
|
||||
|
||||
enum RecordModes
|
||||
{
|
||||
RECORDMODE_EVENT, // Normal (event) mode
|
||||
RECORDMODE_TAPE // Tape (manual) mode
|
||||
};
|
||||
|
||||
|
||||
typedef struct tagACQUISITIONBLOCK // Defines data acq params this test
|
||||
{
|
||||
long nSize; // Block Size (including nSize)
|
||||
long nRecordMode; // Enumerated constant data mode
|
||||
long SampleRate; // Samples per second
|
||||
long TotalSamples; // Total samples in record
|
||||
long PreEventSamples; // Pre-Event samples (Rec Mode only!)
|
||||
long TapeModeChannels; // No of Channels (Tape Mode only!)
|
||||
// long nTrigBlock; // Trigger block size if non-zero
|
||||
long nTrigBlock; // Number of trigger entries (can be 0).
|
||||
}ACQUISITIONBLOCK;
|
||||
|
||||
|
||||
// To enable trigger,
|
||||
// ChanNo and LevelPct must be nonzero
|
||||
// and TRIGCHANDSBL must not be set in LevelPct
|
||||
typedef struct tagTRIGCHANDEF // Defines chan (analog) trigger
|
||||
{
|
||||
BYTE ChanNo; // Channel number to use as trigger
|
||||
BYTE LevelPct; // Trig level in % full scale (0=off)
|
||||
}TRIGCHANDEF; // Trigger when signal exceeds +/-level.
|
||||
|
||||
#define MAXTRIGCHANS 4
|
||||
#define TRIGCHANDSBL 0x80
|
||||
|
||||
typedef struct tagTRIGCHANBLOCK // Defines chan (analog) trigs this test
|
||||
{
|
||||
unsigned short SizeBlock; // Block Size in bytes (including nSize)
|
||||
unsigned short NumTrigs; // Number of entries in array TrigChan
|
||||
TRIGCHANDEF TrigChan[MAXTRIGCHANS]; // Channel (analog) triggers. (NOTE that
|
||||
}TRIGCHANBLOCK; // this will be a variable size array,
|
||||
// but we sized it to 1 to avoid warnings.)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* FtssCsv.File.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using DTS.Common.ISO;
|
||||
|
||||
namespace DTS.Serialization.Diadem
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Basic representation of a Toyota CSV file.
|
||||
/// </summary>
|
||||
///
|
||||
public partial class File
|
||||
: Serialization.File, IWritable<Test>
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the FtssCsv.File class.
|
||||
/// </summary>
|
||||
///
|
||||
public File(bool bUseEVG20, TestPlan plan)
|
||||
: base("Diadem")
|
||||
{
|
||||
_bUseEVG20 = bUseEVG20;
|
||||
_testPlan = plan;
|
||||
}
|
||||
|
||||
private readonly TestPlan _testPlan;
|
||||
private readonly bool _bUseEVG20;
|
||||
/// <summary>
|
||||
/// Get this file format's extension.
|
||||
/// </summary>
|
||||
public static string Extension => ".dat";
|
||||
|
||||
public bool UseIsoCodeForDiadem200 { get; set; } = true;
|
||||
|
||||
public bool UseZeroForUnfiltered { get; set; } = false;
|
||||
|
||||
// FB16225: change options to iso code, sensor serial, or (iso/user) name
|
||||
public enum DiademOptions
|
||||
{
|
||||
NONE,
|
||||
ISO_CODE,
|
||||
SENSOR_SERIAL_NUMBER,
|
||||
CHANNEL_NAME
|
||||
}
|
||||
|
||||
// 43958 Add Group Name as a possibility instead of AAF Rate in Reserved 1
|
||||
public enum DiademOptionsReserved1
|
||||
{
|
||||
NONE,
|
||||
AAF_RATE,
|
||||
GROUP_NAME
|
||||
}
|
||||
|
||||
// FB43958: Add Channel Sensitivity as a possibility in Reserved 2
|
||||
public enum DiademOptionsReserved2
|
||||
{
|
||||
NONE,
|
||||
CHANNEL_SENSITIVITY
|
||||
}
|
||||
|
||||
public DiademOptions ChannelName200Option { get; set; }
|
||||
|
||||
public DiademOptions UserComment201Option { get; set; }
|
||||
|
||||
public DiademOptionsReserved1 Reserved1_301Option { get; set; }
|
||||
|
||||
public DiademOptionsReserved2 Reserved2_302Option { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Get the file writer for this file type.
|
||||
/// </summary>
|
||||
public IWriter<Test> Exporter
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_Exporter == null)
|
||||
{
|
||||
var writer = new Writer(this, DefaultEncoding);
|
||||
writer.UseEVG20 = _bUseEVG20;
|
||||
writer.TestPlan = _testPlan;
|
||||
|
||||
writer.UseIsoCodeForDiadem200 = UseIsoCodeForDiadem200;
|
||||
writer.UseZeroForUnfiltered = UseZeroForUnfiltered;
|
||||
writer.ChannelName200Option = ChannelName200Option;
|
||||
writer.UserComment201Option = UserComment201Option;
|
||||
writer.Reserved1_301Option = Reserved1_301Option;
|
||||
writer.Reserved2_302Option = Reserved2_302Option;
|
||||
_Exporter = writer;
|
||||
}
|
||||
((Writer)_Exporter).WriterParent = this;
|
||||
return _Exporter;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting exporter", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private IWriter<Test> _Exporter = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* SliceRaw.File.PersistentChannel.AlreadyInitializedException.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DTS.Serialization.SliceRaw
|
||||
{
|
||||
// *** see SliceRaw.File.cs ***
|
||||
public partial class File
|
||||
{
|
||||
|
||||
// *** see SliceRaw.File.PersistentChannel.cs ***
|
||||
public partial class PersistentChannel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Representation of an attempt to set a property that has already been initialized
|
||||
/// and exhibits set-once behavior.
|
||||
/// </summary>
|
||||
public class AlreadyInitializedException : ApplicationException
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the AlreadyInitializedException class.
|
||||
/// </summary>
|
||||
///
|
||||
public AlreadyInitializedException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the AlreadyInitializedException class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="msg">
|
||||
/// The <see cref="string"/> message to be associated with this exception.
|
||||
/// </param>
|
||||
///
|
||||
public AlreadyInitializedException(string msg)
|
||||
: base(msg)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the AlreadyInitializedException class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="msg">
|
||||
/// The <see cref="string"/> message to be associated with this exception.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="innerEx">
|
||||
/// The <see cref="System.Exception"/> responsible for this exception inception.
|
||||
/// </param>
|
||||
///
|
||||
public AlreadyInitializedException(string msg, System.Exception innerEx)
|
||||
: base(msg, innerEx)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
} // *** end PersistentChannel ***
|
||||
} // *** end File ***
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* DTS.Slice.Control.Event.Module.AnalogInputChannel.ReviewableShuntDeflectionPercentageAttribute.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace DTS.Slice.Control
|
||||
{
|
||||
// *** see DTS.Slice.Control.Event.cs ***
|
||||
public partial class Event
|
||||
{
|
||||
|
||||
// *** see DTS.Slice.Control.Event.Module.cs ***
|
||||
public partial class Module
|
||||
{
|
||||
|
||||
// *** see DTS.Slice.Control.Event.Module.AnalogInputChannel.cs ***
|
||||
public partial class AnalogInputChannel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A reviewable shunt deflection attribute attached to a specific channel.
|
||||
/// </summary>
|
||||
public class ReviewableShuntDeflectionPercentageAttribute
|
||||
: Slice.Control.Event.Module.Channel.ReviewableAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize an instance of this class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="channel">
|
||||
/// The <see cref="Event.Module.Channel"/> to which this attribute is attached.
|
||||
/// </param>
|
||||
///
|
||||
public ReviewableShuntDeflectionPercentageAttribute(Event.Module.Channel channel)
|
||||
: base("Shunt Error (%)", delegate { return (100.0 * ((channel as DTS.DAS.Concepts.DAS.Channel.IShuntAware).MeasuredShuntDeflectionMv - (channel as DTS.DAS.Concepts.DAS.Channel.IShuntAware).TargetShuntDeflectionMv) / (channel as DTS.DAS.Concepts.DAS.Channel.IShuntAware).TargetShuntDeflectionMv).ToString("F1"); })
|
||||
{
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// A reviewable shunt deflection attribute attached to a specific channel.
|
||||
/// </summary>
|
||||
public class ReviewableCalSignalPercentageAttribute
|
||||
: Slice.Control.Event.Module.Channel.ReviewableAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize an instance of this class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="channel">
|
||||
/// The <see cref="Event.Module.Channel"/> to which this attribute is attached.
|
||||
/// </param>
|
||||
///
|
||||
public ReviewableCalSignalPercentageAttribute(Event.Module.Channel channel)
|
||||
: base("Calibration Signal Error (%)", delegate { return (100.0 * ((channel as DTS.DAS.Concepts.DAS.Channel.ICalSignalAware).MeasuredCalSignalMv - (channel as DTS.DAS.Concepts.DAS.Channel.ICalSignalAware).TargetCalSignalMv) / (channel as DTS.DAS.Concepts.DAS.Channel.ICalSignalAware).TargetCalSignalMv).ToString("F1"); })
|
||||
{
|
||||
}
|
||||
}
|
||||
} // *** end Channel ***
|
||||
} // *** end Module ***
|
||||
} // *** end Event ***
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.Serialization.TSV
|
||||
{
|
||||
public class TSVTest
|
||||
{
|
||||
public enum Fields
|
||||
{
|
||||
LabName,
|
||||
POCName,
|
||||
POCPhoneAndEmail,
|
||||
TestDate,
|
||||
TestTime,
|
||||
TestNumber,
|
||||
TestType,
|
||||
TestObject,
|
||||
DataType,
|
||||
SensorMakeModelSerial,
|
||||
SensorLocation,
|
||||
SensorAxis,
|
||||
SensorMountType,
|
||||
EngineeringUnits,
|
||||
ChannelErrors,
|
||||
SamplingRate,
|
||||
AAFilterCutoffDescription,
|
||||
BitResolution,
|
||||
DigitalFilterType,
|
||||
Notes
|
||||
}
|
||||
|
||||
private readonly Dictionary<Fields, string> _values = new Dictionary<Fields, string>();
|
||||
public string GetValue(Fields field)
|
||||
{
|
||||
if (!_values.ContainsKey(field)) { _values.Add(field, "#NOVALUE"); }
|
||||
return _values[field];
|
||||
}
|
||||
|
||||
public void SetValue(Fields field, string value)
|
||||
{
|
||||
_values[field] = value;
|
||||
foreach (var channel in _channels) { channel.SetValue(field, value); }
|
||||
switch (field)
|
||||
{
|
||||
case Fields.POCName: Properties.Settings1.Default.TSVPOCNameLastUsed = value; Properties.Settings1.Default.Save(); break;
|
||||
case Fields.POCPhoneAndEmail: Properties.Settings1.Default.TSVPOCPhoneAndEmailLastUsed = value; Properties.Settings1.Default.Save(); break;
|
||||
case Fields.DataType: Properties.Settings1.Default.TSVDataTypeLastUsed = value; Properties.Settings1.Default.Save(); break;
|
||||
case Fields.LabName: Properties.Settings1.Default.TSVLabNameLastUsed = value; Properties.Settings1.Default.Save(); break;
|
||||
case Fields.TestObject: Properties.Settings1.Default.TSVTestObjectLastUsed = value; Properties.Settings1.Default.Save(); break;
|
||||
case Fields.TestType: Properties.Settings1.Default.TSVTestTypeLastUsed = value; Properties.Settings1.Default.Save(); break;
|
||||
}
|
||||
}
|
||||
private readonly List<TSVChannel> _channels = new List<TSVChannel>();
|
||||
public TSVChannel[] Channels
|
||||
{
|
||||
get => _channels.ToArray();
|
||||
set { _channels.Clear(); _channels.AddRange(value); }
|
||||
}
|
||||
public Test Test { get; }
|
||||
public FilteredData[] DataFilteredEU { get; }
|
||||
public FilteredData[] DataUnfilteredEU { get; }
|
||||
public FilteredData[] DataADC { get; }
|
||||
public double[] ActualRangesEUFiltered { get; }
|
||||
public double[] ActualRangesEUUnfiltered { get; }
|
||||
public double[] ActualRangesADC { get; }
|
||||
|
||||
public TSVTest(Test test,
|
||||
FilteredData[] euFiltered,
|
||||
FilteredData[] adc,
|
||||
FilteredData[] euUnfiltered,
|
||||
string path,
|
||||
double[] actualRangesEUFiltered,
|
||||
double[] actualRangesEUUnfiltered,
|
||||
double[] actualRAngesADC)
|
||||
{
|
||||
Test = test;
|
||||
|
||||
DataUnfilteredEU = euUnfiltered;
|
||||
DataFilteredEU = euFiltered;
|
||||
DataADC = adc;
|
||||
|
||||
ActualRangesADC = actualRAngesADC;
|
||||
ActualRangesEUUnfiltered = actualRangesEUUnfiltered;
|
||||
ActualRangesEUFiltered = actualRangesEUFiltered;
|
||||
|
||||
for (var i = 0; i < test.Channels.Count && i < euUnfiltered.Length; i++)
|
||||
{
|
||||
_channels.Add(new TSVChannel(this, i, path));
|
||||
}
|
||||
SetValue(Fields.TestNumber, test.Id);
|
||||
SetValue(Fields.TestDate, test.InceptionDate.ToShortDateString());
|
||||
SetValue(Fields.TestTime, test.InceptionDate.ToShortTimeString());
|
||||
|
||||
SetValue(Fields.POCName, Properties.Settings1.Default.TSVPOCNameLastUsed);
|
||||
SetValue(Fields.POCPhoneAndEmail, Properties.Settings1.Default.TSVPOCPhoneAndEmailLastUsed);
|
||||
SetValue(Fields.DataType, Properties.Settings1.Default.TSVDataTypeLastUsed);
|
||||
SetValue(Fields.LabName, Properties.Settings1.Default.TSVLabNameLastUsed);
|
||||
SetValue(Fields.TestObject, Properties.Settings1.Default.TSVTestObjectLastUsed);
|
||||
SetValue(Fields.TestType, Properties.Settings1.Default.TSVTestTypeLastUsed);
|
||||
SetValue(Fields.SamplingRate, test.Modules.First().SampleRateHz.ToString());
|
||||
SetValue(Fields.AAFilterCutoffDescription, string.Format("{0}hz multipole low pass butterworth", test.Modules.First().AaFilterRateHz.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* DTS.Slice.Control.DAS.Channel.IFilter.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using DTS.Common.Utilities;
|
||||
|
||||
namespace DTS.Slice.Control.DAS.Channel
|
||||
{
|
||||
/// <summary>
|
||||
/// Methodical definition of a slice control event module channel filter.
|
||||
/// </summary>
|
||||
public interface IFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// A descriptive <see cref="string"/> designation for the filter.
|
||||
/// </summary>
|
||||
string Name
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Boolean"/> value indicating whether or not this filter is
|
||||
/// a cardinal CFC value.
|
||||
/// </summary>
|
||||
bool IsCfc
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a <see cref="ChannelFilter"/> designation for this filter.
|
||||
/// </summary>
|
||||
ChannelFilter Type
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the <see cref="double"/> cutoff frequency for this filter.
|
||||
/// </summary>
|
||||
double CutoffFrequencyHz
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply the filter to the specified input.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="input">
|
||||
/// The input to the filter.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="displayUnits">
|
||||
/// The <see cref="Event.Module.Channel.DataDisplayUnits"/> to be
|
||||
/// filtered from the channel.
|
||||
/// </param>
|
||||
/// <param name="bUseLegacyTDCSofwareFilterAdjustment">
|
||||
/// when true will adjust data one sample to the right to preserve existing TDC filtering behavior
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The filtering of the input.
|
||||
/// </returns>
|
||||
///
|
||||
double[] Apply(
|
||||
Event.Module.Channel input,
|
||||
Event.Module.Channel.DataDisplayUnits displayUnits,
|
||||
bool bUseLegacyTDCSofwareFilterAdjustment);
|
||||
|
||||
double[] Apply(
|
||||
double[] data,
|
||||
double sampleRate,
|
||||
bool bUseLegacyTDCSoftwareFilterAdjustment
|
||||
);
|
||||
/// <summary>
|
||||
/// the ToString is already overloaded, but we sometimes need the base name, not the decorated name that
|
||||
/// is returned in ToString.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
string ToBaseString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* SoMat.File.cs
|
||||
*
|
||||
* Copyright © 2013
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.Serialization.TSV
|
||||
{
|
||||
///
|
||||
/// <summary>
|
||||
/// File
|
||||
/// </summary>
|
||||
///
|
||||
public partial class File
|
||||
: Serialization.File, IWritable<Test>
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the FtssCsv.File class.
|
||||
/// </summary>
|
||||
///
|
||||
public File()
|
||||
: base("TSV")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get this file format's extension.
|
||||
/// </summary>
|
||||
public static string Extension => ".tsv";
|
||||
|
||||
/// <summary>
|
||||
/// Get the file writer for this file type.
|
||||
/// </summary>
|
||||
public IWriter<Test> Exporter
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_Exporter == null)
|
||||
_Exporter = new Writer(this, DefaultEncoding);
|
||||
return _Exporter;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting exporter", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private IWriter<Test> _Exporter = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
Test.Module.Channel.DataArray.cs
|
||||
|
||||
Copyright © 2009
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using DTS.Utilities;
|
||||
using DTS.Utilities.DotNetProgrammingConstructs;
|
||||
using DTS.Utilities.Xml;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
// *** see Test.Module.cs ***
|
||||
public partial class Module
|
||||
{
|
||||
// *** see Test.Module.Channel.cs ***
|
||||
public partial class Channel
|
||||
{
|
||||
/// <summary>
|
||||
/// Representation of serializable channel data.
|
||||
/// </summary>
|
||||
///
|
||||
/// <typeparam name="DataType">
|
||||
/// The actual type of this channel data's datum.
|
||||
/// </typeparam>
|
||||
///
|
||||
public class DataArray<DataType> : Exceptional, IXmlSerializable
|
||||
{
|
||||
private readonly string DataXmlTag = "Data";
|
||||
private readonly string DataLengthXmlTag = "Length";
|
||||
private readonly string DataTypeXmlTag = "Type";
|
||||
private readonly string DatumXmlTag = "Datum";
|
||||
private readonly string DatumValueXmlTag = "Value";
|
||||
private readonly string DataAdcToMvScaleFactorTag = "ScaleFactorMv";
|
||||
private readonly string DataMvPerEuTag = "SensitivityMvEu";
|
||||
|
||||
/// <summary>
|
||||
/// Method for converting a <see cref="List"/> of the generic data type to
|
||||
/// a DataArray.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="dataList">
|
||||
/// The <see cref="List"/> of the generic data type to be converted into a
|
||||
/// DataArray.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// A DataArray containing the specified values.
|
||||
/// </returns>
|
||||
///
|
||||
public static implicit operator DataArray<DataType>( List<DataType> dataList )
|
||||
{
|
||||
return new DataArray<DataType>( dataList.ToArray( ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method for converting a DataArray of the generic data type to a <see cref="List"/>
|
||||
/// of the generic data type.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="dataArray">
|
||||
/// The DataArray of the specified generic type to be converted into a <see cref="List"/>.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// A <see cref="List"/> of the specified generic type.
|
||||
/// </returns>
|
||||
///
|
||||
public static implicit operator List<DataType>( DataArray<DataType> dataArray )
|
||||
{
|
||||
return new List<DataType>( dataArray.Values );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the Data class.
|
||||
/// </summary>
|
||||
public DataArray( )
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the Data class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="values">
|
||||
/// The values with which to initialize this data collection.
|
||||
/// </param>
|
||||
///
|
||||
public DataArray( DataType[] values )
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Values = values;
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem constructing Test.Module.Channel.DataArray", ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all of the data values in an array.
|
||||
/// </summary>
|
||||
public DataType[] Values
|
||||
{
|
||||
//get { return _Values.Value; }
|
||||
get
|
||||
{
|
||||
if (!_Values.IsInitialized || null == _Values.Value)
|
||||
{
|
||||
return new DataType[0];
|
||||
}
|
||||
else { return _Values.Value; }
|
||||
}
|
||||
set { _Values.Value = value; }
|
||||
}
|
||||
private Property<DataType[]> _Values
|
||||
= new Property<DataType[]>(
|
||||
typeof( DataArray<DataType> ).Namespace + ".Test.Module.Channel.DataArray.Values",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the ADC->MV scale factor for this data.
|
||||
/// </summary>
|
||||
public double ScaleFactorMv
|
||||
{
|
||||
get { return _ScaleFactorMv.Value; }
|
||||
set { _ScaleFactorMv.Value = value; }
|
||||
}
|
||||
private Property<double> _ScaleFactorMv
|
||||
= new Property<double>(
|
||||
typeof( DataArray<DataType> ).Namespace + ".Test.Module.Channel.DataArray.ScaleFactorMv",
|
||||
0.0,
|
||||
false
|
||||
);
|
||||
public double ScaleFactorEU
|
||||
{
|
||||
get { return _ScaleFactorEU.Value; }
|
||||
set { _ScaleFactorEU.Value = value; }
|
||||
}
|
||||
private Property<double> _ScaleFactorEU
|
||||
= new Property<double>(
|
||||
typeof(DataArray<DataType>).Namespace + ".Test.Module.Channel.DataArray.ScaleFactorEU",
|
||||
0.0,
|
||||
false
|
||||
);
|
||||
public bool UseTDASScaleFactors
|
||||
{
|
||||
get { return _UseTDASScaleFactors.Value; }
|
||||
set { _UseTDASScaleFactors.Value = value; }
|
||||
}
|
||||
private Property<bool> _UseTDASScaleFactors
|
||||
= new Property<bool>(
|
||||
typeof(DataArray<DataType>).Namespace + ".Test.Module.Channel.DataArray.UseTDASScaleFactors",
|
||||
false,
|
||||
true
|
||||
);
|
||||
public short DataZeroLevel
|
||||
{
|
||||
get { return _DataZeroLevel.Value; }
|
||||
set { _DataZeroLevel.Value = value; }
|
||||
}
|
||||
private Property<short> _DataZeroLevel
|
||||
= new Property<short>(
|
||||
typeof(DataArray<DataType>).Namespace + ".Test.Module.Channel.DataArray.DataZeroLevel",
|
||||
0,
|
||||
false
|
||||
);
|
||||
/// <summary>
|
||||
/// Get/set the Unit Conversion for this data.
|
||||
/// </summary>
|
||||
public double UnitConversion
|
||||
{
|
||||
get { return _UnitConversion.Value; }
|
||||
set { _UnitConversion.Value = value; }
|
||||
}
|
||||
private Property<double> _UnitConversion
|
||||
= new Property<double>(
|
||||
typeof(DataArray<DataType>).Namespace + ".Test.Module.Channel.DataArray.UnitConversion",
|
||||
1.0,
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the Multiplier for this data.
|
||||
/// </summary>
|
||||
public double Multiplier
|
||||
{
|
||||
get { return _Multiplier.Value; }
|
||||
set { _Multiplier.Value = value; }
|
||||
}
|
||||
private Property<double> _Multiplier
|
||||
= new Property<double>(
|
||||
typeof(DataArray<DataType>).Namespace + ".Test.Module.Channel.DataArray.Multiplier",
|
||||
1.0,
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the Modify Offset for this data.
|
||||
/// </summary>
|
||||
public double UserOffsetEU
|
||||
{
|
||||
get { return _UserOffsetEU.Value; }
|
||||
set { _UserOffsetEU.Value = value; }
|
||||
}
|
||||
private Property<double> _UserOffsetEU
|
||||
= new Property<double>(
|
||||
typeof(DataArray<DataType>).Namespace + ".Test.Module.Channel.DataArray.UserOffsetEU",
|
||||
0.0,
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the ADC->EU scale factor for this data.
|
||||
/// </summary>
|
||||
public double MvPerEu
|
||||
{
|
||||
get { return _MvPerEu.Value; }
|
||||
set { _MvPerEu.Value = value; }
|
||||
}
|
||||
private Property<double> _MvPerEu
|
||||
= new Property<double>(
|
||||
typeof( DataArray<DataType> ).Namespace + ".Test.Module.Channel.DataArray.MvPerEu",
|
||||
0.0,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Write XML serialization for this object to the specified writer.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="writer">
|
||||
/// The <see cref="XmlWriter"/> to which this object's XML serialization
|
||||
/// will be written.
|
||||
/// </param>
|
||||
///
|
||||
public void WriteXml( XmlWriter writer )
|
||||
{
|
||||
try
|
||||
{
|
||||
var cult = new System.Globalization.CultureInfo("");
|
||||
int dataLength = Values.Length;
|
||||
|
||||
writer.WriteStartElement( DataXmlTag );
|
||||
writer.WriteAttributeString( DataLengthXmlTag, dataLength.ToString(cult) );
|
||||
writer.WriteAttributeString( DataTypeXmlTag, typeof( DataType ).FullName );
|
||||
writer.WriteAttributeString( DataAdcToMvScaleFactorTag, ScaleFactorMv.ToString(cult) );
|
||||
writer.WriteAttributeString( DataMvPerEuTag, MvPerEu.ToString(cult) );
|
||||
|
||||
for ( int i=0; i<dataLength; i++ )
|
||||
{
|
||||
writer.WriteStartElement( DatumXmlTag );
|
||||
writer.WriteAttributeString( DatumValueXmlTag, Values[ i ].ToString() );
|
||||
writer.WriteEndElement( );
|
||||
}
|
||||
|
||||
writer.WriteEndElement( );
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem converting DTS.Serialization.Test.Module.Channel.Data object to XML", ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read XML serialization for this object from the specified reader.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="reader">
|
||||
/// The <see cref="XmlReader"/> from which this object's XML serialization
|
||||
/// will be read.
|
||||
/// </param>
|
||||
///
|
||||
public void ReadXml( XmlReader reader )
|
||||
{
|
||||
try
|
||||
{
|
||||
var cult = new System.Globalization.CultureInfo("");
|
||||
reader.MoveToContent();
|
||||
|
||||
Type dataType = null;
|
||||
int dataLength;
|
||||
try
|
||||
{
|
||||
string scaleFactorMvString = null;
|
||||
try { scaleFactorMvString = reader.GetAttribute( DataAdcToMvScaleFactorTag ); }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem extracting ADC->MV scaling factor from XML", ex ); }
|
||||
|
||||
string mvPerEuString = null;
|
||||
try { mvPerEuString = reader.GetAttribute( DataMvPerEuTag ); }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem extracting sensitivity MV/EU factor from XML", ex ); }
|
||||
|
||||
string dataTypeString = null;
|
||||
try { dataTypeString = reader.GetAttribute( DataTypeXmlTag ); }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem extracting data type name from XML", ex ); }
|
||||
|
||||
dataType = null;
|
||||
try { dataType = Type.GetType( dataTypeString ); }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem instantiating type " + ( null != dataTypeString ? "\"" + dataTypeString + "\"" : "<<NULL>>" ), ex ); }
|
||||
|
||||
string dataLengthString = null;
|
||||
try { dataLengthString = reader.GetAttribute( DataLengthXmlTag ); }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem extracting data length string representation from XML", ex ); }
|
||||
|
||||
dataLength = 0;
|
||||
try { dataLength = int.Parse( dataLengthString, cult ); }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem parsing data length from string representation " + ( null != dataLengthString ? "\"" + dataLengthString + "\"" : "<<NULL>>" ), ex ); }
|
||||
|
||||
Array dataArray = null;
|
||||
try { dataArray = Array.CreateInstance( dataType, dataLength ); }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem creating data array of type " + ( null != dataType ? "\"" + dataType.FullName + "\"" : "<<NULL>>" ) + " and length " + dataLength.ToString( ) , ex ); }
|
||||
|
||||
try { this.Values = (DataType[])dataArray; }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem assigning data array dynamically created from XML to Data.Values", ex ); }
|
||||
}
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem creating data array from XML", ex );
|
||||
}
|
||||
|
||||
try { this.ScaleFactorMv = double.Parse( reader.GetAttribute( DataAdcToMvScaleFactorTag ), cult ); }
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem parsing ADC->MV scaling factor property", ex );
|
||||
}
|
||||
|
||||
try { this.MvPerEu = double.Parse( reader.GetAttribute( DataMvPerEuTag ), cult ); }
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem parsing MV/EU sensitivity factor property", ex );
|
||||
}
|
||||
|
||||
MemberInfo[] dataTypeMembers = typeof( DataType ).GetMember( "Parse" );
|
||||
if ( null == dataTypeMembers || dataTypeMembers.Length < 1 )
|
||||
throw new Exception( "data type does not contain a \"Parse\" method" );
|
||||
else if ( dataLength > 0 )
|
||||
{
|
||||
Object dataTypeObject = null;
|
||||
try { dataTypeObject = Activator.CreateInstance( dataType ); }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem creating an instance of type " + ( null != dataType ? typeof( DataType ).FullName : "<<NULL>>" ), ex ); }
|
||||
|
||||
Type[] paramTypes = new Type[ 1 ];
|
||||
paramTypes[ 0 ] = Type.GetType( "System.String" );
|
||||
|
||||
MethodInfo parseMethodInfo = null;
|
||||
try { parseMethodInfo = dataType.GetMethod( "Parse", paramTypes ); }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem getting \"Parse\" method information from data type " + dataType.FullName, ex ); }
|
||||
|
||||
for ( int i=0; i < this.Values.Length; i++ )
|
||||
{
|
||||
reader.Read( );
|
||||
reader.MoveToContent( );
|
||||
|
||||
string datumValueString = null;
|
||||
try { datumValueString = reader.GetAttribute( DatumValueXmlTag ); }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem extracting datum value string representation from XML", ex ); }
|
||||
|
||||
Object[] parameters = new Object[ 1 ];
|
||||
parameters[ 0 ] = datumValueString;
|
||||
DataType parseResult;
|
||||
try { parseResult = (DataType)parseMethodInfo.Invoke( dataTypeObject, parameters ); }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem invoking \"Parse\" method on string representation " + ( null != datumValueString ? datumValueString : "<<NULL>>" ), ex ); }
|
||||
|
||||
try { this.Values[ i ] = parseResult; }
|
||||
catch ( System.Exception ex ) { throw new Exception( "encountered problem inserting parse result " + ( null != parseResult ? parseResult.ToString( ) : "<<NULL>>" ) + " into collection of data values", ex ); }
|
||||
}
|
||||
}
|
||||
|
||||
reader.Read( );
|
||||
reader.MoveToContent( );
|
||||
|
||||
if ( reader.Name.Equals( DataXmlTag, StringComparison.OrdinalIgnoreCase ) )
|
||||
{ //
|
||||
// This needs to be conditional in case we get inline data of length
|
||||
// zero. Though this probably will only ever happen under unit test.
|
||||
//
|
||||
reader.ReadEndElement( ); // consume attribute end tag.
|
||||
reader.MoveToContent( );
|
||||
}
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem converting XML to DTS.Serialization.Test.Module.Channel.Data object", ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should normally return a schema representing the form of the XML
|
||||
/// generated/consumed by WriteXml/ReadXml, but it never called during
|
||||
/// the serialization process so ours just returns null.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// Null <see cref="XmlSchema"/> reference, always.
|
||||
/// </returns>
|
||||
///
|
||||
public XmlSchema GetSchema( )
|
||||
{
|
||||
// This method is never invoked during XML object serialization.
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the specified object for equality with this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="obj">
|
||||
/// The <see cref="object"/> to be tested for equality.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if the specified object has memeberwise equality with
|
||||
/// this object; false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
public override bool Equals( object obj )
|
||||
{
|
||||
DataArray<DataType> that = obj as DataArray<DataType>;
|
||||
try
|
||||
{
|
||||
return (null != that)
|
||||
&& this.ScaleFactorMv.Equals( that.ScaleFactorMv )
|
||||
&& this.MvPerEu.Equals( that.MvPerEu )
|
||||
&& (this.Values.Length == that.Values.Length)
|
||||
&& this.ValuesEquals( that.Values );
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem equality-testing object " + ( null != obj ? "\"" + obj.ToString( )+ "\"" : "<<NULL>>" ), ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the specified object's module list for equality with this object's
|
||||
/// data list.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="thoseChannels">
|
||||
/// The <see cref="List"/> of <see cref="Dts.Serialization.Test"/> object to be
|
||||
/// compared for equality with this test's equivalent.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if the two lists contain equivalent-valued members;
|
||||
/// false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
private bool ValuesEquals( DataType[] thoseValues )
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( null == thoseValues || this.Values.Length != thoseValues.Length )
|
||||
return false;
|
||||
else for ( int i=0; i < this.Values.Length; i++ )
|
||||
if ( !this.Values[ i ].Equals( thoseValues[ i ] ) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem equality testing value array", ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the hash code for this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="int"/> hash code for this object.
|
||||
/// </returns>
|
||||
///
|
||||
public override int GetHashCode( )
|
||||
{
|
||||
return base.GetHashCode( );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* TDAS.File.BinaryChannelHeader.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utils;
|
||||
|
||||
namespace DTS.Serialization.TDAS
|
||||
{
|
||||
// *** see TDAS.File.cs ***
|
||||
public partial class File
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Representation of the information found in a binary channel header.
|
||||
/// </summary>
|
||||
///
|
||||
public class TDASBinaryChannelHeader
|
||||
: Exceptional,
|
||||
IChannelHeader
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Get/set acquisition rate value.
|
||||
/// </summary>
|
||||
public Double AcquisitionRate
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set number of pre-T0 data points.
|
||||
/// </summary>
|
||||
public int NumberOfPreT0DataPoints
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set number of post-T0 data points.
|
||||
/// </summary>
|
||||
public int NumberOfPostT0DataPoints
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set z.
|
||||
/// </summary>
|
||||
public int PreZeroLevelInCnts
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set z.
|
||||
/// </summary>
|
||||
public int PreCalLevelInCnts
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set z.
|
||||
/// </summary>
|
||||
public Double SignalToNoiseRatioInDb
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set z.
|
||||
/// </summary>
|
||||
public int PostZeroLevelInCnts
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set z.
|
||||
/// </summary>
|
||||
public int PostCalLevelInCnts
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set z.
|
||||
/// </summary>
|
||||
public int DataZeroLevelInCnts
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set scale factor MV.
|
||||
/// </summary>
|
||||
public Double ScaleFactorMVPerCnt
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set z.
|
||||
/// </summary>
|
||||
public Double ScaleFactorEUPerCnt
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the CRC32 for this binary channe header.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="stripEuPadding">
|
||||
/// <see cref="bool"/> option enables/disables automatic stripping of EU padding.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The CRC32 of the binary channel header.
|
||||
/// </returns>
|
||||
///
|
||||
private UInt32 CalculateCrc32(bool stripEuPadding, bool bKeepEuLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = new List<byte>();
|
||||
|
||||
data.AddRange(BitConverter.GetBytes(AcquisitionRate));
|
||||
data.AddRange(BitConverter.GetBytes(NumberOfPreT0DataPoints));
|
||||
data.AddRange(BitConverter.GetBytes(NumberOfPostT0DataPoints));
|
||||
data.AddRange(BitConverter.GetBytes(PreZeroLevelInCnts));
|
||||
data.AddRange(BitConverter.GetBytes(PreCalLevelInCnts));
|
||||
data.AddRange(BitConverter.GetBytes(SignalToNoiseRatioInDb));
|
||||
data.AddRange(BitConverter.GetBytes(PostZeroLevelInCnts));
|
||||
data.AddRange(BitConverter.GetBytes(PostCalLevelInCnts));
|
||||
data.AddRange(BitConverter.GetBytes(DataZeroLevelInCnts));
|
||||
data.AddRange(BitConverter.GetBytes(ScaleFactorMVPerCnt));
|
||||
data.AddRange(BitConverter.GetBytes(ScaleFactorEUPerCnt));
|
||||
if (data.Count % 2 > 0) data.Add(0x0);
|
||||
var byteDataArray = data.ToArray();
|
||||
ushort crc = 0xFFFF;
|
||||
for (var i = 0; i < data.Count; i += 2)
|
||||
crc = Utils.Math_DoCRC16Step(BitConverter.ToUInt16(byteDataArray, i), crc);
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem calculating CRC 32", ex);
|
||||
}
|
||||
}
|
||||
public UInt32 UnpaddedEuStringPaddedEuLengthCrc32
|
||||
{
|
||||
get
|
||||
{
|
||||
try { return CalculateCrc32(true, true); }
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting CRC32 for binary header channel with unpadded EU string and padded EU Length", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Get The CRC for the current state of the header (autostrip padding from EU first).
|
||||
/// </summary>
|
||||
public UInt32 UnpaddedEuCrc32
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return CalculateCrc32(true, false);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting CRC32 for binary header channel with unpadded EU string", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the CRC for the current state of the header.
|
||||
/// </summary>
|
||||
public UInt32 Crc32
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return CalculateCrc32(false, false);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem generating CRC for binary channel header information", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* SliceRaw.File.BinaryChannelHeader.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.Utils;
|
||||
|
||||
namespace DTS.Serialization.SliceRaw
|
||||
{
|
||||
// *** see SliceRaw.File.cs ***
|
||||
public partial class File
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Representation of the information found in a binary channel header.
|
||||
/// </summary>
|
||||
///
|
||||
public class BinaryChannelHeader
|
||||
: Exceptional,
|
||||
IChannelHeader
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// "Magic Key" required for our binary file type.
|
||||
/// </summary>
|
||||
///
|
||||
public static uint RequiredMagicKey => 0x2C36351F;
|
||||
|
||||
public static uint CurrentVersionNumber => 0x04;
|
||||
|
||||
/// <summary>
|
||||
/// Header version number required for our binary file type.
|
||||
/// </summary>
|
||||
public static List<uint> KnownHeaderVersionNumbers => new List<uint>(new uint[] { 0x01, 0x02, 0x03, 0x04 });
|
||||
|
||||
/// <summary>
|
||||
/// "Magic Key" relatively-UID <see cref="UInt32"/> for our binary file type.
|
||||
/// </summary>
|
||||
public uint MagicKey
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="UInt32"/> header version number for our binary file type.
|
||||
/// </summary>
|
||||
public uint HeaderVersionNumber
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set offset of sample data start value.
|
||||
/// </summary>
|
||||
public ulong OffsetOfSampleDataStart
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set number of samples.
|
||||
/// </summary>
|
||||
public ulong NumberOfSamples
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set number of bits per sample.
|
||||
/// </summary>
|
||||
public uint NumberOfBitsPerSample
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set signed sample indicator.
|
||||
/// </summary>
|
||||
public uint AreSamplesSigned
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set sample rate value.
|
||||
/// </summary>
|
||||
public double SampleRate
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set number of triggers.
|
||||
/// </summary>
|
||||
public ushort NumberOfTriggers
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the trigger sample numbers
|
||||
/// </summary>
|
||||
public ulong[] TriggerSampleNumbers
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the number of adjustment samples for the channel
|
||||
/// The nature of level triggered is such that a number of qualification samples must pass before the
|
||||
/// trigger is issued and then backdated to where the trigger started, which requires all other units
|
||||
/// all be adjusted
|
||||
/// </summary>
|
||||
public int TriggerAdjustmentSamples
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/set pre test zero level counts.
|
||||
/// </summary>
|
||||
public int PreTestZeroLevelCounts
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the number of Analog Data Counts (ADC) removed during any hardware
|
||||
/// zeroing on the device.
|
||||
/// In the case of SLICE the firmware will remove as much offset as possible and zero the DAC
|
||||
/// </summary>
|
||||
public int RemovedADC
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set pre test diagnostics level counts.
|
||||
/// </summary>
|
||||
public int PreTestDiagnosticsLevelCounts
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the Analog Data Counts (ADC) when 0mV is injected
|
||||
/// (SLICE 1 can not inject 0mV and so will always return 0)
|
||||
/// </summary>
|
||||
public int ZeroMvInADC
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The average ADC over the Zero Window specified for the channel
|
||||
/// </summary>
|
||||
public int WindowAverageADC
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initial Offset in ADC
|
||||
/// </summary>
|
||||
public int OriginalOffsetADC
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/set pre test noise percentage of full scale.
|
||||
/// </summary>
|
||||
public double PreTestNoisePercentageOfFullScale
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// excitation on this channel
|
||||
/// with SLICE2 excitation can differ on each channel, so this gives a firm placeholder for information
|
||||
/// </summary>
|
||||
public double Excitation
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set post test zero level counts.
|
||||
/// </summary>
|
||||
public int PostTestZeroLevelCounts
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set post test diagnostics level counts.
|
||||
/// </summary>
|
||||
public int PostTestDiagnosticsLevelCounts
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set data zero level counts.
|
||||
/// </summary>
|
||||
public int DataZeroLevelCounts
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set scale factor MV.
|
||||
/// </summary>
|
||||
public double ScaleFactorMv
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set sensitivity MV/EU
|
||||
/// </summary>
|
||||
public double MvPerEu
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set EU field length (with terminator).
|
||||
/// </summary>
|
||||
public ushort EuFieldLengthWithTerminator
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set engineering units.
|
||||
/// </summary>
|
||||
public char[] EngineeringUnit
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set ISO code.
|
||||
/// </summary>
|
||||
public char[] IsoCode
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private const int HEADER_VERSION_REMOVEDADC = 2;
|
||||
private const int HEADER_VERSION_3 = 3;
|
||||
private const int HEADER_VERSION_4 = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the CRC32 for this binary channe header.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="stripEuPadding">
|
||||
/// <see cref="bool"/> option enables/disables automatic stripping of EU padding.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The CRC32 of the binary channel header.
|
||||
/// </returns>
|
||||
///
|
||||
private uint CalculateCrc32(bool stripEuPadding, bool bKeepEuLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = new List<byte>();
|
||||
|
||||
data.AddRange(BitConverter.GetBytes(MagicKey));
|
||||
data.AddRange(BitConverter.GetBytes(HeaderVersionNumber));
|
||||
data.AddRange(BitConverter.GetBytes(OffsetOfSampleDataStart));
|
||||
data.AddRange(BitConverter.GetBytes(NumberOfSamples));
|
||||
data.AddRange(BitConverter.GetBytes(NumberOfBitsPerSample));
|
||||
data.AddRange(BitConverter.GetBytes(NumberOfSamples));
|
||||
data.AddRange(BitConverter.GetBytes(AreSamplesSigned));
|
||||
data.AddRange(BitConverter.GetBytes(SampleRate));
|
||||
data.AddRange(BitConverter.GetBytes(NumberOfTriggers));
|
||||
|
||||
for (var i = 0; i < TriggerSampleNumbers.Length; i++)
|
||||
data.AddRange(BitConverter.GetBytes(TriggerSampleNumbers[i]));
|
||||
|
||||
data.AddRange(BitConverter.GetBytes(PreTestZeroLevelCounts));
|
||||
//data.AddRange(BitConverter.GetBytes(PreTestZeroLevelMv));
|
||||
if (HeaderVersionNumber >= HEADER_VERSION_REMOVEDADC) { data.AddRange(BitConverter.GetBytes(RemovedADC)); }
|
||||
if (HeaderVersionNumber >= HEADER_VERSION_3)
|
||||
{
|
||||
data.AddRange(BitConverter.GetBytes(Excitation));
|
||||
data.AddRange(BitConverter.GetBytes(TriggerAdjustmentSamples));
|
||||
data.AddRange(BitConverter.GetBytes(ZeroMvInADC));
|
||||
data.AddRange(BitConverter.GetBytes(OriginalOffsetADC));
|
||||
}
|
||||
if (HeaderVersionNumber >= HEADER_VERSION_4)
|
||||
{
|
||||
data.AddRange(BitConverter.GetBytes(WindowAverageADC));
|
||||
}
|
||||
data.AddRange(BitConverter.GetBytes(PreTestDiagnosticsLevelCounts));
|
||||
data.AddRange(BitConverter.GetBytes(PreTestNoisePercentageOfFullScale));
|
||||
data.AddRange(BitConverter.GetBytes(PostTestZeroLevelCounts));
|
||||
data.AddRange(BitConverter.GetBytes(PostTestDiagnosticsLevelCounts));
|
||||
data.AddRange(BitConverter.GetBytes(DataZeroLevelCounts));
|
||||
data.AddRange(BitConverter.GetBytes(ScaleFactorMv));
|
||||
data.AddRange(BitConverter.GetBytes(MvPerEu));
|
||||
|
||||
// Some data sets have an erroneous EuFieldLengthWithTerminator value that's +1 what it should be,
|
||||
// so we'll want to make an allowance for these ones too.
|
||||
var plusOneFieldLengthBugErrorPresent = EuFieldLengthWithTerminator > EngineeringUnit.Length + 1;
|
||||
if (bKeepEuLength) { plusOneFieldLengthBugErrorPresent = true; }
|
||||
|
||||
var padAdjustedEu = new string(EngineeringUnit).Trim().ToCharArray();
|
||||
if (!stripEuPadding)
|
||||
{ //
|
||||
// If we want to calculate the CRC of the header with leading/trailing
|
||||
// whitespace intact/added.
|
||||
//
|
||||
if (padAdjustedEu.Length % 2 != 0)
|
||||
padAdjustedEu = (new string(padAdjustedEu) + ' ').ToCharArray();
|
||||
}
|
||||
|
||||
|
||||
var euBA = Encoding.UTF8.GetBytes(padAdjustedEu);
|
||||
var euFieldLength = plusOneFieldLengthBugErrorPresent ? EuFieldLengthWithTerminator : (ushort)(euBA.Length + 1);
|
||||
data.AddRange(BitConverter.GetBytes(euFieldLength));
|
||||
|
||||
for (var i = 0; i < padAdjustedEu.Length; i++)
|
||||
data.AddRange(BitConverter.GetBytes(padAdjustedEu[i]));
|
||||
|
||||
for (var i = 0; i < IsoCode.Length; i++)
|
||||
data.AddRange(BitConverter.GetBytes(IsoCode[i]));
|
||||
|
||||
// We need to pad the offset so DIAdem .dat file word alignment will work. DIAdem .dat files reference the .chn files directly.
|
||||
if (data.Count % 2 > 0) data.Add(0x0);
|
||||
var byteDataArray = data.ToArray();
|
||||
//APILogger.Log($"[DTM]: data array for CRC: {BitConverter.ToString(byteDataArray)}");
|
||||
ushort crc = 0xFFFF;
|
||||
for (var i = 0; i < data.Count; i += 2)
|
||||
crc = Utils.Math_DoCRC16Step(BitConverter.ToUInt16(byteDataArray, i), crc);
|
||||
//APILogger.Log($"[DTM]: crc {crc}");
|
||||
return crc;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem calculating CRC 32", ex);
|
||||
}
|
||||
}
|
||||
public uint UnpaddedEuStringPaddedEuLengthCrc32
|
||||
{
|
||||
get
|
||||
{
|
||||
try { return CalculateCrc32(true, true); }
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting CRC32 for binary header channel with unpadded EU string and padded EU Length", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Get The CRC for the current state of the header (autostrip padding from EU first).
|
||||
/// </summary>
|
||||
public uint UnpaddedEuCrc32
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return CalculateCrc32(true, false);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting CRC32 for binary header channel with unpadded EU string", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the CRC for the current state of the header.
|
||||
/// </summary>
|
||||
public uint Crc32
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return CalculateCrc32(false, false);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem generating CRC for binary channel header information", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.DASLib.Service;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
public class EventInfoAggregate
|
||||
{
|
||||
public string EventId { get; set; }
|
||||
public string EventDescription { get; set; }
|
||||
public double DurationSeconds { get; set; }
|
||||
public string GUID { get; set; }
|
||||
public bool HasBeenDownloaded { get; set; }
|
||||
public bool WasTriggered { get; set; }
|
||||
public int NumberOfChannels { get; set; }
|
||||
public UInt64 NumberOfSamples { get; set; }
|
||||
public UInt64 NumberOfBytes { get; set; }
|
||||
public bool Faulted { get; set; }
|
||||
public int EventNumber { get; set; }
|
||||
|
||||
private readonly Dictionary<IDASCommunication, int> _eventIndices = new Dictionary<IDASCommunication, int>();
|
||||
private List<IDASCommunication> _das = null;
|
||||
private Slice.Control.Event _event;
|
||||
|
||||
public Slice.Control.Event GetEvent(bool bClear)
|
||||
{
|
||||
if (bClear) { _event = null; }
|
||||
return GetEvent();
|
||||
}
|
||||
public Slice.Control.Event GetEvent()
|
||||
{
|
||||
if (null == _event)
|
||||
{
|
||||
_event = new Slice.Control.Event(GetDasList(), this);
|
||||
}
|
||||
return _event;
|
||||
}
|
||||
|
||||
public int GetEventIndex(IDASCommunication idas)
|
||||
{
|
||||
if (!_eventIndices.ContainsKey(idas)) { throw new NotImplementedException(string.Format("ERROR in GetEventIndex for {0}", idas.SerialNumber)); }
|
||||
return _eventIndices[idas];
|
||||
}
|
||||
public List<IDASCommunication> GetDasList()
|
||||
{
|
||||
if (null == _das)
|
||||
{
|
||||
_das = new List<IDASCommunication>();
|
||||
_das.AddRange(_eventIndices.Keys.ToArray());
|
||||
}
|
||||
return _das;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public EventInfoAggregate(DownloadReport.EventInfo newEvent)
|
||||
{
|
||||
EventId = newEvent.TestID;
|
||||
EventDescription = newEvent.Description;
|
||||
DurationSeconds = newEvent.Modules[0].PreTriggerSeconds + newEvent.Modules[0].PostTriggerSeconds;
|
||||
GUID = newEvent.TestGUID.ToString();
|
||||
HasBeenDownloaded = newEvent.HasBeenDownloaded;
|
||||
WasTriggered = newEvent.WasTriggered;
|
||||
NumberOfChannels = newEvent.Modules.Sum(s => s.Channels.Length);
|
||||
NumberOfSamples = newEvent.Modules[0].NumberOfSamples;
|
||||
NumberOfBytes = NumberOfSamples * (ulong)NumberOfChannels * (ulong)2;
|
||||
Faulted = 0 != newEvent.FaultFlags;
|
||||
EventNumber = newEvent.EventNumber;
|
||||
_eventIndices.Add(newEvent.Modules[0].OwningDAS, newEvent.EventNumber);
|
||||
}
|
||||
public void Add(DownloadReport.EventInfo newEvent)
|
||||
{
|
||||
if (newEvent.TestID != EventId)
|
||||
{
|
||||
APILogger.Log("Warning, expected matching test ids: ", newEvent.TestID, EventId);
|
||||
}
|
||||
if (newEvent.Description != EventDescription)
|
||||
{
|
||||
APILogger.Log("Warning, expected matching test descriptions: ", newEvent.Description);
|
||||
}
|
||||
var duration = newEvent.Modules[0].PreTriggerSeconds + newEvent.Modules[0].PostTriggerSeconds;
|
||||
if (duration != DurationSeconds)
|
||||
{
|
||||
APILogger.Log("Warning, durations don't match: ", duration, DurationSeconds);
|
||||
DurationSeconds = Math.Min(DurationSeconds, duration);
|
||||
}
|
||||
if (newEvent.TestGUID.ToString() != GUID)
|
||||
{
|
||||
APILogger.Log("Warning, expected test GUIDs to match,", GUID, newEvent.TestGUID.ToString());
|
||||
}
|
||||
if (newEvent.HasBeenDownloaded != HasBeenDownloaded)
|
||||
{
|
||||
APILogger.Log("Warning, event has been downloaded from one unit, but not another");
|
||||
}
|
||||
if (newEvent.WasTriggered != WasTriggered)
|
||||
{
|
||||
APILogger.Log("Warning, one unit has triggered, but another has not");
|
||||
}
|
||||
var faulted = 0 != newEvent.FaultFlags;
|
||||
Faulted = Faulted || faulted;
|
||||
if (newEvent.Modules[0].NumberOfSamples != NumberOfSamples)
|
||||
{
|
||||
APILogger.Log("Warning, expected number of samples to match", NumberOfSamples, newEvent.Modules[0].NumberOfSamples);
|
||||
NumberOfSamples = Math.Min(NumberOfSamples, newEvent.Modules[0].NumberOfSamples);
|
||||
}
|
||||
if (newEvent.EventNumber != EventNumber)
|
||||
{
|
||||
APILogger.Log("Warning, expected event numbers to match", EventNumber, newEvent.EventNumber);
|
||||
}
|
||||
NumberOfChannels += newEvent.Modules.Sum(s => s.Channels.Length);
|
||||
NumberOfBytes = (ulong)2 * (ulong)NumberOfChannels * NumberOfSamples;
|
||||
_eventIndices.Add(newEvent.Modules[0].OwningDAS, newEvent.EventNumber);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* SliceRaw.File.PersistentChannel.DependencyNotInitializedException.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DTS.Serialization.SliceRaw
|
||||
{
|
||||
// *** see SliceRaw.File.cs ***
|
||||
public partial class File
|
||||
{
|
||||
|
||||
// *** see SliceRaw.File.PersistentChannel.cs ***
|
||||
public partial class PersistentChannel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Representation of an attempt to get a property that has an uninitialized dependency.
|
||||
/// </summary>
|
||||
public class DependencyNotInitializedException : ApplicationException
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DependencyNotInitializedException class.
|
||||
/// </summary>
|
||||
///
|
||||
public DependencyNotInitializedException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DependencyNotInitializedException class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="msg">
|
||||
/// The <see cref="string"/> message to be associated with this exception.
|
||||
/// </param>
|
||||
///
|
||||
public DependencyNotInitializedException(string msg)
|
||||
: base(msg)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DependencyNotInitializedException class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="msg">
|
||||
/// The <see cref="string"/> message to be associated with this exception.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="innerEx">
|
||||
/// The <see cref="System.Exception"/> responsible for this exception exception.
|
||||
/// </param>
|
||||
///
|
||||
public DependencyNotInitializedException(string msg, System.Exception innerEx)
|
||||
: base(msg, innerEx)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
} // *** end PersistentChannel ***
|
||||
} // *** end File ***
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace DTS.Serialization.TSV
|
||||
{
|
||||
public class TSVChannel
|
||||
{
|
||||
private readonly TSVTest _parentTest;
|
||||
|
||||
private readonly Dictionary<TSVTest.Fields, string> _values = new Dictionary<TSVTest.Fields, string>();
|
||||
public string GetValue(TSVTest.Fields field)
|
||||
{
|
||||
if (!_values.ContainsKey(field)) { _values.Add(field, "#NOVALUE"); }
|
||||
return _values[field];
|
||||
}
|
||||
public void SetValue(TSVTest.Fields field, string value)
|
||||
{
|
||||
_values[field] = value;
|
||||
switch (field)
|
||||
{
|
||||
case TSVTest.Fields.DataType:
|
||||
if (value == "Raw")
|
||||
{
|
||||
SetValue(TSVTest.Fields.EngineeringUnits, "ADC");
|
||||
SetValue(TSVTest.Fields.DigitalFilterType, "");
|
||||
var actualRange = _parentTest.ActualRangesADC[_channelIndex];
|
||||
|
||||
SetValue(TSVTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
|
||||
|
||||
FileName = System.IO.Path.Combine(System.IO.Path.Combine(_path, "TSV"), "Raw");
|
||||
FileName = System.IO.Path.Combine(FileName, string.Format("{0}_{1}.TSV", _parentTest.Test.Id, ChannelNumber));
|
||||
}
|
||||
else if (value == "Processed")
|
||||
{
|
||||
SetValue(TSVTest.Fields.EngineeringUnits, _engineeringUnits);
|
||||
SetValue(TSVTest.Fields.DigitalFilterType, string.Format("CFC {0}/{1}", _parentTest.DataFilteredEU[_channelIndex].FilterDescription, _parentTest.DataFilteredEU[_channelIndex].FilterFrequencyHz));
|
||||
var actualRange = _parentTest.ActualRangesEUFiltered[_channelIndex];
|
||||
|
||||
SetValue(TSVTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
|
||||
FileName = System.IO.Path.Combine(System.IO.Path.Combine(_path, "TSV"), "Processed");
|
||||
FileName = System.IO.Path.Combine(FileName, string.Format("{0}_{1}.TSV", _parentTest.Test.Id, ChannelNumber));
|
||||
}
|
||||
else if (value == "Converted")
|
||||
{
|
||||
SetValue(TSVTest.Fields.EngineeringUnits, _engineeringUnits);
|
||||
SetValue(TSVTest.Fields.DigitalFilterType, "");
|
||||
var actualRange = _parentTest.ActualRangesEUUnfiltered[_channelIndex];
|
||||
|
||||
SetValue(TSVTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
|
||||
FileName = System.IO.Path.Combine(System.IO.Path.Combine(_path, "TSV"), "Converted");
|
||||
FileName = System.IO.Path.Combine(FileName, string.Format("{0}_{1}.TSV", _parentTest.Test.Id, ChannelNumber));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
private readonly string _engineeringUnits = "";
|
||||
public string FileName { get; set; }
|
||||
|
||||
public void Serialize(TickEventHandler tickHandler)
|
||||
{
|
||||
|
||||
if (!System.IO.Directory.Exists(new System.IO.FileInfo(FileName).Directory.FullName))
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(new System.IO.FileInfo(FileName).Directory.FullName);
|
||||
}
|
||||
using (var sw = new System.IO.StreamWriter(FileName, false, Encoding.Default))
|
||||
{
|
||||
var fields = Enum.GetValues(typeof(TSVTest.Fields)).Cast<TSVTest.Fields>().ToArray();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
sw.WriteLine("{0}\t{1}", TSVStrings.ResourceManager.GetString(string.Format("{0}_Title", field.ToString())),
|
||||
GetValue(field));
|
||||
}
|
||||
var channel = _parentTest.Test.Channels[_channelIndex] as Test.Module.AnalogInputChannel;
|
||||
|
||||
double dStartTime = channel.ParentModule.StartRecordSampleNumber / channel.ParentModule.SampleRateHz;
|
||||
if (channel.ParentModule.TriggerSampleNumbers.Count > 0)
|
||||
{
|
||||
dStartTime -= channel.ParentModule.TriggerSampleNumbers[0] / channel.ParentModule.SampleRateHz;
|
||||
}
|
||||
//double increment = 1D / channel.ParentModule.SampleRateHz;
|
||||
var current = dStartTime;
|
||||
double percentageComplete = _channelIndex / _parentTest.Channels.Length;
|
||||
var weight = 1D / _parentTest.Channels.Length;
|
||||
var decimalplaces = Convert.ToInt32(Math.Ceiling(Math.Log10(channel.ParentModule.SampleRateHz)));
|
||||
double[] data;
|
||||
if (GetValue(TSVTest.Fields.DataType) == "Raw")
|
||||
{
|
||||
data = _parentTest.DataADC[_channelIndex].Data;
|
||||
}
|
||||
else if (GetValue(TSVTest.Fields.DataType) == "Converted")
|
||||
{
|
||||
data = _parentTest.DataUnfilteredEU[_channelIndex].Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = _parentTest.DataFilteredEU[_channelIndex].Data;
|
||||
}
|
||||
for (ulong i = 0; i < channel.ParentModule.NumberOfSamples; i++)
|
||||
{
|
||||
current = dStartTime + (double)i / channel.ParentModule.SampleRateHz;
|
||||
current = Truncate(current, decimalplaces);
|
||||
sw.WriteLine("{0}\t{1}", current, data[i]);
|
||||
if (0 == i % 1000)
|
||||
{
|
||||
var percent = 100D * (percentageComplete + i * weight / channel.ParentModule.NumberOfSamples);
|
||||
tickHandler(this, percent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private static double Truncate(double value, int decimalplaces)
|
||||
{
|
||||
var d = Math.Pow(10, decimalplaces);
|
||||
var tmp = (int)Math.Truncate(d * value);
|
||||
return tmp / d;
|
||||
}
|
||||
private readonly int _channelIndex = 0;
|
||||
public int ChannelNumber => 1 + _channelIndex;
|
||||
private readonly string _path;
|
||||
public TSVChannel(TSVTest parentTest, int channelIndex, string path)
|
||||
{
|
||||
_path = path;
|
||||
_parentTest = parentTest;
|
||||
_channelIndex = channelIndex;
|
||||
var aic = parentTest.Test.Channels[channelIndex] as Test.Module.AnalogInputChannel;
|
||||
|
||||
_engineeringUnits = aic.EngineeringUnits.TrimEnd();
|
||||
|
||||
SetValue(TSVTest.Fields.EngineeringUnits, aic.EngineeringUnits.TrimEnd());
|
||||
SetValue(TSVTest.Fields.SensorMakeModelSerial, aic.SerialNumber);
|
||||
SetValue(TSVTest.Fields.SensorLocation, aic.Description);
|
||||
|
||||
SetValue(TSVTest.Fields.DigitalFilterType, string.Format("CFC {0}/{1}", _parentTest.DataFilteredEU[_channelIndex].FilterDescription, _parentTest.DataFilteredEU[_channelIndex].FilterFrequencyHz));
|
||||
var actualRange = _parentTest.ActualRangesEUFiltered[_channelIndex];
|
||||
|
||||
SetValue(TSVTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
|
||||
FileName = System.IO.Path.Combine(System.IO.Path.Combine(path, "TSV"), "Processed");
|
||||
FileName = System.IO.Path.Combine(FileName, string.Format("{0}_{1}.TSV", parentTest.Test.Id, 1 + channelIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,698 @@
|
||||
/*
|
||||
Test.cs
|
||||
|
||||
Copyright © 2008
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.Utilities.Xml;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Representation of a serializable test information.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("Test")]
|
||||
public partial class Test : Exceptional, IXmlSerializable
|
||||
{
|
||||
|
||||
private readonly Property<string> _software
|
||||
= new Property<string>(typeof(Test).Namespace + ".Test.Software", "DataPRO", true);
|
||||
[XmlSerializationTag("Software")]
|
||||
public string Software
|
||||
{
|
||||
get => _software.Value;
|
||||
set => _software.Value = value;
|
||||
}
|
||||
|
||||
private readonly Property<string> _softwareVersion
|
||||
= new Property<string>(typeof(Test).Namespace + ".Test.SoftwareVersion", "", false);
|
||||
[XmlSerializationTag("SoftwareVersion")]
|
||||
public string SoftwareVersion
|
||||
{
|
||||
get => _softwareVersion.Value;
|
||||
set => _softwareVersion.Value = value;
|
||||
}
|
||||
/// <summary>
|
||||
/// clears all extended fault flags
|
||||
/// http://manuscript.dts.local/f/cases/39223/
|
||||
/// </summary>
|
||||
public void ClearExtendedFaultFlags()
|
||||
{
|
||||
ExtendedFaultFlags1 = 0;
|
||||
ExtendedFaultFlags2 = 0;
|
||||
ExtendedFaultFlags3 = 0;
|
||||
ExtendedFaultFlags4 = 0;
|
||||
}
|
||||
public Test()
|
||||
{
|
||||
TryGetChannelOrder();
|
||||
//
|
||||
// Note that the parameterless constructor for this object will leave
|
||||
// the Id and Description paramters
|
||||
} //
|
||||
public Test(string dtsfile)
|
||||
{
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Initialize an instance of the Test class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="id">
|
||||
/// The <see cref="string"/> ID of this test.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="description">
|
||||
/// The <see cref="string"/> description of this test.
|
||||
/// </param>
|
||||
///
|
||||
public Test(string id, string description) : this(id, description, 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the Test class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="id">
|
||||
/// The <see cref="string"/> ID of this test.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="description">
|
||||
/// The <see cref="string"/> description of this test.
|
||||
/// </param>
|
||||
///
|
||||
public Test(string id, string description, int eventNumber)
|
||||
{
|
||||
TryGetChannelOrder();
|
||||
try
|
||||
{
|
||||
Id = id;
|
||||
Description = description;
|
||||
EventNumber = eventNumber;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem constructing Test object (Id: " + (!string.IsNullOrEmpty(id) ? id : "<<NULL>>") + "Description: " + (!string.IsNullOrEmpty(description) ? description : "<<NULL>>") + ")", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the date of this object's serialization's creation (if applicable).
|
||||
/// </summary>
|
||||
public DateTime InceptionDate
|
||||
{
|
||||
get => _InceptionDate.Value;
|
||||
set => _InceptionDate.Value = value;
|
||||
}
|
||||
private readonly Property<DateTime> _InceptionDate
|
||||
= new Property<DateTime>(
|
||||
typeof(Test).Namespace + ".Test.InceptionDate",
|
||||
DateTime.Now,
|
||||
false
|
||||
);
|
||||
|
||||
private readonly Dictionary<string, int> _channelOrder = new Dictionary<string, int>();
|
||||
|
||||
private static string GetID(Module.Channel channel)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(channel.SensorID)) { return channel.SensorID; }
|
||||
return channel.ChannelDescriptionString;
|
||||
}
|
||||
public class ChannelOrderComparor : IComparer<Module.Channel>
|
||||
{
|
||||
private readonly IDictionary<string, int> _dictionary;
|
||||
|
||||
public ChannelOrderComparor(IDictionary<string, int> dictionary)
|
||||
{
|
||||
_dictionary = dictionary;
|
||||
}
|
||||
public int Compare(Module.Channel a, Module.Channel b)
|
||||
{
|
||||
var keyA = GetID(a);
|
||||
var keyB = GetID(b);
|
||||
var iA = _dictionary.ContainsKey(keyA) ? _dictionary[keyA] : int.MaxValue;
|
||||
var iB = _dictionary.ContainsKey(keyB) ? _dictionary[keyB] : int.MaxValue;
|
||||
return iA.CompareTo(iB);
|
||||
}
|
||||
}
|
||||
public void TryGetChannelOrder()
|
||||
{
|
||||
try
|
||||
{
|
||||
_channelOrder.Clear();
|
||||
if (System.IO.File.Exists("ChannelOrder.txt"))
|
||||
{
|
||||
using (var sr = new System.IO.StreamReader("ChannelOrder.txt"))
|
||||
{
|
||||
string line;
|
||||
var i = 0;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
_channelOrder.Add(line, i++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("Exception getting channel order", ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Get a named-DAS/numbered-channel accessor to this Event's channels.
|
||||
/// </summary>
|
||||
public List<Module.Channel> Channels
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_channelOrder.Count < 1) { TryGetChannelOrder(); }
|
||||
var allChannels = new List<Module.Channel>();
|
||||
foreach (var testModule in Modules)
|
||||
{
|
||||
allChannels.AddRange(testModule.Channels);
|
||||
allChannels.AddRange(testModule.CalculatedChannels);
|
||||
}
|
||||
allChannels.Sort(new Comparison<Module.Channel>(CompareChannels));
|
||||
if (_channelOrder.Count > 0) { allChannels.Sort(new ChannelOrderComparor(_channelOrder)); }
|
||||
return allChannels;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting all test channels", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int CompareChannels(Module.Channel left, Module.Channel right)
|
||||
{
|
||||
if (left == right) { return 0; }
|
||||
if (null == left) { return -1; }
|
||||
if (null == right) { return 1; }
|
||||
var ret = left.AbsoluteDisplayOrder.CompareTo(right.AbsoluteDisplayOrder);
|
||||
if (0 == ret)
|
||||
{
|
||||
ret = left.ParentModule.Number.CompareTo(right.ParentModule.Number);
|
||||
}
|
||||
if (0 == ret)
|
||||
{
|
||||
return left.Number.CompareTo(right.Number);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/// <summary>
|
||||
/// The string ID of this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("Id")]
|
||||
public string Id
|
||||
{
|
||||
get => _Id.Value;
|
||||
set => _Id.Value = value;
|
||||
}
|
||||
private readonly Property<string> _Id
|
||||
= new Property<string>(typeof(Test).Namespace + ".Test.Id", "", false);
|
||||
|
||||
/// <summary>
|
||||
/// The string description of this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("Description")]
|
||||
public string Description
|
||||
{
|
||||
get => _Description.Value;
|
||||
set => _Description.Value = value;
|
||||
}
|
||||
private readonly Property<string> _Description
|
||||
= new Property<string>(typeof(Test).Namespace + ".Test.Description", "", false);
|
||||
//FB 18312 Added event number
|
||||
/// <summary>
|
||||
/// The event number of this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("EventNumber")]
|
||||
public int EventNumber
|
||||
{
|
||||
get => _eventNumber.Value;
|
||||
set => _eventNumber.Value = value;
|
||||
}
|
||||
private readonly Property<int> _eventNumber
|
||||
= new Property<int>(typeof(Test).Namespace + ".Test.EventNumber", 0, false);
|
||||
|
||||
/// <summary>
|
||||
/// The globally unique identification string for this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("Guid")]
|
||||
public Guid Guid
|
||||
{
|
||||
get => _Guid.Value;
|
||||
set => _Guid.Value = value;
|
||||
}
|
||||
private readonly Property<Guid> _Guid
|
||||
= new Property<Guid>(typeof(Test).Namespace + ".Test.Guid", new Guid("00000000-0000-0000-0000-000000000000"), false);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The globally unique identification string for this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("FaultFlags")]
|
||||
public ushort FaultFlags
|
||||
{
|
||||
get => _FaultFlags.Value;
|
||||
set => _FaultFlags.Value = value;
|
||||
}
|
||||
private readonly Property<ushort> _FaultFlags
|
||||
= new Property<ushort>(typeof(Test).Namespace + ".Test.FaultFlags", 0, false);
|
||||
|
||||
[XmlSerializationTag("ExtendedFaultFlags1")]
|
||||
public uint ExtendedFaultFlags1
|
||||
{
|
||||
get => _ExtendedFaultFlags1.Value;
|
||||
set => _ExtendedFaultFlags1.Value = value;
|
||||
}
|
||||
private readonly Property<uint> _ExtendedFaultFlags1
|
||||
= new Property<uint>(typeof(Test).Namespace + ".Test.ExtendedFaultFlags1", 0, true);
|
||||
|
||||
[XmlSerializationTag("ExtendedFaultFlags2")]
|
||||
public uint ExtendedFaultFlags2
|
||||
{
|
||||
get => _ExtendedFaultFlags2.Value;
|
||||
set => _ExtendedFaultFlags2.Value = value;
|
||||
}
|
||||
private readonly Property<uint> _ExtendedFaultFlags2
|
||||
= new Property<uint>(typeof(Test).Namespace + ".Test.ExtendedFaultFlags2", 0, true);
|
||||
|
||||
[XmlSerializationTag("ExtendedFaultFlags3")]
|
||||
public uint ExtendedFaultFlags3
|
||||
{
|
||||
get => _ExtendedFaultFlags3.Value;
|
||||
set => _ExtendedFaultFlags3.Value = value;
|
||||
}
|
||||
private readonly Property<uint> _ExtendedFaultFlags3
|
||||
= new Property<uint>(typeof(Test).Namespace + ".Test.ExtendedFaultFlags3", 0, true);
|
||||
|
||||
[XmlSerializationTag("ExtendedFaultFlags4")]
|
||||
public uint ExtendedFaultFlags4
|
||||
{
|
||||
get => _ExtendedFaultFlags4.Value;
|
||||
set => _ExtendedFaultFlags4.Value = value;
|
||||
}
|
||||
private readonly Property<uint> _ExtendedFaultFlags4
|
||||
= new Property<uint>(typeof(Test).Namespace + ".Test.ExtendedFaultFlags4", 0, true);
|
||||
/// <summary>
|
||||
/// Get/set inline serialized data switch.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("InlineSerializedData")]
|
||||
public bool InlineSerializedData
|
||||
{
|
||||
get => _InlineSerializedData.Value;
|
||||
set
|
||||
{
|
||||
try
|
||||
{
|
||||
_InlineSerializedData.Value = value;
|
||||
foreach (var module in Modules)
|
||||
module.InlineSerializedData = value;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem setting test InlineSerializedData state", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private readonly Property<bool> _InlineSerializedData
|
||||
= new Property<bool>(typeof(Test).Namespace + ".Test.InlineSerializedData", false, true);
|
||||
|
||||
/// <summary>
|
||||
/// The list of modules in this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("Modules")]
|
||||
public List<Module> Modules
|
||||
{
|
||||
get => _Modules.Value;
|
||||
set => _Modules.Value = value;
|
||||
}
|
||||
private readonly Property<List<Module>> _Modules
|
||||
= new Property<List<Module>>(typeof(Test).Namespace + ".Test.Modules", new List<Module>(), true);
|
||||
|
||||
/// <summary>
|
||||
/// The list of das timestamps in this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("DasTimestamps")]
|
||||
public List<DasTimestamp> DasTimestamps
|
||||
{
|
||||
get => _DasTimestamps.Value;
|
||||
set => _DasTimestamps.Value = value;
|
||||
}
|
||||
private readonly Property<List<DasTimestamp>> _DasTimestamps
|
||||
= new Property<List<DasTimestamp>>(typeof(Test).Namespace + ".Test.DasTimestamps", new List<DasTimestamp>(), true);
|
||||
|
||||
/// <summary>
|
||||
/// Write XML serialization for this object to the specified writer.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="writer">
|
||||
/// The <see cref="XmlWriter"/> to which this object's XML serialization
|
||||
/// will be written.
|
||||
/// </param>
|
||||
///
|
||||
public void WriteXml(XmlWriter writer)
|
||||
{
|
||||
try
|
||||
{
|
||||
var attributeExtractor = new AttributeExtractor<XmlSerializationTagAttribute>();
|
||||
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Id").Value, Id);
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Description").Value, Description);
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "EventNumber").Value, EventNumber.ToString());
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "InlineSerializedData").Value, InlineSerializedData.ToString());
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Guid").Value, Guid.ToString());
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "FaultFlags").Value, FaultFlags.ToString());
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "ExtendedFaultFlags1").Value, ExtendedFaultFlags1.ToString());
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "ExtendedFaultFlags2").Value, ExtendedFaultFlags2.ToString());
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "ExtendedFaultFlags3").Value, ExtendedFaultFlags3.ToString());
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "ExtendedFaultFlags4").Value, ExtendedFaultFlags4.ToString());
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Software").Value, Software?.ToString() ?? "UNKNOWN");
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "SoftwareVersion").Value, SoftwareVersion?.ToString() ?? "UNKNOWN");
|
||||
|
||||
writer.WriteStartElement(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Modules").Value);
|
||||
|
||||
foreach (var module in Modules)
|
||||
{
|
||||
module.WriteXml(writer);
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "DasTimestamps").Value);
|
||||
|
||||
foreach (var stamp in DasTimestamps)
|
||||
{
|
||||
stamp.WriteXml(writer);
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem converting DTS.Serialization.Test object to XML", ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// retrieves an attribute if present as an UINT, if not present returns a default value
|
||||
/// </summary>
|
||||
private uint GetUintSafe(string tag,
|
||||
uint defaultValue,
|
||||
XmlReader reader,
|
||||
AttributeExtractor<XmlSerializationTagAttribute> attributeExtractor)
|
||||
{
|
||||
try
|
||||
{
|
||||
var attr = attributeExtractor.ExtractAttachedAttributeFromProperty(this, tag).Value;
|
||||
if (string.IsNullOrEmpty(attr)) { return defaultValue; }
|
||||
attr = reader.GetAttribute(attr);
|
||||
if (string.IsNullOrEmpty(attr)) { return defaultValue; }
|
||||
return Convert.ToUInt32(attr);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log($"Failed to extract attribute: {tag}", ex);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
/// <summary>
|
||||
/// Read XML serialization for this object from the specified reader.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="reader">
|
||||
/// The <see cref="XmlReader"/> from which this object's XML serialization
|
||||
/// will be read.
|
||||
/// </param>
|
||||
///
|
||||
public void ReadXml(XmlReader reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
var attributeExtractor = new AttributeExtractor<XmlSerializationTagAttribute>();
|
||||
|
||||
if (reader.IsStartElement("Test"))
|
||||
{
|
||||
Id = reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Id").Value);
|
||||
Description = reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Description").Value);
|
||||
EventNumber = Convert.ToInt32(reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "EventNumber").Value));
|
||||
InlineSerializedData = bool.Parse(reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "InlineSerializedData").Value));
|
||||
|
||||
try { Guid = new Guid(reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Guid").Value)); }
|
||||
catch (System.Exception) { Guid = new Guid("00000000-0000-0000-0000-000000000000"); }
|
||||
|
||||
try { FaultFlags = Convert.ToUInt16(reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "FaultFlags").Value)); }
|
||||
catch (System.Exception) { FaultFlags = 0; }
|
||||
|
||||
ExtendedFaultFlags1 = GetUintSafe("ExtendedFaultFlags1", 0, reader, attributeExtractor);
|
||||
ExtendedFaultFlags2 = GetUintSafe("ExtendedFaultFlags2", 0, reader, attributeExtractor);
|
||||
ExtendedFaultFlags3 = GetUintSafe("ExtendedFaultFlags3", 0, reader, attributeExtractor);
|
||||
ExtendedFaultFlags4 = GetUintSafe("ExtendedFaultFlags4", 0, reader, attributeExtractor);
|
||||
|
||||
try { Software = reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Software").Value); }
|
||||
catch (System.Exception) { Software = "unknown"; }
|
||||
|
||||
try { SoftwareVersion = reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "SoftwareVersion").Value); }
|
||||
catch (System.Exception) { SoftwareVersion = "unknown"; }
|
||||
|
||||
Modules.Clear();
|
||||
|
||||
if (reader.ReadToDescendant("Modules"))
|
||||
{
|
||||
if (reader.ReadToDescendant("Module"))
|
||||
{
|
||||
do
|
||||
{
|
||||
var deserializedModule = new Module(this);
|
||||
deserializedModule.InlineSerializedData = InlineSerializedData;
|
||||
|
||||
//Give the deserializer a separate reader so that it can't go amuck and read past the current module.
|
||||
deserializedModule.ReadXml(reader.ReadSubtree());
|
||||
Modules.Add(deserializedModule);
|
||||
}
|
||||
while (reader.ReadToNextSibling("Module"));
|
||||
}
|
||||
}
|
||||
|
||||
DasTimestamps.Clear();
|
||||
|
||||
if (reader.ReadToDescendant("DasTimestamps"))
|
||||
{
|
||||
if (reader.ReadToDescendant("DasTimestamp"))
|
||||
{
|
||||
do
|
||||
{
|
||||
var deserializedDasTimestamp = new DasTimestamp(this);
|
||||
//deserializedDasTimestamp.InlineSerializedData = InlineSerializedData;
|
||||
|
||||
//Give the deserializer a separate reader so that it can't go amuck and read past the current timestamp.
|
||||
deserializedDasTimestamp.ReadXml(reader.ReadSubtree());
|
||||
DasTimestamps.Add(deserializedDasTimestamp);
|
||||
}
|
||||
while (reader.ReadToNextSibling("DasTimestamp"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem converting XML to DTS.Serialization.Test object", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should normally return a schema representing the form of the XML
|
||||
/// generated/consumed by WriteXml/ReadXml, but it never called during
|
||||
/// the serialization process so ours just returns null.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// Null <see cref="XmlSchema"/> reference, always.
|
||||
/// </returns>
|
||||
///
|
||||
public XmlSchema GetSchema()
|
||||
{
|
||||
// This method is never invoked during XML object serialization.
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the specified object for equality with this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="obj">
|
||||
/// The <see cref="object"/> to be tested for equality.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if the specified object has memeberwise equality with
|
||||
/// this object; false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(obj is Test that)) { return false; }
|
||||
return Id.Equals(that.Id)
|
||||
&& Description.Equals(that.Description)
|
||||
&& ModulesEquals(that.Modules);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem equality testing object " + (null != obj ? "\"" + obj.ToString() + "\"" : "<<NULL>>"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the specified object's module list for equality with this object's
|
||||
/// module list.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="thoseModules">
|
||||
/// The <see cref="List"/> of <see cref="Dts.Serialization.Test"/> object to be
|
||||
/// compared for equality with this test's equivalent.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if the two lists contain equivalent-valued members;
|
||||
/// false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
private bool ModulesEquals(List<Module> thoseModules)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Modules.Count != thoseModules.Count)
|
||||
return false;
|
||||
for (var i = 0; i < thoseModules.Count; i++)
|
||||
if (!Modules[i].Equals(thoseModules[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem equality-testing module list", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the hash code for this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="int"/> hash code for this object.
|
||||
/// </returns>
|
||||
///
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
private const string END_TAG1 = "</Test>";
|
||||
private const string END_TAG2 = "</TestSetup>";
|
||||
/// <summary>
|
||||
/// returns the metadata at the end of a DTS file (or an empty string if there is none)
|
||||
/// </summary>
|
||||
private static string GetMetaDataFromDTSFile(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!System.IO.File.Exists(path)) { return string.Empty; }
|
||||
var allText = System.IO.File.ReadAllText(path);
|
||||
var startIndex = allText.IndexOf(END_TAG1);
|
||||
var endIndex = allText.IndexOf(END_TAG2);
|
||||
|
||||
if (startIndex >= END_TAG1.Length && endIndex > startIndex)
|
||||
{
|
||||
startIndex += END_TAG1.Length;
|
||||
allText = allText.Substring(startIndex, endIndex - startIndex + END_TAG2.Length);
|
||||
if (allText.StartsWith("\r\n")) { allText = allText.Substring(2); }
|
||||
return allText;
|
||||
}
|
||||
|
||||
return allText;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
public void SaveTest(string directory, string testId, int defaultEncoding,
|
||||
bool includeGroupNameInISOExport)
|
||||
{
|
||||
try
|
||||
{
|
||||
//Back up .dts file if necessary
|
||||
var dtsFilePath = Path.Combine(directory, testId + ".dts");
|
||||
var dtsBackupFilePath = dtsFilePath + ".bak";
|
||||
var metaData = GetMetaDataFromDTSFile(dtsFilePath);
|
||||
//Back up dts file only if a backup file does not exist. This should guarantee that the
|
||||
//original file is the only one that is preserved.
|
||||
var backupExisted = System.IO.File.Exists(dtsBackupFilePath);
|
||||
if (!backupExisted && System.IO.File.Exists(dtsFilePath))
|
||||
{
|
||||
System.IO.File.Move(dtsFilePath, dtsBackupFilePath);
|
||||
}
|
||||
|
||||
//Spit out <Test> portion
|
||||
var f = new SliceRaw.File();
|
||||
|
||||
//Write the SLICEWare-compatible info so that SLICEWare can display the data if desired.
|
||||
f.DefaultEncoding = defaultEncoding;
|
||||
f.Exporter.Write(directory, testId, this, false, includeGroupNameInISOExport, 0D, 0);
|
||||
|
||||
//Append the <TestSetup> DataPRO info to the end of the existing .dts file which already contains SLICEWare-compatible info
|
||||
using (var writer = new StringWriter())
|
||||
{
|
||||
Encoding encoder;
|
||||
try
|
||||
{
|
||||
//force UTF-16 for the dts file, it contains "UTF-16" in the xml by default and isn't consumed by anything that requires
|
||||
//codepage exports (CSV/excel)
|
||||
encoder = Encoding.Unicode; //UTF-16
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("Problem getting encoder", ex);
|
||||
encoder = Encoding.Default;
|
||||
}
|
||||
|
||||
using (var fileWriter = new StreamWriter(dtsFilePath, true, encoder))
|
||||
{
|
||||
fileWriter.Write(fileWriter.NewLine + writer);
|
||||
fileWriter.Write(metaData);
|
||||
//FB9374: successful save without error. if we created a backup for this save, remove it
|
||||
if (!backupExisted) { System.IO.File.Delete(dtsBackupFilePath); }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* DTS.Slice.Control.Event.Module.AnalogInputChannel.ReviewableIsoCodeAttribute.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace DTS.Slice.Control
|
||||
{
|
||||
// *** see DTS.Slice.Control.Event.cs ***
|
||||
public partial class Event
|
||||
{
|
||||
|
||||
// *** see DTS.Slice.Control.Event.Module.cs ***
|
||||
public partial class Module
|
||||
{
|
||||
|
||||
// *** see DTS.Slice.Control.Event.Module.AnalogInputChannel.cs ***
|
||||
public partial class AnalogInputChannel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A reviewable serial number attribute attached to a specific channel.
|
||||
/// </summary>
|
||||
public class ReviewableIsoCodeAttribute
|
||||
: Slice.Control.Event.Module.Channel.ReviewableAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize an instance of this class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="channel">
|
||||
/// The <see cref="Event.Module.Channel"/> to which this attribute is attached.
|
||||
/// </param>
|
||||
///
|
||||
public ReviewableIsoCodeAttribute(Event.Module.Channel channel)
|
||||
: base("ISO Code", delegate { return (channel as AnalogInputChannel).IsoCode.ToString(); })
|
||||
{
|
||||
}
|
||||
}
|
||||
} // *** end Channel ***
|
||||
} // *** end Module ***
|
||||
} // *** end Event ***
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
|
||||
namespace IRIGCh10
|
||||
{
|
||||
/// <summary>
|
||||
/// allows annotating enums with a description attribute, in chapter 10 this allows us
|
||||
/// to associate an enum with a string to put in the TMATS file for that enum
|
||||
/// </summary>
|
||||
public static class DescriptionDecoder
|
||||
{
|
||||
public static string GetDescription(Enum value)
|
||||
{
|
||||
var fi = value.GetType().GetField(value.ToString());
|
||||
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(
|
||||
typeof(DescriptionAttribute), false);
|
||||
if (attributes.Any())
|
||||
{
|
||||
return attributes.First().Description;
|
||||
}
|
||||
return value.ToString();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// a lot of attributes in chapter 10 have a max length associated with them
|
||||
/// note however though that max length in chapter 10 is just a suggested
|
||||
/// max length, not a requirement ...
|
||||
/// </summary>
|
||||
public static class MaxLengthDecoder
|
||||
{
|
||||
public static int GetMaxLength(Enum value)
|
||||
{
|
||||
var fi = value.GetType().GetField(value.ToString());
|
||||
var attributes = (MaxLengthAttribute[])fi.GetCustomAttributes(
|
||||
typeof(MaxLengthAttribute), false);
|
||||
if (attributes.Any())
|
||||
{
|
||||
return attributes.First().Length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
using DTS.Serialization.IRIGCh10.Attributes;
|
||||
using DTS.Serialization.IRIGCH10.Enums;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10
|
||||
{
|
||||
/// <summary>
|
||||
/// implements the packet header portion of a packet
|
||||
/// </summary>
|
||||
public class PacketHeader : IPacketHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// used to indicate the start of a packet, is defined to 0x25, 0xEB by chapter10.pdf
|
||||
/// </summary>
|
||||
public ushort PacketSyncPattern { get; set; } = BitConverter.ToUInt16(new byte[] { 0x25, 0xEB }, 0);
|
||||
/// <summary>
|
||||
/// this is just a shortcut to avoid calculating the ushort value for 0x25,0xEB
|
||||
/// this is the ushort pattern expected for pattern sync
|
||||
/// </summary>
|
||||
public const ushort EXPECTED_SYNC_PATTERN = 60197;
|
||||
/// <summary>
|
||||
/// channel id, default to 0
|
||||
/// </summary>
|
||||
public ushort ChannelId { get; set; } = BitConverter.ToUInt16(new byte[] { 0x00, 0x00 }, 0);
|
||||
/// <summary>
|
||||
/// total length of the packet including header, data, and filler, and any checksums
|
||||
/// </summary>
|
||||
public uint PacketLength { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// length of the data portion of the packet, so sans filler and checksums
|
||||
/// </summary>
|
||||
public uint DataLength { get; set; } = 0;
|
||||
public byte DataVersion { get; set; } = 0;
|
||||
public byte SequenceNum { get; set; } = 0;
|
||||
[Browsable(false)]
|
||||
public byte PacketFlags { get; private set; } = 0;
|
||||
|
||||
public bool SecondaryHeaderPresent
|
||||
{
|
||||
get
|
||||
{
|
||||
var b = new BitArray(new[] { PacketFlags });
|
||||
return b.Get(7);
|
||||
}
|
||||
set
|
||||
{
|
||||
PacketFlags = SetBit(PacketFlags, 7, value);
|
||||
}
|
||||
}
|
||||
public bool IPTSTimeSource
|
||||
{
|
||||
get
|
||||
{
|
||||
var b = new BitArray(new[] { PacketFlags });
|
||||
return b.Get(6);
|
||||
}
|
||||
set
|
||||
{
|
||||
PacketFlags = SetBit(PacketFlags, 6, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool RTCSyncError
|
||||
{
|
||||
get
|
||||
{
|
||||
var b = new BitArray(new[] { PacketFlags });
|
||||
return b.Get(5);
|
||||
}
|
||||
set
|
||||
{
|
||||
PacketFlags = SetBit(PacketFlags, 5, value);
|
||||
}
|
||||
}
|
||||
public enum SecondaryHeaderTimeFormats
|
||||
{
|
||||
Chapter4 = 0,
|
||||
IEEE1588 = 1,
|
||||
ExtendedRelativeTimeCounter = 2,
|
||||
Reserved = 3
|
||||
}
|
||||
public SecondaryHeaderTimeFormats SecondaryHeaderTimeFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
var b = new BitArray(new[] { PacketFlags });
|
||||
return (SecondaryHeaderTimeFormats)Utils.Utils.BitArrayToInt32(b, 2, 3);
|
||||
}
|
||||
set
|
||||
{
|
||||
var b = new BitArray(new[] { PacketFlags });
|
||||
Utils.Utils.SetBits(b, (uint)value, 2, 3);
|
||||
var ret = new byte[1];
|
||||
b.CopyTo(ret, 0);
|
||||
PacketFlags = ret[0];
|
||||
}
|
||||
}
|
||||
public bool DataOverflowError
|
||||
{
|
||||
get
|
||||
{
|
||||
var b = new BitArray(new[] { PacketFlags });
|
||||
return b.Get(4);
|
||||
}
|
||||
set
|
||||
{
|
||||
PacketFlags = SetBit(PacketFlags, 4, value);
|
||||
}
|
||||
}
|
||||
|
||||
private byte SetBit(byte input, int bit, bool bVal)
|
||||
{
|
||||
var b = new BitArray(new[] { input });
|
||||
b.Set(bit, bVal);
|
||||
var ret = new byte[1];
|
||||
b.CopyTo(ret, 0);
|
||||
return ret[0];
|
||||
}
|
||||
public enum DataCheckSumPresences
|
||||
{
|
||||
NotPresent = 0,
|
||||
EightBit = 1,
|
||||
SixteenBit = 2,
|
||||
ThirtyTwoBit = 3
|
||||
}
|
||||
|
||||
public DataCheckSumPresences CheckSumPresence
|
||||
{
|
||||
get
|
||||
{
|
||||
var b = new BitArray(new[] { PacketFlags });
|
||||
return (DataCheckSumPresences)Utils.Utils.BitArrayToInt32(b, 0, 1);
|
||||
}
|
||||
set
|
||||
{
|
||||
var b = new BitArray(new[] { PacketFlags });
|
||||
Utils.Utils.SetBits(b, (uint)value, 0, 1);
|
||||
var ret = new byte[1];
|
||||
b.CopyTo(ret, 0);
|
||||
PacketFlags = ret[0];
|
||||
}
|
||||
}
|
||||
[Browsable(false)]
|
||||
public byte DataType { get; set; } = 0;
|
||||
|
||||
public DataFileDataTypes DataFileType
|
||||
{
|
||||
get
|
||||
{
|
||||
var all = Enum.GetValues(typeof(DataFileDataTypes)).Cast<DataFileDataTypes>().ToArray();
|
||||
foreach (var datatype in all)
|
||||
{
|
||||
var b = PacketHeaderValueAttribute.GetPacketHeaderValue(datatype);
|
||||
if (b == DataType) { return datatype; }
|
||||
}
|
||||
return DataFileDataTypes.ComputerGeneratedDataFormat0;
|
||||
}
|
||||
}
|
||||
|
||||
//10 MHz Relative Time Counter
|
||||
[Browsable(false)]
|
||||
public byte[] RTC { get; set; } = new byte[6];
|
||||
|
||||
public long RTCLong
|
||||
{
|
||||
get
|
||||
{
|
||||
var bytes = new byte[8];
|
||||
Buffer.BlockCopy(RTC, 0, bytes, 0, 6);
|
||||
return BitConverter.ToInt64(bytes, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public ushort CheckSum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// the RealtimeCounter in the packet header is a 6 byte field
|
||||
/// for convenience we'll use a long to interact with it
|
||||
/// even though we are only using 6 bytes
|
||||
/// </summary>
|
||||
/// <param name="rtc"></param>
|
||||
public void SetRTC(long rtc)
|
||||
{
|
||||
var bytes = GetRTCBytes(rtc);
|
||||
Buffer.BlockCopy(bytes, 0, RTC, 0, RTC.Length);
|
||||
}
|
||||
private const int RTC_SIZE_BYTES = 6;
|
||||
public static byte[] GetRTCBytes(long rtc)
|
||||
{
|
||||
var s = rtc.ToString("X");
|
||||
var buffer = new byte[RTC_SIZE_BYTES];
|
||||
for (int i = 0; i < RTC_SIZE_BYTES; i++)
|
||||
{
|
||||
string sVal = s.Substring(i * 2, 2);
|
||||
var val = Convert.ToInt16(sVal, 16);
|
||||
buffer[buffer.Length - 1 - i] = BitConverter.GetBytes(val)[0];
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
public PacketHeader(DataFileDataTypes dataType)
|
||||
{
|
||||
DataType = PacketHeaderValueAttribute.GetPacketHeaderValue(dataType);
|
||||
}
|
||||
public PacketHeader(byte[] bytes)
|
||||
{
|
||||
if (null == bytes) { throw new NullReferenceException("no bytes received"); }
|
||||
if (PACKET_HEADER_LENGTH != bytes.Length) { throw new Exception($"Expected {PACKET_HEADER_LENGTH} bytes, received: {bytes.Length}"); }
|
||||
PacketSyncPattern = BitConverter.ToUInt16(bytes, 0);
|
||||
if (PacketSyncPattern != EXPECTED_SYNC_PATTERN)
|
||||
{
|
||||
System.Diagnostics.Trace.WriteLine("Expected sync pattern not found");
|
||||
}
|
||||
ChannelId = BitConverter.ToUInt16(bytes, 2);
|
||||
PacketLength = BitConverter.ToUInt32(bytes, 4);
|
||||
DataLength = BitConverter.ToUInt32(bytes, 8);
|
||||
DataVersion = bytes[12];
|
||||
SequenceNum = bytes[13];
|
||||
PacketFlags = bytes[14];
|
||||
DataType = bytes[15];
|
||||
RTC = new byte[6];
|
||||
Array.Copy(bytes, 16, RTC, 0, 6);
|
||||
CheckSum = BitConverter.ToUInt16(bytes, 22);
|
||||
var computedCRC = ComputeCheckSum();
|
||||
if (CheckSum != computedCRC)
|
||||
{
|
||||
System.Diagnostics.Trace.WriteLine("Checksum doesn't match");
|
||||
}
|
||||
}
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
using (var sw = new MemoryStream())
|
||||
{
|
||||
using (var bw = new BinaryWriter(sw))
|
||||
{
|
||||
bw.Write(PacketSyncPattern);
|
||||
bw.Write(ChannelId);
|
||||
bw.Write(PacketLength);
|
||||
bw.Write(DataLength);
|
||||
bw.Write(DataVersion);
|
||||
bw.Write(SequenceNum);
|
||||
bw.Write(PacketFlags);
|
||||
bw.Write(DataType);
|
||||
bw.Write(RTC);
|
||||
bw.Write(ComputeCheckSum());
|
||||
}
|
||||
return sw.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetDataVersion(DataTypeVersion version)
|
||||
{
|
||||
DataVersion = PacketHeaderValueAttribute.GetPacketHeaderValue(version);
|
||||
}
|
||||
|
||||
public void SetPacketFlags(bool SecondaryHeaderPresent,
|
||||
bool SecondaryHeaderTime,
|
||||
bool RTCSyncerror,
|
||||
bool DataOverflow,
|
||||
SecondaryHeaderTimeFormat fmt,
|
||||
DataCheckSumType checkSum
|
||||
)
|
||||
{
|
||||
var bitArray = new BitArray(new[] { PacketFlags });
|
||||
|
||||
bitArray[7] = SecondaryHeaderPresent;
|
||||
bitArray[6] = SecondaryHeaderTime;
|
||||
bitArray[5] = RTCSyncerror;
|
||||
bitArray[4] = DataOverflow;
|
||||
|
||||
var byteValue = new BitArray(new[] { PacketHeaderValueAttribute.GetPacketHeaderValue(fmt) });
|
||||
bitArray[3] = byteValue[0];
|
||||
bitArray[2] = byteValue[1];
|
||||
|
||||
byteValue = new BitArray(new[] { PacketHeaderValueAttribute.GetPacketHeaderValue(checkSum) });
|
||||
bitArray[1] = byteValue[0];
|
||||
bitArray[0] = byteValue[1];
|
||||
var bytes = new byte[1];
|
||||
bitArray.CopyTo(bytes, 0);
|
||||
PacketFlags = bytes[0];
|
||||
}
|
||||
|
||||
public ushort ComputeCheckSum()
|
||||
{
|
||||
byte[] bytesToCompute;
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write(PacketSyncPattern);
|
||||
bw.Write(ChannelId);
|
||||
bw.Write(PacketLength);
|
||||
bw.Write(DataLength);
|
||||
bw.Write(DataVersion);
|
||||
bw.Write(SequenceNum);
|
||||
bw.Write(PacketFlags);
|
||||
bw.Write(DataType);
|
||||
bw.Write(RTC);
|
||||
}
|
||||
bytesToCompute = ms.ToArray();
|
||||
}
|
||||
return Utils.Utils.GetCheckSum16(bytesToCompute);
|
||||
}
|
||||
public const int PACKET_HEADER_LENGTH = 24;
|
||||
}
|
||||
|
||||
public interface IPacketHeader
|
||||
{
|
||||
ushort PacketSyncPattern { get; set; }
|
||||
ushort ChannelId { get; set; }
|
||||
uint PacketLength { get; set; }
|
||||
uint DataLength { get; set; }
|
||||
byte DataVersion { get; set; }
|
||||
byte SequenceNum { get; set; }
|
||||
[Browsable(false)]
|
||||
byte PacketFlags { get; }
|
||||
|
||||
bool SecondaryHeaderPresent { get; set; }
|
||||
bool IPTSTimeSource { get; set; }
|
||||
|
||||
bool RTCSyncError { get; set; }
|
||||
|
||||
PacketHeader.SecondaryHeaderTimeFormats SecondaryHeaderTimeFormat { get; set; }
|
||||
|
||||
bool DataOverflowError { get; set; }
|
||||
|
||||
PacketHeader.DataCheckSumPresences CheckSumPresence { get; set; }
|
||||
|
||||
|
||||
[Browsable(false)]
|
||||
byte DataType { get; set; }
|
||||
DataFileDataTypes DataFileType { get; }
|
||||
[Browsable(false)]
|
||||
byte[] RTC { get; set; }
|
||||
long RTCLong { get; }
|
||||
ushort CheckSum { get; set; }
|
||||
void SetRTC(long rtc);
|
||||
|
||||
void SetDataVersion(DataTypeVersion version);
|
||||
|
||||
void SetPacketFlags(bool SecondaryHeaderPresent,
|
||||
bool SecondaryHeaderTime,
|
||||
bool RTCSyncerror,
|
||||
bool DataOverflow,
|
||||
SecondaryHeaderTimeFormat fmt,
|
||||
DataCheckSumType checkSum
|
||||
);
|
||||
|
||||
byte[] GetBytes();
|
||||
ushort ComputeCheckSum();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
using IRIGCh10;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10.TMATS.DataConversion
|
||||
{
|
||||
public enum TransducerInformation
|
||||
{
|
||||
[Description("DCN")] [MaxLength(32)] MeasurementName,
|
||||
[Description("TRD1")] [MaxLength(32)] Type,
|
||||
[Description("TRD2")] [MaxLength(32)] ModelNumber,
|
||||
[Description("TRD3")] [MaxLength(32)] SerialNumber,
|
||||
[Description("TRD4")] [MaxLength(2)] SecurityClassification,
|
||||
[Description("TRD5")] [MaxLength(10)] OriginationDate,
|
||||
[Description("TRD6")] [MaxLength(4)] RevisionNumber,
|
||||
[MaxLength(32)] [Description("TRD7")] Orientation,
|
||||
[MaxLength(24)] [Description("POC1")] PointOfContactName,
|
||||
[MaxLength(48)] [Description("POC2")] PointOfContactAgency,
|
||||
[MaxLength(48)] [Description("POC3")] PointOfContectAddress,
|
||||
[MaxLength(20)] [Description("POC4")] PointOfContactTelephone,
|
||||
}
|
||||
|
||||
public enum ClassificationTypes
|
||||
{
|
||||
[Description("U")] Unclassified,
|
||||
[Description("C")] Confidential,
|
||||
[Description("S")] Secret,
|
||||
[Description("T")] TopSecret,
|
||||
[Description("O")] Other
|
||||
}
|
||||
/// <summary>
|
||||
/// this class handles the transducer information section of the TMAT packet (see chapter 9.pdf)
|
||||
/// </summary>
|
||||
public class TransducerInformationSection : TMATSSection<TransducerInformation>
|
||||
{
|
||||
public TransducerInformationSection(int number) : base(AttributeIdentifiers.DataConversionAttributes, number)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GIVE THE MEASUREMENT NAME.
|
||||
/// </summary>
|
||||
public string MeasurementName
|
||||
{
|
||||
get => GetValue(TransducerInformation.MeasurementName);
|
||||
set => SetValueWithLength(TransducerInformation.MeasurementName, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TYPE OF SENSOR, IF APPROPRIATE
|
||||
/// </summary>
|
||||
public string Type
|
||||
{
|
||||
get => GetValue(TransducerInformation.Type);
|
||||
set => SetValueWithLength(TransducerInformation.Type, value);
|
||||
}
|
||||
/// <summary>
|
||||
/// IF APPROPRIATE
|
||||
/// </summary>
|
||||
public string ModelNumber
|
||||
{
|
||||
get => GetValue(TransducerInformation.ModelNumber);
|
||||
set => SetValueWithLength(TransducerInformation.ModelNumber, value);
|
||||
}
|
||||
/// <summary>
|
||||
/// IF APPLICABLE
|
||||
/// </summary>
|
||||
public string SerialNumber
|
||||
{
|
||||
get => GetValue(TransducerInformation.SerialNumber);
|
||||
set => SetValueWithLength(TransducerInformation.SerialNumber, value);
|
||||
}
|
||||
/// <summary>
|
||||
/// ENTER THE SECURITY CLASSIFICATION OF THIS MEASURAND.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="signalClassified"></param>
|
||||
/// <param name="measurandClassified"></param>
|
||||
public void SetSecurityClassification(ClassificationTypes type,
|
||||
bool signalClassified, bool measurandClassified)
|
||||
{
|
||||
var val = DescriptionDecoder.GetDescription(type);
|
||||
if (signalClassified && measurandClassified)
|
||||
{
|
||||
val = $"{val}B";
|
||||
}
|
||||
else if (signalClassified)
|
||||
{
|
||||
val = $"{val}R";
|
||||
}
|
||||
else if (measurandClassified)
|
||||
{
|
||||
val = $"{val}E";
|
||||
}
|
||||
|
||||
SetValueWithLength(TransducerInformation.SecurityClassification, val);
|
||||
}
|
||||
/// <summary>
|
||||
/// DATE OF ORIGINATION OF THIS DATA FILE. DD – DAY MM – MONTH
|
||||
/// YYYY – YEAR (MM-DD-YYYY)
|
||||
/// </summary>
|
||||
public DateTime? OriginationDate
|
||||
{
|
||||
get
|
||||
{
|
||||
var val = GetValue(TransducerInformation.OriginationDate);
|
||||
if (string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (DateTime.TryParse(val, out var dt))
|
||||
{
|
||||
return dt;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (null == value)
|
||||
{
|
||||
SetValueWithLength(TransducerInformation.OriginationDate, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
var dt = (DateTime) value;
|
||||
SetValueWithLength(TransducerInformation.OriginationDate,
|
||||
$"{dt.Month:00}-{dt.Day:00}-{dt.Year:0000}");
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// SPECIFY THE REVISION NUMBER OF THE DATA PROVIDED.
|
||||
/// </summary>
|
||||
public string RevisionNumber
|
||||
{
|
||||
get => GetValue(TransducerInformation.RevisionNumber);
|
||||
set => SetValueWithLength(TransducerInformation.RevisionNumber, value);
|
||||
}
|
||||
/// <summary>
|
||||
/// DESCRIBE THE PHYSICAL ORIENTATION OF THE SENSOR.
|
||||
/// </summary>
|
||||
public string Orientation
|
||||
{
|
||||
get => GetValue(TransducerInformation.Orientation);
|
||||
set => SetValueWithLength(TransducerInformation.Orientation, value);
|
||||
}
|
||||
/// <summary>
|
||||
/// POINT OF CONTACT WITH THE ORGANIZATION THAT PROVIDED THE CALIBRATION DATA
|
||||
/// </summary>
|
||||
public POC PointOfContact
|
||||
{
|
||||
get => new POC()
|
||||
{
|
||||
Name = GetValue(TransducerInformation.PointOfContactName),
|
||||
Agency = GetValue(TransducerInformation.PointOfContactAgency),
|
||||
Address = GetValue(TransducerInformation.PointOfContectAddress),
|
||||
Telephone = GetValue(TransducerInformation.PointOfContectAddress)
|
||||
};
|
||||
set
|
||||
{
|
||||
SetValueWithLength(TransducerInformation.PointOfContactName, value.Name);
|
||||
SetValueWithLength(TransducerInformation.PointOfContactAgency, value.Agency);
|
||||
SetValueWithLength(TransducerInformation.PointOfContectAddress, value.Address);
|
||||
SetValueWithLength(TransducerInformation.PointOfContactTelephone, value.Telephone);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Point Of Contact structure
|
||||
/// </summary>
|
||||
public class POC
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Agency { get; set; }
|
||||
public string Address { get; set; }
|
||||
public string Telephone { get; set; }
|
||||
|
||||
public POC(string name, string agency, string address, string telephone)
|
||||
{
|
||||
Name = name;
|
||||
Agency = agency;
|
||||
Address = address;
|
||||
Telephone = telephone;
|
||||
}
|
||||
|
||||
public POC()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* TDAS.File.PersistentChannel.NotInitializedException.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DTS.Serialization.TDAS
|
||||
{
|
||||
// *** see TDAS.File.cs ***
|
||||
public partial class File
|
||||
{
|
||||
|
||||
// *** see TDAS.File.PersistentChannel.cs ***
|
||||
public partial class PersistentChannel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Representation of an attempt to get a property that has yet to be initialized.
|
||||
/// </summary>
|
||||
public class NotInitializedException : ApplicationException
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the NotInitializedException class.
|
||||
/// </summary>
|
||||
///
|
||||
public NotInitializedException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the NotInitializedException class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="msg">
|
||||
/// The <see cref="string"/> message to be associated with this exception.
|
||||
/// </param>
|
||||
///
|
||||
public NotInitializedException(string msg)
|
||||
: base(msg)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the NotInitializedException class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="msg">
|
||||
/// The <see cref="string"/> message to be associated with this exception.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="innerEx">
|
||||
/// The <see cref="System.Exception"/> responsible for this exception inception.
|
||||
/// </param>
|
||||
///
|
||||
public NotInitializedException(string msg, System.Exception innerEx)
|
||||
: base(msg, innerEx)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
} // *** end PersistentChannel ***
|
||||
} // *** end File ***
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Iso.File.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
// ISO implementation items:
|
||||
// ------------------------
|
||||
// * Do properly dynamically-presented/not-there-at-all comments.
|
||||
// * Comments.txt file.
|
||||
// * Progress reporting.
|
||||
|
||||
namespace DTS.Serialization.Iso
|
||||
{
|
||||
public partial class File
|
||||
: Serialization.File,
|
||||
IWritable<Test>
|
||||
{
|
||||
|
||||
private readonly Common.ISO.TestPlan _testPlan = null;
|
||||
public Common.ISO.TestPlan GetTestPlan() { return _testPlan; }
|
||||
///
|
||||
/// <summary>
|
||||
/// Initialize an instance of the Iso.File class.
|
||||
/// </summary>
|
||||
///
|
||||
public File(Common.ISO.TestPlan testplan)
|
||||
: base("ISO")
|
||||
{
|
||||
_testPlan = testplan;
|
||||
}
|
||||
public bool UseZeroForUnfiltered { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// when true forces the isocode for filter to by determined by the software filter for the channel
|
||||
/// </summary>
|
||||
public bool UseIsoCodeFilterMapping { get; set; }
|
||||
public bool FilteredExport { get; set; } = false;
|
||||
public bool ExportISOChannelName { get; set; } = false;
|
||||
|
||||
public void AddChannel(string dasserial, int moduleNumber, int number, string description, FilteredData data)
|
||||
{
|
||||
(Exporter as Writer).AddChannel(dasserial, moduleNumber, number, description, data);
|
||||
}
|
||||
|
||||
public void ApplyTestPlan(Serialization.Test test)
|
||||
{
|
||||
foreach (Common.ISO.TestPlan.IsoFields field in Enum.GetValues(typeof(Common.ISO.TestPlan.IsoFields)))
|
||||
{
|
||||
var value = GetTestPlan().GetField(field);
|
||||
switch (field)
|
||||
{
|
||||
case Common.ISO.TestPlan.IsoFields.CustName:
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.CustomerCostUnit:
|
||||
TestInstance.CustomerCostUnit = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.CustomerName:
|
||||
TestInstance.CustomerName = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.CustomerOrderNumber:
|
||||
TestInstance.CustomerOrderNumber = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.CustomerProjectReferenceNumber:
|
||||
TestInstance.CustomerProjectReferenceNumber = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TEName:
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TestEngineerEmail:
|
||||
TestInstance.TestEngineerEmail = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TestEngineerFax:
|
||||
TestInstance.TestEngineerFax = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TestEngineerName:
|
||||
TestInstance.TestEngineerName = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TestEngineerPhone:
|
||||
TestInstance.TestEngineerPhone = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.CustomerTestReferenceNumber:
|
||||
TestInstance.CustomerTestReferenceNumber = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.Date:
|
||||
if (DateTime.TryParse(value, out var temp))
|
||||
{
|
||||
TestInstance.Date = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
TestInstance.Date = test.InceptionDate;
|
||||
}
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.ExtraProperties:
|
||||
TestInstance.ExtraProperties = GetTestPlan().ExtraProperties.Select(kvp => new Test.ExtraProperty(kvp.Key, kvp.Value)).ToList();
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LabName:
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryContactEmail:
|
||||
TestInstance.LaboratoryContactEmail = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryContactFax:
|
||||
TestInstance.LaboratoryContactFax = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryContactName:
|
||||
TestInstance.LaboratoryContactName = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryContactPhone:
|
||||
TestInstance.LaboratoryContactPhone = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryName:
|
||||
TestInstance.LaboratoryName = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryTestReferenceNumber:
|
||||
TestInstance.LaboratoryTestReferenceNumber = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.LaboratoryProjectReferenceNumber:
|
||||
TestInstance.LaboratoryProjectReferenceNumber = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.NumberOfMedia:
|
||||
TestInstance.NumberOfMedia = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.NumberOfTestObjects:
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.ReferenceTemperature:
|
||||
TestInstance.ReferenceTemperature = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.Regulation:
|
||||
TestInstance.Regulation = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.RelativeAirHumidity:
|
||||
TestInstance.RelativeAirHumidity = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.Subtype:
|
||||
TestInstance.Subtype = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.TestComment:
|
||||
TestInstance.TestComment = value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.Title:
|
||||
TestInstance.Title = value == NoValue ? test.Id : value;
|
||||
break;
|
||||
case Common.ISO.TestPlan.IsoFields.Type:
|
||||
TestInstance.Type = value;
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("unsupported iso field");
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Get the file writer for this file type.
|
||||
/// </summary>
|
||||
public IWriter<Serialization.Test> Exporter
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_Exporter == null)
|
||||
{
|
||||
var writer = new Writer(this, DefaultEncoding, this);
|
||||
writer.UseZeroForUnfiltered = UseZeroForUnfiltered;
|
||||
writer.UseIsoCodeFilterMapping = UseIsoCodeFilterMapping;
|
||||
writer.FilteredExport = FilteredExport;
|
||||
writer.ExportISOChannelName = ExportISOChannelName;
|
||||
_Exporter = writer;
|
||||
}
|
||||
return _Exporter;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting exporter", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private IWriter<Serialization.Test> _Exporter = null;
|
||||
|
||||
/// <summary>
|
||||
/// File extension for the disk entity that contains the serialized test information.
|
||||
/// </summary>
|
||||
public static string TestFileExtension
|
||||
{
|
||||
get => _TestFileExtension.Value;
|
||||
private set => _TestFileExtension.Value = value;
|
||||
}
|
||||
private static readonly Property<string> _TestFileExtension = new Property<string>("TestFileExtension", ".mme", true);
|
||||
|
||||
/// <summary>
|
||||
/// File extension for the disk entity that contains serialized channel information.
|
||||
/// </summary>
|
||||
public static string ChannelFileExtension
|
||||
{
|
||||
get => _ChannelFileExtension.Value;
|
||||
private set => _ChannelFileExtension.Value = value;
|
||||
}
|
||||
private static readonly Property<string> _ChannelFileExtension = new Property<string>("ChannelFileExtension", ".chn", true);
|
||||
|
||||
/// <summary>
|
||||
/// String representation of a value-less field.
|
||||
/// </summary>
|
||||
private const string NoValue = "NOVALUE";
|
||||
|
||||
/// <summary>
|
||||
/// Line terminator to use when printing out files.
|
||||
/// </summary>
|
||||
private static readonly string Eol = Environment.NewLine;
|
||||
|
||||
/// <summary>
|
||||
/// Attribute/value seperator to use when printing out files.
|
||||
/// </summary>
|
||||
private const string Separator = ":";
|
||||
|
||||
/// <summary>
|
||||
/// Offset to use for attribute/value seperator when printing out files.
|
||||
/// </summary>
|
||||
private const int SeparatorOffset = 28;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for extracting the value of a field in a controllable context e.g., in
|
||||
/// a try/catch block.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="string"/> representation of the field.
|
||||
/// </returns>
|
||||
///
|
||||
private delegate string FieldValueStringExtractor();
|
||||
|
||||
/// <summary>
|
||||
/// Get a string representation of the field wrapped within the extractor delegate.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="extractor">
|
||||
/// The <see cref="DTS.Serialization.File.Iso.File.FieldValueStringExtractor"/> wrapping the
|
||||
/// field to be stringified.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// A <see cref="string"/> version of the field; "NOVALUE" if the field has not been initialized.
|
||||
/// </returns>
|
||||
///
|
||||
private static string GetFieldString(FieldValueStringExtractor extractor)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{ //
|
||||
// Empty string is no value.
|
||||
//
|
||||
|
||||
var fieldString = extractor();
|
||||
return (!string.IsNullOrEmpty(fieldString) ? fieldString : NoValue);
|
||||
}
|
||||
|
||||
catch (System.Exception)
|
||||
{
|
||||
return NoValue;
|
||||
}
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting field string from field extractor", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the <see cref="Iso.File.Test"/> associated with this file.
|
||||
/// </summary>
|
||||
public Test TestInstance => _TestInstance.Value;
|
||||
|
||||
private readonly Property<Test> _TestInstance
|
||||
= new Property<Test>(
|
||||
typeof(Test).Namespace + ".Iso.File.TestInstance",
|
||||
new Test(),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,423 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace DTS.Serialization {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class TSVStrings {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal TSVStrings() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DTS.Serialization.TSVStrings", typeof(TSVStrings).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to What freuqncy content the user can expect; Include notes of AAfilters applied and any applicable reasoning.
|
||||
/// </summary>
|
||||
internal static string AAFilterCutoffDescription_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("AAFilterCutoffDescription_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to AA Filter Cutoff description.
|
||||
/// </summary>
|
||||
internal static string AAFilterCutoffDescription_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("AAFilterCutoffDescription_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The resolution settings for the test in engineering units per bit.
|
||||
/// </summary>
|
||||
internal static string BitResolution_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("BitResolution_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bit Resolution(Units per bit).
|
||||
/// </summary>
|
||||
internal static string BitResolution_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("BitResolution_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Yes or No depending if channel errors are noted in the data.
|
||||
/// </summary>
|
||||
internal static string ChannelErrors_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("ChannelErrors_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Channel Errors (Y or N).
|
||||
/// </summary>
|
||||
internal static string ChannelErrors_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("ChannelErrors_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The type of data milestone this file supports.
|
||||
/// </summary>
|
||||
internal static string DataType_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("DataType_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Data Type (Raw, Converted, or Processed).
|
||||
/// </summary>
|
||||
internal static string DataType_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("DataType_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The digital filter applied and the cutoff in Hz.
|
||||
/// </summary>
|
||||
internal static string DigitalFilterType_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("DigitalFilterType_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Digital Filter Type/Cutoff (Hz).
|
||||
/// </summary>
|
||||
internal static string DigitalFilterType_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("DigitalFilterType_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Engineering units depicted in Converted and Processed Data sets; Voltages for Raw data.
|
||||
/// </summary>
|
||||
internal static string EngineeringUnits_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("EngineeringUnits_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Engineering Units.
|
||||
/// </summary>
|
||||
internal static string EngineeringUnits_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("EngineeringUnits_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Include the name of the University, Institution, and/or Lab that conducted the test.
|
||||
/// </summary>
|
||||
internal static string LabName_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("LabName_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Lab Name.
|
||||
/// </summary>
|
||||
internal static string LabName_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("LabName_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Any notes or descriptions useful in supporting data file analysis.
|
||||
/// </summary>
|
||||
internal static string Notes_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Notes_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Notes.
|
||||
/// </summary>
|
||||
internal static string Notes_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("Notes_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Include the name of the test Point of Contact.
|
||||
/// </summary>
|
||||
internal static string POCName_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("POCName_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to POC Name.
|
||||
/// </summary>
|
||||
internal static string POCName_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("POCName_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Include applicable lab phone number, email, etc. for contacting the POC.
|
||||
/// </summary>
|
||||
internal static string POCPhoneAndEmail_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("POCPhoneAndEmail_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to POC phone and email.
|
||||
/// </summary>
|
||||
internal static string POCPhoneAndEmail_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("POCPhoneAndEmail_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The data sampling rate in Hz.
|
||||
/// </summary>
|
||||
internal static string SamplingRate_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("SamplingRate_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sampling Rate (Hz).
|
||||
/// </summary>
|
||||
internal static string SamplingRate_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("SamplingRate_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The direction of the sensor axis; include whether direction is global or local.
|
||||
/// </summary>
|
||||
internal static string SensorAxis_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("SensorAxis_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sensor Axis (direction).
|
||||
/// </summary>
|
||||
internal static string SensorAxis_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("SensorAxis_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Location of the sensor, using body region codes.
|
||||
/// </summary>
|
||||
internal static string SensorLocation_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("SensorLocation_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sensor Location.
|
||||
/// </summary>
|
||||
internal static string SensorLocation_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("SensorLocation_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The brand name of the sensor used with the model name and serial number.
|
||||
/// </summary>
|
||||
internal static string SensorMakeModelSerial_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("SensorMakeModelSerial_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sensor Make Model Serial.
|
||||
/// </summary>
|
||||
internal static string SensorMakeModelSerial_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("SensorMakeModelSerial_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to If Applicable include the type of sensor mount: LOFFI, BOBKAT, glued, fixed, other.
|
||||
/// </summary>
|
||||
internal static string SensorMountType_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("SensorMountType_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sensor Mount Type.
|
||||
/// </summary>
|
||||
internal static string SensorMountType_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("SensorMountType_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Date the test was conducted.
|
||||
/// </summary>
|
||||
internal static string TestDate_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("TestDate_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Test Date.
|
||||
/// </summary>
|
||||
internal static string TestDate_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("TestDate_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Test Number that correlates with filename and README file test numbers. This is a lab generated test number that sequences the series of tests for a specific surrogate (PHMS or HIII).
|
||||
/// </summary>
|
||||
internal static string TestNumber_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("TestNumber_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Test Number.
|
||||
/// </summary>
|
||||
internal static string TestNumber_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("TestNumber_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Description of the objects being tested. PHMS with specimen ID, type of HIII, combination, or other.
|
||||
/// </summary>
|
||||
internal static string TestObject_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("TestObject_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Test Object (HIII, PMHS, combo, etc.).
|
||||
/// </summary>
|
||||
internal static string TestObject_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("TestObject_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Local lab time when the test was conducted.
|
||||
/// </summary>
|
||||
internal static string TestTime_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("TestTime_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Test Time.
|
||||
/// </summary>
|
||||
internal static string TestTime_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("TestTime_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Short text description of the type of test conducted.
|
||||
/// </summary>
|
||||
internal static string TestType_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("TestType_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Test Type (sled, blast, drop, etc.).
|
||||
/// </summary>
|
||||
internal static string TestType_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("TestType_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using DTS.Common;
|
||||
|
||||
namespace DTS.Serialization.Iso.Report
|
||||
{
|
||||
/// <summary>
|
||||
/// this class encapsulates a single line in the iso test summary report
|
||||
/// </summary>
|
||||
internal class ChannelData
|
||||
{
|
||||
/// <summary>
|
||||
/// the number of the channel among all channels in the data
|
||||
/// </summary>
|
||||
public int ChannelNumber { get; set; } = 1;
|
||||
/// <summary>
|
||||
/// the iso code for a channel
|
||||
/// </summary>
|
||||
public string ISOCode { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// the name of the channel (iso channel name)
|
||||
/// </summary>
|
||||
public string ChannelName { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// the channel filter class for the channel (as in test setup, does not need to match exported data)
|
||||
/// </summary>
|
||||
public string SAEFilterClass { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// the electronic id at test setup time for the channel
|
||||
/// </summary>
|
||||
public string SetupEID { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// the electronic id at run test time on channel
|
||||
/// </summary>
|
||||
public string DataCollectionEID { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// any data flags present on channel
|
||||
/// </summary>
|
||||
public DataFlag DataFlag { get; set; } = DataFlag.None;
|
||||
|
||||
public const string NAME_OF_CHANNEL = "Name of channel";
|
||||
public string GetLine()
|
||||
{
|
||||
return $"{NAME_OF_CHANNEL} {(1 + ChannelNumber):000} :{ISOCode} / {ChannelName} / {SAEFilterClass} / {SetupEID} / {DataCollectionEID} / {(int)DataFlag}";
|
||||
}
|
||||
/// <summary>
|
||||
/// creates a channeldata instance given a test data channel
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
/// <returns></returns>
|
||||
public static ChannelData CreateChannel(Test.Module.Channel channel)
|
||||
{
|
||||
var isoCode = string.Empty;
|
||||
var isoChannelName = string.Empty;
|
||||
string filter = string.Empty;
|
||||
if ( channel is Test.Module.AnalogInputChannel analog)
|
||||
{
|
||||
isoCode = analog.IsoCode;
|
||||
filter = analog.SoftwareFilter.Replace(" ", "");
|
||||
isoChannelName = analog.IsoChannelName;
|
||||
}
|
||||
var channelData = new ChannelData()
|
||||
{
|
||||
ChannelName = isoChannelName,
|
||||
ChannelNumber = channel.AbsoluteDisplayOrder,
|
||||
DataCollectionEID = channel.DataCollectionEID,
|
||||
DataFlag = (DataFlag)channel.DataFlag,
|
||||
ISOCode = isoCode,
|
||||
SAEFilterClass = filter,
|
||||
SetupEID = channel.SetupEID
|
||||
};
|
||||
return channelData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
Test.IntervalSec.cs
|
||||
|
||||
Copyright © 2008
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using DTS.Utilities;
|
||||
using DTS.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
// *** see test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
/// <summary>
|
||||
/// Get/set the begin value.
|
||||
/// </summary>
|
||||
public class IntervalSec : Exceptional
|
||||
{
|
||||
/// <summary>
|
||||
/// Create an instance of the IntervalSec class.
|
||||
/// </summary>
|
||||
public IntervalSec()
|
||||
{ //
|
||||
// Note that calling the parameterless constructor will leave the begin and
|
||||
// end properties "uninitialized".
|
||||
} //
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of the IntervalSec class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="begin">
|
||||
/// The <see cref="double"/> begin time of this interval.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="end">
|
||||
/// The <see cref="double"/> end time of this interval.
|
||||
/// </param>
|
||||
///
|
||||
public IntervalSec(double begin, double end)
|
||||
{
|
||||
try
|
||||
{
|
||||
Begin = begin;
|
||||
End = end;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem constructing \"IntervalSec\" object", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set whether or not Begin and End values are automatically rounded.
|
||||
/// </summary>
|
||||
public bool DoRoundOffValues { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the number of decimal places Begin and End values will automatically be rounded
|
||||
/// to if DoRoundOffValues property is true.
|
||||
/// </summary>
|
||||
public int NumberRoundingDecimalPlaces
|
||||
{
|
||||
get { return _NumberOfRoundingDecimalPlaces.Value; }
|
||||
set { _NumberOfRoundingDecimalPlaces.Value = value; }
|
||||
}
|
||||
private Property<int> _NumberOfRoundingDecimalPlaces =
|
||||
new Property<int>(
|
||||
typeof( IntervalSec ).Namespace + ".IntervalSec.NumberOfRoundingDecimalPlaces",
|
||||
6,
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> begin time of the interval.
|
||||
/// </summary>
|
||||
public double Begin
|
||||
{
|
||||
get { return DoRoundOffValues ? Math.Round( _Begin.Value, NumberRoundingDecimalPlaces ) : _Begin.Value; }
|
||||
set { _Begin.Value = value; }
|
||||
}
|
||||
private Property<double> _Begin
|
||||
= new Property<double>( typeof( IntervalSec ).Namespace + ".Test.IntervalSec.Begin", 0, false);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> end time of the interval.
|
||||
/// </summary>
|
||||
public double End
|
||||
{
|
||||
get { return DoRoundOffValues ? Math.Round( _End.Value, NumberRoundingDecimalPlaces ) : _End.Value ; }
|
||||
set { _End.Value = value; }
|
||||
}
|
||||
private Property<double> _End
|
||||
= new Property<double>( typeof( IntervalSec ).Namespace + ".Test.IntervalSec.End", 0, false);
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether or not this object and the one specified are equal.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="obj">
|
||||
/// The <see cref="object"/> to be equality-checked.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if the object is equal; false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
public override bool Equals( object obj )
|
||||
{
|
||||
try
|
||||
{
|
||||
IntervalSec that = obj as IntervalSec;
|
||||
return null != obj
|
||||
&& this.Begin.Equals( that.Begin )
|
||||
&& this.End.Equals( that.End );
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Test.IntervalSec.Exception( "encountered problem equality checking " + this.GetType( ).FullName, ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get has code for this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="int"/> hash code for this object.
|
||||
/// </returns>
|
||||
///
|
||||
public override int GetHashCode( )
|
||||
{
|
||||
try
|
||||
{
|
||||
return base.GetHashCode( );
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem generating hash code for " + this.GetType( ).FullName, ex );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,46 @@
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
//[Serializable]
|
||||
public partial class TestSetup : Exceptional
|
||||
{
|
||||
public partial class TestObject : Exceptional
|
||||
{
|
||||
public partial class TOChannel : Exceptional
|
||||
{
|
||||
public TOChannel()
|
||||
{
|
||||
_name.Value = null;
|
||||
_sensorName.Value = null;
|
||||
_version.Value = "1.0.0.0";
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name.Value;
|
||||
set => _name.Value = value;
|
||||
}
|
||||
private readonly Property<string> _name
|
||||
= new Property<string>(typeof(TOChannel).Namespace + ".Channel.Name", "", false);
|
||||
|
||||
public string SensorName
|
||||
{
|
||||
get => _sensorName.Value;
|
||||
set => _sensorName.Value = value;
|
||||
}
|
||||
private readonly Property<string> _sensorName
|
||||
= new Property<string>(typeof(TOChannel).Namespace + ".Channel.SensorName", "", false);
|
||||
|
||||
public string Version
|
||||
{
|
||||
get => _version.Value;
|
||||
set => _version.Value = value;
|
||||
}
|
||||
private readonly Property<string> _version
|
||||
= new Property<string>(typeof(TOChannel).Namespace + ".Channel.Version", "", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using DTS.Serialization.IRIGCH10.Enums;
|
||||
using DTS.Serialization.IRIGCH10.Packets;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10
|
||||
{
|
||||
/// <summary>
|
||||
/// the TMATS packet in the ch10 file is
|
||||
/// a packet containing the setup file, a description of
|
||||
/// what channels, das, time formats, etc are used in the file
|
||||
/// </summary>
|
||||
public class TMATSPacket : AbstractDataPacket, IDataPacket
|
||||
{
|
||||
/// <summary>
|
||||
/// whether the TMATS is in XML or ASCII format
|
||||
/// </summary>
|
||||
public bool XMLFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
var b = new BitArray(BitConverter.GetBytes(ChannelSpecificDataWord));
|
||||
return b.Get(9);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// whether the setup record has changed or not
|
||||
/// </summary>
|
||||
public bool SetupRecordConfigurationChange
|
||||
{
|
||||
get
|
||||
{
|
||||
var b = new BitArray(BitConverter.GetBytes(ChannelSpecificDataWord));
|
||||
return b.Get(8);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// the chapter 10 version of the TMATS file
|
||||
/// </summary>
|
||||
public RCCChapter10Versions Chapter10Version
|
||||
{
|
||||
get
|
||||
{
|
||||
var b = new BitArray(BitConverter.GetBytes(ChannelSpecificDataWord));
|
||||
var ver = Utils.Utils.BitArrayToInt32(b, 0, 7);
|
||||
switch (ver)
|
||||
{
|
||||
case 0x07: return RCCChapter10Versions.RCC_106_07;
|
||||
case 0x08: return RCCChapter10Versions.RCC_106_09;
|
||||
case 0x09: return RCCChapter10Versions.RCC_106_11;
|
||||
case 0x0A: return RCCChapter10Versions.RCC_106_13;
|
||||
case 0x0B: return RCCChapter10Versions.RCC_106_15;
|
||||
default: return RCCChapter10Versions.RESERVED;
|
||||
}
|
||||
}
|
||||
}
|
||||
public enum RCCChapter10Versions
|
||||
{
|
||||
RESERVED,
|
||||
RCC_106_07,
|
||||
RCC_106_09,
|
||||
RCC_106_11,
|
||||
RCC_106_13,
|
||||
RCC_106_15
|
||||
}
|
||||
private const byte DataVersionNoSecondaryHeader = 0x01;
|
||||
private const byte DataVersionSecondaryHeader = 0x09;
|
||||
public TMATSPacket(int nanoseconds, int seconds, string tmatsDoc, bool secondaryHeaderPresent)
|
||||
: base(DataFileDataTypes.ComputerGeneratedDataFormat1, secondaryHeaderPresent)
|
||||
{
|
||||
var tmatsBytes = Encoding.ASCII.GetBytes(tmatsDoc);
|
||||
var dataLength = Convert.ToUInt32(4 + tmatsBytes.Length); ;
|
||||
var offset = CommonHeaderWork(0, secondaryHeaderPresent ? DataVersionSecondaryHeader : DataVersionNoSecondaryHeader,
|
||||
1, BASE_RTC, dataLength, nanoseconds, seconds);
|
||||
Buffer.BlockCopy(tmatsBytes, 0, _dataBytes, offset, tmatsBytes.Length);
|
||||
}
|
||||
|
||||
public TMATSPacket(byte[] bytes) : base(bytes)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// the TMATS document
|
||||
/// </summary>
|
||||
public string TMATSDocument
|
||||
{
|
||||
get
|
||||
{
|
||||
//the document is prepended by a ChannelSpecificDataWord and potentially a time header
|
||||
var prepend = 4; //CSDW
|
||||
if (PacketHeader.SecondaryHeaderPresent) { prepend += SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH; }
|
||||
var length = PacketHeader.DataLength - prepend;
|
||||
var bytes = new byte[length];
|
||||
Buffer.BlockCopy(_dataBytes, prepend, bytes, 0, bytes.Length);
|
||||
return Encoding.ASCII.GetString(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* DTS.Slice.Control.Event.Module.AnalogInputChannel.ReviewableSerialNumberAttribute.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace DTS.Slice.Control
|
||||
{
|
||||
// *** see DTS.Slice.Control.Event.cs ***
|
||||
public partial class Event
|
||||
{
|
||||
|
||||
// *** see DTS.Slice.Control.Event.Module.cs ***
|
||||
public partial class Module
|
||||
{
|
||||
|
||||
// *** see DTS.Slice.Control.Event.Module.AnalogInputChannel.cs ***
|
||||
public partial class AnalogInputChannel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A reviewable serial number attribute attached to a specific channel.
|
||||
/// </summary>
|
||||
public class ReviewableSerialNumberAttribute
|
||||
: Slice.Control.Event.Module.Channel.ReviewableAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize an instance of this class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="channel">
|
||||
/// The <see cref="Event.Module.Channel"/> to which this attribute is attached.
|
||||
/// </param>
|
||||
///
|
||||
public ReviewableSerialNumberAttribute(Event.Module.Channel channel)
|
||||
: base("Serial Number", delegate { return (channel as AnalogInputChannel).SerialNumber.ToString(); })
|
||||
{
|
||||
}
|
||||
}
|
||||
} // *** end Channel ***
|
||||
} // *** end Module ***
|
||||
} // *** end Event ***
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* SliceRaw.File.PersistentEuChannel.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Serialization.SliceRaw
|
||||
{
|
||||
public partial class File
|
||||
{
|
||||
public class PersistentEuChannel : ExceptionalList<double>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Serialization.SliceRaw.File.PersistentEuChannel class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="persistentChannel">
|
||||
/// The <see cref="DTS.Serialization.SliceRaw.File.PersistentChannel"/> to be wrapped by this
|
||||
/// "to EU" conversion class.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="scaler">
|
||||
/// The <see cref="DTS.Common.DAS.ConceptsDataScalar"/> object that defines the conversion from
|
||||
/// ADC to EU for the wrapped data.
|
||||
/// </param>
|
||||
///
|
||||
public PersistentEuChannel(PersistentChannel persistentChannel, DataScaler scaler)
|
||||
{
|
||||
try
|
||||
{
|
||||
BasePersistentChannel = persistentChannel;
|
||||
EuDataScaler = scaler;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem constructing " + GetType().FullName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the base persistent channel of this EU-ifying wrapper.
|
||||
/// </summary>
|
||||
public PersistentChannel BasePersistentChannel
|
||||
{
|
||||
get => _BasePersistentChannel.Value;
|
||||
set => _BasePersistentChannel.Value = value;
|
||||
}
|
||||
private readonly Property<PersistentChannel> _BasePersistentChannel
|
||||
= new Property<PersistentChannel>(
|
||||
typeof(PersistentEuChannel).Namespace + ".PersistentEuChannel.BasePersistentChannel",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the data scaler for converting the ADC data wrapped by this class to EU.
|
||||
/// </summary>
|
||||
public DataScaler EuDataScaler
|
||||
{
|
||||
get => _EuDataScaler.Value;
|
||||
set => _EuDataScaler.Value = value;
|
||||
}
|
||||
private readonly Property<DataScaler> _EuDataScaler
|
||||
= new Property<DataScaler>(
|
||||
typeof(PersistentEuChannel).Namespace + ".PersistentEuChannel.EuDataScaler",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
public double this[ulong i]
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return EuDataScaler.GetEU(BasePersistentChannel[i]);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting value at index " + i.ToString(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
try
|
||||
{
|
||||
throw new NotSupportedException("SliceRaw::File::PersistentEuChannel::[] values are read-only");
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem setting value at index " + i.ToString(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the <see cref="long"/> length of this persistent channel's data.
|
||||
/// </summary>
|
||||
public long Length => BasePersistentChannel.Length;
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of this object's Disposables.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
BasePersistentChannel.Dispose();
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new PersistentChannel.Exception("encountered problem disposing of " + GetType().FullName, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* DTS.Slice.Control.Event.Module.AnalogInputChannel.ReviewableCfcAttribute.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using DTS.Utilities;
|
||||
|
||||
namespace DTS.Slice.Control
|
||||
{
|
||||
// *** see DTS.Slice.Control.Event.cs ***
|
||||
public partial class Event
|
||||
{
|
||||
|
||||
// *** see DTS.Slice.Control.Event.Module.cs ***
|
||||
public partial class Module
|
||||
{
|
||||
|
||||
// *** see DTS.Slice.Control.Event.Module.AnalogInputChannel.cs ***
|
||||
public partial class AnalogInputChannel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A reviewable CFC attribute attached to a specific channel.
|
||||
/// </summary>
|
||||
public class ReviewableDescriptionAttribute
|
||||
: Slice.Control.Event.Module.Channel.ReviewableAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize an instance of this class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="channel">
|
||||
/// The <see cref="Event.Module.Channel"/> to which this attribute is attached.
|
||||
/// </param>
|
||||
///
|
||||
public ReviewableDescriptionAttribute(Event.Module.Channel channel)
|
||||
: base("Description", delegate { return channel.ChannelDescriptionString; })
|
||||
{
|
||||
}
|
||||
}
|
||||
} // *** end Channel ***
|
||||
} // *** end Module ***
|
||||
} // *** end Event ***
|
||||
}
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
namespace DTS.Serialization.TDM
|
||||
{
|
||||
partial class TDMParameterDlg
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.tblLayout = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.btnBrowse = new System.Windows.Forms.Button();
|
||||
this.tbLocation = new System.Windows.Forms.TextBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.tbStart = new System.Windows.Forms.TextBox();
|
||||
this.tbStop = new System.Windows.Forms.TextBox();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.btnOK = new System.Windows.Forms.Button();
|
||||
this.btnCancel = new System.Windows.Forms.Button();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.label6 = new System.Windows.Forms.Label();
|
||||
this.errorProvider1 = new System.Windows.Forms.ErrorProvider(this.components);
|
||||
this.tblLayout.SuspendLayout();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tblLayout
|
||||
//
|
||||
this.tblLayout.ColumnCount = 4;
|
||||
this.tblLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tblLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tblLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tblLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tblLayout.Controls.Add(this.label1, 0, 0);
|
||||
this.tblLayout.Controls.Add(this.btnBrowse, 3, 0);
|
||||
this.tblLayout.Controls.Add(this.tbLocation, 1, 0);
|
||||
this.tblLayout.Controls.Add(this.label2, 0, 2);
|
||||
this.tblLayout.Controls.Add(this.label3, 0, 1);
|
||||
this.tblLayout.Controls.Add(this.tbStart, 1, 2);
|
||||
this.tblLayout.Controls.Add(this.tbStop, 1, 3);
|
||||
this.tblLayout.Controls.Add(this.label4, 0, 3);
|
||||
this.tblLayout.Controls.Add(this.tableLayoutPanel1, 0, 4);
|
||||
this.tblLayout.Controls.Add(this.label5, 2, 2);
|
||||
this.tblLayout.Controls.Add(this.label6, 2, 3);
|
||||
this.tblLayout.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tblLayout.Location = new System.Drawing.Point(0, 0);
|
||||
this.tblLayout.Name = "tblLayout";
|
||||
this.tblLayout.RowCount = 5;
|
||||
this.tblLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tblLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tblLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tblLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tblLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tblLayout.Size = new System.Drawing.Size(511, 136);
|
||||
this.tblLayout.TabIndex = 0;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(3, 8);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(48, 13);
|
||||
this.label1.TabIndex = 0;
|
||||
this.label1.Text = "Location";
|
||||
//
|
||||
// btnBrowse
|
||||
//
|
||||
this.btnBrowse.Location = new System.Drawing.Point(433, 3);
|
||||
this.btnBrowse.Name = "btnBrowse";
|
||||
this.btnBrowse.Size = new System.Drawing.Size(75, 23);
|
||||
this.btnBrowse.TabIndex = 1;
|
||||
this.btnBrowse.Text = "Browse";
|
||||
this.btnBrowse.UseVisualStyleBackColor = true;
|
||||
this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click);
|
||||
//
|
||||
// tbLocation
|
||||
//
|
||||
this.tbLocation.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.tblLayout.SetColumnSpan(this.tbLocation, 2);
|
||||
this.tbLocation.Location = new System.Drawing.Point(57, 4);
|
||||
this.tbLocation.Name = "tbLocation";
|
||||
this.tbLocation.Size = new System.Drawing.Size(370, 20);
|
||||
this.tbLocation.TabIndex = 2;
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(3, 48);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(29, 13);
|
||||
this.label2.TabIndex = 3;
|
||||
this.label2.Text = "Start";
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label3.AutoSize = true;
|
||||
this.tblLayout.SetColumnSpan(this.label3, 2);
|
||||
this.label3.Location = new System.Drawing.Point(3, 29);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(158, 13);
|
||||
this.label3.TabIndex = 4;
|
||||
this.label3.Text = "Start and Stop are relative to T0";
|
||||
//
|
||||
// tbStart
|
||||
//
|
||||
this.tbStart.Location = new System.Drawing.Point(57, 45);
|
||||
this.tbStart.Name = "tbStart";
|
||||
this.tbStart.Size = new System.Drawing.Size(100, 20);
|
||||
this.tbStart.TabIndex = 5;
|
||||
this.tbStart.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
|
||||
//
|
||||
// tbStop
|
||||
//
|
||||
this.tbStop.Location = new System.Drawing.Point(57, 71);
|
||||
this.tbStop.Name = "tbStop";
|
||||
this.tbStop.Size = new System.Drawing.Size(100, 20);
|
||||
this.tbStop.TabIndex = 6;
|
||||
this.tbStop.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(3, 74);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(29, 13);
|
||||
this.label4.TabIndex = 7;
|
||||
this.label4.Text = "Stop";
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.tableLayoutPanel1.ColumnCount = 2;
|
||||
this.tblLayout.SetColumnSpan(this.tableLayoutPanel1, 4);
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel1.Controls.Add(this.btnOK, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.btnCancel, 1, 0);
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 97);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 1;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(505, 36);
|
||||
this.tableLayoutPanel1.TabIndex = 8;
|
||||
//
|
||||
// btnOK
|
||||
//
|
||||
this.btnOK.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
this.btnOK.Location = new System.Drawing.Point(174, 6);
|
||||
this.btnOK.Name = "btnOK";
|
||||
this.btnOK.Size = new System.Drawing.Size(75, 23);
|
||||
this.btnOK.TabIndex = 0;
|
||||
this.btnOK.Text = "&OK";
|
||||
this.btnOK.UseVisualStyleBackColor = true;
|
||||
this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
|
||||
//
|
||||
// btnCancel
|
||||
//
|
||||
this.btnCancel.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.btnCancel.Location = new System.Drawing.Point(255, 6);
|
||||
this.btnCancel.Name = "btnCancel";
|
||||
this.btnCancel.Size = new System.Drawing.Size(75, 23);
|
||||
this.btnCancel.TabIndex = 1;
|
||||
this.btnCancel.Text = "&Cancel";
|
||||
this.btnCancel.UseVisualStyleBackColor = true;
|
||||
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.Location = new System.Drawing.Point(167, 48);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(26, 13);
|
||||
this.label5.TabIndex = 9;
|
||||
this.label5.Text = "(ms)";
|
||||
//
|
||||
// label6
|
||||
//
|
||||
this.label6.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label6.AutoSize = true;
|
||||
this.label6.Location = new System.Drawing.Point(167, 74);
|
||||
this.label6.Name = "label6";
|
||||
this.label6.Size = new System.Drawing.Size(26, 13);
|
||||
this.label6.TabIndex = 10;
|
||||
this.label6.Text = "(ms)";
|
||||
//
|
||||
// errorProvider1
|
||||
//
|
||||
this.errorProvider1.ContainerControl = this;
|
||||
//
|
||||
// TDMParameterDlg
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(239)))), ((int)(((byte)(246)))), ((int)(((byte)(253)))));
|
||||
this.ClientSize = new System.Drawing.Size(511, 136);
|
||||
this.Controls.Add(this.tblLayout);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
|
||||
this.Name = "TDMParameterDlg";
|
||||
this.Text = "TDM Export Parameters";
|
||||
this.tblLayout.ResumeLayout(false);
|
||||
this.tblLayout.PerformLayout();
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TableLayoutPanel tblLayout;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Button btnBrowse;
|
||||
private System.Windows.Forms.TextBox tbLocation;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.TextBox tbStart;
|
||||
private System.Windows.Forms.TextBox tbStop;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.Button btnOK;
|
||||
private System.Windows.Forms.Button btnCancel;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.Label label6;
|
||||
private System.Windows.Forms.ErrorProvider errorProvider1;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,152 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace IRIGCh10
|
||||
{
|
||||
public enum AttributeIdentifiers
|
||||
{
|
||||
[Description("G")] GeneralInformation,
|
||||
[Description("T")] TransmitionAttributes,
|
||||
[Description("R")] StorageSourceAttributes,
|
||||
[Description("M")] MultiplexingAttributes,
|
||||
[Description("P")] PCMFormatAttributes,
|
||||
[Description("D")] PCMMeasurementDescription,
|
||||
[Description("B")] BusDataAttributes,
|
||||
[Description("S")] PacketFormatAttributes,
|
||||
[Description("A")] PAMAttributes,
|
||||
[Description("C")] DataConversionAttributes,
|
||||
[Description("H")] AirborneHardwareAttributes,
|
||||
[Description("V")] VendorSpecificAttributes
|
||||
}
|
||||
|
||||
public class TMATSCreationTest
|
||||
{
|
||||
public static string CreateTMATS()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
var gi = new GeneralInformationGroup();
|
||||
gi.ProgramName = "netacquire-3-pcm-sine-waves";
|
||||
gi.IRIG106RevisionLevel = "07";
|
||||
gi.NumberOfDataSources = 1;
|
||||
gi.SetDataSourceField(1, GeneralInformationGroup.Information.DataSourceIdentificationTags.DataSourceID,
|
||||
"DATASOURCE");
|
||||
gi.SetDataSourceType(1, GeneralInformationGroup.Information.DataSourceTypes.Storage);
|
||||
gi.OriginationDate = new System.DateTime(2018, 11, 20);
|
||||
|
||||
sb.Append(gi.Serialize());
|
||||
|
||||
var storage = new Storage(1);
|
||||
storage.DataSourceID = "DATASOURCE";
|
||||
storage.StorageID = "DATASOURCE";
|
||||
storage.NumberOfChannels = 4;
|
||||
storage.OriginalStorage = true;
|
||||
storage.DateTimeCreated = new System.DateTime(2018, 11, 20);
|
||||
storage.NumberOfSourceBits = 0;
|
||||
storage.RecordingEventsEnabled = false;
|
||||
storage.RecordingIndexEnabled = true;
|
||||
storage.RecordingIndexType = RecordingIndexTypes.Time;
|
||||
storage.RecordingIndexTimeValue = 10000000;
|
||||
storage.SetDataSourceID(1, "Time");
|
||||
storage.SetChannelDataType(1, ChannelDataTypes.IRIGTimeInput);
|
||||
storage.SetTrackNumber(1, 65535);
|
||||
storage.SetPhysicalChannelNumber(1, 65535);
|
||||
storage.SetChannelEnabled(1, true);
|
||||
storage.SetChannelDataLinkName(1, "Time");
|
||||
storage.SetTimeChannelDataTypeFormat();
|
||||
storage.SetTimeFormat(TimeFormats.IRIGB);
|
||||
storage.SetTimeSource(TimeSources.Internal);
|
||||
|
||||
storage.SetDataSourceID(2, "sio/0/in0-10");
|
||||
storage.SetChannelDataType(2, ChannelDataTypes.PCMInput);
|
||||
storage.SetTrackNumber(2, 10);
|
||||
storage.SetPhysicalChannelNumber(2, 10);
|
||||
storage.SetChannelEnabled(2, true);
|
||||
storage.SetChannelDataLinkName(2, "sio/0/in0-10");
|
||||
storage.SetPCMDataTimeFormat(2);
|
||||
storage.SetPCMDataPackingOption(2, DataPackingOptions.ThroughputMode);
|
||||
storage.SetPCMInputClockEdge(2, InputClockEdges.ZeroDegrees);
|
||||
storage.SetPCMInputSignalType(2, InputSignalTypes.SingleEndedWithTTL);
|
||||
storage.SetPCMVideoTypeFormat(2, VideoFormats.None);
|
||||
|
||||
var pcm = new PCM(1);
|
||||
pcm.DataLinkName = "sio/0/in0-10";
|
||||
pcm.PCMCode = PCMCodes.NRZL;
|
||||
pcm.BitsPerSecond = "1000000";
|
||||
pcm.Polarity = Polarities.Normal;
|
||||
pcm.DataDirection = PCMDataDirections.Normal;
|
||||
pcm.TypeFormat = PCMTypeFormats.ClassI;
|
||||
pcm.NumberOfBitsInCommonWordLength = 16;
|
||||
pcm.WordTransferOrder = PCMWordTransferOrders.MostSignificantBit;
|
||||
pcm.PCMWordParity = PCMWordParities.None;
|
||||
|
||||
sb.Append(pcm.Serialize());
|
||||
|
||||
var minorFrameSection = new MinorFrameSection();
|
||||
minorFrameSection.NumberOfMinorFramesInAMajorFrame = 1;
|
||||
minorFrameSection.NumberOfWordsInMinorFrame = 500;
|
||||
minorFrameSection.NumberOfBitsInMinorFrame = 8000;//500*16
|
||||
minorFrameSection.SyncLength = 16;
|
||||
minorFrameSection.SynchronizationPattern = "1110101110010000";
|
||||
|
||||
sb.Append(minorFrameSection.Serialize());
|
||||
|
||||
var subframeSync = new SubframeSync();
|
||||
sb.Append(subframeSync.Serialize());
|
||||
|
||||
storage.SetDataSourceID(3, "sio/0/in1-20");
|
||||
storage.SetChannelDataType(3, ChannelDataTypes.PCMInput);
|
||||
storage.SetTrackNumber(3, 20);
|
||||
storage.SetPhysicalChannelNumber(3, 20);
|
||||
storage.SetChannelEnabled(3, true);
|
||||
storage.SetChannelDataLinkName(3, "sio/0/in1-20");
|
||||
storage.SetPCMDataTimeFormat(3);
|
||||
storage.SetPCMDataPackingOption(3, DataPackingOptions.PackedWithFrameSync);
|
||||
storage.SetPCMInputClockEdge(3, InputClockEdges.ZeroDegrees);
|
||||
storage.SetPCMInputSignalType(3, InputSignalTypes.SingleEndedWithTTL);
|
||||
storage.SetPCMVideoTypeFormat(3, VideoFormats.None);
|
||||
|
||||
var pcm2 = new PCM(2);
|
||||
pcm2.DataLinkName = "sio/0/in1-20";
|
||||
pcm2.PCMCode = PCMCodes.NRZL;
|
||||
pcm2.BitsPerSecond = "1920000";
|
||||
pcm2.Polarity = Polarities.Normal;
|
||||
pcm2.DataRandomized = false;
|
||||
pcm2.TypeFormat = PCMTypeFormats.ClassI;
|
||||
pcm2.NumberOfBitsInCommonWordLength = 16;
|
||||
pcm2.WordTransferOrder = PCMWordTransferOrders.MostSignificantBit;
|
||||
pcm2.PCMWordParity = PCMWordParities.None;
|
||||
|
||||
sb.Append(pcm2.Serialize());
|
||||
|
||||
var minorFrameSection2 = new MinorFrameSection(2);
|
||||
minorFrameSection2.NumberOfMinorFramesInAMajorFrame = 1;
|
||||
minorFrameSection2.NumberOfWordsInMinorFrame = 300;
|
||||
minorFrameSection2.NumberOfBitsInMinorFrame = 4800;//300*16
|
||||
minorFrameSection2.SyncLength = 16;
|
||||
minorFrameSection2.SynchronizationPattern = "1110101110010000";
|
||||
|
||||
sb.Append(minorFrameSection2.Serialize());
|
||||
|
||||
var subframeSync2 = new SubframeSync(2);
|
||||
sb.Append(subframeSync2.Serialize());
|
||||
|
||||
storage.SetDataSourceID(4, "sio/0/in2-30");
|
||||
storage.SetChannelDataType(4, ChannelDataTypes.MessageDataInput);
|
||||
storage.SetTrackNumber(4, 30);
|
||||
storage.SetPhysicalChannelNumber(4, 30);
|
||||
storage.SetChannelEnabled(4, true);
|
||||
storage.SetChannelDataLinkName(4, "sio/0/in2-30");
|
||||
sb.Append(storage.Serialize());
|
||||
|
||||
MessageDataType mdt = new MessageDataType(1);
|
||||
mdt.SetMessageTypeFormat(4, "0");
|
||||
mdt.SetNumberOfMessageSubChannels(4, 1);
|
||||
mdt.SetMessageSubChannelNumber(4, 1, 1);
|
||||
mdt.SetMessageSubChannelName(4, 1, "sio/0/in2-30");
|
||||
|
||||
sb.Append(mdt.Serialize());
|
||||
return sb.ToString();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using IRIGCh10;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10.Attributes
|
||||
{
|
||||
public enum DataConversionAttributes
|
||||
{
|
||||
[Description("DCT")]
|
||||
ConversionType
|
||||
}
|
||||
|
||||
public enum ConversionTypes
|
||||
{
|
||||
[Description("NON")]
|
||||
None,
|
||||
[Description("PRS")]
|
||||
PairSets,
|
||||
[Description("COE")]
|
||||
Coefficients,
|
||||
[Description("NPC")]
|
||||
CoefficientsNegative,
|
||||
[Description("DER")]
|
||||
Derived,
|
||||
[Description("DIS")]
|
||||
Discrete,
|
||||
[Description("PTM")]
|
||||
PCMTime,
|
||||
[Description("BTM")]
|
||||
Time1553,
|
||||
[Description("VOI")]
|
||||
DigitalVoice,
|
||||
[Description("VID")]
|
||||
DigitalVideo,
|
||||
[Description("SP")]
|
||||
SpecializedProcessing,
|
||||
[Description("OTH")]
|
||||
Other
|
||||
}
|
||||
/// <summary>
|
||||
/// implements the data conversion section of the tmats packet
|
||||
/// </summary>
|
||||
public class DataConversionSection : TMATSSection<DataConversionAttributes>
|
||||
{
|
||||
public DataConversionSection(int number) : base(AttributeIdentifiers.DataConversionAttributes, number)
|
||||
{
|
||||
}
|
||||
public void SetConversionType(ConversionTypes type)
|
||||
{
|
||||
SetValueWithLength(DataConversionAttributes.ConversionType,
|
||||
DescriptionDecoder.GetDescription(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
public sealed class StringWriterWithEncoding : StringWriter
|
||||
{
|
||||
private readonly Encoding encoding;
|
||||
|
||||
public StringWriterWithEncoding(Encoding encoding)
|
||||
{
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
public override Encoding Encoding => encoding;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
Test.cs
|
||||
|
||||
Copyright © 2008
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using DTS.Utilities;
|
||||
using DTS.Utilities.DotNetProgrammingConstructs;
|
||||
using DTS.Utilities.Xml;
|
||||
|
||||
namespace DTS.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Representation of a serializable test information.
|
||||
/// </summary>
|
||||
[XmlSerializationTag( "Test" )]
|
||||
public partial class Test : Exceptional, IXmlSerializable
|
||||
{
|
||||
|
||||
private Property<string> _software
|
||||
= new Property<string>(typeof(Test).Namespace + ".Test.Software", "DataPRO", true);
|
||||
[XmlSerializationTag("Software")]
|
||||
public string Software
|
||||
{
|
||||
get { return _software.Value; }
|
||||
set { _software.Value = value; }
|
||||
}
|
||||
|
||||
private Property<string> _softwareVersion
|
||||
= new Property<string>(typeof(Test).Namespace + ".Test.SoftwareVersion", "", false);
|
||||
[XmlSerializationTag("SoftwareVersion")]
|
||||
public string SoftwareVersion
|
||||
{
|
||||
get { return _softwareVersion.Value; }
|
||||
set { _softwareVersion.Value = value; }
|
||||
}
|
||||
/*
|
||||
/// <summary>
|
||||
/// The string ID of this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("Id")]
|
||||
public string Id
|
||||
{
|
||||
get { return _Id.Value; }
|
||||
set { _Id.Value = value; }
|
||||
}
|
||||
private Property<string> _Id
|
||||
= new Property<string>(typeof(Test).Namespace + ".Test.Id", "", false);*/
|
||||
// Initialize an instance of the Test class.
|
||||
public Test()
|
||||
{
|
||||
TryGetChannelOrder();
|
||||
//
|
||||
// Note that the parameterless constructor for this object will leave
|
||||
// the Id and Description paramters
|
||||
} //
|
||||
public Test(string dtsfile)
|
||||
{
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Initialize an instance of the Test class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="id">
|
||||
/// The <see cref="string"/> ID of this test.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="description">
|
||||
/// The <see cref="string"/> description of this test.
|
||||
/// </param>
|
||||
///
|
||||
public Test(string id, string description)
|
||||
{
|
||||
TryGetChannelOrder();
|
||||
try
|
||||
{
|
||||
Id = id;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception( "encountered problem constructing Test object (Id: " + ( !string.IsNullOrEmpty( id ) ? id : "<<NULL>>" ) + "Description: " + ( !string.IsNullOrEmpty( description ) ? description : "<<NULL>>" ) + ")", ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the date of this object's serialization's creation (if applicable).
|
||||
/// </summary>
|
||||
public DateTime InceptionDate
|
||||
{
|
||||
get { return _InceptionDate.Value; }
|
||||
set { _InceptionDate.Value = value; }
|
||||
}
|
||||
private Property<DateTime> _InceptionDate
|
||||
= new Property<DateTime>(
|
||||
typeof( Test ).Namespace + ".Test.InceptionDate",
|
||||
DateTime.Now,
|
||||
false
|
||||
);
|
||||
|
||||
private Dictionary<string, int> _channelOrder = new Dictionary<string, int>();
|
||||
|
||||
private static string GetID(Test.Module.Channel channel)
|
||||
{
|
||||
if (null != channel.SensorID && channel.SensorID.Length > 0) { return channel.SensorID; }
|
||||
else { return channel.ChannelDescriptionString; }
|
||||
}
|
||||
public class ChannelOrderComparor : IComparer<Test.Module.Channel>
|
||||
{
|
||||
private IDictionary<string, int> _dictionary;
|
||||
|
||||
public ChannelOrderComparor(IDictionary<string, int> dictionary)
|
||||
{
|
||||
_dictionary = dictionary;
|
||||
}
|
||||
public int Compare(Test.Module.Channel a, Test.Module.Channel b)
|
||||
{
|
||||
string keyA = GetID(a);
|
||||
string keyB = GetID(b);
|
||||
int iA = _dictionary.ContainsKey(keyA) ? _dictionary[keyA] : int.MaxValue;
|
||||
int iB = _dictionary.ContainsKey(keyB) ? _dictionary[keyB] : int.MaxValue;
|
||||
return iA.CompareTo(iB);
|
||||
}
|
||||
}
|
||||
public void TryGetChannelOrder()
|
||||
{
|
||||
try
|
||||
{
|
||||
_channelOrder.Clear();
|
||||
if (System.IO.File.Exists("ChannelOrder.txt"))
|
||||
{
|
||||
using (System.IO.StreamReader sr = new System.IO.StreamReader("ChannelOrder.txt"))
|
||||
{
|
||||
string line;
|
||||
int i = 0;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
_channelOrder.Add(line, i++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Utilities.Logging.APILogger.Log("Exception getting channel order", ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Get a named-DAS/numbered-channel accessor to this Event's channels.
|
||||
/// </summary>
|
||||
public List<Test.Module.Channel> Channels
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_channelOrder.Count < 1) { TryGetChannelOrder(); }
|
||||
List<Test.Module.Channel> allChannels = new List<Module.Channel>();
|
||||
foreach (Test.Module testModule in this.Modules)
|
||||
{
|
||||
allChannels.AddRange(testModule.Channels);
|
||||
allChannels.AddRange(testModule.CalculatedChannels);
|
||||
}
|
||||
allChannels.Sort(new Comparison<Module.Channel>(CompareChannels));
|
||||
if (_channelOrder.Count > 0) { allChannels.Sort(new ChannelOrderComparor(_channelOrder)); }
|
||||
return allChannels;
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Test.Exception("encountered problem getting all test channels", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int CompareChannels(Test.Module.Channel left, Test.Module.Channel right)
|
||||
{
|
||||
if (left == right) { return 0; }
|
||||
if (null == left) { return -1; }
|
||||
if (null == right) { return 1; }
|
||||
int ret = left.AbsoluteDisplayOrder.CompareTo(right.AbsoluteDisplayOrder);
|
||||
if (0 == ret)
|
||||
{
|
||||
ret = left.ParentModule.Number.CompareTo(right.ParentModule.Number);
|
||||
}
|
||||
if (0 == ret)
|
||||
{
|
||||
return left.Number.CompareTo(right.Number);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/// <summary>
|
||||
/// The string ID of this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag( "Id" )]
|
||||
public string Id
|
||||
{
|
||||
get { return _Id.Value; }
|
||||
set { _Id.Value = value; }
|
||||
}
|
||||
private Property<string> _Id
|
||||
= new Property<string>( typeof( Test ).Namespace + ".Test.Id", "", false);
|
||||
|
||||
/// <summary>
|
||||
/// The string description of this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag( "Description" )]
|
||||
public string Description
|
||||
{
|
||||
get { return _Description.Value; }
|
||||
set { _Description.Value = value; }
|
||||
}
|
||||
private Property<string> _Description
|
||||
= new Property<string>( typeof( Test ).Namespace + ".Test.Description", "", false );
|
||||
|
||||
/// <summary>
|
||||
/// The globally unique identification string for this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag( "Guid" )]
|
||||
public Guid Guid
|
||||
{
|
||||
get { return _Guid.Value; }
|
||||
set { _Guid.Value = value; }
|
||||
}
|
||||
private Property<Guid> _Guid
|
||||
= new Property<Guid>( typeof( Test ).Namespace + ".Test.Guid", new Guid( "00000000-0000-0000-0000-000000000000" ), false );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The globally unique identification string for this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag("FaultFlags")]
|
||||
public UInt16 FaultFlags
|
||||
{
|
||||
get { return _FaultFlags.Value; }
|
||||
set { _FaultFlags.Value = value; }
|
||||
}
|
||||
private Property<UInt16> _FaultFlags
|
||||
= new Property<UInt16>(typeof(Test).Namespace + ".Test.FaultFlags", 0, false);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set inline serialized data switch.
|
||||
/// </summary>
|
||||
[XmlSerializationTag( "InlineSerializedData" )]
|
||||
public bool InlineSerializedData
|
||||
{
|
||||
get { return _InlineSerializedData.Value; }
|
||||
set
|
||||
{
|
||||
try
|
||||
{
|
||||
_InlineSerializedData.Value = value;
|
||||
foreach ( Test.Module module in Modules )
|
||||
module.InlineSerializedData = value;
|
||||
}
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem setting test InlineSerializedData state", ex );
|
||||
}
|
||||
}
|
||||
}
|
||||
private Property<bool> _InlineSerializedData
|
||||
= new Property<bool>( typeof( Test ).Namespace + ".Test.InlineSerializedData", false, true );
|
||||
|
||||
/// <summary>
|
||||
/// The list of modules in this test.
|
||||
/// </summary>
|
||||
[XmlSerializationTag( "Modules" )]
|
||||
public List<Module> Modules
|
||||
{
|
||||
get { return _Modules.Value; }
|
||||
set { _Modules.Value = value; }
|
||||
}
|
||||
private Property<List<Module>> _Modules
|
||||
= new Property<List<Module>>( typeof( Test ).Namespace + ".Test.Modules", new List<Test.Module>( ), true );
|
||||
|
||||
/// <summary>
|
||||
/// Write XML serialization for this object to the specified writer.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="writer">
|
||||
/// The <see cref="XmlWriter"/> to which this object's XML serialization
|
||||
/// will be written.
|
||||
/// </param>
|
||||
///
|
||||
public void WriteXml( XmlWriter writer )
|
||||
{
|
||||
try
|
||||
{
|
||||
AttributeExtractor<XmlSerializationTagAttribute> attributeExtractor = new AttributeExtractor<XmlSerializationTagAttribute>( );
|
||||
|
||||
writer.WriteAttributeString( attributeExtractor.ExtractAttachedAttributeFromProperty( this, "Id" ).Value, this.Id );
|
||||
writer.WriteAttributeString( attributeExtractor.ExtractAttachedAttributeFromProperty( this, "Description" ).Value, this.Description );
|
||||
writer.WriteAttributeString( attributeExtractor.ExtractAttachedAttributeFromProperty( this, "InlineSerializedData" ).Value, this.InlineSerializedData.ToString( ) );
|
||||
writer.WriteAttributeString( attributeExtractor.ExtractAttachedAttributeFromProperty( this, "Guid" ).Value, this.Guid.ToString( ) );
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "FaultFlags").Value, this.FaultFlags.ToString());
|
||||
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Software").Value, this.Software.ToString());
|
||||
writer.WriteAttributeString(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "SoftwareVersion").Value, this.SoftwareVersion.ToString());
|
||||
|
||||
writer.WriteStartElement ( attributeExtractor.ExtractAttachedAttributeFromProperty( this, "Modules" ).Value );
|
||||
|
||||
foreach (var module in Modules)
|
||||
{
|
||||
module.WriteXml(writer);
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem converting DTS.Serialization.Test object to XML", ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read XML serialization for this object from the specified reader.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="reader">
|
||||
/// The <see cref="XmlReader"/> from which this object's XML serialization
|
||||
/// will be read.
|
||||
/// </param>
|
||||
///
|
||||
public void ReadXml( XmlReader reader )
|
||||
{
|
||||
try
|
||||
{
|
||||
AttributeExtractor<XmlSerializationTagAttribute> attributeExtractor = new AttributeExtractor<XmlSerializationTagAttribute>();
|
||||
|
||||
if (reader.IsStartElement("Test"))
|
||||
{
|
||||
this.Id = reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Id").Value);
|
||||
this.Description = reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Description").Value);
|
||||
this.InlineSerializedData = bool.Parse(reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "InlineSerializedData").Value));
|
||||
|
||||
try { this.Guid = new Guid(reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Guid").Value)); }
|
||||
catch (System.Exception) { this.Guid = new Guid("00000000-0000-0000-0000-000000000000"); }
|
||||
|
||||
try { this.FaultFlags = Convert.ToUInt16(reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "FaultFlags").Value)); }
|
||||
catch (System.Exception) { this.FaultFlags = 0; }
|
||||
|
||||
try { this.Software = reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "Software").Value); }
|
||||
catch (System.Exception) { Software = "unknown"; }
|
||||
|
||||
try { this.SoftwareVersion = reader.GetAttribute(attributeExtractor.ExtractAttachedAttributeFromProperty(this, "SoftwareVersion").Value); }
|
||||
catch (System.Exception) { SoftwareVersion = "unknown"; }
|
||||
|
||||
this.Modules.Clear();
|
||||
|
||||
if (reader.ReadToDescendant("Modules"))
|
||||
{
|
||||
if (reader.ReadToDescendant("Module"))
|
||||
{
|
||||
do
|
||||
{
|
||||
Test.Module deserializedModule = new Test.Module(this);
|
||||
deserializedModule.InlineSerializedData = InlineSerializedData;
|
||||
|
||||
//Give the deserializer a separate reader so that it can't go amuck and read past the current module.
|
||||
deserializedModule.ReadXml(reader.ReadSubtree());
|
||||
this.Modules.Add(deserializedModule);
|
||||
}
|
||||
while (reader.ReadToNextSibling("Module"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem converting XML to DTS.Serialization.Test object", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should normally return a schema representing the form of the XML
|
||||
/// generated/consumed by WriteXml/ReadXml, but it never called during
|
||||
/// the serialization process so ours just returns null.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// Null <see cref="XmlSchema"/> reference, always.
|
||||
/// </returns>
|
||||
///
|
||||
public XmlSchema GetSchema( )
|
||||
{
|
||||
// This method is never invoked during XML object serialization.
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the specified object for equality with this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="obj">
|
||||
/// The <see cref="object"/> to be tested for equality.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if the specified object has memeberwise equality with
|
||||
/// this object; false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
public override bool Equals( object obj )
|
||||
{
|
||||
try
|
||||
{
|
||||
Test that = obj as Test;
|
||||
return null != that
|
||||
&& this.Id.Equals( that.Id )
|
||||
&& this.Description.Equals( that.Description )
|
||||
&& this.ModulesEquals( that.Modules );
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem equality testing object " + ( null != obj ? "\"" + obj.ToString( ) + "\"" : "<<NULL>>" ), ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the specified object's module list for equality with this object's
|
||||
/// module list.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="thoseModules">
|
||||
/// The <see cref="List"/> of <see cref="Dts.Serialization.Test"/> object to be
|
||||
/// compared for equality with this test's equivalent.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if the two lists contain equivalent-valued members;
|
||||
/// false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
private bool ModulesEquals( List<Test.Module> thoseModules )
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( this.Modules.Count != thoseModules.Count )
|
||||
return false;
|
||||
else for ( int i=0; i < thoseModules.Count; i++ )
|
||||
if ( !this.Modules[ i ].Equals( thoseModules[ i ] ) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem equality-testing module list", ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the hash code for this object.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="int"/> hash code for this object.
|
||||
/// </returns>
|
||||
///
|
||||
public override int GetHashCode( )
|
||||
{
|
||||
return base.GetHashCode( );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DTS.Serialization.DDAS
|
||||
{
|
||||
public class DDASTest
|
||||
{
|
||||
public enum Fields
|
||||
{
|
||||
LabName,
|
||||
POCName,
|
||||
POCPhoneAndEmail,
|
||||
TestDate,
|
||||
TestTime,
|
||||
TestNumber,
|
||||
TestType,
|
||||
TestObject,
|
||||
DataType,
|
||||
SensorMakeModelSerial,
|
||||
SensorLocation,
|
||||
SensorAxis,
|
||||
SensorMountType,
|
||||
EngineeringUnits,
|
||||
ChannelErrors,
|
||||
SamplingRate,
|
||||
AAFilterCutoffDescription,
|
||||
BitResolution,
|
||||
DigitalFilterType,
|
||||
Notes
|
||||
}
|
||||
|
||||
private readonly Dictionary<Fields, string> _values = new Dictionary<Fields, string>();
|
||||
|
||||
public string GetValue(Fields field)
|
||||
{
|
||||
if (!_values.ContainsKey(field)) _values.Add(field, "#NOVALUE");
|
||||
return _values[field];
|
||||
}
|
||||
|
||||
public void SetValue(Fields field, string value)
|
||||
{
|
||||
_values[field] = value;
|
||||
foreach (var channel in _channels) channel.SetValue(field, value);
|
||||
}
|
||||
|
||||
private readonly List<DDASChannel> _channels = new List<DDASChannel>();
|
||||
|
||||
public DDASChannel[] Channels
|
||||
{
|
||||
get => _channels.ToArray();
|
||||
set
|
||||
{
|
||||
_channels.Clear();
|
||||
_channels.AddRange(value);
|
||||
}
|
||||
}
|
||||
|
||||
public Test Test { get; }
|
||||
|
||||
public FilteredData[] DataUnfilteredEU { get; }
|
||||
|
||||
public FilteredData[] DataADC { get; }
|
||||
|
||||
public double[] ActualRangesEUFiltered { get; }
|
||||
|
||||
public double[] ActualRangesEUUnfiltered { get; }
|
||||
|
||||
public double[] ActualRangesADC { get; }
|
||||
|
||||
public bool FlatFolders { get; }
|
||||
|
||||
public DDASTest(Test test, FilteredData[] adc, FilteredData[] euUnfiltered, string path,
|
||||
double[] actualRangesEUFiltered,
|
||||
double[] actualRangesEUUnfiltered,
|
||||
double[] actualRAngesADC,
|
||||
bool flatFolders)
|
||||
{
|
||||
Test = test;
|
||||
|
||||
DataADC = adc;
|
||||
DataUnfilteredEU = euUnfiltered;
|
||||
|
||||
ActualRangesADC = actualRAngesADC;
|
||||
ActualRangesEUUnfiltered = actualRangesEUUnfiltered;
|
||||
ActualRangesEUFiltered = actualRangesEUFiltered;
|
||||
FlatFolders = flatFolders;
|
||||
for (var i = 0; i < test.Channels.Count && i < DataADC.Length; i++)
|
||||
_channels.Add(new DDASChannel(this, i, path));
|
||||
SetValue(Fields.TestNumber, test.Id);
|
||||
SetValue(Fields.TestDate, test.InceptionDate.ToShortDateString());
|
||||
SetValue(Fields.TestTime, test.InceptionDate.ToShortTimeString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace DTS.Serialization.IRIGCH10.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// helper class for getting BCD values as defined in chapter 10 for things like dates,
|
||||
/// also contains 16/32 bit checksum functions
|
||||
/// </summary>
|
||||
public abstract class Utils
|
||||
{
|
||||
public static byte[] GetBCDBytes(int value)
|
||||
{
|
||||
if (value < 0 || value > 9999)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("value must be between 0, 9999");
|
||||
}
|
||||
|
||||
var bcd = 0;
|
||||
for (var digit = 0; digit < 4; ++digit)
|
||||
{
|
||||
var nibble = value % 10;
|
||||
bcd |= nibble << (digit * 4);
|
||||
value /= 10;
|
||||
}
|
||||
return new byte[] { (byte)(bcd & 0xff), (byte)((bcd >> 8) & 0xff) };
|
||||
}
|
||||
public static ushort GetCheckSum8(byte[] bytes)
|
||||
{
|
||||
ushort crc = 0;
|
||||
foreach (var v in bytes)
|
||||
{
|
||||
crc += v;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
/// <summary>
|
||||
/// computes a 16 bit checksum per ch10
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <returns></returns>
|
||||
public static ushort GetCheckSum16(byte[] bytes)
|
||||
{
|
||||
//we might want to pad with a 0 byte or drop a byte if odd number of bytes?
|
||||
//currently we only use this for packet headers, which are always of a set length, this
|
||||
//is just here for sanity
|
||||
System.Diagnostics.Trace.Assert(0 == bytes.Length % 2, "requires even length incoming data");
|
||||
|
||||
ushort crc = 0;
|
||||
var uints = new ushort[bytes.Length / 2];
|
||||
Buffer.BlockCopy(bytes, 0, uints, 0, bytes.Length);
|
||||
for (var i = 0; i < uints.Length; i++)
|
||||
{
|
||||
crc += uints[i];
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
/// <summary>
|
||||
/// computes a 32 bit checksum per ch 10,
|
||||
/// we use this currently for data packet checksums
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <returns></returns>
|
||||
public static uint GetCheckSum32(byte[] bytes)
|
||||
{
|
||||
//most packets should be filled in after the data portion with filler bytes to have
|
||||
//a length divisible by 4, this is just a sanity check
|
||||
System.Diagnostics.Trace.Assert(0 == bytes.Length % 4);
|
||||
|
||||
uint crc = 0;
|
||||
var uints = new uint[bytes.Length / 4];
|
||||
Buffer.BlockCopy(bytes, 0, uints, 0, bytes.Length);
|
||||
for (var i = 0; i < uints.Length; i++)
|
||||
{
|
||||
crc += uints[i];
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
/// <summary>
|
||||
/// returns an int given a bitarray and the starting and stopping point for bits of interest
|
||||
/// This allows you to return an int from 1-4 bytes
|
||||
/// </summary>
|
||||
/// <param name="ba"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <param name="endIndex"></param>
|
||||
/// <returns></returns>
|
||||
public static int BitArrayToInt32(BitArray ba, int startIndex, int endIndex)
|
||||
{
|
||||
var n = 0;
|
||||
var bit = 0;
|
||||
for (var i = startIndex; i <= endIndex; i++)
|
||||
{
|
||||
if (ba.Get(i))
|
||||
{
|
||||
n |= 1 << bit;
|
||||
}
|
||||
bit++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
public static void SetBits(BitArray b, uint value, int startIndex, int endIndex)
|
||||
{
|
||||
var ba = new BitArray(BitConverter.GetBytes(value));
|
||||
|
||||
var bit = 0;
|
||||
for (var i = startIndex; i <= endIndex; i++)
|
||||
{
|
||||
b.Set(i, ba.Get(bit));
|
||||
bit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user