using DTS.Common.Enums;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Interface.DASFactory.Config;
using System;
namespace DTS.Common.Classes.TMAT
{
///
/// these are all the patterns that represent global keys
///
public enum TMTGlobalKeys
{
[TMTKey("{NAME OF PROGRAM}")] NameOfProgram,
[TMTKey("{TEST ID}")] TestId,
[TMTKey("{DAS SERIAL NUMBER}")] DASSerialNumber,
[TMTKey("{DAS INDEX}")] DASIndex,
[TMTKey("{DAS SAMPLE RATE}")] DASSampleRate,
[TMTKey("{TEST TIMESTAMP}")] TestTimeStamp,
[TMTKey("{DAS BIT RATE}")] DASBitRate,
[TMTKey("{STREAM TIME FORMAT}")] StreamTimeFormat,
//FB 26736 Keys for time & data channel Id
[TMTKey("{UDP STREAM TIME CHANNEL ID}")] UdpStreamTimeChannelId,
[TMTKey("{UDP STREAM DATA CHANNEL ID}")] UdpStreamDataChannelId,
//FB 43761
[TMTKey("{UDP STREAM UART CHANNEL ID}")] UdpStreamUartChannelId,
[TMTKey("{UDP STREAM UART CHANNEL ID ENABLED}")] UdpStreamUartChannelIdEnabled,
//FB 29996 Key for file creation date
[TMTKey("{CREATE DATE}")] CreateDate,
//http://manuscript.dts.local/f/cases/37929/Implement-TSRAIR-module-on-off-selection-via-Max-Slice-Enable-system-attribute
[TMTKey("{NUMBER OF STREAMED CHANNELS}")] NumberOfStreamedChannels,
[TMTKey("{NUMBER OF CHANNELS PLUS TIME}")] NumberOfChannelsPlusTime,
[TMTKey("{NUMBER OF BITS PER MINOR FRAME}")] NumberOfBitsPerMinorFrame
}
///
/// these are all the patterns that represent channel keys when channels are all part of 1 template
///
public enum TMTChannelKeys
{
[TMTKey("{{CHANNEL {0} HARDWARE CHANNEL NUMBER}}")] HardwareChannelNumber,
[TMTKey("{{CHANNEL {0} NAME}}")] ChannelName,
[TMTKey("{{CHANNEL {0} COUPLING MODE}}")] CouplingMode,
[TMTKey("{{CHANNEL {0} BRIDGE RESISTANCE}}")] BridgeResistance,
[TMTKey("{{CHANNEL {0} AAF}}")] AAF,
[TMTKey("{{CHANNEL {0} OFFSET mV}}")] OffsetMV,
[TMTKey("{{CHANNEL {0} INPUT RANGE}}")] InputRangeMV,
[TMTKey("{{CHANNEL {0} MAX RANGE EU}}")] MaxRangeEU,
[TMTKey("{{CHANNEL {0} MIN RANGE EU}}")] MinRangeEU,
[TMTKey("{{CHANNEL {0} EU}}")] EU,
[TMTKey("{{CHANNEL {0} SCALEFACTOR EU}}")] ScaleFactorEU,
[TMTKey("{{CHANNEL {0} OFFSET EU}}")] OffsetEU,
}
///
/// these are patterns for channel keys when channels are split into a separate template
///
public enum TMTChannelKeysEx
{
[TMTKey("{CHANNEL NUMBER}")]ChannelNumber,
[TMTKey("{CHANNEL NAME}")]ChannelName,
[TMTKey("{CHANNEL OFFSET EU}")]ChannelOffsetEU,
[TMTKey("{CHANNEL SCALEFACTOR EU}")]ChannelScaleFactorEU,
[TMTKey("{CHANNEL EU}")]ChannelEU,
[TMTKey("{CHANNEL MAX RANGE EU}")]ChannelMaxRangeEU,
[TMTKey("{CHANNEL MIN RANGE EU}")]ChannelMinRangeEU,
[TMTKey("{BYTE FORMAT}")]ByteFormat,
[TMTKey("{BYTE FORMAT2}")]ByteFormat2,
[TMTKey("{CHANNEL MIDPOINT}")]ChannelMidPoint
}
///
/// Helper attribute, allows us to associate patterns to enums to make processing file easier
///
[System.AttributeUsage(System.AttributeTargets.Field)]
public class TMTKey : System.Attribute
{
///
/// the pattern to look for in a line to replace
///
public string Key { get; set; }
public TMTKey(string key)
{
Key = key;
}
///
/// returns the pattern to look for in a line for a given property
///
///
///
public static string GetKey(TMTGlobalKeys o)
{
var mi = o.GetType().GetMember(o.ToString());
if (mi.Length <= 0) return string.Empty;
return GetCustomAttribute(mi[0], typeof(TMTKey)) is TMTKey attr ? attr.Key : string.Empty;
}
///
/// returns the pattern to look for in a line for a given property
///
///
///
public static string GetKey(TMTChannelKeysEx o)
{
var mi = o.GetType().GetMember(o.ToString());
if (mi.Length <= 0) return string.Empty;
return GetCustomAttribute(mi[0], typeof(TMTKey)) is TMTKey attr ? attr.Key : string.Empty;
}
///
/// returns the pattern to look for in a line for a given channel property
///
///
///
///
public static string GetKey(TMTChannelKeys o, int channelNumber)
{
var mi = o.GetType().GetMember(o.ToString());
if (mi.Length <= 0) return string.Empty;
if (GetCustomAttribute(mi[0], typeof(TMTKey)) is TMTKey attr)
{
return string.Format(attr.Key, channelNumber);
}
else
{
return string.Empty;
}
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S101:Types should be named in Acronym", Justification = "")]
public interface ITMTTemplate
{
///
/// updates the fields in the file with a given value
///
///
///
void UpdateValue(TMTChannelKeysEx key, string value, int channelNumber);
///
/// updates the fields in the file with a given value
///
///
///
void UpdateValue(TMTGlobalKeys key, string value);
///
/// updates the files in the file with the given value
///
///
///
///
void UpdateValue(TMTChannelKeys key, string value, int channelNumber);
///
/// returns all lines in the TMT file
///
///
string[] GetAllLines();
}
public abstract class TmtBase : ITMTTemplate
{
///
/// this is the max length of the channel name in a TMT file,
/// this was done in an effort to keep TMT file length below 4k bytes
/// 2019-10-10 - DTM increased this to 200 as TMT file length was increased to 16k
///
private const int TMT_MAX_CHANNEL_LENGTH = 200;
///
/// does the work to ensure string is of MAX_LENGTH or shorter
///
///
///
public static string TMT_LimitString(string s)
{
return s.Substring(0, Math.Min(s.Length, TMT_MAX_CHANNEL_LENGTH));
}
private static string ScaleFactorOrOffsetToString(double d)
{
return $"{d:0.0##########}";//F11, but strip trailing zeros
}
///
/// updates the given field in the template with a value
///
public static void UpdateChannelField(TMTChannelKeysEx key, ITMTTemplate template, int channelIndex,
float [] ranges, double minEU, double maxEU, string eu, float [] scaleFactors, double adcToEUScalingFactor,
string channelName2, string offsetEU, bool bSigned)
{
switch (key)
{
case TMTChannelKeysEx.ChannelNumber:
template.UpdateValue(key, $"{1 + channelIndex}", channelIndex);
break;
case TMTChannelKeysEx.ChannelName:
template.UpdateValue(key, TMT_LimitString(channelName2), channelIndex);
break;
case TMTChannelKeysEx.ChannelOffsetEU:
template.UpdateValue(key, TMT_LimitString(offsetEU), channelIndex);
break;
case TMTChannelKeysEx.ChannelScaleFactorEU:
if (scaleFactors != null)
{
template.UpdateValue(key, ScaleFactorOrOffsetToString(scaleFactors[channelIndex]), channelIndex);
}
else
{
template.UpdateValue(key, RunTestVariables.MaskEUMetaData ? "1" : ScaleFactorOrOffsetToString(adcToEUScalingFactor), channelIndex);
}
break;
case TMTChannelKeysEx.ByteFormat:
template.UpdateValue(key, bSigned?"TWO":"OFF", channelIndex);
break;
case TMTChannelKeysEx.ByteFormat2:
template.UpdateValue(key, bSigned?"2":"B", channelIndex);
break;
case TMTChannelKeysEx.ChannelMidPoint:
template.UpdateValue(key, bSigned?"0":"2500", channelIndex);
break;
case TMTChannelKeysEx.ChannelEU:
template.UpdateValue(key,
RunTestVariables.MaskEUMetaData ? "---" : eu?.Trim() ?? "", channelIndex);
break;
case TMTChannelKeysEx.ChannelMaxRangeEU:
{
if ( ranges != null)
{
template.UpdateValue(key, ranges[channelIndex].ToString("F0"), channelIndex);
}
else { template.UpdateValue(key, RunTestVariables.MaskEUMetaData ? "1" : maxEU.ToString("F0"), channelIndex); }
}
break;
case TMTChannelKeysEx.ChannelMinRangeEU:
{
if (ranges != null)
{
template.UpdateValue(key, (-1 * ranges[channelIndex]).ToString("F0"), channelIndex);
}
else
{
template.UpdateValue(key, RunTestVariables.MaskEUMetaData ? "1" :
minEU.ToString("F0"), channelIndex);
}
}
break;
}
}
public static void UpdateGlobalField(IDASCommunication das, TMTGlobalKeys key, ITMTTemplate template,
IConfigurationData ConfigData,
String serialNumber,
ushort? timeChannelId,
ushort? dataChannelId,
ushort? uartChannelId,
int dasIndex,
int bitsPerFrame)
{
switch (key)
{
case TMTGlobalKeys.NameOfProgram:
template.UpdateValue(key,
TMT_LimitString(System.Reflection.Assembly.GetExecutingAssembly().GetName().Name));
break;
case TMTGlobalKeys.TestId:
template.UpdateValue(key, TMT_LimitString(ConfigData.TestID));
break;
case TMTGlobalKeys.CreateDate:
//FB 29996 used the same date format from the template
template.UpdateValue(key, DateTime.Now.ToString("MM-dd-yyyy"));
break;
case TMTGlobalKeys.DASSerialNumber:
template.UpdateValue(key, serialNumber);
break;
// FB 26736 replace time & data channel Ids in template
case TMTGlobalKeys.UdpStreamDataChannelId:
if (dataChannelId.HasValue)
{
template.UpdateValue(key, dataChannelId.Value.ToString());
}
break;
case TMTGlobalKeys.UdpStreamTimeChannelId:
if (timeChannelId.HasValue)
{
template.UpdateValue(key, timeChannelId.Value.ToString());
}
break;
//FB 43761 update tmat file with uart channel id & enable/disable T/F
case TMTGlobalKeys.UdpStreamUartChannelId:
if (uartChannelId.HasValue)
{
template.UpdateValue(key, uartChannelId.Value.ToString());
}
break;
case TMTGlobalKeys.UdpStreamUartChannelIdEnabled:
if (uartChannelId.HasValue)
{
template.UpdateValue(key, uartChannelId.Value > 0 ? "T" : "F");
}
else
{
template.UpdateValue(key, "F");
}
break;
case TMTGlobalKeys.DASIndex:
template.UpdateValue(key, dasIndex.ToString());
break;
case TMTGlobalKeys.DASSampleRate:
template.UpdateValue(key, ConfigData.Modules[0].SampleRateHz.ToString());
break;
case TMTGlobalKeys.DASBitRate:
template.UpdateValue(key,
(ConfigData.Modules[0].SampleRateHz * bitsPerFrame).ToString());
break;
case TMTGlobalKeys.StreamTimeFormat:
// FB15388 Add line "R-1\TTF-1:{TIME FORMAT};" to detail either time format 1 or 2
// FB 30035 Get stream time format from StreamOut module
var streamOutModule = Array.Find(ConfigData.Modules, m => m.ModuleType() == DFConstantsAndEnums.ModuleType.StreamOut);
if (streamOutModule != null)
{
template.UpdateValue(key, streamOutModule.StreamProfile.ToString().Contains(Constants.UDP_STREAM_CH10_TF2) ? "2" : "1");
}
break;
case TMTGlobalKeys.TestTimeStamp:
var now = DateTime.Now;
var timeStamp =
$"{now.Month:00}-{now.Day:00}-{now.Year:0000}-{now.Hour:00}-{now.Minute:00}-{now.Second:00}";
template.UpdateValue(key, timeStamp);
break;
case TMTGlobalKeys.NumberOfStreamedChannels: template.UpdateValue(key, GetNumberOfStreamedChannels(das).ToString()); break;
case TMTGlobalKeys.NumberOfChannelsPlusTime: template.UpdateValue(key, (1 + GetNumberOfStreamedChannels(das)).ToString()); break;
case TMTGlobalKeys.NumberOfBitsPerMinorFrame: template.UpdateValue(key, (32 + 16 * GetNumberOfStreamedChannels(das)).ToString()); break;
}
}
public static int GetNumberOfStreamedChannels(IDASCommunication das)
{
if (das is IDASReconfigure reconfigure)
{
if (das.GetHardwareType() == Enums.Hardware.HardwareTypes.SLICE6_AIR_TC)
{
return 24;
}
return GetNumberOfStreamedChannelsReconfigurable(das);
}
else { return 6; }
}
private static int GetNumberOfStreamedChannelsReconfigurable(IDASCommunication das)
{
//for now the TSR AIR is the only reconfigurable streaming devices? we may need to fix this in the future
switch (das.DASInfo.Modules.Length)
{
case 3: return 3; //TSR AIR Lowg only (low g + stream output + UART)
case 4: return 6; //TSR AIR LowG & High G (low g + high g + stream output + UART)
case 5: return 9; //TSR AIR LowG, HighG, ARS
default: return 18; //ALL
}
}
public abstract void UpdateValue(TMTChannelKeysEx key, string value, int channelNumber);
public abstract void UpdateValue(TMTGlobalKeys key, string value);
public abstract void UpdateValue(TMTChannelKeys key, string value, int channelNumber);
public abstract string[] GetAllLines();
}
}