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,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,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,151 @@
/*
Test.IntervalSec.cs
Copyright © 2008
Diversified Technical Systems, Inc.
All Rights Reserved
*/
using System;
using DTS.Common.Utilities;
using DTS.Common.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 => _NumberOfRoundingDecimalPlaces.Value;
set => _NumberOfRoundingDecimalPlaces.Value = value;
}
private readonly 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 => DoRoundOffValues ? Math.Round(_Begin.Value, NumberRoundingDecimalPlaces) : _Begin.Value;
set => _Begin.Value = value;
}
private readonly 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 => DoRoundOffValues ? Math.Round(_End.Value, NumberRoundingDecimalPlaces) : _End.Value;
set => _End.Value = value;
}
private readonly 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
{
var that = obj as IntervalSec;
return null != obj
&& Begin.Equals(that.Begin)
&& End.Equals(that.End);
}
catch (System.Exception ex)
{
throw new Exception("encountered problem equality checking " + 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 " + GetType().FullName, ex);
}
}
}
}
}

File diff suppressed because it is too large Load Diff

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,841 @@
/*
Test.Module.Channel.cs
Copyright © 2008
Diversified Technical Systems, Inc.
All Rights Reserved
*/
using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using DTS.Common.Utilities;
using DTS.Common.Utilities.DotNetProgrammingConstructs;
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 serializable channel information.
/// </summary>
[XmlSerializationTag("Channel")]
public abstract partial class Channel : Exceptional, IXmlSerializable
{
protected Channel()
{
}
public Channel(Module parentModule)
{
try
{
ParentModule = parentModule;
}
catch (System.Exception ex)
{
throw new Exception("encountered problem constructing " + GetType().Name, ex);
}
}
/// <summary>
/// The <see cref="DTS.Serialization.Test.Module"/> that contains this channel.
/// </summary>
public Module ParentModule
{
get => _ParentModule.Value;
private set => _ParentModule.Value = value;
}
private readonly Property<Module> _ParentModule
= new Property<Module>(
typeof(Channel).Namespace + ".Test.Module.Channel.ParentModule",
null,
false
);
/// <summary>
/// Get/set the channel's ordinal number.
/// </summary>
[XmlSerializationTag("Number")]
public int Number
{
get => _Number.Value;
set => _Number.Value = value;
}
private readonly Property<int> _Number
= new Property<int>(
typeof(Channel).Namespace + ".Test.Module.Channel.Number",
-1,
false
);
/// <summary>
/// get/set the absolute display order of the channel (absolutenumber refers to physical number)
/// </summary>
[XmlSerializationTag("AbsoluteDisplayOrder")]
public int AbsoluteDisplayOrder
{
get
{
if (_absoluteDisplayOrder.IsValueInitialized) { return _absoluteDisplayOrder.Value; }
return -1;
}
set => _absoluteDisplayOrder.Value = value;
}
private readonly Property<int> _absoluteDisplayOrder = new Property<int>(
typeof(Channel).Namespace + ".Test.Module.Channel.AbsoluteDisplayOrder",
-1, true);
/// <summary>
/// Get/set the start time for this channel.
/// </summary>
[XmlSerializationTag("Start")]
public DateTime Start
{
get => _Start.Value;
set => _Start.Value = value;
}
private readonly Property<DateTime> _Start
= new Property<DateTime>(
typeof(Channel).Namespace + ".Test.Module.Channel.Start",
DateTime.Now,
false
);
public bool TimeOfFirstSampleValid => _TimeOfFirstSampleSec.IsInitialized;
/// <summary>
/// Get/set the time of first sample in this test.
/// </summary>
[XmlSerializationTag("TimeOfFirstSample")]
public double TimeOfFirstSampleSec
{
get => _TimeOfFirstSampleSec.Value;
set => _TimeOfFirstSampleSec.Value = value;
}
protected Property<double> _TimeOfFirstSampleSec
= new Property<double>(
typeof(Channel).Namespace + ".Test.Module.Channel.TimeOfFirstSample",
0.0,
false
);
/// <summary>
/// Get the type of this channel.
/// </summary>
[XmlSerializationTag("ChannelType")]
public string ChannelType
{
get
{
try
{
return GetType().FullName;
}
catch (System.Exception ex)
{
throw new Exception("encountered problem getting channel type property", ex);
}
}
}
/// <summary>
/// Get/set flag that determines whether or not data will be written to/read from XML serialization.
/// </summary>
public bool ExpressDataInlineOnXmlSerialization
{
get => _ExpressDataInlineOnXmlSerialization.Value;
set => _ExpressDataInlineOnXmlSerialization.Value = value;
}
private readonly Property<bool> _ExpressDataInlineOnXmlSerialization
= new Property<bool>(
typeof(Channel).Namespace + ".Test.Module.Channel.ExpressDataInlineOnXmlSerialization",
false,
true
);
/// <summary>
/// Get/set a user-readable description of this channel object.
/// </summary>
[XmlSerializationTag("ChannelDescriptionString")]
public string ChannelDescriptionString
{
get => _ChannelDescriptionString.Value;
set => _ChannelDescriptionString.Value = value;
}
private readonly Property<string> _ChannelDescriptionString
= new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.ChannelDescriptionString",
"",
false
);
[XmlSerializationTag("HardwareChannelName")]
public string HardwareChannelName
{
get => _HardwareChannelName.Value;
set => _HardwareChannelName.Value = value;
}
private readonly Property<string> _HardwareChannelName
= new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.HardwareChannelName",
"", true);
/// <summary>
/// refers to a unique id for a logical channel in the test
/// for now this is using TestObjectChannel.GetId()
/// which is in the form of TestObjectSerial_ChannelType_ChannelId
/// </summary>
[XmlSerializationTag("ChannelId")]
public string ChannelId
{
//get { return _ChannelId.Value; }
get
{
if (!_ChannelId.IsInitialized || null == _ChannelId.Value)
{
return $"{HardwareChannelName}_{ChannelName2}";
}
return _ChannelId.Value;
}
set => _ChannelId.Value = value;
}
private readonly Property<string> _ChannelId
= new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.ChannelId",
"", true);
/// <summary>
/// refers to the Group name for a logical channel in the test
/// </summary>
[XmlSerializationTag("ChannelGroupName")]
public string ChannelGroupName
{
get => _ChannelGroupName.Value;
set => _ChannelGroupName.Value = value;
}
private readonly Property<string> _ChannelGroupName
= new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.ChannelGroupName",
"", true);
/// <summary>
/// This is the name of the channel before it was changed in the Display Name UI (if it was)
/// </summary>
[XmlSerializationTag("OriginalChannelName")]
public string OriginalChannelName
{
get => _OriginalChannelName.Value;
set => _OriginalChannelName.Value = value;
}
private readonly Property<string> _OriginalChannelName
= new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.OriginalChannelName",
"", true);
[XmlSerializationTag("ChannelName2")]
public string ChannelName2
{
get => _ChannelName2.Value;
set => _ChannelName2.Value = value;
}
private readonly Property<string> _ChannelName2
= new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.ChannelName2",
"", true);
/// <summary>
/// Get/set the data values for this channel.
/// </summary>
[XmlSerializationTag("Data")]
public DataArray<short> Data
{
get => _Data.Value;
set => _Data.Value = value;
}
private readonly Property<DataArray<short>> _Data
= new Property<DataArray<short>>(
typeof(Channel).Namespace + ".Test.Module.Channel.Data",
null,
false
);
/// <summary>
/// Get/set the subsampling indication for this channel's data.
/// </summary>
[XmlSerializationTag("IsSubsampled")]
public bool IsSubsampled
{
get => _IsSubsampled.Value;
set => _IsSubsampled.Value = value;
}
private readonly Property<bool> _IsSubsampled
= new Property<bool>(
typeof(Channel).Namespace + ".Test.Module.Channel.IsSubsampled",
false,
true
);
/// <summary>
/// Get/set whether or not to use EU for scaling.
/// </summary>
[XmlSerializationTag("UseEUScaler")]
public bool UseEUScaler
{
get => _UseEUScaler.Value;
set => _UseEUScaler.Value = value;
}
private readonly Property<bool> _UseEUScaler
= new Property<bool>(
typeof(Channel).Namespace + ".Test.Module.Channel.UseEUScaler",
false,
true
);
[XmlSerializationTag("LastCalibrationDate")]
public DateTime LastCalibrationDate
{
get => _lastCalibrationDate.Value;
set => _lastCalibrationDate.Value = value;
}
private readonly Property<DateTime> _lastCalibrationDate
= new Property<DateTime>(
typeof(Channel).Namespace + ".Test.Module.Channel.LastCalibrationDate",
DateTime.MinValue,
true
);
public bool IsLastCalibrationDateValid => _lastCalibrationDate.IsInitialized;
[XmlSerializationTag("CalDueDate")]
public DateTime CalDueDate
{
get => _calDueDate.Value;
set => _calDueDate.Value = value;
}
private readonly Property<DateTime> _calDueDate
= new Property<DateTime>(
typeof(Channel).Namespace + ".Test.Module.Channel.CalDueDate",
DateTime.MinValue,
true
);
public bool IsCalDueDateValid => _calDueDate.IsInitialized;
[XmlSerializationTag("IsoChannelName")]
public String IsoChannelName
{
get => _isoChannelName.Value;
set => _isoChannelName.Value = value;
}
private readonly Property<string> _isoChannelName
= new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.IsoChannelName",
"",
true
);
public bool IsIsoChannelNameValid => _isoChannelName.IsInitialized;
[XmlSerializationTag("UserChannelName")]
public String UserChannelName
{
get => _userChannelName.Value;
set => _userChannelName.Value = value;
}
private readonly Property<string> _userChannelName
= new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.UserChannelName",
"",
true
);
public string LinearSensorCalibration
{
get => _linearSensorCalibration.Value;
set => _linearSensorCalibration.Value = value;
}
private readonly Property<string> _linearSensorCalibration
= new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.LinearSensorCalibration",
"",
true
);
public bool IsUserChannelNameValid => _userChannelName.IsInitialized;
[XmlSerializationTag("UserCode")]
public String UserCode
{
get => _userCode.Value;
set => _userCode.Value = value;
}
private readonly Property<string> _userCode
= new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.UserCode",
"",
true
);
public bool IsUserCodeValid => _userCode.IsInitialized;
[XmlSerializationTag("SensorID")]
public string SensorID
{
get => _sensorID.Value;
set => _sensorID.Value = value;
}
private readonly Property<String> _sensorID =
new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.SensorID",
"",
true
);
public bool IsSensorIDValid => _sensorID.IsInitialized;
[XmlSerializationTag("OffsetToleranceLowMv")]
public double OffsetToleranceLowMv
{
get => _offsetToleranceLowMv.Value;
set => _offsetToleranceLowMv.Value = value;
}
private readonly Property<double> _offsetToleranceLowMv =
new Property<double>(
typeof(Channel).Namespace + ".Test.Module.Channel.OffsetToleranceLowMv",
0D,
true
);
public bool IsOffsetToleranceLowMvValid => _offsetToleranceLowMv.IsInitialized;
[XmlSerializationTag("OffsetToleranceHighMv")]
public double OffsetToleranceHighMv
{
get => _offsetToleranceHighMv.Value;
set => _offsetToleranceHighMv.Value = value;
}
private readonly Property<double> _offsetToleranceHighMv =
new Property<double>(
typeof(Channel).Namespace + ".Test.Module.Channel.OffsetToleranceHighMv",
0D,
true
);
public bool IsOffsetToleranceHighMvValid => _offsetToleranceHighMv.IsInitialized;
[XmlSerializationTag("UserValue1")]
public string UserValue1
{
get => _userValue1.Value;
set => _userValue1.Value = value;
}
private readonly Property<string> _userValue1 = new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.UserValue1",
"", true);
[XmlSerializationTag("UserValue2")]
public string UserValue2
{
get => _userValue2.Value;
set => _userValue2.Value = value;
}
private readonly Property<string> _userValue2 = new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.UserValue2",
"", true);
[XmlSerializationTag("UserValue3")]
public string UserValue3
{
get => _userValue3.Value;
set => _userValue3.Value = value;
}
private readonly Property<string> _userValue3 = new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.UserValue3",
"", true);
/// <summary>
/// the electronic id for a channel at test setup time
/// </summary>
[XmlSerializationTag("SetupEID")]
public string SetupEID
{
get => _SetupEID.Value ?? string.Empty;
set => _SetupEID.Value = value;
}
private readonly Property<string> _SetupEID = new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.SetupEID",
string.Empty, true);
/// <summary>
/// the electronic id on a channel at run time
/// </summary>
[XmlSerializationTag("DataCollectionEID")]
public string DataCollectionEID
{
get => _DataCollectionEID.Value ?? string.Empty;
set => _DataCollectionEID.Value = value;
}
private readonly Property<string> _DataCollectionEID = new Property<string>(
typeof(Channel).Namespace + ".Test.Module.Channel.DataCollectionEID",
string.Empty, true);
/// <summary>
/// Get/set the unsubsampled sample rate for this channel (if applicable).
/// </summary>
[XmlSerializationTag("UnsubsampledSampleRateHz")]
public float UnsubsampledSampleRateHz
{
get => _UnsubsampledSampleRateHz.Value;
set => _UnsubsampledSampleRateHz.Value = value;
}
private readonly Property<float> _UnsubsampledSampleRateHz
= new Property<float>(
typeof(Channel).Namespace + ".Test.Module.Channel.UnsubsampledSampleRateHz",
0,
true
);
/// <summary>
/// Get/set <see cref="double"/> noise as percentage of full scale value for this channel.
/// </summary>
public double NoiseAsPercentageOfFullScale
{
get => _NoiseAsPercentageOfFullScale.Value;
set => _NoiseAsPercentageOfFullScale.Value = value;
}
private readonly Property<double> _NoiseAsPercentageOfFullScale
= new Property<double>(
typeof(Channel).Namespace + ".Test.Module.Channel.NoiseAsPercentageOfFullScale",
0.0,
false
);
/// <summary>
/// Get the pre-test zero level (in ADC).
/// </summary>
public short PreTestZeroLevelAdc
{
get => _PreTestZeroLevelAdc.Value;
set => _PreTestZeroLevelAdc.Value = value;
}
private readonly Property<short> _PreTestZeroLevelAdc
= new Property<short>(
typeof(Channel).Namespace + ".Test.Module.Channel.PreTestZeroLevelAdc",
0,
false
);
//zeroMvInADC
public short ZeroMvInADC
{
get
{
if (_ZeroMvInADC.IsValueInitialized) { return _ZeroMvInADC.Value; }
return 0;
}
set => _ZeroMvInADC.Value = value;
}
private readonly Property<short> _ZeroMvInADC
= new Property<short>(
typeof(Channel).Namespace + ".Test.Module.Channel.ZeroMvInADC",
0,
false);
/// <summary>
/// WindowAverageADC is the average ADC over the averaging zero window for the channel
/// WindowAverageADC is initialized to short.MinValue, so this value is considered
/// an uninitialized or invalid value
/// </summary>
public short WindowAverageADC
{
get
{
if (_WindowAverageADC.IsValueInitialized) { return _WindowAverageADC.Value; }
return short.MinValue;
}
set => _WindowAverageADC.Value = value;
}
private readonly Property<short> _WindowAverageADC
= new Property<short>(
typeof(Channel).Namespace + ".Test.Module.Channel.WindowAverageADC",
short.MinValue,
false);
public int TriggerAdjustmentSamples
{
get => _TriggerAdjustmentSamples.Value;
set => _TriggerAdjustmentSamples.Value = value;
}
private readonly Property<int> _TriggerAdjustmentSamples
= new Property<int>(
typeof(Channel).Namespace + ".Test.Module.Channel.TriggerAdjustmentSamples",
0,
false);
public short OriginalOffsetADC
{
get => _OriginalOffsetADC.Value;
set => _OriginalOffsetADC.Value = value;
}
private readonly Property<short> _OriginalOffsetADC
= new Property<short>(
typeof(Channel).Namespace + ".Test.Module.Channel.OriginalOffsetADC",
0,
false);
public double Excitation
{
get => _Excitation.Value;
set => _Excitation.Value = value;
}
private readonly Property<double> _Excitation
= new Property<double>(
typeof(Channel).Namespace + ".Test.Module.Channel.Excitation",
5D,
false);
public int RemovedADC
{
get
{
if (_RemovedADC.IsValueInitialized) { return _RemovedADC.Value; }
return 0;
}
set => _RemovedADC.Value = value;
}
private readonly Property<int> _RemovedADC
= new Property<int>(
typeof(Channel).Namespace + ".Test.Module.Channel.RemovedADC",
0,
true
);
public int RemovedInternalADC
{
get
{
if (_RemovedInternalADC.IsValueInitialized) { return _RemovedInternalADC.Value; }
return 0;
}
set => _RemovedInternalADC.Value = value;
}
private readonly Property<int> _RemovedInternalADC
= new Property<int>(
typeof(Channel).Namespace + ".Test.Module.Channel.RemovedInternalADC",
0,
true
);
/// <summary>
/// Get/set the sample rate for this test module.
/// </summary>
[XmlSerializationTag("IsSupersampled")]
public bool IsSupersampled
{
get => _IsSupersampled.Value;
set => _IsSupersampled.Value = value;
}
private readonly Property<bool> _IsSupersampled
= new Property<bool>(
typeof(Module).Namespace + ".Test.Module.Channel.IsSupersampled",
false,
false
);
/// <summary>
/// Get/set the EU Scale Factor.
/// </summary>
[XmlSerializationTag("ScaleFactorEU")]
public double ScaleFactorEU
{
get => _ScaleFactorEU.Value;
set => _ScaleFactorEU.Value = value;
}
private readonly Property<double> _ScaleFactorEU
= new Property<double>(
typeof(Module).Namespace + ".Test.Module.Channel.ScaleFactorEU",
0D,
false
);
/// <summary>
/// Get/set the sample rate for this test module.
/// </summary>
[XmlSerializationTag("UnsupersampledSampleRateHz")]
public float UnsupersampledSampleRateHz
{
get => _UnsupersampledSampleRateHz.Value;
set => _UnsupersampledSampleRateHz.Value = value;
}
private readonly Property<float> _UnsupersampledSampleRateHz
= new Property<float>(
typeof(Module).Namespace + ".Test.Module.Channel.UnsupersampledSampleRateHz",
0,
false
);
/// <summary>
/// Get data zero level counts.
/// </summary>
public abstract short DataZeroLevelAdc
{
get;
}
/// <summary>
/// Get/set the persistent information for this channel.
/// </summary>
public SliceRaw.File.PersistentChannel PersistentChannelInfo
{
get => _PersistentChannelInfo.Value;
set => _PersistentChannelInfo.Value = value;
}
private readonly Property<SliceRaw.File.PersistentChannel> _PersistentChannelInfo
= new Property<SliceRaw.File.PersistentChannel>(
typeof(Channel).Namespace + ".Test.Module.Channel.PersistentChannelInfo",
null,
false
);
/// <summary>
/// Get/set the persistent information for this channel.
/// </summary>
public TDAS.File.PersistentChannel TDASPersistentChannelInfo
{
get => _TDASPersistentChannelInfo.Value;
set => _TDASPersistentChannelInfo.Value = value;
}
private readonly Property<TDAS.File.PersistentChannel> _TDASPersistentChannelInfo
= new Property<TDAS.File.PersistentChannel>(
typeof(Channel).Namespace + ".Test.Module.Channel.TDASPersistentChannelInfo",
null,
false
);
[XmlSerializationTag("DataFlag")]
public int DataFlag
{
get => _DataFlag.Value;
set => _DataFlag.Value = value;
}
private readonly Property<int> _DataFlag = new Property<int>(
typeof(Channel).Namespace + ".Test.Module.Channel.DataFlag",
1, true);
public bool IsDataFlagValid => _DataFlag.IsInitialized;
//public DTS.Slice.Control.Event.Module.Channel emc;
public object emc;
/// <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 abstract void WriteXml(XmlWriter writer);
/// <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 abstract void ReadXml(XmlReader reader);
/// <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 virtual 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
{
var that = obj as Channel;
return null != obj
&& ChannelId.Equals(that.ChannelId)
&& Data.Equals(that.Data)
&& ExpressDataInlineOnXmlSerialization.Equals(that.ExpressDataInlineOnXmlSerialization)
&& Number.Equals(that.Number)
&& PreTestZeroLevelAdc.Equals(that.PreTestZeroLevelAdc)
&& NoiseAsPercentageOfFullScale.Equals(that.NoiseAsPercentageOfFullScale)
&& IsSubsampled.Equals(that.IsSubsampled)
&& UnsubsampledSampleRateHz.Equals(that.UnsubsampledSampleRateHz)
&& IsSupersampled.Equals(that.IsSupersampled)
&& UnsupersampledSampleRateHz.Equals(that.UnsupersampledSampleRateHz)
&& _TimeOfFirstSampleSec.IsInitialized == that._TimeOfFirstSampleSec.IsInitialized && (_TimeOfFirstSampleSec.IsInitialized ? TimeOfFirstSampleSec == that.TimeOfFirstSampleSec : true)
&& Start.ToString().Equals(that.Start.ToString())
&& UserValue1.Equals(that.UserValue1)
&& UserValue2.Equals(that.UserValue2)
&& UserValue3.Equals(that.UserValue3)
&& AbsoluteDisplayOrder.Equals(that.AbsoluteDisplayOrder)
&& SetupEID.Equals(that.SetupEID)
&& DataCollectionEID.Equals(that.DataCollectionEID);
}
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;
}
}
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using DTS.Common.DAS.Concepts;
namespace DTS.Serialization
{
/// <summary>
/// A collection of a channel and associated metadata that will all be needed together when
/// this file format starts laying down bytes.
/// </summary>
public class ChannelWithMeta
{
/// <summary>
/// Get/set the <see cref="DTS.Serialization.Test.Module.Channel"/> to be serialized.
/// </summary>
public Test.Module.Channel Channel { get; }
/// <summary>
/// Get/set the <see cref="DataScaler"/> associated with the
/// specified channel.
/// </summary>
public DataScaler Scaler { get; }
/// <summary>
/// Get/set the <see cref="double"/> sample rate associated with the specified channel.
/// </summary>
public double SampleRate { get; }
/// <summary>
/// Get/set the <see cref="double"/> start time associated with the specified channel.
/// </summary>
public double StartTime { get; }
/// <summary>
/// Initialize an instance of the ChannelWithMeta class.
/// </summary>
///
/// <param name="channel">
/// A <see cref="DTS.Serialization.Test.Module.Channel"/> to be serialized.
/// </param>
///
/// <param name="scaler">
/// The <see cref="DataScaler"/> containing scaling information for
/// the specified channel.
/// </param>
///
/// <param name="samplerate">
/// The <see cref="double"/> sample rate of the associated channel.
/// </param>
///
/// <param name="starttime">
/// The <see cref="double"/> start time of the associated channel.
/// </param>
///
public ChannelWithMeta(DTS.Serialization.Test.Module.Channel channel, DataScaler scaler, double samplerate, double starttime)
{
Channel = channel;
Scaler = scaler;
SampleRate = samplerate;
StartTime = starttime;
}
public static double GetMinStartTime(double start, IList<ChannelWithMeta> channelsWithMeta)
{
// Start is a generally a negative value, so to get the value for the start time of the minimum common data set, run Max()
return Math.Max(start, channelsWithMeta.Min(cwm => cwm.StartTime));
}
public static double GetMinStopTime(double stop, IList<ChannelWithMeta> channelsWithMeta)
{
// To get the value for the stop time of the minimum common data set, run Min()
// LINQ statement will sometimes hand back float-rounding error numbers (4.999999999999995 v 5.0), so cast to decimals.
return (double)Math.Min((decimal)stop,
channelsWithMeta.Min(cwm =>
(decimal)cwm.StartTime + (cwm.Channel.PersistentChannelInfo.Length - 1) * 1m / (decimal)cwm.SampleRate));
}
}
}

