1683 lines
74 KiB
C#
1683 lines
74 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Data;
|
|
using System.ComponentModel;
|
|
using System.Data.SqlClient;
|
|
using System.Windows;
|
|
|
|
namespace DatabaseImport
|
|
{
|
|
public class TestTemplate : TagAwareBase, IComparable<TestTemplate>, ICachedContainer
|
|
{
|
|
/// <summary>
|
|
/// returns true whenever the test template is a quick test setup, false otherwise
|
|
/// </summary>
|
|
public bool QuickSensorCheck { get; set; }
|
|
|
|
// #region var and const
|
|
|
|
public const string NON_ISO_INTERNAL_GROUP_NAME = "[NONE]";
|
|
private const int MAX_REALTIME_CHANNELS = 6;
|
|
private const int MAX_ERRORS_TO_DISPLAY = 5;
|
|
internal List<CalculatedValueClass> CalculatedChannels = new List<CalculatedValueClass>();
|
|
private string _errorMessage = "";
|
|
|
|
/// <summary>
|
|
/// dictionary of harware overrides for the test
|
|
/// key is hardware id
|
|
/// if present, then value is whether the hardware is included or removed from the test.
|
|
/// </summary>
|
|
internal Dictionary<string, HardwareInclusionInstruction> HardwareOverrides = new Dictionary<string, HardwareInclusionInstruction>();
|
|
|
|
/// <summary>
|
|
/// cache of sensors for the test setup
|
|
/// this keeps us from having to lookup sensors and apply changes every time we need to use them
|
|
/// </summary>
|
|
public Dictionary<string, Dictionary<string, Dictionary<string, SensorData>>> SensorLookup = new Dictionary<string, Dictionary<string, Dictionary<string, SensorData>>>();
|
|
|
|
public string TestSetupXml { get; set; }
|
|
|
|
private readonly Dictionary<string, DASSettings> _dasSettings = new Dictionary<string, DASSettings>();
|
|
public DASSettings[] DASSettings
|
|
{
|
|
get => _dasSettings.Count < 1 ? new DASSettings[0] : _dasSettings.Values.ToArray();
|
|
set
|
|
{
|
|
_dasSettings.Clear();
|
|
foreach (var setting in value) { _dasSettings[setting.DASSerialNumber] = setting; }
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// whether to upload data after data collection is completed
|
|
/// this lets you separate out the time consumptive network data tasks from the ones you want to keep fast (export/view)
|
|
/// </summary>
|
|
private bool _uploadData;
|
|
public bool UploadData
|
|
{
|
|
get => _uploadData;
|
|
set => SetProperty(ref _uploadData, value, TestTemplateTags.UploadData.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// whether to upload data after data collection is completed
|
|
/// this lets you separate out the time consumptive network data tasks from the ones you want to keep fast (export/view)
|
|
/// </summary>
|
|
private bool _uploadExportsOnly;
|
|
public bool UploadExportsOnly
|
|
{
|
|
get => _uploadExportsOnly;
|
|
set => SetProperty(ref _uploadExportsOnly, value, TestTemplateTags.UploadExportsOnly.ToString());
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// folder to upload to
|
|
/// </summary>
|
|
private string _uploadFolder = "";
|
|
public string UploadFolder
|
|
{
|
|
get => _uploadFolder;
|
|
set => SetProperty(ref _uploadFolder, value, TestTemplateTags.UploadFolder.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// whether all units in the test share a common line
|
|
/// this should be set to false if DAS in the test don't share a common line
|
|
/// the default is true
|
|
/// if units share a common status line and there are multiple units in the test, then each unit will monitor the status line
|
|
/// if false or there's only one unit, the status line should not be monitored
|
|
/// </summary>
|
|
private bool _bCommonLine;
|
|
public bool CommonLine
|
|
{
|
|
get => _bCommonLine;
|
|
set => SetProperty(ref _bCommonLine, value, TestTemplateTags.CommonLine.ToString());
|
|
}
|
|
/// <summary>
|
|
/// true if the test objects and other fields have already been loaded from the database, false otherwise
|
|
/// </summary>
|
|
internal bool _bIsLoaded;
|
|
public bool IsLoaded => _bIsLoaded;
|
|
|
|
/// <summary>
|
|
/// when true the expectation is that any unit that can have a battery will have a battery, and the user should be warned
|
|
/// whenever a unit that should have a battery does not have an acceptable battery voltage
|
|
/// </summary>
|
|
private bool _warnOnFailedBattery;
|
|
public bool WarnOnFailedBattery
|
|
{
|
|
get => _warnOnFailedBattery;
|
|
set => SetProperty(ref _warnOnFailedBattery, value, TestTemplateTags.WarnOnFailedBattery.ToString());
|
|
}
|
|
public string CompletionErrorMessage => _testTemplateLite.CompletionErrorMessage;
|
|
|
|
/// <summary>
|
|
/// returns whether the test setup is dirty or not (whether the is complete is calculated already or not)
|
|
/// </summary>
|
|
private bool _bIsDirty = true;
|
|
public bool IsDirty
|
|
{
|
|
get => _bIsDirty;
|
|
set => _bIsDirty = value;
|
|
}
|
|
private List<TestGraph> _testGraphs = new List<TestGraph>();
|
|
private TestTemplateLite _testTemplateLite;
|
|
public string Name
|
|
{
|
|
get => _testTemplateLite.Name;
|
|
set => _testTemplateLite.Name = value;
|
|
}
|
|
private bool _bAllowMissingSensors;
|
|
public bool AllowMissingSensors
|
|
{
|
|
get => _bAllowMissingSensors;
|
|
set => SetProperty(ref _bAllowMissingSensors, value, TestTemplateTags.AllowMissingSensors.ToString());
|
|
}
|
|
|
|
private bool _bAllowSensorIdToBlankChannel;
|
|
public bool AllowSensorIdToBlankChannel
|
|
{
|
|
get => _bAllowSensorIdToBlankChannel;
|
|
set => SetProperty(ref _bAllowSensorIdToBlankChannel, value, TestTemplateTags.AllowSensorIdToBlankChannel.ToString());
|
|
}
|
|
|
|
private bool _bAutomaticProgression;
|
|
public bool AutomaticProgression
|
|
{
|
|
get => _bAutomaticProgression;
|
|
set => SetProperty(ref _bAutomaticProgression, value, TestTemplateTags.AutomaticProgression.ToString());
|
|
}
|
|
|
|
private int _automaticProgressionDelayMs;
|
|
|
|
public int AutomaticProgressionDelayMS
|
|
{
|
|
get => _automaticProgressionDelayMs;
|
|
set => SetProperty(ref _automaticProgressionDelayMs, value,
|
|
TestTemplateTags.AutomaticProgressionDelayMS.ToString());
|
|
}
|
|
|
|
private bool _invertTriggerCompletion;
|
|
|
|
public bool InvertTriggerCompletion
|
|
{
|
|
get => _invertTriggerCompletion;
|
|
set => SetProperty(ref _invertTriggerCompletion, value,
|
|
TestTemplateTags.InvertTriggerCompletion.ToString());
|
|
}
|
|
|
|
private bool _triggerCheckStep;
|
|
public bool TriggerCheckStep
|
|
{
|
|
get => _triggerCheckStep;
|
|
set => SetProperty(ref _triggerCheckStep, value, TestTemplateTags.TriggerCheckStep.ToString());
|
|
}
|
|
|
|
private int _postTestDiagnosticsLevel;
|
|
public bool PostTestDiagnosticsLevel
|
|
{
|
|
get => _postTestDiagnosticsLevel != 0;
|
|
set
|
|
{
|
|
if (value) { SetProperty(ref _postTestDiagnosticsLevel, 255, TestTemplateTags.PostTestDiagnostics.ToString()); }
|
|
else { SetProperty(ref _postTestDiagnosticsLevel, 0, TestTemplateTags.PostTestDiagnostics.ToString()); }
|
|
}
|
|
}
|
|
|
|
private bool _triggerCheckRealtime;
|
|
|
|
public bool TriggerCheckRealtime
|
|
{
|
|
get => _triggerCheckRealtime;
|
|
set => SetProperty(ref _triggerCheckRealtime, value, TestTemplateTags.TriggerCheckRealtime.ToString());
|
|
}
|
|
|
|
private bool _invertStartRecordCompletion;
|
|
|
|
public bool InvertStartRecordCompletion
|
|
{
|
|
get => _invertStartRecordCompletion;
|
|
set => SetProperty(ref _invertStartRecordCompletion, value,
|
|
TestTemplateTags.InvertStartRecordCompletion.ToString());
|
|
}
|
|
|
|
private bool _bViewDiagnostics = true;
|
|
public bool ViewDiagnostics
|
|
{
|
|
get => _bViewDiagnostics;
|
|
set => SetProperty(ref _bViewDiagnostics, value, TestTemplateTags.ViewDiagnostics.ToString());
|
|
}
|
|
|
|
private bool _bVerify = true;
|
|
|
|
public bool VerifyChannels
|
|
{
|
|
get => _bVerify;
|
|
set => SetProperty(ref _bVerify, value, TestTemplateTags.VerifyChannels.ToString());
|
|
}
|
|
|
|
private bool _bAutoVerifyChannels = true;
|
|
public bool AutoVerifyChannels
|
|
{
|
|
get => _bAutoVerifyChannels;
|
|
set => SetProperty(ref _bAutoVerifyChannels, value, TestTemplateTags.AutoVerifyProgress.ToString());
|
|
}
|
|
|
|
private double _autoVerifyDelay = 2D;
|
|
|
|
public double AutoVerifyDelaySeconds
|
|
{
|
|
get => _autoVerifyDelay;
|
|
set => SetProperty(ref _autoVerifyDelay, value, TestTemplateTags.AutoVerifyDelaySeconds.ToString());
|
|
}
|
|
private bool _bUseCustomerDetails;
|
|
public bool UseCustomerDetails
|
|
{
|
|
get => _bUseCustomerDetails;
|
|
set => SetProperty(ref _bUseCustomerDetails, value, TestTemplateTags.UseCustomerDetails.ToString());
|
|
}
|
|
private bool _bUseTestEngineerDetails;
|
|
public bool UseTestEngineerDetails
|
|
{
|
|
get => _bUseTestEngineerDetails;
|
|
set => SetProperty(ref _bUseTestEngineerDetails, value, TestTemplateTags.UseTestEngineerDetails.ToString());
|
|
}
|
|
private bool _bTurnOffExcitation = true;
|
|
public bool TurnOffExcitation
|
|
{
|
|
get => _bTurnOffExcitation;
|
|
set => SetProperty(ref _bTurnOffExcitation, value, TestTemplateTags.TurnOffExcitation.ToString());
|
|
}
|
|
|
|
private bool _bUseLabratoryDetails;
|
|
public bool UseLabratoryDetails
|
|
{
|
|
get => _bUseLabratoryDetails;
|
|
set => SetProperty(ref _bUseLabratoryDetails, value, TestTemplateTags.UseLabratoryDetails.ToString());
|
|
}
|
|
private bool _localOnly;
|
|
public bool LocalOnly
|
|
{
|
|
get => _localOnly;
|
|
set => SetProperty(ref _localOnly, value, TestTemplateTags.LocalOnly.ToString());
|
|
}
|
|
|
|
public DateTime LastModified
|
|
{
|
|
get => _testTemplateLite.LastModified;
|
|
set
|
|
{
|
|
_testTemplateLite.LastModified = value;
|
|
OnPropertyChanged(TestTemplateTags.LastModified.ToString());
|
|
}
|
|
}
|
|
public string LastModifiedBy
|
|
{
|
|
get => _testTemplateLite.LastModifiedBy;
|
|
set
|
|
{
|
|
_testTemplateLite.LastModifiedBy = value;
|
|
OnPropertyChanged(TestTemplateTags.LastMmodifiedBy.ToString());
|
|
}
|
|
}
|
|
|
|
public string Description
|
|
{
|
|
get => _testTemplateLite.Description;
|
|
set
|
|
{
|
|
_testTemplateLite.Description = value;
|
|
OnPropertyChanged(TestTemplateTags.Description.ToString());
|
|
}
|
|
}
|
|
|
|
private double _samplesPerSecond;
|
|
public double SamplesPerSecond
|
|
{
|
|
get => _samplesPerSecond;
|
|
set
|
|
{
|
|
SetProperty(ref _samplesPerSecond, value, TestTemplateTags.SamplesPerSecond.ToString());
|
|
OnPropertyChanged(TestTemplateTags.SampleRateText.ToString());
|
|
}
|
|
}
|
|
public double PreTriggerSeconds
|
|
{
|
|
get => _testTemplateLite.PreTriggerSeconds;
|
|
set
|
|
{
|
|
_testTemplateLite.PreTriggerSeconds = value;
|
|
foreach (var roi in RegionsOfInterest)
|
|
{
|
|
roi.PreTrigger = PreTriggerSeconds * -1D;
|
|
}
|
|
OnPropertyChanged(TestTemplateTags.PreTriggerSeconds.ToString());
|
|
}
|
|
}
|
|
|
|
public double PostTriggerSeconds
|
|
{
|
|
get => _testTemplateLite.PostTriggerSeconds;
|
|
set
|
|
{
|
|
_testTemplateLite.PostTriggerSeconds = value;
|
|
foreach (var roi in RegionsOfInterest)
|
|
{
|
|
roi.PostTrigger = PostTriggerSeconds;
|
|
}
|
|
OnPropertyChanged(TestTemplateTags.PostTriggerSeconds.ToString());
|
|
}
|
|
}
|
|
|
|
private string _isfFile = "";
|
|
|
|
public string ISFFile
|
|
{
|
|
get => _isfFile;
|
|
set => SetProperty(ref _isfFile, value, TestTemplateTags.ISFFile.ToString());
|
|
}
|
|
|
|
private bool _doAutoArm;
|
|
public bool DoAutoArm
|
|
{
|
|
get => _doAutoArm;
|
|
set => SetProperty(ref _doAutoArm, value, TestTemplateTags.DoAutoArm.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// CheckoutMode means a non destructive data collection
|
|
/// squib fires will only occur internally
|
|
/// </summary>
|
|
private bool _checkoutMode;
|
|
public bool CheckoutMode
|
|
{
|
|
get => _checkoutMode;
|
|
set => SetProperty(ref _checkoutMode, value, TestTemplateTags.CheckoutMode.ToString());
|
|
}
|
|
/// <summary>
|
|
/// QuitTestWithoutWarning flag will suppress warnings on exit
|
|
/// see: 7509 add option to Quit Test Without Warning
|
|
/// </summary>
|
|
private bool _quitTestWithoutWarning;
|
|
public bool QuitTestWithoutWarning
|
|
{
|
|
get => _quitTestWithoutWarning;
|
|
set => SetProperty(ref _quitTestWithoutWarning, value, TestTemplateTags.QuitTestWithoutWarning.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// SuppressMissingSensorsWarning flag will suppress missing sensors warnings
|
|
/// see: 8877 Suppress modal warning in checkout mode for missing sensors.
|
|
/// </summary>
|
|
private bool _suppressMissingSensorsWarning;
|
|
public bool SuppressMissingSensorsWarning
|
|
{
|
|
get => _suppressMissingSensorsWarning;
|
|
set => SetProperty(ref _suppressMissingSensorsWarning, value, TestTemplateTags.SuppressMissingSensorsWarning.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// suppress warnings on exit
|
|
/// see: 7642 add two test setup option to suppress "not all channels have been viewed" warnings in both real-time and viewer.
|
|
/// </summary>
|
|
private bool _notAllChannelsRealTime;
|
|
public bool NotAllChannelsRealTime
|
|
{
|
|
get => _notAllChannelsRealTime;
|
|
set => SetProperty(ref _notAllChannelsRealTime, value, TestTemplateTags.NotAllChannelsRealTime.ToString());
|
|
}
|
|
/// <summary>
|
|
/// suppress warnings on exit
|
|
/// see: 7642 add two test setup option to suppress "not all channels have been viewed" warnings in both real-time and viewer.
|
|
/// </summary>
|
|
private bool _notAllChannelsViewer;
|
|
public bool NotAllChannelsViewer
|
|
{
|
|
get => _notAllChannelsViewer;
|
|
set => SetProperty(ref _notAllChannelsViewer, value, TestTemplateTags.NotAllChannelsViewer.ToString());
|
|
}
|
|
|
|
public RecordingModes RecordingMode
|
|
{
|
|
get => _testTemplateLite.RecordingMode;
|
|
set
|
|
{
|
|
if (value != _testTemplateLite.RecordingMode)
|
|
{
|
|
_testTemplateLite.RecordingMode = value;
|
|
OnPropertyChanged(TestTemplateTags.RecordingMode.ToString());
|
|
OnPropertyChanged(TestTemplateTags.RecordingModeText.ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool _bStrictDiagnostics;
|
|
public bool StrictDiagnostics
|
|
{
|
|
get => _bStrictDiagnostics;
|
|
set => SetProperty(ref _bStrictDiagnostics, value, TestTemplateTags.StrictDiagnostics.ToString());
|
|
}
|
|
public TestTestObject[] TestObjectsWithChannels
|
|
{
|
|
get
|
|
{
|
|
var list = new List<TestTestObject>(_testObjects);
|
|
for (var i = list.Count - 1; i >= 0; i--)
|
|
{
|
|
var isoTestObject = list[i].GetISOTestObject();
|
|
if (0 == isoTestObject.AllChannels.Length) { list.RemoveAt(i); }
|
|
}
|
|
return list.ToArray();
|
|
}
|
|
}
|
|
public List<TestObject> TestObjectsAndAddedGroupsList = new List<TestObject>();
|
|
// public TestObject[] TestObjectsAndAddedGroups => TestObjectsAndAddedGroupsList.ToArray();
|
|
private List<TestTestObject> _testObjects = new List<TestTestObject>();
|
|
public TestTestObject[] TestObjects
|
|
{
|
|
get => _testObjects.ToArray();
|
|
}
|
|
|
|
|
|
private List<TestTestObject> _addedGroups = new List<TestTestObject>();
|
|
public TestTestObject[] AddedGroups
|
|
{
|
|
get => _addedGroups.ToArray();
|
|
set
|
|
{
|
|
//MarkIsCompleteUnchecked(); Removed to fix FB 10241 with the assumption that simply Setting AddedGroups should not cause a database write.
|
|
SetProperty(ref _addedGroups, new List<TestTestObject>(value), TestTemplateTags.SysBuiltTestObjectTypes.ToString());
|
|
OnPropertyChanged(TestTemplateTags.AllTestObjects.ToString());//check this
|
|
OnPropertyChanged("TestObjectsAndAddedGroups");
|
|
OnPropertyChanged(TestTemplateTags.TestObjectsAndAddedGroups.ToString());
|
|
}
|
|
}
|
|
private bool _bRequireUserConfirmationOnErrors;
|
|
public bool RequireUserConfirmationOnErrors
|
|
{
|
|
get => _bRequireUserConfirmationOnErrors;
|
|
set => SetProperty(ref _bRequireUserConfirmationOnErrors, value, TestTemplateTags.RequireUserConfirmationOnErrors.ToString());
|
|
}
|
|
|
|
private bool _roiDownload;
|
|
public bool DoROIDownload
|
|
{
|
|
get => _roiDownload;
|
|
set
|
|
{
|
|
SetProperty(ref _roiDownload, value, TestTemplateTags.DoROIDownload.ToString());
|
|
OnPropertyChanged(TestTemplateTags.ROIButtonVisibility.ToString());
|
|
}
|
|
}
|
|
private bool _roiDownloadView;
|
|
public bool ViewROIDownload
|
|
{
|
|
get => _roiDownloadView;
|
|
set
|
|
{
|
|
SetProperty(ref _roiDownloadView, value, TestTemplateTags.ViewROIDownload.ToString());
|
|
OnPropertyChanged(TestTemplateTags.ViewROIDownloadButtonVisibility.ToString());
|
|
}
|
|
}
|
|
private bool _downloadAll;
|
|
public bool DownloadAll
|
|
{
|
|
get => _downloadAll;
|
|
set
|
|
{
|
|
SetProperty(ref _downloadAll, value, TestTemplateTags.DownloadAll.ToString());
|
|
OnPropertyChanged(TestTemplateTags.DownloadAllButtonVisibility.ToString());
|
|
}
|
|
}
|
|
|
|
private bool _viewRealtime;
|
|
public bool ViewRealtime
|
|
{
|
|
get => 0 != GetNumberOfRealtimeSupportedChannels() && _viewRealtime;
|
|
set
|
|
{
|
|
SetProperty(ref _viewRealtime, value, TestTemplateTags.ViewRealtime.ToString());
|
|
OnPropertyChanged(TestTemplateTags.ViewRealtime.ToString());
|
|
}
|
|
}
|
|
|
|
private BindingList<RegionOfInterest> _regionsOfInterest = new BindingList<RegionOfInterest>();
|
|
|
|
public BindingList<RegionOfInterest> RegionsOfInterest
|
|
{
|
|
get => _regionsOfInterest;
|
|
set
|
|
{
|
|
if (null != value)
|
|
{
|
|
_regionsOfInterest.ListChanged -= _roi_ListChanged;
|
|
foreach (var roi in value)
|
|
{
|
|
roi.PreTrigger = PreTriggerSeconds * -1D;
|
|
roi.PostTrigger = PostTriggerSeconds;
|
|
}
|
|
SetProperty(ref _regionsOfInterest, value, TestTemplateTags.RegionsOfInterest.ToString());
|
|
_regionsOfInterest.ListChanged += _roi_ListChanged;
|
|
}
|
|
}
|
|
}
|
|
|
|
private double _roiStart;
|
|
public double ROIStart
|
|
{
|
|
get => _roiStart;
|
|
set => SetProperty(ref _roiStart, value, TestTemplateTags.ROIStart.ToString());
|
|
}
|
|
|
|
private double _roiEnd;
|
|
public double ROIEnd
|
|
{
|
|
get => _roiEnd;
|
|
set => SetProperty(ref _roiEnd, value, TestTemplateTags.ROIEnd.ToString());
|
|
}
|
|
private bool _viewDownloadAll;
|
|
public bool ViewDownloadAll
|
|
{
|
|
get => _viewDownloadAll;
|
|
set
|
|
{
|
|
SetProperty(ref _viewDownloadAll, value, TestTemplateTags.ViewDownloadAll.ToString());
|
|
OnPropertyChanged(TestTemplateTags.ViewDownloadAllButtonVisibility.ToString());
|
|
}
|
|
}
|
|
private bool _viewExport;
|
|
public bool ViewExport
|
|
{
|
|
get => _viewExport;
|
|
set
|
|
{
|
|
SetProperty(ref _viewExport, value, TestTemplateTags.ViewExport.ToString());
|
|
OnPropertyChanged(TestTemplateTags.ViewExportButtonVisibility.ToString());
|
|
}
|
|
}
|
|
private SupportedExportFormatBitFlags _exportFormats;
|
|
public SupportedExportFormatBitFlags ExportFormats
|
|
{
|
|
get => _exportFormats;
|
|
set => SetProperty(ref _exportFormats, value, TestTemplateTags.ExportFormats.ToString());
|
|
}
|
|
|
|
private string _downloadFolder = Properties.Settings.Default.DownloadFolder;
|
|
public string DownloadFolder
|
|
{
|
|
get => _downloadFolder;
|
|
set => SetProperty(ref _downloadFolder, value, TestTemplateTags.DownloadFolder.ToString());
|
|
}
|
|
|
|
private string _exportFolder = Properties.Settings.Default.DownloadFolder;
|
|
public string ExportFolder
|
|
{
|
|
get => _exportFolder;
|
|
set => SetProperty(ref _exportFolder, value, TestTemplateTags.ExportFolder.ToString());
|
|
}
|
|
|
|
private bool _sameAsDownloadFolder = true;
|
|
public bool SameAsDownloadFolder
|
|
{
|
|
get => _sameAsDownloadFolder;
|
|
set => SetProperty(ref _sameAsDownloadFolder, value, TestTemplateTags.SameAsDownloadFolder.ToString());
|
|
}
|
|
private LabratoryDetails _labDetails;
|
|
public LabratoryDetails LabDetails
|
|
{
|
|
get => _labDetails;
|
|
set => SetProperty(ref _labDetails, value, TestTemplateTags.LabDetails.ToString());
|
|
}
|
|
|
|
private CustomerDetails _customerDetails;
|
|
public CustomerDetails CustomerDetails
|
|
{
|
|
get => _customerDetails;
|
|
set => SetProperty(ref _customerDetails, value, TestTemplateTags.CustomerDetails.ToString());
|
|
}
|
|
|
|
private TestEngineerDetails _testEngineerDetails;
|
|
public TestEngineerDetails TestEngineerDetails
|
|
{
|
|
get => _testEngineerDetails;
|
|
set => SetProperty(ref _testEngineerDetails, value, TestTemplateTags.TestEngineerDetails.ToString());
|
|
}
|
|
private int _defaultNumberRealtimeGraphs;
|
|
public int DefaultNumberRealtimeGraphs
|
|
{
|
|
get
|
|
{
|
|
switch (_defaultNumberRealtimeGraphs)
|
|
{
|
|
case 6:
|
|
return 6;
|
|
case 3:
|
|
return 3;
|
|
case 1:
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
set
|
|
{
|
|
switch (value)
|
|
{
|
|
case 6:
|
|
_defaultNumberRealtimeGraphs = value;
|
|
break;
|
|
case 3:
|
|
_defaultNumberRealtimeGraphs = value;
|
|
break;
|
|
case 1:
|
|
default:
|
|
_defaultNumberRealtimeGraphs = value;
|
|
break;
|
|
}
|
|
OnPropertyChanged(TestTemplateTags.DefaultNumberRealtimeGraphs.ToString());
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// this is a brave new world, this is the hardware for this test.
|
|
/// now groups in this test setup may have hardware assigned, or no hardware assigned
|
|
/// we'll take that if we find it, but then we'll also check a list we have for the test itself and intersect the two
|
|
/// we then modify the groups IN MEMORY and change their hardware to match all hardware officially in the test
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public void ApplyHardwareOverrides()
|
|
{
|
|
//for now don't do anything if the test setup is non iso
|
|
var hardwareInTest = new Dictionary<string, DASHardware>();
|
|
foreach (var group in TestObjects)
|
|
{
|
|
foreach (var h in group.Hardware)
|
|
{
|
|
var hiso = h.GetHardware();
|
|
if (!hardwareInTest.ContainsKey(hiso.GetId()))
|
|
{
|
|
hardwareInTest.Add(hiso.GetId(), h);
|
|
}
|
|
}
|
|
}
|
|
foreach (var group in AddedGroups)
|
|
{
|
|
foreach (var h in group.Hardware)
|
|
{
|
|
var hiso = h.GetHardware();
|
|
if (!hardwareInTest.ContainsKey(hiso.GetId()))
|
|
{
|
|
hardwareInTest.Add(hiso.GetId(), h);
|
|
}
|
|
}
|
|
}
|
|
using (var e = HardwareOverrides.GetEnumerator())
|
|
{
|
|
while (e.MoveNext())
|
|
{
|
|
switch (e.Current.Value.Action)
|
|
{
|
|
case HardwareInclusionInstruction.Actions.Add:
|
|
if (!hardwareInTest.ContainsKey(e.Current.Value.HardwareId))
|
|
{
|
|
DASHardware h = null;
|
|
try
|
|
{
|
|
h = DASHardwareList.GetList().GetHardware(e.Current.Value.HardwareId);
|
|
}
|
|
catch (DASHardwareList.HardwareTypeChangedException)
|
|
{
|
|
//APILogger.Log("test: " + Name + " refers to hardware: " +
|
|
// e.Current.Value.HardwareId + " which has changed types. " +
|
|
// ex.Message);
|
|
}
|
|
if (null != h)
|
|
{
|
|
hardwareInTest.Add(h.GetHardware().GetId(), h);
|
|
}
|
|
}
|
|
break;
|
|
case HardwareInclusionInstruction.Actions.Remove:
|
|
if (hardwareInTest.ContainsKey(e.Current.Value.HardwareId))
|
|
{
|
|
hardwareInTest.Remove(e.Current.Value.HardwareId);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
GetNonISOTestObject();
|
|
foreach (var group in TestObjects)
|
|
{
|
|
var hardware = new List<DASHardware>();
|
|
using (var e2 = hardwareInTest.GetEnumerator())
|
|
{
|
|
while (e2.MoveNext())
|
|
{
|
|
var newH = new DASHardware(e2.Current.Value.GetHardware());
|
|
newH.SetTimeStampMemory(e2.Current.Value.GetTimeStampMemory());
|
|
hardware.Add(newH);
|
|
}
|
|
}
|
|
group.SetHardware(hardware.ToArray());
|
|
}
|
|
foreach (var ag in AddedGroups)
|
|
{
|
|
var hardware = new List<DASHardware>();
|
|
using (var e2 = hardwareInTest.GetEnumerator())
|
|
{
|
|
while (e2.MoveNext())
|
|
{
|
|
var newH = new DASHardware(e2.Current.Value.GetHardware());
|
|
newH.SetTimeStampMemory(e2.Current.Value.GetTimeStampMemory());
|
|
hardware.Add(newH);
|
|
}
|
|
}
|
|
ag.SetHardware(hardware.ToArray());
|
|
}
|
|
|
|
}
|
|
internal Dictionary<string, LevelTriggerChannel> LevelTriggerChannels = new Dictionary<string, LevelTriggerChannel>();
|
|
public string GetLTKey(LevelTriggerChannel ch)
|
|
{
|
|
return $"{ch.HardwareChannelId}x{ch.SensorSerialNumber}";
|
|
}
|
|
public void SetLevelTrigger(LevelTriggerChannel channel)
|
|
{
|
|
var key = GetLTKey(channel);
|
|
LevelTriggerChannels[key] = new LevelTriggerChannel(channel);//do a copy just for safety
|
|
}
|
|
/// <summary>
|
|
/// sets a channel to be disabled
|
|
/// disabled channels don't appear in run test
|
|
/// </summary>
|
|
/// <param name="groupName"></param>
|
|
/// <param name="channelName"></param>
|
|
/// <param name="disabled"></param>
|
|
public void SetDisabled(string groupName, string channelName, bool disabled)
|
|
{
|
|
var matches = from g in TestObjects where g.SerialNumber == groupName select g;
|
|
if (!matches.Any()) return;
|
|
var iso = matches.First().GetISOTestObject();
|
|
var allChannels = iso.AllChannels;
|
|
foreach (var ch in allChannels)
|
|
{
|
|
if (ch.Name == channelName)
|
|
{
|
|
ch.Disabled = disabled;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
public SensorData GetSensor(string serialNumber, string testObjectSerial, string channelName)
|
|
{
|
|
lock (SensorLock)
|
|
{
|
|
var tto = GetTestTestObject(testObjectSerial);
|
|
if (!SensorLookup.ContainsKey(testObjectSerial) ||
|
|
!SensorLookup[testObjectSerial].ContainsKey(channelName) ||
|
|
!SensorLookup[testObjectSerial][channelName].ContainsKey(serialNumber))
|
|
{
|
|
var matches = from s in _sensorsFromBinary where s.SerialNumber == serialNumber select s;
|
|
if (matches.Any())
|
|
{
|
|
var s = matches.First();
|
|
var position = tto.Position.Position;
|
|
if (position != TestTestObject.UserSetKey && position != TestTestObject.ChannelDefaultsKey &&
|
|
position != s.Position)
|
|
{
|
|
s.Position = position;
|
|
}
|
|
return s;
|
|
}
|
|
}
|
|
if (SensorLookup.ContainsKey(testObjectSerial))
|
|
{
|
|
if (SensorLookup[testObjectSerial].ContainsKey(channelName))
|
|
{
|
|
if (SensorLookup[testObjectSerial][channelName].ContainsKey(serialNumber))
|
|
{
|
|
if (SensorLookup[testObjectSerial][channelName][serialNumber].FilterClassIso == "?")
|
|
{
|
|
SensorLookup[testObjectSerial][channelName][serialNumber].FilterClassIso =
|
|
"P"; // "Prefiltered > CFC 1000" (Unfiltered)
|
|
}
|
|
//for some reason the Filter isn't always set, setting filterclassiso will ensure it gets set, even though it should have already _been_ set
|
|
SensorLookup[testObjectSerial][channelName][serialNumber].FilterClassIso =
|
|
SensorLookup[testObjectSerial][channelName][serialNumber].FilterClassIso;
|
|
if (null == tto)
|
|
{
|
|
return SensorLookup[testObjectSerial][channelName][serialNumber];
|
|
}
|
|
var position = tto.Position.Position;
|
|
if (position != TestTestObject.UserSetKey &&
|
|
position != TestTestObject.ChannelDefaultsKey &&
|
|
position != SensorLookup[testObjectSerial][channelName][serialNumber].Position)
|
|
{
|
|
SensorLookup[testObjectSerial][channelName][serialNumber].Position = position;
|
|
}
|
|
return SensorLookup[testObjectSerial][channelName][serialNumber];
|
|
}
|
|
}
|
|
}
|
|
if (null == tto)
|
|
{
|
|
return SensorData.IsTestSpecificDigitalOutSN(serialNumber)
|
|
? new DigitalOutputSetting { SerialNumber = serialNumber }
|
|
: SensorsCollection.SensorsList.GetSensorBySerialNumber(serialNumber);
|
|
}
|
|
|
|
var ttosd = tto.GetSensor(channelName, serialNumber);
|
|
if (ttosd != null)
|
|
{
|
|
ttosd.TestObject = tto.TestObject.Test_Object;
|
|
var position = tto.Position.Position;
|
|
if (position != TestTestObject.UserSetKey &&
|
|
position != TestTestObject.ChannelDefaultsKey &&
|
|
position != ttosd.Position)
|
|
{
|
|
ttosd.Position = position;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return SensorData.IsTestSpecificDigitalOutSN(serialNumber)
|
|
? new DigitalOutputSetting { SerialNumber = serialNumber }
|
|
: null;
|
|
}
|
|
return ttosd;
|
|
}
|
|
}
|
|
public void SetSensor(SensorData sd, string testobjectserial, string channelname)
|
|
{
|
|
SetSensor(sd, testobjectserial, channelname, false);
|
|
}
|
|
|
|
private static readonly object SensorLock = new object();
|
|
|
|
/// <summary>
|
|
/// sets the sensor (and custom values like range/CFC/polarity) for a channel in the test
|
|
/// </summary>
|
|
/// <param name="sd"></param>
|
|
/// <param name="testobjectserial"></param>
|
|
/// <param name="channelname"></param>
|
|
/// <param name="bSetPositionFromSensor"></param>
|
|
public void SetSensor(SensorData sd, string testobjectserial, string channelname, bool bSetPositionFromSensor)
|
|
{
|
|
lock (SensorLock)
|
|
{
|
|
if (!SensorLookup.ContainsKey(testobjectserial))
|
|
{
|
|
SensorLookup.Add(testobjectserial, new Dictionary<string, Dictionary<string, SensorData>>());
|
|
}
|
|
if (!SensorLookup[testobjectserial].ContainsKey(channelname))
|
|
{
|
|
SensorLookup[testobjectserial].Add(channelname, new Dictionary<string, SensorData>());
|
|
}
|
|
//Build out the ISO fields we know about
|
|
// FB 5423
|
|
var tto = GetTestTestObject(testobjectserial) ?? new TestTestObject(new TestObject());
|
|
sd.TestObject = tto.TestObject.Test_Object;
|
|
|
|
|
|
// ReSharper disable once InconsistentNaming
|
|
var isoTO = tto.GetISOTestObject();
|
|
var channel = isoTO.GetChannel(channelname);
|
|
if (bSetPositionFromSensor)
|
|
{
|
|
if (tto.Position.Position != sd.Position && tto.Position.Position != TestTestObject.UserSetKey)
|
|
{
|
|
tto.SetPosition(TestTestObject.UserSetKey);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((tto.Position.Position != TestTestObject.ChannelDefaultsKey) && //Remove this?
|
|
(tto.Position.Position != TestTestObject.UserSetKey))
|
|
{
|
|
sd.Position = tto.Position.Position;
|
|
}
|
|
}
|
|
if (null != channel)
|
|
{
|
|
sd.FineLocation1 = channel.Channel.Fine_Loc_1;
|
|
sd.FineLocation2 = channel.Channel.Fine_Loc_2;
|
|
sd.FineLocation3 = channel.Channel.Fine_Loc_3;
|
|
sd.MainLocation = channel.Channel.Trans_Main_Loc;
|
|
sd.PhysicalDimension = channel.Channel.Physical_Dimension;
|
|
sd.Direction = channel.Channel.Direction;
|
|
}
|
|
|
|
SensorLookup[testobjectserial][channelname][sd.SerialNumber] = sd;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// sets the dirty flag
|
|
/// does NOT set the flag in the database, so this should only be called when the flag needs to be set in memory
|
|
/// (for instance during initialization)
|
|
/// </summary>
|
|
/// <param name="bDirty"></param>
|
|
public void SetIsDirty(bool bDirty)
|
|
{
|
|
_bIsDirty = bDirty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// sets the complete flag
|
|
/// does not set the flag in the database, so this should only be called when the flag needs to be set in memory
|
|
/// (for instance during initialization)
|
|
/// </summary>
|
|
/// <param name="bComplete"></param>
|
|
public void SetIsComplete(bool bComplete)
|
|
{
|
|
_testTemplateLite.IsComplete = bComplete;
|
|
}
|
|
|
|
/// <summary>
|
|
/// sets the completion error message.
|
|
/// does not set the field in the db, so this should only be called when the information nets to be set in memory and not the db
|
|
/// (for instance during initialization)
|
|
/// </summary>
|
|
/// <param name="msg"></param>
|
|
public void SetCompletionErrorMessage(string msg)
|
|
{
|
|
_errorMessage = msg;
|
|
}
|
|
|
|
public int CompareTo(TestTemplate right)
|
|
{
|
|
if (null == right) { return 1; }
|
|
var r = string.Compare(Name, right.Name, StringComparison.Ordinal);
|
|
return 0 == r ? LastModified.CompareTo(right.LastModified) : r;
|
|
}
|
|
|
|
public TestTestObject GetTestTestObject(string testObjectSerial)
|
|
{
|
|
foreach (var tto in TestObjects)
|
|
{
|
|
if (tto.SerialNumber == testObjectSerial) { return tto; }
|
|
}
|
|
return Array.Find(AddedGroups, addedGroup => addedGroup.SerialNumber == testObjectSerial);
|
|
}
|
|
|
|
/// <summary>
|
|
/// a list of hardware as read from the XML/binary
|
|
/// this is used as the record of hardware that was present when test was committed
|
|
/// </summary>
|
|
private List<DASHardware> _hardwareFromBinary = new List<DASHardware>();
|
|
|
|
/// <summary>
|
|
/// a list of sensors as read from the XML/binary
|
|
/// this is used as the record of hardware that was present when test was committed
|
|
/// </summary>
|
|
private List<SensorData> _sensorsFromBinary = new List<SensorData>();
|
|
|
|
/// <summary>
|
|
/// a list of sensor calibrations as read from the XML/binary
|
|
/// this is used as the record of calibrations that was present when test was committed
|
|
/// </summary>
|
|
private List<SensorCalibration> _calibrationsFromBinary = new List<SensorCalibration>();
|
|
|
|
public IISOHardware[] GetAllCachedHardware()
|
|
{
|
|
var list = from h in _hardwareFromBinary select h.GetHardware();
|
|
if (list.Any())
|
|
{
|
|
return list.ToArray();
|
|
}
|
|
return new IISOHardware[0];
|
|
}
|
|
|
|
public DASHardware GetCachedHardware(string serialNumber)
|
|
{
|
|
var matches = from h in _hardwareFromBinary where h.SerialNumber == serialNumber select h;
|
|
if (matches.Any())
|
|
{
|
|
return matches.First();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// #region Validate
|
|
|
|
public static bool ValidateTestSetupName(ref List<string> errors, TestTemplate CurrentTestSetup)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(CurrentTestSetup.Name))
|
|
{
|
|
errors.Add("EditTestSetup_NameRequired");
|
|
return false;
|
|
}
|
|
if (CurrentTestSetup.Name == "QuickSensorCheck_DefaultTestName" &&
|
|
!CurrentTestSetup.QuickSensorCheck)
|
|
{
|
|
errors.Add("QuickSensorCheck_DefaultTestNameInvalid");
|
|
return false;
|
|
}
|
|
|
|
if (DiskUtility.ValidateFileAndPathNameChars(CurrentTestSetup.Name))
|
|
{
|
|
var nameToCheck = CurrentTestSetup.Name.ToLower();
|
|
if (nameToCheck.Equals("iso") || nameToCheck.Equals("csv") || nameToCheck.Equals("realtime"))
|
|
{
|
|
errors.Add("EditTestSetup_NameCannotBeISOCSVOrRealtime");
|
|
return false;
|
|
}
|
|
|
|
var encoding = Encoding.GetEncoding("UTF-8");
|
|
var nameInBytes = encoding.GetBytes(nameToCheck);
|
|
if (nameInBytes.Length == nameToCheck.Length) return true;
|
|
errors.Add("EditTestSetup_NameCannotContainDoubleByteCharacters");
|
|
return false;
|
|
}
|
|
errors.Add("EditTestSetup_NameContainsInvalidCharacters");
|
|
//fatal
|
|
return false;
|
|
}
|
|
|
|
public static bool Validate(ref List<string> errors, ref List<string> warnings, bool displayWindow, TestTemplate CurrentTestSetup, bool bValid, StrictLevel strictness, bool bWarnOnNotFullyAssigned, bool bRefreshHardware = true)
|
|
{
|
|
if (!Validate(ref errors, ref warnings, displayWindow, CurrentTestSetup, bValid, strictness, true,
|
|
bWarnOnNotFullyAssigned, bRefreshHardware))
|
|
{
|
|
CurrentTestSetup.SetIsComplete(false);
|
|
return false;
|
|
}
|
|
if (errors.Any())
|
|
{
|
|
CurrentTestSetup.SetIsComplete(false);
|
|
return false;
|
|
}
|
|
CurrentTestSetup.SetIsComplete(true);
|
|
return true;
|
|
}
|
|
|
|
private SensorCalibration GetSensorCalibration(SensorData sd, ExcitationVoltageOptions.ExcitationVoltageOption preferredExcitation)
|
|
{
|
|
var matches = from sc in _calibrationsFromBinary where sc.SerialNumber == sd.SerialNumber select sc;
|
|
if (matches.Any())
|
|
{
|
|
SensorCalibration sc = null;
|
|
|
|
foreach (var cal in matches)
|
|
{
|
|
if (cal.IsProportional)
|
|
{
|
|
var bIsOk = Array.Exists(cal.Records.Records, record => record.Excitation == preferredExcitation);
|
|
if (!bIsOk) { continue; }
|
|
}
|
|
if (null == sc) { sc = cal; }
|
|
else if (sc.CalibrationDate < cal.CalibrationDate) { sc = cal; }
|
|
else if (sc.CalibrationDate == cal.CalibrationDate && sc.ModifyDate < cal.ModifyDate)
|
|
{
|
|
sc = cal;
|
|
}
|
|
}
|
|
|
|
if (null != sc) { return sc; }
|
|
}
|
|
return SensorCalibration.GetLatestCalibrationBySerialNumberAndExcitation(sd, preferredExcitation);
|
|
}
|
|
public static bool Validate(ref List<string> errors, ref List<string> warnings, bool displayWindow, TestTemplate CurrentTestSetup, bool bValid, StrictLevel strictness, bool markIsCompleteUnchecked, bool bWarnOnNotFullyAssigned, bool bRefreshHardware)
|
|
{
|
|
//I'm not sure of all the entry points into this function
|
|
//it seems like there are many
|
|
//however there are definite times we _don't_ want to just blindly change the iscompleteunchecked flag
|
|
//just because we want to do some validation on the test plan ...
|
|
//for now I just fixed the ones I know shouldn't be changing the flag blindly
|
|
//and preserved current behavior for the rest ...
|
|
//if (markIsCompleteUnchecked) { CurrentTestSetup.MarkIsCompleteUnchecked(); }
|
|
|
|
var bHasHardware = false;
|
|
var bHasChannels = false;
|
|
|
|
var testobjects = new List<TestTestObject>();
|
|
testobjects.AddRange(CurrentTestSetup.TestObjects);
|
|
testobjects.AddRange(CurrentTestSetup.AddedGroups);
|
|
|
|
var serialNumbersProcessed = new Dictionary<string, bool>();
|
|
var hardwareChannelIdsProcessed = new Dictionary<string, bool>();
|
|
var channelLookup = new Dictionary<string, HardwareChannel>();
|
|
var usedISOCodesLookup = new Dictionary<string, bool>();
|
|
|
|
var availableAnalogChannels = 0;
|
|
var availableDigitalInputChannels = 0;
|
|
var availableDigitalOutputChannels = 0;
|
|
var availableSquibChannels = 0;
|
|
|
|
if (testobjects.Any())
|
|
{
|
|
//this is using the assumption that all testobjects now have the same list of hardware
|
|
foreach (var lastTo in testobjects)
|
|
{
|
|
if (bRefreshHardware) { lastTo.RefreshHardware(); }
|
|
foreach (var h in lastTo.Hardware)
|
|
{
|
|
if (null == h)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var hType = h.GetHardwareTypeEnum();
|
|
if (hType == HardwareTypes.SLICE_EthernetController
|
|
|| hType == HardwareTypes.SLICE_Distributor
|
|
|| hType == HardwareTypes.SLICE_LabEthernet
|
|
|| hType == HardwareTypes.SLICE6DB)
|
|
{
|
|
continue;
|
|
}
|
|
bHasHardware = true;
|
|
|
|
if (CurrentTestSetup.DoAutoArm)
|
|
{
|
|
switch (hType)
|
|
{
|
|
case HardwareTypes.TDAS_Pro_Rack:
|
|
case HardwareTypes.TDAS_LabRack:
|
|
case HardwareTypes.G5INDUMMY:
|
|
case HardwareTypes.G5VDS:
|
|
errors.Add("EditTestSetupPage_HardwareDoesNotSupportAutoArm");
|
|
break;
|
|
}
|
|
}
|
|
for (var i = 0; i < h.Channels.Length; i++)
|
|
{
|
|
var ch = h.Channels[i];
|
|
if (channelLookup.ContainsKey(ch.GetId())) continue;
|
|
channelLookup.Add(ch.GetId(), ch);
|
|
if (ch.IsSupportedBridgeType(Test.Module.Channel.Sensor.BridgeType.SQUIB))
|
|
{
|
|
availableSquibChannels++; i++; /*bypass next channel as it's also a squib*/
|
|
}
|
|
else if (ch.IsSupportedBridgeType(Test.Module.Channel.Sensor.BridgeType.DigitalInput))
|
|
{ availableDigitalInputChannels++; }
|
|
else if (ch.IsSupportedBridgeType(Test.Module.Channel.Sensor.BridgeType.TOMDigital))
|
|
{ availableDigitalOutputChannels++; }
|
|
else { availableAnalogChannels++; }
|
|
}
|
|
}
|
|
}
|
|
if (!bHasHardware && bWarnOnNotFullyAssigned)
|
|
{
|
|
errors.Add("EditTestSetupPage_NoHardwareInTest");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add("EditTestSetupPage_NoGroupsInTest");
|
|
}
|
|
|
|
foreach (var to in testobjects)
|
|
{
|
|
var isoTo = to.GetISOTestObject();
|
|
foreach (var ch in isoTo.AllChannels)
|
|
{
|
|
if (!ch.Required)
|
|
{
|
|
continue;
|
|
}
|
|
bHasChannels = true;
|
|
if (string.IsNullOrWhiteSpace(ch.SensorSerialNumber))
|
|
{
|
|
if (!errors.Contains("EditTestSetupPage_NoSensorOnChannel") &&
|
|
bWarnOnNotFullyAssigned)
|
|
{
|
|
errors.Add("EditTestSetupPage_NoSensorOnChannel");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (serialNumbersProcessed.ContainsKey(ch.SensorSerialNumber))
|
|
{
|
|
var err = string.Format("EditTestSetupPage_SerialNumberAppearsTwice",
|
|
ch.SensorSerialNumber);
|
|
if (!errors.Contains(err))
|
|
{
|
|
errors.Add(err);
|
|
}
|
|
return false;
|
|
}
|
|
serialNumbersProcessed.Add(ch.SensorSerialNumber, true);
|
|
var sd = CurrentTestSetup.GetSensor(ch.SensorSerialNumber, to.SerialNumber, ch.Name);
|
|
if (null == sd)
|
|
{
|
|
var err = string.Format("EditTestSetupPage_CouldNotFindSensor",
|
|
ch.SensorSerialNumber, ch.Name, to.DisplaySerialNumber);
|
|
if (!errors.Contains(err))
|
|
{
|
|
errors.Add(err);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (sd.IsSquib())
|
|
{
|
|
availableSquibChannels--;
|
|
if (sd.SquibFireDelayMS + sd.SquibFireDurationMS >
|
|
CurrentTestSetup.PostTriggerSeconds * 1000)
|
|
{
|
|
errors.Add(string.Format(
|
|
"TestTemplate_InsufficientPostTriggerLength",
|
|
sd.SerialNumber, ch.Name));
|
|
}
|
|
}
|
|
else if (sd.IsDigitalInput())
|
|
{
|
|
availableDigitalInputChannels--;
|
|
}
|
|
else if (sd.IsDigitalOutput())
|
|
{
|
|
availableDigitalOutputChannels--;
|
|
if (sd.DigitalOutputDelayMS + sd.DigitalOutputDurationMS >
|
|
CurrentTestSetup.PostTriggerSeconds * 1000)
|
|
{
|
|
errors.Add(string.Format(
|
|
"TestTemplate_InsufficientPostTriggerLength",
|
|
sd.SerialNumber, ch.Name));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
availableAnalogChannels--;
|
|
}
|
|
|
|
var sensor = SensorsCollection.SensorsList.GetSensorBySerialNumber(ch.SensorSerialNumber);
|
|
if (sensor != null)
|
|
{
|
|
var sensorDimension = sensor.PhysicalDimension;
|
|
if ((((App)Application.Current).IsoDb.GetPhysicalDimensionByIso(sensorDimension) !=
|
|
null) &&
|
|
(((App)Application.Current).IsoDb.GetPhysicalDimensionByIso(ch.Channel
|
|
.Physical_Dimension) != null) &&
|
|
(sd.IncompatibleSensorAssignment(sensorDimension, ch.Channel.Physical_Dimension)))
|
|
{
|
|
var err = string.Format(
|
|
"EditTestSetupPage_IncompatibleSensorNotSupported",
|
|
((App)Application.Current).IsoDb.GetPhysicalDimensionByIso(sensorDimension)
|
|
.Text_L1,
|
|
ch.SensorSerialNumber,
|
|
((App)Application.Current).IsoDb
|
|
.GetPhysicalDimensionByIso(ch.Channel.Physical_Dimension).Text_L1,
|
|
ch.Name, to.DisplaySerialNumber);
|
|
switch (SerializedSettings.IsoChannelSensorCompatibilityLevel)
|
|
{
|
|
case IsoChannelSensorCompatibilityLevels.DontAllow:
|
|
if (!errors.Contains(err))
|
|
{
|
|
errors.Add(err);
|
|
}
|
|
bValid = false;
|
|
break;
|
|
case IsoChannelSensorCompatibilityLevels.Warn:
|
|
if (!warnings.Contains(
|
|
"EditObjectSensorsControl_Warning" + ": " + err))
|
|
{
|
|
warnings.Add("EditObjectSensorsControl_Warning" +
|
|
": " + err);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!sd.IsDigitalOutput() &&
|
|
(CurrentTestSetup.GetISOTestSetupISOSupportLevel() ==
|
|
SerializedSettings.ISOSupportLevels.ISO_ONLY))
|
|
{
|
|
if (sd.MainLocation.Contains('?') ||
|
|
sd.FineLocation1.Contains('?') ||
|
|
sd.FineLocation2.Contains('?') ||
|
|
sd.FineLocation3.Contains('?') ||
|
|
sd.Direction.Contains('?') ||
|
|
sd.PhysicalDimension.Contains('?'))
|
|
{
|
|
var isoto = to.GetISOTestObject();
|
|
foreach (var isotoChannel in isoto.AllChannels)
|
|
{
|
|
//reapplying channel iso settings here with the exception of filter class, position, and test object
|
|
if (ch.Name != isotoChannel.Name) continue;
|
|
sd.MainLocation = ch.Channel.Trans_Main_Loc;
|
|
sd.FineLocation1 = ch.Channel.Fine_Loc_1;
|
|
sd.FineLocation2 = ch.Channel.Fine_Loc_2;
|
|
sd.FineLocation3 = ch.Channel.Fine_Loc_3;
|
|
sd.Direction = ch.Channel.Direction;
|
|
sd.PhysicalDimension = ch.Channel.Physical_Dimension;
|
|
}
|
|
}
|
|
if (usedISOCodesLookup.ContainsKey(sd.ISOCode))
|
|
{
|
|
var err = string.Format("TestTemplate_DuplicateISOCode",
|
|
sd.ISOCode);
|
|
if (!errors.Contains(err))
|
|
{
|
|
errors.Add(err);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
usedISOCodesLookup[sd.ISOCode] = true;
|
|
}
|
|
}
|
|
|
|
SensorCalibration sc = null;
|
|
var preferredExcitation = sd.SupportedExcitation[0];
|
|
sc = CurrentTestSetup.GetSensorCalibration(sd, preferredExcitation);
|
|
//sc = SensorCalibration.GetLatestCalibrationBySerialNumberAndExcitation(sd, preferredExcitation); //se);
|
|
if (null == sc)
|
|
{
|
|
bValid = false;
|
|
var err = string.Format("EditTestSEtupPage_MissingCalibration",
|
|
ch.Name, sd.SerialNumber);
|
|
if (!errors.Contains(err))
|
|
{
|
|
errors.Add(err);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var now = DateTime.Now;
|
|
var days = sc.CalibrationDate.AddDays(sd.CalInterval).Subtract(now).TotalDays;
|
|
if (SerializedSettings.TestSetupDefaultDontAllowOutOfCalSensors &&
|
|
((days < 0) || (days < Properties.Settings.Default.CalWarningPeriodDays)))
|
|
{
|
|
bValid = false;
|
|
var err = string.Format(
|
|
"OverdueSensors_CalibrationDateOverdueOrNear",
|
|
ch.Name, sd.SerialNumber);
|
|
if (!errors.Contains(err))
|
|
{
|
|
errors.Add(err);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(ch.HardwareId)) continue;
|
|
|
|
if (!channelLookup.ContainsKey(ch.HardwareId))
|
|
{
|
|
var err = string.Format("EditTestSetupPage_InvalidHardware",
|
|
ch.Name, to.DisplaySerialNumber);
|
|
if (!errors.Contains(err))
|
|
{
|
|
errors.Add(err);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (hardwareChannelIdsProcessed.ContainsKey(ch.HardwareId))
|
|
{
|
|
bValid = false;
|
|
var err = string.Format(
|
|
"EditTestSetupPage_HardwareAlreadyInUse", ch.Name,
|
|
to.DisplaySerialNumber);
|
|
if (!errors.Contains(err))
|
|
{
|
|
errors.Add(err);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hardwareChannelIdsProcessed.Add(ch.HardwareId, true);
|
|
var hch = channelLookup[ch.HardwareId];
|
|
if (sd.ByPassFilter &&
|
|
((hch.Hardware.GetHardwareTypeEnum() != HardwareTypes.TDAS_Pro_Rack) &&
|
|
(hch.Hardware.GetHardwareTypeEnum() != HardwareTypes.TDAS_LabRack)))
|
|
{
|
|
var err = string.Format(
|
|
"EditTestSetupPage_BypassAAFilterNotSupported",
|
|
ch.Name, to.DisplaySerialNumber);
|
|
if (!errors.Contains(err))
|
|
{
|
|
errors.Add(err);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (hch.IsSupportedBridgeType(sd.Bridge)) continue;
|
|
var err = string.Format(
|
|
"EditTestSetupPage_BridgeNotSupported",
|
|
sd.Bridge.ToString(), ch.Name, to.DisplaySerialNumber);
|
|
if (!errors.Contains(err))
|
|
{
|
|
errors.Add(err);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!bHasChannels) { errors.Add("EditTestSetupPage_NoChannelsInTest"); }
|
|
if (availableAnalogChannels < 0 && !CurrentTestSetup.AllowMissingSensors && bWarnOnNotFullyAssigned)
|
|
{
|
|
if (!errors.Contains("EditTestSetupPage_NeedMoreAnalogChannels") && !errors.Contains("EditTestSetupPage_NoHardwareInTest"))
|
|
{ errors.Add("EditTestSetupPage_NeedMoreAnalogChannels"); }
|
|
}
|
|
if (availableDigitalInputChannels < 0 && !CurrentTestSetup.AllowMissingSensors && bWarnOnNotFullyAssigned)
|
|
{
|
|
if (!errors.Contains("EditTestSetupPage_NeedMoreDigitalInputChannels") && !errors.Contains("EditTestSetupPage_NoHardwareInTest"))
|
|
{ errors.Add("EditTestSetupPage_NeedMoreDigitalInputChannels"); }
|
|
}
|
|
if (availableDigitalOutputChannels < 0 && !CurrentTestSetup.AllowMissingSensors && bWarnOnNotFullyAssigned)
|
|
{
|
|
if (!errors.Contains("EditTestSetupPage_NeedMoreDigitalOutputChannels") && !errors.Contains("EditTestSetupPage_NoHardwareInTest"))
|
|
{ errors.Add("EditTestSetupPage_NeedMoreDigitalOutputChannels"); }
|
|
}
|
|
if (availableSquibChannels < 0 && !CurrentTestSetup.AllowMissingSensors && bWarnOnNotFullyAssigned)
|
|
{
|
|
if (!errors.Contains("EditTestSetupPage_NeedMoreSquibChannels") && !errors.Contains("EditTestSetupPage_NoHardwareInTest"))
|
|
{ errors.Add("EditTestSetupPage_NeedMoreSquibChannels"); }
|
|
}
|
|
|
|
if (!ValidateTestSetupName(ref errors, CurrentTestSetup)) { bValid = false; }
|
|
ValidateStorageSpace(ref errors, CurrentTestSetup);//not fatal
|
|
ValidateUploadFolder(ref errors, CurrentTestSetup);//not fatal
|
|
ValidateAutoArmAllowability(ref errors, CurrentTestSetup);
|
|
|
|
return bValid;
|
|
}
|
|
public static bool ValidateUploadFolder(ref List<string> errors, TestTemplate currentTest)
|
|
{
|
|
//if we have a export ini file, we still allow a blank upload folder
|
|
if (!currentTest.UploadData || !string.IsNullOrWhiteSpace(currentTest.UploadFolder)) return true;
|
|
if (SerializedSettings.ExportINIFile.Length > 0) { return true; }
|
|
errors.Add("TestTestTemplate_InvalidUploadPath");
|
|
return false;
|
|
}
|
|
|
|
private static bool ValidateAutoArmAllowability(ref List<string> errors, TestTemplate currentTest)
|
|
{
|
|
if (!currentTest.DoAutoArm || Properties.Settings.Default.AllowAutoArm) return true;
|
|
errors.Add("EditTestSetupInfo_AutoArmNotAllowed");
|
|
return false;
|
|
}
|
|
|
|
public static bool ValidateStorageSpace(ref List<string> errors, TestTemplate currentTest)
|
|
{
|
|
var bStorageSpaceValid = true;
|
|
var preTriggerSeconds = currentTest.PreTriggerSeconds;
|
|
var postTriggerSeconds = currentTest.PostTriggerSeconds;
|
|
var sampleRate = currentTest.SamplesPerSecond;
|
|
var secondsToRecord = preTriggerSeconds + postTriggerSeconds;
|
|
var sampleClocksToRecord = (ulong)(secondsToRecord * sampleRate + 1);
|
|
|
|
var das = new List<DASHardware>();
|
|
foreach (var to in currentTest.TestObjects)
|
|
{
|
|
foreach (var h in to.Hardware)
|
|
{
|
|
if (!das.Contains(h)) { das.Add(h); }
|
|
}
|
|
}
|
|
foreach (var to in currentTest.AddedGroups)
|
|
{
|
|
foreach (var h in to.Hardware)
|
|
{
|
|
if (!das.Contains(h)) { das.Add(h); }
|
|
}
|
|
}
|
|
foreach (var d in das)
|
|
{
|
|
double maxSampleClockTicks = d.GetMaxMemoryLong();
|
|
if (!(maxSampleClockTicks > 0)) continue;
|
|
if (!(sampleClocksToRecord > maxSampleClockTicks)) continue;
|
|
bStorageSpaceValid = false;
|
|
errors.Add(string.Format("TestTemplate_InsufficientMemory", d.SerialNumber, maxSampleClockTicks));
|
|
}
|
|
return bStorageSpaceValid;
|
|
}
|
|
private void _roi_ListChanged(object sender, ListChangedEventArgs e)
|
|
{
|
|
OnPropertyChanged(TestTemplateTags.RegionsOfInterest.ToString());
|
|
}
|
|
|
|
public void AddTestGraph(TestGraph tg)
|
|
{
|
|
_testGraphs.Add(tg);
|
|
}
|
|
/// <summary>
|
|
/// holds test settings that don't have individual db columns
|
|
/// </summary>
|
|
//private ISO.TestSettingDictionary _settings = CreateSettingsDictionary();
|
|
private TestSettingDictionary _settings;
|
|
/// <summary>
|
|
/// loads values from a serialized string into the settings table
|
|
/// </summary>
|
|
/// <param name="s"></param>
|
|
public void LoadSettings(string s)
|
|
{
|
|
_settings.LoadSettings(s);
|
|
}
|
|
/// <summary>
|
|
/// returns the iso support level of object (as determined by it's groups, or the current application support level)
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public SerializedSettings.ISOSupportLevels GetISOTestSetupISOSupportLevel()
|
|
{
|
|
var nonIsoTestObject = GetNonISOTestObject();
|
|
foreach (var to in TestObjects)
|
|
{
|
|
if (to == nonIsoTestObject)
|
|
{
|
|
//if it only has digital outputs, it could be either a non iso or an iso group, so ignore it
|
|
var isoto = to.GetISOTestObject();
|
|
if (isoto.AllChannels.Where(ch => ch.Required && !string.IsNullOrWhiteSpace(ch.SensorSerialNumber)).Any(ch => !SensorData.IsTestSpecificDigitalOutSN(ch.SensorSerialNumber)))
|
|
{
|
|
return SerializedSettings.ISOSupportLevels.NO_ISO;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return to.GetObjectISOLevel();
|
|
}
|
|
}
|
|
if (AddedGroups.Any())
|
|
{
|
|
return SerializedSettings.ISOSupportLevels.ISO_ONLY;
|
|
}
|
|
return SerializedSettings.ISOSupportLevel;
|
|
}
|
|
private TestTestObject CreateNonISOGroupIfNecessary()
|
|
{
|
|
foreach (var group in _testObjects)
|
|
{
|
|
if (group.SerialNumberOrOriginalSerialNumber == NON_ISO_INTERNAL_GROUP_NAME)
|
|
{
|
|
return group;
|
|
}
|
|
}
|
|
//if you got here it wasn't found
|
|
var guid = Guid.NewGuid();
|
|
var template = new TestObjectTemplate();
|
|
|
|
var isoTestObjectTemplate = template.ToISOTestObjectTemplate();
|
|
isoTestObjectTemplate.Embedded = true;
|
|
isoTestObjectTemplate.TemplateName = guid.ToString();
|
|
if (Application.Current is App app)
|
|
{
|
|
var db = app.IsoDb;
|
|
template = new TestObjectTemplate(isoTestObjectTemplate, ref db);
|
|
}
|
|
|
|
var to = new TestObject { Template = template };
|
|
to.GetISOTestObject().Embedded = true;
|
|
to.GetISOTestObject().OriginalSerialNumber = NON_ISO_INTERNAL_GROUP_NAME;
|
|
to.SerialNumber = guid.ToString();
|
|
|
|
var g = new TestTestObject(to);
|
|
_testObjects.Add(g);
|
|
TestObjectsAndAddedGroupsList.Add(g);
|
|
return g;
|
|
}
|
|
|
|
public TestTestObject GetNonISOTestObject()
|
|
{
|
|
return CreateNonISOGroupIfNecessary();
|
|
}
|
|
|
|
public void AddTestObject(TestObject to, int excitationWarmupMs, double targetSampleRate, string testobject, string position)
|
|
{
|
|
if (null != to)
|
|
{
|
|
var tto = new TestTestObject(to)
|
|
{
|
|
ExcitationWarmupTimeMS = excitationWarmupMs,
|
|
TargetSampleRate = targetSampleRate
|
|
};
|
|
tto.SetPosition(position);
|
|
tto.SetTestObject(testobject);
|
|
|
|
//if this is the NON ISO group (which is created by default), the replace the original NONE group ...
|
|
if (tto.SerialNumberOrOriginalSerialNumber == NON_ISO_INTERNAL_GROUP_NAME)
|
|
{
|
|
var index = -1;
|
|
for (var i = 0; i < TestObjectsAndAddedGroupsList.Count; i++)
|
|
{
|
|
if (TestObjectsAndAddedGroupsList[i].SerialNumberOrOriginalSerialNumber != NON_ISO_INTERNAL_GROUP_NAME) continue;
|
|
index = i;
|
|
break;
|
|
}
|
|
if (index >= 0)
|
|
{
|
|
TestObjectsAndAddedGroupsList.RemoveAt(index);
|
|
}
|
|
|
|
index = -1;
|
|
for (var i = 0; i < _testObjects.Count; i++)
|
|
{
|
|
if (_testObjects[i].SerialNumberOrOriginalSerialNumber != NON_ISO_INTERNAL_GROUP_NAME) continue;
|
|
index = i;
|
|
break;
|
|
}
|
|
if (index >= 0)
|
|
{
|
|
_testObjects.RemoveAt(index);
|
|
}
|
|
}
|
|
|
|
_testObjects.Add(tto);
|
|
TestObjectsAndAddedGroupsList.Add(tto);
|
|
OnPropertyChanged(TestTemplateTags.TestObjects.ToString());
|
|
OnPropertyChanged(TestTemplateTags.DefaultNumberRealtimeGraphs.ToString());
|
|
}
|
|
}
|
|
|
|
public void AddTestObject(string serialNumber, int excitationWarmupMs, double targetSampleRate, string testobject, string position)
|
|
{
|
|
var to = TestObjectList.TestObjectsList.GetTestObject(serialNumber);
|
|
AddTestObject(to, excitationWarmupMs, targetSampleRate, testobject, position);
|
|
OnPropertyChanged(TestTemplateTags.DefaultNumberRealtimeGraphs.ToString());
|
|
}
|
|
|
|
public void AddAddedGroup(TestObject to, string testobject, string position)
|
|
{
|
|
if (null == to) return;
|
|
var tto = new TestTestObject(to);
|
|
tto.SetPosition(position);
|
|
tto.SetTestObject(testobject);
|
|
tto.SerialNumberConverted = tto.SerialNumber.Remove(0, Name.Length + 1);
|
|
tto.TestSetupName = Name;
|
|
_addedGroups.Add(tto);
|
|
TestObjectsAndAddedGroupsList.Add(tto);
|
|
OnPropertyChanged(TestTemplateTags.DefaultNumberRealtimeGraphs.ToString());
|
|
}
|
|
public void AddAddedGroup(string serialNumber, string testobject, string position)
|
|
{
|
|
var to = TestObjectList.AddedGroupsList.GetAddedGroup(serialNumber);
|
|
AddAddedGroup(to, testobject, position);
|
|
OnPropertyChanged(TestTemplateTags.DefaultNumberRealtimeGraphs.ToString());
|
|
}
|
|
|
|
public int GetNumberOfRealtimeSupportedChannels()
|
|
{
|
|
var count = 0;
|
|
foreach (var to in TestObjects)
|
|
{
|
|
var isoto = to.GetISOTestObject();
|
|
count += isoto.AllChannels.Where(ch => ch.Required && !string.IsNullOrWhiteSpace(ch.SensorSerialNumber)).Select(ch => GetSensor(ch.SensorSerialNumber, to.SerialNumber, ch.Name)).Where(sd => null != sd).Count(sd => !sd.IsDigitalInput() && !sd.IsDigitalOutput() && !sd.IsSquib());
|
|
}
|
|
foreach (var to in AddedGroups)
|
|
{
|
|
var isoto = to.GetISOTestObject();
|
|
count += isoto.AllChannels.Where(ch => ch.Required && !string.IsNullOrWhiteSpace(ch.SensorSerialNumber)).Select(ch => GetSensor(ch.SensorSerialNumber, to.SerialNumber, ch.Name)).Where(sd => null != sd).Count(sd => !sd.IsDigitalInput() && !sd.IsDigitalOutput() && !sd.IsSquib());
|
|
}
|
|
if (0 == count) { count = MAX_REALTIME_CHANNELS; }
|
|
return count;
|
|
}
|
|
public void AddCalculatedChannel(CalculatedValueClass ch)
|
|
{
|
|
CalculatedChannels.Add(ch);
|
|
}
|
|
private readonly Dictionary<char, TestObjectMetaData> _metaDataLookup = new Dictionary<char, TestObjectMetaData>();
|
|
private TestSetupMetaData _testSetupMeta = new TestSetupMetaData(Properties.Settings.Default.RequireXCrashCompatibilityForISOExports);
|
|
public void SetTestSetupMetaData(TestSetupMetaData meta)
|
|
{
|
|
_testSetupMeta = meta;
|
|
}
|
|
public void SetMetaData(char testobject, TestObjectMetaData meta)
|
|
{
|
|
_metaDataLookup[testobject] = meta;
|
|
}
|
|
}
|
|
}
|