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