View File

@@ -0,0 +1,499 @@
/*
Test.Module.Channel.DataArray.cs
Copyright © 2009
Diversified Technical Systems, Inc.
All Rights Reserved
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using DTS.Common.Utilities;
using DTS.Common.Utilities.DotNetProgrammingConstructs;
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
{
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];
}
return _Values.Value;
}
set => _Values.Value = value;
}
private readonly 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 => _ScaleFactorMv.Value;
set => _ScaleFactorMv.Value = value;
}
private readonly Property<double> _ScaleFactorMv
= new Property<double>(
typeof(DataArray<DataType>).Namespace + ".Test.Module.Channel.DataArray.ScaleFactorMv",
0.0,
false
);
public double ScaleFactorEU
{
get => _ScaleFactorEU.Value;
set => _ScaleFactorEU.Value = value;
}
private readonly Property<double> _ScaleFactorEU
= new Property<double>(
typeof(DataArray<DataType>).Namespace + ".Test.Module.Channel.DataArray.ScaleFactorEU",
0.0,
false
);
public bool UseEUScaleFactors
{
get => _UseEUScaleFactors.Value;
set => _UseEUScaleFactors.Value = value;
}
private readonly Property<bool> _UseEUScaleFactors
= new Property<bool>(
typeof(DataArray<DataType>).Namespace + ".Test.Module.Channel.DataArray.UseEUScaleFactors",
false,
true
);
public short DataZeroLevel
{
get => _DataZeroLevel.Value;
set => _DataZeroLevel.Value = value;
}
private readonly 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 => _UnitConversion.Value;
set => _UnitConversion.Value = value;
}
private readonly 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 => _Multiplier.Value;
set => _Multiplier.Value = value;
}
private readonly 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 => _UserOffsetEU.Value;
set => _UserOffsetEU.Value = value;
}
private readonly 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 => _MvPerEu.Value;
set => _MvPerEu.Value = value;
}
private readonly 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("");
var 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 (var 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 { 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 { ScaleFactorMv = double.Parse(reader.GetAttribute(DataAdcToMvScaleFactorTag), cult); }
catch (System.Exception ex)
{
throw new Exception("encountered problem parsing ADC->MV scaling factor property", ex);
}
try { MvPerEu = double.Parse(reader.GetAttribute(DataMvPerEuTag), cult); }
catch (System.Exception ex)
{
throw new Exception("encountered problem parsing MV/EU sensitivity factor property", ex);
}
var dataTypeMembers = typeof(DataType).GetMember("Parse");
if (null == dataTypeMembers || dataTypeMembers.Length < 1)
throw new Exception("data type does not contain a \"Parse\" method");
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); }
var 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 (var i = 0; i < 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); }
var 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 " + (datumValueString ?? "<<NULL>>"), ex); }
try { 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)
{
var that = obj as DataArray<DataType>;
try
{
return (null != that)
&& ScaleFactorMv.Equals(that.ScaleFactorMv)
&& MvPerEu.Equals(that.MvPerEu)
&& (Values.Length == that.Values.Length)
&& 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 || Values.Length != thoseValues.Length)
return false;
for (var i = 0; i < Values.Length; i++)
if (!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,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,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);
}
}
}
}

File diff suppressed because it is too large Load Diff

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