init
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,491 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using DTS.Common.Events;
|
||||
using DTS.Common.Events.TTSImport;
|
||||
using DTS.Common.Interface.DataRecorders;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
|
||||
using Prism.Events;
|
||||
using Unity;
|
||||
using DTS.Common.Interactivity;
|
||||
using Prism.Regions;
|
||||
using Prism.Commands;
|
||||
using TTSImport.Model;
|
||||
using TTSImport.Resources;
|
||||
using DTS.DASLib.Service;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// this class handles Level Trigger edit/create functionality
|
||||
/// </summary>
|
||||
[PartCreationPolicy(CreationPolicy.Shared)]
|
||||
public class TOMChannelsViewModel : ITOMChannelsViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The Hardware Scan view
|
||||
/// </summary>
|
||||
public ITOMChannelsView View { get; set; }
|
||||
|
||||
private IEventAggregator _eventAggregator { get; }
|
||||
private IRegionManager _regionManager;
|
||||
private IUnityContainer UnityContainer { get; }
|
||||
|
||||
public InteractionRequest<Notification> NotificationRequest { get; }
|
||||
public InteractionRequest<Confirmation> ConfirmationRequest { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the TechnologyDomainEditViewModel.
|
||||
/// </summary>
|
||||
/// <param name="view">The ITOMChannelsView.</param>
|
||||
/// <param name="regionManager">The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed.</param>
|
||||
/// <param name="eventAggregator">The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other.</param>
|
||||
/// <param name="unityContainer">The unityContainer.</param>
|
||||
public TOMChannelsViewModel(ITOMChannelsView view, IRegionManager regionManager,
|
||||
IEventAggregator eventAggregator, IUnityContainer unityContainer)
|
||||
{
|
||||
View = view;
|
||||
View.DataContext = this;
|
||||
|
||||
NotificationRequest = new InteractionRequest<Notification>();
|
||||
ConfirmationRequest = new InteractionRequest<Confirmation>();
|
||||
|
||||
_eventAggregator = eventAggregator;
|
||||
UnityContainer = unityContainer;
|
||||
_regionManager = regionManager;
|
||||
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
|
||||
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>()
|
||||
.Subscribe(OnBusyIndicatorNotification, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<AssignedChannelsChangedEvent>().Subscribe(OnAssignedChannelsChangedEvent,
|
||||
ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportHardwareScanFinishedEvent>()
|
||||
.Subscribe(OnHardwareScanComplete, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportReadFileStatusEvent>().Subscribe(OnReadFileFinished, ThreadOption.PublisherThread, true);
|
||||
}
|
||||
|
||||
#region Methods
|
||||
private void OnReadFileFinished(ReadFileStatusArg statusArg)
|
||||
{
|
||||
_setup = statusArg.TTSSetup;
|
||||
_hardware = null;
|
||||
}
|
||||
private void OnHardwareScanComplete(List<IDASHardware> hardware)
|
||||
{
|
||||
_hardware = hardware;
|
||||
}
|
||||
|
||||
private void OnAssignedChannelsChangedEvent(ITTSSetup setup)
|
||||
{
|
||||
if (!Application.Current.Dispatcher.CheckAccess())
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
OnAssignedChannelsChangedEvent(setup);
|
||||
}));
|
||||
return;
|
||||
}
|
||||
_setup = setup;
|
||||
if (null == _hardware || null == _setup) { return; }
|
||||
var channels = new ObservableCollection<Model.DASChannel>();
|
||||
var remainingChannels = new ObservableCollection<ITTSChannelRecord>();
|
||||
var channelIdToChannel = new Dictionary<string, Model.DASChannel>();
|
||||
foreach (var das in _hardware)
|
||||
{
|
||||
var ichannels = das.GetIHardwareChannels();
|
||||
for (var i = 0; i < ichannels.Length; i += 2)
|
||||
{
|
||||
var ch = ichannels[i];
|
||||
if (!ch.IsSquib) { continue; }
|
||||
var newChannel = new Model.DASChannel(ch);
|
||||
channels.Add(newChannel);
|
||||
channelIdToChannel[ch.GetId()] = newChannel;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var channelRecord in _setup.Channels)
|
||||
{
|
||||
if (channelRecord.IsEmptyRecord)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!channelRecord.IsSquib)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!channelRecord.IsChannelCodeValid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (channelRecord.ChannelCode == TTSChannelRecord.NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (null != channelRecord.HardwareChannel)
|
||||
{
|
||||
if (channelIdToChannel.ContainsKey(channelRecord.HardwareChannel.GetId()))
|
||||
{
|
||||
channelIdToChannel[channelRecord.HardwareChannel.GetId()].SetITTSChannelRecord(channelRecord);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
remainingChannels.Add(channelRecord);
|
||||
}
|
||||
}
|
||||
|
||||
DASChannels = channels;
|
||||
RemainingChannels = remainingChannels;
|
||||
OnPropertyChanged("DASChannels");
|
||||
OnPropertyChanged("RemainingChannels");
|
||||
}
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
public Task CleanupAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter)
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter, object model)
|
||||
{
|
||||
}
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task InitializeAsync(object parameter)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Activated()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnBusyIndicatorNotification(bool eventArg)
|
||||
{
|
||||
IsBusy = eventArg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
|
||||
{
|
||||
// The NotificationRequest.Raise triggers the Invoke() method of the PopupWindowAction object to show the NotificationWindow window
|
||||
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
|
||||
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, "",
|
||||
eventArgsWithTitle.Image, string.Empty);
|
||||
|
||||
NotificationRequest.Raise(new Notification
|
||||
{
|
||||
Content = eventArgsWithoutTitle,
|
||||
Title = eventArgsWithTitle.Title
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
private ITTSSetup _setup;
|
||||
private IList<IDASHardware> _hardware;
|
||||
public bool IsDirty { get; private set; }
|
||||
private bool _isBusy;
|
||||
|
||||
public bool IsBusy
|
||||
{
|
||||
get => _isBusy;
|
||||
set
|
||||
{
|
||||
_isBusy = value;
|
||||
OnPropertyChanged("IsBusy");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isMenuIncluded;
|
||||
|
||||
public bool IsMenuIncluded
|
||||
{
|
||||
get => _isMenuIncluded;
|
||||
set
|
||||
{
|
||||
_isMenuIncluded = value;
|
||||
OnPropertyChanged("IsMenuIncluded");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isNavigationIncluded;
|
||||
|
||||
public bool IsNavigationIncluded
|
||||
{
|
||||
get => _isNavigationIncluded;
|
||||
set
|
||||
{
|
||||
_isNavigationIncluded = value;
|
||||
OnPropertyChanged("IsNavigationIncluded");
|
||||
}
|
||||
}
|
||||
public bool AssignEnabled { get; set; }
|
||||
public bool RemoveEnabled { get; set; }
|
||||
public bool EnableOrDisableEnabled { get; set; }
|
||||
public ObservableCollection<Model.DASChannel> DASChannels { get; set; } = new ObservableCollection<Model.DASChannel>();
|
||||
public ObservableCollection<ITTSChannelRecord> RemainingChannels { get; set; } =
|
||||
new ObservableCollection<ITTSChannelRecord>();
|
||||
|
||||
private ITTSChannelRecord _selectedRemainingChannel;
|
||||
public ITTSChannelRecord SelectedRemainingChannel
|
||||
{
|
||||
get => _selectedRemainingChannel;
|
||||
set
|
||||
{
|
||||
_selectedRemainingChannel = value;
|
||||
if (null == _selectedRemainingChannel || null == SelectedDASChannel) return;
|
||||
AssignEnabled = true;
|
||||
OnPropertyChanged("AssignEnabled");
|
||||
}
|
||||
}
|
||||
private void DetermineRemoveEnableStatus()
|
||||
{
|
||||
if (_selectedDASChannel?.Channel != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(_selectedDASChannel.EID) &&
|
||||
_selectedDASChannel.EID == _selectedDASChannel.Channel.SensorEID)
|
||||
{
|
||||
//can only be replaced, can't be removed
|
||||
RemoveEnabled = false;
|
||||
}
|
||||
RemoveEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveEnabled = false;
|
||||
}
|
||||
OnPropertyChanged("RemoveEnabled");
|
||||
AssignEnabled = null != _selectedDASChannel && null != _selectedRemainingChannel;
|
||||
OnPropertyChanged("AssignEnabled");
|
||||
EnableOrDisableEnabled = _selectedDASChannel?.Channel != null;
|
||||
OnPropertyChanged("EnableOrDisableEnabled");
|
||||
OnPropertyChanged("EnableOrDisableText");
|
||||
}
|
||||
private Model.DASChannel _selectedDASChannel;
|
||||
public Model.DASChannel SelectedDASChannel
|
||||
{
|
||||
get => _selectedDASChannel;
|
||||
set
|
||||
{
|
||||
_selectedDASChannel = value;
|
||||
DetermineRemoveEnableStatus();
|
||||
}
|
||||
}
|
||||
|
||||
public string EnableOrDisableText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SelectedDASChannel?.Channel == null)
|
||||
{
|
||||
return StringResources.Analog_Enable;
|
||||
}
|
||||
return SelectedDASChannel.Channel.Disabled
|
||||
? StringResources.Analog_Enable
|
||||
: StringResources.Analog_Disable;
|
||||
}
|
||||
}
|
||||
#endregion Properties
|
||||
|
||||
#region Commands
|
||||
#region assign
|
||||
/// <summary>
|
||||
/// Assign a channel code to a channel
|
||||
/// </summary>
|
||||
private DelegateCommand _assignCommand;
|
||||
public DelegateCommand AssignCommand => _assignCommand ?? (_assignCommand = new DelegateCommand(Assign));
|
||||
private void Assign()
|
||||
{
|
||||
if (SelectedRemainingChannel == null) { return; }
|
||||
|
||||
_eventAggregator.GetEvent<TTSImportTestSetupChangedEvent>().Publish(_setup);
|
||||
//BEFORE we go any further, check the state of sensor ids
|
||||
//if the channel has a sensor id AND there's a sensor on the channel with the same id
|
||||
//then prompt on replacing the id
|
||||
//IF the channel has a sensor id and there's no sensor on the channel BUT the new sensor has a different id
|
||||
//then prompt on replacing the id
|
||||
var bReplacingID = false;
|
||||
if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID))
|
||||
{
|
||||
if (null != SelectedRemainingChannel && SelectedRemainingChannel.SensorEID != SelectedDASChannel.EID)
|
||||
{
|
||||
bReplacingID = true;
|
||||
}
|
||||
//if existing channel has this ID, we will need to clear out the old id and assign a new one...
|
||||
if (null != SelectedDASChannel.Channel && SelectedDASChannel.Channel.SensorEID == SelectedDASChannel.EID)
|
||||
{
|
||||
bReplacingID = true;
|
||||
}
|
||||
}
|
||||
if (bReplacingID)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
var dialogResult = MessageBox.Show(StringResources.AssignSensorPrompt, StringResources.UserFeedbackRequired, MessageBoxButton.YesNo);
|
||||
if (dialogResult == MessageBoxResult.Yes)
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(AssignWork));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
AssignWork();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// assigns a channel record to a physical channel
|
||||
/// </summary>
|
||||
private void AssignWork()
|
||||
{
|
||||
if (null != SelectedDASChannel.Channel)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID))
|
||||
{
|
||||
SelectedDASChannel.Channel.SensorEID = "";
|
||||
}
|
||||
RemainingChannels.Add(SelectedDASChannel.Channel);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID))
|
||||
{
|
||||
SelectedRemainingChannel.SensorEID = SelectedDASChannel.EID;
|
||||
}
|
||||
|
||||
SelectedDASChannel.SetITTSChannelRecord(SelectedRemainingChannel);
|
||||
|
||||
var channel = SelectedRemainingChannel;
|
||||
var index = RemainingChannels.IndexOf(channel);
|
||||
SelectedRemainingChannel = null;
|
||||
RemainingChannels.Remove(channel);
|
||||
if (index < RemainingChannels.Count)
|
||||
{
|
||||
SelectedRemainingChannel = RemainingChannels[index];
|
||||
OnPropertyChanged("SelectedRemainingChannel");
|
||||
}
|
||||
else if (RemainingChannels.Count > 0)
|
||||
{
|
||||
SelectedRemainingChannel = RemainingChannels[index - 1];
|
||||
OnPropertyChanged("SelectedRemainingChannel");
|
||||
}
|
||||
CollectionViewSource.GetDefaultView(DASChannels)?.Refresh();
|
||||
index = DASChannels.IndexOf(SelectedDASChannel);
|
||||
for (var i = index; i < DASChannels.Count; i++)
|
||||
{
|
||||
var dasChannel = DASChannels[i];
|
||||
if (null != dasChannel.Channel) { continue; }
|
||||
SelectedDASChannel = dasChannel;
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
//didn't find a match, start from the beginning?
|
||||
for (var i = 0; i < index; i++)
|
||||
{
|
||||
var dasChannel = DASChannels[i];
|
||||
if (null != dasChannel.Channel)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
SelectedDASChannel = dasChannel;
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
//if we get here there's no new channel to go to, but we need to set the remove/enable/disable button status
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
DetermineRemoveEnableStatus();
|
||||
}
|
||||
#endregion
|
||||
#region remove
|
||||
private DelegateCommand _removeCommand;
|
||||
public DelegateCommand RemoveCommand => _removeCommand ?? (_removeCommand = new DelegateCommand(Remove));
|
||||
/// <summary>
|
||||
/// remove a hardware channel assignment (does not remove the channel from the test setup though?)
|
||||
/// </summary>
|
||||
private void Remove()
|
||||
{
|
||||
if (null == SelectedDASChannel || null == SelectedDASChannel.Channel) { return; }
|
||||
_eventAggregator.GetEvent<TTSImportTestSetupChangedEvent>().Publish(_setup);
|
||||
RemainingChannels.Add(SelectedDASChannel.Channel);
|
||||
SelectedDASChannel.SetITTSChannelRecord(null);
|
||||
CollectionViewSource.GetDefaultView(DASChannels)?.Refresh();
|
||||
var index = DASChannels.IndexOf(SelectedDASChannel);
|
||||
for (var i = index; i < DASChannels.Count; i++)
|
||||
{
|
||||
if (null == DASChannels[i].Channel) { continue; }
|
||||
SelectedDASChannel = DASChannels[i];
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < index; i++)
|
||||
{
|
||||
if (null == DASChannels[i].Channel) { continue; }
|
||||
SelectedDASChannel = DASChannels[i];
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
//if we get here there's no new channel to go to, but we need to set the remove/enable/disable button status
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
DetermineRemoveEnableStatus();
|
||||
}
|
||||
#endregion
|
||||
#region enableordisable
|
||||
private DelegateCommand _enableOrDisableCommand;
|
||||
public DelegateCommand EnableOrDisableCommand =>
|
||||
_enableOrDisableCommand ?? (_enableOrDisableCommand = new DelegateCommand(EnableOrDisable));
|
||||
/// <summary>
|
||||
/// enables or disables a channel in the test.
|
||||
/// </summary>
|
||||
private void EnableOrDisable()
|
||||
{
|
||||
if (SelectedDASChannel?.Channel == null) { return; }
|
||||
SelectedDASChannel.Channel.Disabled = !SelectedDASChannel.Channel.Disabled;
|
||||
SelectedDASChannel.Disabled = SelectedDASChannel.Channel.Disabled;
|
||||
|
||||
OnPropertyChanged("EnableOrDisableText");
|
||||
_eventAggregator.GetEvent<TTSImportTestSetupChangedEvent>().Publish(_setup);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Occurs when a property value changes.
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,438 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Added" xml:space="preserve">
|
||||
<value>Added</value>
|
||||
</data>
|
||||
<data name="Analog_Assign" xml:space="preserve">
|
||||
<value>適用</value>
|
||||
</data>
|
||||
<data name="Analog_Disable" xml:space="preserve">
|
||||
<value>無効</value>
|
||||
</data>
|
||||
<data name="Analog_Enable" xml:space="preserve">
|
||||
<value>有効</value>
|
||||
</data>
|
||||
<data name="Analog_Remove" xml:space="preserve">
|
||||
<value>削除</value>
|
||||
</data>
|
||||
<data name="Assigned" xml:space="preserve">
|
||||
<value>アサイン</value>
|
||||
</data>
|
||||
<data name="BatteryVoltageStatusColumn" xml:space="preserve">
|
||||
<value>バッテリーステータス</value>
|
||||
</data>
|
||||
<data name="Browse" xml:space="preserve">
|
||||
<value>フォルダの参照</value>
|
||||
</data>
|
||||
<data name="CableMultiplier" xml:space="preserve">
|
||||
<value>ケーブル長補正</value>
|
||||
</data>
|
||||
<data name="Capacity" xml:space="preserve">
|
||||
<value>定格容量</value>
|
||||
</data>
|
||||
<data name="CHAN" xml:space="preserve">
|
||||
<value>DAS CH</value>
|
||||
</data>
|
||||
<data name="ChannelType" xml:space="preserve">
|
||||
<value>CH 種類</value>
|
||||
</data>
|
||||
<data name="Channel_Summary" xml:space="preserve">
|
||||
<value>チャンネル 一覧</value>
|
||||
</data>
|
||||
<data name="Code" xml:space="preserve">
|
||||
<value>CH名</value>
|
||||
</data>
|
||||
<data name="DASChannel" xml:space="preserve">
|
||||
<value>DAS CH</value>
|
||||
</data>
|
||||
<data name="DASChannels" xml:space="preserve">
|
||||
<value>DAS チャンネル</value>
|
||||
</data>
|
||||
<data name="DASSerial" xml:space="preserve">
|
||||
<value>DAS シリアル番号</value>
|
||||
</data>
|
||||
<data name="DAS_Summary" xml:space="preserve">
|
||||
<value>DAS 一覧</value>
|
||||
</data>
|
||||
<data name="EID" xml:space="preserve">
|
||||
<value>EID</value>
|
||||
</data>
|
||||
<data name="EIDFound" xml:space="preserve">
|
||||
<value>EID 数</value>
|
||||
</data>
|
||||
<data name="EULabel" xml:space="preserve">
|
||||
<value>単位</value>
|
||||
</data>
|
||||
<data name="HWSerialNumber" xml:space="preserve">
|
||||
<value>HW SN</value>
|
||||
</data>
|
||||
<data name="Import" xml:space="preserve">
|
||||
<value>xml 保存</value>
|
||||
</data>
|
||||
<data name="ImportFile" xml:space="preserve">
|
||||
<value>入力ファイルの選択</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_PossibleStatus_Done" xml:space="preserve">
|
||||
<value>完了</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_PossibleStatus_Failed" xml:space="preserve">
|
||||
<value>Failed</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_PossibleStatus_Working" xml:space="preserve">
|
||||
<value>処理中</value>
|
||||
</data>
|
||||
<data name="InputVoltageStatusColumn" xml:space="preserve">
|
||||
<value>入力電圧ステータス</value>
|
||||
</data>
|
||||
<data name="JCode" xml:space="preserve">
|
||||
<value>センサー詳細</value>
|
||||
</data>
|
||||
<data name="Mode" xml:space="preserve">
|
||||
<value>モード</value>
|
||||
</data>
|
||||
<data name="Name" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="NONE" xml:space="preserve">
|
||||
<value>-----</value>
|
||||
</data>
|
||||
<data name="Polarity" xml:space="preserve">
|
||||
<value>±</value>
|
||||
</data>
|
||||
<data name="PostTrigger" xml:space="preserve">
|
||||
<value>トリガー後 (sec)</value>
|
||||
</data>
|
||||
<data name="PreTrigger" xml:space="preserve">
|
||||
<value>トリガー前 (sec)</value>
|
||||
</data>
|
||||
<data name="Range" xml:space="preserve">
|
||||
<value>要求レンジ</value>
|
||||
</data>
|
||||
<data name="RemainingChannels" xml:space="preserve">
|
||||
<value>未処理チャンネル</value>
|
||||
</data>
|
||||
<data name="Requested" xml:space="preserve">
|
||||
<value>要求チャンネル</value>
|
||||
</data>
|
||||
<data name="RunTest" xml:space="preserve">
|
||||
<value>試験実施</value>
|
||||
</data>
|
||||
<data name="SampleRate" xml:space="preserve">
|
||||
<value>サンプル周波数 (per sec)</value>
|
||||
</data>
|
||||
<data name="Sens" xml:space="preserve">
|
||||
<value>校正値</value>
|
||||
</data>
|
||||
<data name="SensorSN" xml:space="preserve">
|
||||
<value>センサー SN</value>
|
||||
</data>
|
||||
<data name="SerialNumber" xml:space="preserve">
|
||||
<value>センサー SN</value>
|
||||
</data>
|
||||
<data name="TestLength" xml:space="preserve">
|
||||
<value>試験時間 (sec)</value>
|
||||
</data>
|
||||
<data name="TestSetupName" xml:space="preserve">
|
||||
<value>テストセットアップ名:</value>
|
||||
</data>
|
||||
<data name="ToyotaCode" xml:space="preserve">
|
||||
<value>Toyota Code</value>
|
||||
</data>
|
||||
<data name="Type" xml:space="preserve">
|
||||
<value>CH 種類</value>
|
||||
</data>
|
||||
<data name="Unassigned" xml:space="preserve">
|
||||
<value>未アサイン</value>
|
||||
</data>
|
||||
<data name="ValueEU" xml:space="preserve">
|
||||
<value>VAL (EU)</value>
|
||||
</data>
|
||||
<data name="ValuePercent" xml:space="preserve">
|
||||
<value>VAL (%)</value>
|
||||
</data>
|
||||
<data name="AssignSensorPrompt" xml:space="preserve">
|
||||
<value>Assign sensor? ID on the channel will be applied to the sensor and removed from any other sensors.</value>
|
||||
</data>
|
||||
<data name="UserFeedbackRequired" xml:space="preserve">
|
||||
<value>User feedback required</value>
|
||||
</data>
|
||||
<data name="Current" xml:space="preserve">
|
||||
<value>電流 (amp)</value>
|
||||
</data>
|
||||
<data name="Delay" xml:space="preserve">
|
||||
<value>遅延時間 (ms)</value>
|
||||
</data>
|
||||
<data name="Duration" xml:space="preserve">
|
||||
<value>持続時間 (ms)</value>
|
||||
</data>
|
||||
<data name="LimitDuration" xml:space="preserve">
|
||||
<value>持続時間制限</value>
|
||||
</data>
|
||||
<data name="ResHighTolerance" xml:space="preserve">
|
||||
<value>抵抗値 上限. (Ω)</value>
|
||||
</data>
|
||||
<data name="ResLowTolerance" xml:space="preserve">
|
||||
<value>抵抗値 加減. (Ω)</value>
|
||||
</data>
|
||||
<data name="CH" xml:space="preserve">
|
||||
<value>CH</value>
|
||||
</data>
|
||||
<data name="EditFile_AddCode" xml:space="preserve">
|
||||
<value>CH名追加</value>
|
||||
</data>
|
||||
<data name="EditFile_DeleteCode" xml:space="preserve">
|
||||
<value>CH名削除</value>
|
||||
</data>
|
||||
<data name="EditFile_Replace" xml:space="preserve">
|
||||
<value>センサー交換</value>
|
||||
</data>
|
||||
<data name="Filter" xml:space="preserve">
|
||||
<value>ソフトウエアフィルター</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_MustBeCSVOrXML" xml:space="preserve">
|
||||
<value>TTS import requires either .csv or .xml input file</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_NoOriginalCSV" xml:space="preserve">
|
||||
<value>TTS import requires a .csv filename in the OriginalImportFile attribute</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_UnexpectedZeroMethod" xml:space="preserve">
|
||||
<value>is an unexpected zero method type. Only None, AverageOverTime, and UsePreEventDiagnosticsZero are allowed</value>
|
||||
</data>
|
||||
<data name="JHyphenCode" xml:space="preserve">
|
||||
<value>センサー詳細</value>
|
||||
</data>
|
||||
<data name="NumChannelsAndSensors" xml:space="preserve">
|
||||
<value>要求チャンネル数:{0}, 予備センサー数:{1}</value>
|
||||
</data>
|
||||
<data name="SaveFile" xml:space="preserve">
|
||||
<value>ファイル保存</value>
|
||||
</data>
|
||||
<data name="Search" xml:space="preserve">
|
||||
<value>検索</value>
|
||||
</data>
|
||||
<data name="TestName" xml:space="preserve">
|
||||
<value>試験No</value>
|
||||
</data>
|
||||
<data name="Table_NA" xml:space="preserve">
|
||||
<value>---</value>
|
||||
</data>
|
||||
<data name="Analog" xml:space="preserve">
|
||||
<value>アナログ</value>
|
||||
</data>
|
||||
<data name="DigitalIn" xml:space="preserve">
|
||||
<value>Digital In</value>
|
||||
</data>
|
||||
<data name="TOM" xml:space="preserve">
|
||||
<value>TOM</value>
|
||||
</data>
|
||||
<data name="AllowEIDToBlankChannelChallenge" xml:space="preserve">
|
||||
<value>The sensor {0} has an EID, but no EID was found.\r\n\r\nPress OK to clear the EID for {0} and assign the sensor.\r\nPress Cancel to leave the EID unchanged and the sensor unassigned.</value>
|
||||
</data>
|
||||
<data name="ROIEnd" xml:space="preserve">
|
||||
<value>ダウンロード終了時間 (sec)</value>
|
||||
</data>
|
||||
<data name="ROIStart" xml:space="preserve">
|
||||
<value>ダウンロード開始時間 (sec)</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_DuplicateSensorSerialNumber" xml:space="preserve">
|
||||
<value>{0} が2箇所以上あります。</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_DuplicateChannelCode" xml:space="preserve">
|
||||
<value>{0} が2箇所以上あります。</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_DuplicateDescription" xml:space="preserve">
|
||||
<value>{0} が2箇所以上あります。</value>
|
||||
</data>
|
||||
<data name="DIn" xml:space="preserve">
|
||||
<value>D In</value>
|
||||
</data>
|
||||
<data name="DOut" xml:space="preserve">
|
||||
<value>D Out</value>
|
||||
</data>
|
||||
<data name="ECM" xml:space="preserve">
|
||||
<value>ECM</value>
|
||||
</data>
|
||||
<data name="G5" xml:space="preserve">
|
||||
<value>G5</value>
|
||||
</data>
|
||||
<data name="Rack" xml:space="preserve">
|
||||
<value>Rack</value>
|
||||
</data>
|
||||
<data name="SPD" xml:space="preserve">
|
||||
<value>SPD</value>
|
||||
</data>
|
||||
<data name="SPS" xml:space="preserve">
|
||||
<value>SPS</value>
|
||||
</data>
|
||||
<data name="SPT" xml:space="preserve">
|
||||
<value>SPT</value>
|
||||
</data>
|
||||
<data name="Squib" xml:space="preserve">
|
||||
<value>スクイブ</value>
|
||||
</data>
|
||||
<data name="Total" xml:space="preserve">
|
||||
<value>合計</value>
|
||||
</data>
|
||||
<data name="Units" xml:space="preserve">
|
||||
<value>単位</value>
|
||||
</data>
|
||||
<data name="AssignSensorExcitationError" xml:space="preserve">
|
||||
<value>Sensor Assignment Error</value>
|
||||
</data>
|
||||
<data name="InvalidExcitationAssignment" xml:space="preserve">
|
||||
<value>{0} V 印加電圧をサポートしていません。</value>
|
||||
</data>
|
||||
<data name="MissingECMSWarning" xml:space="preserve">
|
||||
<value>以下の IP Addresses の機器は応答していません. 対象機器を再起動してください。</value>
|
||||
</data>
|
||||
<data name="Warning" xml:space="preserve">
|
||||
<value>警告!</value>
|
||||
</data>
|
||||
<data name="EmptyChannelCodeWarning" xml:space="preserve">
|
||||
<value>Non empty channel codes are required, please complete channel codes to continue</value>
|
||||
</data>
|
||||
<data name="TestId" xml:space="preserve">
|
||||
<value>試験番号</value>
|
||||
</data>
|
||||
<data name="TESTID_PREFIX_SUFFIX_None" xml:space="preserve">
|
||||
<value>[-----]</value>
|
||||
</data>
|
||||
<data name="TESTID_PREFIX_SUFFIX_TestSetupName" xml:space="preserve">
|
||||
<value>[テストセットアップ名]</value>
|
||||
</data>
|
||||
<data name="TESTID_PREFIX_SUFFIX_TimeStamp" xml:space="preserve">
|
||||
<value>[タイムスタンプ]</value>
|
||||
</data>
|
||||
<data name="EditFile_ADDDI" xml:space="preserve">
|
||||
<value>DI追加</value>
|
||||
</data>
|
||||
<data name="EditFile_AddSquib" xml:space="preserve">
|
||||
<value>スクイブ追加</value>
|
||||
</data>
|
||||
<data name="AAF_SLICE" xml:space="preserve">
|
||||
<value>アンチエイリアスフィルター SLICE : {0}</value>
|
||||
</data>
|
||||
<data name="AAF_TDAS" xml:space="preserve">
|
||||
<value>アンチエイリアスフィルター TDAS : {0}</value>
|
||||
</data>
|
||||
<data name="ExcitationNotSupportedByChannel" xml:space="preserve">
|
||||
<value> {0} V 印加電圧はこのDASでは使用できません。</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,30 @@
|
||||
using DTS.Common.Interface;
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for SummaryView.xaml
|
||||
/// </summary>
|
||||
public partial class SummaryView : ISummaryView
|
||||
{
|
||||
public SummaryView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void UpdateTestIds(string[] serializedValues)
|
||||
{
|
||||
ctrlTestId.PopulateAllTestIdPrefixSuffixValues(serializedValues);
|
||||
}
|
||||
|
||||
public void SetTestName(string testName)
|
||||
{
|
||||
ctrlTestId.TestName = testName;
|
||||
ctrlTestId.TestSetupLabel = testName;
|
||||
}
|
||||
public string GetTestId()
|
||||
{
|
||||
return ctrlTestId.GetTestId();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,861 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
using DTS.Common.Events;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
|
||||
using Prism.Events;
|
||||
using Unity;
|
||||
using DTS.Common.Interactivity;
|
||||
using Prism.Regions;
|
||||
using Prism.Commands;
|
||||
using TTSImport.Model;
|
||||
using TTSImport.Resources;
|
||||
using Application = System.Windows.Application;
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// this class handles Level Trigger edit/create functionality
|
||||
/// </summary>
|
||||
[PartCreationPolicy(CreationPolicy.Shared)]
|
||||
public class EditFileViewModel : IEditFileViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The Hardware Scan view
|
||||
/// </summary>
|
||||
public IEditFileView View { get; set; }
|
||||
private const string DOUBLEUPTO15 = "0.###############"; //Write up to 15 decimal places to .csv
|
||||
private const string STRINGWRITEFORMAT_CHANNELRANGE = DOUBLEUPTO15;
|
||||
private const string STRINGWRITEFORMAT_SENSITIVITY = DOUBLEUPTO15;
|
||||
private const string STRINGWRITEFORMAT_CAPACITY = DOUBLEUPTO15;
|
||||
|
||||
private IEventAggregator _eventAggregator { get; }
|
||||
private IRegionManager _regionManager;
|
||||
private IUnityContainer UnityContainer { get; }
|
||||
|
||||
public InteractionRequest<Notification> NotificationRequest { get; }
|
||||
public InteractionRequest<Confirmation> ConfirmationRequest { get; }
|
||||
|
||||
///<summary>
|
||||
///Occurs when a property value changes.
|
||||
///</summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
public void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
switch (propertyName)
|
||||
{
|
||||
case "TestName":
|
||||
ChangeValidationIsNeeded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#region constructors and initializers
|
||||
/// <summary>
|
||||
/// Creates a new instance of the TechnologyDomainEditViewModel.
|
||||
/// </summary>
|
||||
/// <param name="view"></param>
|
||||
/// <param name="regionManager">The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed.</param>
|
||||
/// <param name="eventAggregator">The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other.</param>
|
||||
/// <param name="unityContainer">The unityContainer.</param>
|
||||
public EditFileViewModel(EditFileView view, IRegionManager regionManager,
|
||||
IEventAggregator eventAggregator, IUnityContainer unityContainer)
|
||||
{
|
||||
View = view;
|
||||
View.DataContext = this;
|
||||
|
||||
NotificationRequest = new InteractionRequest<Notification>();
|
||||
ConfirmationRequest = new InteractionRequest<Confirmation>();
|
||||
|
||||
_eventAggregator = eventAggregator;
|
||||
UnityContainer = unityContainer;
|
||||
_regionManager = regionManager;
|
||||
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
|
||||
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Subscribe(OnBusyIndicatorNotification, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportReadFileStatusEvent>().Subscribe(OnReadFileFinished, ThreadOption.PublisherThread, true);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// filters the available sensors from the db by the given text
|
||||
/// we keep two lists, allchannels and SystemSensors
|
||||
/// SystemSensors only holds those that aren't in use and are
|
||||
/// available
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
public void Search(string text)
|
||||
{
|
||||
SystemSensors.Clear();
|
||||
//build a list of sensors already used to exclude those sensors
|
||||
var hash = new HashSet<string>();
|
||||
foreach (var ch in RequiredChannels)
|
||||
{
|
||||
hash.Add(ch.SensorSerialNumber);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
//nothing to sort
|
||||
foreach (var s in _allChannels)
|
||||
{
|
||||
if (!hash.Contains(s.SensorSerialNumber))
|
||||
{
|
||||
SystemSensors.Add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
text = text.ToLower();
|
||||
foreach (var s in _allChannels)
|
||||
{
|
||||
if (s.SensorSerialNumber.ToLower().Contains(text))
|
||||
{
|
||||
if (!hash.Contains(s.SensorSerialNumber))
|
||||
{
|
||||
SystemSensors.Add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void OnReadFileFinished(ReadFileStatusArg statusArg)
|
||||
{
|
||||
if (!Application.Current.Dispatcher.CheckAccess())
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
OnReadFileFinished(statusArg);
|
||||
}));
|
||||
return;
|
||||
}
|
||||
if (!statusArg.Status) return;
|
||||
_setup = statusArg.TTSSetup;
|
||||
}
|
||||
|
||||
public void InitializeView()
|
||||
{
|
||||
if (_setup == null) return;
|
||||
|
||||
//turn off Change Validation and remove old channels/sensors, if any
|
||||
ChangeValidationIsNeeded = false;
|
||||
RequiredChannels.Clear();
|
||||
SystemSensors.Clear();
|
||||
//will turn Change Validation back on
|
||||
TestName = _setup.TestId;
|
||||
SaveFileEnabled = false;
|
||||
|
||||
var requiredChannels = new ObservableCollection<ITTSChannelRecord>();
|
||||
_allChannels.Clear();
|
||||
|
||||
foreach (var channelRecord in _setup.Channels)
|
||||
{
|
||||
if (channelRecord.IsDigitalOutput) { continue; }
|
||||
if (channelRecord.ChannelCode != TTSChannelRecord.NONE)
|
||||
{
|
||||
//isn't a "reserved sensor"
|
||||
var requiredChannel = channelRecord.Copy();
|
||||
requiredChannel.Parent = this;
|
||||
requiredChannels.Add(requiredChannel);
|
||||
}
|
||||
}
|
||||
foreach (var sensor in DTS.SensorDB.SensorsCollection.SensorsList.GetAllSensors(false))
|
||||
{
|
||||
if (sensor.IsDigitalOutput()) { continue; }
|
||||
if (sensor.IsTestSpecificSquib) { continue; }
|
||||
if (sensor.IsTestSpecificDigitalIn) { continue; }
|
||||
_allChannels.Add(new TTSChannelRecord(sensor) { Parent = this });
|
||||
}
|
||||
RequiredChannels = requiredChannels;
|
||||
Search(_searchText);
|
||||
ValidateChannelCodes();
|
||||
ValidateJCodes();
|
||||
_originalHash = GenerateHash();
|
||||
NumChannelsAndSensors = string.Format(StringResources.NumChannelsAndSensors, RequiredChannels.Count, SystemSensors.Count);
|
||||
SaveFileEnabled = false;
|
||||
}
|
||||
|
||||
private string GenerateHash()
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
foreach (var rc in RequiredChannels)
|
||||
{
|
||||
bytes.AddRange(rc.GetBytes());
|
||||
}
|
||||
foreach (var rs in SystemSensors)
|
||||
{
|
||||
bytes.AddRange(rs.GetBytes());
|
||||
}
|
||||
|
||||
var sha = new SHA256Managed();
|
||||
var hash = sha.ComputeHash(bytes.ToArray());
|
||||
return BitConverter.ToString(hash).Replace("-", string.Empty);
|
||||
}
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
public Task CleanupAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter)
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter, object model)
|
||||
{
|
||||
}
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task InitializeAsync(object parameter)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Activated()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnBusyIndicatorNotification(bool eventArg)
|
||||
{
|
||||
IsBusy = eventArg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
|
||||
{
|
||||
// The NotificationRequest.Raise triggers the Invoke() method of the PopupWindowAction object to show the NotificationWindow window
|
||||
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
|
||||
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, "",
|
||||
eventArgsWithTitle.Image, string.Empty);
|
||||
|
||||
NotificationRequest.Raise(new Notification
|
||||
{
|
||||
Content = eventArgsWithoutTitle,
|
||||
Title = eventArgsWithTitle.Title
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// this is the list of all channels, this is a superset while SystemSensors is the subset
|
||||
/// this contains some records we don't want
|
||||
/// </summary>
|
||||
private readonly List<ITTSChannelRecord> _allChannels = new List<ITTSChannelRecord>();
|
||||
/// <summary>
|
||||
/// this is the current text the user is search for in available channels/sensors
|
||||
/// </summary>
|
||||
private readonly string _searchText = "";
|
||||
private ITTSSetup _setup;
|
||||
public bool ChangeValidationIsNeeded { get; set; }
|
||||
public bool IsDirty { get; private set; }
|
||||
private bool _isBusy;
|
||||
|
||||
public bool IsBusy
|
||||
{
|
||||
get => _isBusy;
|
||||
set
|
||||
{ _isBusy = value; OnPropertyChanged("IsBusy"); }
|
||||
}
|
||||
|
||||
private bool _isMenuIncluded;
|
||||
|
||||
public bool IsMenuIncluded
|
||||
{
|
||||
get => _isMenuIncluded;
|
||||
set
|
||||
{ _isMenuIncluded = value; OnPropertyChanged("IsMenuIncluded"); }
|
||||
}
|
||||
|
||||
private bool _isNavigationIncluded;
|
||||
|
||||
public bool IsNavigationIncluded
|
||||
{
|
||||
get => _isNavigationIncluded;
|
||||
set
|
||||
{ _isNavigationIncluded = value; OnPropertyChanged("IsNavigationIncluded"); }
|
||||
}
|
||||
|
||||
private bool _isTestNameValid;
|
||||
public bool IsTestNameValid { get => _isTestNameValid; set { _isTestNameValid = value; OnPropertyChanged("IsTestNameValid"); } }
|
||||
|
||||
private string _testName = string.Empty;
|
||||
public string TestName
|
||||
{
|
||||
get => _testName;
|
||||
set
|
||||
{
|
||||
_testName = value;
|
||||
IsTestNameValid = !string.IsNullOrWhiteSpace(value);
|
||||
OnPropertyChanged("TestName");
|
||||
}
|
||||
}
|
||||
private DelegateCommand<string> _testNameLostFocus;
|
||||
public DelegateCommand<string> TestNameLostFocus => _testNameLostFocus ?? (_testNameLostFocus = new DelegateCommand<string>(TestNameLostFocusMethod));
|
||||
public void TestNameLostFocusMethod(string code)
|
||||
{
|
||||
if (!ChangeValidationIsNeeded) return;
|
||||
ValidateChange();
|
||||
}
|
||||
private bool _saveFileEnabled;
|
||||
public bool SaveFileEnabled
|
||||
{
|
||||
get => _saveFileEnabled;
|
||||
set
|
||||
{
|
||||
_saveFileEnabled = value;
|
||||
OnPropertyChanged("SaveFileEnabled");
|
||||
|
||||
EnableOrDisableButtons();
|
||||
}
|
||||
}
|
||||
|
||||
private string _numChannelsAndSensors = string.Empty;
|
||||
public string NumChannelsAndSensors
|
||||
{
|
||||
get => _numChannelsAndSensors;
|
||||
set { _numChannelsAndSensors = value; OnPropertyChanged("NumChannelsAndSensors"); }
|
||||
}
|
||||
|
||||
private bool _replaceEnabled;
|
||||
public bool ReplaceEnabled
|
||||
{
|
||||
get => _replaceEnabled;
|
||||
set { _replaceEnabled = value; OnPropertyChanged("ReplaceEnabled"); }
|
||||
}
|
||||
|
||||
private bool _addCodeEnabled;
|
||||
public bool AddCodeEnabled
|
||||
{
|
||||
get => _addCodeEnabled;
|
||||
set { _addCodeEnabled = value; OnPropertyChanged("AddCodeEnabled"); }
|
||||
}
|
||||
|
||||
private bool _deleteCodeEnabled;
|
||||
public bool DeleteCodeEnabled
|
||||
{
|
||||
get => _deleteCodeEnabled;
|
||||
set { _deleteCodeEnabled = value; OnPropertyChanged("DeleteCodeEnabled"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// stores a hash representing the state of channels at the time they were read in
|
||||
/// this is used to determine if any changes of significance were made in edit file
|
||||
/// </summary>
|
||||
private string _originalHash;
|
||||
|
||||
private ObservableCollection<ITTSChannelRecord> _requiredChannels = new ObservableCollection<ITTSChannelRecord>();
|
||||
public ObservableCollection<ITTSChannelRecord> RequiredChannels
|
||||
{
|
||||
get => _requiredChannels;
|
||||
set
|
||||
{ _requiredChannels = value; OnPropertyChanged("RequiredChannels"); }
|
||||
}
|
||||
private ObservableCollection<ITTSChannelRecord> _systemSensors = new ObservableCollection<ITTSChannelRecord>();
|
||||
public ObservableCollection<ITTSChannelRecord> SystemSensors
|
||||
{
|
||||
get => _systemSensors;
|
||||
set
|
||||
{ _systemSensors = value; OnPropertyChanged("SystemSensors"); }
|
||||
}
|
||||
|
||||
private ITTSChannelRecord _selectedRequiredChannel;
|
||||
public ITTSChannelRecord SelectedRequiredChannel
|
||||
{
|
||||
get => _selectedRequiredChannel;
|
||||
set
|
||||
{
|
||||
_selectedRequiredChannel = value; OnPropertyChanged("SelectedRequiredChannel");
|
||||
|
||||
EnableOrDisableButtons();
|
||||
}
|
||||
}
|
||||
|
||||
private ITTSChannelRecord _selectedSystemSensor;
|
||||
public ITTSChannelRecord SelectedSystemSensor
|
||||
{
|
||||
get => _selectedSystemSensor;
|
||||
set
|
||||
{
|
||||
_selectedSystemSensor = value;
|
||||
OnPropertyChanged("SelectedSystemSensor");
|
||||
EnableOrDisableButtons();
|
||||
}
|
||||
}
|
||||
|
||||
private void EnableOrDisableButtons()
|
||||
{
|
||||
if (null == _selectedRequiredChannel || null == _selectedSystemSensor) { ReplaceEnabled = false; }
|
||||
else if (_selectedRequiredChannel.IsDigitalInput)
|
||||
{
|
||||
ReplaceEnabled = _selectedSystemSensor.IsDigitalInput;
|
||||
}
|
||||
else if (_selectedRequiredChannel.IsDigitalOutput)
|
||||
{
|
||||
ReplaceEnabled = _selectedSystemSensor.IsDigitalOutput;
|
||||
}
|
||||
else if (_selectedRequiredChannel.IsSquib)
|
||||
{
|
||||
ReplaceEnabled = _selectedSystemSensor.IsSquib;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplaceEnabled = !(_selectedSystemSensor.IsSquib
|
||||
|| _selectedSystemSensor.IsDigitalInput ||
|
||||
_selectedSystemSensor.IsDigitalOutput);
|
||||
}
|
||||
|
||||
|
||||
AddCodeEnabled = _selectedSystemSensor != null;
|
||||
DeleteCodeEnabled = _selectedRequiredChannel != null;
|
||||
}
|
||||
#endregion Properties
|
||||
|
||||
#region Commands
|
||||
/// <summary>
|
||||
/// Browse to import file
|
||||
/// </summary>
|
||||
private DelegateCommand _saveFileClicked;
|
||||
public DelegateCommand SaveFileClicked => _saveFileClicked ?? (_saveFileClicked = new DelegateCommand(SaveFileMethod));
|
||||
public void SaveFileMethod()
|
||||
{
|
||||
using (var sfd = new System.Windows.Forms.SaveFileDialog())
|
||||
{
|
||||
var fullFilePath = Path.GetFullPath(_setup.OriginalImportFile);
|
||||
sfd.Filter = @"TTS import (*.csv)|*.csv";
|
||||
sfd.RestoreDirectory = true;
|
||||
sfd.FilterIndex = 0;
|
||||
var fi = new FileInfo(fullFilePath);
|
||||
|
||||
sfd.FileName = fi.Name;
|
||||
|
||||
if (fi.DirectoryName != null) sfd.InitialDirectory = Path.GetFullPath(fi.DirectoryName);
|
||||
var result = sfd.ShowDialog();
|
||||
if (result != System.Windows.Forms.DialogResult.OK) return;
|
||||
fullFilePath = sfd.FileName;
|
||||
|
||||
var csv = new StringBuilder();
|
||||
|
||||
var newRow = _setup.Line1;
|
||||
csv.Append(newRow + Environment.NewLine);
|
||||
|
||||
newRow = _setup.Line2;
|
||||
_setup.TestId = TestName;
|
||||
if (_setup.Line2 != null)
|
||||
{
|
||||
var fields = _setup.Line2.Split(',');
|
||||
var newLine2 = fields.Where((t, index) => index > 0).Aggregate(_setup.TestId, (current, t) => current + "," + t);
|
||||
newRow = newLine2;
|
||||
}
|
||||
csv.Append(newRow + Environment.NewLine);
|
||||
|
||||
newRow = _setup.Line3;
|
||||
csv.Append(newRow + Environment.NewLine);
|
||||
|
||||
newRow = _setup.Line4;
|
||||
csv.Append(newRow + Environment.NewLine);
|
||||
|
||||
//Order the required channels first
|
||||
var channelList = RequiredChannels.ToList();
|
||||
|
||||
_setup.Channels = channelList.ToArray();
|
||||
|
||||
foreach (var channel in _setup.Channels)
|
||||
{
|
||||
var channelNumber = channel.ChannelNumber.ToString();
|
||||
var channelCode = channel.ChannelCode;
|
||||
var channelRange = channel.IsSquib ? channel.SquibFireDelayMs.ToString(STRINGWRITEFORMAT_CHANNELRANGE) : channel.ChannelRange.ToString(STRINGWRITEFORMAT_CHANNELRANGE); //Write up to 15 decimal places to .csv
|
||||
var channelFilter = channel.IsSquib ? channel.SquibFireDurationMs.ToString(STRINGWRITEFORMAT_CHANNELRANGE) : channel.ChannelFilterHz.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
||||
if (channel.ChannelCode == TTSChannelRecord.NONE)
|
||||
{
|
||||
//Blank the following fields from reserved sensors
|
||||
channelNumber = "";
|
||||
channelCode = "";
|
||||
channelRange = "";
|
||||
channelFilter = "";
|
||||
}
|
||||
|
||||
var sensorSensitivity = channel.SensorSensitivity.ToString(STRINGWRITEFORMAT_SENSITIVITY); //Write up to 15 decimal places to .csv
|
||||
var sensorExcitationVolts = channel.SensorExcitationVolts.ToString("0.#");
|
||||
var sensorCapacity = channel.SensorCapacity.ToString(STRINGWRITEFORMAT_CAPACITY); //Write up to 15 decimal places to .csv
|
||||
var sensorPolarity = channel.SensorPolarity ? "+" : "-";
|
||||
|
||||
//Only FullBridge and HalfBridge contain a space
|
||||
string channelType;
|
||||
switch (channel.ChannelType)
|
||||
{
|
||||
case DTS.Common.Enums.TTS.ToyotaBridgeType.FullBridge:
|
||||
channelType = "Full Bridge";
|
||||
break;
|
||||
case DTS.Common.Enums.TTS.ToyotaBridgeType.HalfBridge:
|
||||
channelType = "Half Bridge";
|
||||
break;
|
||||
default:
|
||||
channelType = channel.ChannelType.ToString();
|
||||
break;
|
||||
}
|
||||
|
||||
var proportionalToExcitation = channel.ProportionalToExcitation ? "mv/V/EU" : "";
|
||||
var bridgeResistance = channel.BridgeResistance.ToString("0.#");
|
||||
var initialOffsetVoltage = channel.InitialOffsetVoltage.ToString("0.#");
|
||||
var initialOffsetVoltageTolerance = channel.InitialOffsetVoltageTolerance.ToString("0.#");
|
||||
var removeOffset = channel.RemoveOffset ? "1" : "0";
|
||||
var zeroMethod = ((int)channel.ZeroMethod).ToString();
|
||||
var initialEUInMv = double.IsNaN(channel.InitialEUInMV) ? "" : channel.InitialEUInMV.ToString("0.##");
|
||||
var initialEUInEU = double.IsNaN(channel.InitialEUInEU) ? "" : channel.InitialEUInEU.ToString("0.##");
|
||||
var iRTraccExponent = double.IsNaN(channel.IRTraccExponent) ? "" : channel.IRTraccExponent.ToString("0.##");
|
||||
var polynomialConstant = double.IsNaN(channel.PolynomialConstant) ? "" : channel.PolynomialConstant.ToString("0.##");
|
||||
var polynomialCoefficientC = double.IsNaN(channel.PolynomialCoefficientC) ? "" : channel.PolynomialCoefficientC.ToString("0.##");
|
||||
var polynomialCoefficentB = double.IsNaN(channel.PolynomialCoefficentB) ? "" : channel.PolynomialCoefficentB.ToString("0.##");
|
||||
var polynomialCoefficientA = double.IsNaN(channel.PolynomialCoefficientA) ? "" : channel.PolynomialCoefficientA.ToString("0.##");
|
||||
var polynomialCoefficientAlpha = double.IsNaN(channel.PolynomialCoefficientAlpha) ? "" : channel.PolynomialCoefficientAlpha.ToString("0.##");
|
||||
var diagnosticsMode = channel.DiagnosticsMode ? TTSChannelRecord.DIAGNOSTICSMODE : "";
|
||||
|
||||
if (channel.IsDigitalInput)
|
||||
{
|
||||
channelRange = string.Empty;
|
||||
channelFilter = string.Empty;
|
||||
}
|
||||
|
||||
if (channel.IsDigitalOutput)
|
||||
{
|
||||
//14708 Squib appears to be unassigned when using edit file during TTS import
|
||||
//I changed this to be consistent with the reader, which only reads the first 3
|
||||
//fields for digital outputs
|
||||
newRow = $"{channelNumber},{channelCode},{channel.JCodeOrDescription}{Environment.NewLine}";
|
||||
}
|
||||
|
||||
if (channel.IsDigitalInput || channel.IsSquib)
|
||||
{
|
||||
//14708 Squib appears to be unassigned when using edit file during TTS import
|
||||
//don't wipe out EID or serial number, these are valid fields for these sensors
|
||||
//isocode and description should be valid too? as well as channel description?
|
||||
//note that the import reads up to the serial number, so no point it writing more
|
||||
newRow =
|
||||
$"{channelNumber},{channelCode},{channel.JCodeOrDescription},{channelRange},{channelFilter},{channel.SensorEID},{channel.SensorSerialNumber}{Environment.NewLine}";
|
||||
}
|
||||
else
|
||||
{
|
||||
newRow = $"{channelNumber},{channelCode},{channel.JCodeOrDescription},{channelRange},{channelFilter},{channel.SensorEID},{channel.SensorSerialNumber},{sensorSensitivity},{sensorExcitationVolts},{sensorCapacity},{channel.SensorEU}," +
|
||||
$"{sensorPolarity},{channelType},{channel.Description},{proportionalToExcitation},{bridgeResistance},{initialOffsetVoltage},{initialOffsetVoltageTolerance},{removeOffset},{zeroMethod},{channel.CableMultiplier.ToString(System.Globalization.CultureInfo.InvariantCulture)}," +
|
||||
$"{initialEUInMv},{initialEUInEU},{iRTraccExponent},{polynomialConstant},{polynomialCoefficientC},{polynomialCoefficentB},{polynomialCoefficientA},{polynomialCoefficientAlpha},{channel.ISOCode},{channel.ISODescription},{channel.ISOPolarity},{diagnosticsMode}{Environment.NewLine}";
|
||||
}
|
||||
|
||||
csv.Append(newRow);
|
||||
}
|
||||
|
||||
File.WriteAllText(fullFilePath, csv.ToString(), Encoding.GetEncoding("Shift-JIS"));
|
||||
_setup.OriginalImportFile = fullFilePath;
|
||||
}
|
||||
SaveFileEnabled = false;
|
||||
//Enable future nav steps since changes have been saved
|
||||
_eventAggregator.GetEvent<TTSImportSavedChangesStatusEvent>().Publish(true);
|
||||
_originalHash = GenerateHash();
|
||||
}
|
||||
|
||||
|
||||
#region Replace
|
||||
/// <summary>
|
||||
/// Swap the assignments of a Required Channel and a Reserved Sensor
|
||||
/// </summary>
|
||||
private DelegateCommand _replaceCommand;
|
||||
public DelegateCommand ReplaceCommand => _replaceCommand ?? (_replaceCommand = new DelegateCommand(Replace));
|
||||
private void Replace()
|
||||
{
|
||||
//11574 replace button removed JCode and range and filter from an "add code" channel in edit file
|
||||
//we preserve the original channel settings when doing replace
|
||||
//Initialize a Reserved Sensor that's about to become a Required Channel
|
||||
SelectedSystemSensor.ChannelNumber = SelectedRequiredChannel.ChannelNumber;
|
||||
SelectedSystemSensor.ChannelCode = SelectedRequiredChannel.ChannelCode;
|
||||
SelectedRequiredChannel.ChannelCode = TTSChannelRecord.NONE;
|
||||
SelectedSystemSensor.JCodeOrDescription = SelectedRequiredChannel.JCodeOrDescription;
|
||||
SelectedSystemSensor.ChannelRange = SelectedRequiredChannel.ChannelRange;
|
||||
SelectedSystemSensor.ChannelFilterHz = SelectedRequiredChannel.ChannelFilterHz;
|
||||
|
||||
// Save off the channels that are about to be removed from their old lists
|
||||
var savedSelectedSystemSensor = SelectedSystemSensor;
|
||||
var savedSelectedRequiredChannel = SelectedRequiredChannel;
|
||||
|
||||
//Save the indices of the channels that are about to be removed from their old lists
|
||||
var selectedRequiredChannelIndex = RequiredChannels.IndexOf(SelectedRequiredChannel);
|
||||
var selectedSystemSensorIndex = SystemSensors.IndexOf(SelectedSystemSensor);
|
||||
|
||||
//Remove the channels from their old lists
|
||||
RequiredChannels.Remove(SelectedRequiredChannel);
|
||||
SystemSensors.Remove(SelectedSystemSensor);
|
||||
|
||||
//Insert the saved channels into their new lists
|
||||
RequiredChannels.Insert(selectedRequiredChannelIndex, savedSelectedSystemSensor);
|
||||
SystemSensors.Insert(selectedSystemSensorIndex, savedSelectedRequiredChannel);
|
||||
|
||||
//Re-select the same rows in the tables
|
||||
SelectedRequiredChannel = RequiredChannels[selectedRequiredChannelIndex];
|
||||
SelectedSystemSensor = SystemSensors[selectedSystemSensorIndex];
|
||||
|
||||
UpdateAndValidate();
|
||||
}
|
||||
#endregion Replace
|
||||
|
||||
#region Add Code
|
||||
private DelegateCommand _addCodeCommand;
|
||||
public DelegateCommand AddCodeCommand => _addCodeCommand ?? (_addCodeCommand = new DelegateCommand(AddCode));
|
||||
/// <summary>
|
||||
/// remove a hardware channel assignment(does not remove the channel from the test setup though?)
|
||||
/// </summary>
|
||||
private void AddCode()
|
||||
{
|
||||
AddSystemSensor();
|
||||
UpdateAndValidate();
|
||||
}
|
||||
|
||||
private void AddSystemSensor()
|
||||
{
|
||||
var maxChannelNumber = RequiredChannels.Select(requiredChannel => requiredChannel.ChannelNumber).Concat(new[] { 0 }).Max();
|
||||
SelectedSystemSensor.ChannelNumber = maxChannelNumber + 1;
|
||||
SelectedSystemSensor.ChannelCode = string.Empty;
|
||||
SelectedSystemSensor.JCodeOrDescription = string.Empty;
|
||||
SelectedSystemSensor.ChannelRange = 0;
|
||||
SelectedSystemSensor.ChannelFilterHz = -1;
|
||||
RequiredChannels.Add(SelectedSystemSensor);
|
||||
|
||||
var selectedSystemSensorIndex = SystemSensors.IndexOf(SelectedSystemSensor);
|
||||
SystemSensors.Remove(SelectedSystemSensor);
|
||||
if (SystemSensors.Count > 0)
|
||||
{
|
||||
//If removing from the end of the list, set the previous record to Selected, otherwise set next record to Selected
|
||||
SelectedSystemSensor = selectedSystemSensorIndex == SystemSensors.Count ? SystemSensors[selectedSystemSensorIndex - 1] : SystemSensors[selectedSystemSensorIndex];
|
||||
}
|
||||
}
|
||||
#endregion Add Code
|
||||
|
||||
private DelegateCommand _addSquibCommand;
|
||||
|
||||
public DelegateCommand AddSquibCommand =>
|
||||
_addSquibCommand ?? (_addSquibCommand = new DelegateCommand(AddSquib));
|
||||
private void AddSquib()
|
||||
{
|
||||
var maxChannelNumber = RequiredChannels.Select(requiredChannel => requiredChannel.ChannelNumber).Concat(new[] { 0 }).Max();
|
||||
var channelRecord = new TTSChannelRecord();
|
||||
channelRecord.ChannelNumber = ++maxChannelNumber;
|
||||
channelRecord.IsSquib = true;
|
||||
int maxSquibNumber = 0;
|
||||
foreach (var rc in RequiredChannels)
|
||||
{
|
||||
if (!rc.IsSquib) continue;
|
||||
var channelCode = rc.ChannelCode.Replace("TF", "").Replace("SQ", "");
|
||||
if (int.TryParse(channelCode, out var temp))
|
||||
{
|
||||
maxSquibNumber = Math.Max(temp, maxSquibNumber);
|
||||
}
|
||||
}
|
||||
maxSquibNumber++;
|
||||
channelRecord.ChannelCode = $"SQ{maxSquibNumber}";
|
||||
channelRecord.JCodeOrDescription = string.Empty;
|
||||
channelRecord.LimitDuration = true;
|
||||
channelRecord.ChannelRange = (int)channelRecord.SquibFireDelayMs;
|
||||
channelRecord.SquibFireDurationMs = _setup.DefaultSquibFireDurationMs;
|
||||
channelRecord.ChannelFilterHz = (int)channelRecord.SquibFireDurationMs; //-1;
|
||||
channelRecord.Parent = this;
|
||||
RequiredChannels.Add(channelRecord);
|
||||
Validate();
|
||||
}
|
||||
|
||||
private DelegateCommand _addDICommand;
|
||||
|
||||
public DelegateCommand ADDDICommand =>
|
||||
_addDICommand ?? (_addDICommand = new DelegateCommand(AddDI));
|
||||
|
||||
private void AddDI()
|
||||
{
|
||||
var maxChannelNumber = RequiredChannels.Select(requiredChannel => requiredChannel.ChannelNumber).Concat(new[] { 0 }).Max();
|
||||
var channelRecord = new TTSChannelRecord();
|
||||
channelRecord.ChannelNumber = ++maxChannelNumber;
|
||||
channelRecord.IsDigitalInput = true;
|
||||
int maxDINumber = 0;
|
||||
foreach (var rc in RequiredChannels)
|
||||
{
|
||||
if (!rc.IsDigitalInput) continue;
|
||||
var channelCode = rc.ChannelCode.Replace("DI", "");
|
||||
if (int.TryParse(channelCode, out var temp))
|
||||
{
|
||||
maxDINumber = Math.Max(temp, maxDINumber);
|
||||
}
|
||||
}
|
||||
maxDINumber++;
|
||||
channelRecord.ChannelCode = $"DI{maxDINumber}";
|
||||
channelRecord.JCodeOrDescription = string.Empty;
|
||||
channelRecord.ChannelFilterHz = -1;
|
||||
channelRecord.Parent = this;
|
||||
channelRecord.IsChannelCodeValid = true;
|
||||
RequiredChannels.Add(channelRecord);
|
||||
}
|
||||
|
||||
#region Delete Code
|
||||
private DelegateCommand _deleteCodeCommand;
|
||||
public DelegateCommand DeleteCodeCommand =>
|
||||
_deleteCodeCommand ?? (_deleteCodeCommand = new DelegateCommand(DeleteCode));
|
||||
/// <summary>
|
||||
/// enables or disables a channel in the test.
|
||||
/// </summary>
|
||||
private void DeleteCode()
|
||||
{
|
||||
DeleteRequiredChannel();
|
||||
UpdateAndValidate();
|
||||
}
|
||||
|
||||
private void DeleteRequiredChannel()
|
||||
{
|
||||
if (null == SelectedRequiredChannel) { return; }
|
||||
SelectedRequiredChannel.ChannelCode = TTSChannelRecord.NONE; //So that when it's saved, these fields will be set to empty strings, but if it's re-Added, force user to enter a value.
|
||||
SelectedRequiredChannel.JCodeOrDescription = string.Empty; //In case it's re-Added, force user to enter a value.
|
||||
SelectedRequiredChannel.ChannelRange = 0; //In case it's re-Added, force user to enter a value.
|
||||
SelectedRequiredChannel.ChannelFilterHz = -1; //In case it's re-Added, force user to choose a filter or "None".
|
||||
SelectedRequiredChannel.HardwareChannel = null;
|
||||
SystemSensors.Add(SelectedRequiredChannel);
|
||||
|
||||
var selectedRequiredChannelIndex = RequiredChannels.IndexOf(SelectedRequiredChannel);
|
||||
RequiredChannels.Remove(SelectedRequiredChannel);
|
||||
if (RequiredChannels.Count > 0)
|
||||
{
|
||||
//Ensure the channels don't have any gaps
|
||||
foreach (var channel in RequiredChannels)
|
||||
{
|
||||
channel.ChannelNumber = RequiredChannels.IndexOf(channel) + 1;
|
||||
}
|
||||
|
||||
//If removing from the end of the list, set the previous record to Selected, otherwise set next record to Selected
|
||||
SelectedRequiredChannel = selectedRequiredChannelIndex == RequiredChannels.Count ? RequiredChannels[selectedRequiredChannelIndex - 1] : RequiredChannels[selectedRequiredChannelIndex];
|
||||
}
|
||||
}
|
||||
#endregion Delete Code
|
||||
|
||||
private void UpdateAndValidate()
|
||||
{
|
||||
NumChannelsAndSensors = string.Format(StringResources.NumChannelsAndSensors, RequiredChannels.Count, SystemSensors.Count);
|
||||
EnableOrDisableButtons();
|
||||
ValidateChange();
|
||||
CollectionViewSource.GetDefaultView(RequiredChannels)?.Refresh();
|
||||
}
|
||||
#endregion Commands
|
||||
|
||||
/// <summary>
|
||||
/// Returns True if all fields are valid, False if not
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Validate()
|
||||
{
|
||||
var duplicates = RequiredChannels.GroupBy(x => x.ChannelCode).Any(g => g.Count() > 1);
|
||||
return !duplicates && IsTestNameValid && RequiredChannels.All(x => x.IsChannelCodeValid /*&& x.IsJCodeValid*/ &&
|
||||
(x.IsRangeValid || x.RangeVisible != System.Windows.Visibility.Visible) &&
|
||||
(x.IsFilterValid || x.FilterVisible != System.Windows.Visibility.Visible));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns true if there are any changes that have not been saved yet
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool HasUnsavedChanges()
|
||||
{
|
||||
var hash = GenerateHash();
|
||||
return hash != _originalHash;
|
||||
}
|
||||
/// <summary>
|
||||
/// If all fields are valid after a change, enables the Save File button and returns True.
|
||||
/// If not all fields are valid after a change, disables the Save File button and returns False.
|
||||
/// Disables all future nav steps (they will be enabled when the Save File button is clicked).
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ValidateChange(ITTSChannelRecord record = null)
|
||||
{
|
||||
//Enable the Save File button if everything is valid
|
||||
ValidateChannelCodes();
|
||||
ValidateJCodes();
|
||||
bool bValid = Validate();
|
||||
SaveFileEnabled = bValid && HasUnsavedChanges();
|
||||
|
||||
//Prevent calls to Validate if losing focus on an unchanged control, for example
|
||||
ChangeValidationIsNeeded = false;
|
||||
|
||||
//Disable future nav steps since changes have been made but not saved, or are just or are just invalid
|
||||
_eventAggregator.GetEvent<TTSImportSavedChangesStatusEvent>().Publish(!SaveFileEnabled);
|
||||
return SaveFileEnabled;
|
||||
}
|
||||
|
||||
private void ValidateChannelCodes()
|
||||
{
|
||||
var channelCodeToChannel = new Dictionary<string, ITTSChannelRecord>();
|
||||
foreach (var channel in RequiredChannels)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(channel.ChannelCode))
|
||||
{
|
||||
channel.IsChannelCodeValid = false;
|
||||
}
|
||||
else if (channel.ChannelCode == TTSChannelRecord.NONE)
|
||||
{
|
||||
channel.IsChannelCodeValid = false;
|
||||
}
|
||||
else if (channelCodeToChannel.ContainsKey(channel.ChannelCode))
|
||||
{
|
||||
channelCodeToChannel[channel.ChannelCode].IsChannelCodeValid = false;
|
||||
channel.IsChannelCodeValid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
channelCodeToChannel[channel.ChannelCode] = channel;
|
||||
channel.IsChannelCodeValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateJCodes()
|
||||
{
|
||||
var channelJCodeToChannel = new Dictionary<string, ITTSChannelRecord>();
|
||||
foreach (var channel in RequiredChannels)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(channel.JCodeOrDescription))
|
||||
{
|
||||
channel.IsJCodeValid = false;
|
||||
}
|
||||
//else if (channelJCodeToChannel.ContainsKey(channel.JCodeOrDescription))
|
||||
//{
|
||||
// channelJCodeToChannel[channel.JCodeOrDescription].IsJCodeValid = false;
|
||||
// channel.IsJCodeValid = false;
|
||||
//}
|
||||
else
|
||||
{
|
||||
channelJCodeToChannel[channel.JCodeOrDescription] = channel;
|
||||
channel.IsJCodeValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using DTS.Common.Events;
|
||||
using DTS.Common.Events.TTSImport;
|
||||
using DTS.Common.Interface.DataRecorders;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.DOChannels;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
|
||||
using Prism.Events;
|
||||
using Unity;
|
||||
using DTS.Common.Interactivity;
|
||||
using Prism.Regions;
|
||||
using Prism.Commands;
|
||||
using TTSImport.Model;
|
||||
using TTSImport.Resources;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// this class handles Level Trigger edit/create functionality
|
||||
/// </summary>
|
||||
[PartCreationPolicy(CreationPolicy.Shared)]
|
||||
public class DigitalOutputChannelsViewModel : IDigitalOutputChannelsViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The Hardware Scan view
|
||||
/// </summary>
|
||||
public IDigitalOutputChannelsView View { get; set; }
|
||||
|
||||
private IEventAggregator _eventAggregator { get; }
|
||||
private IRegionManager _regionManager;
|
||||
private IUnityContainer UnityContainer { get; }
|
||||
|
||||
public InteractionRequest<Notification> NotificationRequest { get; }
|
||||
public InteractionRequest<Confirmation> ConfirmationRequest { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the TechnologyDomainEditViewModel.
|
||||
/// </summary>
|
||||
/// <param name="view">The IDigitalOutputChannelsView.</param>
|
||||
/// <param name="regionManager">The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed.</param>
|
||||
/// <param name="eventAggregator">The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other.</param>
|
||||
/// <param name="unityContainer">The unityContainer.</param>
|
||||
public DigitalOutputChannelsViewModel(IDigitalOutputChannelsView view, IRegionManager regionManager,
|
||||
IEventAggregator eventAggregator, IUnityContainer unityContainer)
|
||||
{
|
||||
View = view;
|
||||
View.DataContext = this;
|
||||
|
||||
NotificationRequest = new InteractionRequest<Notification>();
|
||||
ConfirmationRequest = new InteractionRequest<Confirmation>();
|
||||
|
||||
_eventAggregator = eventAggregator;
|
||||
UnityContainer = unityContainer;
|
||||
_regionManager = regionManager;
|
||||
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
|
||||
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>()
|
||||
.Subscribe(OnBusyIndicatorNotification, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<AssignedChannelsChangedEvent>().Subscribe(OnAssignedChannelsChangedEvent,
|
||||
ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportHardwareScanFinishedEvent>()
|
||||
.Subscribe(OnHardwareScanComplete, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<EIDMappingEvent>()
|
||||
.Subscribe(OnEIDComplete, ThreadOption.PublisherThread, true);
|
||||
}
|
||||
|
||||
#region Methods
|
||||
private void OnEIDComplete(IDictionary<string, string> sensorIdToChannelId)
|
||||
{
|
||||
var channelIdToSensorId = new Dictionary<string, string>();
|
||||
using (var e = sensorIdToChannelId.GetEnumerator())
|
||||
{
|
||||
while (e.MoveNext())
|
||||
{
|
||||
channelIdToSensorId[e.Current.Value] = e.Current.Key;
|
||||
}
|
||||
}
|
||||
_hardwareChannelIdToSensorId = channelIdToSensorId;
|
||||
}
|
||||
private void OnHardwareScanComplete(List<IDASHardware> hardware)
|
||||
{
|
||||
_hardware = hardware;
|
||||
}
|
||||
|
||||
private void OnAssignedChannelsChangedEvent(ITTSSetup setup)
|
||||
{
|
||||
if (!Application.Current.Dispatcher.CheckAccess())
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
OnAssignedChannelsChangedEvent(setup);
|
||||
}));
|
||||
return;
|
||||
}
|
||||
_setup = setup;
|
||||
if (null == _hardware || null == _setup) { return; }
|
||||
var channels = new ObservableCollection<DASChannel>();
|
||||
var channelIdToChannelRecord = new Dictionary<string, ITTSChannelRecord>();
|
||||
foreach (var ch in _setup.Channels)
|
||||
{
|
||||
if (!ch.IsDigitalOutput) { continue; }
|
||||
if (null == ch.HardwareChannel) { continue; }
|
||||
if (ch.ChannelCode == TTSChannelRecord.NONE) { continue; }
|
||||
channelIdToChannelRecord[ch.HardwareChannel.GetId()] = ch;
|
||||
}
|
||||
var channelIdToDASChannel = new Dictionary<string, DASChannel>();
|
||||
foreach (var das in _hardware)
|
||||
{
|
||||
var ichannels = das.GetIHardwareChannels();
|
||||
foreach (var ch in ichannels)
|
||||
{
|
||||
if (!ch.IsDigitalOut) { continue; }
|
||||
var newChannel = new DASChannel(ch, _setup);
|
||||
if (_hardwareChannelIdToSensorId.ContainsKey(ch.GetId()))
|
||||
{
|
||||
newChannel.EID = _hardwareChannelIdToSensorId[ch.GetId()];
|
||||
}
|
||||
channels.Add(newChannel);
|
||||
channelIdToDASChannel[newChannel.HardwareChannel.GetId()] = newChannel;
|
||||
if (channelIdToChannelRecord.ContainsKey(ch.GetId()))
|
||||
{
|
||||
newChannel.SetITTSChannelRecord(channelIdToChannelRecord[ch.GetId()]);
|
||||
newChannel.Channel.ChannelCode = $"Digital Out {ch.ToString()}";
|
||||
newChannel.Channel.SensorSerialNumber = newChannel.Channel.ChannelCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (var enumChannels = channelIdToDASChannel.GetEnumerator())
|
||||
{
|
||||
while (enumChannels.MoveNext())
|
||||
{
|
||||
if (null == enumChannels.Current.Value.Channel)
|
||||
{
|
||||
//CREATE new channel
|
||||
var ch = new TTSChannelRecord();
|
||||
ch.ChannelCode = $"Digital Out {enumChannels.Current.Value.HardwareChannel?.ToString()}";
|
||||
ch.IsChannelCodeValid = true;
|
||||
ch.IsDigitalOutput = true;
|
||||
ch.SensorEU = "V";
|
||||
ch.HardwareChannel = enumChannels.Current.Value.HardwareChannel;
|
||||
//ch.SensorSerialNumber = ch.ChannelCode;
|
||||
enumChannels.Current.Value.SetITTSChannelRecord(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DASChannels = channels;
|
||||
OnPropertyChanged("DASChannels");
|
||||
CollectionViewSource.GetDefaultView(DASChannels)?.Refresh();
|
||||
}
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
public Task CleanupAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter)
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter, object model)
|
||||
{
|
||||
}
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task InitializeAsync(object parameter)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Activated()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnBusyIndicatorNotification(bool eventArg)
|
||||
{
|
||||
IsBusy = eventArg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
|
||||
{
|
||||
// The NotificationRequest.Raise triggers the Invoke() method of the PopupWindowAction object to show the NotificationWindow window
|
||||
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
|
||||
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, "",
|
||||
eventArgsWithTitle.Image, string.Empty);
|
||||
|
||||
NotificationRequest.Raise(new Notification
|
||||
{
|
||||
Content = eventArgsWithoutTitle,
|
||||
Title = eventArgsWithTitle.Title
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
private ITTSSetup _setup;
|
||||
private IList<IDASHardware> _hardware;
|
||||
private IDictionary<string, string> _hardwareChannelIdToSensorId = new Dictionary<string, string>();
|
||||
public bool IsDirty { get; private set; }
|
||||
private bool _isBusy;
|
||||
|
||||
public bool IsBusy
|
||||
{
|
||||
get => _isBusy;
|
||||
set
|
||||
{
|
||||
_isBusy = value;
|
||||
OnPropertyChanged("IsBusy");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isMenuIncluded;
|
||||
|
||||
public bool IsMenuIncluded
|
||||
{
|
||||
get => _isMenuIncluded;
|
||||
set
|
||||
{
|
||||
_isMenuIncluded = value;
|
||||
OnPropertyChanged("IsMenuIncluded");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isNavigationIncluded;
|
||||
|
||||
public bool IsNavigationIncluded
|
||||
{
|
||||
get => _isNavigationIncluded;
|
||||
set
|
||||
{
|
||||
_isNavigationIncluded = value;
|
||||
OnPropertyChanged("IsNavigationIncluded");
|
||||
}
|
||||
}
|
||||
public ObservableCollection<DASChannel> DASChannels { get; set; } = new ObservableCollection<DASChannel>();
|
||||
|
||||
private DASChannel _selectedDASChannel;
|
||||
public DASChannel SelectedDASChannel
|
||||
{
|
||||
get => _selectedDASChannel;
|
||||
set => _selectedDASChannel = value;
|
||||
}
|
||||
|
||||
public string EnableOrDisableText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SelectedDASChannel?.Channel == null)
|
||||
{
|
||||
return StringResources.Analog_Enable;
|
||||
}
|
||||
return SelectedDASChannel.Channel.Disabled
|
||||
? StringResources.Analog_Enable
|
||||
: StringResources.Analog_Disable;
|
||||
}
|
||||
}
|
||||
#endregion Properties
|
||||
|
||||
#region Commands
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Occurs when a property value changes.
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
<base:BaseView x:Class="TTSImport.EditFileView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
|
||||
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:strings="clr-namespace:TTSImport"
|
||||
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
|
||||
xmlns:controls="clr-namespace:DTS.Common.Controls;assembly=DTS.Common"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="768" d:DesignWidth="1100">
|
||||
<base:BaseView.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/CommonStyles.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/brushes.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Controls/combobox.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="ItemContainerStyle" Value="{StaticResource TTS_ListViewItemStyle}"/>
|
||||
</Style>
|
||||
<Style TargetType="TextBox" BasedOn="{StaticResource TTS_TextBoxStyle}"/>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource TTS_TextBlockStyle}"/>
|
||||
<Style TargetType="CheckBox" BasedOn="{StaticResource PageContentCheckBoxStyle}" />
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource TTS_ComboBoxStyle}"/>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource TTS_ButtonStyle}"/>
|
||||
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource Gray_GridViewColumnHeaderStyle}"/>
|
||||
|
||||
<converters:BooleanToBorderThicknessConverter x:Key="BooleanToBorderThickness" />
|
||||
<converters:BooleanToColorConverter x:Key="BooleanToColor" />
|
||||
<converters:BooleanToColorConverter x:Key="BooleanToWarningColor" WarningBrush="True" />
|
||||
</ResourceDictionary>
|
||||
</base:BaseView.Resources>
|
||||
<Grid Background="{DynamicResource Brush_ApplicationContentBackground}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="{strings:TranslateExtension SaveFile}" IsEnabled="{Binding SaveFileEnabled}" AutomationProperties.AutomationId="SaveFileButton" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding SaveFileClicked}" AutomationProperties.AutomationId="SaveFileClickedCommand" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<TextBlock Text="{strings:TranslateExtension TestName}" AutomationProperties.AutomationId="TestNameTextBlock" />
|
||||
<TextBox Text="{Binding TestName, UpdateSourceTrigger=PropertyChanged, FallbackValue=NO_LABEL}" Width="500"
|
||||
BorderBrush="{Binding IsTestNameValid, Converter={StaticResource BooleanToColor}}"
|
||||
BorderThickness="{Binding IsTestNameValid, Converter={StaticResource BooleanToBorderThickness}}" AutomationProperties.AutomationId="TestNameTextBox" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="LostFocus">
|
||||
<i:InvokeCommandAction Command="{Binding TestNameLostFocus}" CommandParameter="{Binding TestName}" AutomationProperties.AutomationId="TestNameLostFocusCommand" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Right">
|
||||
<TextBlock Text="{strings:TranslateExtension Search}" AutomationProperties.AutomationId="SearchTextBlock" Margin="3,0" VerticalAlignment="Center"/>
|
||||
<TextBox Text="{Binding Search}" AutomationProperties.AutomationId="SearchTextBox" Width="200" TextChanged="TextBox_TextChanged"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<TextBlock Text="{Binding NumChannelsAndSensors, FallbackValue=NO_LABEL}" HorizontalAlignment="Left" AutomationProperties.AutomationId="NumChannelAndSensorsTextBlock" />
|
||||
</StackPanel>
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ListView Grid.Row="0" Grid.Column="0" ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
ItemsSource="{Binding RequiredChannels}" SelectedItem="{Binding SelectedRequiredChannel}" AutomationProperties.AutomationId="RequiredChannelsListView" >
|
||||
<ListView.View>
|
||||
<controls:AutoSizedGridView>
|
||||
<GridViewColumn Header="{strings:TranslateExtension CH}" Width="50" DisplayMemberBinding="{Binding ChannelNumber}" AutomationProperties.AutomationId="ChannelNumber" />
|
||||
<GridViewColumn Header="{strings:TranslateExtension Code}" AutomationProperties.AutomationId="ChannelCode" >
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBox Text="{Binding ChannelCode, UpdateSourceTrigger=PropertyChanged}" MinWidth="180" AutomationProperties.AutomationId="ChannelCodeTextBox"
|
||||
BorderBrush="{Binding IsChannelCodeValid, Converter={StaticResource BooleanToColor}}"
|
||||
BorderThickness="{Binding IsChannelCodeValid, Converter={StaticResource BooleanToBorderThickness}}" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="LostFocus">
|
||||
<i:InvokeCommandAction Command="{Binding ControlLostFocus}" CommandParameter="{Binding ChannelCode}" AutomationProperties.AutomationId="ChannelCodeLostFocusCommand" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</TextBox>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension JHyphenCode}" AutomationProperties.AutomationId="JCode" >
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBox Text="{Binding JCodeOrDescription, UpdateSourceTrigger=PropertyChanged}" MinWidth="180"
|
||||
BorderBrush="{Binding IsJCodeValid, Converter={StaticResource BooleanToWarningColor}}"
|
||||
BorderThickness="{Binding IsJCodeValid, Converter={StaticResource BooleanToBorderThickness}}" AutomationProperties.AutomationId="JCodeTextBox" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="LostFocus">
|
||||
<i:InvokeCommandAction Command="{Binding ControlLostFocus}" CommandParameter="{Binding JCodeOrDescription}" AutomationProperties.AutomationId="JCodeOrDescriptionLostFocusCommand" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</TextBox>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Range}" AutomationProperties.AutomationId="Range" >
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBox Text="{Binding ChannelRangeString}" MinWidth="120" Visibility="{Binding RangeVisible}"
|
||||
BorderBrush="{Binding IsRangeValid, Converter={StaticResource BooleanToColor}}"
|
||||
BorderThickness="{Binding IsRangeValid, Converter={StaticResource BooleanToBorderThickness}}" AutomationProperties.AutomationId="RangeTextBox" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="LostFocus">
|
||||
<i:InvokeCommandAction Command="{Binding ControlLostFocus}" CommandParameter="{Binding ChannelRangeString}" AutomationProperties.AutomationId="RangeControlLostFocusCommand"/>
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</TextBox>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Filter}" AutomationProperties.AutomationId="Filter" >
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<ComboBox ItemsSource="{Binding Filters}" MinWidth="70"
|
||||
SelectedItem="{Binding FilterString, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding FilterVisible}"
|
||||
BorderBrush="{Binding IsFilterValid, Converter={StaticResource BooleanToColor}}"
|
||||
BorderThickness="{Binding IsFilterValid, Converter={StaticResource BooleanToBorderThickness}}"
|
||||
AutomationProperties.AutomationId="FilterComboBox">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="SelectionChanged">
|
||||
<i:InvokeCommandAction Command="{Binding FilterSelectionChanged}"
|
||||
CommandParameter="{Binding FilterString}" AutomationProperties.AutomationId="FilterSelectionChangedCommand" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</ComboBox>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension SensorSN}">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock MinWidth="170" Text="{Binding SensorSerialNumber}" AutomationProperties.AutomationId="SensorSerialNumber"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</controls:AutoSizedGridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
<StackPanel Orientation="Vertical" VerticalAlignment="Center" Grid.Row="0" Grid.Column="1">
|
||||
<Button Content="{strings:TranslateExtension EditFile_Replace}" IsEnabled="{Binding ReplaceEnabled}" Width="85" AutomationProperties.AutomationId="ReplaceButton" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding ReplaceCommand}" AutomationProperties.AutomationId="ReplaceCommand" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Content="{strings:TranslateExtension EditFile_AddCode}" IsEnabled="{Binding AddCodeEnabled}" Width="85" AutomationProperties.AutomationId="AddCodeButton" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding AddCodeCommand}" AutomationProperties.AutomationId="AddCodeCommand" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Content="{strings:TranslateExtension EditFile_DeleteCode}" IsEnabled="{Binding DeleteCodeEnabled}" Width="85" AutomationProperties.AutomationId="DeleteCodeButton" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding DeleteCodeCommand}" AutomationProperties.AutomationId="DeleteCodeCommand" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Content="{strings:TranslateExtension EditFile_AddSquib}" Width="85" AutomationProperties.AutomationId="AddSquibButton" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding AddSquibCommand}" AutomationProperties.AutomationId="AddSquibCommand" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Content="{strings:TranslateExtension EditFile_ADDDI}" Width="85" AutomationProperties.AutomationId="ADDDIButton" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding ADDDICommand}" AutomationProperties.AutomationId="ADDDICommand" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<ListView Grid.Row="0" Grid.Column="2"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
ItemsSource="{Binding SystemSensors}"
|
||||
SelectedItem="{Binding SelectedSystemSensor}" AutomationProperties.AutomationId="SystemSensorsListView" >
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Header="{strings:TranslateExtension SensorSN}" Width="200">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding SensorSerialNumber}" AutomationProperties.AutomationId="SysSensorSerialNumber" />
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</base:BaseView>
|
||||
@@ -0,0 +1,159 @@
|
||||
<base:BaseView x:Class="TTSImport.SummaryView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
|
||||
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:ttsImport="clr-namespace:TTSImport"
|
||||
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
xmlns:controls="clr-namespace:DTS.Common.Controls;assembly=DTS.Common"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="768" d:DesignWidth="1366">
|
||||
<base:BaseView.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/CommonStyles.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/brushes.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Controls/combobox.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="ItemContainerStyle" Value="{StaticResource TTS_ListViewItemStyle}"/>
|
||||
</Style>
|
||||
<Style TargetType="TextBox" BasedOn="{StaticResource TTS_TextBoxStyle}">
|
||||
<Setter Property="Margin" Value="0,0,3,3"/>
|
||||
</Style>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource TTS_TextBlockStyle}">
|
||||
<Setter Property="Margin" Value="0,0,3,3"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
</Style>
|
||||
<Style TargetType="CheckBox" BasedOn="{StaticResource PageContentCheckBoxStyle}" />
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource TTS_ComboBoxStyle}">
|
||||
<Setter Property="Height" Value="28"/>
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="Width" Value="150"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Left"/>
|
||||
<Setter Property="Margin" Value="0,0,3,3"/>
|
||||
</Style>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource TTS_ButtonStyle}"/>
|
||||
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource Gray_GridViewColumnHeaderStyle}"/>
|
||||
<Style TargetType="xctk:DoubleUpDown" BasedOn="{StaticResource PageContentXCDoubleUpDown}">
|
||||
<Setter Property="Increment" Value="0.1"/>
|
||||
<Setter Property="Width" Value="150"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Left"/>
|
||||
<Setter Property="Margin" Value="0,0,3,3"/>
|
||||
</Style>
|
||||
<converters:NonZeroToColorConverter x:Key="NonZeroToColor" />
|
||||
<converters:BooleanToBorderThicknessConverter x:Key="BooleanToBorderThickness" />
|
||||
<converters:BooleanToColorConverter x:Key="BooleanToColor" />
|
||||
</ResourceDictionary>
|
||||
</base:BaseView.Resources>
|
||||
<Grid Background="{DynamicResource Brush_ApplicationContentBackground}" >
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:CommonStatusRibbon Content="{Binding StatusAndProgressBarView}" Grid.Row="0" Grid.ColumnSpan="3" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="{ttsImport:TranslateExtension ImportFile}" VerticalAlignment="Top"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding ImportFileName}" VerticalAlignment="Top" AutomationProperties.AutomationId="ImportFileName" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="{ttsImport:TranslateExtension TestSetupName}" VerticalAlignment="Top"/>
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding TestSetupName}" Width="150" VerticalAlignment="Top" AutomationProperties.AutomationId="TestSetupName" />
|
||||
<Button Grid.Row="2" Grid.Column="2" Background="White" Content="{ttsImport:TranslateExtension Import}" Width="150"
|
||||
IsEnabled="{Binding ImportEnabled}" HorizontalAlignment="Left" AutomationProperties.AutomationId="btnImport" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding ImportClicked}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="{ttsImport:TranslateExtension TestId}"/>
|
||||
<StackPanel Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Orientation="Horizontal">
|
||||
<controls:TestIdControl x:Name="ctrlTestId" AutomationProperties.AutomationId="TestIdControl"/>
|
||||
<Button Background="White" Content="{ttsImport:TranslateExtension RunTest}" Width="150"
|
||||
Visibility="{Binding RunTestVisible}" HorizontalAlignment="Left" AutomationProperties.AutomationId="btnRunTest" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding RunTestClicked}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="{ttsImport:TranslateExtension SampleRate}" VerticalAlignment="Top"/>
|
||||
<ComboBox Grid.Row="4" Grid.Column="1" AutomationProperties.AutomationId="SampleRateComboBox"
|
||||
ItemsSource="{Binding AvailableSampleRates}" SelectedItem ="{Binding SampleRate, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
|
||||
<TextBlock Grid.Row="5" Grid.Column="0" Text="{ttsImport:TranslateExtension Mode}"/>
|
||||
<ComboBox Grid.Row="5" Grid.Column="1" AutomationProperties.AutomationId="ModeComboBox"
|
||||
ItemsSource="{Binding AvailableRecordingModes}"
|
||||
SelectedItem="{Binding RecordingMode, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0" Text="{ttsImport:TranslateExtension PreTrigger}" Visibility="{Binding SummaryPreTriggerVisibility}" />
|
||||
<xctk:DoubleUpDown Grid.Row="6" Grid.Column="1" Value="{Binding PreTrigger}" Minimum="0" AutomationProperties.AutomationId="PreTriggerUpDown"
|
||||
Visibility="{Binding SummaryPreTriggerVisibility}"/>
|
||||
|
||||
<TextBlock Grid.Row="7" Grid.Column="0" Text="{Binding PostTriggerOrTestLength}" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<xctk:DoubleUpDown Grid.Row="7" Grid.Column="1" Value="{Binding PostTrigger}" Minimum="0" AutomationProperties.AutomationId="PostTriggerUpDown" />
|
||||
|
||||
<TextBlock Grid.Row="8" Grid.Column="0" Text="{ttsImport:TranslateExtension ROIStart}" VerticalAlignment="Top" HorizontalAlignment="Left" />
|
||||
<xctk:DoubleUpDown Grid.Row="8" Grid.Column="1" Value="{Binding ROIStart}" AutomationProperties.AutomationId="ROIStartUpDown"
|
||||
BorderBrush="{Binding IsROIStartValid, Converter={StaticResource BooleanToColor}}"
|
||||
BorderThickness="{Binding IsROIStartValid, Converter={StaticResource BooleanToBorderThickness}}"/>
|
||||
|
||||
<TextBlock Grid.Row="9" Grid.Column="0" Text="{ttsImport:TranslateExtension ROIEnd}" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<xctk:DoubleUpDown Grid.Row="9" Grid.Column="1" Value="{Binding ROIEnd}" AutomationProperties.AutomationId="ROIEndUpDown"
|
||||
BorderBrush="{Binding IsROIEndValid, Converter={StaticResource BooleanToColor}}"
|
||||
BorderThickness="{Binding IsROIEndValid, Converter={StaticResource BooleanToBorderThickness}}"/>
|
||||
|
||||
<TextBlock Grid.Row="10" Grid.Column="0" Grid.ColumnSpan="3" Text="{Binding AAF_TDAS}" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<TextBlock Grid.Row="11" Grid.Column="0" Grid.ColumnSpan="3" Text="{Binding AAF_SLICE}" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<ScrollViewer Grid.Row="12" Grid.Column="0" Grid.ColumnSpan="3" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
||||
<ListView ItemsSource="{Binding SummaryChannelList}" HorizontalAlignment="Left">
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Header="{ttsImport:TranslateExtension Type}" Width="100" >
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding ChannelType,FallbackValue='Channel Type'}" Width="100" AutomationProperties.AutomationId="ChannelType" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{ttsImport:TranslateExtension Assigned}" Width="100">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Assigned,FallbackValue='Assigned'}" Width="100" AutomationProperties.AutomationId="Assigned" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{ttsImport:TranslateExtension Unassigned}" Width="100">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Unassigned,FallbackValue='Unassigned'}" Width="100" Background="{Binding Unassigned, Converter={StaticResource NonZeroToColor}}" AutomationProperties.AutomationId="Unassigned" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</base:BaseView>
|
||||
@@ -0,0 +1,622 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using DTS.Common.Events;
|
||||
using DTS.Common.Events.TTSImport;
|
||||
using DTS.Common.Interface.DataRecorders;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using TTSImport.Resources;
|
||||
using Application = System.Windows.Application;
|
||||
using DASChannel = TTSImport.Model.DASChannel;
|
||||
using MessageBox = System.Windows.MessageBox;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Enums;
|
||||
using TTSImport.Model;
|
||||
using Prism.Events;
|
||||
using Unity;
|
||||
using DTS.Common.Interactivity;
|
||||
using Prism.Regions;
|
||||
using Prism.Commands;
|
||||
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// this class handles Level Trigger edit/create functionality
|
||||
/// </summary>
|
||||
[PartCreationPolicy(CreationPolicy.Shared)]
|
||||
public class AnalogChannelsViewModel : IAnalogChannelsViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The Hardware Scan view
|
||||
/// </summary>
|
||||
public IAnalogChannelsView View { get; set; }
|
||||
|
||||
private IEventAggregator _eventAggregator { get; }
|
||||
private IRegionManager _regionManager;
|
||||
private IUnityContainer UnityContainer { get; }
|
||||
|
||||
public InteractionRequest<Notification> NotificationRequest { get; }
|
||||
public InteractionRequest<Confirmation> ConfirmationRequest { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Occurs when a property value changes.
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
public void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
#region constructors and initializers
|
||||
/// <summary>
|
||||
/// Creates a new instance of the TechnologyDomainEditViewModel.
|
||||
/// </summary>
|
||||
/// <param name="view"></param>
|
||||
/// <param name="regionManager">The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed.</param>
|
||||
/// <param name="eventAggregator">The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other.</param>
|
||||
/// <param name="unityContainer">The unityContainer.</param>
|
||||
public AnalogChannelsViewModel(IAnalogChannelsView view, IRegionManager regionManager,
|
||||
IEventAggregator eventAggregator, IUnityContainer unityContainer)
|
||||
{
|
||||
View = view;
|
||||
View.DataContext = this;
|
||||
|
||||
NotificationRequest = new InteractionRequest<Notification>();
|
||||
ConfirmationRequest = new InteractionRequest<Confirmation>();
|
||||
|
||||
_eventAggregator = eventAggregator;
|
||||
UnityContainer = unityContainer;
|
||||
_regionManager = regionManager;
|
||||
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
|
||||
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>()
|
||||
.Subscribe(OnBusyIndicatorNotification, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<AssignedChannelsChangedEvent>().Subscribe(OnAssignedChannelsChangedEvent,
|
||||
ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportHardwareScanFinishedEvent>()
|
||||
.Subscribe(OnHardwareScanComplete, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<EIDMappingEvent>()
|
||||
.Subscribe(OnEIDComplete, ThreadOption.PublisherThread, true);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
private void OnEIDComplete(IDictionary<string, string> sensorIdToChannelId)
|
||||
{
|
||||
var channelIdToSensorId = new Dictionary<string, string>();
|
||||
using (var e = sensorIdToChannelId.GetEnumerator())
|
||||
{
|
||||
while (e.MoveNext())
|
||||
{
|
||||
channelIdToSensorId[e.Current.Value] = e.Current.Key;
|
||||
}
|
||||
}
|
||||
_hardwareChannelIdToSensorId = channelIdToSensorId;
|
||||
}
|
||||
|
||||
public string Validate()
|
||||
{
|
||||
var bEmptyChannelCodes = false;
|
||||
|
||||
foreach (var channel in DASChannels)
|
||||
{
|
||||
if (null == channel.Channel)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(channel.ToyotaCode))
|
||||
{
|
||||
bEmptyChannelCodes = true;
|
||||
}
|
||||
}
|
||||
return bEmptyChannelCodes ? StringResources.EmptyChannelCodeWarning : string.Empty;
|
||||
}
|
||||
private void OnHardwareScanComplete(List<IDASHardware> hardware)
|
||||
{
|
||||
_hardware = hardware;
|
||||
}
|
||||
|
||||
private void OnAssignedChannelsChangedEvent(ITTSSetup setup)
|
||||
{
|
||||
if (!Application.Current.Dispatcher.CheckAccess())
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
OnAssignedChannelsChangedEvent(setup);
|
||||
}));
|
||||
return;
|
||||
}
|
||||
_setup = setup;
|
||||
if (null == _hardware || null == _setup) { return; }
|
||||
var channels = new ObservableCollection<DASChannel>();
|
||||
var remainingChannels = new ObservableCollection<ITTSChannelRecord>();
|
||||
|
||||
var channelIdToDASChannel = new Dictionary<string, DASChannel>();
|
||||
foreach (var das in _hardware)
|
||||
{
|
||||
if (das.IsSLICEEthernetController) { continue; }
|
||||
var ichannels = das.GetIHardwareChannels();
|
||||
foreach (var ch in ichannels)
|
||||
{
|
||||
if (!ch.IsAnalog) { continue; }
|
||||
var newChannel = new DASChannel(ch);
|
||||
if (_hardwareChannelIdToSensorId.ContainsKey(ch.GetId()))
|
||||
{
|
||||
newChannel.EID = _hardwareChannelIdToSensorId[ch.GetId()];
|
||||
}
|
||||
channels.Add(newChannel);
|
||||
channelIdToDASChannel[newChannel.HardwareChannel.GetId()] = newChannel;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var channelRecord in _setup.Channels)
|
||||
{
|
||||
if (channelRecord.IsEmptyRecord) { continue; }
|
||||
if (channelRecord.IsDigitalInput) { continue; }
|
||||
if (channelRecord.IsDigitalOutput) { continue; }
|
||||
if (channelRecord.IsSquib) { continue; }
|
||||
if (!channelRecord.IsChannelCodeValid) { continue; }
|
||||
if (channelRecord.ChannelCode == TTSChannelRecord.NONE) { continue; }
|
||||
if (null != channelRecord.HardwareChannel)
|
||||
{
|
||||
var key = channelRecord.HardwareChannel.GetId();
|
||||
if (channelIdToDASChannel.ContainsKey(key))
|
||||
{
|
||||
channelIdToDASChannel[key].SetITTSChannelRecord(channelRecord);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
remainingChannels.Add(channelRecord);
|
||||
}
|
||||
}
|
||||
|
||||
DASChannels = channels;
|
||||
RemainingChannels = remainingChannels;
|
||||
OnPropertyChanged("DASChannels");
|
||||
OnPropertyChanged("RemainingChannels");
|
||||
}
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
public Task CleanupAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter)
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter, object model)
|
||||
{
|
||||
}
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task InitializeAsync(object parameter)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Activated()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnBusyIndicatorNotification(bool eventArg)
|
||||
{
|
||||
IsBusy = eventArg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
|
||||
{
|
||||
// The NotificationRequest.Raise triggers the Invoke() method of the PopupWindowAction object to show the NotificationWindow window
|
||||
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
|
||||
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, "",
|
||||
eventArgsWithTitle.Image, string.Empty);
|
||||
|
||||
NotificationRequest.Raise(new Notification
|
||||
{
|
||||
Content = eventArgsWithoutTitle,
|
||||
Title = eventArgsWithTitle.Title
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
private ITTSSetup _setup;
|
||||
private IList<IDASHardware> _hardware;
|
||||
private IDictionary<string, string> _hardwareChannelIdToSensorId = new Dictionary<string, string>();
|
||||
public bool IsDirty { get; private set; }
|
||||
private bool _isBusy;
|
||||
|
||||
public bool IsBusy
|
||||
{
|
||||
get => _isBusy;
|
||||
set
|
||||
{
|
||||
_isBusy = value;
|
||||
OnPropertyChanged("IsBusy");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isMenuIncluded;
|
||||
|
||||
public bool IsMenuIncluded
|
||||
{
|
||||
get => _isMenuIncluded;
|
||||
set
|
||||
{
|
||||
_isMenuIncluded = value;
|
||||
OnPropertyChanged("IsMenuIncluded");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isNavigationIncluded;
|
||||
|
||||
public bool IsNavigationIncluded
|
||||
{
|
||||
get => _isNavigationIncluded;
|
||||
set
|
||||
{
|
||||
_isNavigationIncluded = value;
|
||||
OnPropertyChanged("IsNavigationIncluded");
|
||||
}
|
||||
}
|
||||
|
||||
public bool AssignEnabled { get; set; }
|
||||
public bool RemoveEnabled { get; set; }
|
||||
public bool EnableOrDisableEnabled { get; set; }
|
||||
public ObservableCollection<DASChannel> DASChannels { get; set; } = new ObservableCollection<DASChannel>();
|
||||
public ObservableCollection<ITTSChannelRecord> RemainingChannels { get; set; } =
|
||||
new ObservableCollection<ITTSChannelRecord>();
|
||||
|
||||
private ITTSChannelRecord _selectedRemainingChannel;
|
||||
public ITTSChannelRecord SelectedRemainingChannel
|
||||
{
|
||||
get => _selectedRemainingChannel;
|
||||
set
|
||||
{
|
||||
_selectedRemainingChannel = value;
|
||||
if (null == _selectedRemainingChannel || null == SelectedDASChannel) return;
|
||||
AssignEnabled = true;
|
||||
OnPropertyChanged("AssignEnabled");
|
||||
}
|
||||
}
|
||||
private DASChannel _selectedDASChannel;
|
||||
public DASChannel SelectedDASChannel
|
||||
{
|
||||
get => _selectedDASChannel;
|
||||
set
|
||||
{
|
||||
_selectedDASChannel = value;
|
||||
DetermineRemoveEnableStatus();
|
||||
}
|
||||
}
|
||||
public void DetermineRemoveEnableStatus()
|
||||
{
|
||||
if (_selectedDASChannel?.Channel != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(_selectedDASChannel.EID) &&
|
||||
_selectedDASChannel.EID == _selectedDASChannel.Channel.SensorEID)
|
||||
{
|
||||
//can only be replaced, can't be removed
|
||||
RemoveEnabled = false;
|
||||
}
|
||||
RemoveEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveEnabled = false;
|
||||
}
|
||||
OnPropertyChanged("RemoveEnabled");
|
||||
AssignEnabled = null != _selectedDASChannel && null != _selectedRemainingChannel;
|
||||
OnPropertyChanged("AssignEnabled");
|
||||
EnableOrDisableEnabled = null != _selectedDASChannel && null != _selectedDASChannel.Channel;
|
||||
OnPropertyChanged("EnableOrDisableEnabled");
|
||||
OnPropertyChanged("EnableOrDisableText");
|
||||
}
|
||||
|
||||
public string EnableOrDisableText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SelectedDASChannel?.Channel == null)
|
||||
{
|
||||
return StringResources.Analog_Enable;
|
||||
}
|
||||
return SelectedDASChannel.Channel.Disabled
|
||||
? StringResources.Analog_Enable
|
||||
: StringResources.Analog_Disable;
|
||||
}
|
||||
}
|
||||
#endregion Properties
|
||||
|
||||
#region Commands
|
||||
#region assign
|
||||
/// <summary>
|
||||
/// Assign a channel code to a channel
|
||||
/// </summary>
|
||||
private DelegateCommand _assignCommand;
|
||||
public DelegateCommand AssignCommand => _assignCommand ?? (_assignCommand = new DelegateCommand(Assign));
|
||||
private void Assign()
|
||||
{
|
||||
if (SelectedRemainingChannel == null) { return; }
|
||||
|
||||
var error = string.Empty;
|
||||
if (!VoltageIsValid(SelectedRemainingChannel, SelectedDASChannel, out error))
|
||||
{
|
||||
var window = Application.Current.MainWindow;
|
||||
if (null == window) { return; }
|
||||
MessageBox.Show(window, error, StringResources.AssignSensorExcitationError, MessageBoxButton.OK);
|
||||
return;
|
||||
}
|
||||
_eventAggregator.GetEvent<TTSImportTestSetupChangedEvent>().Publish(_setup);
|
||||
//BEFORE we go any further, check the state of sensor ids
|
||||
//if the channel has a sensor id AND there's a sensor on the channel with the same id
|
||||
//then prompt on replacing the id
|
||||
//IF the channel has a sensor id and there's no sensor on the channel BUT the new sensor has a different id
|
||||
//then prompt on replacing the id
|
||||
var bReplacingID = false;
|
||||
if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID))
|
||||
{
|
||||
if (null != SelectedRemainingChannel && SelectedRemainingChannel.SensorEID != SelectedDASChannel.EID)
|
||||
{
|
||||
bReplacingID = true;
|
||||
}
|
||||
//if existing channel has this ID, we will need to clear out the old id and assign a new one...
|
||||
if (null != SelectedDASChannel.Channel &&
|
||||
SelectedDASChannel.Channel.SensorEID == SelectedDASChannel.EID)
|
||||
{
|
||||
bReplacingID = true;
|
||||
}
|
||||
}
|
||||
else if (_setup.RequireEIDFound && !string.IsNullOrWhiteSpace(SelectedRemainingChannel.SensorEID))
|
||||
{
|
||||
var window = Application.Current.MainWindow;
|
||||
if (null == window) { return; }
|
||||
var msg = string.Format(StringResources.AllowEIDToBlankChannelChallenge, SelectedRemainingChannel.SensorSerialNumber);
|
||||
msg = msg.Replace("\\r\\n", "\r\n");
|
||||
|
||||
var dialogResult = MessageBox.Show(window, msg, StringResources.UserFeedbackRequired, MessageBoxButton.OKCancel);
|
||||
APILogger.Log(msg, $"User pressed {dialogResult.ToString()}");
|
||||
if (dialogResult == MessageBoxResult.OK)
|
||||
{
|
||||
SelectedRemainingChannel.SensorEID = string.Empty;
|
||||
AssignWork();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (bReplacingID)
|
||||
{
|
||||
var window = Application.Current.MainWindow;
|
||||
if (null == window) { return; }
|
||||
var dialogResult = MessageBox.Show(window, StringResources.AssignSensorPrompt, StringResources.UserFeedbackRequired, MessageBoxButton.YesNo);
|
||||
APILogger.Log(StringResources.AssignSensorPrompt, $"User pressed {dialogResult.ToString()}");
|
||||
if (dialogResult == MessageBoxResult.Yes)
|
||||
{
|
||||
AssignWork();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
AssignWork();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns True if the sensor's voltage is supported by the hardware channel, or an error message and False if not
|
||||
/// </summary>
|
||||
/// <param name="selectedRemainingChannel"></param>
|
||||
/// <param name="selectedDASChannel"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
private bool VoltageIsValid(ITTSChannelRecord selectedRemainingChannel, DASChannel selectedDASChannel, out string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
var voltageEnum = ExcitationVoltageOptions.ExcitationVoltageOption.Undefined;
|
||||
try
|
||||
{
|
||||
voltageEnum = Test.Module.Channel.Sensor.GetExcitationVoltageEnumFromMagnitude(selectedRemainingChannel.SensorExcitationVolts);
|
||||
}
|
||||
catch { } //GetExcitationVoltageEnumFromMagnitude will throw an exception if an invalid voltage is passed to it
|
||||
|
||||
if (selectedDASChannel.HardwareChannel.IsSupportedExcitation(voltageEnum)) return true;
|
||||
error = string.Format(StringResources.InvalidExcitationAssignment, selectedRemainingChannel.SensorExcitationVolts);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// removes the channel as a selected channel for any level triggers
|
||||
/// removes the channel as a possible channel for any level triggers
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
private void RemoveFromLevelTriggers(ITTSChannelRecord channel)
|
||||
{
|
||||
if (null != _setup)
|
||||
{
|
||||
foreach (var lt in _setup.LevelTriggers)
|
||||
{
|
||||
lt.Remove(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// adds the channel as a possible channel to any level triggers
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
private void AddToLevelTriggers(ITTSChannelRecord channel)
|
||||
{
|
||||
if (null != _setup)
|
||||
{
|
||||
foreach (var lt in _setup.LevelTriggers)
|
||||
{
|
||||
lt.Add(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// assigns a channel record to a physical channel
|
||||
/// </summary>
|
||||
private void AssignWork()
|
||||
{
|
||||
if (null == SelectedDASChannel || null == SelectedRemainingChannel) { return; }
|
||||
var excitation =
|
||||
Test.Module.Channel.Sensor.GetExcitationVoltageEnumFromMagnitude(SelectedRemainingChannel
|
||||
.SensorExcitationVolts);
|
||||
if (!SelectedDASChannel.HardwareChannel.IsSupportedExcitation(excitation))
|
||||
{
|
||||
var window = Application.Current.MainWindow;
|
||||
if (null == window) { return; }
|
||||
var msg = string.Format(StringResources.ExcitationNotSupportedByChannel, excitation.ToString());
|
||||
var result = MessageBox.Show(window, msg, StringResources.Warning, MessageBoxButton.OK);
|
||||
APILogger.Log(msg, $"user pressed {result.ToString()}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (null != SelectedDASChannel.Channel)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID))
|
||||
{
|
||||
SelectedDASChannel.Channel.SensorEID = "";
|
||||
}
|
||||
RemainingChannels.Add(SelectedDASChannel.Channel);
|
||||
RemoveFromLevelTriggers(SelectedDASChannel.Channel);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID))
|
||||
{
|
||||
SelectedRemainingChannel.SensorEID = SelectedDASChannel.EID;
|
||||
}
|
||||
|
||||
SelectedDASChannel.SetITTSChannelRecord(SelectedRemainingChannel);
|
||||
|
||||
AddToLevelTriggers(SelectedDASChannel.Channel);
|
||||
var channel = SelectedRemainingChannel;
|
||||
var index = RemainingChannels.IndexOf(channel);
|
||||
SelectedRemainingChannel = null;
|
||||
RemainingChannels.Remove(channel);
|
||||
CollectionViewSource.GetDefaultView(DASChannels)?.Refresh();
|
||||
if (index < RemainingChannels.Count)
|
||||
{
|
||||
SelectedRemainingChannel = RemainingChannels[index];
|
||||
OnPropertyChanged("SelectedRemainingChannel");
|
||||
}
|
||||
else if (RemainingChannels.Count > 0)
|
||||
{
|
||||
SelectedRemainingChannel = RemainingChannels[index - 1];
|
||||
OnPropertyChanged("SelectedRemainingChannel");
|
||||
}
|
||||
index = DASChannels.IndexOf(SelectedDASChannel);
|
||||
for (var i = index; i < DASChannels.Count; i++)
|
||||
{
|
||||
var dasChannel = DASChannels[i];
|
||||
if (null != dasChannel.Channel) { continue; }
|
||||
SelectedDASChannel = dasChannel;
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
//didn't find a match, start from the beginning?
|
||||
for (var i = 0; i < index; i++)
|
||||
{
|
||||
var dasChannel = DASChannels[i];
|
||||
if (null != dasChannel.Channel)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
SelectedDASChannel = dasChannel;
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
//if we get here there's no new channel to go to, change remove/enable/disable button status
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
DetermineRemoveEnableStatus();
|
||||
}
|
||||
#endregion
|
||||
#region remove
|
||||
private DelegateCommand _removeCommand;
|
||||
public DelegateCommand RemoveCommand => _removeCommand ?? (_removeCommand = new DelegateCommand(Remove));
|
||||
/// <summary>
|
||||
/// remove a hardware channel assignment (does not remove the channel from the test setup though?)
|
||||
/// </summary>
|
||||
private void Remove()
|
||||
{
|
||||
if (null == SelectedDASChannel || null == SelectedDASChannel.Channel) { return; }
|
||||
_eventAggregator.GetEvent<TTSImportTestSetupChangedEvent>().Publish(_setup);
|
||||
RemainingChannels.Add(SelectedDASChannel.Channel);
|
||||
SelectedDASChannel.SetITTSChannelRecord(null);
|
||||
CollectionViewSource.GetDefaultView(DASChannels)?.Refresh();
|
||||
var index = DASChannels.IndexOf(SelectedDASChannel);
|
||||
for (var i = index; i < DASChannels.Count; i++)
|
||||
{
|
||||
if (null == DASChannels[i].Channel) { continue; }
|
||||
SelectedDASChannel = DASChannels[i];
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < index; i++)
|
||||
{
|
||||
if (null == DASChannels[i].Channel) { continue; }
|
||||
SelectedDASChannel = DASChannels[i];
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
//if we get here there's no new channel to go to, but we need to set the remove/enable/disable button status
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
DetermineRemoveEnableStatus();
|
||||
}
|
||||
#endregion
|
||||
#region enableordisable
|
||||
private DelegateCommand _enableOrDisableCommand;
|
||||
public DelegateCommand EnableOrDisableCommand =>
|
||||
_enableOrDisableCommand ?? (_enableOrDisableCommand = new DelegateCommand(EnableOrDisable));
|
||||
/// <summary>
|
||||
/// enables or disables a channel in the test.
|
||||
/// </summary>
|
||||
private void EnableOrDisable()
|
||||
{
|
||||
if (SelectedDASChannel?.Channel == null) { return; }
|
||||
SelectedDASChannel.Channel.Disabled = !SelectedDASChannel.Channel.Disabled;
|
||||
SelectedDASChannel.Disabled = SelectedDASChannel.Channel.Disabled;
|
||||
if (SelectedDASChannel.Channel.Disabled)
|
||||
{
|
||||
RemoveFromLevelTriggers(SelectedDASChannel.Channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddToLevelTriggers(SelectedDASChannel.Channel);
|
||||
}
|
||||
OnPropertyChanged("EnableOrDisableText");
|
||||
_eventAggregator.GetEvent<TTSImportTestSetupChangedEvent>().Publish(_setup);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
<base:BaseView x:Class="TTSImport.TOMChannelsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="768" d:DesignWidth="1366"
|
||||
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
|
||||
xmlns:controls="clr-namespace:DTS.Common.Controls;assembly=DTS.Common"
|
||||
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
|
||||
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:strings="clr-namespace:TTSImport"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
|
||||
<base:BaseView.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/CommonStyles.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Controls/combobox.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="ItemContainerStyle" Value="{StaticResource TTS_ListViewItemStyle}"/>
|
||||
</Style>
|
||||
<Style TargetType="TextBox" BasedOn="{StaticResource TTS_TextBoxStyle}"/>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource TTS_TextBlockStyle}"/>
|
||||
<Style TargetType="CheckBox" BasedOn="{StaticResource PageContentCheckBoxStyle}" />
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource TTS_ComboBoxStyle}"/>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource TTS_ButtonStyle}"/>
|
||||
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource Gray_GridViewColumnHeaderStyle}"/>
|
||||
<Style TargetType="xctk:DoubleUpDown" BasedOn="{StaticResource PageContentXCDoubleUpDown}">
|
||||
<Setter Property="UpdateValueOnEnterKey" Value="True" />
|
||||
</Style>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
|
||||
</ResourceDictionary>
|
||||
</base:BaseView.Resources>
|
||||
<Grid Background="{DynamicResource Brush_ApplicationContentBackground}"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<WrapPanel Orientation="Vertical" VerticalAlignment="Center" Grid.Column="1">
|
||||
<Button Content="{strings:TranslateExtension Analog_Assign}" IsEnabled="{Binding AssignEnabled}" Width="85" AutomationProperties.AutomationId="TOM_AssignButton">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding AssignCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Content="{strings:TranslateExtension Analog_Remove}" IsEnabled="{Binding RemoveEnabled}" Width="85" AutomationProperties.AutomationId="TOM_RemoveButton">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding RemoveCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Content="{Binding EnableOrDisableText,FallbackValue=Enable}" IsEnabled="{Binding EnableOrDisableEnabled}" Width="85" AutomationProperties.AutomationId="TOM_EnableDisableButton">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding EnableOrDisableCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
<GroupBox Header="{strings:TranslateExtension RemainingChannels}" AutomationProperties.AutomationId="RemainingChannelsGroupBox" Grid.Column="2">
|
||||
<ListView ItemsSource="{Binding RemainingChannels}" SelectedItem="{Binding SelectedRemainingChannel}" AutomationProperties.AutomationId="RemainingChannelsListView">
|
||||
<ListView.View>
|
||||
<GridView AutomationProperties.AutomationId="RemainingChannelsGridView">
|
||||
<GridViewColumn Header="{strings:TranslateExtension ToyotaCode}" >
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock MinWidth="130" Text="{Binding ChannelCode}" AutomationProperties.AutomationId="RemainingChannelsChannelCode"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</GroupBox>
|
||||
<GroupBox Header="{strings:TranslateExtension DASChannels}" AutomationProperties.AutomationId="DASChannelsGroupBox" Grid.Column="0">
|
||||
<ListView ItemsSource="{Binding DASChannels}" SelectedItem="{Binding SelectedDASChannel}" AutomationProperties.AutomationId="DASChannelsListView">
|
||||
<ListView.View>
|
||||
<controls:AutoSizedGridView AutomationProperties.AutomationId="DASChannelsGridView">
|
||||
<GridViewColumn Header="{strings:TranslateExtension DASChannel}" AutomationProperties.AutomationId="DASChannel">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding DASChannelString}" MinWidth="230" AutomationProperties.AutomationId="DASChannelTextBlock"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
|
||||
<GridViewColumn Header="{strings:TranslateExtension Code}" AutomationProperties.AutomationId="ToyotaCode">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBox Text="{Binding ToyotaCode}" MinWidth="70" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="ToyotaCodeTextBox"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension JHyphenCode}" AutomationProperties.AutomationId="Name">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBox Text="{Binding Name}" MinWidth="140" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="NameTextBox"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Mode}" AutomationProperties.AutomationId="Mode">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<ComboBox MinWidth="270" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="ModeComboBox"
|
||||
ItemsSource="{Binding SquibFireModes}" SelectedItem="{Binding SquibFireMode, UpdateSourceTrigger=PropertyChanged}" Padding="0" Height="28"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Current}" AutomationProperties.AutomationId="Current">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<xctk:DoubleUpDown Value="{Binding SquibFireCurrent}" MinWidth="70" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="CurrentUpDown"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Delay}" AutomationProperties.AutomationId="Delay">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<xctk:DoubleUpDown Value="{Binding SquibFireDelayMs}" MinWidth="70" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="DelayUpDown" Minimum="0" Maximum="99000"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension LimitDuration}" AutomationProperties.AutomationId="LimitDuration">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<CheckBox MinWidth="70" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="LimitDurationCheckBox" IsChecked="{Binding LimitDuration}"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Duration}" AutomationProperties.AutomationId="Duration">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<xctk:DoubleUpDown Value="{Binding SquibFireDurationMs}" MinWidth="70" Visibility="{Binding LimitDuration, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="DurationUpDown" Minimum=".20" Maximum="25.5"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension ResLowTolerance}" AutomationProperties.AutomationId="ResLowTolerance">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<xctk:DoubleUpDown Value="{Binding SquibFireResistanceLowOhm}" MinWidth="70" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="ResLowToleranceUpDown" Maximum="8" Minimum="1"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension ResHighTolerance}" AutomationProperties.AutomationId="ResHighTolerance">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<xctk:DoubleUpDown Value="{Binding SquibFireResistanceHighOhm}" MinWidth="70" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="ResHighToleranceUpDown" Maximum="8" Minimum="1"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</controls:AutoSizedGridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</base:BaseView>
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
[MarkupExtensionReturnTypeAttribute(typeof(string))]
|
||||
public class TranslateExtension : MarkupExtension
|
||||
{
|
||||
private readonly string _key;
|
||||
public TranslateExtension(string key) { _key = key; }
|
||||
|
||||
public const string NotFound = "#stringnotfound#";
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_key)) { return NotFound; }
|
||||
return Resources.StringResources.ResourceManager.GetString(_key) ?? NotFound + " " + _key;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="TTSImport.Properties" GeneratedClassName="Settings">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="DefaultTestImportMethod" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<section name="TTSImport.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<userSettings>
|
||||
<TTSImport.Properties.Settings>
|
||||
<setting name="DefaultTestImportMethod" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
</TTSImport.Properties.Settings>
|
||||
</userSettings>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
|
||||
@@ -0,0 +1,87 @@
|
||||
<base:BaseView x:Class="TTSImport.DigitalOutputChannelsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="768" d:DesignWidth="1366"
|
||||
xmlns:controls="clr-namespace:DTS.Common.Controls;assembly=DTS.Common"
|
||||
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
|
||||
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
|
||||
xmlns:strings="clr-namespace:TTSImport"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
|
||||
<base:BaseView.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/CommonStyles.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Controls/combobox.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="ItemContainerStyle" Value="{StaticResource TTS_ListViewItemStyle}"/>
|
||||
</Style>
|
||||
<Style TargetType="TextBox" BasedOn="{StaticResource TTS_TextBoxStyle}"/>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource TTS_TextBlockStyle}"/>
|
||||
<Style TargetType="CheckBox" BasedOn="{StaticResource PageContentCheckBoxStyle}" />
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource TTS_ComboBoxStyle}"/>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource TTS_ButtonStyle}"/>
|
||||
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource Gray_GridViewColumnHeaderStyle}"/>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibility" />
|
||||
</ResourceDictionary>
|
||||
</base:BaseView.Resources>
|
||||
<Grid Background="{DynamicResource Brush_ApplicationContentBackground}">
|
||||
<GroupBox Header="{strings:TranslateExtension DASChannels}" AutomationProperties.AutomationId="DODASChannelsGroupBox">
|
||||
<ListView ItemsSource="{Binding DASChannels}" SelectedItem="{Binding SelectedDASChannel}" AutomationProperties.AutomationId="DASChannelsListView">
|
||||
<ListView.Resources>
|
||||
<Style TargetType="{x:Type ListViewItem}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Disabled}" Value="True">
|
||||
<Setter Property="Background" Value="Gray" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ListView.Resources>
|
||||
<ListView.View>
|
||||
<controls:AutoSizedGridView AutomationProperties.AutomationId="DASChannelsGridView">
|
||||
<GridViewColumn Header="{strings:TranslateExtension DASChannel}">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding DASChannelString}" MinWidth="230" AutomationProperties.AutomationId="DASChannelTextBlock"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Mode}" AutomationProperties.AutomationId="Mode">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<ComboBox MinWidth="270" AutomationProperties.AutomationId="ModeComboBox" ItemsSource="{Binding OutputModes}" SelectedItem="{Binding DigitalOutputMode, UpdateSourceTrigger=PropertyChanged}" Padding="0" Height="28"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Delay}" AutomationProperties.AutomationId="Delay">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<xctk:DoubleUpDown Value="{Binding DigitalOutputDelayMs}" MinWidth="70" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="DelayUpDown" Minimum="0" Maximum="99000"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension LimitDuration}" AutomationProperties.AutomationId="LimitDuration">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<CheckBox MinWidth="70" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="LimitDurationCheckBox" IsChecked="{Binding LimitDuration}"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Duration}" AutomationProperties.AutomationId="Duration">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<xctk:DoubleUpDown Value="{Binding DigitalOutputDurationMs}" MinWidth="70" Visibility="{Binding LimitDuration, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="DurationUpDown" />
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</controls:AutoSizedGridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</base:BaseView>
|
||||
@@ -0,0 +1,93 @@
|
||||
<base:BaseView x:Class="TTSImport.LevelTriggerView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
|
||||
xmlns:strings="clr-namespace:TTSImport"
|
||||
xmlns:xceed="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit"
|
||||
xmlns:controls="clr-namespace:DTS.Common.Controls;assembly=DTS.Common"
|
||||
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="768" d:DesignWidth="1366">
|
||||
<base:BaseView.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/CommonStyles.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Controls/combobox.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="ItemContainerStyle" Value="{StaticResource TTS_ListViewItemStyle}"/>
|
||||
</Style>
|
||||
<Style TargetType="TextBox" BasedOn="{StaticResource TTS_TextBoxStyle}"/>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource TTS_TextBlockStyle}"/>
|
||||
<Style TargetType="CheckBox" BasedOn="{StaticResource PageContentCheckBoxStyle}" />
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource TTS_ComboBoxStyle}"/>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource TTS_ButtonStyle}"/>
|
||||
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource Gray_GridViewColumnHeaderStyle}"/>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
|
||||
</ResourceDictionary>
|
||||
</base:BaseView.Resources>
|
||||
<Grid Background="{DynamicResource Brush_ApplicationContentBackground}" >
|
||||
|
||||
<ListView ItemsSource="{Binding LevelTriggers, UpdateSourceTrigger=PropertyChanged}" AutomationProperties.AutomationId="LevelTriggersListView">
|
||||
<ListView.View>
|
||||
<controls:AutoSizedGridView AutomationProperties.AutomationId="LevelTriggersGridView">
|
||||
<GridViewColumn Header="{strings:TranslateExtension Code}" AutomationProperties.AutomationId="ChannelCode">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<ComboBox SelectedItem="{Binding Channel}" ItemsSource="{Binding AvailableChannels, UpdateSourceTrigger=PropertyChanged}"
|
||||
MinWidth="235" DisplayMemberPath="ChannelCode" AutomationProperties.AutomationId="ChannelCodeComboBox"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension JHyphenCode}" >
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock MinWidth="80" Text="{Binding JCode,FallbackValue='JCODE'}" AutomationProperties.AutomationId="JCode"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension ValuePercent}" AutomationProperties.AutomationId="ValuePercent">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<xceed:DoubleUpDown Value="{Binding ValuePercent}" MinWidth="70" DefaultValue="0"
|
||||
Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="ValuePercentUpDown"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension ValueEU}" AutomationProperties.AutomationId="ValueEU">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<xceed:DoubleUpDown Value="{Binding ValueEU}" MinWidth="70" DefaultValue="0"
|
||||
Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="ValueEUUpDown"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension EULabel}" AutomationProperties.AutomationId="EU">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock MinWidth="100" Text="{Binding EULabel}" AutomationProperties.AutomationId="EUTextBlock" />
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension HWSerialNumber}" AutomationProperties.AutomationId="HWChannelInfo">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock MinWidth="250" Text="{Binding HWSerialNumber}" AutomationProperties.AutomationId="HWChannelInfoTextBlock" />
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension CHAN}" AutomationProperties.AutomationId="ChannelNumber">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding ChannelNumber,FallbackValue='001',StringFormat={}{0:000}}" AutomationProperties.AutomationId="ChannelNumberTextBlock" MinWidth="85" TextAlignment="Right"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</controls:AutoSizedGridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</base:BaseView>
|
||||
@@ -0,0 +1,17 @@
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for HardwareScanView.xaml
|
||||
/// </summary>
|
||||
public partial class TOMChannelsView : ITOMChannelsView
|
||||
{
|
||||
public TOMChannelsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TTSImport.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public int DefaultTestImportMethod {
|
||||
get {
|
||||
return ((int)(this["DefaultTestImportMethod"]));
|
||||
}
|
||||
set {
|
||||
this["DefaultTestImportMethod"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<base:BaseView x:Class="TTSImport.DigitalInputChannelsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
|
||||
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:strings="clr-namespace:TTSImport"
|
||||
xmlns:controls="clr-namespace:DTS.Common.Controls;assembly=DTS.Common"
|
||||
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="768" d:DesignWidth="1366">
|
||||
<base:BaseView.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/CommonStyles.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Controls/combobox.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="ItemContainerStyle" Value="{StaticResource TTS_ListViewItemStyle}"/>
|
||||
</Style>
|
||||
<Style TargetType="TextBox" BasedOn="{StaticResource TTS_TextBoxStyle}"/>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource TTS_TextBlockStyle}"/>
|
||||
<Style TargetType="CheckBox" BasedOn="{StaticResource PageContentCheckBoxStyle}" />
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource TTS_ComboBoxStyle}"/>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource TTS_ButtonStyle}"/>
|
||||
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource Gray_GridViewColumnHeaderStyle}"/>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibility" />
|
||||
</ResourceDictionary>
|
||||
</base:BaseView.Resources>
|
||||
<Grid Background="{DynamicResource Brush_ApplicationContentBackground}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<GroupBox Header="{strings:TranslateExtension DASChannels}" AutomationProperties.AutomationId="DASChannelsGroupBox" Grid.Column="0">
|
||||
<ListView ItemsSource="{Binding DASChannels}" SelectedItem="{Binding SelectedDASChannel}" AutomationProperties.AutomationId="DASChannelsListView">
|
||||
<ListView.Resources>
|
||||
<Style TargetType="{x:Type ListViewItem}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Disabled}" Value="True">
|
||||
<Setter Property="Background" Value="Gray" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ListView.Resources>
|
||||
<ListView.View>
|
||||
<controls:AutoSizedGridView AutomationProperties.AutomationId="DASChannelsGridView">
|
||||
<GridViewColumn Header="{strings:TranslateExtension DASChannel}" AutomationProperties.AutomationId="DASChannel">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding DASChannelString}" MinWidth="230" AutomationProperties.AutomationId="DASChannelTextBlock"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
|
||||
<GridViewColumn Header="{strings:TranslateExtension Code}" AutomationProperties.AutomationId="ToyotaCode">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBox Text="{Binding ToyotaCode}" MinWidth="70" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="ToyotaCodeTextBox"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension JHyphenCode}" AutomationProperties.AutomationId="Name">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBox Text="{Binding Name}" MinWidth="140" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="NameTextBox"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</controls:AutoSizedGridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</GroupBox>
|
||||
<StackPanel Orientation="Vertical" VerticalAlignment="Center" Grid.Column="1">
|
||||
<Button Content="{strings:TranslateExtension Analog_Assign}" IsEnabled="{Binding AssignEnabled}" Width="85" AutomationProperties.AutomationId="DI_AssignButton">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding AssignCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Content="{strings:TranslateExtension Analog_Remove}" IsEnabled="{Binding RemoveEnabled}" Width="85" AutomationProperties.AutomationId="DI_RemoveButton">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding RemoveCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Content="{Binding EnableOrDisableText,FallbackValue=Enable}" IsEnabled="{Binding EnableOrDisableEnabled}" Width="85" AutomationProperties.AutomationId="DI_EnableDisableButton">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding EnableOrDisableCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<GroupBox Header="{strings:TranslateExtension RemainingChannels}" AutomationProperties.AutomationId="RemainingChannelsGroupBox" Grid.Column="2">
|
||||
<ListView ItemsSource="{Binding RemainingChannels}" SelectedItem="{Binding SelectedRemainingChannel}" AutomationProperties.AutomationId="RemainingChannelsListView">
|
||||
<ListView.View>
|
||||
<controls:AutoSizedGridView AutomationProperties.AutomationId="RemainingChannelsGridView">
|
||||
<GridViewColumn Header="{strings:TranslateExtension ToyotaCode}" AutomationProperties.AutomationId="ToyotaCode">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding ChannelCode}" MinWidth="130" AutomationProperties.AutomationId="ToyotaCodeTextBlock"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</controls:AutoSizedGridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</base:BaseView>
|
||||
@@ -0,0 +1,613 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using DTS.Common.Base;
|
||||
using DTS.Common.Classes;
|
||||
using DTS.Common.Events;
|
||||
using DTS.Common.Events.TTSImport;
|
||||
using DTS.Common.Interface;
|
||||
using DTS.Common.Interface.DataRecorders;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.HardwareScan;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using Prism.Events;
|
||||
using Unity;
|
||||
using DTS.Common.Interactivity;
|
||||
using Prism.Regions;
|
||||
using Prism.Commands;
|
||||
using TTSImport.Model;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// this class handles Hardware Scan functionality
|
||||
/// </summary>
|
||||
[PartCreationPolicy(CreationPolicy.Shared)]
|
||||
public class HardwareScanViewModel : IHardwareScanViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The Status and Progress bars
|
||||
/// </summary>
|
||||
public IStatusAndProgressBarView StatusAndProgressBarView { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Hardware Scan view
|
||||
/// </summary>
|
||||
public IHardwareScanView View { get; set; }
|
||||
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private IRegionManager _regionManager;
|
||||
private IUnityContainer UnityContainer { get; set; }
|
||||
|
||||
public InteractionRequest<Notification> NotificationRequest { get; private set; }
|
||||
public InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the TechnologyDomainEditViewModel.
|
||||
/// </summary>
|
||||
/// <param name="hardwareScanView">The Hardware Scan View.</param>
|
||||
/// <param name="regionManager">The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed.</param>
|
||||
/// <param name="eventAggregator">The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other.</param>
|
||||
/// <param name="unityContainer">The unityContainer.</param>
|
||||
public HardwareScanViewModel(IHardwareScanView hardwareScanView, IRegionManager regionManager,
|
||||
IEventAggregator eventAggregator, IUnityContainer unityContainer)
|
||||
{
|
||||
View = hardwareScanView;
|
||||
View.DataContext = this;
|
||||
|
||||
NotificationRequest = new InteractionRequest<Notification>();
|
||||
ConfirmationRequest = new InteractionRequest<Confirmation>();
|
||||
|
||||
_eventAggregator = eventAggregator;
|
||||
UnityContainer = unityContainer;
|
||||
_regionManager = regionManager;
|
||||
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
|
||||
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Subscribe(OnBusyIndicatorNotification, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportReadFileStatusEvent>().Subscribe(OnReadFileFinished, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportHardwareScanFinishedEvent>().Subscribe(OnHardwareScanFinished, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<AssignedChannelsChangedEvent>().Subscribe(OnAssignedChannelsChangedEvent, ThreadOption.PublisherThread, true);
|
||||
}
|
||||
|
||||
#region Methods
|
||||
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
public Task CleanupAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter)
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter, object model)
|
||||
{
|
||||
}
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
StatusAndProgressBarView = GetStatusAndProgressBarView(this);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task InitializeAsync(object parameter)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Activated()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnBusyIndicatorNotification(bool eventArg)
|
||||
{
|
||||
IsBusy = eventArg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
|
||||
{
|
||||
// The NotificationRequest.Raise triggers the Invoke() method of the PopupWindowAction object to show the NotificationWindow window
|
||||
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
|
||||
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, "",
|
||||
eventArgsWithTitle.Image, string.Empty);
|
||||
|
||||
NotificationRequest.Raise(new Notification
|
||||
{
|
||||
Content = eventArgsWithoutTitle,
|
||||
Title = eventArgsWithTitle.Title
|
||||
});
|
||||
}
|
||||
|
||||
private readonly StatusAndProgressBarEventArgs statusAndProgressBarEventArgs = new StatusAndProgressBarEventArgs();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the text, background color, progress value, and/or progress visibility
|
||||
/// </summary>
|
||||
/// <param name="status"></param>
|
||||
public void SetStatus(string status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case "Waiting": //change this to string resources but use the same one in DataPRO and here???
|
||||
statusAndProgressBarEventArgs.StatusColor =
|
||||
DTS.Common.BrushesAndColors.Brush_ApplicationStatus_Waiting.Color;
|
||||
statusAndProgressBarEventArgs.ProgressBarVisibility = Visibility.Collapsed;
|
||||
break;
|
||||
case "Working":
|
||||
statusAndProgressBarEventArgs.StatusColor =
|
||||
DTS.Common.BrushesAndColors.Brush_ApplicationStatus_Busy.Color;
|
||||
statusAndProgressBarEventArgs.ProgressValue = 0;
|
||||
statusAndProgressBarEventArgs.ProgressBarVisibility = Visibility.Visible;
|
||||
break;
|
||||
case "Failed":
|
||||
statusAndProgressBarEventArgs.StatusColor =
|
||||
DTS.Common.BrushesAndColors.Brush_ApplicationStatus_Failed.Color;
|
||||
statusAndProgressBarEventArgs.ProgressBarVisibility = Visibility.Collapsed;
|
||||
break;
|
||||
case "Done":
|
||||
statusAndProgressBarEventArgs.StatusColor =
|
||||
DTS.Common.BrushesAndColors.Brush_ApplicationStatus_Complete.Color;
|
||||
statusAndProgressBarEventArgs.ProgressBarVisibility = Visibility.Collapsed;
|
||||
break;
|
||||
}
|
||||
statusAndProgressBarEventArgs.StatusText = status;
|
||||
|
||||
statusAndProgressBarEventArgs.Requester = this;
|
||||
_eventAggregator.GetEvent<StatusAndProgressBarEvent>().Publish(statusAndProgressBarEventArgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the progress value on the Status and Progress bar
|
||||
/// </summary>
|
||||
/// <param name="progress"></param>
|
||||
public void SetProgress(double progress)
|
||||
{
|
||||
statusAndProgressBarEventArgs.ProgressValue = (int)progress;
|
||||
statusAndProgressBarEventArgs.Requester = this;
|
||||
_eventAggregator.GetEvent<StatusAndProgressBarEvent>().Publish(statusAndProgressBarEventArgs);
|
||||
}
|
||||
|
||||
private IStatusAndProgressBarView GetStatusAndProgressBarView(IBaseViewModel parent)
|
||||
{
|
||||
var view = UnityContainer.Resolve<IStatusAndProgressBarView>();
|
||||
var viewModel = UnityContainer.Resolve<IStatusAndProgressBarViewModel>();
|
||||
view.DataContext = viewModel;
|
||||
viewModel.Initialize(parent);
|
||||
return view;
|
||||
}
|
||||
|
||||
private void OnReadFileFinished(ReadFileStatusArg statusArg)
|
||||
{
|
||||
if (statusArg.Status)
|
||||
{
|
||||
_setup = statusArg.TTSSetup;
|
||||
}
|
||||
}
|
||||
|
||||
public void HardwareScan()
|
||||
{
|
||||
SetStatus(Resources.StringResources
|
||||
.ImportTestSetup_PossibleStatus_Working); //use string resource (same both here and where passed)
|
||||
var data = new WorkFunctionThreadData();
|
||||
ThreadPool.QueueUserWorkItem(HardwareScanWorkThread, data);
|
||||
}
|
||||
|
||||
void HardwareScanWorkThread(object obj)
|
||||
{
|
||||
ITTSSetup temp = null;
|
||||
//Blank out the tables before re-scanning
|
||||
HardwareRecords[0].Update(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
DasSummaryList = new List<IDASHardware>();
|
||||
ChannelSummaryList = new List<ChannelSummary>();
|
||||
_eventAggregator.GetEvent<TTSImportHardwareScanRunEvent>().Publish(temp); //temp not needed?
|
||||
}
|
||||
|
||||
private void UpdateUnitCount(IDASHardware hardwareRecord, ref uint sps, ref uint spd, ref uint spt, ref uint ecm,
|
||||
ref uint g5, ref uint rack)
|
||||
{
|
||||
if (hardwareRecord.SerialNumber.Length < 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var firstThree = hardwareRecord.SerialNumber.Substring(0, 3).ToLower();
|
||||
switch (firstThree)
|
||||
{
|
||||
case "spt": spt++; break;
|
||||
case "spd": spd++; break;
|
||||
case "sps": sps++; break;
|
||||
case "spe": ecm++; break;
|
||||
case "slt": spt++; break;
|
||||
case "sld": spd++; break;
|
||||
case "sle": ecm++; break;
|
||||
case "sls": sps++; break;
|
||||
case "sg5": g5++; break;
|
||||
}
|
||||
var firstTwo = hardwareRecord.SerialNumber.Substring(0, 2).ToLower();
|
||||
switch (firstTwo)
|
||||
{
|
||||
case "dr": rack++; break;
|
||||
case "lr": rack++; break;
|
||||
case "5m": g5++; break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns IP addresses for which SLICE2 modules have been found without a corresponding ECM/SLE
|
||||
/// </summary>
|
||||
/// <param name="hardwareRecords"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<string> GetMissingECMIPAddresses(List<IDASHardware> hardwareRecords)
|
||||
{
|
||||
var foundECMIPAddresses = new HashSet<string>();
|
||||
var missingECMIPAddresses = new List<string>();
|
||||
foreach (var hardwareRecord in hardwareRecords)
|
||||
{
|
||||
if (!hardwareRecord.IsSLICEEthernetController) continue;
|
||||
var ipAddress = hardwareRecord.Connection;
|
||||
var index = ipAddress.IndexOf(':');
|
||||
if (index > 0)
|
||||
{
|
||||
ipAddress = ipAddress.Substring(0, index);
|
||||
}
|
||||
foundECMIPAddresses.Add(ipAddress);
|
||||
}
|
||||
foreach (var hardwareRecord in hardwareRecords)
|
||||
{
|
||||
if (hardwareRecord.SerialNumber.Length < 3) { continue; }
|
||||
var ipAddress = hardwareRecord.Connection.ToLower();
|
||||
var index = ipAddress.IndexOf(':');
|
||||
if (index > 0)
|
||||
{
|
||||
ipAddress = ipAddress.Substring(0, index);
|
||||
}
|
||||
if (foundECMIPAddresses.Contains(ipAddress)) { continue; }
|
||||
if (missingECMIPAddresses.Contains(ipAddress)) { continue; }
|
||||
var firstThree = hardwareRecord.SerialNumber.Substring(0, 3).ToLower();
|
||||
switch (firstThree)
|
||||
{
|
||||
case "spt":
|
||||
case "spd":
|
||||
case "sps":
|
||||
case "slt":
|
||||
case "sld":
|
||||
case "sls":
|
||||
if (ipAddress.Contains("usb") || ipAddress.Length < 6) { continue; }
|
||||
missingECMIPAddresses.Add(ipAddress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return missingECMIPAddresses;
|
||||
}
|
||||
/// <summary>
|
||||
/// Fill in the table of DAS that are in the database and connected
|
||||
/// </summary>
|
||||
/// <param name="hardwareRecords"></param>
|
||||
private void OnHardwareScanFinished(List<IDASHardware> hardwareRecords)
|
||||
{
|
||||
//Create mapping from IP address to ECM/SDB/Rack
|
||||
var connectionToParent =
|
||||
hardwareRecords.Where(hardwareRecord => hardwareRecord.IsSLICEEthernetController ||
|
||||
hardwareRecord.IsTDASRack()).ToDictionary(hardwareRecord => hardwareRecord.Connection, hardwareRecord => hardwareRecord.SerialNumber);
|
||||
|
||||
var moduleRecords = new List<IDASHardware>();
|
||||
uint analog = 0;
|
||||
uint din = 0;
|
||||
uint dout = 0;
|
||||
uint squib = 0;
|
||||
uint sps = 0;
|
||||
uint spd = 0;
|
||||
uint spt = 0;
|
||||
uint ecm = 0;
|
||||
uint g5 = 0;
|
||||
uint rack = 0;
|
||||
|
||||
var missingECMIPS = GetMissingECMIPAddresses(hardwareRecords);
|
||||
if (missingECMIPS.Any())
|
||||
{
|
||||
var prompt = $"{Resources.StringResources.MissingECMSWarning}\r\n";
|
||||
prompt += string.Join("\r\n", missingECMIPS.ToArray());
|
||||
var mreLocal = new ManualResetEvent(false);
|
||||
APILogger.Log("MessageBox", prompt);
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
var window = Application.Current.MainWindow;
|
||||
if (null == window)
|
||||
{
|
||||
return;
|
||||
}
|
||||
MessageBox.Show(window, prompt, Resources.StringResources.Warning,
|
||||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
mreLocal.Set();
|
||||
}));
|
||||
mreLocal.WaitOne();
|
||||
}
|
||||
|
||||
foreach (var hardwareRecord in hardwareRecords)
|
||||
{
|
||||
//We don't want to list bridges, but we do want to list modules in a TDAS Rack, and DAS connected via ECM, SDB, and USB.
|
||||
//Modules in a TDAS Rack have IsModule() == false.
|
||||
//DAS connected via ECM or SDB have a hardwareRecord.Connection that's in the connectionToParent dictionary above.
|
||||
//DAS connected via USB have a hardwareRecord.Connection == "USB".
|
||||
if (hardwareRecord.IsModule() &&
|
||||
!connectionToParent.ContainsKey(hardwareRecord.Connection) &&
|
||||
hardwareRecord.Connection != "USB") continue;
|
||||
|
||||
UpdateUnitCount(hardwareRecord, ref sps, ref spd, ref spt, ref ecm, ref g5, ref rack);
|
||||
|
||||
//We want to display TDAS Racks, ECM, and SDBs in a separate row for their battery and
|
||||
//voltage status but also as a parent of their connected DAS.
|
||||
if (!hardwareRecord.IsSLICEEthernetController && !hardwareRecord.IsTDASRack())
|
||||
{
|
||||
//Display the DAS with its associated parent (TDAS Rack/ECM/SDB)
|
||||
var parentDAS = connectionToParent.ContainsKey(hardwareRecord.Connection)
|
||||
? connectionToParent[hardwareRecord.Connection]
|
||||
: hardwareRecord.ParentDAS;
|
||||
if (!string.IsNullOrWhiteSpace(parentDAS))
|
||||
{
|
||||
//DAS connected via USB have a blank ParentDAS
|
||||
//When the hardwareRecord.ToString() override is implemented for all DAS types, the following
|
||||
//can be modified to use it. Currently, only Slice DAS connected via ECM return "<parent>:<das>".
|
||||
hardwareRecord.SerialNumberFamily = "[" + parentDAS + ":" + hardwareRecord.SerialNumber + "]";
|
||||
}
|
||||
else
|
||||
{
|
||||
hardwareRecord.SerialNumberFamily = hardwareRecord.SerialNumber;
|
||||
}
|
||||
UpdateChannelCount(hardwareRecord, ref analog, ref squib, ref din, ref dout);
|
||||
}
|
||||
else
|
||||
{
|
||||
hardwareRecord.SerialNumberFamily = hardwareRecord.SerialNumber;
|
||||
if (hardwareRecord.IsTDASRack())
|
||||
{
|
||||
UpdateChannelCount(hardwareRecord, ref analog, ref squib, ref din, ref dout);
|
||||
}
|
||||
}
|
||||
moduleRecords.Add(hardwareRecord);
|
||||
}
|
||||
HardwareRecords[0].Update(analog, squib, din, dout, ecm, sps, spt, spd, g5, rack);
|
||||
|
||||
DasSummaryList = moduleRecords;
|
||||
|
||||
SetStatus(hardwareRecords.Any()
|
||||
? Resources.StringResources.ImportTestSetup_PossibleStatus_Done
|
||||
: Resources.StringResources.ImportTestSetup_PossibleStatus_Failed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// counts the number of analog/squib/digitalin/digitalout on given hardware and updates count
|
||||
/// </summary>
|
||||
/// <param name="hardwareRecord"></param>
|
||||
/// <param name="analog"></param>
|
||||
/// <param name="squib"></param>
|
||||
/// <param name="din"></param>
|
||||
/// <param name="dout"></param>
|
||||
private static void UpdateChannelCount(IDASHardware hardwareRecord, ref uint analog, ref uint squib, ref uint din,
|
||||
ref uint dout)
|
||||
{
|
||||
var channels = hardwareRecord.GetIHardwareChannels();
|
||||
for (var i = 0; i < channels.Length; i++)
|
||||
{
|
||||
var ch = channels[i];
|
||||
if (ch.IsAnalog)
|
||||
{
|
||||
analog++;
|
||||
}
|
||||
else if (ch.IsDigitalIn)
|
||||
{
|
||||
din++;
|
||||
}
|
||||
else if (ch.IsDigitalOut)
|
||||
{
|
||||
dout++;
|
||||
}
|
||||
else if (ch.IsSquib)
|
||||
{
|
||||
squib++;
|
||||
i++;//skip the next squib
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets a global dictionary to be used by SetChannelSummaryList
|
||||
/// </summary>
|
||||
private void OnAssignedChannelsChangedEvent(ITTSSetup setup)
|
||||
{
|
||||
SetChannelSummaryList(_setup.Channels);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill in the table of channels that were found in the Read File step
|
||||
/// </summary>
|
||||
/// <param name="channelRecords"></param>
|
||||
public void SetChannelSummaryList(ITTSChannelRecord[] channelRecords)
|
||||
{
|
||||
const int Requested = 0;
|
||||
const int Assigned = 1;
|
||||
const int Unassigned = 2;
|
||||
|
||||
var tomChannels = new[] { 0, 0, 0 };
|
||||
var digitalInChannels = new[] { 0, 0, 0 };
|
||||
var analogChannels = new[] { 0, 0, 0 };
|
||||
|
||||
foreach (var channelRecord in channelRecords)
|
||||
{
|
||||
if (string.Equals(channelRecord.ChannelCode, TTSChannelRecord.NONE, StringComparison.CurrentCultureIgnoreCase)) continue;
|
||||
if (channelRecord.IsSquib)
|
||||
{
|
||||
tomChannels[Requested] += 1;
|
||||
if (channelRecord.HardwareChannel != null && channelRecord.HardwareChannel.IsSquib)
|
||||
{
|
||||
tomChannels[Assigned] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tomChannels[Unassigned] += 1;
|
||||
}
|
||||
}
|
||||
else if (channelRecord.IsDigitalInput)
|
||||
{
|
||||
digitalInChannels[Requested] += 1;
|
||||
if (channelRecord.HardwareChannel != null && channelRecord.HardwareChannel.IsDigitalIn)
|
||||
{
|
||||
digitalInChannels[Assigned] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
digitalInChannels[Unassigned] += 1;
|
||||
}
|
||||
}
|
||||
else if (!channelRecord.IsDigitalOutput)
|
||||
{
|
||||
//Must be analog
|
||||
analogChannels[Requested] += 1;
|
||||
if (channelRecord.HardwareChannel != null && channelRecord.HardwareChannel.IsAnalog)
|
||||
{
|
||||
analogChannels[Assigned] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
analogChannels[Unassigned] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
var temp = new List<ChannelSummary>();
|
||||
var channel = new ChannelSummary
|
||||
{
|
||||
ChannelType = Resources.StringResources.Analog,
|
||||
Requested = analogChannels[Requested],
|
||||
Assigned = analogChannels[Assigned],
|
||||
Unassigned = analogChannels[Unassigned],
|
||||
};
|
||||
temp.Add(channel);
|
||||
|
||||
channel = new ChannelSummary
|
||||
{
|
||||
ChannelType = Resources.StringResources.TOM,
|
||||
Requested = tomChannels[Requested],
|
||||
Assigned = tomChannels[Assigned],
|
||||
Unassigned = tomChannels[Unassigned],
|
||||
};
|
||||
temp.Add(channel);
|
||||
|
||||
channel = new ChannelSummary
|
||||
{
|
||||
ChannelType = Resources.StringResources.DigitalIn,
|
||||
Requested = digitalInChannels[Requested],
|
||||
Assigned = digitalInChannels[Assigned],
|
||||
Unassigned = digitalInChannels[Unassigned],
|
||||
};
|
||||
temp.Add(channel);
|
||||
|
||||
ChannelSummaryList = temp;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
private ITTSSetup _setup;
|
||||
|
||||
public bool IsDirty { get; private set; }
|
||||
private bool _isBusy = false;
|
||||
|
||||
public bool IsBusy
|
||||
{
|
||||
get => _isBusy;
|
||||
set
|
||||
{
|
||||
_isBusy = value;
|
||||
OnPropertyChanged("IsBusy");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isMenuIncluded = false;
|
||||
|
||||
public bool IsMenuIncluded
|
||||
{
|
||||
get => _isMenuIncluded;
|
||||
set
|
||||
{
|
||||
_isMenuIncluded = value;
|
||||
OnPropertyChanged("IsMenuIncluded");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isNavigationIncluded = false;
|
||||
|
||||
public bool IsNavigationIncluded
|
||||
{
|
||||
get => _isNavigationIncluded;
|
||||
set
|
||||
{
|
||||
_isNavigationIncluded = value;
|
||||
OnPropertyChanged("IsNavigationIncluded");
|
||||
}
|
||||
}
|
||||
|
||||
private List<IDASHardware> _dasSummaryList = new List<IDASHardware>();
|
||||
|
||||
public List<IDASHardware> DasSummaryList
|
||||
{
|
||||
get => _dasSummaryList;
|
||||
set
|
||||
{
|
||||
_dasSummaryList = value;
|
||||
OnPropertyChanged("DasSummaryList");
|
||||
}
|
||||
}
|
||||
|
||||
private readonly IHardwareSummaryRecord[] _hardwareRecords = { new HardwareSummaryRecord() };
|
||||
public IHardwareSummaryRecord[] HardwareRecords => _hardwareRecords;
|
||||
|
||||
private List<ChannelSummary> _channelSummaryList = new List<ChannelSummary>();
|
||||
|
||||
public List<ChannelSummary> ChannelSummaryList
|
||||
{
|
||||
get => _channelSummaryList;
|
||||
set
|
||||
{
|
||||
_channelSummaryList = value;
|
||||
OnPropertyChanged("ChannelSummaryList");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Commands
|
||||
|
||||
#endregion
|
||||
|
||||
///<summary>
|
||||
///Occurs when a property value changes.
|
||||
///</summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,481 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using DTS.Common.Events;
|
||||
using DTS.Common.Events.TTSImport;
|
||||
using DTS.Common.Interface.DataRecorders;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.DIChannels;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
|
||||
using Prism.Events;
|
||||
using Unity;
|
||||
using DTS.Common.Interactivity;
|
||||
using Prism.Regions;
|
||||
using Prism.Commands;
|
||||
using TTSImport.Model;
|
||||
using TTSImport.Resources;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// this class handles Level Trigger edit/create functionality
|
||||
/// </summary>
|
||||
[PartCreationPolicy(CreationPolicy.Shared)]
|
||||
public class DigitalInputChannelsViewModel : IDigitalInputChannelsViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The Hardware Scan view
|
||||
/// </summary>
|
||||
public IDigitalInputChannelsView View { get; set; }
|
||||
|
||||
private IEventAggregator _eventAggregator { get; }
|
||||
private IRegionManager _regionManager;
|
||||
private IUnityContainer UnityContainer { get; }
|
||||
|
||||
public InteractionRequest<Notification> NotificationRequest { get; }
|
||||
public InteractionRequest<Confirmation> ConfirmationRequest { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the TechnologyDomainEditViewModel.
|
||||
/// </summary>
|
||||
/// <param name="view">The IDigitalInputChannelsView.</param>
|
||||
/// <param name="regionManager">The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed.</param>
|
||||
/// <param name="eventAggregator">The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other.</param>
|
||||
/// <param name="unityContainer">The unityContainer.</param>
|
||||
public DigitalInputChannelsViewModel(IDigitalInputChannelsView view, IRegionManager regionManager,
|
||||
IEventAggregator eventAggregator, IUnityContainer unityContainer)
|
||||
{
|
||||
View = view;
|
||||
View.DataContext = this;
|
||||
|
||||
NotificationRequest = new InteractionRequest<Notification>();
|
||||
ConfirmationRequest = new InteractionRequest<Confirmation>();
|
||||
|
||||
_eventAggregator = eventAggregator;
|
||||
UnityContainer = unityContainer;
|
||||
_regionManager = regionManager;
|
||||
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
|
||||
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>()
|
||||
.Subscribe(OnBusyIndicatorNotification, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<AssignedChannelsChangedEvent>().Subscribe(OnAssignedChannelsChangedEvent,
|
||||
ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportHardwareScanFinishedEvent>()
|
||||
.Subscribe(OnHardwareScanComplete, ThreadOption.PublisherThread, true);
|
||||
}
|
||||
|
||||
#region Methods
|
||||
private void OnHardwareScanComplete(List<IDASHardware> hardware)
|
||||
{
|
||||
_hardware = hardware;
|
||||
}
|
||||
|
||||
private void OnAssignedChannelsChangedEvent(ITTSSetup setup)
|
||||
{
|
||||
if (!Application.Current.Dispatcher.CheckAccess())
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
OnAssignedChannelsChangedEvent(setup);
|
||||
}));
|
||||
return;
|
||||
}
|
||||
_setup = setup;
|
||||
if (null == _hardware || null == _setup) { return; }
|
||||
var channels = new ObservableCollection<DASChannel>();
|
||||
var remainingChannels = new ObservableCollection<ITTSChannelRecord>();
|
||||
var channelIdToChannelRecord = new Dictionary<string, DASChannel>();
|
||||
foreach (var das in _hardware)
|
||||
{
|
||||
var ichannels = das.GetIHardwareChannels();
|
||||
foreach (var ch in ichannels)
|
||||
{
|
||||
if (!ch.IsDigitalIn) { continue; }
|
||||
var newChannel = new DASChannel(ch);
|
||||
channels.Add(newChannel);
|
||||
channelIdToChannelRecord[ch.GetId()] = newChannel;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var channelRecord in _setup.Channels)
|
||||
{
|
||||
if (channelRecord.IsEmptyRecord)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!channelRecord.IsDigitalInput)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!channelRecord.IsChannelCodeValid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (channelRecord.ChannelCode == TTSChannelRecord.NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (null != channelRecord.HardwareChannel &&
|
||||
channelIdToChannelRecord.ContainsKey(channelRecord.HardwareChannel.GetId()))
|
||||
{
|
||||
channelIdToChannelRecord[channelRecord.HardwareChannel.GetId()].SetITTSChannelRecord(channelRecord);
|
||||
}
|
||||
else
|
||||
{
|
||||
remainingChannels.Add(channelRecord);
|
||||
}
|
||||
}
|
||||
|
||||
DASChannels = channels;
|
||||
RemainingChannels = remainingChannels;
|
||||
OnPropertyChanged("DASChannels");
|
||||
OnPropertyChanged("RemainingChannels");
|
||||
}
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
public Task CleanupAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter)
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter, object model)
|
||||
{
|
||||
}
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task InitializeAsync(object parameter)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Activated()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnBusyIndicatorNotification(bool eventArg)
|
||||
{
|
||||
IsBusy = eventArg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
|
||||
{
|
||||
// The NotificationRequest.Raise triggers the Invoke() method of the PopupWindowAction object to show the NotificationWindow window
|
||||
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
|
||||
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, "",
|
||||
eventArgsWithTitle.Image, string.Empty);
|
||||
|
||||
NotificationRequest.Raise(new Notification
|
||||
{
|
||||
Content = eventArgsWithoutTitle,
|
||||
Title = eventArgsWithTitle.Title
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
private ITTSSetup _setup;
|
||||
private IList<IDASHardware> _hardware;
|
||||
public bool IsDirty { get; private set; }
|
||||
private bool _isBusy;
|
||||
|
||||
public bool IsBusy
|
||||
{
|
||||
get => _isBusy;
|
||||
set
|
||||
{
|
||||
_isBusy = value;
|
||||
OnPropertyChanged("IsBusy");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isMenuIncluded;
|
||||
|
||||
public bool IsMenuIncluded
|
||||
{
|
||||
get => _isMenuIncluded;
|
||||
set
|
||||
{
|
||||
_isMenuIncluded = value;
|
||||
OnPropertyChanged("IsMenuIncluded");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isNavigationIncluded;
|
||||
|
||||
public bool IsNavigationIncluded
|
||||
{
|
||||
get => _isNavigationIncluded;
|
||||
set
|
||||
{
|
||||
_isNavigationIncluded = value;
|
||||
OnPropertyChanged("IsNavigationIncluded");
|
||||
}
|
||||
}
|
||||
public bool AssignEnabled { get; set; }
|
||||
public bool RemoveEnabled { get; set; }
|
||||
public bool EnableOrDisableEnabled { get; set; }
|
||||
public ObservableCollection<DASChannel> DASChannels { get; set; } = new ObservableCollection<DASChannel>();
|
||||
public ObservableCollection<ITTSChannelRecord> RemainingChannels { get; set; } =
|
||||
new ObservableCollection<ITTSChannelRecord>();
|
||||
|
||||
private ITTSChannelRecord _selectedRemainingChannel;
|
||||
public ITTSChannelRecord SelectedRemainingChannel
|
||||
{
|
||||
get => _selectedRemainingChannel;
|
||||
set
|
||||
{
|
||||
_selectedRemainingChannel = value;
|
||||
if (null == _selectedRemainingChannel || null == SelectedDASChannel) return;
|
||||
AssignEnabled = true;
|
||||
OnPropertyChanged("AssignEnabled");
|
||||
}
|
||||
}
|
||||
private DASChannel _selectedDASChannel;
|
||||
public DASChannel SelectedDASChannel
|
||||
{
|
||||
get => _selectedDASChannel;
|
||||
set
|
||||
{
|
||||
_selectedDASChannel = value;
|
||||
DetermineRemoveEnableStatus();
|
||||
}
|
||||
}
|
||||
private void DetermineRemoveEnableStatus()
|
||||
{
|
||||
if (_selectedDASChannel?.Channel != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(_selectedDASChannel.EID) &&
|
||||
_selectedDASChannel.EID == _selectedDASChannel.Channel.SensorEID)
|
||||
{
|
||||
//can only be replaced, can't be removed
|
||||
RemoveEnabled = false;
|
||||
}
|
||||
RemoveEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveEnabled = false;
|
||||
}
|
||||
OnPropertyChanged("RemoveEnabled");
|
||||
AssignEnabled = null != _selectedDASChannel && null != _selectedRemainingChannel;
|
||||
OnPropertyChanged("AssignEnabled");
|
||||
EnableOrDisableEnabled = _selectedDASChannel?.Channel != null;
|
||||
OnPropertyChanged("EnableOrDisableEnabled");
|
||||
OnPropertyChanged("EnableOrDisableText");
|
||||
}
|
||||
public string EnableOrDisableText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SelectedDASChannel?.Channel == null)
|
||||
{
|
||||
return StringResources.Analog_Enable;
|
||||
}
|
||||
return SelectedDASChannel.Channel.Disabled
|
||||
? StringResources.Analog_Enable
|
||||
: StringResources.Analog_Disable;
|
||||
}
|
||||
}
|
||||
#endregion Properties
|
||||
|
||||
#region Commands
|
||||
#region assign
|
||||
/// <summary>
|
||||
/// Assign a channel code to a channel
|
||||
/// </summary>
|
||||
private DelegateCommand _assignCommand;
|
||||
public DelegateCommand AssignCommand => _assignCommand ?? (_assignCommand = new DelegateCommand(Assign));
|
||||
private void Assign()
|
||||
{
|
||||
if (SelectedRemainingChannel == null) { return; }
|
||||
|
||||
_eventAggregator.GetEvent<TTSImportTestSetupChangedEvent>().Publish(_setup);
|
||||
//BEFORE we go any further, check the state of sensor ids
|
||||
//if the channel has a sensor id AND there's a sensor on the channel with the same id
|
||||
//then prompt on replacing the id
|
||||
//IF the channel has a sensor id and there's no sensor on the channel BUT the new sensor has a different id
|
||||
//then prompt on replacing the id
|
||||
var bReplacingID = false;
|
||||
if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID))
|
||||
{
|
||||
if (null != SelectedRemainingChannel && SelectedRemainingChannel.SensorEID != SelectedDASChannel.EID)
|
||||
{
|
||||
bReplacingID = true;
|
||||
}
|
||||
//if existing channel has this ID, we will need to clear out the old id and assign a new one...
|
||||
if (null != SelectedDASChannel.Channel && SelectedDASChannel.Channel.SensorEID == SelectedDASChannel.EID)
|
||||
{
|
||||
bReplacingID = true;
|
||||
}
|
||||
}
|
||||
if (bReplacingID)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
var dialogResult = MessageBox.Show(StringResources.AssignSensorPrompt, StringResources.UserFeedbackRequired, MessageBoxButton.YesNo);
|
||||
if (dialogResult == MessageBoxResult.Yes)
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(AssignWork));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
AssignWork();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// assigns a channel record to a physical channel
|
||||
/// </summary>
|
||||
private void AssignWork()
|
||||
{
|
||||
if (null != SelectedDASChannel.Channel)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID))
|
||||
{
|
||||
SelectedDASChannel.Channel.SensorEID = "";
|
||||
}
|
||||
RemainingChannels.Add(SelectedDASChannel.Channel);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID))
|
||||
{
|
||||
SelectedRemainingChannel.SensorEID = SelectedDASChannel.EID;
|
||||
}
|
||||
|
||||
SelectedRemainingChannel.DigitalInputMode = DTS.Common.Enums.DigitalInputModes.CCNO;
|
||||
SelectedDASChannel.SetITTSChannelRecord(SelectedRemainingChannel);
|
||||
|
||||
var channel = SelectedRemainingChannel;
|
||||
var index = RemainingChannels.IndexOf(channel);
|
||||
SelectedRemainingChannel = null;
|
||||
RemainingChannels.Remove(channel);
|
||||
CollectionViewSource.GetDefaultView(DASChannels)?.Refresh();
|
||||
if (index < RemainingChannels.Count)
|
||||
{
|
||||
SelectedRemainingChannel = RemainingChannels[index];
|
||||
OnPropertyChanged("SelectedRemainingChannel");
|
||||
}
|
||||
else if (RemainingChannels.Count > 0)
|
||||
{
|
||||
SelectedRemainingChannel = RemainingChannels[index - 1];
|
||||
OnPropertyChanged("SelectedRemainingChannel");
|
||||
}
|
||||
index = DASChannels.IndexOf(SelectedDASChannel);
|
||||
for (var i = index; i < DASChannels.Count; i++)
|
||||
{
|
||||
var dasChannel = DASChannels[i];
|
||||
if (null != dasChannel.Channel) { continue; }
|
||||
SelectedDASChannel = dasChannel;
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
//didn't find a match, start from the beginning?
|
||||
for (var i = 0; i < index; i++)
|
||||
{
|
||||
var dasChannel = DASChannels[i];
|
||||
if (null != dasChannel.Channel)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
SelectedDASChannel = dasChannel;
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
//if we get here there's no new channel to go to, but we need to set the remove/enable/disable button status
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
DetermineRemoveEnableStatus();
|
||||
}
|
||||
#endregion
|
||||
#region remove
|
||||
private DelegateCommand _removeCommand;
|
||||
public DelegateCommand RemoveCommand => _removeCommand ?? (_removeCommand = new DelegateCommand(Remove));
|
||||
/// <summary>
|
||||
/// remove a hardware channel assignment (does not remove the channel from the test setup though?)
|
||||
/// </summary>
|
||||
private void Remove()
|
||||
{
|
||||
if (null == SelectedDASChannel || null == SelectedDASChannel.Channel) { return; }
|
||||
_eventAggregator.GetEvent<TTSImportTestSetupChangedEvent>().Publish(_setup);
|
||||
RemainingChannels.Add(SelectedDASChannel.Channel);
|
||||
SelectedDASChannel.SetITTSChannelRecord(null);
|
||||
CollectionViewSource.GetDefaultView(DASChannels)?.Refresh();
|
||||
var index = DASChannels.IndexOf(SelectedDASChannel);
|
||||
for (var i = index; i < DASChannels.Count; i++)
|
||||
{
|
||||
if (null == DASChannels[i].Channel) { continue; }
|
||||
SelectedDASChannel = DASChannels[i];
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < index; i++)
|
||||
{
|
||||
if (null == DASChannels[i].Channel) { continue; }
|
||||
SelectedDASChannel = DASChannels[i];
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
return;
|
||||
}
|
||||
//if we get here there's no new channel to go to, but we need to set the remove/enable/disable button status
|
||||
OnPropertyChanged("SelectedDASChannel");
|
||||
DetermineRemoveEnableStatus();
|
||||
}
|
||||
#endregion
|
||||
#region enableordisable
|
||||
private DelegateCommand _enableOrDisableCommand;
|
||||
public DelegateCommand EnableOrDisableCommand =>
|
||||
_enableOrDisableCommand ?? (_enableOrDisableCommand = new DelegateCommand(EnableOrDisable));
|
||||
/// <summary>
|
||||
/// enables or disables a channel in the test.
|
||||
/// </summary>
|
||||
private void EnableOrDisable()
|
||||
{
|
||||
if (SelectedDASChannel?.Channel == null) { return; }
|
||||
SelectedDASChannel.Channel.Disabled = !SelectedDASChannel.Channel.Disabled;
|
||||
SelectedDASChannel.Disabled = SelectedDASChannel.Channel.Disabled;
|
||||
|
||||
OnPropertyChanged("EnableOrDisableText");
|
||||
_eventAggregator.GetEvent<TTSImportTestSetupChangedEvent>().Publish(_setup);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Occurs when a property value changes.
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using DTS.Common.Interface;
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ReadFileView.xaml
|
||||
/// </summary>
|
||||
public partial class ReadFileView : IReadFileView
|
||||
{
|
||||
public ReadFileView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void Connect(int connectionId, object target)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Events;
|
||||
using DTS.Common.Events.TTSImport;
|
||||
using DTS.Common.Interface;
|
||||
using DTS.Common.Interface.DataRecorders;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.LevelTrigger;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
|
||||
using Prism.Events;
|
||||
using Unity;
|
||||
using DTS.Common.Interactivity;
|
||||
using Prism.Regions;
|
||||
using Prism.Commands;
|
||||
using TTSImport.Model;
|
||||
using TTSImport.Resources;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// this class handles Level Trigger edit/create functionality
|
||||
/// </summary>
|
||||
[PartCreationPolicy(CreationPolicy.Shared)]
|
||||
public class LevelTriggerViewModel : ILevelTriggerViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The Hardware Scan view
|
||||
/// </summary>
|
||||
public ILevelTriggerView View { get; set; }
|
||||
|
||||
private IEventAggregator _eventAggregator { get; }
|
||||
private IRegionManager _regionManager;
|
||||
private IUnityContainer UnityContainer { get; }
|
||||
|
||||
public InteractionRequest<Notification> NotificationRequest { get; }
|
||||
public InteractionRequest<Confirmation> ConfirmationRequest { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the TechnologyDomainEditViewModel.
|
||||
/// </summary>
|
||||
/// <param name="levelTriggerView">The Level Trigger View.</param>
|
||||
/// <param name="regionManager">The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed.</param>
|
||||
/// <param name="eventAggregator">The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other.</param>
|
||||
/// <param name="unityContainer">The unityContainer.</param>
|
||||
public LevelTriggerViewModel(ILevelTriggerView levelTriggerView, IRegionManager regionManager,
|
||||
IEventAggregator eventAggregator, IUnityContainer unityContainer)
|
||||
{
|
||||
View = levelTriggerView;
|
||||
View.DataContext = this;
|
||||
|
||||
NotificationRequest = new InteractionRequest<Notification>();
|
||||
ConfirmationRequest = new InteractionRequest<Confirmation>();
|
||||
|
||||
_eventAggregator = eventAggregator;
|
||||
UnityContainer = unityContainer;
|
||||
_regionManager = regionManager;
|
||||
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
|
||||
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Subscribe(OnBusyIndicatorNotification, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportReadFileStatusEvent>().Subscribe(OnReadFileFinished, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<EIDMappingEvent>().Subscribe(OnEIDMapping, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportHardwareScanFinishedEvent>().Subscribe(OnHardwareScanFinished, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportSavedChangesStatusEvent>().Subscribe(OnImportSavedChanges, ThreadOption.PublisherThread, true);
|
||||
}
|
||||
|
||||
#region Methods
|
||||
|
||||
private void OnImportSavedChanges(bool bSaved)
|
||||
{
|
||||
if (bSaved)
|
||||
{
|
||||
UpdateLevelTriggers();
|
||||
}
|
||||
}
|
||||
private void OnHardwareScanFinished(List<IDASHardware> hardware)
|
||||
{
|
||||
_hardware = hardware;
|
||||
}
|
||||
|
||||
private void OnReadFileFinished(ReadFileStatusArg statusArg)
|
||||
{
|
||||
if (statusArg.Status)
|
||||
{
|
||||
_setup = statusArg.TTSSetup;
|
||||
}
|
||||
}
|
||||
|
||||
private IDictionary<string, string> _sensorIdToChannelId = new Dictionary<string, string>();
|
||||
private void OnEIDMapping(IDictionary<string, string> sensorIdToChannelId)
|
||||
{
|
||||
_sensorIdToChannelId = sensorIdToChannelId;
|
||||
UpdateLevelTriggers();
|
||||
}
|
||||
|
||||
private void UpdateLevelTriggers()
|
||||
{
|
||||
if (null == _setup)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (null == _hardware || !_hardware.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var channelIdToDASChannel = new Dictionary<string, DASChannel>();
|
||||
var channelIdToIChannel = new Dictionary<string, IHardwareChannel>();
|
||||
var availableSquibChannels = new Queue<IHardwareChannel>();
|
||||
var availableDigitalInputChannels = new Queue<IHardwareChannel>();
|
||||
foreach (var h in _hardware)
|
||||
{
|
||||
var channels = h.GetIHardwareChannels();
|
||||
foreach (var ch in channels)
|
||||
{
|
||||
//Create a DASChannel so that voltage can be validated below
|
||||
channelIdToDASChannel[ch.GetId()] = new DASChannel(ch);
|
||||
channelIdToIChannel[ch.GetId()] = ch;
|
||||
if (ch.IsDigitalIn)
|
||||
{
|
||||
availableDigitalInputChannels.Enqueue(ch);
|
||||
}
|
||||
else if (ch.IsSquib)
|
||||
{
|
||||
availableSquibChannels.Enqueue(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
//handle pre-assigned channels if any
|
||||
//these are channels which we know the sensor should be assigned to a given hardware channel ahead of time
|
||||
//we do this before the EID check so that EID will override it
|
||||
if (_setup.PreAssignedSensorIdAndHwId.Any())
|
||||
{
|
||||
var remainingPreassigned = new List<Tuple<string, string>>();
|
||||
foreach (var tuple in _setup.PreAssignedSensorIdAndHwId)
|
||||
{
|
||||
var sensorId = tuple.Item1;
|
||||
var hwId = tuple.Item2;
|
||||
if (!channelIdToIChannel.ContainsKey(hwId))
|
||||
{
|
||||
remainingPreassigned.Add(tuple);
|
||||
continue;
|
||||
}
|
||||
var matches = from ch in _setup.Channels where ch.SensorSerialNumber == sensorId select ch;
|
||||
if (matches.Any())
|
||||
{
|
||||
var ittsChannel = matches.First();
|
||||
//do not make the assignment if the user has already assigned the channel to a different hardware channel
|
||||
//this would happen if the user scanned, didn't find the hardware, went to analog channels, assigned the sensor
|
||||
//then finally went to hardware scan and then DID find the hardware. in this case just ignore the preassignment
|
||||
if (null == ittsChannel.HardwareChannel)
|
||||
{
|
||||
var hardwareChannel = channelIdToIChannel[hwId];
|
||||
var excitation = Test.Module.Channel.Sensor.GetExcitationVoltageEnumFromMagnitude(ittsChannel.SensorExcitationVolts);
|
||||
//if we have a hardware assignment, but the excitation is no longer valid, then don't make the assignment
|
||||
if (hardwareChannel.IsAnalog && !hardwareChannel.IsSupportedExcitation(excitation))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ittsChannel.HardwareChannel = hardwareChannel;
|
||||
}
|
||||
}
|
||||
}
|
||||
//if there are any remaining channels, these are hardware assignments that we didn't find hardware for, and we still need
|
||||
//to look for assignment
|
||||
_setup.PreAssignedSensorIdAndHwId = remainingPreassigned.ToArray();
|
||||
}
|
||||
|
||||
foreach (var channel in _setup.Channels)
|
||||
{
|
||||
if (null != channel.HardwareChannel &&
|
||||
!channelIdToIChannel.ContainsKey(channel.HardwareChannel.GetId()))
|
||||
{
|
||||
//hardware no longer present, unassign
|
||||
channel.HardwareChannel = null;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(channel.SensorEID))
|
||||
{
|
||||
//11245 TOM and DI channels in TTS imports without IDs should have sensors assigned automatically
|
||||
if (channel.IsSquib)
|
||||
{
|
||||
if (availableSquibChannels.Any())
|
||||
{
|
||||
var first = availableSquibChannels.Dequeue();
|
||||
channel.HardwareChannel = first;
|
||||
//first channel voltage/initiation, second current, etc
|
||||
var second = availableSquibChannels.Dequeue();
|
||||
}
|
||||
}
|
||||
else if (channel.IsDigitalInput)
|
||||
{
|
||||
if (availableDigitalInputChannels.Any())
|
||||
{
|
||||
var first = availableDigitalInputChannels.Dequeue();
|
||||
channel.HardwareChannel = first;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_sensorIdToChannelId.ContainsKey(channel.SensorEID) ||
|
||||
!channelIdToDASChannel.ContainsKey(_sensorIdToChannelId[channel.SensorEID]) ||
|
||||
!VoltageIsValid(channel, channelIdToDASChannel[_sensorIdToChannelId[channel.SensorEID]])
|
||||
//the below condition I think was missing a not, it appears to be looking for channels that don't have a valid channel code
|
||||
//but DO have a valid match for sensor id ... this is probably a reserve channel where the sensor was still found that it's looking for
|
||||
//15643 Sensors with EID do not remain assigned after import of XML produced from TTS import
|
||||
//changed it again ... this is inhibiting sensors from being assigned, additionally tested it with a sensor without a valid channel code but
|
||||
//a valid eid, and it worked fine
|
||||
|| (_sensorIdToChannelId.ContainsKey(channel.SensorEID) && !channel.IsChannelCodeValid)
|
||||
)
|
||||
{
|
||||
//unassign hardware if one is assigned, sensor id wasn't found or the sensor has an invalid excitation voltage for this hardware
|
||||
//or the channel does have a jcode
|
||||
channel.HardwareChannel = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
var channelId = _sensorIdToChannelId[channel.SensorEID];
|
||||
if (!channelIdToIChannel.ContainsKey(channelId)) continue;
|
||||
channel.HardwareChannel = channelIdToIChannel[channelId];
|
||||
}
|
||||
|
||||
|
||||
foreach (var lt in _setup.LevelTriggers)
|
||||
{
|
||||
lt.Refresh();
|
||||
}
|
||||
OnPropertyChanged("LevelTriggers");
|
||||
_eventAggregator.GetEvent<AssignedChannelsChangedEvent>().Publish(_setup);
|
||||
CollectionViewSource.GetDefaultView(LevelTriggers)?.Refresh();
|
||||
}
|
||||
/// <summary>
|
||||
/// returns True if the sensor's voltage is supported by the hardware channel, False if not
|
||||
/// </summary>
|
||||
/// <param name="selectedRemainingChannel"></param>
|
||||
/// <param name="selectedDASChannel"></param>
|
||||
/// <returns></returns>
|
||||
private bool VoltageIsValid(ITTSChannelRecord selectedRemainingChannel, DASChannel selectedDASChannel)
|
||||
{
|
||||
var voltageEnum = ExcitationVoltageOptions.ExcitationVoltageOption.Undefined;
|
||||
try
|
||||
{
|
||||
voltageEnum = Test.Module.Channel.Sensor.GetExcitationVoltageEnumFromMagnitude(selectedRemainingChannel.SensorExcitationVolts);
|
||||
}
|
||||
catch { } //GetExcitationVoltageEnumFromMagnitude will throw an exception if an invalid voltage is passed to it
|
||||
|
||||
return selectedDASChannel.HardwareChannel.IsSupportedExcitation(voltageEnum);
|
||||
}
|
||||
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
public Task CleanupAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter)
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter, object model)
|
||||
{
|
||||
}
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task InitializeAsync(object parameter)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Activated()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnBusyIndicatorNotification(bool eventArg)
|
||||
{
|
||||
IsBusy = eventArg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
|
||||
{
|
||||
// The NotificationRequest.Raise triggers the Invoke() method of the PopupWindowAction object to show the NotificationWindow window
|
||||
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
|
||||
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, "",
|
||||
eventArgsWithTitle.Image, string.Empty);
|
||||
|
||||
NotificationRequest.Raise(new Notification
|
||||
{
|
||||
Content = eventArgsWithoutTitle,
|
||||
Title = eventArgsWithTitle.Title
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
private IList<IDASHardware> _hardware;
|
||||
private ITTSSetup _setup;
|
||||
public ILevelTrigger[] LevelTriggers => _setup?.LevelTriggers;
|
||||
public bool IsDirty { get; private set; }
|
||||
private bool _isBusy;
|
||||
|
||||
public bool IsBusy
|
||||
{
|
||||
get => _isBusy;
|
||||
set
|
||||
{
|
||||
_isBusy = value;
|
||||
OnPropertyChanged("IsBusy");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isMenuIncluded;
|
||||
|
||||
public bool IsMenuIncluded
|
||||
{
|
||||
get => _isMenuIncluded;
|
||||
set
|
||||
{
|
||||
_isMenuIncluded = value;
|
||||
OnPropertyChanged("IsMenuIncluded");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isNavigationIncluded;
|
||||
|
||||
public bool IsNavigationIncluded
|
||||
{
|
||||
get => _isNavigationIncluded;
|
||||
set
|
||||
{
|
||||
_isNavigationIncluded = value;
|
||||
OnPropertyChanged("IsNavigationIncluded");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Commands
|
||||
#endregion
|
||||
|
||||
///<summary>
|
||||
///Occurs when a property value changes.
|
||||
///</summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.DOChannels;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <inheritdoc cref="IDigitalOutputChannelsView" />
|
||||
/// <summary>
|
||||
/// Interaction logic for HardwareScanView.xaml
|
||||
/// </summary>
|
||||
public partial class DigitalOutputChannelsView : IDigitalOutputChannelsView
|
||||
{
|
||||
public DigitalOutputChannelsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for HardwareScanView.xaml
|
||||
/// </summary>
|
||||
public partial class AnalogChannelsView : IAnalogChannelsView
|
||||
{
|
||||
public AnalogChannelsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("TTSImport")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("DTS")]
|
||||
[assembly: AssemblyProduct("TTSImport")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("a8ff540f-f22a-45ae-a63b-4984ed74c654")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows.Media.Imaging;
|
||||
using DTS.Common;
|
||||
using DTS.Common.Interface;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.DIChannels;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.DOChannels;
|
||||
using Prism.Ioc;
|
||||
using Prism.Modularity;
|
||||
using TTSImport;
|
||||
using Unity;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
// ReSharper disable RedundantAttributeUsageProperty
|
||||
// ReSharper disable UnusedParameter.Local
|
||||
|
||||
[assembly: TTSImportModuleName]
|
||||
[assembly: TTSImportModuleImageAttribute]
|
||||
namespace TTSImport
|
||||
{
|
||||
[Export(typeof(IModule))]
|
||||
[Module(ModuleName = "TTSImportModule")]
|
||||
public class TTSImportModule : IModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Injected unity container
|
||||
/// </summary>
|
||||
private readonly IUnityContainer _unityContainer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TTSImportModule"/> class.
|
||||
/// </summary>
|
||||
/// <param name="unityContainer">Obtained reference of the unity container by using dependency injection.</param>
|
||||
public TTSImportModule(IUnityContainer unityContainer)
|
||||
{
|
||||
|
||||
_unityContainer = unityContainer;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// Register View & View-Model with Unity dependency injection container as a singleton.
|
||||
_unityContainer.RegisterType<IHardwareScanView, HardwareScanView>();
|
||||
_unityContainer.RegisterType<IHardwareScanViewModel, HardwareScanViewModel>();
|
||||
_unityContainer.RegisterType<IEditFileView, EditFileView>();
|
||||
_unityContainer.RegisterType<IEditFileViewModel, EditFileViewModel>();
|
||||
_unityContainer.RegisterType<ISummaryView, SummaryView>();
|
||||
_unityContainer.RegisterType<ISummaryViewModel, SummaryViewModel>();
|
||||
_unityContainer.RegisterType<IReadFileView, ReadFileView>();
|
||||
_unityContainer.RegisterType<IReadFileViewModel, ReadFileViewModel>();
|
||||
_unityContainer.RegisterType<ILevelTriggerView, LevelTriggerView>();
|
||||
_unityContainer.RegisterType<ILevelTriggerViewModel, LevelTriggerViewModel>();
|
||||
_unityContainer.RegisterType<IAnalogChannelsView, AnalogChannelsView>();
|
||||
_unityContainer.RegisterType<IAnalogChannelsViewModel, AnalogChannelsViewModel>();
|
||||
_unityContainer.RegisterType<ITOMChannelsView, TOMChannelsView>();
|
||||
_unityContainer.RegisterType<ITOMChannelsViewModel, TOMChannelsViewModel>();
|
||||
_unityContainer.RegisterType<IDigitalInputChannelsView, DigitalInputChannelsView>();
|
||||
_unityContainer.RegisterType<IDigitalInputChannelsViewModel, DigitalInputChannelsViewModel>();
|
||||
_unityContainer.RegisterType<IDigitalOutputChannelsView, DigitalOutputChannelsView>();
|
||||
_unityContainer.RegisterType<IDigitalOutputChannelsViewModel, DigitalOutputChannelsViewModel>();
|
||||
}
|
||||
|
||||
public void OnInitialized(IContainerProvider containerProvider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterTypes(IContainerRegistry containerRegistry)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute class contains assembly name
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
|
||||
public class TTSImportModuleNameAttribute : TextAttribute
|
||||
{
|
||||
public TTSImportModuleNameAttribute() : this(null) { }
|
||||
|
||||
public TTSImportModuleNameAttribute(string s)
|
||||
{
|
||||
AssemblyName = AssemblyNames.TTSImport.ToString();
|
||||
}
|
||||
|
||||
public override string AssemblyName { get; }
|
||||
|
||||
public override Type GetAttributeType()
|
||||
{
|
||||
return typeof(TextAttribute);
|
||||
}
|
||||
|
||||
public override string GetAssemblyName()
|
||||
{
|
||||
return AssemblyName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute class contains assembly image and name - used on the Main screen to SummaryModule available components
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
|
||||
public class TTSImportModuleImageAttribute : ImageAttribute
|
||||
{
|
||||
private BitmapImage _img;
|
||||
|
||||
public TTSImportModuleImageAttribute() : this(null) { }
|
||||
public override BitmapImage AssemblyImage
|
||||
{
|
||||
get { _img = AssemblyInfo.GetImage(AssemblyNames.TTSImport.ToString()); return _img; }
|
||||
}
|
||||
public TTSImportModuleImageAttribute(string s)
|
||||
{
|
||||
_img = AssemblyInfo.GetImage(AssemblyNames.TTSImport.ToString());
|
||||
}
|
||||
|
||||
public override Type GetAttributeType()
|
||||
{
|
||||
return typeof(ImageAttribute);
|
||||
}
|
||||
public override BitmapImage GetAssemblyImage()
|
||||
{
|
||||
return AssemblyImage;
|
||||
}
|
||||
private string _name;
|
||||
public override string AssemblyName
|
||||
{
|
||||
get { _name = AssemblyNames.TTSImport.ToString(); return _name; }
|
||||
}
|
||||
|
||||
public override string GetAssemblyName()
|
||||
{
|
||||
return AssemblyName;
|
||||
}
|
||||
private string _group;
|
||||
public override string AssemblyGroup
|
||||
{
|
||||
get { _group = eAssemblyGroups.Prepare.ToString(); return _group; }
|
||||
}
|
||||
|
||||
public override string GetAssemblyGroup()
|
||||
{
|
||||
return AssemblyGroup;
|
||||
}
|
||||
|
||||
private eAssemblyRegion _region;
|
||||
public override eAssemblyRegion AssemblyRegion
|
||||
{
|
||||
get { _region = eAssemblyRegion.TTSImportRegion; return _region; }
|
||||
}
|
||||
public override eAssemblyRegion GetAssemblyRegion()
|
||||
{
|
||||
return AssemblyRegion;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,450 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Added" xml:space="preserve">
|
||||
<value>Added</value>
|
||||
</data>
|
||||
<data name="Analog_Assign" xml:space="preserve">
|
||||
<value>Assign</value>
|
||||
</data>
|
||||
<data name="Analog_Disable" xml:space="preserve">
|
||||
<value>Disable</value>
|
||||
</data>
|
||||
<data name="Analog_Enable" xml:space="preserve">
|
||||
<value>Enable</value>
|
||||
</data>
|
||||
<data name="Analog_Remove" xml:space="preserve">
|
||||
<value>Remove</value>
|
||||
</data>
|
||||
<data name="Assigned" xml:space="preserve">
|
||||
<value>Assigned</value>
|
||||
</data>
|
||||
<data name="BatteryVoltageStatusColumn" xml:space="preserve">
|
||||
<value>Battery Voltage Status</value>
|
||||
</data>
|
||||
<data name="Browse" xml:space="preserve">
|
||||
<value>Browse</value>
|
||||
</data>
|
||||
<data name="CableMultiplier" xml:space="preserve">
|
||||
<value>Cable Multiplier</value>
|
||||
</data>
|
||||
<data name="Capacity" xml:space="preserve">
|
||||
<value>Capacity</value>
|
||||
</data>
|
||||
<data name="CHAN" xml:space="preserve">
|
||||
<value>CHAN</value>
|
||||
</data>
|
||||
<data name="ChannelType" xml:space="preserve">
|
||||
<value>Channel Type</value>
|
||||
</data>
|
||||
<data name="Channel_Summary" xml:space="preserve">
|
||||
<value>Channel Summary</value>
|
||||
</data>
|
||||
<data name="Code" xml:space="preserve">
|
||||
<value>Code</value>
|
||||
</data>
|
||||
<data name="DASChannel" xml:space="preserve">
|
||||
<value>DAS Channel</value>
|
||||
</data>
|
||||
<data name="DASChannels" xml:space="preserve">
|
||||
<value>DAS Channels</value>
|
||||
</data>
|
||||
<data name="DASSerial" xml:space="preserve">
|
||||
<value>DAS Serial</value>
|
||||
</data>
|
||||
<data name="DAS_Summary" xml:space="preserve">
|
||||
<value>DAS Summary</value>
|
||||
</data>
|
||||
<data name="EID" xml:space="preserve">
|
||||
<value>EID</value>
|
||||
</data>
|
||||
<data name="EIDFound" xml:space="preserve">
|
||||
<value>EID Found</value>
|
||||
</data>
|
||||
<data name="EULabel" xml:space="preserve">
|
||||
<value>EU Label</value>
|
||||
</data>
|
||||
<data name="HWSerialNumber" xml:space="preserve">
|
||||
<value>HW SN</value>
|
||||
</data>
|
||||
<data name="Import" xml:space="preserve">
|
||||
<value>Import</value>
|
||||
</data>
|
||||
<data name="ImportFile" xml:space="preserve">
|
||||
<value>Import File</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_PossibleStatus_Done" xml:space="preserve">
|
||||
<value>Done</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_PossibleStatus_Failed" xml:space="preserve">
|
||||
<value>Failed</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_PossibleStatus_Working" xml:space="preserve">
|
||||
<value>Working</value>
|
||||
</data>
|
||||
<data name="InputVoltageStatusColumn" xml:space="preserve">
|
||||
<value>Input Voltage Status</value>
|
||||
</data>
|
||||
<data name="JCode" xml:space="preserve">
|
||||
<value>JCode</value>
|
||||
</data>
|
||||
<data name="Mode" xml:space="preserve">
|
||||
<value>Mode</value>
|
||||
</data>
|
||||
<data name="Name" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="NONE" xml:space="preserve">
|
||||
<value>NONE</value>
|
||||
</data>
|
||||
<data name="Polarity" xml:space="preserve">
|
||||
<value>Polarity</value>
|
||||
</data>
|
||||
<data name="PostTrigger" xml:space="preserve">
|
||||
<value>Post Trigger (sec)</value>
|
||||
</data>
|
||||
<data name="PreTrigger" xml:space="preserve">
|
||||
<value>Pre Trigger (sec)</value>
|
||||
</data>
|
||||
<data name="Range" xml:space="preserve">
|
||||
<value>Range</value>
|
||||
</data>
|
||||
<data name="RemainingChannels" xml:space="preserve">
|
||||
<value>Remaining Channels</value>
|
||||
</data>
|
||||
<data name="Requested" xml:space="preserve">
|
||||
<value>Requested</value>
|
||||
</data>
|
||||
<data name="RunTest" xml:space="preserve">
|
||||
<value>Run Test</value>
|
||||
</data>
|
||||
<data name="SampleRate" xml:space="preserve">
|
||||
<value>Sample Rate (per sec)</value>
|
||||
</data>
|
||||
<data name="Sens" xml:space="preserve">
|
||||
<value>Sens</value>
|
||||
</data>
|
||||
<data name="SensorSN" xml:space="preserve">
|
||||
<value>Sensor SN</value>
|
||||
</data>
|
||||
<data name="SerialNumber" xml:space="preserve">
|
||||
<value>Sensor SN</value>
|
||||
</data>
|
||||
<data name="TestLength" xml:space="preserve">
|
||||
<value>Test Length (sec)</value>
|
||||
</data>
|
||||
<data name="TestSetupName" xml:space="preserve">
|
||||
<value>Test Setup Name:</value>
|
||||
</data>
|
||||
<data name="ToyotaCode" xml:space="preserve">
|
||||
<value>Toyota Code</value>
|
||||
</data>
|
||||
<data name="Type" xml:space="preserve">
|
||||
<value>Type</value>
|
||||
</data>
|
||||
<data name="Unassigned" xml:space="preserve">
|
||||
<value>Unassigned</value>
|
||||
</data>
|
||||
<data name="ValueEU" xml:space="preserve">
|
||||
<value>VAL (EU)</value>
|
||||
</data>
|
||||
<data name="ValuePercent" xml:space="preserve">
|
||||
<value>VAL (%)</value>
|
||||
</data>
|
||||
<data name="AssignSensorPrompt" xml:space="preserve">
|
||||
<value>Assign sensor? ID on the channel will be applied to the sensor and removed from any other sensors.</value>
|
||||
</data>
|
||||
<data name="UserFeedbackRequired" xml:space="preserve">
|
||||
<value>User feedback required</value>
|
||||
</data>
|
||||
<data name="Current" xml:space="preserve">
|
||||
<value>Current (amp)</value>
|
||||
</data>
|
||||
<data name="Delay" xml:space="preserve">
|
||||
<value>Delay (ms)</value>
|
||||
</data>
|
||||
<data name="Duration" xml:space="preserve">
|
||||
<value>Duration (ms)</value>
|
||||
</data>
|
||||
<data name="LimitDuration" xml:space="preserve">
|
||||
<value>Limit duration</value>
|
||||
</data>
|
||||
<data name="ResHighTolerance" xml:space="preserve">
|
||||
<value>Res. High Tol. (Ω)</value>
|
||||
</data>
|
||||
<data name="ResLowTolerance" xml:space="preserve">
|
||||
<value>Res. Low Tol. (Ω)</value>
|
||||
</data>
|
||||
<data name="CH" xml:space="preserve">
|
||||
<value>CH</value>
|
||||
</data>
|
||||
<data name="EditFile_AddCode" xml:space="preserve">
|
||||
<value>Add Code</value>
|
||||
</data>
|
||||
<data name="EditFile_DeleteCode" xml:space="preserve">
|
||||
<value>Delete Code</value>
|
||||
</data>
|
||||
<data name="EditFile_Replace" xml:space="preserve">
|
||||
<value>Replace</value>
|
||||
</data>
|
||||
<data name="Filter" xml:space="preserve">
|
||||
<value>Filter</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_MustBeCSVOrXML" xml:space="preserve">
|
||||
<value>TTS import requires either .csv or .xml input file</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_NoOriginalCSV" xml:space="preserve">
|
||||
<value>TTS import requires a .csv filename in the OriginalImportFile attribute</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_UnexpectedZeroMethod" xml:space="preserve">
|
||||
<value>is an unexpected zero method type. Only None, AverageOverTime, and UsePreEventDiagnosticsZero are allowed</value>
|
||||
</data>
|
||||
<data name="JHyphenCode" xml:space="preserve">
|
||||
<value>J-Code</value>
|
||||
</data>
|
||||
<data name="NumChannelsAndSensors" xml:space="preserve">
|
||||
<value>{0} Required Channel(s), {1} System Sensor(s)</value>
|
||||
</data>
|
||||
<data name="SaveFile" xml:space="preserve">
|
||||
<value>Save File</value>
|
||||
</data>
|
||||
<data name="Search" xml:space="preserve">
|
||||
<value>Search</value>
|
||||
</data>
|
||||
<data name="TestName" xml:space="preserve">
|
||||
<value>Test Name</value>
|
||||
</data>
|
||||
<data name="Table_NA" xml:space="preserve">
|
||||
<value>---</value>
|
||||
</data>
|
||||
<data name="Analog" xml:space="preserve">
|
||||
<value>Analog</value>
|
||||
</data>
|
||||
<data name="DigitalIn" xml:space="preserve">
|
||||
<value>Digital In</value>
|
||||
</data>
|
||||
<data name="TOM" xml:space="preserve">
|
||||
<value>TOM</value>
|
||||
</data>
|
||||
<data name="AllowEIDToBlankChannelChallenge" xml:space="preserve">
|
||||
<value>The sensor {0} has an EID, but no EID was found.\r\n\r\nPress OK to clear the EID for {0} and assign the sensor.\r\nPress Cancel to leave the EID unchanged and the sensor unassigned.</value>
|
||||
</data>
|
||||
<data name="ROIEnd" xml:space="preserve">
|
||||
<value>ROI End (sec)</value>
|
||||
</data>
|
||||
<data name="ROIStart" xml:space="preserve">
|
||||
<value>ROI Start (sec)</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_DuplicateSensorSerialNumber" xml:space="preserve">
|
||||
<value>{0} is a duplicate Sensor Serial Number.</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_DuplicateChannelCode" xml:space="preserve">
|
||||
<value>{0} is a duplicate Channel Code.</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_DuplicateDescription" xml:space="preserve">
|
||||
<value>{0} is a duplicate Description.</value>
|
||||
</data>
|
||||
<data name="DIn" xml:space="preserve">
|
||||
<value>D In</value>
|
||||
</data>
|
||||
<data name="DOut" xml:space="preserve">
|
||||
<value>D Out</value>
|
||||
</data>
|
||||
<data name="ECM" xml:space="preserve">
|
||||
<value>ECM</value>
|
||||
</data>
|
||||
<data name="G5" xml:space="preserve">
|
||||
<value>G5</value>
|
||||
</data>
|
||||
<data name="Rack" xml:space="preserve">
|
||||
<value>Rack</value>
|
||||
</data>
|
||||
<data name="SPD" xml:space="preserve">
|
||||
<value>SPD</value>
|
||||
</data>
|
||||
<data name="SPS" xml:space="preserve">
|
||||
<value>SPS</value>
|
||||
</data>
|
||||
<data name="SPT" xml:space="preserve">
|
||||
<value>SPT</value>
|
||||
</data>
|
||||
<data name="Squib" xml:space="preserve">
|
||||
<value>Squib</value>
|
||||
</data>
|
||||
<data name="Total" xml:space="preserve">
|
||||
<value>Total</value>
|
||||
</data>
|
||||
<data name="Units" xml:space="preserve">
|
||||
<value>Units</value>
|
||||
</data>
|
||||
<data name="AssignSensorExcitationError" xml:space="preserve">
|
||||
<value>Sensor Assignment Error</value>
|
||||
</data>
|
||||
<data name="InvalidExcitationAssignment" xml:space="preserve">
|
||||
<value>Hardware does not support {0} volt excitation.</value>
|
||||
</data>
|
||||
<data name="MissingECMSWarning" xml:space="preserve">
|
||||
<value>Devices at the following IP Addresses were unresponsive. Please reconnect or power cycle the units.</value>
|
||||
</data>
|
||||
<data name="Warning" xml:space="preserve">
|
||||
<value>Warning</value>
|
||||
</data>
|
||||
<data name="EmptyChannelCodeWarning" xml:space="preserve">
|
||||
<value>Non empty channel codes are required, please complete channel codes to continue</value>
|
||||
</data>
|
||||
<data name="TestId" xml:space="preserve">
|
||||
<value>Test Id</value>
|
||||
</data>
|
||||
<data name="TESTID_PREFIX_SUFFIX_None" xml:space="preserve">
|
||||
<value>[None]</value>
|
||||
</data>
|
||||
<data name="TESTID_PREFIX_SUFFIX_TestSetupName" xml:space="preserve">
|
||||
<value>[Test Setup Name]</value>
|
||||
</data>
|
||||
<data name="TESTID_PREFIX_SUFFIX_TimeStamp" xml:space="preserve">
|
||||
<value>[Time Stamp]</value>
|
||||
</data>
|
||||
<data name="EditFile_ADDDI" xml:space="preserve">
|
||||
<value>Add DI</value>
|
||||
</data>
|
||||
<data name="EditFile_AddSquib" xml:space="preserve">
|
||||
<value>Add Squib</value>
|
||||
</data>
|
||||
<data name="AAF_SLICE" xml:space="preserve">
|
||||
<value>Requested SLICE AAF: {0}</value>
|
||||
</data>
|
||||
<data name="AAF_TDAS" xml:space="preserve">
|
||||
<value>Requested TDAS AAF: {0}</value>
|
||||
</data>
|
||||
<data name="ExcitationNotSupportedByChannel" xml:space="preserve">
|
||||
<value>Sensor excitation {0} not supported by channel</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_DuplicateJCode" xml:space="preserve">
|
||||
<value>JCode {0} is a duplicate</value>
|
||||
</data>
|
||||
<data name="ImportTestSetup_EmptyJCode" xml:space="preserve">
|
||||
<value>record {0} has an empty J-Code</value>
|
||||
</data>
|
||||
<data name="ReservedSensorFound" xml:space="preserve">
|
||||
<value>Reserved Sensor(s) found in file. These are now unsupported and were skipped.</value>
|
||||
</data>
|
||||
<data name="SensorNotFound" xml:space="preserve">
|
||||
<value>Sensor "{0}" not found in database</value>
|
||||
</data>
|
||||
</root>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,209 @@
|
||||
<base:BaseView x:Class="TTSImport.HardwareScanView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="768" d:DesignWidth="1366"
|
||||
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
|
||||
xmlns:strings="clr-namespace:TTSImport"
|
||||
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
|
||||
xmlns:controls="clr-namespace:DTS.Common.Controls;assembly=DTS.Common">
|
||||
<base:BaseView.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/brushes.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Controls/combobox.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="ItemContainerStyle" Value="{StaticResource TTS_ListViewItemStyle}"/>
|
||||
</Style>
|
||||
<Style TargetType="TextBox" BasedOn="{StaticResource TTS_TextBoxStyle}"/>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource TTS_TextBlockStyle}"/>
|
||||
<Style TargetType="CheckBox" BasedOn="{StaticResource PageContentCheckBoxStyle}" />
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource TTS_ComboBoxStyle}"/>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource TTS_ButtonStyle}"/>
|
||||
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource Gray_GridViewColumnHeaderStyle}"/>
|
||||
<converters:NonZeroToColorConverter x:Key="NonZeroToColor" />
|
||||
</ResourceDictionary>
|
||||
</base:BaseView.Resources>
|
||||
<Grid Background="{DynamicResource Brush_ApplicationContentBackground}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<controls:CommonStatusRibbon Content="{Binding StatusAndProgressBarView}" Grid.Row="0" Grid.ColumnSpan="3" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"/>
|
||||
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
||||
<Grid Background="{DynamicResource Brush_ApplicationContentBackground}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="20"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<GroupBox Header="{strings:TranslateExtension DAS_Summary}" Grid.Row="1" Grid.Column="0"
|
||||
AutomationProperties.AutomationId="DASSummaryGroupBox" HorizontalAlignment="Left">
|
||||
<WrapPanel Orientation="Vertical">
|
||||
<ListView ItemsSource="{Binding HardwareRecords}">
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Header="{strings:TranslateExtension ECM}" Width="50">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding ECM,FallbackValue='100'}" Width="40" AutomationProperties.AutomationId="ECM" TextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension SPS}" Width="50">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding SPS,FallbackValue='100'}" Width="40" AutomationProperties.AutomationId="SPS" TextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension SPT}" Width="50">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding SPT,FallbackValue='100'}" Width="40" AutomationProperties.AutomationId="SPT" TextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension SPD}" Width="50">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding SPD,FallbackValue='100'}" Width="43" AutomationProperties.AutomationId="SPD" TextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension G5}" Width="50">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding G5,FallbackValue='100'}" Width="43" AutomationProperties.AutomationId="G5" TextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Rack}" Width="50">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Rack,FallbackValue='100'}" Width="43" AutomationProperties.AutomationId="Rack" TextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Analog}" Width="50">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Analog,FallbackValue='100'}" Width="43" AutomationProperties.AutomationId="Analog" TextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Squib}" Width="50">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Squib,FallbackValue='100'}" Width="43" AutomationProperties.AutomationId="Squib" TextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension DIn}" Width="50">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding DIn,FallbackValue='100'}" Width="43" AutomationProperties.AutomationId="DIn" TextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension DOut}" Width="50">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding DOut,FallbackValue='100'}" Width="43" AutomationProperties.AutomationId="Dout" TextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Total}" Width="50">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Total,FallbackValue='100'}" Width="43" AutomationProperties.AutomationId="Total" TextAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
<ListView ItemsSource="{Binding DasSummaryList}">
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Header="{strings:TranslateExtension DASSerial}" Width="200">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding SerialNumberFamily,FallbackValue='DAS Serial'}" Width="190" AutomationProperties.AutomationId="SerialNumber" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension EIDFound}" Width="100">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate> <TextBlock Text="{Binding EIDFound,FallbackValue='EID Found'}" Width="100" AutomationProperties.AutomationId="EIDFound" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension InputVoltageStatusColumn}" Width="150">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding InputVoltageStatus,FallbackValue='Input Voltage'}" Width="150" Background="{Binding InputVoltageColor}" AutomationProperties.AutomationId="InputVoltageStatus" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension BatteryVoltageStatusColumn}" Width="150">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding BatteryVoltageStatus,FallbackValue='Battery Voltage'}" Width="150" Background="{Binding BatteryVoltageColor}" AutomationProperties.AutomationId="BatteryVoltageStatus" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</WrapPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="{strings:TranslateExtension Channel_Summary}" Grid.Row="1" Grid.Column="2"
|
||||
AutomationProperties.AutomationId="ChannelSummaryGroupBox" HorizontalAlignment="Left" VerticalAlignment="Top">
|
||||
<ListView ItemsSource="{Binding ChannelSummaryList}" >
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Header="{strings:TranslateExtension ChannelType}" Width="100">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding ChannelType,FallbackValue='Channel Type'}" Width="100" AutomationProperties.AutomationId="ChannelType" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Requested}" Width="100">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Requested,FallbackValue='Requested'}" Width="100" AutomationProperties.AutomationId="Requested" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Assigned}" Width="100">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Assigned,FallbackValue='Assigned'}" Width="100" AutomationProperties.AutomationId="Assigned" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Unassigned}" Width="100">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Unassigned,FallbackValue='Unassigned'}" Width="100" Background="{Binding Unassigned, Converter={StaticResource NonZeroToColor}}" AutomationProperties.AutomationId="Unassigned" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</base:BaseView>
|
||||
@@ -0,0 +1,257 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{B77A01D2-6C47-4740-A9C8-72D92B058E78}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>TTSImport</RootNamespace>
|
||||
<AssemblyName>TTSImport</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>CODE_ANALYSIS;DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>CODE_ANALYSIS;DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Practices.ServiceLocation">
|
||||
<HintPath>..\..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Microsoft.Practices.ServiceLocation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="Microsoft.Xaml.Behaviors">
|
||||
<HintPath>..\..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Microsoft.Xaml.Behaviors.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="Prism">
|
||||
<HintPath>..\..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Prism.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Prism.Unity.Wpf">
|
||||
<HintPath>..\..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Prism.Unity.Wpf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Prism.Wpf">
|
||||
<HintPath>..\..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Prism.Wpf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Security" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Windows.Interactivity">
|
||||
<HintPath>..\..\..\..\..\Common\DTS.Common\lib\System.Windows.Interactivity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Unity.Abstractions">
|
||||
<HintPath>..\..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Unity.Abstractions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Container">
|
||||
<HintPath>..\..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Unity.Container.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="Xceed.Wpf.Toolkit">
|
||||
<HintPath>..\..\..\..\..\Common\DTS.Common\lib\Xceed.Wpf.Toolkit\Xceed.Wpf.Toolkit.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Model\DASChannel.cs" />
|
||||
<Compile Include="Model\HardwareSummaryRecord.cs" />
|
||||
<Compile Include="Model\SummaryChannel.cs" />
|
||||
<Compile Include="Model\ChannelSummary.cs" />
|
||||
<Compile Include="Model\TTSChannelRecord.cs" />
|
||||
<Compile Include="Model\TTSLevelTriggerRecord.cs" />
|
||||
<Compile Include="Model\TTSTestSetup.cs" />
|
||||
<Compile Include="Model\WorkFunctionThreadData.cs" />
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Resources\StringResources.ja.Designer.cs" />
|
||||
<Compile Include="TTSImportModule.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Resources\StringResources.Designer.cs">
|
||||
<DependentUpon>StringResources.resx</DependentUpon>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<Compile Include="Resources\TranslateExtension.cs" />
|
||||
<Compile Include="ViewModel\EditFileViewModel.cs" />
|
||||
<Compile Include="ViewModel\DigitalInputChannelsViewModel.cs" />
|
||||
<Compile Include="ViewModel\DigitalOutputChannelsViewModel.cs" />
|
||||
<Compile Include="ViewModel\TOMChannelsViewModel.cs" />
|
||||
<Compile Include="ViewModel\AnalogChannelsViewModel.cs" />
|
||||
<Compile Include="ViewModel\LevelTriggerViewModel.cs" />
|
||||
<Compile Include="ViewModel\HardwareScanViewModel.cs" />
|
||||
<Compile Include="ViewModel\ReadFileViewModel.cs" />
|
||||
<Compile Include="ViewModel\SummaryViewModel.cs" />
|
||||
<Compile Include="View\EditFileView.xaml.cs">
|
||||
<DependentUpon>EditFileView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="View\DigitalInputChannelsView.xaml.cs">
|
||||
<DependentUpon>DigitalInputChannelsView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="View\DigitalOutputChannelsView.xaml.cs">
|
||||
<DependentUpon>DigitalOutputChannelsView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="View\TOMChannelsView.xaml.cs">
|
||||
<DependentUpon>TOMChannelsView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="View\AnalogChannelsView.xaml.cs">
|
||||
<DependentUpon>AnalogChannelsView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="View\LevelTriggerView.xaml.cs">
|
||||
<DependentUpon>LevelTriggerView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="View\HardwareScanView.xaml.cs">
|
||||
<DependentUpon>HardwareScanView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="View\ReadFileView.xaml.cs">
|
||||
<DependentUpon>ReadFileView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="View\SummaryView.xaml.cs">
|
||||
<DependentUpon>SummaryView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\StringResources.ja.resx">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\StringResources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>StringResources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\Common\DTS.Common.Core\DTS.Common.Core.csproj">
|
||||
<Project>{fab1f470-1574-4301-b56e-d3364aa93679}</Project>
|
||||
<Name>DTS.Common.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\..\Common\DTS.Common.DAS.Concepts\DTS.Common.DAS.Concepts.csproj">
|
||||
<Project>{03D8C736-36EB-4CD1-A6D9-130452B23239}</Project>
|
||||
<Name>DTS.Common.DAS.Concepts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\..\Common\DTS.Common.ISO\DTS.Common.ISO.csproj">
|
||||
<Project>{4dccddd1-032f-430c-9a6f-231daca4fbd0}</Project>
|
||||
<Name>DTS.Common.ISO</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\..\Common\DTS.Common.Storage\DTS.Common.Storage.csproj">
|
||||
<Project>{e0d1a7d0-dce8-403d-ba85-5a5d66ba1313}</Project>
|
||||
<Name>DTS.Common.Storage</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\..\Common\DTS.Common.Utilities\DTS.Common.Utilities.csproj">
|
||||
<Project>{03eace47-ea59-44ac-b49d-956e4dc4d618}</Project>
|
||||
<Name>DTS.Common.Utilities</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\..\Common\DTS.Common\DTS.Common.csproj">
|
||||
<Project>{114edc77-f3b5-4576-a91b-40818d503b55}</Project>
|
||||
<Name>DTS.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\IService\IService.csproj">
|
||||
<Project>{c9c45b72-05a3-4962-bc13-a78b1f4b1925}</Project>
|
||||
<Name>IService</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\SensorDB\SensorDB.csproj">
|
||||
<Project>{444ef10c-046e-47ad-a9a5-17318d488723}</Project>
|
||||
<Name>SensorDB</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\Users\Users.csproj">
|
||||
<Project>{BE8D217D-6DA9-4BCA-B62A-A82325B33979}</Project>
|
||||
<Name>Users</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="View\EditFileView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="View\DigitalInputChannelsView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="View\DigitalOutputChannelsView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="View\TOMChannelsView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="View\AnalogChannelsView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="View\LevelTriggerView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="View\HardwareScanView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="View\ReadFileView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="View\SummaryView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using DTS.Common.Interface;
|
||||
// ReSharper disable CheckNamespace
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for HardwareScanView.xaml
|
||||
/// </summary>
|
||||
public partial class LevelTriggerView : ILevelTriggerView
|
||||
{
|
||||
public LevelTriggerView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
<base:BaseView x:Class="TTSImport.AnalogChannelsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
|
||||
xmlns:controls="clr-namespace:DTS.Common.Controls;assembly=DTS.Common"
|
||||
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
|
||||
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:strings="clr-namespace:TTSImport"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="768" d:DesignWidth="1366"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
|
||||
<base:BaseView.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/CommonStyles.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Controls/combobox.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="ItemContainerStyle" Value="{StaticResource TTS_ListViewItemStyle}"/>
|
||||
</Style>
|
||||
<Style TargetType="TextBox" BasedOn="{StaticResource TTS_TextBoxStyle}"/>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource TTS_TextBlockStyle}"/>
|
||||
<Style TargetType="CheckBox" BasedOn="{StaticResource PageContentCheckBoxStyle}" />
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource TTS_ComboBoxStyle}"/>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource TTS_ButtonStyle}"/>
|
||||
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource Gray_GridViewColumnHeaderStyle}"/>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibility" />
|
||||
</ResourceDictionary>
|
||||
</base:BaseView.Resources>
|
||||
<Grid Background="{DynamicResource Brush_ApplicationContentBackground}"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<WrapPanel Orientation="Vertical" VerticalAlignment="Center" Grid.Column="1">
|
||||
<Button Content="{strings:TranslateExtension Analog_Assign}" IsEnabled="{Binding AssignEnabled}" Width="85" AutomationProperties.AutomationId="Analog_AssignButton">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding AssignCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Content="{strings:TranslateExtension Analog_Remove}" IsEnabled="{Binding RemoveEnabled}" Width="85" AutomationProperties.AutomationId="Analog_RemoveButton">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding RemoveCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Content="{Binding EnableOrDisableText,FallbackValue=Enable}" IsEnabled="{Binding EnableOrDisableEnabled}" Width="85" AutomationProperties.AutomationId="Analog_EnableDisableButton">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding EnableOrDisableCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
<GroupBox Header="{strings:TranslateExtension RemainingChannels}" Grid.Column="2"
|
||||
AutomationProperties.AutomationId="RemainingChannelsGroupBox">
|
||||
<ListView ItemsSource="{Binding RemainingChannels}" SelectedItem="{Binding SelectedRemainingChannel}" AutomationProperties.AutomationId="RemainingChannelsListView">
|
||||
<ListView.View>
|
||||
<controls:AutoSizedGridView AutomationProperties.AutomationId="RemainingChannelsGridView">
|
||||
<GridViewColumn Header="{strings:TranslateExtension Code}" AutomationProperties.AutomationId="ToyotaCode">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding ChannelCode}" MinWidth="130" AutomationProperties.AutomationId="ToyotaCodeTextBlock"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension SensorSN}" AutomationProperties.AutomationId="SensorSN">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding SensorSerialNumber}" MinWidth="130" AutomationProperties.AutomationId="SensorSNTextBlock"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</controls:AutoSizedGridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</GroupBox>
|
||||
<GroupBox Header="{strings:TranslateExtension DASChannels}" Grid.Column="0"
|
||||
AutomationProperties.AutomationId="DASChannelsGroupBox">
|
||||
<ListView ItemsSource="{Binding DASChannels}" SelectedItem="{Binding SelectedDASChannel}" AutomationProperties.AutomationId="DASChannelsListView">
|
||||
<ListView.View>
|
||||
<controls:AutoSizedGridView AutomationProperties.AutomationId="DASChannelsGridView">
|
||||
<GridViewColumn Header="{strings:TranslateExtension DASChannel}">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding DASChannelString}" MinWidth="130" AutomationProperties.AutomationId="DASChannelTextBlock"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Code}" AutomationProperties.AutomationId="ToyotaCode">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBox Text="{Binding ToyotaCode}" MinWidth="70" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="ToyotaCodeTextBox"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension EID}" >
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding EID}" MinWidth="100" AutomationProperties.AutomationId="EIDTextBlock"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension JHyphenCode}" AutomationProperties.AutomationId="Name">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBox Text="{Binding Name}" MinWidth="100" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="NameTextBox"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension SerialNumber}">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding SerialNumber}" MinWidth="80" AutomationProperties.AutomationId="SerialNumberTextBlock" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" />
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Sens}" AutomationProperties.AutomationId="Sensitivity">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding SensitivityString}" MinWidth="100" AutomationProperties.AutomationId="SensitivityTextBlock" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" />
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Capacity}" AutomationProperties.AutomationId="Capacity">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<TextBlock Text="{Binding Capacity}" MinWidth="50" AutomationProperties.AutomationId="CapacityTextBlock" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" />
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Range}" AutomationProperties.AutomationId="Range">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<xctk:DoubleUpDown ShowButtonSpinner="False" Value="{Binding Range}" MinWidth="50" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="RangeUpDown"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension Polarity}" AutomationProperties.AutomationId="Polarity">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<ComboBox ItemsSource="{Binding Polarities}" SelectedItem="{Binding Polarity, UpdateSourceTrigger=PropertyChanged}" Width="50" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="PolarityComboBox"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{strings:TranslateExtension CableMultiplier}" AutomationProperties.AutomationId="CableMultiplier">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<ItemContainerTemplate>
|
||||
<xctk:DoubleUpDown Value="{Binding CableMultiplier}" MinWidth="70" Visibility="{Binding IsActive, Converter={StaticResource BoolToVisibility}, ConverterParameter=HIDE}" AutomationProperties.AutomationId="CableMultiplierUpDown"/>
|
||||
</ItemContainerTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</controls:AutoSizedGridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</base:BaseView>
|
||||
@@ -0,0 +1,16 @@
|
||||
using DTS.Common.Interface;
|
||||
// ReSharper disable CheckNamespace
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for HardwareScanView.xaml
|
||||
/// </summary>
|
||||
public partial class HardwareScanView : IHardwareScanView
|
||||
{
|
||||
public HardwareScanView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,751 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using DTS.Common.Events;
|
||||
using DTS.Common.Interface;
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile;
|
||||
using Prism.Events;
|
||||
using Unity;
|
||||
using DTS.Common.Interactivity;
|
||||
using Prism.Regions;
|
||||
using Prism.Commands;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using DTS.Common;
|
||||
using DTS.Common.Interface.DataRecorders;
|
||||
using DTS.Common.Base;
|
||||
using DTS.Common.Classes;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Events.TTSImport;
|
||||
using TTSImport.Model;
|
||||
using TTSImport.Resources;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// this class handles Summary functionality
|
||||
/// </summary>
|
||||
[PartCreationPolicy(CreationPolicy.Shared)]
|
||||
public class SummaryViewModel : ISummaryViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The Status and Progress bars
|
||||
/// </summary>
|
||||
public IStatusAndProgressBarView StatusAndProgressBarView { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Summary view
|
||||
/// </summary>
|
||||
public ISummaryView View { get; set; }
|
||||
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private IRegionManager _regionManager;
|
||||
private IUnityContainer UnityContainer { get; set; }
|
||||
|
||||
public InteractionRequest<Notification> NotificationRequest { get; private set; }
|
||||
public InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the TechnologyDomainEditViewModel.
|
||||
/// </summary>
|
||||
/// <param name="view"></param>
|
||||
/// <param name="regionManager">The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed.</param>
|
||||
/// <param name="eventAggregator">The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other.</param>
|
||||
/// <param name="unityContainer">The unityContainer.</param>
|
||||
public SummaryViewModel(ISummaryView view, IRegionManager regionManager, IEventAggregator eventAggregator,
|
||||
IUnityContainer unityContainer)
|
||||
{
|
||||
View = view;
|
||||
View.DataContext = this;
|
||||
|
||||
NotificationRequest = new InteractionRequest<Notification>();
|
||||
ConfirmationRequest = new InteractionRequest<Confirmation>();
|
||||
|
||||
_eventAggregator = eventAggregator;
|
||||
UnityContainer = unityContainer;
|
||||
_regionManager = regionManager;
|
||||
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
|
||||
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Subscribe(OnBusyIndicatorNotification, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportReadFileStatusEvent>().Subscribe(OnReadFileFinished, ThreadOption.PublisherThread, true);
|
||||
_eventAggregator.GetEvent<TTSImportTestSetupChangedEvent>().Subscribe(OnTestSetupChanged, ThreadOption.PublisherThread, true);
|
||||
|
||||
}
|
||||
|
||||
#region Methods
|
||||
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
public Task CleanupAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter)
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize(object parameter, object model)
|
||||
{
|
||||
}
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
StatusAndProgressBarView = GetStatusAndProgressBarView(this);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task InitializeAsync(object parameter)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Activated()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnBusyIndicatorNotification(bool eventArg)
|
||||
{
|
||||
IsBusy = eventArg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
|
||||
{
|
||||
// The NotificationRequest.Raise triggers the Invoke() method of the PopupWindowAction object to show the NotificationWindow window
|
||||
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
|
||||
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, "",
|
||||
eventArgsWithTitle.Image, string.Empty);
|
||||
|
||||
NotificationRequest.Raise(new Notification
|
||||
{
|
||||
Content = eventArgsWithoutTitle,
|
||||
Title = eventArgsWithTitle.Title
|
||||
});
|
||||
}
|
||||
|
||||
public string GetTestId()
|
||||
{
|
||||
return null == View ? "" : View.GetTestId();
|
||||
}
|
||||
private void OnReadFileFinished(ReadFileStatusArg statusArg)
|
||||
{
|
||||
TestSetupImported = false;
|
||||
if (!statusArg.Status) return;
|
||||
_setup = statusArg.TTSSetup;
|
||||
View?.SetTestName(_setup.TestId);
|
||||
OnPropertyChanged(PropertyNames.ImportFileName.ToString());
|
||||
OnPropertyChanged(PropertyNames.TestSetupName.ToString());
|
||||
OnPropertyChanged(PropertyNames.SampleRate.ToString());
|
||||
OnPropertyChanged(PropertyNames.RecordingMode.ToString());
|
||||
OnPropertyChanged(PropertyNames.TestLength.ToString());
|
||||
OnPropertyChanged(PropertyNames.PreTrigger.ToString());
|
||||
OnPropertyChanged(PropertyNames.PostTrigger.ToString());
|
||||
OnPropertyChanged(PropertyNames.ROIStart.ToString());
|
||||
OnPropertyChanged(PropertyNames.ROIEnd.ToString());
|
||||
OnPropertyChanged(PropertyNames.AAF_TDAS.ToString());
|
||||
OnPropertyChanged(PropertyNames.AAF_SLICE.ToString());
|
||||
}
|
||||
private void OnTestSetupChanged(ITTSSetup setup)
|
||||
{
|
||||
TestSetupImported = false;
|
||||
}
|
||||
public void UpdateUI()
|
||||
{
|
||||
SampleRate = _setup.SampleRate;
|
||||
SetAvailableRecordingModes();
|
||||
RecordingMode = _setup.Mode;
|
||||
SetChannelList();
|
||||
TestSetupComplete = !SummaryChannelList.Exists(channelType => (channelType.Unassigned != "0") && (channelType.Unassigned != Resources.StringResources.Table_NA));
|
||||
if (!TestSetupComplete || Array.Exists(_setup.Channels, channel => channel.IsModified) || Array.Exists(_setup.LevelTriggers, levelTrigger => levelTrigger.IsModified))
|
||||
{
|
||||
TestSetupImported = false;
|
||||
}
|
||||
}
|
||||
|
||||
private List<double> _availableSampleRates = new List<double>();
|
||||
public List<double> AvailableSampleRates
|
||||
{
|
||||
get => _availableSampleRates;
|
||||
set
|
||||
{
|
||||
_availableSampleRates = value;
|
||||
OnPropertyChanged("AvailableSampleRates");
|
||||
}
|
||||
}
|
||||
public void SetAvailableSampleRates(int[] values)
|
||||
{
|
||||
AvailableSampleRates.Clear();
|
||||
|
||||
var minSampleRate = (double)values.Min();
|
||||
var maxSampleRate = (double)values.Max();
|
||||
foreach (var channel in _setup.Channels)
|
||||
{
|
||||
if (channel.HardwareChannel == null) continue;
|
||||
minSampleRate = Math.Max(channel.HardwareChannel.GetParentDAS().GetMinSampleRateDouble(), minSampleRate);
|
||||
maxSampleRate = Math.Min(channel.HardwareChannel.GetParentDAS().GetMaxSampleRateDouble(), maxSampleRate);
|
||||
}
|
||||
foreach (var sampleRate in values)
|
||||
{
|
||||
if (sampleRate >= minSampleRate && sampleRate <= maxSampleRate)
|
||||
{
|
||||
AvailableSampleRates.Add(sampleRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string AAF_TDAS => string.Format(StringResources.AAF_TDAS, !_aafExceptions.ContainsKey(SampleRate) ? (SampleRate / 5) : _aafExceptions[SampleRate][0]);
|
||||
public string AAF_SLICE => string.Format(StringResources.AAF_SLICE, !_aafExceptions.ContainsKey(SampleRate) ? (SampleRate / 5) : _aafExceptions[SampleRate][1]);
|
||||
|
||||
private Dictionary<double, List<double>> _aafExceptions = new Dictionary<double, List<double>>();
|
||||
public void SetAAFExceptions(Dictionary<double, List<double>> values)
|
||||
{
|
||||
_aafExceptions.Clear();
|
||||
_aafExceptions = values;
|
||||
}
|
||||
|
||||
public List<RecordingModes> AvailableRecordingModes { get; } = new List<RecordingModes>();
|
||||
|
||||
private void SetAvailableRecordingModes()
|
||||
{
|
||||
AvailableRecordingModes.Clear();
|
||||
|
||||
AvailableRecordingModes.Add(RecordingModes.CircularBuffer);
|
||||
AvailableRecordingModes.Add(RecordingModes.Recorder);
|
||||
if (_setup.AllowAdvancedRecordingModes)
|
||||
{
|
||||
AvailableRecordingModes.Add(RecordingModes.HybridRecorder);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSerializedTestIdValues(string[] values)
|
||||
{
|
||||
View?.UpdateTestIds(values);
|
||||
}
|
||||
/// <summary>
|
||||
/// Fill in the table of channels, including those added after the file was read
|
||||
/// </summary>
|
||||
public void SetChannelList()
|
||||
{
|
||||
const int Assigned = 0;
|
||||
const int Unassigned = 1;
|
||||
|
||||
var analogChannels = new[] { 0, 0 };
|
||||
var tomChannels = new[] { 0, 0 };
|
||||
var digitalInChannels = new[] { 0, 0 };
|
||||
var levelTriggers = new[] { 0, 0 };
|
||||
|
||||
foreach (var channelRecord in _setup.Channels)
|
||||
{
|
||||
if (string.Equals(channelRecord.ChannelCode, TTSChannelRecord.NONE, StringComparison.CurrentCultureIgnoreCase) || channelRecord.Disabled) continue;
|
||||
if (channelRecord.IsSquib)
|
||||
{
|
||||
if (channelRecord.HardwareChannel != null && channelRecord.HardwareChannel.IsSquib)
|
||||
{
|
||||
tomChannels[Assigned] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tomChannels[Unassigned] += 1;
|
||||
}
|
||||
}
|
||||
else if (channelRecord.IsDigitalInput)
|
||||
{
|
||||
if (channelRecord.HardwareChannel != null && channelRecord.HardwareChannel.IsDigitalIn)
|
||||
{
|
||||
digitalInChannels[Assigned] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
digitalInChannels[Unassigned] += 1;
|
||||
}
|
||||
}
|
||||
else if (!channelRecord.IsDigitalOutput)
|
||||
{
|
||||
if (channelRecord.HardwareChannel != null && channelRecord.HardwareChannel.IsAnalog)
|
||||
{
|
||||
analogChannels[Assigned] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
analogChannels[Unassigned] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var levelTrigger in _setup.LevelTriggers)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(levelTrigger.Code))
|
||||
{
|
||||
levelTriggers[Assigned] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
var temp = new List<SummaryChannel>();
|
||||
var channel = new SummaryChannel
|
||||
{
|
||||
ChannelType = "Analog", //internationalize these
|
||||
Assigned = analogChannels[Assigned],
|
||||
Unassigned = analogChannels[Unassigned].ToString()
|
||||
};
|
||||
temp.Add(channel);
|
||||
|
||||
channel = new SummaryChannel
|
||||
{
|
||||
ChannelType = "TOM",
|
||||
Assigned = tomChannels[Assigned],
|
||||
Unassigned = tomChannels[Unassigned].ToString()
|
||||
};
|
||||
temp.Add(channel);
|
||||
|
||||
channel = new SummaryChannel
|
||||
{
|
||||
ChannelType = "Digital In",
|
||||
Assigned = digitalInChannels[Assigned],
|
||||
Unassigned = digitalInChannels[Unassigned].ToString()
|
||||
};
|
||||
temp.Add(channel);
|
||||
|
||||
channel = new SummaryChannel
|
||||
{
|
||||
ChannelType = "Level Trigger",
|
||||
Assigned = levelTriggers[Assigned],
|
||||
Unassigned = Resources.StringResources.Table_NA
|
||||
};
|
||||
temp.Add(channel);
|
||||
|
||||
SummaryChannelList = temp;
|
||||
}
|
||||
|
||||
private readonly StatusAndProgressBarEventArgs statusAndProgressBarEventArgs = new StatusAndProgressBarEventArgs();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the text, background color, progress value, and/or progress visibility
|
||||
/// </summary>
|
||||
/// <param name="status"></param>
|
||||
/// <param name="error"></param>
|
||||
public void SetStatus(string status, string error = default(string)) //default(string) is null
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case "Waiting": //change this to string resources but use the same one in DataPRO and here???
|
||||
statusAndProgressBarEventArgs.StatusColor = BrushesAndColors.Brush_ApplicationStatus_Waiting.Color;
|
||||
statusAndProgressBarEventArgs.ProgressBarVisibility = Visibility.Collapsed;
|
||||
break;
|
||||
case "Working":
|
||||
statusAndProgressBarEventArgs.StatusColor = BrushesAndColors.Brush_ApplicationStatus_Busy.Color;
|
||||
statusAndProgressBarEventArgs.ProgressValue = 0;
|
||||
statusAndProgressBarEventArgs.ProgressBarVisibility = Visibility.Visible;
|
||||
break;
|
||||
case "Failed":
|
||||
TestSetupImported = false;
|
||||
statusAndProgressBarEventArgs.StatusColor = BrushesAndColors.Brush_ApplicationStatus_Failed.Color;
|
||||
statusAndProgressBarEventArgs.ProgressBarVisibility = Visibility.Collapsed;
|
||||
break;
|
||||
case "Done":
|
||||
TestSetupImported = true;
|
||||
foreach (var ch in _setup.Channels)
|
||||
{
|
||||
ch.IsModified = false;
|
||||
}
|
||||
foreach (var lt in _setup.LevelTriggers)
|
||||
{
|
||||
lt.IsModified = false;
|
||||
}
|
||||
statusAndProgressBarEventArgs.StatusColor = BrushesAndColors.Brush_ApplicationStatus_Complete.Color;
|
||||
statusAndProgressBarEventArgs.ProgressBarVisibility = Visibility.Collapsed;
|
||||
break;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(error))
|
||||
{
|
||||
statusAndProgressBarEventArgs.StatusText = status + " - " + error;
|
||||
}
|
||||
else
|
||||
{
|
||||
statusAndProgressBarEventArgs.StatusText = status;
|
||||
}
|
||||
|
||||
statusAndProgressBarEventArgs.Requester = this;
|
||||
_eventAggregator.GetEvent<StatusAndProgressBarEvent>().Publish(statusAndProgressBarEventArgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the progress value on the Status and Progress bar
|
||||
/// </summary>
|
||||
/// <param name="progress"></param>
|
||||
public void SetProgress(double progress)
|
||||
{
|
||||
statusAndProgressBarEventArgs.ProgressValue = (int)progress;
|
||||
statusAndProgressBarEventArgs.Requester = this;
|
||||
_eventAggregator.GetEvent<StatusAndProgressBarEvent>().Publish(statusAndProgressBarEventArgs);
|
||||
}
|
||||
|
||||
private IStatusAndProgressBarView GetStatusAndProgressBarView(IBaseViewModel parent)
|
||||
{
|
||||
var view = UnityContainer.Resolve<IStatusAndProgressBarView>();
|
||||
var viewModel = UnityContainer.Resolve<IStatusAndProgressBarViewModel>();
|
||||
view.DataContext = viewModel;
|
||||
viewModel.Initialize(parent);
|
||||
return view;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
private ITTSSetup _setup;
|
||||
public bool IsDirty { get; private set; }
|
||||
private bool _isBusy = false;
|
||||
|
||||
public bool IsBusy
|
||||
{
|
||||
get => _isBusy;
|
||||
set
|
||||
{
|
||||
_isBusy = value;
|
||||
OnPropertyChanged("IsBusy");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isMenuIncluded = false;
|
||||
|
||||
public bool IsMenuIncluded
|
||||
{
|
||||
get => _isMenuIncluded;
|
||||
set
|
||||
{
|
||||
_isMenuIncluded = value;
|
||||
OnPropertyChanged("IsMenuIncluded");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isNavigationIncluded = false;
|
||||
|
||||
public bool IsNavigationIncluded
|
||||
{
|
||||
get => _isNavigationIncluded;
|
||||
set
|
||||
{
|
||||
_isNavigationIncluded = value;
|
||||
OnPropertyChanged("IsNavigationIncluded");
|
||||
}
|
||||
}
|
||||
|
||||
private List<SummaryChannel> _summaryChannelList = new List<SummaryChannel>();
|
||||
|
||||
public List<SummaryChannel> SummaryChannelList
|
||||
{
|
||||
get => _summaryChannelList;
|
||||
set
|
||||
{
|
||||
_summaryChannelList = value;
|
||||
OnPropertyChanged("SummaryChannelList");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _testSetupComplete;
|
||||
public bool TestSetupComplete
|
||||
{
|
||||
get => _testSetupComplete;
|
||||
set
|
||||
{
|
||||
_testSetupComplete = value;
|
||||
OnPropertyChanged("ImportEnabled");
|
||||
}
|
||||
}
|
||||
|
||||
private bool _testSetupImported;
|
||||
public bool TestSetupImported
|
||||
{
|
||||
get => _testSetupImported;
|
||||
set
|
||||
{
|
||||
_testSetupImported = value;
|
||||
OnPropertyChanged("RunTestVisible");
|
||||
}
|
||||
}
|
||||
|
||||
public bool ImportEnabled => TestSetupComplete & IsROIValid;
|
||||
|
||||
public Visibility RunTestVisible => TestSetupImported ? Visibility.Visible : Visibility.Hidden;
|
||||
public Visibility SummaryPreTriggerVisibility => RecordingMode == RecordingModes.CircularBuffer ? Visibility.Visible : Visibility.Collapsed;
|
||||
public string PostTriggerOrTestLength => RecordingMode == RecordingModes.CircularBuffer ? StringResources.PostTrigger : StringResources.TestLength;
|
||||
|
||||
private bool _isROIStartValid = true;
|
||||
|
||||
public bool IsROIStartValid
|
||||
{
|
||||
get => _isROIStartValid;
|
||||
set
|
||||
{
|
||||
_isROIStartValid = value;
|
||||
OnPropertyChanged("IsROIStartValid");
|
||||
}
|
||||
}
|
||||
private bool _isROIEndValid = true;
|
||||
|
||||
public bool IsROIEndValid
|
||||
{
|
||||
get => _isROIEndValid;
|
||||
set
|
||||
{
|
||||
_isROIEndValid = value;
|
||||
OnPropertyChanged("IsROIEndValid");
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateROIValid()
|
||||
{
|
||||
if (null == _setup)
|
||||
{
|
||||
IsROIEndValid = true;
|
||||
IsROIStartValid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_setup.ROIEnd < _setup.ROIStart)
|
||||
{
|
||||
IsROIStartValid = false;
|
||||
IsROIEndValid = false;
|
||||
return;
|
||||
}
|
||||
if (RecordingMode == RecordingModes.Recorder)
|
||||
{
|
||||
IsROIStartValid = true;
|
||||
IsROIEndValid = !(_setup.ROIEnd - _setup.ROIStart > _setup.PostTrigger);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsROIEndValid = !(_setup.ROIEnd > _setup.PostTrigger);
|
||||
IsROIStartValid = !(Math.Abs(_setup.ROIStart) > _setup.PreTrigger);
|
||||
}
|
||||
}
|
||||
public bool IsROIValid
|
||||
{
|
||||
get
|
||||
{
|
||||
CalculateROIValid();
|
||||
return IsROIStartValid && IsROIEndValid;
|
||||
}
|
||||
}
|
||||
//=> RecordingMode != RecordingModes.Recorder || !(_setup.ROIEnd - _setup.ROIStart > _setup.PostTrigger);
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Commands
|
||||
|
||||
/// <summary>
|
||||
/// browse to a file to import, should be xml, maybe needs a few other criteria
|
||||
/// </summary>
|
||||
private DelegateCommand _importCommand;
|
||||
|
||||
public DelegateCommand ImportClicked => _importCommand ?? (_importCommand = new DelegateCommand(ImportMethod));
|
||||
|
||||
private void ImportMethod()
|
||||
{
|
||||
_eventAggregator.GetEvent<TTSImportSummaryImportEvent>().Publish(_setup);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the test since the Run Test button was clicked
|
||||
/// </summary>
|
||||
private DelegateCommand _runTestCommand;
|
||||
|
||||
public DelegateCommand RunTestClicked =>
|
||||
_runTestCommand ?? (_runTestCommand = new DelegateCommand(RunTestMethod));
|
||||
|
||||
private void RunTestMethod()
|
||||
{
|
||||
SetStatus(Resources.StringResources.ImportTestSetup_PossibleStatus_Working); //use string resource (same both here and where passed)
|
||||
ThreadPool.QueueUserWorkItem(RunTestWorkThread, null);
|
||||
}
|
||||
void RunTestWorkThread(object obj)
|
||||
{
|
||||
_eventAggregator.GetEvent<TTSImportSummaryRunTestEvent>().Publish(_setup);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region properties
|
||||
|
||||
/// <summary>
|
||||
/// all properties that are exposed
|
||||
/// </summary>
|
||||
public enum PropertyNames
|
||||
{
|
||||
ImportFileName,
|
||||
TestSetupName,
|
||||
SampleRate,
|
||||
RecordingMode,
|
||||
TestLength,
|
||||
PreTrigger,
|
||||
PostTrigger,
|
||||
ROIStart,
|
||||
ROIEnd,
|
||||
AAF_TDAS,
|
||||
AAF_SLICE,
|
||||
AllowAdvancedRecordingModes,
|
||||
AllowTSRAIRRecordingModes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// full path to import file
|
||||
/// </summary>
|
||||
public string ImportFileName => _setup?.Filename ?? "";
|
||||
|
||||
public string TestSetupName
|
||||
{
|
||||
get => _setup?.TestId ?? "";
|
||||
set
|
||||
{
|
||||
TestSetupImported = false;
|
||||
_setup.TestId = value;
|
||||
View?.SetTestName(_setup.TestId);
|
||||
}
|
||||
}
|
||||
|
||||
public double SampleRate
|
||||
{
|
||||
get => _setup?.SampleRate ?? 10000;
|
||||
set
|
||||
{
|
||||
if (_setup.SampleRate != value)
|
||||
{
|
||||
TestSetupImported = false;
|
||||
_setup.SampleRate = value;
|
||||
}
|
||||
OnPropertyChanged(PropertyNames.SampleRate.ToString());
|
||||
OnPropertyChanged(PropertyNames.AAF_TDAS.ToString());
|
||||
OnPropertyChanged(PropertyNames.AAF_SLICE.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPropertyChanged(PropertyNames sampleRate)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public RecordingModes RecordingMode
|
||||
{
|
||||
get => _setup?.Mode ?? RecordingModes.CircularBuffer;
|
||||
set
|
||||
{
|
||||
if (_setup.Mode != value)
|
||||
{
|
||||
TestSetupImported = false;
|
||||
switch (value)
|
||||
{
|
||||
case RecordingModes.CircularBuffer:
|
||||
case RecordingModes.Recorder:
|
||||
case RecordingModes.HybridRecorder:
|
||||
_setup.Mode = value;
|
||||
break;
|
||||
default:
|
||||
_setup.Mode = RecordingModes.CircularBuffer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
OnPropertyChanged("RecordingMode");
|
||||
OnPropertyChanged("SummaryPreTriggerVisibility");
|
||||
OnPropertyChanged("PostTriggerOrTestLength");
|
||||
OnPropertyChanged("IsROIValid");
|
||||
OnPropertyChanged("ImportEnabled");
|
||||
}
|
||||
}
|
||||
|
||||
public string PreTrigger
|
||||
{
|
||||
get => _setup?.PreTrigger.ToString("0.00") ?? "";
|
||||
set
|
||||
{
|
||||
if (!double.TryParse(value, out double preTrigger)) return;
|
||||
//if (preTrigger * -1 > _setup.ROIStart) ROIStart = (preTrigger * -1).ToString("0.00");
|
||||
//if (preTrigger * -1 > _setup.ROIEnd) ROIEnd = (preTrigger * -1).ToString("0.00");
|
||||
TestSetupImported = false;
|
||||
_setup.PreTrigger = preTrigger;
|
||||
OnPropertyChanged("PreTrigger");
|
||||
|
||||
OnPropertyChanged("IsROIValid");
|
||||
OnPropertyChanged("ImportEnabled");
|
||||
}
|
||||
}
|
||||
|
||||
public string PostTrigger
|
||||
{
|
||||
get => _setup?.PostTrigger.ToString("0.00") ?? "";
|
||||
set
|
||||
{
|
||||
if (!double.TryParse(value, out double postTrigger)) return;
|
||||
//if (postTrigger < _setup.ROIStart) ROIStart = postTrigger.ToString("0.00");
|
||||
//if (postTrigger < _setup.ROIEnd) ROIEnd = postTrigger.ToString("0.00");
|
||||
TestSetupImported = false;
|
||||
_setup.PostTrigger = postTrigger;
|
||||
OnPropertyChanged("PostTrigger");
|
||||
|
||||
OnPropertyChanged("IsROIValid");
|
||||
OnPropertyChanged("ImportEnabled");
|
||||
}
|
||||
}
|
||||
|
||||
public string ROIStart
|
||||
{
|
||||
get => _setup?.ROIStart.ToString("0.00") ?? "";
|
||||
set
|
||||
{
|
||||
if (!double.TryParse(value, out double roiStart)) return;
|
||||
if (roiStart < _setup.PreTrigger * -1 || roiStart > _setup.PostTrigger || roiStart > _setup.ROIEnd) return;
|
||||
TestSetupImported = false;
|
||||
_setup.ROIStart = roiStart;
|
||||
OnPropertyChanged("ROIStart");
|
||||
|
||||
OnPropertyChanged("IsROIValid");
|
||||
OnPropertyChanged("ImportEnabled");
|
||||
}
|
||||
}
|
||||
|
||||
public string ROIEnd
|
||||
{
|
||||
get => _setup?.ROIEnd.ToString("0.00") ?? "";
|
||||
set
|
||||
{
|
||||
if (!double.TryParse(value, out double roiEnd)) return;
|
||||
if (roiEnd < _setup.PreTrigger * -1 || roiEnd > _setup.PostTrigger || roiEnd < _setup.ROIStart) return;
|
||||
TestSetupImported = false;
|
||||
_setup.ROIEnd = roiEnd;
|
||||
OnPropertyChanged("ROIEnd");
|
||||
|
||||
OnPropertyChanged("IsROIValid");
|
||||
OnPropertyChanged("ImportEnabled");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
///<summary>
|
||||
///Occurs when a property value changes.
|
||||
///</summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<base:BaseView x:Class="TTSImport.ReadFileView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
|
||||
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:root="clr-namespace:TTSImport"
|
||||
xmlns:controls="clr-namespace:DTS.Common.Controls;assembly=DTS.Common">
|
||||
<base:BaseView.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/CommonStyles.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource PageContentTextStyle}" >
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Left"/>
|
||||
<Setter Property="Margin" Value="5" />
|
||||
</Style>
|
||||
<Style TargetType="TextBox">
|
||||
<Setter Property="Margin" Value="5" />
|
||||
</Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Margin" Value="5" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</base:BaseView.Resources>
|
||||
<Grid Background="{DynamicResource Brush_ApplicationContentBackground}" >
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" MinWidth="160"/>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<ContentControl Content="{Binding StatusAndProgressBarView}" Grid.Row="0" Grid.ColumnSpan="4" Height="100" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="{root:TranslateExtension ImportFile}" VerticalAlignment="Top"/>
|
||||
<Button Grid.Row="1" Grid.Column="1" Content="{root:TranslateExtension Browse}" Width="150" HorizontalAlignment="Left" AutomationProperties.AutomationId="btnBrowse" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding BrowseClicked}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<TextBlock Grid.Row="1" Grid.Column="2" TextWrapping="Wrap" Height="40"
|
||||
Text="{Binding FileToImport, FallbackValue='C:\\Data\\Long Path Here\\Data\\Long Path Here\\Data\\Long Path Here\\Data\\Long Path Here\\Data\\Long Path Here\\Import.csv'}" x:Name="tbExportFile"
|
||||
AutomationProperties.AutomationId="FileToImport" />
|
||||
</Grid>
|
||||
</base:BaseView>
|
||||
@@ -0,0 +1,18 @@
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS.DIChannels;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <inheritdoc cref="IDigitalInputChannelsView" />
|
||||
/// <summary>
|
||||
/// Interaction logic for HardwareScanView.xaml
|
||||
/// </summary>
|
||||
public partial class DigitalInputChannelsView : IDigitalInputChannelsView
|
||||
{
|
||||
public DigitalInputChannelsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using DTS.Common.Interface.TestSetups.Imports.TTS;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace TTSImport
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for EditFileView.xaml
|
||||
/// </summary>
|
||||
public partial class EditFileView : IEditFileView
|
||||
{
|
||||
public EditFileView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
/// <summary>
|
||||
/// handles when textbox text is changed
|
||||
/// this signals that we need to filter the available sensors
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
var tb = (TextBox)sender;
|
||||
var text = tb.Text;
|
||||
var vm = (IEditFileViewModel)tb.DataContext;
|
||||
vm.Search(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user