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,66 @@
using IRIGCh10;
using System.ComponentModel;
namespace DTS.Serialization.IRIGCH10.TMATS.DataConversion
{
public enum CoefficientsAttributes
{
[Description("CO\\N")]
OrderOfCurveFit,
[Description("CO1")]
DerivedFromPairSet,
[Description("CO")]
Coefficient0,
[Description("CO-1")]
Coefficient1,
[Description("CO-2")]
Coefficient2,
[Description("CO-3")]
Coefficient3,
[Description("CO-4")]
Coefficient4,
[Description("CO-5")]
Coefficient5,
[Description("CO-6")]
Coefficient6,
[Description("CO-7")]
Coefficient7
}
/// <summary>
/// implements the coefficient section of the tmats document
/// </summary>
public class CoefficientSection : TMATSSection<CoefficientsAttributes>
{
public CoefficientSection(int number)
: base(AttributeIdentifiers.DataConversionAttributes, number)
{
}
/// <summary>
/// SPECIFY THE ORDER OF THE POLYNOMINAL CURVE FIT, n.
/// </summary>
public int? OrderOfCurveFit
{
get => GetIntOrNull(CoefficientsAttributes.OrderOfCurveFit);
set => SetIntOrNull(CoefficientsAttributes.OrderOfCurveFit, value);
}
/// <summary>
/// VALUE OF THE ZERO ORDER TERM (OFFSET), SCIENTIFIC NOTATION MAY BE USED.
/// </summary>
public string Coefficient0
{
get => GetValue(CoefficientsAttributes.Coefficient0);
set => SetValueWithLength(CoefficientsAttributes.Coefficient0, value);
}
/// <summary>
/// VALUE OF THE COEFFICIENT OF THE N-TH POWER OF X (FIRST ORDER COEFFICIENT IS
/// THE EQUIVALENT OF BIT WEIGHT).
/// SCIENTIFIC NOTATION MAY BE USED.
/// </summary>
public string Coefficient1
{
get => GetValue(CoefficientsAttributes.Coefficient1);
set => SetValueWithLength(CoefficientsAttributes.Coefficient1, value);
}
}
}

View File

@@ -0,0 +1,53 @@
using IRIGCh10;
using System.ComponentModel;
namespace DTS.Serialization.IRIGCH10.Attributes
{
public enum DataConversionAttributes
{
[Description("DCT")]
ConversionType
}
public enum ConversionTypes
{
[Description("NON")]
None,
[Description("PRS")]
PairSets,
[Description("COE")]
Coefficients,
[Description("NPC")]
CoefficientsNegative,
[Description("DER")]
Derived,
[Description("DIS")]
Discrete,
[Description("PTM")]
PCMTime,
[Description("BTM")]
Time1553,
[Description("VOI")]
DigitalVoice,
[Description("VID")]
DigitalVideo,
[Description("SP")]
SpecializedProcessing,
[Description("OTH")]
Other
}
/// <summary>
/// implements the data conversion section of the tmats packet
/// </summary>
public class DataConversionSection : TMATSSection<DataConversionAttributes>
{
public DataConversionSection(int number) : base(AttributeIdentifiers.DataConversionAttributes, number)
{
}
public void SetConversionType(ConversionTypes type)
{
SetValueWithLength(DataConversionAttributes.ConversionType,
DescriptionDecoder.GetDescription(type));
}
}
}

View File

@@ -0,0 +1,87 @@
using IRIGCh10;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace DTS.Serialization.IRIGCH10.TMATS.DataConversion
{
public enum MeasurandAttributes
{
[Description("MN1")]
[MaxLength(64)]
Description,
[Description("MNA")]
[MaxLength(32)]
MeasurementAlias,
[Description("MN2")]
[MaxLength(10)]
ExcitationVoltage,
[Description("MN3")]
[MaxLength(16)]
EngineeringUnits,
[Description("MN4")]
[MaxLength(3)]
LinkType
}
public enum SourceDataTypeLinks
{
[Description("ANA")]
FM,
[Description("PCM")]
PCM,
[Description("PAM")]
PAM,
[Description("OTH")]
Other
}
/// <summary>
/// implements the measurand section of the tmats document
/// </summary>
public class MeasurandSection : TMATSSection<MeasurandAttributes>
{
public MeasurandSection(int number) : base(AttributeIdentifiers.DataConversionAttributes, number)
{
}
/// <summary>
/// DESCRIBE THE PARAMETER BEING MEASURED.
/// </summary>
public string Description
{
get => GetValue(MeasurandAttributes.Description);
set => SetValueWithLength(MeasurandAttributes.Description, value);
}
/// <summary>
/// ALTERNATE MEASURAND NAME
/// </summary>
public string MeasurementAlias
{
get => GetValue(MeasurandAttributes.MeasurementAlias);
set => SetValueWithLength( MeasurandAttributes.MeasurementAlias, value);
}
/// <summary>
/// SENSOR REFERENCE VOLTAGE, IN VOLTS
/// </summary>
public string ExcitationVoltage
{
get => GetValue(MeasurandAttributes.ExcitationVoltage);
set => SetValueWithLength(MeasurandAttributes.ExcitationVoltage, value);
}
/// <summary>
/// DEFINE THE ENGINEERING UNITS APPLICABLE TO THE OUTPUT DATA.
/// </summary>
public string EngineeringUnits
{
get => GetValue(MeasurandAttributes.EngineeringUnits);
set => SetValueWithLength(MeasurandAttributes.EngineeringUnits, value);
}
/// <summary>
/// DEFINE THE SOURCE DATA LINK TYPE:
/// </summary>
/// <param name="linkType"></param>
public void SetLinkType(SourceDataTypeLinks linkType)
{
SetValueWithLength(MeasurandAttributes.LinkType, DescriptionDecoder.GetDescription(linkType));
}
}
}

View File

