init
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user