1758 lines
86 KiB
C#
1758 lines
86 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using DataPROWin7.Common;
|
|
using DTS.Common.Classes.Hardware;
|
|
using DTS.Common.Interface.DASFactory;
|
|
using DTS.Common.Utilities.Logging;
|
|
using DTS.DASLib.Service;
|
|
using DTS.Common.SharedResource.Strings;
|
|
using System.Threading;
|
|
using DataPROWin7.DataModel.Classes.Hardware;
|
|
using DTS.Common.Interface.Channels;
|
|
using DTS.Common.Interface.Groups.GroupList;
|
|
using DTS.Common.Interface.DASFactory.Config;
|
|
using DTS.Common.Enums.DASFactory;
|
|
using DTS.Common.Enums;
|
|
using DTS.Slice.Users.UserSettings;
|
|
using DTS.Common.Enums.Sensors;
|
|
using DTS.Common.Classes.Groups;
|
|
using DTS.SensorDB;
|
|
using DTS.Common.Classes.Sensors;
|
|
using DTS.Common.Constant.DASSpecific;
|
|
using DTS.Common.Enums.Hardware;
|
|
using DTS.Common.Classes.Groups.ChannelSettings;
|
|
using DTS.Common.DataModel.Common;
|
|
using DTS.Common.Enums.TSRAIRGo;
|
|
using DTS.Common.DataModel.Classes.TSRAIRGo;
|
|
using DTS.Common.Interface.Sensors.AnalogDiagnostics;
|
|
using DTS.Common;
|
|
|
|
namespace DataPROWin7.DataModel.Classes
|
|
{
|
|
public class LevelTriggerCapableChannel
|
|
{
|
|
public HardwareChannel HardwareChannel { get; }
|
|
|
|
public string DASOrModuleSerialNumber
|
|
{
|
|
get
|
|
{
|
|
switch (HardwareChannel.Hardware.DASTypeEnum)
|
|
{
|
|
case HardwareTypes.TDAS_Pro_Rack:
|
|
case HardwareTypes.TDAS_LabRack:
|
|
//need module Serial Number
|
|
return HardwareChannel.ModuleSerialNumber;
|
|
default:
|
|
return HardwareChannel.Hardware.SerialNumber;
|
|
}
|
|
}
|
|
}
|
|
private readonly SensorData _sd;
|
|
private readonly IGroupChannel _groupChannel;
|
|
private DTS.Common.ISO.LevelTriggerChannel _testSetupLevelTrigger = null;
|
|
public LevelTriggerCapableChannel(HardwareChannel hwch,
|
|
SensorData sd,
|
|
SensorCalibration sc,
|
|
IGroup group,
|
|
IGroupChannel groupChannel)
|
|
{
|
|
HardwareChannel = hwch;
|
|
_sd = sd;
|
|
sd.Calibration = sc;
|
|
_groupChannel = groupChannel;
|
|
}
|
|
public double LessThanValue { get; private set; } = 0D;
|
|
public double GreaterThanValue { get; private set; } = 0D;
|
|
private bool _isLessThanThresholdEnabled = true;
|
|
public bool IsLessThanThresholdEnabled
|
|
{
|
|
get => _isLessThanThresholdEnabled;
|
|
set
|
|
{
|
|
_isLessThanThresholdEnabled = value;
|
|
if (null == _testSetupLevelTrigger) return;
|
|
_testSetupLevelTrigger.LessThanEnabled = value;
|
|
}
|
|
}
|
|
private bool _isGreaterThanThresholdEnabled = false;
|
|
public bool IsGreatherThanThresholdEnabled
|
|
{
|
|
get => _isGreaterThanThresholdEnabled;
|
|
set
|
|
{
|
|
_isGreaterThanThresholdEnabled = value;
|
|
if (null == _testSetupLevelTrigger) return;
|
|
_testSetupLevelTrigger.GreaterThanEnabled = value;
|
|
}
|
|
}
|
|
public double InsideUpperBoundValue { get; private set; } = 0D;
|
|
public double InsideLowerBoundValue { get; private set; } = 0D;
|
|
public double OutsideUpperBoundValue { get; private set; } = 0D;
|
|
public double OutsideLowerBoundValue { get; private set; } = 0D;
|
|
private bool _bTriggerBetweenBounds = false;
|
|
private bool _bTriggerOutsideBounds = false;
|
|
public DTS.Common.ISO.LevelTriggerChannel ToISOLevelTriggerChannel()
|
|
{
|
|
var lt = new DTS.Common.ISO.LevelTriggerChannel(
|
|
_groupChannel.Id.ToString(),
|
|
HardwareChannel.GetId(),
|
|
_sd.SerialNumber,
|
|
!SensorConstants.IsTSRAirHighGChannel(HardwareChannel.ModuleSerialNumber) && _isGreaterThanThresholdEnabled,
|
|
GreaterThanValue,
|
|
!SensorConstants.IsTSRAirHighGChannel(HardwareChannel.ModuleSerialNumber) && _isLessThanThresholdEnabled,
|
|
LessThanValue,
|
|
InsideLowerBoundValue,
|
|
InsideUpperBoundValue,
|
|
OutsideLowerBoundValue,
|
|
OutsideUpperBoundValue,
|
|
SensorConstants.IsTSRAirHighGChannel(HardwareChannel.ModuleSerialNumber) || _bTriggerOutsideBounds,
|
|
_bTriggerBetweenBounds);
|
|
lt.GroupChannel = _groupChannel;
|
|
|
|
return lt;
|
|
}
|
|
public void FromISOLevelTriggerChannel(DTS.Common.ISO.LevelTriggerChannel channel)
|
|
{
|
|
LessThanValue = channel.LessThanThresholdEU;
|
|
GreaterThanValue = channel.GreaterThanThresholdEU;
|
|
_isGreaterThanThresholdEnabled = !SensorConstants.IsTSRAirHighGChannel(HardwareChannel.ModuleSerialNumber) && channel.GreaterThanEnabled;
|
|
_isLessThanThresholdEnabled = !SensorConstants.IsTSRAirHighGChannel(HardwareChannel.ModuleSerialNumber) && channel.LessThanEnabled;
|
|
_testSetupLevelTrigger = channel;
|
|
InsideUpperBoundValue = channel.InsideUpperLevelEU;
|
|
InsideLowerBoundValue = channel.InsideLowerLevelEU;
|
|
OutsideUpperBoundValue = channel.OutsideUpperLevelEU;
|
|
OutsideLowerBoundValue = channel.OutsideLowerLevelEU;
|
|
_bTriggerBetweenBounds = channel.TriggerBetweenBounds;
|
|
_bTriggerOutsideBounds = SensorConstants.IsTSRAirHighGChannel(HardwareChannel.ModuleSerialNumber) || channel.TriggerOutsideBounds;
|
|
}
|
|
}
|
|
public class Diagnostics
|
|
{
|
|
private readonly Configuration configuration = new Configuration();
|
|
public Diagnostics()
|
|
{
|
|
}
|
|
public bool Reset(DataModel.TestTemplate currentTest,
|
|
List<IDASCommunication> dasList,
|
|
Dictionary<string, int> dasSampleRateList,
|
|
DASHardware[] hardware,
|
|
StatusHelpers.SetProgressValueDelegate setProgressFunction,
|
|
DTS.Slice.Users.User currentUser)
|
|
{
|
|
DASHardware.MarkAllDASUnclean(dasList);
|
|
|
|
ConnectIfNeededPartial(dasList);
|
|
if (DataNeverDownloaded(dasList))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
public void ContinueReset(DataModel.TestTemplate currentTest,
|
|
List<IDASCommunication> dasList,
|
|
Dictionary<string, int> dasSampleRateList,
|
|
DASHardware[] hardware,
|
|
StatusHelpers.SetProgressValueDelegate setProgressFunction,
|
|
DTS.Slice.Users.User currentUser)
|
|
{
|
|
UpdateConfigAndPrepareForDiagnostics(currentTest, dasList, dasSampleRateList, hardware, setProgressFunction, currentUser);
|
|
RunDiagnostics(dasList, hardware);
|
|
}
|
|
private void ConnectIfNeededPartial(List<IDASCommunication> dasList)
|
|
{
|
|
var maxQueryConfigTimeout = DetermineMaxQueryConfigTime();
|
|
StartAutoResolutionPartial(dasList, maxQueryConfigTimeout);
|
|
}
|
|
private const int TSRAIRGO_QUERYCONFIG_TIMEOUT = 150000;
|
|
private int DetermineMaxQueryConfigTime()
|
|
{
|
|
if (RunTestVariables.IsTSRAIRGo)
|
|
{
|
|
return TSRAIRGO_QUERYCONFIG_TIMEOUT;
|
|
}
|
|
int maxQueryConfigTimeout = 0;
|
|
|
|
maxQueryConfigTimeout = Math.Max(maxQueryConfigTimeout,
|
|
SerializedSettings.ResolveChannels_SLICE_QueryConfigTimeoutSec * 1000);
|
|
|
|
return maxQueryConfigTimeout;
|
|
}
|
|
private void StartAutoResolutionPartial(List<IDASCommunication> dasList, int maxQueryConfigTimeout)
|
|
{
|
|
BuildLookups(dasList, maxQueryConfigTimeout);
|
|
}
|
|
private void BuildLookups(List<IDASCommunication> dasList, int maxQueryConfigTimeout)
|
|
{
|
|
QueryConfigurationPartial(dasList, maxQueryConfigTimeout);
|
|
}
|
|
private void QueryConfigurationPartial(List<IDASCommunication> das, int maxQueryConfigTimeout)
|
|
{
|
|
try
|
|
{
|
|
var doneEvent = new ManualResetEvent(false);
|
|
using (var cs = new ConfigurationService())
|
|
{
|
|
cs.ServiceCallbackError += CS_ServiceCallbackError;
|
|
cs.GetConfiguration(das, true, delegate (ServiceBase.CallbackData data)
|
|
{
|
|
switch (data.Status)
|
|
{
|
|
case ServiceBase.CallbackData.CallbackStatus.AllFinished:
|
|
doneEvent.Set();
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.Failure:
|
|
doneEvent.Set();
|
|
break;
|
|
}
|
|
}, das);
|
|
|
|
|
|
var totalTimeWaited = 0;
|
|
while (totalTimeWaited < maxQueryConfigTimeout && !doneEvent.WaitOne(100, false))
|
|
{
|
|
totalTimeWaited += 100;
|
|
}
|
|
|
|
if (totalTimeWaited >= maxQueryConfigTimeout)
|
|
{
|
|
cs.Cancel();
|
|
APILogger.Log("timeout");
|
|
throw new TimeoutException();
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log("QueryConfig failed: " + ex.Message);
|
|
throw;
|
|
}
|
|
}
|
|
private static void CS_ServiceCallbackError(object sender, string msg, Exception caught)
|
|
{
|
|
APILogger.Log("error querying configuration", msg);
|
|
}
|
|
private void UpdateConfigAndPrepareForDiagnostics(DataModel.TestTemplate currentTest,
|
|
List<IDASCommunication> ldas,
|
|
Dictionary<string, int> dasSampleRateList, DASHardware[] hardware,
|
|
StatusHelpers.SetProgressValueDelegate setProgressFunction,
|
|
DTS.Slice.Users.User currentUser)
|
|
{
|
|
try
|
|
{
|
|
//Store the entire Test Setup .xml in the SETUP folder
|
|
ExportCurrentTestSetup(currentTest, currentUser);
|
|
|
|
//Also, store a portion (the DAS and Fields) of the Test Setup on the DAS (in the TestSetup filestore).
|
|
var testSetupXML = ExportCurrentTestSetupFields(currentTest);
|
|
if (testSetupXML != null)
|
|
{
|
|
StoreTestSetup(ldas, testSetupXML);
|
|
}
|
|
}
|
|
catch (Exception ex) { APILogger.Log(ex); }
|
|
|
|
try
|
|
{
|
|
|
|
var channelLookup = new Dictionary<string, HardwareChannel>();
|
|
var channelsForDas = new Dictionary<int, List<HardwareChannel>>();
|
|
|
|
foreach (var group in currentTest.Groups)
|
|
{
|
|
AddChannelsForDAS(channelsForDas, channelLookup, hardware);
|
|
}
|
|
|
|
var dasLookup = new Dictionary<string, DASHardware>();
|
|
foreach (var h in hardware) { dasLookup[h.SerialNumber] = h; }
|
|
foreach (var idas in ldas)
|
|
{
|
|
DASHardware h = null;
|
|
if (dasLookup.ContainsKey(idas.SerialNumber))
|
|
{
|
|
h = dasLookup[idas.SerialNumber];
|
|
}
|
|
|
|
if (null == h)
|
|
{
|
|
h = DASHardwareList.GetList()
|
|
.GetHardware(idas.SerialNumber, ((ICommunication)idas).ConnectString);
|
|
}
|
|
if (!channelsForDas.ContainsKey(h.DASId)) continue;
|
|
foreach (var ch in channelsForDas[h.DASId])
|
|
{
|
|
ch.DiagnosticStatus = DiagnosticStatus.Untested;
|
|
}
|
|
}
|
|
UpdateConfig(currentTest, ldas, hardware, setProgressFunction, currentUser);
|
|
|
|
PrepareForDiagnostics(ldas, dasSampleRateList);
|
|
}
|
|
catch (Exception ex) { APILogger.Log(ex); }
|
|
}
|
|
private static void AddChannelsForDAS(Dictionary<int, List<HardwareChannel>> channelsForDas, Dictionary<string, HardwareChannel> channelLookup, DASHardware[] hardwares)
|
|
{
|
|
foreach (var h in hardwares)
|
|
{
|
|
if (!channelsForDas.ContainsKey(h.DASId))
|
|
{
|
|
channelsForDas.Add(h.DASId, new List<HardwareChannel>());
|
|
}
|
|
foreach (var ch in h.Channels)
|
|
{
|
|
if (null == ch.Sensor) continue;
|
|
if (ch.IsClock) continue;
|
|
var key = $"{h.DASId}_{ch.ChannelNumber}";
|
|
if (!channelLookup.ContainsKey(key))
|
|
{
|
|
channelLookup[key] = ch;
|
|
channelsForDas[h.DASId].Add(ch);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private void ExportCurrentTestSetup(DataModel.TestTemplate currentTest,
|
|
DTS.Slice.Users.User currentUser)
|
|
{
|
|
var path = System.IO.Path.Combine(currentTest.TestDirectory.Trim(), "SETUP");
|
|
try
|
|
{
|
|
if (!System.IO.Directory.Exists(path))
|
|
{
|
|
System.IO.Directory.CreateDirectory(path);
|
|
}
|
|
var filename = System.IO.Path.Combine(path, string.IsNullOrEmpty(currentTest.TestId) ? "TestSetup.xml" : $"{currentTest.TestId}.xml");
|
|
if (System.IO.File.Exists(filename))
|
|
{
|
|
System.IO.File.Delete(filename);
|
|
}
|
|
|
|
var includedTests = new Dictionary<string, DataModel.TestTemplate>();
|
|
var includedGroups = new Dictionary<string, IGroup>();
|
|
var includedDAS = new Dictionary<string, DASHardware>();
|
|
var includedSensors = new Dictionary<string, SensorData>();
|
|
var sensorsAlreadyAdded = new HashSet<int>();
|
|
var includedSensorModels = new Dictionary<string, SensorModel>();
|
|
var includedCalibration = new Dictionary<string, SensorCalibration[]>();
|
|
var includedCustomerDetails = new Dictionary<string, DTS.Common.ISO.CustomerDetails>();
|
|
var includedTestEngineerDetails = new Dictionary<string, DTS.Common.ISO.TestEngineerDetails>();
|
|
var includedLabDetails = new Dictionary<string, DTS.Common.ISO.LabratoryDetails>();
|
|
var includedUsers = new Dictionary<string, DTS.Slice.Users.User>();
|
|
var includedGlobalSettings = new Dictionary<string, string>();
|
|
|
|
ExportTestSetup.PrepareForExport(currentTest, includedTests,
|
|
includedGroups,
|
|
includedDAS,
|
|
includedSensors,
|
|
sensorsAlreadyAdded,
|
|
includedSensorModels,
|
|
includedCalibration,
|
|
includedCustomerDetails,
|
|
includedTestEngineerDetails,
|
|
includedLabDetails,
|
|
true,
|
|
false
|
|
);
|
|
|
|
ExportTestSetup.ExportToFile(includedTests,
|
|
includedGroups,
|
|
includedDAS,
|
|
includedSensors,
|
|
includedSensorModels,
|
|
includedCalibration,
|
|
includedCustomerDetails,
|
|
includedTestEngineerDetails,
|
|
includedLabDetails,
|
|
includedUsers,
|
|
includedGlobalSettings,
|
|
filename,
|
|
string.Empty
|
|
);
|
|
|
|
//Store as the latest Test Setup
|
|
Defaults.SetUserSetting(currentUser.Id, PropertyEnums.PropertyIds.LastRunTestSetup, filename);
|
|
currentTest.SetupFile = filename;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log(ex);
|
|
}
|
|
}
|
|
private string ExportCurrentTestSetupFields(DataModel.TestTemplate currentTest)
|
|
{
|
|
try
|
|
{
|
|
var includedTests = new Dictionary<string, DataModel.TestTemplate>();
|
|
var includedDAS = new Dictionary<string, DASHardware>();
|
|
|
|
//Remove the Test Channels group
|
|
var tempCurrentTest = new DataModel.TestTemplate(currentTest);
|
|
tempCurrentTest.Groups.Clear();
|
|
|
|
ExportTestSetup.PrepareForExportFields(tempCurrentTest, includedTests, includedDAS);
|
|
|
|
return ExportTestSetup.ExportToFileFields(includedTests,
|
|
includedDAS,
|
|
string.Empty
|
|
);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log(ex);
|
|
return null;
|
|
}
|
|
}
|
|
private void StoreTestSetup(List<IDASCommunication> dasList, string testSetupXML)
|
|
{
|
|
using (var configService = new ConfigurationService())
|
|
{
|
|
var mreLocal = new ManualResetEvent(false);
|
|
configService.StoreTestSetupXML(dasList, delegate (ServiceBase.CallbackData cbd)
|
|
{
|
|
switch (cbd.Status)
|
|
{
|
|
case ServiceBase.CallbackData.CallbackStatus.AllFinished:
|
|
mreLocal.Set();
|
|
break;
|
|
}
|
|
}, dasList, testSetupXML);
|
|
mreLocal.WaitOne();
|
|
}
|
|
}
|
|
private void UpdateConfig(DataModel.TestTemplate currentTest,
|
|
List<IDASCommunication> ldas,
|
|
DASHardware[] hardware,
|
|
StatusHelpers.SetProgressValueDelegate setProgressFunction,
|
|
DTS.Slice.Users.User currentUser)
|
|
{
|
|
SortOutConfig(currentTest, ldas, true, hardware, currentUser);
|
|
|
|
var exceptionThrown = false;
|
|
|
|
//Check the AAFilter rate
|
|
var OkToProceed = true;
|
|
try
|
|
{
|
|
OkToProceed = CheckAAFilterRate(ldas);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log("UpdateConfig - failed to checkaafilterrate", ex);
|
|
exceptionThrown = true;
|
|
}
|
|
if (exceptionThrown || !OkToProceed)
|
|
{
|
|
return; //we have failed
|
|
}
|
|
|
|
foreach (var das in ldas)
|
|
{
|
|
setProgressFunction(das, 0D, TSRAIRGoStatus.StatusTypes.UPDATING_DAS_CONFIG);
|
|
}
|
|
configuration.SetConfig(currentTest, ldas, true, setProgressFunction);
|
|
}
|
|
public delegate void ReportErrorsDelegate(List<string> errors);
|
|
/// <summary>
|
|
/// Sorts out analog channels in the test setup versus the AnalogInputDASchannel object and sets properties on the daschannel
|
|
/// This function was in multiple places with near identical code, I brought it together to one place and abstracted it out of the
|
|
/// huge SortOutConfig function
|
|
/// </summary>
|
|
/// <param name="dasChannel"></param>
|
|
/// <param name="currentTest"></param>
|
|
/// <param name="harwarechanneltoAbsoluteDisplayOrder"></param>
|
|
/// <param name="key"></param>
|
|
/// <param name="moduleChannelNumber"></param>
|
|
/// <param name="channelLookup"></param>
|
|
/// <param name="das"></param>
|
|
/// <param name="h"></param>
|
|
/// <param name="allHardware"></param>
|
|
/// <param name="mod"></param>
|
|
/// <param name="testObjectChannelIdToGroup"></param>
|
|
/// <param name="ReportErrors"></param>
|
|
/// <returns></returns>
|
|
public static bool SortOutConfigAnalog(AnalogInputDASChannel dasChannel,
|
|
string key, int moduleChannelNumber,
|
|
IDASCommunication das, DASHardware h,
|
|
IDASModule mod, SortOutConfigParams soParams, ReportErrorsDelegate ReportErrors = null)
|
|
{
|
|
if (null == dasChannel) { return false; }
|
|
|
|
APILogger.DebugLog($"SortOutConfig hc={dasChannel?.HardwareChannelName ?? "N/A"}, key={key}, das={das?.SerialNumber??"N/A"}, h={h?.SerialNumber??"N/A"}");
|
|
if (soParams.ContainsHardwareChannelDisplayOrder(key))
|
|
{
|
|
dasChannel.AbsoluteDisplayOrder = soParams.GetHardwareChannelAbsoluteDisplayOrder(key);
|
|
}
|
|
dasChannel.ModuleChannelNumber = moduleChannelNumber;
|
|
|
|
var hc = soParams.GetHardwareChannel(key);
|
|
var sensor = hc.Sensor;
|
|
SensorCalibration sc = null;
|
|
|
|
|
|
//SensorID is the EID of the sensor, and is saved in the config so
|
|
//that if the associated DAS is connected to a different computer,
|
|
//this test-used EID can be found. This is helpful, for example,
|
|
//when the Quick build button is used to create a new Test Setup and
|
|
//the same sensor is connected to a different DAS. Prior to this
|
|
//saving in the config, only the "live" EID was known when reading the config.
|
|
dasChannel.SensorID = sensor.EID;
|
|
dasChannel.SetupEID = sensor.EID;
|
|
if ( null != dasChannel.IDs && dasChannel.IDs.Length > 0 && null != dasChannel.IDs[0] && dasChannel.IDs[0].IsValid())
|
|
{
|
|
dasChannel.DataCollectionEID = dasChannel.IDs[0].ID;
|
|
}
|
|
|
|
|
|
foreach (var se in sensor.SupportedExcitation)
|
|
{
|
|
//for now for thermocouples just accept any excitation
|
|
if (!dasChannel.IsSupported(se) && !sensor.IsThermocoupler())
|
|
{
|
|
APILogger.DebugLog($"SortOutConfig hc={dasChannel?.HardwareChannelName ?? "N/A"}, {se.ToString()} not supported on channel");
|
|
continue;
|
|
}
|
|
sc = SensorCalibration.GetLatestCalibrationBySerialNumberAndExcitation(sensor, se);
|
|
if (null != sc) { break; }
|
|
else
|
|
{
|
|
APILogger.DebugLog($"SortOutConfig hc={dasChannel?.HardwareChannelName ?? "N/A"}, no sensor calibration for {se.ToString()}");
|
|
}
|
|
}
|
|
if (null == sc)
|
|
{
|
|
APILogger.DebugLog($"SortOutConfig hc={dasChannel?.HardwareChannelName ?? "N/A"}, no calibration!");
|
|
return false;
|
|
}
|
|
|
|
// 14055 use non-linear cal if we're a single-cal'd sensor or if we're a dual-cal and behavior isn't to use linear
|
|
var bUseNonLinear = !sc.NonLinear || !sc.LinearAdded || CalibrationBehaviors.LinearIfAvailable !=
|
|
soParams.TestTemplate.CalibrationBehavior;
|
|
|
|
if (sensor.Bridge == SensorConstants.BridgeType.IEPE)
|
|
{
|
|
dasChannel.CouplingMode = sensor.CouplingMode;
|
|
}
|
|
dasChannel.ACCouplingModeEnabled = sensor.ACCouplingModeEnabled;
|
|
|
|
if (null != hc.GroupChannel)
|
|
{
|
|
var groupChannel = (GroupChannel)hc.GroupChannel;
|
|
if (groupChannel.IsTSRAIRLowG)
|
|
{
|
|
if (groupChannel.ACCouplingEnabled)
|
|
{
|
|
dasChannel.ACCouplingModeEnabled = true;
|
|
dasChannel.CouplingMode = SensorConstants.CouplingModes.AC;
|
|
}
|
|
else
|
|
{
|
|
dasChannel.ACCouplingModeEnabled = false;
|
|
dasChannel.CouplingMode = SensorConstants.CouplingModes.DC;
|
|
}
|
|
}
|
|
}
|
|
|
|
dasChannel.BridgeResistanceOhms = sensor.BridgeResistance;
|
|
if (sc.NonLinear && bUseNonLinear &&
|
|
sc.IRTraccCalculationType ==
|
|
NonLinearStyles.IRTraccCalFactor)
|
|
{
|
|
if (!Equals(sc.Records.Records[0].Poly.CalibrationFactor, 0.0))
|
|
{
|
|
dasChannel.ZeroPoint = sc.Records.Records[0].Poly.ZeroPositionIntercept /
|
|
sc.Records.Records[0].Poly.CalibrationFactor;
|
|
}
|
|
else
|
|
{
|
|
dasChannel.ZeroPoint = 0.0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dasChannel.ZeroPoint = sc.Records.Records[sc.Records.Records.Count() - 1].ZeroPoint;
|
|
}
|
|
dasChannel.BypassAAFilter = sensor.ByPassFilter;
|
|
dasChannel.CalSignalIsEnabled = sensor.CalSignal;
|
|
dasChannel.Description = sensor.Comment;
|
|
dasChannel.Manufacturer = sensor.Manufacturer;
|
|
dasChannel.Model = sensor.Model;
|
|
dasChannel.OriginalChannelName = hc.ChannelName;
|
|
dasChannel.ChannelName2 = hc.DisplayName;
|
|
dasChannel.ChannelId = hc.GroupChannel.Id.ToString();
|
|
dasChannel.ChannelGroupName = hc.GroupChannel.GroupName;
|
|
dasChannel.HardwareChannelName = hc.GetIdSimple(soParams.AllHardware);
|
|
|
|
dasChannel.SensorCapacity = sensor.Capacity;
|
|
dasChannel.SensorPolarity = sensor.Polarity;
|
|
dasChannel.DesiredRangeWithHeadroomEU = sensor.Capacity * SerializedSettings.DesiredRangeOverheadPercent *
|
|
MeasurementUnitList.GetMeasurementUnit(sc.Records.Records[0].EngineeringUnits).GetScalerConversionFrom(sensor.DisplayUnit);
|
|
if (sensor.UniPolar)
|
|
{
|
|
//we only want half the above range
|
|
//note SLICEWare does this slightly different and uses capacity/2D, but I think it's better to have the safety net of the headroom
|
|
dasChannel.DesiredRangeWithHeadroomEU /= 2D;
|
|
}
|
|
|
|
dasChannel.Excitation = GetExcitationVoltageEnum(sc, hc.GroupChannel, soParams.GetChannelLookup(), sensor);
|
|
//25452 non optimal gain selected for non-linear sensors
|
|
if (sc.NonLinear && bUseNonLinear)
|
|
{
|
|
//we have to pick a gain by doing some guesswork
|
|
var inputRanges = new List<double>(das.GetNominalRanges(sensor.Bridge));
|
|
inputRanges.Sort();
|
|
//iterate through, find the smallest input range mV that satisfies the desired headroom and min value (0)
|
|
var exc = DTS.Common.DAS.Concepts.Test.Module.Channel.Sensor.GetExcitationVoltageMagnitudeFromEnum(dasChannel.Excitation);
|
|
int i;
|
|
for (i = 0; i < inputRanges.Count - 1; i++)
|
|
{
|
|
double[] eu = { sc.GetPolynomialEU(0, exc), sc.GetPolynomialEU(inputRanges[i], exc) };
|
|
//this one is acceptable if both the min and max values are satisfied
|
|
//we're ignoring a whole bunch of problems, like negative or inverted outputs, and so on
|
|
if (eu[0] <= 1 && eu[1] >= dasChannel.DesiredRangeWithHeadroomEU) { break; }
|
|
if (eu[1] <= 1 && eu[0] >= dasChannel.DesiredRangeWithHeadroomEU) { break; }
|
|
}
|
|
dasChannel.DesiredRangeWithHeadroomEU = inputRanges[i];
|
|
}
|
|
if (sensor.IsDigitalInput() || sensor.IsDigitalOutput()) { dasChannel.DesiredRangeWithHeadroomEU = sensor.FullScaleCapacity; }
|
|
dasChannel.DiagnosticsMode = sensor.DiagnosticsMode;
|
|
dasChannel.EngineeringUnits = sc.Records.Records[0].EngineeringUnits;
|
|
dasChannel.EventStartTime = DateTime.Now;
|
|
|
|
dasChannel.InitialOffset = hc.GroupChannel.InitialOffset.ToDbSerializeString();
|
|
switch (hc.GroupChannel.InitialOffset.Form)
|
|
{
|
|
case InitialOffsetTypes.EU:
|
|
dasChannel.InitialEU = hc.GroupChannel.InitialOffset.EU; break;
|
|
default:
|
|
dasChannel.InitialEU = 0D;
|
|
break;
|
|
}
|
|
|
|
dasChannel.IsInverted = sensor.Invert;
|
|
if (sensor.FilterClassIso == "?")
|
|
{
|
|
sensor.FilterClassIso = "P"; // "Prefiltered > CFC 1000" (Unfiltered)
|
|
}
|
|
dasChannel.ISOCode = hc.GroupChannel.IsoCode;
|
|
//IEPE should nto be marked as proportional to excitation
|
|
dasChannel.IsProportionalToExcitation = sc.IsProportional
|
|
&& sensor.Bridge != SensorConstants.BridgeType.IEPE;
|
|
|
|
dasChannel.AtCapacity = bUseNonLinear ? sc.Records.Records[0].AtCapacity : sc.Records.Records[sc.Records.Records.Count() - 1].AtCapacity;
|
|
dasChannel.SensitivityUnits = bUseNonLinear ? sc.Records.Records[0].SensitivityUnits : sc.Records.Records[sc.Records.Records.Count() - 1].SensitivityUnits;
|
|
dasChannel.CapacityOutputIsBasedOn = bUseNonLinear ? sc.Records.Records[0].CapacityOutputIsBasedOn : sc.Records.Records[sc.Records.Records.Count() - 1].CapacityOutputIsBasedOn;
|
|
dasChannel.UserCode = hc.UserCode;
|
|
dasChannel.UserChannelName = hc.UserChannelName;
|
|
dasChannel.IsoChannelName = hc.IsoChannelName;
|
|
dasChannel.LastCalibrationDate = sc.CalibrationDate;
|
|
dasChannel.CalDueDate = sensor.GetDueDate(sc);
|
|
dasChannel.DigitalMultiplier = sensor.ScaleMultiplier;
|
|
|
|
dasChannel.DIUnits = sensor.DIUnits;
|
|
dasChannel.DigitalMode = sensor.InputMode;
|
|
dasChannel.LinearizationFormula = new LinearizationFormula(bUseNonLinear ? sc.Records.Records[0].Poly : sc.Records.Records[sc.Records.Records.Count() - 1].Poly);
|
|
dasChannel.LinearSensorCalibration = bUseNonLinear ? sc.LinearAddedValues : string.Empty;
|
|
dasChannel.OffsetToleranceHighMilliVolts = sensor.OffsetToleranceHigh;
|
|
dasChannel.OffsetToleranceLowMilliVolts = sensor.OffsetToleranceLow;
|
|
dasChannel.RemoveOffset = sc.RemoveOffset;
|
|
if (UseACCoupling(sensor, hc))
|
|
{
|
|
dasChannel.RemoveOffset = false;
|
|
}
|
|
APILogger.DebugLog($"SortOutConfig hc={dasChannel?.HardwareChannelName ?? "N/A"}, sc={sc?.ToSerializedString() ?? "N/A"}, sensor={sensor?.SerialNumber ?? "N/A"}");
|
|
dasChannel.SensitivityMilliVoltsPerEU = GetSensitivity(sc, hc.GroupChannel, soParams.GetChannelLookup(), sensor, bUseNonLinear);
|
|
dasChannel.UnitConverision = MeasurementUnitList.GetMeasurementUnit(sc.Records.Records[0].EngineeringUnits).GetScalerConversion(sensor.DisplayUnit);
|
|
if (sc.NonLinear && bUseNonLinear && sc.IRTraccCalculationType != NonLinearStyles.Polynomial)
|
|
{
|
|
dasChannel.SensorCapacityEU = sensor.FullScaleCapacity;
|
|
}
|
|
else if (sc.NonLinear && bUseNonLinear && sc.IRTraccCalculationType == NonLinearStyles.Polynomial)
|
|
{
|
|
//why is this being done twice?
|
|
//well at least for this type, lets not do it twice.
|
|
}
|
|
else if (sensor.IsDigitalInput()) { dasChannel.SensorCapacityEU = sensor.Capacity; }
|
|
else if (sensor.IsDigitalOutput()) { dasChannel.SensorCapacityEU = sensor.FullScaleCapacity; }
|
|
else
|
|
{
|
|
dasChannel.SensorCapacityEU = sensor.Capacity *
|
|
MeasurementUnitList.GetMeasurementUnit(sc.Records.Records[0].EngineeringUnits).GetScalerConversionFrom(sensor.DisplayUnit);
|
|
}
|
|
dasChannel.SerialNumber = sensor.SerialNumber;
|
|
dasChannel.Unipolar = sensor.UniPolar;
|
|
dasChannel.ShuntIsEnabled = sensor.PerformShuntEmulation && !sensor.DiagnosticsMode
|
|
&& sensor.Bridge != SensorConstants.BridgeType.IEPE && !sensor.IsTestSpecificEmbedded && !sensor.IsTestSpecificThermo;
|
|
dasChannel.SoftwareFilterFrequency = sensor.FilterClass.Frequency;
|
|
//FB 13120 For now we will continue using the SoftwareFilterFrequency until we move all the refrences to SoftwareFilterClass.
|
|
dasChannel.SoftwareFilterClass = sensor.FilterClass;
|
|
//33415 Voltage insertion channel should be half bridge
|
|
dasChannel.TypeOfBridge = null != hc.GroupChannel && Array.Exists(hc.GroupChannel.ChannelSettings, chset => ChannelSettingBase.BRIDGE_TYPE == chset.SettingName)
|
|
? (SensorConstants.BridgeType)Enum.Parse(typeof(SensorConstants.BridgeType), hc.GroupChannel.ChannelSettings.First(chset => ChannelSettingBase.BRIDGE_TYPE == chset.SettingName).Value)
|
|
: sensor.Bridge;
|
|
dasChannel.UserValue1 = sensor.UserValue1;
|
|
dasChannel.UserValue2 = sensor.UserValue2;
|
|
dasChannel.UserValue3 = sensor.UserValue3;
|
|
dasChannel.VerifyOffset = true;
|
|
dasChannel.VoltageInsertionCheckEnabled = false;
|
|
//FB14606: Test Setup Specific-ize ZeroMethod parameters
|
|
dasChannel.ZeroAverageStartSeconds = hc.GroupChannel.ZeroMethodStart;
|
|
dasChannel.ZeroAverageStopSeconds = hc.GroupChannel.ZeroMethodEnd;
|
|
dasChannel.ZeroMethod = hc.GroupChannel.ZeroMethod;
|
|
if (dasChannel.IEPEChannel != (sensor.Bridge == SensorConstants.BridgeType.IEPE))
|
|
{
|
|
//IEPE status of channel disagrees with sensor, can we reprogram the DAS?
|
|
if (dasChannel.CanReProgram())
|
|
{
|
|
dasChannel.IEPEChannel = sensor.Bridge == SensorConstants.BridgeType.IEPE;
|
|
}
|
|
else
|
|
{
|
|
if (dasChannel.IEPEChannel)
|
|
{
|
|
ReportErrors?.Invoke(new List<string>(new[]
|
|
{
|
|
string.Format(StringResources.EditObjectSensorsControl_InvalidIEPEOnNonIEPE, dasChannel.ChannelName2, sensor.SerialNumber)
|
|
}));
|
|
}
|
|
else
|
|
{
|
|
ReportErrors?.Invoke(new List<string>(new[]
|
|
{
|
|
string.Format(StringResources.EditObjectSensorsControl_InvalidNonIEPEOnIEPE, dasChannel.ChannelName2, sensor.SerialNumber)
|
|
}));
|
|
}
|
|
//FAIL ?
|
|
}
|
|
}
|
|
|
|
dasChannel.TriggerBelowThresholdEu = null;
|
|
dasChannel.TriggerAboveThresholdEu = null;
|
|
dasChannel.LevelTriggerType = DTS.Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.NONE;
|
|
|
|
//the edittestsetupleveltrigger is a convenient wrapper and easier that the isoleveltrigger, so I use it here.
|
|
var lt = new LevelTriggerCapableChannel(hc, sensor, sc, soParams.GetGroupFromChannelId(hc.GroupChannel.Id), hc.GroupChannel);
|
|
//ReSharper disable once InconsistentNaming
|
|
var existingLT = soParams.TestTemplate.GetLevelTrigger(lt.ToISOLevelTriggerChannel());
|
|
if (null != existingLT)
|
|
{
|
|
lt.FromISOLevelTriggerChannel(existingLT);
|
|
if (h.IsTSRAIR())
|
|
{
|
|
if (existingLT.TriggerOutsideBounds)
|
|
{
|
|
dasChannel.LevelTriggerType = DTS.Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.OutsideWindow;
|
|
dasChannel.TriggerAboveThresholdEu = lt.OutsideUpperBoundValue;
|
|
dasChannel.TriggerBelowThresholdEu = lt.OutsideLowerBoundValue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (existingLT.TriggerBetweenBounds)
|
|
{
|
|
dasChannel.LevelTriggerType = DTS.Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.InsideWindow;
|
|
dasChannel.TriggerAboveThresholdEu = lt.InsideUpperBoundValue;
|
|
dasChannel.TriggerBelowThresholdEu = lt.InsideLowerBoundValue;
|
|
}
|
|
else if (existingLT.TriggerOutsideBounds)
|
|
{
|
|
dasChannel.LevelTriggerType = DTS.Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.OutsideWindow;
|
|
dasChannel.TriggerBelowThresholdEu = lt.OutsideLowerBoundValue;
|
|
dasChannel.TriggerAboveThresholdEu = lt.OutsideUpperBoundValue;
|
|
}
|
|
else if (existingLT.GreaterThanEnabled && existingLT.LessThanEnabled)
|
|
{
|
|
dasChannel.LevelTriggerType = DTS.Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.GreaterThan | DTS.Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.LessThan;
|
|
dasChannel.TriggerAboveThresholdEu = lt.GreaterThanValue;
|
|
dasChannel.TriggerBelowThresholdEu = lt.LessThanValue;
|
|
}
|
|
else if (existingLT.LessThanEnabled)
|
|
{
|
|
dasChannel.LevelTriggerType = DTS.Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.LessThan;
|
|
dasChannel.TriggerBelowThresholdEu = lt.LessThanValue;
|
|
}
|
|
else if (existingLT.GreaterThanEnabled)
|
|
{
|
|
dasChannel.LevelTriggerType = DTS.Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.GreaterThan;
|
|
dasChannel.TriggerAboveThresholdEu = lt.GreaterThanValue;
|
|
}
|
|
}
|
|
}
|
|
if (h.IsTSRAIR())
|
|
{
|
|
//18057 set channel's supersampling rate
|
|
dasChannel.UnsupersampledSampleRate = soParams.TestTemplate.GetSampleRateForEmbeddedHardware(h, das.DASInfo.Modules[mod.ModuleArrayIndex].TypeOfModule);
|
|
}
|
|
return true;
|
|
}
|
|
public static void SortOutConfigCAN(IDASChannel c, int moduleChannelNumber, SortOutConfigParams soParams)
|
|
{
|
|
var canChannel = c as CANInputDASChannel;
|
|
canChannel.ModuleChannelNumber = moduleChannelNumber;
|
|
var testChannel = soParams.TestTemplate.ChannelsForGroup.FirstOrDefault().Value;
|
|
canChannel.IsFD = testChannel[0].CanIsFD;
|
|
canChannel.ArbBaseBitrate = testChannel[0].CanArbBaseBitrate;
|
|
canChannel.ArbBaseSJW = testChannel[0].CanArbBaseSJW;
|
|
canChannel.DataBitrate = testChannel[0].CanDataBitrate;
|
|
canChannel.DataSJW = testChannel[0].CanDataSJW;
|
|
canChannel.FileType = testChannel[0].CanFileType;
|
|
}
|
|
/// <summary>
|
|
/// sorts out the squib properties from the test setup and sets properties on the squibchannel
|
|
/// </summary>
|
|
/// <param name="currentChannelIdx"></param>
|
|
/// <param name="mod"></param>
|
|
/// <param name="harwarechanneltoAbsoluteDisplayOrder"></param>
|
|
/// <param name="key"></param>
|
|
/// <param name="moduleChannelNumber"></param>
|
|
/// <param name="channelLookup"></param>
|
|
/// <param name="c"></param>
|
|
/// <param name="currentTest"></param>
|
|
/// <param name="das"></param>
|
|
public static void SortOutConfigSquib(ref int currentChannelIdx, IDASModule mod,
|
|
string key, ref int moduleChannelNumber, IDASChannel c,
|
|
IDASCommunication das, SortOutConfigParams soParams)
|
|
{
|
|
currentChannelIdx++; //It's OK to increment this here because we need to handle both squib channels (Voltage and Current)
|
|
OutputSquibChannel squib2 = null;
|
|
if (currentChannelIdx < mod.Channels.Length) { squib2 = mod.Channels[currentChannelIdx] as OutputSquibChannel; }
|
|
if (null == squib2) { throw new NotSupportedException("require both VO and CU channels"); }
|
|
|
|
var outputSquibChannel = c as OutputSquibChannel;
|
|
if ( soParams.ContainsHardwareChannelDisplayOrder(key))
|
|
{
|
|
outputSquibChannel.AbsoluteDisplayOrder = soParams.GetHardwareChannelAbsoluteDisplayOrder(key);
|
|
squib2.AbsoluteDisplayOrder = outputSquibChannel.AbsoluteDisplayOrder;
|
|
}
|
|
outputSquibChannel.ModuleChannelNumber = moduleChannelNumber;
|
|
moduleChannelNumber++;
|
|
squib2.ModuleChannelNumber = moduleChannelNumber;
|
|
var hc = soParams.GetHardwareChannel(key);
|
|
var sensor = hc.Sensor;
|
|
|
|
//SensorID is the EID of the sensor, and is saved in the config so
|
|
//that if the associated DAS is connected to a different computer,
|
|
//this test-used EID can be found. This is helpful, for example,
|
|
//when the Quick build button is used to create a new Test Setup and
|
|
//the same sensor is connected to a different DAS. Prior to this
|
|
//saving in the config, only the "live" EID was known when reading the config.
|
|
outputSquibChannel.IDs = new EID[] { new EID(sensor.EID) };
|
|
|
|
sensor.ISOCode = hc.GroupChannel.IsoCode;
|
|
foreach (var se in sensor.SupportedExcitation)
|
|
{
|
|
var sc = SensorCalibration
|
|
.GetLatestCalibrationBySerialNumberAndExcitation(sensor, se);
|
|
if (null != sc) { break; }
|
|
}
|
|
|
|
outputSquibChannel.DiagnosticsMode = false;
|
|
squib2.DiagnosticsMode = false;
|
|
|
|
outputSquibChannel.EventStartTime = DateTime.Now;
|
|
squib2.EventStartTime = DateTime.Now;
|
|
|
|
|
|
var isocode = new DTS.Common.ISO.IsoCode(sensor.ISOCode)
|
|
{
|
|
PhysicalDimension = "VO"
|
|
};
|
|
outputSquibChannel.ISOCode = isocode.StringRepresentation;
|
|
isocode.PhysicalDimension = "CU";
|
|
squib2.ISOCode = isocode.StringRepresentation;
|
|
|
|
outputSquibChannel.UserCode = hc.GroupChannel.UserCode;
|
|
outputSquibChannel.UserChannelName = hc.GroupChannel.UserChannelName;
|
|
outputSquibChannel.IsoChannelName = hc.GroupChannel.IsoChannelName;
|
|
|
|
squib2.UserCode = outputSquibChannel.UserCode;
|
|
squib2.UserChannelName = outputSquibChannel.UserChannelName;
|
|
squib2.IsoChannelName = outputSquibChannel.IsoChannelName;
|
|
|
|
outputSquibChannel.BypassCurrentFilter = sensor.BypassCurrentFilter;
|
|
squib2.BypassCurrentFilter = outputSquibChannel.BypassCurrentFilter;
|
|
|
|
outputSquibChannel.BypassVoltageFilter = sensor.BypassVoltageFilter;
|
|
squib2.BypassVoltageFilter = outputSquibChannel.BypassVoltageFilter;
|
|
|
|
outputSquibChannel.ConfigurationMode = DFConstantsAndEnums.ConfigMode.Normal;
|
|
squib2.ConfigurationMode = DFConstantsAndEnums.ConfigMode.Normal;
|
|
|
|
outputSquibChannel.Date = DateTime.Now;
|
|
squib2.Date = DateTime.Now;
|
|
|
|
outputSquibChannel.DelayMS = sensor.SquibFireDelayMS;
|
|
squib2.DelayMS = sensor.SquibFireDelayMS;
|
|
|
|
outputSquibChannel.DiagnosticsMode = false;
|
|
squib2.DiagnosticsMode = false;
|
|
|
|
outputSquibChannel.DurationMS = sensor.SquibFireDurationMS;
|
|
squib2.DurationMS = outputSquibChannel.DurationMS;
|
|
|
|
outputSquibChannel.LimitDuration = sensor.LimitSquibFireDuration;
|
|
squib2.LimitDuration = outputSquibChannel.LimitDuration;
|
|
|
|
outputSquibChannel.MeasurementType = sensor.SquibMeasurementType;
|
|
squib2.MeasurementType = SquibMeasurementType.CURRENT;
|
|
|
|
outputSquibChannel.FireMode = sensor.SquibFireMode;
|
|
|
|
squib2.FireMode = outputSquibChannel.FireMode;
|
|
|
|
outputSquibChannel.SquibDescription = sensor.Comment;
|
|
squib2.SquibDescription = sensor.Comment;
|
|
|
|
outputSquibChannel.SquibFiredPassed = false;
|
|
squib2.SquibFiredPassed = false;
|
|
|
|
outputSquibChannel.SquibFiredValid = false;
|
|
squib2.SquibFiredPassed = outputSquibChannel.SquibFiredPassed;
|
|
|
|
outputSquibChannel.SquibToleranceHigh = sensor.SquibToleranceHigh;
|
|
squib2.SquibToleranceHigh = outputSquibChannel.SquibToleranceHigh;
|
|
|
|
outputSquibChannel.SquibToleranceLow = sensor.SquibToleranceLow;
|
|
squib2.SquibToleranceLow = outputSquibChannel.SquibToleranceLow;
|
|
|
|
outputSquibChannel.SquibOutputCurrent = sensor.SquibOutputCurrent;
|
|
squib2.SquibOutputCurrent = outputSquibChannel.SquibOutputCurrent;
|
|
|
|
outputSquibChannel.UserValue1 = sensor.UserValue1;
|
|
squib2.UserValue1 = outputSquibChannel.UserValue1;
|
|
outputSquibChannel.UserValue2 = sensor.UserValue2;
|
|
squib2.UserValue2 = outputSquibChannel.UserValue2;
|
|
outputSquibChannel.UserValue3 = sensor.UserValue3;
|
|
squib2.UserValue3 = outputSquibChannel.UserValue3;
|
|
outputSquibChannel.ChannelName2 = hc.DisplayName;
|
|
outputSquibChannel.ChannelId = hc.GroupChannel.Id.ToString();
|
|
outputSquibChannel.Sensor = hc.GroupChannel.SensorData.SerialNumber.ToString();
|
|
squib2.SerialNumber = hc.GroupChannel.SensorData.SerialNumber;
|
|
outputSquibChannel.SerialNumber = hc.GroupChannel.SensorData.SerialNumber;
|
|
outputSquibChannel.ChannelGroupName = hc.GroupChannel.GroupName;
|
|
squib2.ChannelId = hc.GroupChannel.Id.ToString() + Constants.CURRENT_SUFFIX;
|
|
squib2.Sensor = hc.GroupChannel.SensorData.SerialNumber.ToString() + Constants.CURRENT_SUFFIX;
|
|
squib2.ChannelGroupName = hc.GroupChannel.GroupName;
|
|
squib2.ChannelName2 = hc.DisplayName;
|
|
|
|
outputSquibChannel.SetupEID = sensor.EID;
|
|
squib2.SetupEID = sensor.EID;
|
|
if ( null != outputSquibChannel.IDs && outputSquibChannel.IDs.Length > 0 && null != outputSquibChannel.IDs[0]
|
|
&& outputSquibChannel.IDs[0].IsValid())
|
|
{
|
|
outputSquibChannel.DataCollectionEID = outputSquibChannel.IDs[0].ID;
|
|
squib2.DataCollectionEID = outputSquibChannel.DataCollectionEID;
|
|
}
|
|
|
|
|
|
if (squib2.SquibDescription.EndsWith(".1"))
|
|
{
|
|
var newName = squib2.SquibDescription;
|
|
newName = newName.Substring(0, newName.Length - 2) + ".2";
|
|
squib2.ChannelName2 = squib2.ChannelName2.Replace(squib2.SquibDescription, newName);
|
|
}
|
|
outputSquibChannel.HardwareChannelName = hc.GetIdSimple();
|
|
squib2.HardwareChannelName = hc.GetIdSimple();
|
|
|
|
//8747 - controls the default software filter for this channel
|
|
//by using a harcoded filter, like TDC does
|
|
if (SerializedSettings.UseLegacyTOMCFC &&
|
|
soParams.TestTemplate.DASSampleRateList[das.SerialNumber] > TestObjectHelper.TDC_LEGACY_TOM_CUTOFF_SPS)
|
|
{
|
|
outputSquibChannel.SoftwareFilterFrequency = TestObjectHelper.TDC_LEGACY_TOM_HIGH_FILTER;
|
|
squib2.SoftwareFilterFrequency = TestObjectHelper.TDC_LEGACY_TOM_HIGH_FILTER;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// sorts out TOMdigital properties from the test setup and sets the properties on the DASChannel
|
|
/// </summary>
|
|
/// <param name="c"></param>
|
|
/// <param name="key"></param>
|
|
/// <param name="harwarechanneltoAbsoluteDisplayOrder"></param>
|
|
/// <param name="moduleChannelNumber"></param>
|
|
/// <param name="channelLookup"></param>
|
|
public static void SortOutConfigTOMDigitalChannel(IDASChannel c, string key,
|
|
int moduleChannelNumber, SortOutConfigParams soParams)
|
|
{
|
|
var dOut = c as OutputTOMDigitalChannel;
|
|
if (soParams.ContainsHardwareChannelDisplayOrder(key))
|
|
{
|
|
dOut.AbsoluteDisplayOrder = soParams.GetHardwareChannelAbsoluteDisplayOrder(key);
|
|
}
|
|
dOut.ModuleChannelNumber = moduleChannelNumber;
|
|
var hc = soParams.GetHardwareChannel(key);
|
|
var sensor = hc.Sensor;
|
|
|
|
//SensorID is the EID of the sensor, and is saved in the config so
|
|
//that if the associated DAS is connected to a different computer,
|
|
//this test-used EID can be found. This is helpful, for example,
|
|
//when the Quick build button is used to create a new Test Setup and
|
|
//the same sensor is connected to a different DAS. Prior to this
|
|
//saving in the config, only the "live" EID was known when reading the config.
|
|
dOut.IDs = new EID[] { new EID(sensor.EID) };
|
|
|
|
dOut.DiagnosticsMode = false;
|
|
dOut.EventStartTime = DateTime.Now;
|
|
|
|
if (sensor.FilterClassIso == "?")
|
|
{
|
|
sensor.FilterClassIso = "P"; // "Prefiltered > CFC 1000" (Unfiltered)
|
|
}
|
|
dOut.ConfigurationMode = DFConstantsAndEnums.ConfigMode.Normal;
|
|
|
|
dOut.DelayMS = sensor.DigitalOutputDelayMS;
|
|
dOut.DiagnosticsMode = false;
|
|
dOut.DigitalChannelDescription = sensor.SerialNumber;
|
|
|
|
dOut.LimitDuration = sensor.DigitalOutputLimitDuration;
|
|
dOut.DurationMS = dOut.LimitDuration ? sensor.DigitalOutputDurationMS : 0;
|
|
dOut.OutputMode = sensor.DigitalOutputMode;
|
|
|
|
dOut.HardwareChannelName = hc.GetIdSimple();
|
|
dOut.IsoChannelName = sensor.ISOChannelName;
|
|
}
|
|
/// <summary>
|
|
/// this is the overall sortoutconfig function that was in multiple places, I tried to encapsulate and clean it up a little
|
|
/// </summary>
|
|
/// <param name="currentTest"></param>
|
|
/// <param name="ldas"></param>
|
|
/// <param name="clearDiagnostics"></param>
|
|
/// <param name="allHardware"></param>
|
|
/// <param name="currentUser"></param>
|
|
public static void SortOutConfig(DataModel.TestTemplate currentTest,
|
|
List<IDASCommunication> ldas,
|
|
bool clearDiagnostics,
|
|
DASHardware[] allHardware,
|
|
DTS.Slice.Users.User currentUser)
|
|
{
|
|
//18413 Diagnostics has not been run error message when using trigger check before realtime.
|
|
if (clearDiagnostics) { DASHardware.MarkAllDASUnclean(ldas); }
|
|
|
|
// set the test setup das order index for any das that support it
|
|
// used in 14531 Implement TMATS support for S6A stream on boot
|
|
var currentDasIndex = 0;
|
|
foreach (var das in ldas)
|
|
{
|
|
if (das is DTS.Common.Interface.TestSetups.ITestDASOrder iTestDASOrder)
|
|
{
|
|
iTestDASOrder.DASIndex = currentDasIndex++;
|
|
}
|
|
}
|
|
|
|
var soParams = new SortOutConfigParams() { TestTemplate = currentTest };
|
|
|
|
foreach (var group in currentTest.Groups)
|
|
{
|
|
soParams.AddGroupChannels(currentTest.ChannelsForGroup[group]);
|
|
}
|
|
|
|
foreach (var group in currentTest.Groups)
|
|
{
|
|
AddAndOrderChannels(group, soParams);
|
|
}
|
|
|
|
currentTest.FilterLookup = soParams.FilterLookup;
|
|
soParams.SetAllHardware(currentTest.GetHardware());
|
|
|
|
foreach (var das in ldas)
|
|
{
|
|
if (null == das.ConfigData) { continue; }
|
|
SortOutConfigDAS(das, currentUser, soParams);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// this was the portion of sort out config that applied to DAS, I abstracted it out to it's own function
|
|
/// for readability
|
|
/// </summary>
|
|
/// <param name="dasSerialToDASHardware"></param>
|
|
/// <param name="das"></param>
|
|
/// <param name="harwarechanneltoAbsoluteDisplayOrder"></param>
|
|
/// <param name="currentUser"></param>
|
|
/// <param name="channelLookup"></param>
|
|
/// <param name="allHardware"></param>
|
|
/// <param name="currentTest"></param>
|
|
/// <param name="testObjectChannelIdToGroup"></param>
|
|
/// <param name="reportErrors"></param>
|
|
public static void SortOutConfigDAS(IDASCommunication das,
|
|
DTS.Slice.Users.User currentUser,
|
|
SortOutConfigParams soParams,
|
|
ReportErrorsDelegate reportErrors = null)
|
|
{
|
|
if (null == das) { return; }
|
|
APILogger.DebugLog($"SortOutConfigDAS {das?.SerialNumber ?? "N/A"}");
|
|
if (!soParams.ContainsHardware(das.SerialNumber))
|
|
{
|
|
//this das is not part of the test (but may have configured channels, we need to set them to not collect data)
|
|
foreach (var module in das.ConfigData.Modules)
|
|
{
|
|
foreach (var c in module.Channels)
|
|
{
|
|
DisableChannel(c);
|
|
}
|
|
}
|
|
APILogger.DebugLog($"SortOutConfigDAS das={das?.SerialNumber ?? "N/A"} - not part of test, eliminating all channels");
|
|
return;
|
|
}
|
|
var h = soParams.GetHardware(das.SerialNumber);
|
|
if (null == h)
|
|
{
|
|
APILogger.DebugLog($"SortOutConfigDAS das={das?.SerialNumber ?? "N/A"} - no get hardware");
|
|
return;
|
|
}
|
|
var moduleNumber = 0;
|
|
|
|
var absoluteDisplayMax = 0;
|
|
if (soParams.GetHardwareChannelToAbsoluteDisplayOrderCount() > 0)
|
|
{
|
|
absoluteDisplayMax = soParams.GetMaxAbsoluteDisplayOrder();
|
|
}
|
|
var modules = new IDASModule[0];
|
|
if ( null != das.ConfigData.Modules)
|
|
{
|
|
modules = das.ConfigData.Modules;
|
|
}
|
|
foreach (var mod in modules)
|
|
{
|
|
if (null == mod) { continue; }
|
|
APILogger.DebugLog($"SortOutConfigDAS das={das?.SerialNumber ?? "N/A"}, module= {mod?.ModuleArrayIndex??-1}");
|
|
//this is just to make sure the profile is intialized, the StreamOutputModule will get set during processing below
|
|
mod.StreamProfile = (UDPStreamProfile)Enum.Parse(typeof(UDPStreamProfile),
|
|
Defaults.GetUserSettingValueString(currentUser.Id, PropertyEnums.PropertyIds.DefaultUDPStreamProfile));
|
|
var moduleChannelNumber = 0;
|
|
for (var currentChannelIdx = 0; currentChannelIdx < mod.Channels.Length; currentChannelIdx++)
|
|
{
|
|
APILogger.DebugLog($"SortOutConfigDAS das={das?.SerialNumber ?? "N/A"}, module= {mod?.ModuleArrayIndex ?? -1}, channel={currentChannelIdx}");
|
|
var c = mod.Channels[currentChannelIdx];
|
|
|
|
var key = $"{h.DASId}_{c.Number}";
|
|
var hc = soParams.GetHardwareChannel(key);
|
|
|
|
if (mod.IsClock())
|
|
{
|
|
c.ConfigurationMode = DFConstantsAndEnums.ConfigMode.Clock;
|
|
if (c is TimestampDASChannel tsdasChannel)
|
|
{
|
|
tsdasChannel.AbsoluteDisplayOrder = ++absoluteDisplayMax;
|
|
tsdasChannel.ModuleChannelNumber = moduleChannelNumber;
|
|
}
|
|
}
|
|
else if (null == hc || null == hc.Sensor)
|
|
{
|
|
APILogger.DebugLog($"SortOutConfigDAS das={das?.SerialNumber ?? "N/A"}, module= {mod?.ModuleArrayIndex ?? -1}, channel={currentChannelIdx} - no sensor on channel or no hardwarechannel");
|
|
DisableChannel(c);
|
|
}
|
|
else if (mod.IsUart())
|
|
{
|
|
c.ConfigurationMode = DFConstantsAndEnums.ConfigMode.UART;
|
|
if (c is UARTInputDASChannel uartChannel)
|
|
{
|
|
uartChannel.AbsoluteDisplayOrder = ++absoluteDisplayMax;
|
|
uartChannel.ModuleChannelNumber = moduleChannelNumber;
|
|
uartChannel.SerialNumber = hc.Sensor.SerialNumber;
|
|
uartChannel.HardwareChannelName = hc.GetIdSimple(soParams.AllHardware);
|
|
}
|
|
}
|
|
else if (mod.IsStreamOut())
|
|
{
|
|
c.ConfigurationMode = DFConstantsAndEnums.ConfigMode.StreamOut;
|
|
if (c is StreamOutputDASChannel streamOut)
|
|
{
|
|
streamOut.AbsoluteDisplayOrder = ++absoluteDisplayMax;
|
|
streamOut.ModuleChannelNumber = moduleChannelNumber;
|
|
streamOut.SerialNumber = hc.Sensor.SerialNumber;
|
|
streamOut.HardwareChannelName = hc.GetIdSimple(soParams.AllHardware);
|
|
mod.StreamProfile = hc.Sensor.StreamOutUDPProfile;
|
|
}
|
|
}
|
|
else if (mod.IsStreamIn())
|
|
{
|
|
c.ConfigurationMode = DFConstantsAndEnums.ConfigMode.StreamIn;
|
|
if (c is StreamInputDASChannel streamIn)
|
|
{
|
|
streamIn.AbsoluteDisplayOrder = ++absoluteDisplayMax;
|
|
streamIn.ModuleChannelNumber = moduleChannelNumber;
|
|
streamIn.SerialNumber = hc.Sensor.SerialNumber;
|
|
streamIn.HardwareChannelName = hc.GetIdSimple(soParams.AllHardware);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
c.ConfigurationMode = DFConstantsAndEnums.ConfigMode.Normal;
|
|
if (c is AnalogInputDASChannel dasChannel)
|
|
{
|
|
SortOutConfigAnalog(dasChannel, key, moduleChannelNumber,
|
|
das, h, mod, soParams, reportErrors);
|
|
//it had been contuing out but that seems wrong -
|
|
//for instance if we fail to sort out this channel because of support excitation
|
|
//you still want to go onto the next channel ...
|
|
}
|
|
else if (c is OutputSquibChannel)
|
|
{
|
|
SortOutConfigSquib(ref currentChannelIdx, mod, key, ref moduleChannelNumber,
|
|
c, das, soParams);
|
|
}
|
|
else if (c is OutputTOMDigitalChannel)
|
|
{
|
|
SortOutConfigTOMDigitalChannel(c, key, moduleChannelNumber, soParams);
|
|
}
|
|
else if (c is CANInputDASChannel)
|
|
{
|
|
SortOutConfigCAN(c, moduleChannelNumber, soParams);
|
|
}
|
|
}
|
|
|
|
moduleChannelNumber++;
|
|
}
|
|
|
|
var filterrate = Convert.ToUInt32(soParams.TestTemplate.GetAAFForHardware(h));
|
|
|
|
mod.AAFilterRateHz = filterrate;
|
|
mod.PostTriggerSeconds = soParams.TestTemplate.GetPostTriggerSeconds(das.SerialNumber);
|
|
mod.PreTriggerSeconds = soParams.TestTemplate.GetPreTriggerSeconds(das.SerialNumber);
|
|
mod.NumberOfEvents = soParams.TestTemplate.NumberOfEvents;
|
|
mod.WakeUpMotionTimeout = soParams.TestTemplate.WakeUpMotionTimeout;
|
|
mod.RecordingMode = RecordingModeExtensions.FromRecordingModes(soParams.TestTemplate.RecordingMode);
|
|
switch (soParams.TestTemplate.RecordingMode)
|
|
{
|
|
case RecordingModes.Interval:
|
|
mod.ScheduledStartTime = soParams.TestTemplate.RTCScheduleStartDateTime;
|
|
mod.RecordingInterval = soParams.TestTemplate.IntervalBetweenEventStartsMinutes;
|
|
break;
|
|
case RecordingModes.Scheduled:
|
|
mod.ScheduledStartTime = soParams.TestTemplate.RTCScheduleStartDateTime;
|
|
break;
|
|
case RecordingModes.MultipleEventCircularBufferPlusUART:
|
|
mod.RecordingMode = DFConstantsAndEnums.RecordingMode.AutoCircularBufferPlusUART;
|
|
break;
|
|
case RecordingModes.MultipleEventRecorderPlusUART:
|
|
mod.RecordingMode = DFConstantsAndEnums.RecordingMode.AutoRecorderModePlusUART;
|
|
break;
|
|
case RecordingModes.ContinuousRecorderPlusUART:
|
|
mod.RecordingMode = DFConstantsAndEnums.RecordingMode.ContinuousRecorderModePlusUART;
|
|
break;
|
|
case RecordingModes.Active:
|
|
case RecordingModes.MultipleEventActive:
|
|
mod.RecordingMode = SetActiveRecordingMode(soParams.TestTemplate);
|
|
break;
|
|
}
|
|
mod.SampleRateHz = Convert.ToUInt32(soParams.TestTemplate.GetSampleRateForHardware(h));
|
|
mod.FirmwareVersion = das.DASInfo.Modules[moduleNumber].FirmwareVersion;
|
|
mod.MaxEventStorageSpaceInBytes = das.DASInfo.Modules[moduleNumber].MaxEventStorageSpaceInBytes;
|
|
moduleNumber++;
|
|
}
|
|
das.ConfigData.TestID = soParams.TestTemplate.Name;
|
|
das.ConfigData.TestSetupUniqueId = soParams.TestTemplate.TestSetupUniqueId;
|
|
das.ConfigData.Description = soParams.TestTemplate.Description;
|
|
das.ConfigData.InstanceID = soParams.TestTemplate.TestId;
|
|
if ( das is IAlignUDPToPPSAware alignAware)
|
|
{
|
|
alignAware.AlignUDPToPPS = soParams.TestTemplate.AlignUDPToPPS;
|
|
}
|
|
}
|
|
|
|
public class SortOutConfigParams
|
|
{
|
|
private Dictionary<string, HardwareChannel> _channelLookup = new Dictionary<string, HardwareChannel>();
|
|
private readonly Dictionary<string, int> _harwarechanneltoAbsoluteDisplayOrder = new Dictionary<string, int>();
|
|
public int GetHardwareChannelToAbsoluteDisplayOrderCount() { return _harwarechanneltoAbsoluteDisplayOrder.Count; }
|
|
public bool ContainsHardwareChannelDisplayOrder(string key) { return _harwarechanneltoAbsoluteDisplayOrder.ContainsKey(key); }
|
|
public int GetHardwareChannelAbsoluteDisplayOrder(string key)
|
|
{
|
|
return _harwarechanneltoAbsoluteDisplayOrder.ContainsKey(key) ? _harwarechanneltoAbsoluteDisplayOrder[key] : -1;
|
|
}
|
|
|
|
public int GetMaxAbsoluteDisplayOrder()
|
|
{
|
|
return _harwarechanneltoAbsoluteDisplayOrder.Values.Max();
|
|
}
|
|
|
|
public Dictionary<string, double> FilterLookup { get; private set; } = new Dictionary<string, double>();
|
|
private readonly List<IGroupChannel> _channels = new List<IGroupChannel>();
|
|
public void AddGroupChannels(IGroupChannel [] channels)
|
|
{
|
|
_channels.AddRange(channels);
|
|
_channels.Sort((a, b) => a.TestSetupOrder.CompareTo(b.TestSetupOrder));
|
|
}
|
|
public void SetAbsoluteDisplayOrderFromIndex(string key, IGroupChannel ch)
|
|
{
|
|
_harwarechanneltoAbsoluteDisplayOrder[key] = _channels.IndexOf(ch);
|
|
}
|
|
public HardwareChannel GetHardwareChannel(string key)
|
|
{
|
|
return _channelLookup.ContainsKey(key) ? _channelLookup[key] : null;
|
|
}
|
|
public void SetHardwareChannel(string key, HardwareChannel channel)
|
|
{
|
|
_channelLookup[key] = channel;
|
|
}
|
|
public void SetChannelLookup(Dictionary<string, HardwareChannel> lookup)
|
|
{
|
|
_channelLookup = lookup;
|
|
}
|
|
public Dictionary<string, HardwareChannel> GetChannelLookup() { return _channelLookup; }
|
|
private readonly Dictionary<long, IGroup> _channelIdToGroup = new Dictionary<long, IGroup>();
|
|
public IGroup GetGroupFromChannelId(long id)
|
|
{
|
|
return _channelIdToGroup.ContainsKey(id) ? _channelIdToGroup[id] : null;
|
|
}
|
|
public void SetChannelIdToGroup(long id, IGroup group)
|
|
{
|
|
_channelIdToGroup[id] = group;
|
|
}
|
|
public DataModel.TestTemplate TestTemplate { get; set; } = new DataModel.TestTemplate();
|
|
public DASHardware [] AllHardware { get; private set; }
|
|
public void SetAllHardware(DASHardware[] hardware)
|
|
{
|
|
AllHardware = hardware;
|
|
_hardwareToSerialLookup.Clear();
|
|
SetHardwareLookupEntries(hardware);
|
|
}
|
|
public void SetHardwareLookupEntries(DASHardware [] hardware)
|
|
{
|
|
foreach (var h in hardware) { _hardwareToSerialLookup[h.SerialNumber] = h; }
|
|
}
|
|
private readonly Dictionary<string, DASHardware> _hardwareToSerialLookup = new Dictionary<string, DASHardware>();
|
|
public bool ContainsHardware(string serialNumber) { return _hardwareToSerialLookup.ContainsKey(serialNumber); }
|
|
public DASHardware GetHardware(string serialNumber)
|
|
{
|
|
return _hardwareToSerialLookup.ContainsKey(serialNumber) ? _hardwareToSerialLookup[serialNumber] : null;
|
|
}
|
|
}
|
|
|
|
public static void AddAndOrderChannels(IGroup group,
|
|
SortOutConfigParams soParams)
|
|
{
|
|
var hardware = soParams.TestTemplate.GetHardware();
|
|
|
|
foreach (var h in hardware)
|
|
{
|
|
foreach (var ch in h.Channels)
|
|
{
|
|
if (null == ch.Sensor) continue;
|
|
var key = $"{h.DASId}_{ch.ChannelNumber}";
|
|
soParams.SetHardwareChannel(key, ch);
|
|
try
|
|
{
|
|
if (soParams.FilterLookup.ContainsKey(key))
|
|
{
|
|
//item with same key is already added, previously spammed the log with this...
|
|
}
|
|
else
|
|
{
|
|
soParams.FilterLookup.Add(key, ch.Sensor.Filter.Frequency);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log("************************** " + ch.GetId() + " " + ex.Message + " **************");
|
|
}
|
|
}
|
|
}
|
|
|
|
var groupChannels = soParams.TestTemplate.ChannelsForGroup[group].ToList();
|
|
groupChannels.Sort((a, b) => a.TestSetupOrder.CompareTo(b.TestSetupOrder));
|
|
|
|
foreach (var ch in groupChannels)
|
|
{
|
|
if (ch.SensorId < 0 || ch.DASId < 0 || ch.DASChannelIndex < 0) { continue; }
|
|
|
|
var key = $"{ch.DASId}_{ch.DASChannelIndex}";
|
|
soParams.SetChannelIdToGroup(ch.Id, group);
|
|
soParams.SetAbsoluteDisplayOrderFromIndex(key, ch);
|
|
}
|
|
}
|
|
private static void DisableChannel(IDASChannel c)
|
|
{
|
|
c.ConfigurationMode = DFConstantsAndEnums.ConfigMode.Disabled;
|
|
if (c is AnalogInputDASChannel dasChannel)
|
|
{
|
|
dasChannel.ChannelName2 = "";
|
|
dasChannel.SerialNumber = "";
|
|
dasChannel.SensorCapacityEU = 1;
|
|
dasChannel.SensorCapacity = 0;
|
|
dasChannel.SensorPolarity = "";
|
|
dasChannel.TriggerAboveThresholdEu = null;
|
|
dasChannel.TriggerBelowThresholdEu = null;
|
|
dasChannel.LevelTriggerType = DTS.Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.NONE;
|
|
}
|
|
else if (c is OutputSquibChannel outputSquibChannel)
|
|
{
|
|
outputSquibChannel.FireMode = SquibFireMode.NONE;
|
|
}
|
|
else if (c is OutputTOMDigitalChannel dOut)
|
|
{
|
|
dOut.ConfigurationMode = DFConstantsAndEnums.ConfigMode.Disabled;
|
|
dOut.OutputMode = DigitalOutputModes.NONE;
|
|
}
|
|
}
|
|
public static ExcitationVoltageOptions.ExcitationVoltageOption GetExcitationVoltageEnum(SensorCalibration sc, IGroupChannel c,
|
|
Dictionary<string, HardwareChannel> channelLookup, SensorData sd)
|
|
{
|
|
var preferredExcitation = sd.SupportedExcitation[0];
|
|
if (c.DASId < 0 || c.DASChannelIndex < 0)
|
|
{
|
|
return preferredExcitation;
|
|
}
|
|
|
|
var key = $"{c.DASId}_{c.DASChannelIndex}";
|
|
//find the appropriate excitation
|
|
var h = channelLookup[key];
|
|
foreach (var se in sd.SupportedExcitation)
|
|
{
|
|
if (!h.IsSupportedExcitation(se)) continue;
|
|
preferredExcitation = se;
|
|
break;
|
|
}
|
|
return preferredExcitation;
|
|
}
|
|
private static bool UseACCoupling(SensorData sensor, HardwareChannel channel)
|
|
{
|
|
if (null == sensor || null == channel) { return false; }
|
|
switch (sensor.Bridge)
|
|
{
|
|
case SensorConstants.BridgeType.DigitalInput:
|
|
case SensorConstants.BridgeType.IEPE:
|
|
case SensorConstants.BridgeType.RTC:
|
|
case SensorConstants.BridgeType.SQUIB:
|
|
case SensorConstants.BridgeType.StreamOut:
|
|
case SensorConstants.BridgeType.StreamIn:
|
|
case SensorConstants.BridgeType.TOMDigital:
|
|
case SensorConstants.BridgeType.UART:
|
|
case SensorConstants.BridgeType.CAN:
|
|
return false;
|
|
}
|
|
if (!sensor.ACCouplingModeEnabled) { return false; }
|
|
if (channel.Hardware.ProtocolVersion < SLICE6AIR.AC_COUPLER_ENABLE) { return false; }
|
|
if (channel.Hardware.DASTypeEnum != HardwareTypes.SLICE6_AIR) { return false; }
|
|
return true;
|
|
}
|
|
public static double GetSensitivity(SensorCalibration sc, IGroupChannel c, Dictionary<string, HardwareChannel> channelLookup, SensorData sd, bool useNonLinear)
|
|
{
|
|
var preferredExcitation = sd.SupportedExcitation[0];
|
|
if ((sd.SupportedExcitation.Length > 1) && (c.DASId >= 0 && c.DASChannelIndex >= 0))
|
|
{
|
|
//find the appropriate excitation
|
|
var key = $"{c.DASId}_{c.DASChannelIndex}";
|
|
if (channelLookup.ContainsKey(key))
|
|
{
|
|
var h = channelLookup[key];
|
|
foreach (var se in sd.SupportedExcitation)
|
|
{
|
|
if (!h.IsSupportedExcitation(se)) continue;
|
|
preferredExcitation = se;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//hardware not found, just return the first excitation?
|
|
APILogger.Log(
|
|
$"warning, failed to find hardware {c.IsoChannelName}/{c.UserChannelName} - {c.DASId}:{c.DASChannelIndex}");
|
|
}
|
|
}
|
|
//nonlinear cal records are first, linear last
|
|
var record = useNonLinear ? Array.Find(sc.Records.Records, r => r.Excitation == preferredExcitation || !sc.IsProportional) : sc.Records.Records.LastOrDefault(r => r.Excitation == preferredExcitation || !sc.IsProportional);
|
|
if (null == record) { throw new NotSupportedException("no calibration record found for " + sc.SerialNumber + " for excitation " + preferredExcitation); }
|
|
//now finally, do any math we need
|
|
return record.Sensitivity;
|
|
}
|
|
public static DFConstantsAndEnums.RecordingMode SetActiveRecordingMode(DataModel.TestTemplate currentTest)
|
|
{
|
|
var result = DFConstantsAndEnums.RecordingMode.AutoActiveMode;
|
|
if (currentTest.WakeUpWithMotion)
|
|
{
|
|
result = DFConstantsAndEnums.RecordingMode.AerospaceWithMotion;
|
|
}
|
|
else if (currentTest.StartWithEvent)
|
|
{
|
|
result = DFConstantsAndEnums.RecordingMode.MultipleEventRecorderTriggerStart;
|
|
}
|
|
return result;
|
|
}
|
|
public bool CheckAAFilterRate(List<IDASCommunication> dasList)
|
|
{
|
|
var result = true;
|
|
|
|
var failureList = new List<string>();
|
|
using (var configService = new ConfigurationService())
|
|
{
|
|
var mreLocal = new ManualResetEvent(false);
|
|
configService.CheckAAFilterRate(dasList, delegate (ServiceBase.CallbackData cbd)
|
|
{
|
|
switch (cbd.Status)
|
|
{
|
|
case ServiceBase.CallbackData.CallbackStatus.Failure:
|
|
failureList.Add(cbd.Target.SerialNumber);
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.AllFinished:
|
|
mreLocal.Set();
|
|
break;
|
|
}
|
|
}, dasList);
|
|
mreLocal.WaitOne();
|
|
}
|
|
if (failureList.Any())
|
|
{
|
|
result = false;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
private void PrepareForDiagnostics(List<IDASCommunication> ldas, Dictionary<string, int> dasSampleRateList)
|
|
{
|
|
|
|
using (var diagnosticsService = new DiagnosticsService())
|
|
{
|
|
var sampleRateLookup = new Dictionary<string, double>();
|
|
var aafLookup = new Dictionary<string, float>();
|
|
|
|
foreach (var serialNumber in ldas.Where(x => dasSampleRateList.ContainsKey(x.SerialNumber)).Select(y=>y.SerialNumber))
|
|
{
|
|
var sampleRate = dasSampleRateList[serialNumber];
|
|
sampleRateLookup.Add(serialNumber, sampleRate);
|
|
aafLookup.Add(serialNumber, Convert.ToSingle(SerializedSettings.GetAAFException(SerializableAAF.DAS_TYPE.SLICE, sampleRate)));
|
|
}
|
|
|
|
var mre = new ManualResetEvent(false);
|
|
|
|
diagnosticsService.PrepareForDiagnostics(ldas,
|
|
PrePostResults.PreEventDiagnosticsResult,
|
|
sampleRateLookup,
|
|
aafLookup,
|
|
delegate (ServiceBase.CallbackData callbackData)
|
|
{
|
|
switch (callbackData.Status)
|
|
{
|
|
case ServiceBase.CallbackData.CallbackStatus.Success:
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.Progress:
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.NewData:
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.Failure:
|
|
callbackData.Target.DiagnosticsHasBeenRun = false;
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.Canceled:
|
|
callbackData.Target.DiagnosticsHasBeenRun = false;
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.AllFinished:
|
|
mre.Set();
|
|
break;
|
|
}
|
|
},
|
|
ldas);
|
|
|
|
|
|
var timeWaited = 0;
|
|
int MaxTime = 0;
|
|
MaxTime = Math.Max(MaxTime, SerializedSettings.Diagnostics_Slice_TimeoutSec * 1000);
|
|
while (!mre.WaitOne(100, false) && timeWaited < MaxTime)
|
|
{
|
|
timeWaited += 100;
|
|
}
|
|
if (timeWaited >= MaxTime)
|
|
{
|
|
APILogger.Log(
|
|
"Diagnostics::Exiting early due to timeout");
|
|
}
|
|
}
|
|
}
|
|
private bool DataNeverDownloaded(List<IDASCommunication> dasList)
|
|
{
|
|
int maxQueryDownloadTimeout = 0;
|
|
|
|
maxQueryDownloadTimeout = Math.Max(maxQueryDownloadTimeout,
|
|
SerializedSettings.ResolveChannels_SLICE_QueryDownloadTimeoutSec * 1000);
|
|
|
|
CheckForData(dasList, maxQueryDownloadTimeout);
|
|
|
|
var bHaveUnDownloadedData = false;
|
|
foreach (var downloadStatus in dasList.Select(x=>x.EventDownloadedStatus))
|
|
{
|
|
if (bHaveUnDownloadedData)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ((null != downloadStatus) && Array.Exists(downloadStatus, b => !b))
|
|
{
|
|
bHaveUnDownloadedData = true;
|
|
}
|
|
}
|
|
|
|
return bHaveUnDownloadedData;
|
|
}
|
|
protected void CheckForData(List<IDASCommunication> dasList, int maxQueryDownloadTimeout)
|
|
{
|
|
using (var ds = new DownloadService())
|
|
{
|
|
var mre = new ManualResetEvent(false);
|
|
var cancelEvent = new ManualResetEvent(false);
|
|
var doneEvent = new ManualResetEvent(false);
|
|
ds.QueryDownloadedStatus(dasList,
|
|
delegate (ServiceBase.CallbackData callbackData)
|
|
{
|
|
switch (callbackData.Status)
|
|
{
|
|
case ServiceBase.CallbackData.CallbackStatus.Canceled:
|
|
case ServiceBase.CallbackData.CallbackStatus.Failure:
|
|
cancelEvent.Set();
|
|
mre.Set();
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.AllFinished:
|
|
mre.Set();
|
|
break;
|
|
}
|
|
}, dasList);
|
|
var timeWaited = 0;
|
|
while (!cancelEvent.WaitOne(0, false) && !doneEvent.WaitOne(0, false) &&
|
|
!mre.WaitOne(100, false) && timeWaited < maxQueryDownloadTimeout)
|
|
{
|
|
timeWaited += 100;
|
|
var percent = 100D * timeWaited / maxQueryDownloadTimeout;
|
|
APILogger.Log($"{StringResources.CheckHardwareStatus_CheckingDAS} {percent:F0}%");
|
|
}
|
|
if (timeWaited >= maxQueryDownloadTimeout || cancelEvent.WaitOne(0, false) ||
|
|
doneEvent.WaitOne(0, false))
|
|
{
|
|
cancelEvent.Set();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void RunDiagnostics(List<IDASCommunication> ldas, DASHardware[] hardware)
|
|
{
|
|
using (var diagnosticsService = new DiagnosticsService())
|
|
{
|
|
var mre = new ManualResetEvent(false);
|
|
var cancelEvent = new ManualResetEvent(false);
|
|
var doneEvent = new ManualResetEvent(false);
|
|
var workEventDone = new ManualResetEvent(false);
|
|
var preOrPost = PrePostResults.PreEventDiagnosticsResult;
|
|
if (ldas.Count > 0)
|
|
{
|
|
try
|
|
{
|
|
diagnosticsService.SetStatusIndicator(ldas, DiagnosticsStatusIndicatorState.Pending, delegate (ServiceBase.CallbackData callbackData)
|
|
{
|
|
switch (callbackData.Status)
|
|
{
|
|
case ServiceBase.CallbackData.CallbackStatus.AllFinished:
|
|
mre.Set();
|
|
break;
|
|
}
|
|
},
|
|
ldas);
|
|
}
|
|
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log(ex);
|
|
diagnosticsService.Cancel();
|
|
Thread.Sleep(100);
|
|
cancelEvent.Set();
|
|
return;
|
|
}
|
|
var totalTime = 0;
|
|
int MaxTime = 0;
|
|
MaxTime = Math.Max(MaxTime, SerializedSettings.Diagnostics_Slice_TimeoutSec * 1000);
|
|
while (totalTime < MaxTime && !cancelEvent.WaitOne(0, false) && !doneEvent.WaitOne(0, false) && !mre.WaitOne(10, false))
|
|
{
|
|
totalTime += 10;
|
|
}
|
|
if (totalTime >= MaxTime || cancelEvent.WaitOne(0, false) || doneEvent.WaitOne(0, false))
|
|
{
|
|
APILogger.Log("Diagnostics::Exiting early due to timeout or user cancel");
|
|
diagnosticsService.ForceCancel();
|
|
Thread.Sleep(100);
|
|
cancelEvent.Set();
|
|
return;
|
|
}
|
|
|
|
//keep track of what units failed and why so we can warn later
|
|
//17822 DataPRO and TDAS rack unresponsive during diagnostics
|
|
var failedUnits = new List<Tuple<IDASCommunication, string>>();
|
|
|
|
try
|
|
{
|
|
diagnosticsService.Diagnos(ldas, 0, preOrPost, delegate (ServiceBase.CallbackData callbackData)
|
|
{
|
|
switch (callbackData.Status)
|
|
{
|
|
case ServiceBase.CallbackData.CallbackStatus.Success:
|
|
callbackData.Target.DiagnosticsHasBeenRun = true;
|
|
|
|
foreach (var h in hardware)
|
|
{
|
|
if (h.SerialNumber != callbackData.Target.SerialNumber) continue;
|
|
if (null == ((InfoResult)callbackData.Target.DASInfo).OwningDAS.BaseInput) continue;
|
|
h.MeasuredInputVoltage = Math.Round(((InfoResult)callbackData.Target.DASInfo).OwningDAS.BaseInput.InputMilliVolts / 1000D, 2);
|
|
h.MeasuredBatteryVoltage = Math.Round(((InfoResult)callbackData.Target.DASInfo).OwningDAS.BaseInput.BatteryMilliVolts / 1000D, 2);
|
|
}
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.Progress:
|
|
case ServiceBase.CallbackData.CallbackStatus.NewData:
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.Failure:
|
|
callbackData.Target.DiagnosticsHasBeenRun = false;
|
|
var msg = callbackData.ErrorMessage;
|
|
if (callbackData.ErrorException is TriggerShortedException)
|
|
{
|
|
msg = string.Format(StringResources.Diagnostics_ShortedTrigger);
|
|
}
|
|
failedUnits.Add(new Tuple<IDASCommunication, string>(callbackData.Target, msg));
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.Canceled:
|
|
callbackData.Target.DiagnosticsHasBeenRun = false;
|
|
break;
|
|
case ServiceBase.CallbackData.CallbackStatus.AllFinished:
|
|
mre.Set();
|
|
break;
|
|
}
|
|
},
|
|
ldas, MaxTime);
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log(ex.Message);
|
|
diagnosticsService.ForceCancel();
|
|
Thread.Sleep(100);
|
|
cancelEvent.Set();
|
|
return;
|
|
}
|
|
totalTime = 0;
|
|
while (totalTime < MaxTime && !cancelEvent.WaitOne(0, false) && !doneEvent.WaitOne(0, false) && !mre.WaitOne(10, false))
|
|
{
|
|
totalTime += 10;
|
|
}
|
|
if (totalTime >= MaxTime || cancelEvent.WaitOne(0, false) || doneEvent.WaitOne(0, false))
|
|
{
|
|
APILogger.Log("Diagnostics::Exiting early due to timeout or user cancel");
|
|
diagnosticsService.ForceCancel();
|
|
Thread.Sleep(100);
|
|
cancelEvent.Set();
|
|
return;
|
|
}
|
|
|
|
//warn if there are any failed units
|
|
if (failedUnits.Any())
|
|
{
|
|
var msgs = new List<string>();
|
|
foreach (var failedUnit in failedUnits)
|
|
{
|
|
msgs.Add(string.Format(StringResources.DiagnosticsFailed_Unit,
|
|
failedUnit.Item1.SerialNumber, failedUnit.Item2));
|
|
}
|
|
//notify consumer that work is done and it can stop waiting
|
|
workEventDone.Set();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|