@@ -0,0 +1,103 @@
using IRIGCh10;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace DTS.Serialization.IRIGCH10.Attributes
{
public enum OtherInformationAttributes
{
[MaxLength(32)]
[Description("MOT1")]
HighMeasurementValue,
[MaxLength(32)]
[Description("MOT2")]
LowMeasurementValue,
[MaxLength(32)]
[Description("MOT3")]
HighAlertLimitValue,
[MaxLength(32)]
[Description("MOT4")]
LowAlertLimitValue,
[MaxLength(32)]
[Description("MOT5")]
HighWarningLimitValue,
[MaxLength(32)]
[Description("MOT6")]
LowWarningLimitValue,
[Description("SR")]
[MaxLength(6)]
SampleRate
}
/// <summary>
/// implements the other information section of the TMAT packet, see chapter 9
/// </summary>
public class OtherInformationSection : TMATSSection<OtherInformationAttributes>
{
public OtherInformationSection(int number)
: base(AttributeIdentifiers.DataConversionAttributes, number)
{
}
/// <summary>
/// HIGHEST ENGINEERING UNIT VALUE DEFINED BY THE CALIBRATION DATA,
/// SCIENTIFIC NOTATION MAY BE USED.
/// </summary>
public string HighMeasurementValue
{
get => GetValue(OtherInformationAttributes.HighMeasurementValue);
set => SetValueWithLength(OtherInformationAttributes.HighMeasurementValue, value);
}
/// <summary>
/// LOWEST ENGINEERING UNIT VALUE DEFINED IN THE CALIBRATION DATA,
/// SCIENTIFIC NOTATION MAY BE USED.
/// </summary>
public string LowMeasurementValue
{
get => GetValue(OtherInformationAttributes.LowMeasurementValue);
set => SetValueWithLength(OtherInformationAttributes.LowMeasurementValue, value);
}
/// <summary>
/// HIGHEST ENGINEERING UNIT VALUE EXPECTED OR SAFE OPERATING VALUE OF
/// THE PARAMETER (“RED”), SCIENTIFIC NOTATION MAY BE USED.
/// </summary>
public string HighAlertLimitValue
{
get => GetValue(OtherInformationAttributes.HighAlertLimitValue);
set => SetValueWithLength(OtherInformationAttributes.HighAlertLimitValue, value);
}
/// <summary>
/// LOWEST ENGINEERING UNIT VALUE EXPECTED OR SAFE OPERATING VALUE OF
/// THE PARAMETER (“RED”), SCIENTIFIC NOTATION MAY BE USED.
/// </summary>
public string LowAlertLimitValue
{
get => GetValue(OtherInformationAttributes.LowAlertLimitValue);
set => SetValueWithLength(OtherInformationAttributes.LowAlertLimitValue, value);
}
/// <summary>
/// HIGHEST ENGINEERING UNIT VALUE EXPECTED OR SAFE OPERATING VALUE OF
/// THE PARAMETER (“YELLOW”), SCIENTIFIC NOTATION MAY BE USED.
/// </summary>
public string HighWarningLimitValue
{
get => GetValue(OtherInformationAttributes.HighWarningLimitValue);
set => SetValueWithLength(OtherInformationAttributes.HighWarningLimitValue, value);
}
/// <summary>
/// LOWEST ENGINEERING UNIT VALUE EXPECTED OR SAFE OPERATING VALUE OF
/// THE PARAMETER (“YELLOW”), SCIENTIFIC NOTATION MAY BE USED.
/// </summary>
public string LowWarningLimitValue
{
get => GetValue(OtherInformationAttributes.LowWarningLimitValue);
set => SetValueWithLength(OtherInformationAttributes.LowWarningLimitValue, value);
}
/// <summary>
/// ENTER THE SAMPLE RATE IN TERMS OF SAMPLES/SECOND.
/// </summary>
public string SampleRate
{
get => GetValue(OtherInformationAttributes.SampleRate);
set => SetValueWithLength(OtherInformationAttributes.SampleRate, value);
}
}
}

View File

@@ -0,0 +1,55 @@
using IRIGCh10;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace DTS.Serialization.IRIGCH10.TMATS.DataConversion
{
public enum TelemetryAttributes
{
[Description("BFM")]
[MaxLength(3)]
BinaryFormat
}
public enum BinaryFormats
{
[Description("INT")]
Integer,
[Description("UNS")]
UnsignedBinary,
[Description("SIG")]
SignAndMagnitudeSig,
[Description("SIM")]
SignAndMagnitudeSim,
[Description("ONE")]
OnesCompliment,
[Description("TWO")]
TwosCompliment,
[Description("OFF")]
OffsetBinary,
[Description("FPT")]
FloatingPoint,
[Description("BCD")]
BinaryCodedDecimal,
[Description("BWT")]
BitWeight,
[Description("OTH")]
Other
}
/// <summary>
/// implements part of the telemetry section of the TMATS packet (see chapter 9)
/// </summary>
public class TelemetrySection : TMATSSection<TelemetryAttributes>
{
public TelemetrySection(int number) : base(AttributeIdentifiers.DataConversionAttributes, number)
{
}
public void SetBinaryFormat(BinaryFormats format)
{
SetValueWithLength(TelemetryAttributes.BinaryFormat,
DescriptionDecoder.GetDescription(format));
}
}
}

View File

