This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1 @@
12

View File

@@ -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);
}
}
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
// }
//}
}

View File

@@ -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)
{
}
}
}
}

View File

@@ -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>

View File

@@ -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
);
}
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}
}
}

View File

@@ -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() { }
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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 )

View File

@@ -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();
}
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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)
{
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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]);
}
}
}
}
}

View File

@@ -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; }
}
}
}

View File

@@ -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));
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}
}
}
}
}
}

View File

@@ -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");
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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() { }
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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; }
}
}

View File

@@ -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));
}
}
}
}

View File

@@ -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");
}
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}
}
}
}
}

View File

@@ -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>

View File

@@ -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);
}
}
}
}
}

View File

@@ -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");
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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>

View File

@@ -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;
// }
//}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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 ***
}

View File

@@ -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 ***
}

View 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>

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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 ***
}

View 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 ***
}

View File

@@ -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()));
}
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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( );
}
}
}
}
}
}

View File

@@ -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);
}
}
}
}
}
}

View File

@@ -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);
}
}
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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 ***
}

View 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));
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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 ***
}

View File

@@ -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;
}
}
}

View File

@@ -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();
}
}

View File

@@ -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()
{
}
}
}

View File

@@ -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 ***
}

View 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
);
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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 );
}
}
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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 ***
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -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 ***
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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));
}
}
}

View File

@@ -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;
}
}

View File

@@ -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( );
}
}
}

View File

@@ -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());
}
}
}

View File

@@ -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