init
This commit is contained in:
@@ -0,0 +1,324 @@
|
||||
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);
|
||||
|
||||
public static void WriteFile(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private static AnalogDataFormat1Packet GetAnalogPacket(long currentSample, GetNextSampleDelegate getNextSample,
|
||||
long channelLength, int totalChannels, int nanoseconds,
|
||||
int seconds, double sampleRate, out long samplesProcessed, byte sequenceNumber, bool includeSecondaryHeader)
|
||||
{
|
||||
var newRTC = GetRTC(currentSample, sampleRate);
|
||||
|
||||
var numSamples = channelLength;
|
||||
numSamples -= currentSample;
|
||||
|
||||
//we should target 100ms of data per packet
|
||||
var numSamplesPerPacket = Math.Floor(sampleRate / 10);
|
||||
|
||||
if (numSamples > numSamplesPerPacket)
|
||||
{
|
||||
numSamples = Convert.ToInt64(numSamplesPerPacket);
|
||||
}
|
||||
|
||||
var analogPacket = new AnalogDataFormat1Packet(nanoseconds, seconds,
|
||||
getNextSample, totalChannels, channelLength, newRTC, numSamples, currentSample, sequenceNumber, 3,
|
||||
includeSecondaryHeader);
|
||||
|
||||
samplesProcessed = numSamples;
|
||||
return analogPacket;
|
||||
}
|
||||
|
||||
//for convenience just store relative time counter 10MHZ conversion factor
|
||||
private const int RTC_PER_SECOND = 10000000;
|
||||
private static long GetRTC(long currentSample, double sampleRate)
|
||||
{
|
||||
var secondsPassed = currentSample / sampleRate;
|
||||
return AbstractDataPacket.BASE_RTC + Convert.ToInt64(secondsPassed * RTC_PER_SECOND);
|
||||
}
|
||||
|
||||
private static long GetRTC(long tickDelta)
|
||||
{
|
||||
var seconds = (double)tickDelta / TimeSpan.TicksPerSecond;
|
||||
return AbstractDataPacket.BASE_RTC - Convert.ToInt64(seconds * RTC_PER_SECOND);
|
||||
}
|
||||
/// <summary>
|
||||
/// parses out all packets from array of bytes
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
public Chapter10File(byte[] bytes)
|
||||
{
|
||||
_bytes = new byte[bytes.Length];
|
||||
Buffer.BlockCopy(bytes, 0, _bytes, 0, bytes.Length);
|
||||
var currentByteIndex = 0L;
|
||||
var badPackets = 0;
|
||||
var goodPackets = 0;
|
||||
while (currentByteIndex < (bytes.Length - PacketHeader.PACKET_HEADER_LENGTH))
|
||||
{
|
||||
try
|
||||
{
|
||||
currentByteIndex = ReadTransportHeader(bytes, currentByteIndex, out var transportHeader);
|
||||
var startOfChapter10Packet = currentByteIndex;
|
||||
currentByteIndex = ReadChapter10PacketHeader(bytes, currentByteIndex, out var packetHeader);
|
||||
if (packetHeader.PacketSyncPattern != PacketHeader.EXPECTED_SYNC_PATTERN || packetHeader.CheckSum != packetHeader.ComputeCheckSum())
|
||||
{
|
||||
badPackets++;
|
||||
//this packet is invalid, so we need to skip ahead
|
||||
//skip until we see the next sync pattern, then backstep to the start of the transport bytes, then continue on
|
||||
currentByteIndex = GetIndexOfNextPacket(bytes, startOfChapter10Packet);
|
||||
continue;
|
||||
}
|
||||
_transportHeaders.Add(transportHeader);
|
||||
if (packetHeader.SecondaryHeaderPresent)
|
||||
{
|
||||
ReadChapter10SecondHeaderTimeFormat(bytes, startOfChapter10Packet + PacketHeader.PACKET_HEADER_LENGTH, out var secondaryTimeHeader);
|
||||
_secondaryTimePackets.Add(secondaryTimeHeader);
|
||||
}
|
||||
_packets.Add(packetHeader);
|
||||
|
||||
_packetToByteStartStop[packetHeader] = new Tuple<long, long>(startOfChapter10Packet, currentByteIndex);
|
||||
goodPackets++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Hit exception processing file at byte: {currentByteIndex}, {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
GoodPackets = goodPackets;
|
||||
RejectedPackets = badPackets;
|
||||
}
|
||||
/// <summary>
|
||||
/// determines the next valid packet starting location after the provided starting spot
|
||||
/// this is used to skip over bad data to the next good packet
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <returns></returns>
|
||||
public static long GetIndexOfNextPacket(byte[] bytes, long startIndex)
|
||||
{
|
||||
for (var i = startIndex; i < bytes.Length - 1; i++)
|
||||
{
|
||||
if (BitConverter.ToUInt16(bytes, (int)i) == PacketHeader.EXPECTED_SYNC_PATTERN)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
//if we got here there are no more valid packets, you are done.
|
||||
return bytes.Length;
|
||||
}
|
||||
/// <summary>
|
||||
/// reads a secondary time header from provided bytes and starting spot
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="secondaryTimeFormat"></param>
|
||||
private void ReadChapter10SecondHeaderTimeFormat(byte[] bytes, long start, out ISecondaryTimeFormatHeader secondaryTimeFormat)
|
||||
{
|
||||
var headerBytes = new byte[SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH];
|
||||
Array.Copy(bytes, start, headerBytes, 0, SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH);
|
||||
secondaryTimeFormat = new SecondaryTimeFormatHeader(headerBytes);
|
||||
}
|
||||
/// <summary>
|
||||
/// reads a transport header from provided bytes and starting spot
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <param name="transportHeader"></param>
|
||||
/// <returns></returns>
|
||||
private long ReadTransportHeader(byte[] bytes, long startIndex, out TransportStreamHeader transportHeader)
|
||||
{
|
||||
var transportHeaderBytes = new byte[4];
|
||||
Array.Copy(bytes, startIndex, transportHeaderBytes, 0, 4);
|
||||
transportHeader = new TransportStreamHeader(transportHeaderBytes);
|
||||
return startIndex + 4L;
|
||||
}
|
||||
/// <summary>
|
||||
/// reads a Packet from stream of bytes at given starting spot
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <param name="packetHeader"></param>
|
||||
/// <returns></returns>
|
||||
public static long ReadChapter10PacketHeader(byte[] bytes, long startIndex, out IPacketHeader packetHeader)
|
||||
{
|
||||
var headerBytes = new byte[PacketHeader.PACKET_HEADER_LENGTH];
|
||||
Array.Copy(bytes, startIndex, headerBytes, 0, PacketHeader.PACKET_HEADER_LENGTH);
|
||||
packetHeader = new PacketHeader(headerBytes);
|
||||
return startIndex + packetHeader.PacketLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,571 @@
|
||||
/*
|
||||
* Iso.File.Test.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.DotNetProgrammingConstructs;
|
||||
|
||||
namespace DTS.Serialization.Iso
|
||||
{
|
||||
// *** see Iso.File.cs ***
|
||||
public partial class File
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// ISO-style representation of a test.
|
||||
/// </summary>
|
||||
///
|
||||
public partial class Test : Exceptional
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the data format edition number <see cref="string"/> of the file format generated by this object.
|
||||
/// </summary>
|
||||
public string DataFormatEditionNumber
|
||||
{
|
||||
get => _DataFormatEditionNumber.Value;
|
||||
set => _DataFormatEditionNumber.Value = value;
|
||||
}
|
||||
public const string DataFormatEditionNumberLabel = "Data format edition number";
|
||||
private readonly Property<string> _DataFormatEditionNumber
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.DataFormatEditionNumber",
|
||||
"1.6",
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the laboratory name <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string LaboratoryName
|
||||
{
|
||||
get => _LaboratoryName.Value;
|
||||
set => _LaboratoryName.Value = value;
|
||||
}
|
||||
private const string LaboratoryNameLabel = "Laboratory name";
|
||||
private readonly Property<string> _LaboratoryName
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.LaboratoryName",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the laboratory contact name <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string LaboratoryContactName
|
||||
{
|
||||
get => _LaboratoryContactName.Value;
|
||||
set => _LaboratoryContactName.Value = value;
|
||||
}
|
||||
private const string LaboratoryContactNameLabel = "Laboratory contact name";
|
||||
private readonly Property<string> _LaboratoryContactName
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.LaboratoryContactName",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the laboratory contact phone <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string LaboratoryContactPhone
|
||||
{
|
||||
get => _LaboratoryContactPhone.Value;
|
||||
set => _LaboratoryContactPhone.Value = value;
|
||||
}
|
||||
private const string LaboratoryContactPhoneLabel = "Laboratory contact phone";
|
||||
private readonly Property<string> _LaboratoryContactPhone
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.LaboratoryContactPhone",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the laboratory contact fax <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string LaboratoryContactFax
|
||||
{
|
||||
get => _LaboratoryContactFax.Value;
|
||||
set => _LaboratoryContactFax.Value = value;
|
||||
}
|
||||
private const string LaboratoryContactFaxLabel = "Laboratory contact fax";
|
||||
private readonly Property<string> _LaboratoryContactFax
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.LaboratoryContactFax",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the laboratory contact email <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string LaboratoryContactEmail
|
||||
{
|
||||
get => _LaboratoryContactEmail.Value;
|
||||
set => _LaboratoryContactEmail.Value = value;
|
||||
}
|
||||
private const string LaboratoryContactEmailLabel = "Laboratory contact email";
|
||||
private readonly Property<string> _LaboratoryContactEmail
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.LaboratoryContactEmail",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the laboratory test reference number <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string LaboratoryTestReferenceNumber
|
||||
{
|
||||
get => _LaboratoryTestReferenceNumber.Value;
|
||||
set => _LaboratoryTestReferenceNumber.Value = value;
|
||||
}
|
||||
private const string LaboratoryTestReferenceNumberLabel = "Laboratory test ref. number";
|
||||
private readonly Property<string> _LaboratoryTestReferenceNumber
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.LaboratoryTestReferenceNumber",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the laboratory project reference number <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string LaboratoryProjectReferenceNumber
|
||||
{
|
||||
get => _LaboratoryProjectReferenceNumber.Value;
|
||||
set => _LaboratoryProjectReferenceNumber.Value = value;
|
||||
}
|
||||
private const string LaboratoryProjectReferenceNumberLabel = ".Laboratory project ref. num"; //The leading "." means it's additional to the standard
|
||||
private readonly Property<string> _LaboratoryProjectReferenceNumber
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.LaboratoryProjectReferenceNumber",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the customer name <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string CustomerName
|
||||
{
|
||||
get => _CustomerName.Value;
|
||||
set => _CustomerName.Value = value;
|
||||
}
|
||||
private const string CustomerNameLabel = "Customer name";
|
||||
private readonly Property<string> _CustomerName
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.CustomerName",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the customer test reference number <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string CustomerTestReferenceNumber
|
||||
{
|
||||
get => _CustomerTestReferenceNumber.Value;
|
||||
set => _CustomerTestReferenceNumber.Value = value;
|
||||
}
|
||||
private const string CustomerTestReferenceNumberLabel = "Customer test ref. number";
|
||||
private readonly Property<string> _CustomerTestReferenceNumber
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.CustomerTestReferenceNumber",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the customer project reference number <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string CustomerProjectReferenceNumber
|
||||
{
|
||||
get => _CustomerProjectReferenceNumber.Value;
|
||||
set => _CustomerProjectReferenceNumber.Value = value;
|
||||
}
|
||||
private const string CustomerProjectReferenceNumberLabel = "Customer project ref. number";
|
||||
private readonly Property<string> _CustomerProjectReferenceNumber
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.CustomerProjectReferenceNumber",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set customer order number <see cref="string"/> for the current test.
|
||||
/// </summary>
|
||||
public string CustomerOrderNumber
|
||||
{
|
||||
get => _CustomerOrderNumber.Value;
|
||||
set => _CustomerOrderNumber.Value = value;
|
||||
}
|
||||
private const string CustomerOrderNumberLabel = "Customer order number";
|
||||
private readonly Property<string> _CustomerOrderNumber
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.CustomerOrderNumber",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set customer cost unit <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string CustomerCostUnit
|
||||
{
|
||||
get => _CustomerCostUnit.Value;
|
||||
set => _CustomerCostUnit.Value = value;
|
||||
}
|
||||
private const string CustomerCostUnitLabel = "Customer cost unit";
|
||||
private readonly Property<string> _CustomerCostUnit
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.CustomerCostUnit",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the Test engineer name <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string TestEngineerName
|
||||
{
|
||||
get => _TestEngineerName.Value;
|
||||
set => _TestEngineerName.Value = value;
|
||||
}
|
||||
private const string TestEngineerNameLabel = "Customer test engineer name";
|
||||
private readonly Property<string> _TestEngineerName
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.CustomerTestEngineerName",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the Test engineer phone <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string TestEngineerPhone
|
||||
{
|
||||
get => _TestEngineerPhone.Value;
|
||||
set => _TestEngineerPhone.Value = value;
|
||||
}
|
||||
private const string TestEngineerPhoneLabel = "Customer test engineer phone";
|
||||
private readonly Property<string> _TestEngineerPhone
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.CustomerTestEngineerPhone",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the Test engineer fax <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string TestEngineerFax
|
||||
{
|
||||
get => _TestEngineerFax.Value;
|
||||
set => _TestEngineerFax.Value = value;
|
||||
}
|
||||
private const string TestEngineerFaxLabel = "Customer test engineer fax";
|
||||
private readonly Property<string> _TestEngineerFax
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.CustomerTestEngineerFax",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the Test engineer email <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string TestEngineerEmail
|
||||
{
|
||||
get => _TestEngineerEmail.Value;
|
||||
set => _TestEngineerEmail.Value = value;
|
||||
}
|
||||
private const string TestEngineerEmailLabel = "Customer test engineer email";
|
||||
private readonly Property<string> _TestEngineerEmail
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.CustomerTestEngineerEmail",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the title <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string Title
|
||||
{
|
||||
get => _Title.Value;
|
||||
set => _Title.Value = value;
|
||||
}
|
||||
private const string TitleLabel = "Title";
|
||||
private readonly Property<string> _Title
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Title",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the number of media <see cref="string"/> representation for this test.
|
||||
/// </summary>
|
||||
public string NumberOfMedia
|
||||
{
|
||||
get => _NumberOfMedia.Value;
|
||||
set => _NumberOfMedia.Value = value;
|
||||
}
|
||||
private const string NumberOfMediaLabel = "Medium No./number of media";
|
||||
private readonly Property<string> _NumberOfMedia
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.NumberOfMedia",
|
||||
"1/1",
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the timestamp <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string Timestamp
|
||||
{
|
||||
get => _Timestamp.Value;
|
||||
set => _Timestamp.Value = value;
|
||||
}
|
||||
private const string TimestampLabel = "Timestamp";
|
||||
private readonly Property<string> _Timestamp
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Timestamp",
|
||||
// 14967 DateTime stamp not complete in ISO export
|
||||
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set this ISO file test's comment <see cref="string"/>.
|
||||
/// </summary>
|
||||
public string TestComment
|
||||
{
|
||||
get => _Comments.Value;
|
||||
set => _Comments.Value = value;
|
||||
}
|
||||
protected const string CommentsLabel = "Comments";
|
||||
private readonly Property<string> _Comments
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Comments",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the type <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string Type
|
||||
{
|
||||
get => _Type.Value;
|
||||
set => _Type.Value = value;
|
||||
}
|
||||
private const string TypeLabel = "Type of the test";
|
||||
private readonly Property<string> _Type
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Type",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the date <see cref="System.DateTime"/> for this test.
|
||||
/// </summary>
|
||||
public DateTime Date
|
||||
{
|
||||
get => _Date.Value;
|
||||
set => _Date.Value = value;
|
||||
}
|
||||
private const string DateLabel = "Date of the test";
|
||||
private readonly Property<DateTime> _Date
|
||||
= new Property<DateTime>(
|
||||
typeof(File).Namespace + ".Iso.File.Date",
|
||||
DateTime.Now,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the subtype <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string Subtype
|
||||
{
|
||||
get => _Subtype.Value;
|
||||
set => _Subtype.Value = value;
|
||||
}
|
||||
private const string SubtypeLabel = "Subtype of the test";
|
||||
private readonly Property<string> _Subtype
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Subtype",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the regulation <see cref="string"/> for this test.
|
||||
/// </summary>
|
||||
public string Regulation
|
||||
{
|
||||
get => _Regulation.Value;
|
||||
set => _Regulation.Value = value;
|
||||
}
|
||||
private const string RegulationLabel = "Regulation";
|
||||
private readonly Property<string> _Regulation
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.Regulation",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> reference temperature value for this test.
|
||||
/// </summary>
|
||||
public string ReferenceTemperature
|
||||
{
|
||||
get => _ReferenceTemperature.Value;
|
||||
set => _ReferenceTemperature.Value = value;
|
||||
}
|
||||
private const string ReferenceTemperatureLabel = "Reference temperature";
|
||||
private readonly Property<string> _ReferenceTemperature
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.ReferenceTemperature",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
// [DefaultValue( "90.0" )] -- all values should have
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="double"/> relative air humdity value for this test.
|
||||
/// </summary>
|
||||
public string RelativeAirHumidity
|
||||
{
|
||||
get => _RelativeAirHumidity.Value;
|
||||
set => _RelativeAirHumidity.Value = value;
|
||||
}
|
||||
private const string RelativeAirHumidityLabel = "Relative air humidity";
|
||||
private readonly Property<string> _RelativeAirHumidity
|
||||
= new Property<string>(
|
||||
typeof(File).Namespace + ".Iso.File.RelativeAirHumidity",
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get the <see cref="int"/> number of test objects in this test.
|
||||
/// </summary>
|
||||
public int NumberOfTestObjects => Objects.Count;
|
||||
|
||||
private const string NumberOfTestObjectsLabel = "Number of test objects";
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the <see cref="DTS.Serialization.Iso.File.Test.Object"/>s for this test.
|
||||
/// </summary>
|
||||
public List<Object> Objects
|
||||
{
|
||||
get => _Objects.Value;
|
||||
set => _Objects.Value = value;
|
||||
}
|
||||
private readonly Property<List<Object>> _Objects
|
||||
= new Property<List<Object>>(
|
||||
typeof(File).Namespace + ".Iso.File.Test.Objects",
|
||||
new List<Object>(),
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the list of <see cref="DTS.Serialization.Iso.File.Test.Channel"/>s for this test.
|
||||
/// </summary>
|
||||
public List<Channel> Channels
|
||||
{
|
||||
get => _Channels.Value;
|
||||
set => _Channels.Value = value;
|
||||
}
|
||||
private readonly Property<List<Channel>> _Channels
|
||||
= new Property<List<Channel>>(
|
||||
typeof(File).Namespace + ".Iso.File.Channels",
|
||||
new List<Channel>(),
|
||||
true
|
||||
);
|
||||
|
||||
/// <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.ExtraProperties",
|
||||
new List<ExtraProperty>(),
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Generate a <see cref="string"/> representation for this instance.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// A <see cref="string"/> representation of this instance.
|
||||
/// </returns>
|
||||
///
|
||||
public override string ToString()
|
||||
{
|
||||
try
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
string line = null;
|
||||
|
||||
builder.Append(DataFormatEditionNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => DataFormatEditionNumber)) + (null != line ? Eol : ""));
|
||||
builder.Append(LaboratoryNameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryName)) + (null != line ? Eol : ""));
|
||||
builder.Append(LaboratoryContactNameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryContactName)) + (null != line ? Eol : ""));
|
||||
builder.Append(LaboratoryContactPhoneLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryContactPhone)) + (null != line ? Eol : ""));
|
||||
builder.Append(LaboratoryContactFaxLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryContactFax)) + (null != line ? Eol : ""));
|
||||
builder.Append(LaboratoryContactEmailLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryContactEmail)) + (null != line ? Eol : ""));
|
||||
builder.Append(LaboratoryTestReferenceNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryTestReferenceNumber)) + (null != line ? Eol : ""));
|
||||
builder.Append(LaboratoryProjectReferenceNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryProjectReferenceNumber)) + (null != line ? Eol : ""));
|
||||
builder.Append(CustomerNameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerName)) + (null != line ? Eol : ""));
|
||||
builder.Append(CustomerTestReferenceNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerTestReferenceNumber)) + (null != line ? Eol : ""));
|
||||
builder.Append(CustomerProjectReferenceNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerProjectReferenceNumber)) + (null != line ? Eol : ""));
|
||||
builder.Append(CustomerOrderNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerOrderNumber)) + (null != line ? Eol : ""));
|
||||
builder.Append(CustomerCostUnitLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerCostUnit)) + (null != line ? Eol : ""));
|
||||
builder.Append(TestEngineerNameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestEngineerName)) + (null != line ? Eol : ""));
|
||||
builder.Append(TestEngineerPhoneLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestEngineerPhone)) + (null != line ? Eol : ""));
|
||||
builder.Append(TestEngineerFaxLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestEngineerFax)) + (null != line ? Eol : ""));
|
||||
builder.Append(TestEngineerEmailLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestEngineerEmail)) + (null != line ? Eol : ""));
|
||||
builder.Append(TitleLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Title)) + (null != line ? Eol : ""));
|
||||
builder.Append(NumberOfMediaLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => NumberOfMedia)) + (null != line ? Eol : ""));
|
||||
builder.Append(TimestampLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Timestamp)) + (null != line ? Eol : ""));
|
||||
builder.Append(CommentsLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestComment)) + (null != line ? Eol : ""));
|
||||
builder.Append(TypeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Type)) + (null != line ? Eol : ""));
|
||||
builder.Append(ReferenceTemperatureLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => ReferenceTemperature.ToString())) + (null != line ? Eol : ""));
|
||||
builder.Append(RelativeAirHumidityLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => RelativeAirHumidity.ToString())) + (null != line ? Eol : ""));
|
||||
builder.Append(DateLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Date.ToString("yyyy-MM-dd"))) + (null != line ? Eol : ""));
|
||||
builder.Append(RegulationLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Regulation)) + (null != line ? Eol : ""));
|
||||
builder.Append(SubtypeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Subtype)) + (null != line ? Eol : ""));
|
||||
foreach (var exp in ExtraProperties)
|
||||
{
|
||||
builder.Append(exp.Key.PadRight(SeparatorOffset) + Separator + (line = exp.Value) + (null != line ? Eol : ""));
|
||||
}
|
||||
builder.Append(NumberOfTestObjectsLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => NumberOfTestObjects.ToString())) + (null != line ? Eol : ""));
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem generating string representation for " + GetType().FullName, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user