@@ -0,0 +1,193 @@
using IRIGCh10;
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace DTS.Serialization.IRIGCH10.TMATS.DataConversion
{
public enum TransducerInformation
{
[Description("DCN")] [MaxLength(32)] MeasurementName,
[Description("TRD1")] [MaxLength(32)] Type,
[Description("TRD2")] [MaxLength(32)] ModelNumber,
[Description("TRD3")] [MaxLength(32)] SerialNumber,
[Description("TRD4")] [MaxLength(2)] SecurityClassification,
[Description("TRD5")] [MaxLength(10)] OriginationDate,
[Description("TRD6")] [MaxLength(4)] RevisionNumber,
[MaxLength(32)] [Description("TRD7")] Orientation,
[MaxLength(24)] [Description("POC1")] PointOfContactName,
[MaxLength(48)] [Description("POC2")] PointOfContactAgency,
[MaxLength(48)] [Description("POC3")] PointOfContectAddress,
[MaxLength(20)] [Description("POC4")] PointOfContactTelephone,
}
public enum ClassificationTypes
{
[Description("U")] Unclassified,
[Description("C")] Confidential,
[Description("S")] Secret,
[Description("T")] TopSecret,
[Description("O")] Other
}
/// <summary>
/// this class handles the transducer information section of the TMAT packet (see chapter 9.pdf)
/// </summary>
public class TransducerInformationSection : TMATSSection<TransducerInformation>
{
public TransducerInformationSection(int number) : base(AttributeIdentifiers.DataConversionAttributes, number)
{
}
/// <summary>
/// GIVE THE MEASUREMENT NAME.
/// </summary>
public string MeasurementName
{
get => GetValue(TransducerInformation.MeasurementName);
set => SetValueWithLength(TransducerInformation.MeasurementName, value);
}
/// <summary>
/// TYPE OF SENSOR, IF APPROPRIATE
/// </summary>
public string Type
{
get => GetValue(TransducerInformation.Type);
set => SetValueWithLength(TransducerInformation.Type, value);
}
/// <summary>
/// IF APPROPRIATE
/// </summary>
public string ModelNumber
{
get => GetValue(TransducerInformation.ModelNumber);
set => SetValueWithLength(TransducerInformation.ModelNumber, value);
}
/// <summary>
/// IF APPLICABLE
/// </summary>
public string SerialNumber
{
get => GetValue(TransducerInformation.SerialNumber);
set => SetValueWithLength(TransducerInformation.SerialNumber, value);
}
/// <summary>
/// ENTER THE SECURITY CLASSIFICATION OF THIS MEASURAND.
/// </summary>
/// <param name="type"></param>
/// <param name="signalClassified"></param>
/// <param name="measurandClassified"></param>
public void SetSecurityClassification(ClassificationTypes type,
bool signalClassified, bool measurandClassified)
{
var val = DescriptionDecoder.GetDescription(type);
if (signalClassified && measurandClassified)
{
val = $"{val}B";
}
else if (signalClassified)
{
val = $"{val}R";
}
else if (measurandClassified)
{
val = $"{val}E";
}
SetValueWithLength(TransducerInformation.SecurityClassification, val);
}
/// <summary>
/// DATE OF ORIGINATION OF THIS DATA FILE. DD DAY MM MONTH
/// YYYY YEAR (MM-DD-YYYY)
/// </summary>
public DateTime? OriginationDate
{
get
{
var val = GetValue(TransducerInformation.OriginationDate);
if (string.IsNullOrWhiteSpace(val))
{
return null;
}
if (DateTime.TryParse(val, out var dt))
{
return dt;
}
return null;
}
set
{
if (null == value)
{
SetValueWithLength(TransducerInformation.OriginationDate, string.Empty);
}
else
{
var dt = (DateTime) value;
SetValueWithLength(TransducerInformation.OriginationDate,
$"{dt.Month:00}-{dt.Day:00}-{dt.Year:0000}");
}
}
}
/// <summary>
/// SPECIFY THE REVISION NUMBER OF THE DATA PROVIDED.
/// </summary>
public string RevisionNumber
{
get => GetValue(TransducerInformation.RevisionNumber);
set => SetValueWithLength(TransducerInformation.RevisionNumber, value);
}
/// <summary>
/// DESCRIBE THE PHYSICAL ORIENTATION OF THE SENSOR.
/// </summary>
public string Orientation
{
get => GetValue(TransducerInformation.Orientation);
set => SetValueWithLength(TransducerInformation.Orientation, value);
}
/// <summary>
/// POINT OF CONTACT WITH THE ORGANIZATION THAT PROVIDED THE CALIBRATION DATA
/// </summary>
public POC PointOfContact
{
get => new POC()
{
Name = GetValue(TransducerInformation.PointOfContactName),
Agency = GetValue(TransducerInformation.PointOfContactAgency),
Address = GetValue(TransducerInformation.PointOfContectAddress),
Telephone = GetValue(TransducerInformation.PointOfContectAddress)
};
set
{
SetValueWithLength(TransducerInformation.PointOfContactName, value.Name);
SetValueWithLength(TransducerInformation.PointOfContactAgency, value.Agency);
SetValueWithLength(TransducerInformation.PointOfContectAddress, value.Address);
SetValueWithLength(TransducerInformation.PointOfContactTelephone, value.Telephone);
}
}
}
/// <summary>
/// Point Of Contact structure
/// </summary>
public class POC
{
public string Name { get; set; }
public string Agency { get; set; }
public string Address { get; set; }
public string Telephone { get; set; }
public POC(string name, string agency, string address, string telephone)
{
Name = name;
Agency = agency;
Address = address;
Telephone = telephone;
}
public POC()
{
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace IRIGCh10
{
public static class DescriptionDecoder
{
public static string GetDescription(Enum value)
{
var fi = value.GetType().GetField(value.ToString());
var attributes = (DescriptionAttribute[]) fi.GetCustomAttributes(
typeof(DescriptionAttribute), false);
if (attributes.Any())
{
return attributes.First().Description;
}
return value.ToString();
}
}
public static class MaxLengthDecoder
{
public static int GetMaxLength(Enum value)
{
var fi = value.GetType().GetField(value.ToString());
var attributes = (MaxLengthAttribute[]) fi.GetCustomAttributes(
typeof(MaxLengthAttribute), false);
if (attributes.Any())
{
return attributes.First().Length;
}
return 0;
}
}
}

View File

@@ -0,0 +1,395 @@
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
namespace IRIGCh10
{
public enum GeneralTags
{
[Description("PN")]
[MaxLength(16)]
ProgramName,
[Description("TA")]
[MaxLength(64)]
TestItem
}
public class GeneralInformationGroup : TMATSSection<GeneralTags>
{
/// <summary>
/// Name of program
/// </summary>
public string ProgramName
{
get => GetValue(GeneralTags.ProgramName);
set => SetValueWithLength(GeneralTags.ProgramName, value);
}
/// <summary>
/// TEST ITEM DESCRIPTION IN TERMS OF NAME, MODEL, PLATFORM, OR
/// IDENTIFICATION CODE, AS APPROPRIATE
/// </summary>
public string TestItem
{
get => GetValue(GeneralTags.TestItem);
set => SetValueWithLength(GeneralTags.TestItem, value);
}
/// <summary>
/// VERSION OF IRIG 106 STANDARD USED TO GENERATE THIS TMATS FILE
/// </summary>
public string IRIG106RevisionLevel
{
get => _information.GetValue(InformationTags.IRIG106RevisionLevel);
set => _information.SetValueWithLength(InformationTags.IRIG106RevisionLevel, value);
}
/// <summary>
/// DATE OF ORIGINATION OF THIS MISSION CONFIGURATION.
/// </summary>
public DateTime? OriginationDate
{
get => _information.GetDate(InformationTags.OriginationDate);
set => _information.SetDate(InformationTags.OriginationDate, value);
}
/// <summary>
/// REVISION NUMBER ASSOCIATED WITH THIS MISSION CONFIGURATION
/// </summary>
public string RevisionNumber
{
get => _information.GetValue(InformationTags.RevisionNumber);
set => _information.SetValueWithLength(InformationTags.RevisionNumber, value);
}
/// <summary>
/// DATE OF REVISION.
/// </summary>
public DateTime? RevisionDate
{
get => _information.GetDate(InformationTags.RevisionDate);
set => _information.SetDate(InformationTags.RevisionDate, value);
}
/// <summary>
/// UPDATE NUMBER OF CURRENT CHANGE WHICH HAS NOT BEEN INCORPORATED
/// AS A REVISION
/// </summary>
public string UpdateNumber
{
get => _information.GetValue(InformationTags.UpdateNumber);
set => _information.SetValueWithLength(InformationTags.UpdateNumber, value);
}
/// <summary>
/// DATE OF UPDATE.
/// </summary>
public DateTime? UpdateDate
{
get => _information.GetDate(InformationTags.UpdateDate);
set => _information.SetDate(InformationTags.UpdateDate, value);
}
/// <summary>
/// TEST IDENTIFICATION
/// </summary>
public string TestNumber
{
get => _information.GetValue(InformationTags.TestNumber);
set => _information.SetValue(InformationTags.TestNumber, value);
}
public int NumberOfPointsOfContact
{
get => _information.GetContactCount();
set => _information.SetContactCount(value);
}
/// <summary>
/// SPECIFY THE NUMBER OF DATA SOURCES: FOR RF TELEMETRY
/// SYSTEMS, GIVE THE NUMBER OF CARRIERS; FOR TAPE OR STORAGE
/// RECORDED DATA, IDENTIFY THE NUMBER OF TAPE OR STORAGE
/// SOURCES.
/// </summary>
public int NumberOfDataSources
{
get => _information.GetDataSourceCount();
set => _information.SetDataSourceCount(value);
}
/// <summary>
/// APPROXIMATE DURATION OF TEST IN HOURS.
/// </summary>
public string TestDuration
{
get => _information.GetValue(Information.TestInformationTags.TestDuration);
set => _information.SetValue(Information.TestInformationTags.TestDuration, value);
}
/// <summary>
/// INDICATE WHETHER A PRE-TEST REQUIREMENT IS APPLICABLE (Y OR
/// N). PROVIDE DETAILS IN COMMENTS RECORD.
/// </summary>
public bool PreTestRequirement
{
get
{
var val = _information.GetValue(Information.TestInformationTags.PreTestRequirement);
if (string.IsNullOrWhiteSpace(val)) { return false; }
if (val == "Y") { return true; }
return false;
}
set => _information.SetValue(Information.TestInformationTags.PreTestRequirement, value ? "Y" : "N");
}
/// <summary>
/// INDICATE WHETHER A PRE-TEST REQUIREMENT IS APPLICABLE (Y OR
/// N). PROVIDE DETAILS IN COMMENTS RECORD.
/// </summary>
public bool PostTestRequirement
{
get
{
var val = _information.GetValue(Information.TestInformationTags.PostTestRequirement);
if (string.IsNullOrWhiteSpace(val)) { return false; }
if (val == "Y") { return true; }
return false;
}
set => _information.SetValue(Information.TestInformationTags.PostTestRequirement, value ? "Y" : "N");
}
public void SetDataSourceField(int number, Information.DataSourceIdentificationTags tag,
string value)
{
_information.SetDataSourceField(number, tag, value);
}
public void SetDataSourceType(int number, Information.DataSourceTypes sourceType)
{
_information.SetDataSourceType(number, sourceType);
}
public SecurityClassifications SecurityClassification
{
get
{
var val = _securitySection.GetValue(SecurityTags.SecurityClassification);
if (string.IsNullOrWhiteSpace(val))
{
return SecurityClassifications.Unclassified;
}
var classes = Enum.GetValues(typeof(SecurityClassifications))
.Cast<SecurityClassifications>().ToArray();
foreach (var item in classes)
{
if (DescriptionDecoder.GetDescription(item) == val)
{
return item;
}
}
return SecurityClassifications.Unclassified;
}
}
/// <summary>
/// PROVIDE THE ADDITIONAL INFORMATION REQUESTED OR ANY OTHER INFORMATION DESIRED.
/// </summary>
public string Comments
{
get => _comments.GetValue(CommentTags.Comments);
set => _comments.SetValueWithLength(CommentTags.Comments, value);
}
#region infrastructure
public override string Serialize()
{
var sb = new StringBuilder();
sb.Append(_information.Serialize());
sb.Append(base.Serialize());
return sb.ToString();
}
private CommentSection _comments = new CommentSection();
public class CommentSection : TMATSSection<CommentTags>
{
}
public enum CommentTags
{
[Description("COM")]
[MaxLength(1600)]
Comments
}
public enum SecurityClassifications
{
[Description("U")]
Unclassified,
[Description("C")]
Confidential,
[Description("S")]
Secret,
[Description("T")]
TopSecret,
[Description("O")]
Other
}
public enum SecurityTags
{
[Description("SC")]
[MaxLength(1)]
SecurityClassification
}
public class SecuritySection : TMATSSection<SecurityTags>
{
}
private SecuritySection _securitySection = new SecuritySection();
private Information _information = new Information();
public enum InformationTags
{
[Description("106")]
[MaxLength(2)]
IRIG106RevisionLevel,
[Description("OD")]
[MaxLength(10)]
OriginationDate,
[Description("RN")]
[MaxLength(4)]
RevisionNumber,
[Description("RD")]
[MaxLength(10)]
RevisionDate,
[Description("UN")]
[MaxLength(2)]
UpdateNumber,
[Description("UD")]
[MaxLength(10)]
UpdateDate,
[MaxLength(16)]
[Description("TN")]
TestNumber
}
public class Information : TMATSSection<InformationTags>
{
#region Contacts
public int GetContactCount()
{
return _contacts.GetCount();
}
public void SetContactCount(int count)
{
_contacts.SetCount(count);
}
public void SetContactField(int number, PointOfContactTags tag, string value) => _contacts.SetValue(number, tag, value);
public string GetContactField(int number, PointOfContactTags tag) => _contacts.GetValue(number, tag);
public enum PointOfContactTags
{
[Description("POC1-")]
[MaxLength(24)]
Name,
[Description("POC2-")]
[MaxLength(48)]
Agency,
[Description("POC3-")]
[MaxLength(48)]
Address,
[Description("POC4-")]
[MaxLength(20)]
Telephone
}
private TMATSectionNumberedArray<PointOfContactTags> _contacts =
new TMATSectionNumberedArray<PointOfContactTags>("POC\\N", 9);
#endregion Contacts
#region DataSourceIdentification
public int GetDataSourceCount() => _datasources.GetCount();
public void SetDataSourceCount(int value) => _datasources.SetCount(value);
public void SetDataSourceField(int number, DataSourceIdentificationTags tag,
string value)
{
if (tag == DataSourceIdentificationTags.DataSourceID)
{
//must be unique
for (var i = 1; i < _datasources.GetCount(); i++)
{
if( i == number ){ continue; }
if (_datasources.GetValue(number, tag) == value)
{
throw new Exception($"Datasource ID must be unique");
}
}
}
_datasources.SetValue(number, tag, value);
}
public void SetDataSourceType(int number, DataSourceTypes type)
{
SetDataSourceField(number, DataSourceIdentificationTags.DataSourceType,
DescriptionDecoder.GetDescription(type));
}
public string GetDataSourceField(int number, DataSourceIdentificationTags tag) =>
_datasources.GetValue(number, tag);
public enum DataSourceIdentificationTags
{
[MaxLength(32)]
[Description("DSI-")]
DataSourceID,
[MaxLength(3)]
[Description("DST-")]
DataSourceType
}
public enum DataSourceTypes
{
[Description("RF")]
RF,
[Description("STO")]
Storage,
[Description("TAP")]
Tape,
[Description("OTH")]
Other
}
private TMATSectionNumberedArray<DataSourceIdentificationTags> _datasources =
new TMATSectionNumberedArray<DataSourceIdentificationTags>("DSI\\N");
#endregion
public enum TestInformationTags
{
[Description("TI1")]
[MaxLength(4)]
TestDuration,
[Description("TI2")]
[MaxLength(1)]
PreTestRequirement,
[Description("TI3")]
[MaxLength(1)]
PostTestRequirement
}
public class TestInformation : TMATSSection<TestInformationTags>
{
}
private TestInformation _testInformation = new TestInformation();
public void SetValue(TestInformationTags tag, string value) => _testInformation.SetValueWithLength(tag, value);
public string GetValue(TestInformationTags tag) => _testInformation.GetValue(tag);
public override string Serialize()
{
var sb = new StringBuilder();
sb.Append(base.Serialize());
sb.Append(_contacts.Serialize());
sb.Append(_datasources.Serialize());
sb.Append(_testInformation.Serialize());
return sb.ToString();
}
}
#endregion
}
}

View File

@@ -0,0 +1,531 @@
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
namespace IRIGCh10
{
public enum PCMCodes
{
[Description("NRZ-L")]
NRZL,
[Description("NRZ-M")]
NRZM,
[Description("NRZ-S")]
NRZS,
[Description("BIO-L")]
BIOL,
[Description("BIO-M")]
BIOM,
[Description("BIO-S")]
BIOS,
[Description("RNRZ-L")]
RNRZL,
[Description("OTHER")]
Other
}
public enum Polarities
{
[Description("N")]
Normal,
[Description("I")]
Inverted
}
public enum PCMDataDirections
{
[Description("N")]
Normal,
[Description("R")]
Reversed
}
public enum PCMAttributes
{
[Description("DLN")]
[MaxLength(32)]
DataLinkName,
[MaxLength(6)]
[Description("D1")]
PCMCode,
[Description("D2")]
[MaxLength(9)]
Bitrate,
[Description("D3")]
Encrypted,
[Description("D4")]
[MaxLength(1)]
Polarity,
[Description("D5")]
AutoPolarityCorrection,
[Description("D6")]
DataDirection,
[Description("D7")]
DataRandomized,
[MaxLength(1)]
[Description("D8")]
RandomizerLength
}
public class PCM : TMATSSection<PCMAttributes>
{
/// <summary>
/// IDENTIFY THE DATA LINK NAME CONSISTENT WITH THE MUX/MOD
/// GROUP.
/// </summary>
public string DataLinkName
{
get => GetValue(PCMAttributes.DataLinkName);
set => SetValueWithLength(PCMAttributes.DataLinkName, value);
}
/// <summary>
/// DEFINE THE DATA FORMAT CODE:
/// </summary>
public PCMCodes? PCMCode
{
get
{
var val = GetValue(PCMAttributes.PCMCode);
if (string.IsNullOrWhiteSpace(val))
{
return null;
}
var codes = Enum.GetValues(typeof(PCMCodes))
.Cast<PCMCodes>().ToArray();
foreach (var code in codes)
{
if (DescriptionDecoder.GetDescription(code) == val)
{
return code;
}
}
return null;
}
set
{
if (null == value)
{
SetValueWithLength(PCMAttributes.PCMCode, string.Empty);
}
else
{
SetValueWithLength(PCMAttributes.PCMCode,
DescriptionDecoder.GetDescription(value));
}
}
}
/// <summary>
/// DATA RATE IN BITS PER SECOND. SCIENTIFIC NOTATION MAY BE
/// USED.
/// </summary>
public string BitsPerSecond
{
get => GetValue(PCMAttributes.Bitrate);
set => SetValueWithLength(PCMAttributes.Bitrate, value);
}
/// <summary>
/// DATA RANDOMIZED
/// </summary>
public bool DataRandomized
{
get
{
var val = GetValue(PCMAttributes.DataRandomized);
if( string.IsNullOrWhiteSpace(val) ){ return false; }
if( val == "N" ){ return false; }
return true;
}
set { SetValueWithLength(PCMAttributes.DataRandomized, value ? "Y" : "N"); }
}
/// <summary>
/// DATA POLARITY:
/// </summary>
public Polarities Polarity
{
get
{
var val = GetValue(PCMAttributes.Polarity);
if (string.IsNullOrWhiteSpace(val))
{
return Polarities.Normal;
}
return val == "I" ? Polarities.Inverted : Polarities.Normal;
}
set
{
SetValueWithLength(PCMAttributes.Polarity,
DescriptionDecoder.GetDescription(value));
}
}
/// <summary>
/// TIME SEQUENCE OF DATA:
/// </summary>
public PCMDataDirections DataDirection
{
get
{
var val = GetValue(PCMAttributes.DataDirection);
if (string.IsNullOrWhiteSpace(val))
{
return PCMDataDirections.Normal;
}
return val == "R" ? PCMDataDirections.Reversed : PCMDataDirections.Normal;
}
set
{
SetValueWithLength(PCMAttributes.DataDirection,
DescriptionDecoder.GetDescription(value));
}
}
/// <summary>
/// TYPE OF PCM FORMAT: CLASS I - ONE CLASS II TWO
/// 1553 BUS - 1553 BUS BUS ALTERNATE TAG AND DATA-ALTD
/// PACKET TELEMETRY PKTM OTHER - OTHR, DESCRIBE IN
/// COMMENTS RECORD.
/// </summary>
public PCMTypeFormats TypeFormat
{
get
{
var val = _typeFormat.GetValue(TypeFormatTags.TypeFormat);
if (string.IsNullOrWhiteSpace(val))
{
return PCMTypeFormats.Other;
}
var formats = Enum.GetValues(typeof(PCMTypeFormats))
.Cast<PCMTypeFormats>().ToArray();
foreach (var format in formats)
{
if (DescriptionDecoder.GetDescription(format) == val)
{
return format;
}
}
return PCMTypeFormats.Other;
}
set
{
_typeFormat.SetValueWithLength(TypeFormatTags.TypeFormat,
DescriptionDecoder.GetDescription(value));
}
}
/// <summary>
/// NUMBER OF BITS IN COMMON WORD LENGTH
/// </summary>
public ushort NumberOfBitsInCommonWordLength
{
get
{
var val = _typeFormat.GetValue(TypeFormatTags.CommonWordLength);
if (string.IsNullOrWhiteSpace(val))
{
return 0;
}
if (ushort.TryParse(val, out var uTmp))
{
return uTmp;
}
return 0;
}
set
{
_typeFormat.SetValueWithLength(TypeFormatTags.CommonWordLength,
value.ToString());
}
}
/// <summary>
/// DEFINE THE DEFAULT FOR THE FIRST BIT TRANSFERRED IN
/// NORMAL TIME SEQUENCE:
/// </summary>
public PCMWordTransferOrders WordTransferOrder
{
get
{
var val = _typeFormat.GetValue(TypeFormatTags.WordTransferOrder);
if (string.IsNullOrWhiteSpace(val))
{
return PCMWordTransferOrders.MostSignificantBit;
}
var orders = Enum.GetValues(typeof(PCMWordTransferOrders))
.Cast<PCMWordTransferOrders>().ToArray();
foreach (var order in orders)
{
if (DescriptionDecoder.GetDescription(order) == val)
{
return order;
}
}
return PCMWordTransferOrders.MostSignificantBit;
}
set => _typeFormat.SetValueWithLength(TypeFormatTags.WordTransferOrder,
DescriptionDecoder.GetDescription(value));
}
public PCMWordParities PCMWordParity
{
get
{
var value = _typeFormat.GetValue(TypeFormatTags.Parity);
if (string.IsNullOrWhiteSpace(value))
{
return PCMWordParities.None;
}
var parities = Enum.GetValues(typeof(PCMWordParities)).Cast<PCMWordParities>().ToArray();
foreach (var parity in parities)
{
if( DescriptionDecoder.GetDescription(parity) == value){ return parity; }
}
return PCMWordParities.None;
}
set => _typeFormat.SetValueWithLength(TypeFormatTags.Parity,
DescriptionDecoder.GetDescription(value));
}
private PCMTypeFormat _typeFormat;
public override string Serialize()
{
var sb = new StringBuilder();
sb.Append(_typeFormat.Serialize());
sb.Append(base.Serialize());
return sb.ToString();
}
public PCM(int number) : base(AttributeIdentifiers.PCMFormatAttributes, number)
{
_typeFormat = new PCMTypeFormat(number);
}
}
public enum PCMWordTransferOrders
{
[Description("M")]
MostSignificantBit,
[Description("L")]
LeastSignificantBit
}
public enum PCMWordParities
{
[Description("EV")]
Even,
[Description("OD")]
Odd,
[Description("NO")]
None
}
public enum TypeFormatTags
{
[Description("TF")]
[MaxLength(4)]
TypeFormat,
[Description("F1")]
[MaxLength(2)]
CommonWordLength,
[Description("F2")]
[MaxLength(1)]
WordTransferOrder,
[Description("F3")]
Parity,
[Description("F4")]
ParityTransferOrder
}
public enum PCMTypeFormats
{
[Description("ONE")]
ClassI,
[Description("TWO")]
ClassII,
[Description("1553")]
Bus1553,
[Description("BUS")]
Bus,
[Description("ALTD")]
AlternateTagAndData,
[Description("PKTM")]
PacketTelemetry,
[Description("OTHR")]
Other
}
public class PCMTypeFormat : TMATSSection<TypeFormatTags>
{
public PCMTypeFormat(int number) : base(AttributeIdentifiers.PCMFormatAttributes,
number)
{
}
}
public enum MinorFrameTags
{
[Description("MF\\N")]
[MaxLength(3)]
NumberOfMinorFramesInMajorFrame,
[Description("MF1")]
[MaxLength(4)]
NumberOfWordsInMinorFrame,
[Description("MF2")]
[MaxLength(5)]
NumberOfBitsInMinorFrame,
[Description("MF3")]
[MaxLength(3)]
SyncType,
[MaxLength(2)]
[Description("MF4")]
SyncLength,
[MaxLength(33)]
[Description("MF5")]
SyncPattern
}
public class MinorFrameSection : TMATSSection<MinorFrameTags>
{
public ushort NumberOfMinorFramesInAMajorFrame
{
get
{
var value = GetValue(MinorFrameTags.NumberOfMinorFramesInMajorFrame);
if (string.IsNullOrWhiteSpace(value))
{
return 0;
}
if (ushort.TryParse(value, out var s))
{
return s;
}
return 0;
}
set => SetValueWithLength(MinorFrameTags.NumberOfMinorFramesInMajorFrame, value.ToString());
}
/// <summary>
/// SPECIFIES THE NUMBER OF WORDS IN A MINOR FRAME, AS DEFINED IN
/// CHAPTER 4, PARAGRAPH 4.3. (THE MINOR FRAME SYNCHRONIZATION
/// PATTERN IS ALWAYS CONSIDERED AS ONE WORD, REGARDLESS OF ITS
/// LENGTH.)
/// </summary>
public int NumberOfWordsInMinorFrame
{
get
{
var val = GetValue(MinorFrameTags.NumberOfWordsInMinorFrame);
if (string.IsNullOrWhiteSpace(val))
{
return 0;
}
if( int.TryParse( val, out var iTmp)){ return iTmp; }
return 0;
}
set => SetValueWithLength(MinorFrameTags.NumberOfWordsInMinorFrame, value.ToString());
}
/// <summary>
/// NUMBER OF BITS IN A MINOR FRAME INCLUDING MINOR FRAME
/// SYNCHRONIZATION PATTERN
/// </summary>
public int NumberOfBitsInMinorFrame
{
get
{
var val = GetValue(MinorFrameTags.NumberOfBitsInMinorFrame);
if (string.IsNullOrEmpty(val))
{
return 0;
}
if( int.TryParse( val, out var iTmp)){ return iTmp; }
return 0;
}
set => SetValueWithLength(MinorFrameTags.NumberOfBitsInMinorFrame,
value.ToString());
}
/// <summary>
/// SPECIFY THE MINOR FRAME SYNCHRONIZATION PATTERN LENGTH
/// IN NUMBER OF BITS.
/// </summary>
public ushort SyncLength
{
get
{
var val = GetValue(MinorFrameTags.SyncLength);
if (string.IsNullOrWhiteSpace(val))
{
return 0;
}
if( ushort.TryParse( val, out var s)){ return s; }
return 0;
}
set => SetValueWithLength(MinorFrameTags.SyncLength, value.ToString());
}
/// <summary>
/// DEFINE MINOR FRAME SYNCHRONIZATION PATTERN IN BITS
/// (“1”s and “0”s) WITH THE LEFT MOST BIT
/// AS THE “FIRST BIT TRANSMITTED”
/// </summary>
public string SynchronizationPattern
{
get => GetValue(MinorFrameTags.SyncPattern);
set => SetValueWithLength(MinorFrameTags.SyncPattern, value);
}
public MinorFrameSection(int number=1) : base(AttributeIdentifiers.PCMFormatAttributes, number)
{
}
}
public enum SynchronizationCriteriaTags
{
[Description("SYNC1")]
InSyncCriteria,
[Description("SYNC2")]
InSyncSyncPatternCriteria,
[Description("SYNC3")]
NumberOfDisagrees,
[Description("SYNC4")]
OutOfSyncSyncPatternCriteria
}
public enum MinorFrameFormatTags
{
[Description("MFW1-")]
WordNumber,
[Description("MFW2-")]
NumberOfBitsInWord
}
public enum SubFrameSynchronizationTags
{
SubframeIDCounterName,
SubframeSyncType,
SubFrameIDCounterLocation,
IDCounterWordLength,
IDCounterMSBStartingBitLocation,
IDCounterLength,
IDCounterTransferOrder,
IDCounterInitialValue,
InitialCountSubframeNumber,
IDCounterEndValue,
EndCountSubframeNumber,
CountDirection
}
public enum SubFrameDefinitionTags
{
SubFrameName,
SuperCom,
LocationDefinition,
SubframeLocation,
Interval,
SubframeDepth
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,152 @@
using System.ComponentModel;
namespace IRIGCh10
{
public enum AttributeIdentifiers
{
[Description("G")] GeneralInformation,
[Description("T")] TransmitionAttributes,
[Description("R")] StorageSourceAttributes,
[Description("M")] MultiplexingAttributes,
[Description("P")] PCMFormatAttributes,
[Description("D")] PCMMeasurementDescription,
[Description("B")] BusDataAttributes,
[Description("S")] PacketFormatAttributes,
[Description("A")] PAMAttributes,
[Description("C")] DataConversionAttributes,
[Description("H")] AirborneHardwareAttributes,
[Description("V")] VendorSpecificAttributes
}
public class TMATSCreationTest
{
public static string CreateTMATS()
{
var sb = new System.Text.StringBuilder();
var gi = new GeneralInformationGroup();
gi.ProgramName = "netacquire-3-pcm-sine-waves";
gi.IRIG106RevisionLevel = "07";
gi.NumberOfDataSources = 1;
gi.SetDataSourceField(1, GeneralInformationGroup.Information.DataSourceIdentificationTags.DataSourceID,
"DATASOURCE");
gi.SetDataSourceType(1, GeneralInformationGroup.Information.DataSourceTypes.Storage);
gi.OriginationDate = new System.DateTime(2018, 11, 20);
sb.Append(gi.Serialize());
var storage = new Storage(1);
storage.DataSourceID = "DATASOURCE";
storage.StorageID = "DATASOURCE";
storage.NumberOfChannels = 4;
storage.OriginalStorage = true;
storage.DateTimeCreated = new System.DateTime(2018, 11, 20);
storage.NumberOfSourceBits = 0;
storage.RecordingEventsEnabled = false;
storage.RecordingIndexEnabled = true;
storage.RecordingIndexType = RecordingIndexTypes.Time;
storage.RecordingIndexTimeValue = 10000000;
storage.SetDataSourceID(1, "Time");
storage.SetChannelDataType(1, ChannelDataTypes.IRIGTimeInput);
storage.SetTrackNumber(1, 65535);
storage.SetPhysicalChannelNumber(1, 65535);
storage.SetChannelEnabled(1, true);
storage.SetChannelDataLinkName(1, "Time");
storage.SetTimeChannelDataTypeFormat();
storage.SetTimeFormat(TimeFormats.IRIGB);
storage.SetTimeSource(TimeSources.Internal);
storage.SetDataSourceID(2, "sio/0/in0-10");
storage.SetChannelDataType(2, ChannelDataTypes.PCMInput);
storage.SetTrackNumber(2, 10);
storage.SetPhysicalChannelNumber(2, 10);
storage.SetChannelEnabled(2, true);
storage.SetChannelDataLinkName(2, "sio/0/in0-10");
storage.SetPCMDataTimeFormat(2);
storage.SetPCMDataPackingOption(2, DataPackingOptions.ThroughputMode);
storage.SetPCMInputClockEdge(2, InputClockEdges.ZeroDegrees);
storage.SetPCMInputSignalType(2, InputSignalTypes.SingleEndedWithTTL);
storage.SetPCMVideoTypeFormat(2, VideoFormats.None);
var pcm = new PCM(1);
pcm.DataLinkName = "sio/0/in0-10";
pcm.PCMCode = PCMCodes.NRZL;
pcm.BitsPerSecond = "1000000";
pcm.Polarity = Polarities.Normal;
pcm.DataDirection = PCMDataDirections.Normal;
pcm.TypeFormat = PCMTypeFormats.ClassI;
pcm.NumberOfBitsInCommonWordLength = 16;
pcm.WordTransferOrder = PCMWordTransferOrders.MostSignificantBit;
pcm.PCMWordParity = PCMWordParities.None;
sb.Append(pcm.Serialize());
var minorFrameSection = new MinorFrameSection();
minorFrameSection.NumberOfMinorFramesInAMajorFrame = 1;
minorFrameSection.NumberOfWordsInMinorFrame = 500;
minorFrameSection.NumberOfBitsInMinorFrame = 8000;//500*16
minorFrameSection.SyncLength = 16;
minorFrameSection.SynchronizationPattern = "1110101110010000";
sb.Append(minorFrameSection.Serialize());
var subframeSync = new SubframeSync();
sb.Append(subframeSync.Serialize());
storage.SetDataSourceID(3, "sio/0/in1-20");
storage.SetChannelDataType(3, ChannelDataTypes.PCMInput);
storage.SetTrackNumber(3, 20);
storage.SetPhysicalChannelNumber(3, 20);
storage.SetChannelEnabled(3, true);
storage.SetChannelDataLinkName(3, "sio/0/in1-20");
storage.SetPCMDataTimeFormat(3);
storage.SetPCMDataPackingOption(3, DataPackingOptions.PackedWithFrameSync);
storage.SetPCMInputClockEdge(3, InputClockEdges.ZeroDegrees);
storage.SetPCMInputSignalType(3, InputSignalTypes.SingleEndedWithTTL);
storage.SetPCMVideoTypeFormat(3, VideoFormats.None);
var pcm2 = new PCM(2);
pcm2.DataLinkName = "sio/0/in1-20";
pcm2.PCMCode = PCMCodes.NRZL;
pcm2.BitsPerSecond = "1920000";
pcm2.Polarity = Polarities.Normal;
pcm2.DataRandomized = false;
pcm2.TypeFormat = PCMTypeFormats.ClassI;
pcm2.NumberOfBitsInCommonWordLength = 16;
pcm2.WordTransferOrder = PCMWordTransferOrders.MostSignificantBit;
pcm2.PCMWordParity = PCMWordParities.None;
sb.Append(pcm2.Serialize());
var minorFrameSection2 = new MinorFrameSection(2);
minorFrameSection2.NumberOfMinorFramesInAMajorFrame = 1;
minorFrameSection2.NumberOfWordsInMinorFrame = 300;
minorFrameSection2.NumberOfBitsInMinorFrame = 4800;//300*16
minorFrameSection2.SyncLength = 16;
minorFrameSection2.SynchronizationPattern = "1110101110010000";
sb.Append(minorFrameSection2.Serialize());
var subframeSync2 = new SubframeSync(2);
sb.Append(subframeSync2.Serialize());
storage.SetDataSourceID(4, "sio/0/in2-30");
storage.SetChannelDataType(4, ChannelDataTypes.MessageDataInput);
storage.SetTrackNumber(4, 30);
storage.SetPhysicalChannelNumber(4, 30);
storage.SetChannelEnabled(4, true);
storage.SetChannelDataLinkName(4, "sio/0/in2-30");
sb.Append(storage.Serialize());
MessageDataType mdt = new MessageDataType(1);
mdt.SetMessageTypeFormat(4, "0");
mdt.SetNumberOfMessageSubChannels(4, 1);
mdt.SetMessageSubChannelNumber(4, 1, 1);
mdt.SetMessageSubChannelName(4, 1, "sio/0/in2-30");
sb.Append(mdt.Serialize());
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,171 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace IRIGCh10
{
/// <summary>
/// this is the base class for sections in the TMATS document
/// each section is made of a bunch of attributes and values
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class TMATSSection<T> where T : Enum
{
private Dictionary<T, string> _values = new Dictionary<T, string>();
/// <summary>
/// Sets the given tag to a given value
/// </summary>
/// <param name="tag"></param>
/// <param name="value"></param>
public void SetValue(T tag, string value) => _values[tag] = value;
/// <summary>
/// returns given value for a given tag
/// value will be null if value was never set
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
public string GetValue(T tag) => _values.ContainsKey(tag)?_values[tag]: null;
/// <summary>
/// sets a given tag to a given date, or an empty string if date is null
/// </summary>
/// <param name="tag"></param>
/// <param name="value"></param>
public void SetDate(T tag, DateTime? value)
{
if (null == value)
{
SetValueWithLength(tag, string.Empty);
}
var dt = (DateTime) value;
SetValueWithLength(tag, $"{dt.Month:00}-{dt.Day:00}-{dt.Year:0000}");
}
/// <summary>
/// gets a date for a tag, or null if date isn't set
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
public DateTime? GetDate(T tag)
{
var value = GetValue(tag);
if( string.IsNullOrWhiteSpace(value) ){ return null; }
if (DateTime.TryParseExact(value, "MM-DD-YYYY", System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None,
out var dt))
{
return dt;
}
return null;
}
/// <summary>
/// gets a int value for tag, or null if tag was never set
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
public int? GetIntOrNull(T tag)
{
var val = GetValue(tag);
if( string.IsNullOrWhiteSpace(val)){ return null; }
if (int.TryParse(val, out var iTmp))
{
return iTmp;
}
return null;
}
/// <summary>
/// sets tag value
/// </summary>
/// <param name="tag"></param>
/// <param name="val"></param>
public void SetIntOrNull(T tag, int? val)
{
if (null == val)
{
SetValueWithLength(tag, string.Empty);
}
else
{
SetValueWithLength(tag, ((int) val).ToString());
}
}
/// <summary>
/// originally designed to check the length of values against the max length in spec
/// however no longer checks length as max length is just a suggestion in the spec...
/// </summary>
/// <param name="tag"></param>
/// <param name="value"></param>
public void SetValueWithLength(T tag, string value)
{
var maxLength = MaxLengthDecoder.GetMaxLength(tag);
//apprently maxlength is just a suggestion ...
//if (maxLength < value.Length)
//{
// throw new FormatException($"{tag.ToString()} must be {maxLength} characters or less");
//}
SetValue(tag, value);
}
/// <summary>
/// returns all fields in the section for the tmats document
/// </summary>
/// <returns></returns>
public virtual string Serialize()
{
var tags = Enum.GetValues(typeof(T)).Cast<T>().ToArray();
var sb = new StringBuilder();
foreach (var tag in tags)
{
var s = Serialize(tag);
if( string.IsNullOrWhiteSpace(s)){ continue; }
sb.AppendLine(s);
}
return sb.ToString();
}
/// <summary>
/// some attributes have to be associated with a number, like P-x\N:1 where x is
/// the channel number, this keeps track of the number for all attributes
/// </summary>
private int _number = -1;
private AttributeIdentifiers _attribute = AttributeIdentifiers.GeneralInformation;
/// <summary>
/// serializes just one tag/value to a string
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
protected string Serialize(T tag)
{
var value = GetValue(tag);
if( string.IsNullOrWhiteSpace(value)){ return null; }
var attrib = DescriptionDecoder.GetDescription(tag);
var attributeIdentifier = DescriptionDecoder.GetDescription(_attribute);
if (_number < 0)
{
return $"{attributeIdentifier}\\{attrib}:{value};";
}
return $"{attributeIdentifier}-{_number}\\{attrib}:{value};";
}
/// <summary>
/// generic constructor for attributes which don't need to be associated with a number,
/// like General Information
/// </summary>
public TMATSSection()
{
}
/// <summary>
/// constructor for attributes that are associated with a specific number, like PCM
/// being associated with a channel number
/// </summary>
/// <param name="attribute"></param>
/// <param name="number"></param>
public TMATSSection(AttributeIdentifiers attribute, int number)
{
_attribute = attribute;
_number = number;
}
}
}

View File

@@ -0,0 +1,154 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace IRIGCh10
{
public class TMATSectionNumbered<T> where T : Enum
{
public AttributeIdentifiers Identifier { get; set; } = AttributeIdentifiers.GeneralInformation;
public int Number { get; set; } = -1;
private Dictionary<T, string> _values = new Dictionary<T, string>();
public void SetValue(T tag, string value) => _values[tag] = value;
public string GetValue(T tag) => _values.ContainsKey(tag)?_values[tag] : null;
public string Serialize(int number)
{
var sb = new StringBuilder();
var tags = Enum.GetValues(typeof(T)).Cast<T>().ToArray();
foreach (var tag in tags)
{
var s = Serialize(number, tag);
if( string.IsNullOrWhiteSpace(s) ){ continue; }
sb.AppendLine(s);
}
return sb.ToString();
}
private string Serialize(int number, T tag)
{
var value = GetValue(tag);
if( string.IsNullOrWhiteSpace(value) ){ return null; }
var attr = DescriptionDecoder.GetDescription(tag);
var identifier = DescriptionDecoder.GetDescription(Identifier);
if (Number > 0)
{
return $"{identifier}-{Number}\\{attr}{number}:{value};";
}
else{ return $"{identifier}\\{attr}{number}:{value};"; }
}
public void SetValueWithLength(T tag, string value)
{
var maxLength = MaxLengthDecoder.GetMaxLength(tag);
//maxlength is just a suggestion ...
//if (maxLength < value.Length)
//{
// throw new FormatException($"{tag.ToString()} must be {maxLength} characters or less");
//}
SetValue(tag, value);
}
}
public class TMATSectionNumberedArray<T> where T:Enum
{
private List<TMATSectionNumbered<T>> _items = new List<TMATSectionNumbered<T>>();
private AttributeIdentifiers _attributeIdentifier = AttributeIdentifiers.GeneralInformation;
private readonly int _number = -1;
private readonly int _maxNumber = -1;
private string _numberedTag;
public TMATSectionNumberedArray(string numberedTag)
{
_numberedTag = numberedTag;
}
public TMATSectionNumberedArray(string numberedTag, int maxNumber)
{
_numberedTag = numberedTag;
_maxNumber = maxNumber;
}
public TMATSectionNumberedArray(AttributeIdentifiers identifier, int number, string numberedTag, int maxNumber)
{
_number = number;
_maxNumber = maxNumber;
_numberedTag = numberedTag;
_attributeIdentifier = identifier;
}
//private AttributeIdentifiers _attribute = AttributeIdentifiers.GeneralInformation;
public virtual void SetValue(int number, T tag, string value)
{
if (number > _items.Count)
{
SetCount(number);
}
_items[number - 1].SetValueWithLength(tag, value);
}
public string GetValue(int number, T tag) => number > _items.Count ? null : _items[number - 1].GetValue(tag);
public string Serialize()
{
if (!_items.Any())
{
return string.Empty;
}
var sb = new StringBuilder();
var attribute = DescriptionDecoder.GetDescription(_attributeIdentifier);
if (_number > 0)
{
attribute = $"{attribute}-{_number}";
}
if (!string.IsNullOrWhiteSpace(_numberedTag))
{
sb.AppendLine($"{attribute}\\{_numberedTag}:{_items.Count()};");
}
var number = 1;
foreach (var item in _items)
{
var s = item.Serialize(number++);
if( string.IsNullOrWhiteSpace(s) ){ continue; }
sb.Append(s);
}
return sb.ToString();
}
public int GetCount() => _items.Count;
public void SetCount(int count)
{
if (_maxNumber > 0 && count > _maxNumber)
{
throw new Exception($"count exceeds maximum number for array");
}
if( _items.Count == count ){ return; }
if (_items.Count > count)
{
var toKeep = _items.Take(count);
_items.Clear();
_items.AddRange(toKeep);
}
else
{
for (var i = _items.Count; i < count; i++)
{
var newItem = new TMATSectionNumbered<T>();
_items.Add(newItem);
if (_number > 0)
{
newItem.Number = _number;;
}
newItem.Identifier = _attributeIdentifier;
}
}
}
}
}