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,27 @@
using System;
using System.ComponentModel;
using DTS.Common.Interface;
namespace TTSImport.Model
{
public class ChannelSummary : IChannelSummary
{
private string _channelType = String.Empty;
public string ChannelType { get => _channelType; set { _channelType = value; OnPropertyChanged("ChannelType"); } }
private int _requested = 0;
public int Requested { get => _requested; set { _requested = value; OnPropertyChanged("Requested"); } }
private int _assigned = 0;
public int Assigned { get => _assigned; set { _assigned = value; OnPropertyChanged("Assigned"); } }
private int _unassigned = 0;
public int Unassigned { get => _unassigned; set { _unassigned = value; OnPropertyChanged("Unassigned"); } }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -0,0 +1,485 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using DTS.Common.Interface.DataRecorders;
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
using DTS.Common.Enums;
namespace TTSImport.Model
{
/// <summary>
/// this class represents a hardware channel + some additional meta information (mostly the TTSChannelRecord or sensor that might be assigned)
/// It's currently for use in AnalogChannelsViewModel
/// </summary>
public class DASChannel : DependencyObject, INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public bool SetProperty<T>(ref T storage, T value, string propertyName = null)
{
if (Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
public void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region enums and constants
public const string POSITIVE = "+";
public const string NEGATIVE = "-";
public IEnumerable<string> Polarities => new[] { POSITIVE, NEGATIVE };
public IEnumerable<SquibFireMode> SquibFireModes => new[]
{
SquibFireMode.CAP, SquibFireMode.CONSTANT
};
public IEnumerable<DigitalOutputModes> OutputModes => new[]
{
DigitalOutputModes.NONE,
DigitalOutputModes.CCNO,
DigitalOutputModes.CCNC,
DigitalOutputModes.FVHL,
DigitalOutputModes.FVLH
};
#endregion
#region constructors and initializers
public DASChannel(IHardwareChannel channel)
{
HardwareChannel = channel;
}
public DASChannel(IHardwareChannel channel, ITTSSetup setup)
{
HardwareChannel = channel;
TestSetup = setup;
}
public ITTSSetup TestSetup { get; }
#endregion
#region properties
/// <summary>
/// the digital output mode (if relevant)
/// </summary>
public DigitalOutputModes DigitalOutputMode
{
get => Channel?.DigitalOutputMode ?? DigitalOutputModes.NONE;
set
{
if (Channel.DigitalOutputMode == value) return;
if (Channel.DigitalOutputMode == DigitalOutputModes.NONE)
{
//Add to the Test Setup
AddDigitalOutputChannel();
}
else if (value == DigitalOutputModes.NONE)
{
//Remove from the Test Setup
RemoveDigitalOutputChannel();
}
Channel.DigitalOutputMode = value;
Channel.IsModified = true;
OnPropertyChanged("IsActive");
}
}
/// <summary>
/// the delay between trigger and output (if relevant)
/// </summary>
public double DigitalOutputDelayMs
{
get => Channel?.DigitalOutputDelay ?? 0D;
set
{
if (null != Channel)
{
Channel.DigitalOutputDelay = value;
Channel.IsModified = true;
}
}
}
/// <summary>
/// the duration of output after output started (if relevant)
/// </summary>
public double DigitalOutputDurationMs
{
get => Channel?.DigitalOutputDuration ?? 100D;
set
{
if (null != Channel)
{
Channel.DigitalOutputDuration = value;
Channel.IsModified = true;
}
}
}
/// <summary>
/// the polarity of the sensor associated with this hardware channel (if any)
/// </summary>
public string Polarity
{
get
{
if (null != Channel)
{
return Channel.SensorPolarity ? POSITIVE : NEGATIVE;
}
return POSITIVE;
}
set
{
if (null != Channel)
{
Channel.SensorPolarity = value == POSITIVE;
}
}
}
public SquibFireMode SquibFireMode
{
get
{
if (null != Channel)
{
return Channel.SquibFireMode;
}
return SquibFireMode.CAP;
}
set
{
if (null != Channel)
{
Channel.SquibFireMode = value;
Channel.IsModified = true;
}
}
}
/// <summary>
/// whether this channel should be considered disabled or not
/// disabled channels will exist in the test setup but won't be used during run test
/// </summary>
public bool Disabled
{
get => (bool)GetValue(DisabledProperty);
set => SetValue(DisabledProperty, value);
}
/// <summary>
/// this is the Toyota channel record associated with the hardware channel
/// can be null if there's no sensor associated
/// </summary>
public ITTSChannelRecord Channel { get; private set; }
/// <summary>
/// a string representation of the hardware channel (eg [SPS00001] ch 13)
/// </summary>
public string DASChannelString => HardwareChannel?.ToString() ?? "";
/// <summary>
/// the Channel code associated with the physical hardware channel (if any)
/// </summary>
public string ToyotaCode
{
get => Channel?.ChannelCode ?? "";
set
{
if (null != Channel)
{
Channel.ChannelCode = value;
Channel.IsModified = true;
}
}
}
/// <summary>
/// the electronic id on the physical channel (if any)
/// </summary>
public string EID { get; set; }
/// <summary>
/// the "name" of the channel, if any (is blank if no TTSRecord associated with this channel)
/// </summary>
public string Name
{
get => Channel?.JCodeOrDescription ?? "";
set
{
if (null != Channel)
{
Channel.JCodeOrDescription = value;
Channel.IsModified = true;
}
}
}
/// <summary>
/// the serial number for a sensor on this channel (if any)
/// </summary>
public string SerialNumber => Channel?.SensorSerialNumber ?? "";
public string SensitivityString => Sensitivity.ToString("N12");
/// <summary>
/// the sensitivity of the sensor on this channel (if any)
/// </summary>
public double Sensitivity => Channel?.SensorSensitivity ?? 0D;
/// <summary>
/// true as long as there is a TTS record associated with this physical channel
/// </summary>
public bool IsActive
{
get
{
if (null == Channel) return false;
if (null != Channel.HardwareChannel && Channel.HardwareChannel.IsDigitalOut)
{
return Channel.DigitalOutputMode != DigitalOutputModes.NONE;
}
return true;
}
}
/// <summary>
/// the capacity of the sensor associated with this physical channel (if any)
/// </summary>
public double Capacity => Channel?.SensorCapacity ?? 0D;
/// <summary>
/// the range of the sensor associated with this physical channel (if any)
/// </summary>
public double Range
{
get => Channel?.ChannelRange ?? 0D;
set
{
if (null != Channel)
{
Channel.ChannelRange = value;
Channel.IsModified = true;
}
}
}
public double CableMultiplier
{
get => Channel?.CableMultiplier ?? 1D;
set
{
if (null != Channel)
{
Channel.CableMultiplier = value;
Channel.IsModified = true;
}
}
}
/// <summary>
/// the delay in ms between trigger and squib fire
/// </summary>
public double SquibFireDelayMs
{
get => Channel?.SquibFireDelayMs ?? 0D;
set
{
if (null != Channel)
{
Channel.SquibFireDelayMs = value;
Channel.IsModified = true;
}
}
}
/// <summary>
/// the limit for current (amps)
/// </summary>
public double SquibFireCurrent
{
get => Channel?.SquibFireCurrent ?? 0D;
set
{
if (null != Channel)
{
Channel.SquibFireCurrent = value;
Channel.IsModified = true;
}
}
}
/// <summary>
/// whether to limit the duration or not of squib fire
/// </summary>
public bool LimitDuration
{
get
{
if (null == Channel) { return false; }
if (Channel.IsDigitalOutput && Channel.DigitalOutputMode == DigitalOutputModes.NONE) { return false; }
return Channel.LimitDuration;
}
set
{
if (null != Channel)
{
Channel.LimitDuration = value;
Channel.IsModified = true;
OnPropertyChanged("LimitDuration");
}
}
}
/// <summary>
/// the duration of the squib fire in ms from the start of firing
/// (if limiting duration)
/// </summary>
public double SquibFireDurationMs
{
get => Channel?.SquibFireDurationMs ?? .20D;
set
{
if (null != Channel)
{
Channel.SquibFireDurationMs = value;
Channel.IsModified = true;
}
}
}
/// <summary>
/// the squib resistance tolerance low value (ohms)
/// </summary>
public double SquibFireResistanceLowOhm
{
get => Channel?.SquibFireResistanceLowOhm ?? 1D;
set
{
if (null != Channel)
{
Channel.SquibFireResistanceLowOhm = value;
Channel.IsModified = true;
}
}
}
/// <summary>
/// the squib resistance tolerance high value (ohms)
/// </summary>
public double SquibFireResistanceHighOhm
{
get => Channel?.SquibFireResistanceHighOhm ?? 8D;
set
{
if (null != Channel)
{
Channel.SquibFireResistanceHighOhm = value;
Channel.IsModified = true;
}
}
}
/// <summary>
/// this is the hardware channel we are wrapping
/// </summary>
public IHardwareChannel HardwareChannel { get; }
#endregion
#region dependency properties
/// <summary>
/// the disabled property allows controls to make use of Disabled in styles, allow us to have a specific style for when a DASChannel is disabled
/// </summary>
public static readonly DependencyProperty DisabledProperty =
DependencyProperty.Register("Disabled", typeof(bool), typeof(DASChannel), new PropertyMetadata(false));
#endregion
#region methods
/// <summary>
/// Assigns this hardware to that TTSChannelRecord, or that channel record to this physical hardware
/// [depending on the POV]
/// </summary>
/// <param name="channel">the channel being assigned (can be null if removing a sensor from a physical channel)</param>
public void SetITTSChannelRecord(ITTSChannelRecord channel)
{
//if we are assigning something to this DASChannel, then any existing sensor
//record on this channel is no longer on it, so unassign the hardwareassignment to existing
if (null != Channel)
{
Channel.HardwareChannel = null;
}
Channel = channel;
//now assign the hardware channel on the channelrecord to this hardware channel
if (null != channel)
{
channel.HardwareChannel = HardwareChannel;
}
//clean up the ui
OnPropertyChanged("ToyotaCode");
OnPropertyChanged("EID");
OnPropertyChanged("Name");
OnPropertyChanged("SerialNumber");
OnPropertyChanged("SensitivityString");
OnPropertyChanged("IsActive");
OnPropertyChanged("Capacity");
OnPropertyChanged("Range");
OnPropertyChanged("Polarity");
OnPropertyChanged("CableMultiplier");
OnPropertyChanged("SquibFireDelayMs");
OnPropertyChanged("SquibFireCurrent");
OnPropertyChanged("LimitDuration");
OnPropertyChanged("SquibFireDurationMs");
OnPropertyChanged("SquibFireResistanceLowOhm");
OnPropertyChanged("SquibFireResistanceHighOhm");
OnPropertyChanged("InputMode");
OnPropertyChanged("OutputMode");
OnPropertyChanged("DigitalOutputDelayMs");
OnPropertyChanged("DigitalOutputDurationMs");
Disabled = channel?.Disabled ?? false;
}
/// <summary>
/// Adds a Digital Output channel to the Test Setup when DigitalOutputMode
/// changes from None to something other than None.
/// </summary>
private void AddDigitalOutputChannel()
{
var newChannels = new List<ITTSChannelRecord>(TestSetup.Channels);
newChannels.Add(Channel);
TestSetup.Channels = newChannels.ToArray();
}
/// <summary>
/// Removes a Digital Output channel from the Test Setup when DigitalOutputMode
/// changes to None.
/// </summary>
private void RemoveDigitalOutputChannel()
{
var newChannels = new List<ITTSChannelRecord>();
foreach (var channel in TestSetup.Channels)
{
if (channel.HardwareChannel != Channel.HardwareChannel)
{
newChannels.Add(channel);
}
}
TestSetup.Channels = newChannels.ToArray();
}
#endregion
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.ComponentModel;
using DTS.Common.Interface;
namespace TTSImport.Model
{
public class DasSummary : IDasSummary
{
private string _dasSerial;
public string DASSerial { get => _dasSerial; set { _dasSerial = value; OnPropertyChanged("DASSerial"); } }
private string _eidFound;
public string EIDFound { get => _eidFound; set { _eidFound = value; OnPropertyChanged("EIDFound"); } }
private string _batteryVoltageStatus;
public string BatteryVoltageStatus { get => _batteryVoltageStatus; set { _batteryVoltageStatus = value; OnPropertyChanged("BatteryVoltageStatus"); } }
private System.Windows.Media.SolidColorBrush _batteryVoltageColor;
public System.Windows.Media.SolidColorBrush BatteryVoltageColor { get => _batteryVoltageColor; set { _batteryVoltageColor = value; OnPropertyChanged("BatteryVoltageColor"); } }
private string _inputVoltageStatus;
public string InputVoltageStatus { get => _inputVoltageStatus; set { _inputVoltageStatus = value; OnPropertyChanged("InputVoltageStatus"); } }
private System.Windows.Media.SolidColorBrush _inputVoltageColor;
public System.Windows.Media.SolidColorBrush InputVoltageColor { get => _inputVoltageColor; set { _inputVoltageColor = value; OnPropertyChanged("InputVoltageColor"); } }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -0,0 +1,162 @@
using DTS.Common.Base;
using DTS.Common.Interface.TestSetups.Imports.TTS.HardwareScan;
namespace TTSImport.Model
{
public class HardwareSummaryRecord : BasePropertyChanged, IHardwareSummaryRecord
{
private uint _dout;
public uint DOut
{
get => _dout;
set
{
_dout = value;
OnPropertyChanged("DOut");
}
}
private uint _din;
public uint DIn
{
get => _din;
set
{
_din = value;
OnPropertyChanged("DIn");
}
}
private uint _squib;
public uint Squib
{
get => _squib;
set
{
_squib = value;
OnPropertyChanged("Squib");
}
}
private uint _analog;
public uint Analog
{
get => _analog;
set
{
_analog = value;
OnPropertyChanged("Analog");
}
}
private uint _sps;
public uint SPS
{
get => _sps;
set
{
_sps = value;
OnPropertyChanged("SPS");
}
}
private uint _spd;
public uint SPD
{
get => _spd;
set
{
_spd = value;
OnPropertyChanged("SPD");
}
}
private uint _spt;
public uint SPT
{
get => _spt;
set
{
_spt = value;
OnPropertyChanged("SPT");
}
}
private uint _ecm;
public uint ECM
{
get => _ecm;
set
{
_ecm = value;
OnPropertyChanged("ECM");
}
}
private uint _rack;
public uint Rack
{
get => _rack;
set
{
_rack = value;
OnPropertyChanged("Rack");
}
}
private uint _g5;
public uint G5
{
get => _g5;
set
{
_g5 = value;
OnPropertyChanged("G5");
}
}
private uint _total;
public uint Total
{
get => _total;
private set
{
_total = value;
OnPropertyChanged("Total");
}
}
public void UpdateTotal()
{
Total = Analog + Squib + DIn + DOut;
}
public void Update(uint analog, uint squib, uint din, uint dout, uint ecm, uint sps, uint spt, uint spd,
uint g5,
uint rack)
{
Analog = analog;
Squib = squib;
DIn = din;
DOut = dout;
ECM = ecm;
SPS = sps;
SPT = spt;
SPD = spd;
G5 = g5;
Rack = rack;
UpdateTotal();
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.ComponentModel;
using DTS.Common.Interface;
namespace TTSImport.Model
{
public class SummaryChannel : ISummaryChannel
{
private string _channelType = string.Empty;
public string ChannelType { get => _channelType; set { _channelType = value; OnPropertyChanged("ChannelType"); } }
private int _assigned;
public int Assigned { get => _assigned; set { _assigned = value; OnPropertyChanged("Assigned"); } }
private string _unassigned = string.Empty;
public string Unassigned { get => _unassigned; set { _unassigned = value; OnPropertyChanged("Unassigned"); } }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -0,0 +1,563 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using DTS.Common.DAS.Concepts;
using DTS.Common.Enums;
using DTS.Common.Enums.Sensors;
using DTS.Common.Enums.TTS;
using DTS.Common.Interface.DataRecorders;
using DTS.Common.Interface.TestSetups.Imports.TTS;
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
using DTS.SensorDB;
using Prism.Commands;
using TTSImport.Resources;
namespace TTSImport.Model
{
/// <inheritdoc />
/// <summary>
/// this class represents a line in the TTS import CSV,
/// </summary>
public class TTSChannelRecord : DTS.Common.Base.BasePropertyChanged, ITTSChannelRecord
{
#region INotifyPropertyChanged
public override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
switch (propertyName)
{
case "ChannelCode":
case "JCodeOrDescription":
case "ChannelRange":
case "ChannelFilterHz":
if (Parent != null)
{
Parent.ChangeValidationIsNeeded = true;
}
break;
}
}
#endregion
#region enums
public const string CFC1000 = "1650";
public const string CFC600 = "1000";
public const string CFC180 = "300";
public const string CFC60 = "100";
public const string CFC10 = "17";
public const string NONE = "None";
public IEnumerable<string> Filters => new[] { CFC1000, CFC600, CFC180, CFC60, CFC10, NONE };
public const string DIAGNOSTICSMODE = "DIAGNOSTICSMODE";
#endregion enums
private const string SYSTEMSETTING = "0.###";
private string STRINGDISPLAYFORMAT_CHANNELRANGE = SYSTEMSETTING; //Get the value from the UI in System Settings
public IEditFileViewModel Parent { get; set; }
private int _channelNumber;
public int ChannelNumber
{
get => _channelNumber;
set => SetProperty(ref _channelNumber, value, "ChannelNumber");
}
private string _channelCode;
public string ChannelCode
{
get => _channelCode ?? "";
set => SetProperty(ref _channelCode, value, "ChannelCode");
}
private string _jCodeOrDescription;
public string JCodeOrDescription
{
get => _jCodeOrDescription ?? "";
set
{
_jCodeOrDescription = value;
IsJCodeValid = !string.IsNullOrEmpty(value);
OnPropertyChanged("JCodeOrDescription");
}
}
private double _channelRange;
public double ChannelRange
{
get => _channelRange;
set
{
_channelRange = value;
IsRangeValid = !double.IsNaN(value) && value > 0;
OnPropertyChanged("ChannelRange");
}
}
public string ChannelRangeString
{
get => ChannelRange <= 0 ? string.Empty : ChannelRange.ToString(STRINGDISPLAYFORMAT_CHANNELRANGE); //Should use the UI setting
set
{
if (double.TryParse(value, out double range))
{
ChannelRange = range;
IsRangeValid = true;
}
else
{
ChannelRange = double.NaN;
IsRangeValid = false;
}
OnPropertyChanged("ChannelRangeString");
}
}
public Visibility RangeVisible
{
get
{
if (!IsSquib && !IsDigitalInput && !IsDigitalOutput)
{
return Visibility.Visible;
}
return Visibility.Hidden;
}
}
private int _channelFilterHz;
public int ChannelFilterHz
{
get => _channelFilterHz;
set
{
_channelFilterHz = value;
IsFilterValid = value != -1;
OnPropertyChanged("ChannelFilterHz");
}
}
public string FilterString
{
get => ChannelFilterHz <= 0 ? "" : ChannelFilterHz.ToString("F0");
set
{
if (int.TryParse(value, out int filter) || filter > 0)
{
if (filter == 1650 || filter == 1000 || filter == 300 || filter == 100 || filter == 17)
{
ChannelFilterHz = filter;
IsFilterValid = true;
}
else
{
ChannelFilterHz = -1;
IsFilterValid = false;
}
}
else
{
ChannelFilterHz = 0;
IsFilterValid = true; //Is this right?
}
OnPropertyChanged("FilterString");
}
}
public Visibility FilterVisible
{
get
{
if (!IsSquib && !IsDigitalInput && !IsDigitalOutput)
{
return Visibility.Visible;
}
return Visibility.Hidden;
}
}
private string _sensorSerialNumber;
public string SensorSerialNumber
{
get => _sensorSerialNumber ?? "";
set => SetProperty(ref _sensorSerialNumber, value, "SensorSerialNumber");
}
private DelegateCommand<string> _controlLostFocus;
public DelegateCommand<string> ControlLostFocus => _controlLostFocus ?? (_controlLostFocus = new DelegateCommand<string>(ControlLostFocusMethod));
public void ControlLostFocusMethod(string code)
{
if (!Parent.ChangeValidationIsNeeded) return;
Parent.ValidateChange(this);
}
private DelegateCommand<string> _filterSelectionChanged;
public DelegateCommand<string> FilterSelectionChanged => _filterSelectionChanged ?? (_filterSelectionChanged = new DelegateCommand<string>(FilterSelectionChangedMethod));
public void FilterSelectionChangedMethod(string code)
{
if (!Parent.ChangeValidationIsNeeded) return;
Parent.ValidateChange();
}
public string SensorEID { get; set; }
public double SensorSensitivity { get; set; }
public double SensorExcitationVolts { get; set; }
public double SensorCapacity { get; set; }
public string SensorEU { get; set; }
public bool SensorPolarity { get; set; }
public ToyotaBridgeType ChannelType { get; set; }
public string Description { get; set; }
public bool ProportionalToExcitation { get; set; }
public double BridgeResistance { get; set; }
public double InitialOffsetVoltage { get; set; }
public double InitialOffsetVoltageTolerance { get; set; }
public bool RemoveOffset { get; set; }
public ToyotaZeroMethods ZeroMethod { get; set; }
public double CableMultiplier { get; set; }
public double InitialEUInMV { get; set; }
public double InitialEUInEU { get; set; }
public double IRTraccExponent { get; set; }
public double PolynomialConstant { get; set; }
public double PolynomialCoefficientC { get; set; }
public double PolynomialCoefficentB { get; set; }
public double PolynomialCoefficientA { get; set; }
public double PolynomialCoefficientAlpha { get; set; }
public string ISOCode { get; set; }
public string ISODescription { get; set; }
public string ISOPolarity { get; set; }
public bool IsSquib { get; set; }
public bool IsDigitalInput { get; set; }
public bool IsDigitalOutput { get; set; }
public IHardwareChannel HardwareChannel { get; set; }
/// <inheritdoc />
/// <summary>
/// returns true if the record is empty (no channel code and no sensor serial number)
/// </summary>
public bool IsEmptyRecord => ChannelCode == StringResources.NONE && string.IsNullOrWhiteSpace(SensorSerialNumber);
/// <summary>
/// returns whether the channelcode is valid or not
/// </summary>
private bool _isChannelCodeValid;
public bool IsChannelCodeValid
{
get => _isChannelCodeValid;
set => SetProperty(ref _isChannelCodeValid, value, "IsChannelCodeValid");
}
private bool _isJCodeValid;
public bool IsJCodeValid
{
get => _isJCodeValid;
set => SetProperty(ref _isJCodeValid, value, "IsJCodeValid");
}
private bool _isRangeValid;
public bool IsRangeValid
{
get => _isRangeValid;
set => SetProperty(ref _isRangeValid, value, "IsRangeValid");
}
private bool _isFilterValid;
public bool IsFilterValid
{
get => _isFilterValid;
set => SetProperty(ref _isFilterValid, value, "IsFilterValid");
}
/// <inheritdoc />
/// <summary>
/// disabled channels are channels which are in the test setup, but aren't used during run test
/// </summary>
public bool Disabled { get; set; }
/// <inheritdoc />
/// <summary>
/// for squibs, controls the squib fire mode
/// </summary>
public SquibFireMode SquibFireMode { get; set; }
/// <inheritdoc />
/// <summary>
/// the delay in ms between trigger and squib fire
/// </summary>
public double SquibFireDelayMs { get; set; }
/// <inheritdoc />
/// <summary>
/// the limit for current (amps)
/// </summary>
public double SquibFireCurrent { get; set; }
/// <inheritdoc />
/// <summary>
/// whether to limit the duration or not of squib fire
/// </summary>
public bool LimitDuration { get; set; }
/// <summary>
/// the duration of the squib fire in ms from the start of firing
/// (if limiting duration)
/// </summary>
private double _squibFireDurationMs;
public double SquibFireDurationMs
{
get => _squibFireDurationMs;
set => _squibFireDurationMs = value < DTS.DASLib.Service.OutputSquibChannel.DEFAULT_MIN_FIRE_DURATION_MS
? DTS.DASLib.Service.OutputSquibChannel.DEFAULT_MIN_FIRE_DURATION_MS
: value > DTS.DASLib.Service.OutputSquibChannel.DEFAULT_MAX_FIRE_DURATION_MS
? DTS.DASLib.Service.OutputSquibChannel.DEFAULT_MAX_FIRE_DURATION_MS
: value;
}
/// <inheritdoc />
/// <summary>
/// the squib resistance tolerance low value (ohms)
/// </summary>
public double SquibFireResistanceLowOhm { get; set; }
/// <inheritdoc />
/// <summary>
/// the squib resistance tolerance high value (ohms)
/// </summary>
public double SquibFireResistanceHighOhm { get; set; }
/// <inheritdoc />
/// <summary>
/// digital input mode (if relevant)
/// </summary>
public DigitalInputModes DigitalInputMode { get; set; }
/// <inheritdoc />
/// <summary>
/// the digital output mode (if relevant)
/// </summary>
public DigitalOutputModes DigitalOutputMode { get; set; }
/// <inheritdoc />
/// <summary>
/// the delay between trigger and output (if relevant)
/// </summary>
public double DigitalOutputDelay { get; set; }
/// <inheritdoc />
/// <summary>
/// the duration of output after output started (if relevant)
/// </summary>
public double DigitalOutputDuration { get; set; }
/// <inheritdoc />
/// <summary>
/// controls whether the channel should be marked as diagnostics mode or not
/// note that diagnostics mode is only used when the configuration supports diagnostics mode
/// even if the sensor has diagnosticsmode set to true
/// </summary>
public bool DiagnosticsMode { get; set; }
private void InitValues()
{
ChannelCode = NONE;
InitialEUInMV = double.NaN;
InitialEUInEU = double.NaN;
IRTraccExponent = double.NaN;
PolynomialConstant = double.NaN;
PolynomialCoefficentB = double.NaN;
PolynomialCoefficientA = double.NaN;
PolynomialCoefficientAlpha = double.NaN;
PolynomialCoefficientC = double.NaN;
ISOCode = "";
ISODescription = "";
SquibFireMode = SquibFireMode.CAP;
SquibFireResistanceHighOhm = 8D;
SquibFireResistanceLowOhm = 1D;
SquibFireCurrent = 3D;
SquibFireDurationMs = 0.20D;
DigitalInputMode = DigitalInputModes.CCNO;
DigitalOutputMode = DigitalOutputModes.NONE;
DiagnosticsMode = false;
}
public TTSChannelRecord()
{
InitValues();
}
public TTSChannelRecord(SensorData sd)
{
InitValues();
if (sd == null
|| sd.Filter == null
|| sd.Calibration == null
|| sd.Calibration.Records == null
|| sd.Calibration.Records.Records == null
|| sd.Calibration.Records.Records[0] == null
|| sd.Calibration.Records.Records[0].Poly == null) return;
BridgeResistance = sd.BridgeResistance;
CableMultiplier = double.TryParse(sd.UserValue2, NumberStyles.Any, CultureInfo.InvariantCulture, out var d) ? d : 1D;
ChannelCode = sd.UserSerialNumber;
ChannelFilterHz = (int)sd.Filter.Frequency;
ChannelRange = sd.RangeHigh;
ChannelRangeString = sd.RangeHigh.ToString(CultureInfo.InvariantCulture);
//Channel Type
switch (sd.Bridge)
{
case SensorConstants.BridgeType.DigitalInput:
IsDigitalInput = true;
break;
case SensorConstants.BridgeType.QuarterBridge:
break;
case SensorConstants.BridgeType.HalfBridge_SigPlus:
ChannelType = ToyotaBridgeType.HalfBridge;
break;
case SensorConstants.BridgeType.FullBridge:
ChannelType = ToyotaBridgeType.FullBridge;
break;
case SensorConstants.BridgeType.SQUIB:
IsSquib = true;
break;
case SensorConstants.BridgeType.TOMDigital:
IsDigitalOutput = true;
break;
}
if (sd.Calibration.NonLinear)
{
switch (sd.Calibration.IRTraccCalculationType)
{
case NonLinearStyles.IRTraccDiagnosticsZero:
case NonLinearStyles.IRTraccAverageOverTime:
case NonLinearStyles.IRTraccZeroMMmV:
ChannelType = ToyotaBridgeType.IRTRACC;
break;
case NonLinearStyles.Polynomial:
ChannelType = ToyotaBridgeType.LinearChestPot;
break;
}
}
Description = sd.Comment;
InitialEUInEU = sd.Calibration.InitialOffsets.Offsets[0].EU;
InitialEUInMV = sd.Calibration.InitialOffsets.Offsets[0].MV;
InitialOffsetVoltage = sd.OffsetToleranceHigh - Math.Abs(sd.OffsetToleranceLow);
InitialOffsetVoltageTolerance = (sd.OffsetToleranceHigh + Math.Abs(sd.OffsetToleranceLow)) / 2.0;
if (sd.Calibration.NonLinear && !sd.Calibration.Records.Records[0].Poly.LinearizationExponent
.Equals(0.0))
{
IRTraccExponent = sd.Calibration.Records.Records[0].Poly.LinearizationExponent;
}
ISOCode = sd.ISOCode;
ISODescription = string.Empty;
ISOPolarity = sd.Polarity;
JCodeOrDescription = sd.Comment;
LimitDuration = sd.LimitDuration;
if (sd.Calibration.Records.Records[0].Poly.PolynomialExponents.Length == 5)
{
PolynomialCoefficientA = sd.Calibration.Records.Records[0].Poly.PolynomialCoefficients[3];
PolynomialCoefficientAlpha = sd.Calibration.Records.Records[0].Poly.PolynomialCoefficients[4];
PolynomialCoefficentB = sd.Calibration.Records.Records[0].Poly.PolynomialCoefficients[2];
PolynomialCoefficientC = sd.Calibration.Records.Records[0].Poly.PolynomialCoefficients[1];
PolynomialConstant = sd.Calibration.Records.Records[0].Poly.PolynomialCoefficients[0];
}
ProportionalToExcitation = sd.Calibration.IsProportional;
RemoveOffset = sd.Calibration.RemoveOffset;
SensorCapacity = sd.Capacity;
SensorEID = sd.EID;
SensorEU = sd.Calibration.Records.Records[0].EngineeringUnits;
SensorExcitationVolts = Test.Module.Channel.Sensor.GetExcitationVoltageMagnitudeFromEnum(sd.Calibration.Records.Records[0].Excitation);
SensorPolarity = !sd.Invert; //positive polarity means do not invert, invert means negative polarity
if (sd.Calibration.NonLinear)
{
switch (sd.Calibration.IRTraccCalculationType)
{
case NonLinearStyles.IRTraccAverageOverTime:
SensorSensitivity = sd.Calibration.Records.Records[0].Poly.PolynomialSensitivity;
break;
case NonLinearStyles.IRTraccDiagnosticsZero:
break;
case NonLinearStyles.IRTraccZeroMMmV:
break;
}
}
else
{
SensorSensitivity = sd.Calibration.Records.Records[0].Sensitivity;
}
SensorSerialNumber = sd.SerialNumber;
SquibFireCurrent = sd.SquibOutputCurrent;
SquibFireDelayMs = sd.SquibFireDelayMS;
SquibFireDurationMs = sd.SquibFireDurationMS;
SquibFireMode = sd.SquibFireMode;
SquibFireResistanceHighOhm = sd.SquibToleranceHigh;
SquibFireResistanceLowOhm = sd.SquibToleranceLow;
DigitalOutputMode = sd.DigitalOutputMode;
DigitalInputMode = sd.InputMode;
DigitalOutputDelay = sd.DigitalOutputDelayMS;
DigitalOutputDuration = sd.DigitalOutputDurationMS;
LimitDuration = sd.LimitDuration;
//Latest info from Takashi
switch (sd.Calibration.ZeroMethods.Methods[0].Method)
{
case ZeroMethodType.None: ZeroMethod = ToyotaZeroMethods.None; break;
case ZeroMethodType.AverageOverTime: ZeroMethod = ToyotaZeroMethods.AverageOverTime; break;
case ZeroMethodType.UsePreEventDiagnosticsZero: ZeroMethod = ToyotaZeroMethods.UsePreEventDiagnosticsZero; break;
}
IsChannelCodeValid = !string.IsNullOrWhiteSpace(ChannelCode) && ChannelCode != NONE;
}
public ITTSChannelRecord Copy()
{
return (TTSChannelRecord)MemberwiseClone();
}
public bool OriginallyRequestedChannel { get; set; }
public bool IsModified { get; set; }
public byte[] GetBytes()
{
var bytes = new List<byte>();
bytes.AddRange(BitConverter.GetBytes(ChannelNumber));
bytes.AddRange(System.Text.Encoding.UTF8.GetBytes(ChannelCode ?? ""));
bytes.AddRange(System.Text.Encoding.UTF8.GetBytes(JCodeOrDescription ?? ""));
bytes.AddRange(BitConverter.GetBytes(ChannelRange));
bytes.AddRange(BitConverter.GetBytes(ChannelFilterHz));
bytes.AddRange(System.Text.Encoding.UTF8.GetBytes(SensorEID ?? ""));
bytes.AddRange(System.Text.Encoding.UTF8.GetBytes(SensorSerialNumber ?? ""));
bytes.AddRange(BitConverter.GetBytes(SensorSensitivity));
bytes.AddRange(BitConverter.GetBytes(SensorExcitationVolts));
bytes.AddRange(BitConverter.GetBytes(SensorCapacity));
bytes.AddRange(System.Text.Encoding.UTF8.GetBytes(SensorEU ?? ""));
bytes.AddRange(BitConverter.GetBytes(SensorPolarity));
bytes.AddRange(BitConverter.GetBytes((int)ChannelType));
bytes.AddRange(System.Text.Encoding.UTF8.GetBytes(Description ?? ""));
bytes.AddRange(BitConverter.GetBytes(ProportionalToExcitation));
bytes.AddRange(BitConverter.GetBytes(BridgeResistance));
bytes.AddRange(BitConverter.GetBytes(InitialOffsetVoltage));
bytes.AddRange(BitConverter.GetBytes(InitialOffsetVoltageTolerance));
bytes.AddRange(BitConverter.GetBytes(RemoveOffset));
bytes.AddRange(BitConverter.GetBytes((int)ZeroMethod));
bytes.AddRange(BitConverter.GetBytes(Disabled));
if (IsSquib)
{
bytes.AddRange(BitConverter.GetBytes((int)SquibFireMode));
bytes.AddRange(BitConverter.GetBytes(SquibFireDelayMs));
bytes.AddRange(BitConverter.GetBytes(LimitDuration));
if (LimitDuration)
{
bytes.AddRange(BitConverter.GetBytes(SquibFireDurationMs));
}
bytes.AddRange(BitConverter.GetBytes(SquibFireCurrent));
bytes.AddRange(BitConverter.GetBytes(SquibFireResistanceLowOhm));
bytes.AddRange(BitConverter.GetBytes(SquibFireResistanceHighOhm));
}
if (IsDigitalInput)
{
bytes.AddRange(BitConverter.GetBytes((int)DigitalInputMode));
}
if (!IsDigitalOutput) return bytes.ToArray();
bytes.AddRange(BitConverter.GetBytes((int)DigitalOutputMode));
bytes.AddRange(BitConverter.GetBytes(DigitalOutputDelay));
bytes.AddRange(BitConverter.GetBytes(DigitalOutputDuration));
return bytes.ToArray();
}
}
}

View File

@@ -0,0 +1,325 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTS.Common.Base;
using DTS.Common.Interface.TestSetups.Imports.TTS.LevelTrigger;
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
using DTS.Common.Utilities.Logging;
namespace TTSImport.Model
{
/// <summary>
/// this class represents a level trigger for TTS
/// for a level trigger you need a sensor and a hardware channel
/// the role of the sensor is fulfulled by a ITTSChannelRecord for TTS level triggers
/// </summary>
public class TTSLevelTriggerRecord : BasePropertyChanged, ILevelTrigger
{
#region properties
/// <summary>
/// the channel code of the channel record this level trigger applies to (if any)
/// </summary>
public string Code => Channel?.ChannelCode ?? "";
/// <summary>
/// the JCODE of the channel record associated with this level trigger (if any)
/// </summary>
public string JCode => Channel?.JCodeOrDescription ?? "";
/// <summary>
/// the level trigger is expressed in EU, but the UI
/// lets you convert between a % of full scale and an explicit EU value
/// </summary>
private double _valuePercent;
public double ValuePercent
{
get => _valuePercent;
set
{
_valuePercent = value;
IsModified = true;
RecalculateEUValue();
}
}
/// <summary>
/// the EU threshold for the level trigger
/// </summary>
private double _valueEU = 0D;
public double ValueEU
{
get => _valueEU;
set
{
_valueEU = value;
IsModified = true;
RecalculatePercent();
}
}
/// <summary>
/// the engineering units for the sensor associated with the level trigger (if any)
/// </summary>
public string EULabel => Channel?.SensorEU ?? "";
/// <summary>
/// the display string of the hardware channel associated with the level trigger (if any)
/// </summary>
public string HWSerialNumber => Channel?.HardwareChannel?.ToString() ?? "";
/// <summary>
/// the TTS channel number of the channel associated with the sensor associated with this level trigger (if any)
/// </summary>
public int ChannelNumber => Channel?.ChannelNumber ?? 0;
/// <summary>
/// the TTS channel record associated with this physical channel (if any)
/// </summary>
private ITTSChannelRecord _channel;
public ITTSChannelRecord Channel
{
get => _channel;
set
{
_channel = value;
IsModified = true;
OnPropertyChanged("Code");
OnPropertyChanged("JCode");
OnPropertyChanged("EULabel");
OnPropertyChanged("HWSerialNumber");
OnPropertyChanged("ChannelNumber");
OnPropertyChanged("IsActive");
//we've just set this level trigger, which potentially affects other level triggers
//it might be sufficient to just raise the available channels notification, but
//the refresh method will do that
foreach (var lt in TestSetup.LevelTriggers)
{
if (lt == this) { continue; }
lt.Refresh();
}
}
}
private const int MAX_G5_LEVELTRIGGER = 2;
/// <summary>
/// the test setup from which all channels come
/// and to which the level trigger itself is associated with
/// </summary>
public ITTSSetup TestSetup { get; }
/// <summary>
/// available channels/sensors that could be chosen to associate this level trigger with
/// requires that channel has a channel code and an associated physical hardware channel
/// already
/// </summary>
public ITTSChannelRecord[] AvailableChannels
{
get
{
//we want to make sure no code is reused
//and we want to make sure no sim is reused
var existingCodesHash = new HashSet<string>();
var existingSIMs = new HashSet<string>();
//make sure only 2 per G5
//g5 serial to level trigger count
var existingG5 = new Dictionary<string, int>();
foreach (var lt in TestSetup.LevelTriggers)
{
if (lt == this)
{
continue;
}
if (null == lt.Channel) continue;
existingCodesHash.Add(lt.Channel.ChannelCode);
if (null == lt.Channel.HardwareChannel) continue;
if (lt.Channel.HardwareChannel.GetParentDAS().IsTDASRack())
{
existingSIMs.Add(lt.Channel.HardwareChannel.ModuleSerialNumber);
}
else if (lt.Channel.HardwareChannel.GetParentDAS().IsG5())
{
var key = lt.Channel.HardwareChannel.GetParentDAS().SerialNumber;
if (!existingG5.ContainsKey(key))
{
existingG5[key] = 1;
}
else
{
existingG5[key] = existingG5[key] + 1;
}
}
}
var channels = new List<ITTSChannelRecord> { new TTSChannelRecord() };
if (null == TestSetup) return channels.ToArray();
foreach (var ch in TestSetup.Channels)
{
if (ch.Disabled) { continue; }
if (ch.IsEmptyRecord)
{
channels.Add(ch);
}
else if (null != ch.HardwareChannel)
{
//Digital Input channels must be initialized to either the default in the config file, or CCNO if a G5
if (ch.IsDigitalInput)
{
ch.DigitalInputMode = DTS.Common.Enums.DigitalInputModes.CCNO;
}
if (ch.IsDigitalInput || ch.IsDigitalOutput || ch.IsSquib) { continue; }
//only allow analog linear sensors
switch (ch.ChannelType)
{
case DTS.Common.Enums.TTS.ToyotaBridgeType.FullBridge:
case DTS.Common.Enums.TTS.ToyotaBridgeType.HalfBridge:
case DTS.Common.Enums.TTS.ToyotaBridgeType.Voltage:
case DTS.Common.Enums.TTS.ToyotaBridgeType.PotentionmeterFullBridge:
case DTS.Common.Enums.TTS.ToyotaBridgeType.PotentionmeterHalfBridge:
break;
//full bridge, half bridge are allowed, everything else ignore
default:
continue;
}
if (existingCodesHash.Contains(ch.ChannelCode)) { continue; }
if (existingSIMs.Contains(ch.HardwareChannel.ModuleSerialNumber))
{
continue;
}
if (ch.HardwareChannel.GetParentDAS().IsG5())
{
var key = ch.HardwareChannel.GetParentDAS().SerialNumber;
if (existingG5.ContainsKey(key))
{
if (existingG5[key] >= MAX_G5_LEVELTRIGGER)
{
continue;
}
}
}
channels.Add(ch);
}
}
return channels.ToArray();
}
}
/// <summary>
/// returns true if there's an associated sensor and physical hardware channel for this level trigger
/// </summary>
public bool IsActive
{
get
{
if (null == Channel)
{
return false;
}
return !Channel.IsEmptyRecord;
}
}
public bool IsModified { get; set; }
#endregion
#region methods
public byte[] GetBytes()
{
var bytes = new List<byte>();
if (!IsActive) return bytes.ToArray();
bytes.AddRange(Encoding.UTF8.GetBytes(Code ?? ""));
bytes.AddRange(Encoding.UTF8.GetBytes(JCode ?? ""));
bytes.AddRange(BitConverter.GetBytes(ValueEU));
bytes.AddRange(Encoding.UTF8.GetBytes(HWSerialNumber ?? ""));
return bytes.ToArray();
}
/// <summary>
/// recalculates the EU threshold based on the current percentage of full scale threshold
/// </summary>
private void RecalculateEUValue()
{
if (null != Channel)
{
_valueEU = ValuePercent / 100D * Channel.ChannelRange;
OnPropertyChanged("ValueEU");
}
}
/// <summary>
/// recalculates the threshold as a % of full scale based on current EU threshold
/// </summary>
private void RecalculatePercent()
{
if (null != Channel)
{
_valuePercent = 100D * ValueEU / Channel.ChannelRange;
OnPropertyChanged("ValuePercent");
}
}
public override string ToString()
{
return Code;
}
private volatile bool _bInRefresh = false;
/// <summary>
/// refreshes what the available channels are
/// </summary>
public void Refresh()
{
try
{
if (_bInRefresh) { return; }
_bInRefresh = true;
var channels = AvailableChannels;
OnPropertyChanged("AvailableChannels");
//if there's a channel assigned make sure it's an available channel ...
//if not then reverse the channel assignment
//this might happen if the user removed the hardware assignment
if (null == Channel)
{
return;
}
var matches = from ch in channels where ch == Channel select ch;
if (matches.Any()) return;
var match = (from ch in channels where ch.ChannelCode == Channel.ChannelCode select ch).FirstOrDefault();
if (null != match)
{
Channel = match;
return;
}
Channel = null;
}
catch (Exception ex)
{
APILogger.Log(ex);
}
finally { _bInRefresh = false; }
}
/// <inheritdoc />
/// <summary>
/// adds the channel as a possible channel for level trigger
/// </summary>
/// <param name="channel"></param>
public void Add(ITTSChannelRecord channel)
{
OnPropertyChanged("AvailableChannels");
}
/// <inheritdoc />
/// <summary>
/// removes the channel as a possible channel for level trigger,
/// unassigns channel if currently assigned
/// </summary>
/// <param name="channel"></param>
public void Remove(ITTSChannelRecord channel)
{
if (Channel != channel) return;
Channel = null;
OnPropertyChanged("AvailableChannels");
}
#endregion
#region constructors
public TTSLevelTriggerRecord(ITTSSetup setup)
{
TestSetup = setup;
}
#endregion
}
}

View File

@@ -0,0 +1,105 @@
using System;
using DTS.Common.Enums;
using DTS.Common.Interface.TestSetups.Imports.TTS.LevelTrigger;
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Text;
using DTS.Common.Interface.Sensors;
namespace TTSImport.Model
{
public class TTSTestSetup : ITTSSetup
{
public double SampleRate { get; set; }
public RecordingModes Mode { get; set; }
public double TestLength => PreTrigger + PostTrigger;
public double PreTrigger { get; set; }
public double PostTrigger { get; set; }
public double ROIStart { get; set; }
public double ROIEnd { get; set; }
public string Filename { get; set; }
public string TestId { get; set; }
/// <summary>
/// The first 4 lines of the .csv file are needed if a new .csv is to be created
/// </summary>
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
public string Line4 { get; set; }
public string[] DummyList { get; set; }
public ITTSChannelRecord[] Channels { get; set; }
public ILevelTrigger[] LevelTriggers { get; set; }
public string OriginalImportFile { get; set; }
/// <summary>
/// If True, HybridRecorder is added to CircularBuffer and Recorder as choices.
/// </summary>
public bool AllowAdvancedRecordingModes { get; set; }
/// <summary>
/// if True, Active Ram and Active Ram Multiple events are valid modes
/// http://manuscript.dts.local/f/cases/31841/Add-support-for-Active-RAM-mode
/// </summary>
public bool AllowActiveRecordingModes { get; set; }
public bool AllowTSRAIRRecordingModes { get; set; }
/// <inheritdoc />
/// <summary>
/// allows consumers to specify whether EIDs must be found for sensors to be used
/// </summary>
public bool RequireEIDFound { get; set; }
/// <summary>
/// The value from DataPRO.config.exe
/// </summary>
public string DefaultDigitalInputMode { get; set; }
public ISquibSettingDefaults SquibDefaults { get; set; }
/// <summary>
/// The value from DataPRO.config.exe
/// </summary>
public double DefaultSquibFireDurationMs { get; set; }
/// <summary>
/// this holds sensor to hardware assignments that are pre-existing before the user even scans hardware
/// this can only happen through the XML import
/// the assignments are removed once they are made, but persist across hardware scans until they are made (for instance if the hardware
/// is not present in the first hardwarescan the assignments will remain till the hardware is found).
/// this is not true if the user has already manually assigned the channel
/// </summary>
public Tuple<string, string>[] PreAssignedSensorIdAndHwId { get; set; }
private const int NUM_LEVEL_TRIGGERS = 6;
public TTSTestSetup()
{
DummyList = new string[8];
Channels = new ITTSChannelRecord[0];
LevelTriggers = new ILevelTrigger[NUM_LEVEL_TRIGGERS];
for (var i = 0; i < NUM_LEVEL_TRIGGERS; i++)
{
LevelTriggers[i] = new TTSLevelTriggerRecord(this);
}
}
public new string GetHashCode()
{
var bytes = new List<byte>();
bytes.AddRange(BitConverter.GetBytes(SampleRate));
bytes.AddRange(BitConverter.GetBytes((int)Mode));
bytes.AddRange(BitConverter.GetBytes(PreTrigger));
bytes.AddRange(BitConverter.GetBytes(PostTrigger));
bytes.AddRange(BitConverter.GetBytes(ROIStart));
bytes.AddRange(BitConverter.GetBytes(ROIEnd));
bytes.AddRange(Encoding.UTF8.GetBytes(TestId ?? ""));
foreach (var ch in Channels)
{
bytes.AddRange(ch.GetBytes());
}
foreach (var lt in LevelTriggers)
{
bytes.AddRange(lt.GetBytes());
}
var sha = new SHA256Managed();
var hash = sha.ComputeHash(bytes.ToArray());
var hashString = BitConverter.ToString(hash).Replace("-", string.Empty);
return hashString;
}
}
}

View File

@@ -0,0 +1,16 @@
using System.Threading;
namespace TTSImport.Model
{
public class WorkFunctionThreadData
{
public ManualResetEvent CancelEvent { get; }
public ManualResetEvent DoneEvent { get; }
public WorkFunctionThreadData()
{
CancelEvent = new ManualResetEvent(false);
DoneEvent = new ManualResetEvent(false);
}
}
}